code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * omap_hwmod common data structures
 *
 * Copyright (C) 2010 Texas Instruments, Inc.
 * Thara Gopinath <thara@ti.com>
 * Benoît Cousson
 *
 * Copyright (C) 2010 Nokia Corporation
 * Paul Walmsley
 *
 * This data/structures are to be used while defining OMAP on-chip module
 * data and their integration with other OMAP modules and Linux.
 */

#include <linux/types.h>
#include <linux/platform_data/ti-sysc.h>

#include "omap_hwmod.h"

#include "omap_hwmod_common_data.h"

/**
 * struct omap_hwmod_sysc_type1 - TYPE1 sysconfig scheme.
 *
 * To be used by hwmod structure to specify the sysconfig offsets
 * if the device ip is compliant with the original PRCM protocol
 * defined for OMAP2420.
 */
struct sysc_regbits omap_hwmod_sysc_type1 = {
	.midle_shift	= SYSC_TYPE1_MIDLEMODE_SHIFT,
	.clkact_shift	= SYSC_TYPE1_CLOCKACTIVITY_SHIFT,
	.sidle_shift	= SYSC_TYPE1_SIDLEMODE_SHIFT,
	.enwkup_shift	= SYSC_TYPE1_ENAWAKEUP_SHIFT,
	.srst_shift	= SYSC_TYPE1_SOFTRESET_SHIFT,
	.autoidle_shift	= SYSC_TYPE1_AUTOIDLE_SHIFT,
};

/**
 * struct omap_hwmod_sysc_type2 - TYPE2 sysconfig scheme.
 *
 * To be used by hwmod structure to specify the sysconfig offsets if the
 * device ip is compliant with the new PRCM protocol defined for new
 * OMAP4 IPs.
 */
struct sysc_regbits omap_hwmod_sysc_type2 = {
	.midle_shift	= SYSC_TYPE2_MIDLEMODE_SHIFT,
	.sidle_shift	= SYSC_TYPE2_SIDLEMODE_SHIFT,
	.srst_shift	= SYSC_TYPE2_SOFTRESET_SHIFT,
	.dmadisable_shift = SYSC_TYPE2_DMADISABLE_SHIFT,
};

/**
 * struct omap_hwmod_sysc_type3 - TYPE3 sysconfig scheme.
 * Used by some IPs on AM33xx
 */
struct sysc_regbits omap_hwmod_sysc_type3 = {
	.midle_shift	= SYSC_TYPE3_MIDLEMODE_SHIFT,
	.sidle_shift	= SYSC_TYPE3_SIDLEMODE_SHIFT,
};

struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = {
	.manager_count		= 2,
	.has_framedonetv_irq	= 0
};

struct sysc_regbits omap34xx_sr_sysc_fields = {
	.clkact_shift	= 20,
};

struct sysc_regbits omap36xx_sr_sysc_fields = {
	.sidle_shift	= 24,
	.enwkup_shift	= 26,
};

struct sysc_regbits omap3_sham_sysc_fields = {
	.sidle_shift	= 4,
	.srst_shift	= 1,
	.autoidle_shift	= 0,
};

struct sysc_regbits omap3xxx_aes_sysc_fields = {
	.sidle_shift	= 6,
	.srst_shift	= 1,
	.autoidle_shift	= 0,
};

struct sysc_regbits omap_hwmod_sysc_type_mcasp = {
	.sidle_shift	= 0,
};

struct sysc_regbits omap_hwmod_sysc_type_usb_host_fs = {
	.midle_shift	= 4,
	.sidle_shift	= 2,
	.srst_shift	= 1,
};


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * omap_hwmod_common_data.h - OMAP hwmod common macros and declarations
 *
 * Copyright (C) 2010-2011 Nokia Corporation
 * Copyright (C) 2010-2012 Texas Instruments, Inc.
 * Paul Walmsley
 * Benoît Cousson
 */
#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_COMMON_DATA_H
#define __ARCH_ARM_MACH_OMAP2_OMAP_HWMOD_COMMON_DATA_H

#include "omap_hwmod.h"

#include "common.h"
#include "display.h"

/* Common IP block data across OMAP2xxx */
extern struct omap_hwmod omap2xxx_l3_main_hwmod;
extern struct omap_hwmod omap2xxx_l4_core_hwmod;
extern struct omap_hwmod omap2xxx_l4_wkup_hwmod;
extern struct omap_hwmod omap2xxx_mpu_hwmod;
extern struct omap_hwmod omap2xxx_iva_hwmod;
extern struct omap_hwmod omap2xxx_timer3_hwmod;
extern struct omap_hwmod omap2xxx_timer4_hwmod;
extern struct omap_hwmod omap2xxx_timer5_hwmod;
extern struct omap_hwmod omap2xxx_timer6_hwmod;
extern struct omap_hwmod omap2xxx_timer7_hwmod;
extern struct omap_hwmod omap2xxx_timer8_hwmod;
extern struct omap_hwmod omap2xxx_timer9_hwmod;
extern struct omap_hwmod omap2xxx_timer10_hwmod;
extern struct omap_hwmod omap2xxx_timer11_hwmod;
extern struct omap_hwmod omap2xxx_timer12_hwmod;
extern struct omap_hwmod omap2xxx_wd_timer2_hwmod;
extern struct omap_hwmod omap2xxx_uart1_hwmod;
extern struct omap_hwmod omap2xxx_uart2_hwmod;
extern struct omap_hwmod omap2xxx_uart3_hwmod;
extern struct omap_hwmod omap2xxx_dss_core_hwmod;
extern struct omap_hwmod omap2xxx_dss_dispc_hwmod;
extern struct omap_hwmod omap2xxx_dss_rfbi_hwmod;
extern struct omap_hwmod omap2xxx_dss_venc_hwmod;
extern struct omap_hwmod omap2xxx_gpio1_hwmod;
extern struct omap_hwmod omap2xxx_gpio2_hwmod;
extern struct omap_hwmod omap2xxx_gpio3_hwmod;
extern struct omap_hwmod omap2xxx_gpio4_hwmod;
extern struct omap_hwmod omap2xxx_mcspi1_hwmod;
extern struct omap_hwmod omap2xxx_mcspi2_hwmod;
extern struct omap_hwmod omap2xxx_gpmc_hwmod;
extern struct omap_hwmod omap2xxx_rng_hwmod;
extern struct omap_hwmod omap2xxx_sham_hwmod;
extern struct omap_hwmod omap2xxx_aes_hwmod;

/* Common interface data across OMAP2xxx */
extern struct omap_hwmod_ocp_if omap2xxx_l3_main__l4_core;
extern struct omap_hwmod_ocp_if omap2xxx_mpu__l3_main;
extern struct omap_hwmod_ocp_if omap2xxx_dss__l3;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__l4_wkup;
extern struct omap_hwmod_ocp_if omap2_l4_core__uart1;
extern struct omap_hwmod_ocp_if omap2_l4_core__uart2;
extern struct omap_hwmod_ocp_if omap2_l4_core__uart3;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__mcspi1;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__mcspi2;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer2;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer3;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer4;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer5;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer6;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer7;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer8;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer9;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer10;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer11;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__timer12;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_dispc;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_rfbi;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__dss_venc;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__rng;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__sham;
extern struct omap_hwmod_ocp_if omap2xxx_l4_core__aes;

/* OMAP hwmod classes - forward declarations */
extern struct omap_hwmod_class l3_hwmod_class;
extern struct omap_hwmod_class l4_hwmod_class;
extern struct omap_hwmod_class mpu_hwmod_class;
extern struct omap_hwmod_class iva_hwmod_class;
extern struct omap_hwmod_class omap2_uart_class;
extern struct omap_hwmod_class omap2_dss_hwmod_class;
extern struct omap_hwmod_class omap2_dispc_hwmod_class;
extern struct omap_hwmod_class omap2_rfbi_hwmod_class;
extern struct omap_hwmod_class omap2_venc_hwmod_class;
extern struct omap_hwmod_class_sysconfig omap2_hdq1w_sysc;
extern struct omap_hwmod_class omap2_hdq1w_class;

extern struct omap_hwmod_class omap2xxx_timer_hwmod_class;
extern struct omap_hwmod_class omap2xxx_wd_timer_hwmod_class;
extern struct omap_hwmod_class omap2xxx_gpio_hwmod_class;
extern struct omap_hwmod_class omap2xxx_mailbox_hwmod_class;
extern struct omap_hwmod_class omap2xxx_mcspi_class;

extern struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr;

#endif

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * omap_hwmod_common_ipblock_data.c - common IP block data for OMAP2+
 *
 * Copyright (C) 2011 Nokia Corporation
 * Copyright (C) 2012 Texas Instruments, Inc.
 * Paul Walmsley
 */

#include "omap_hwmod.h"
#include "omap_hwmod_common_data.h"

/*
 * 'dss' class
 * display sub-system
 */

static struct omap_hwmod_class_sysconfig omap2_dss_sysc = {
	.rev_offs	= 0x0000,
	.sysc_offs	= 0x0010,
	.syss_offs	= 0x0014,
	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
			   SYSS_HAS_RESET_STATUS),
	.sysc_fields	= &omap_hwmod_sysc_type1,
};

struct omap_hwmod_class omap2_dss_hwmod_class = {
	.name	= "dss",
	.sysc	= &omap2_dss_sysc,
	.reset	= omap_dss_reset,
};

/*
 * 'rfbi' class
 * remote frame buffer interface
 */

static struct omap_hwmod_class_sysconfig omap2_rfbi_sysc = {
	.rev_offs	= 0x0000,
	.sysc_offs	= 0x0010,
	.syss_offs	= 0x0014,
	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
			   SYSC_HAS_AUTOIDLE),
	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
	.sysc_fields	= &omap_hwmod_sysc_type1,
};

struct omap_hwmod_class omap2_rfbi_hwmod_class = {
	.name	= "rfbi",
	.sysc	= &omap2_rfbi_sysc,
};


code:
/*
 * OMAP IP block custom reset and preprogramming stubs
 *
 * Copyright (C) 2012 Texas Instruments, Inc.
 * Paul Walmsley
 *
 * A small number of IP blocks need custom reset and preprogramming
 * functions.  The stubs in this file provide a standard way for the
 * hwmod code to call these functions, which are to be located under
 * drivers/.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation version 2.
 *
 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
 * kind, whether express or implied; without even the implied warranty
 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 */
#include <linux/kernel.h>
#include <linux/errno.h>

#include "omap_hwmod.h"
#include "common.h"

#define OMAP_RTC_STATUS_REG	0x44
#define OMAP_RTC_KICK0_REG	0x6c
#define OMAP_RTC_KICK1_REG	0x70

#define OMAP_RTC_KICK0_VALUE	0x83E70B13
#define OMAP_RTC_KICK1_VALUE	0x95A4F1E0
#define OMAP_RTC_STATUS_BUSY	BIT(0)
#define OMAP_RTC_MAX_READY_TIME	50

/**
 * omap_rtc_wait_not_busy - Wait for the RTC BUSY flag
 * @oh: struct omap_hwmod *
 *
 * For updating certain RTC registers, the MPU must wait
 * for the BUSY status in OMAP_RTC_STATUS_REG to become zero.
 * Once the BUSY status is zero, there is a 15 microseconds access
 * period in which the MPU can program.
 */
static void omap_rtc_wait_not_busy(struct omap_hwmod *oh)
{
	int i;

	/* BUSY may stay active for 1/32768 second (~30 usec) */
	omap_test_timeout(omap_hwmod_read(oh, OMAP_RTC_STATUS_REG)
			  & OMAP_RTC_STATUS_BUSY, OMAP_RTC_MAX_READY_TIME, i);
	/* now we have ~15 microseconds to read/write various registers */
}

/**
 * omap_hwmod_rtc_unlock - Unlock the Kicker mechanism.
 * @oh: struct omap_hwmod *
 *
 * RTC IP have kicker feature. This prevents spurious writes to its registers.
 * In order to write into any of the RTC registers, KICK values has te be
 * written in respective KICK registers. This is needed for hwmod to write into
 * sysconfig register.
 */
void omap_hwmod_rtc_unlock(struct omap_hwmod *oh)
{
	unsigned long flags;

	local_irq_save(flags);
	omap_rtc_wait_not_busy(oh);
	omap_hwmod_write(OMAP_RTC_KICK0_VALUE, oh, OMAP_RTC_KICK0_REG);
	omap_hwmod_write(OMAP_RTC_KICK1_VALUE, oh, OMAP_RTC_KICK1_REG);
	local_irq_restore(flags);
}

/**
 * omap_hwmod_rtc_lock - Lock the Kicker mechanism.
 * @oh: struct omap_hwmod *
 *
 * RTC IP have kicker feature. This prevents spurious writes to its registers.
 * Once the RTC registers are written, KICK mechanism needs to be locked,
 * in order to prevent any spurious writes. This function locks back the RTC
 * registers once hwmod completes its write into sysconfig register.
 */
void omap_hwmod_rtc_lock(struct omap_hwmod *oh)
{
	unsigned long flags;

	local_irq_save(flags);
	omap_rtc_wait_not_busy(oh);
	omap_hwmod_write(0x0, oh, OMAP_RTC_KICK0_REG);
	omap_hwmod_write(0x0, oh, OMAP_RTC_KICK1_REG);
	local_irq_restore(flags);
}


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * OMAP SoC specific OPP Data helpers
 *
 * Copyright (C) 2009-2010 Texas Instruments Incorporated - https://www.ti.com/
 *	Nishanth Menon
 *	Kevin Hilman
 * Copyright (C) 2010 Nokia Corporation.
 *      Eduardo Valentin
 */
#ifndef __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H
#define __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H

#include "omap_hwmod.h"

#include "voltage.h"

/*
 * *BIG FAT WARNING*:
 * USE the following ONLY in opp data initialization common to an SoC.
 * DO NOT USE these in board files/pm core etc.
 */

/**
 * struct omap_opp_def - OMAP OPP Definition
 * @hwmod_name:	Name of the hwmod for this domain
 * @freq:	Frequency in hertz corresponding to this OPP
 * @u_volt:	Nominal voltage in microvolts corresponding to this OPP
 * @default_available:	True/false - is this OPP available by default
 *
 * OMAP SOCs have a standard set of tuples consisting of frequency and voltage
 * pairs that the device will support per voltage domain. This is called
 * Operating Points or OPP. The actual definitions of OMAP Operating Points
 * varies over silicon within the same family of devices. For a specific
 * domain, you can have a set of {frequency, voltage} pairs and this is denoted
 * by an array of omap_opp_def. As the kernel boots and more information is
 * available, a set of these are activated based on the precise nature of
 * device the kernel boots up on. It is interesting to remember that each IP
 * which belongs to a voltage domain may define their own set of OPPs on top
 * of this - but this is handled by the appropriate driver.
 */
struct omap_opp_def {
	char *hwmod_name;

	unsigned long freq;
	unsigned long u_volt;

	bool default_available;
};

/*
 * Initialization wrapper used to define an OPP for OMAP variants.
 */
#define OPP_INITIALIZER(_hwmod_name, _enabled, _freq, _uv)	\
{								\
	.hwmod_name	= _hwmod_name,				\
	.default_available	= _enabled,			\
	.freq		= _freq,				\
	.u_volt		= _uv,					\
}

/*
 * Initialization wrapper used to define SmartReflex process data
 * XXX Is this needed?  Just use C99 initializers in data files?
 */
#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)  \
{								       \
	.volt_nominal	= _v_nom,				       \
	.sr_efuse_offs	= _efuse_offs,				       \
	.sr_errminlimit = _errminlimit,				       \
	.vp_errgain	= _errgain				       \
}

/* Use this to initialize the default table */
extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
		u32 opp_def_size);

extern struct omap_volt_data omap34xx_vddmpu_volt_data[];
extern struct omap_volt_data omap34xx_vddcore_volt_data[];
extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
extern struct omap_volt_data omap36xx_vddcore_volt_data[];

extern struct omap_volt_data omap443x_vdd_mpu_volt_data[];
extern struct omap_volt_data omap443x_vdd_iva_volt_data[];
extern struct omap_volt_data omap443x_vdd_core_volt_data[];
extern struct omap_volt_data omap446x_vdd_mpu_volt_data[];
extern struct omap_volt_data omap446x_vdd_iva_volt_data[];
extern struct omap_volt_data omap446x_vdd_core_volt_data[];

#endif		/* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
  * This file configures the internal USB PHY in OMAP4430. Used
  * with TWL6030 transceiver and MUSB on OMAP4430.
  *
  * Copyright (C) 2010 Texas Instruments Incorporated - https://www.ti.com
  * Author: Hema HK <hemahk@ti.com>
  */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/types.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/usb.h>
#include <linux/usb/musb.h>

#include "soc.h"
#include "control.h"
#include "usb.h"

#define CONTROL_DEV_CONF		0x300
#define PHY_PD				0x1

/**
 * omap4430_phy_power_down: disable MUSB PHY during early init
 *
 * OMAP4 MUSB PHY module is enabled by default on reset, but this will
 * prevent core retention if not disabled by SW. USB driver will
 * later on enable this, once and if the driver needs it.
 */
static int __init omap4430_phy_power_down(void)
{
	void __iomem *ctrl_base;

	if (!cpu_is_omap44xx())
		return 0;

	ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K);
	if (!ctrl_base) {
		pr_err("control module ioremap failed\n");
		return -ENOMEM;
	}

	/* Power down the phy */
	writel_relaxed(PHY_PD, ctrl_base + CONTROL_DEV_CONF);

	iounmap(ctrl_base);

	return 0;
}
omap_early_initcall(omap4430_phy_power_down);

void am35x_musb_reset(void)
{
	u32	regval;

	/* Reset the musb interface */
	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);

	regval |= AM35XX_USBOTGSS_SW_RST;
	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);

	regval &= ~AM35XX_USBOTGSS_SW_RST;
	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);

	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
}

void am35x_musb_phy_power(u8 on)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(100);
	u32 devconf2;

	if (on) {
		/*
		 * Start the on-chip PHY and its PLL.
		 */
		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);

		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
		devconf2 |= CONF2_PHY_PLLON;

		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);

		pr_info("Waiting for PHY clock good...\n");
		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
				& CONF2_PHYCLKGD)) {
			cpu_relax();

			if (time_after(jiffies, timeout)) {
				pr_err("musb PHY clock good timed out\n");
				break;
			}
		}
	} else {
		/*
		 * Power down the on-chip PHY.
		 */
		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);

		devconf2 &= ~CONF2_PHY_PLLON;
		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
	}
}

void am35x_musb_clear_irq(void)
{
	u32 regval;

	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
	regval |= AM35XX_USBOTGSS_INT_CLR;
	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
}

void am35x_set_mode(u8 musb_mode)
{
	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);

	devconf2 &= ~CONF2_OTGMODE;
	switch (musb_mode) {
	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
		devconf2 |= CONF2_FORCE_HOST;
		break;
	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
		devconf2 |= CONF2_FORCE_DEVICE;
		break;
	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
		devconf2 |= CONF2_NO_OVERRIDE;
		break;
	default:
		pr_info("Unsupported mode %u\n", musb_mode);
	}

	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * OMAP and TWL PMIC specific initializations.
 *
 * Copyright (C) 2010 Texas Instruments Incorporated.
 * Thara Gopinath
 * Copyright (C) 2009 Texas Instruments Incorporated.
 * Nishanth Menon
 * Copyright (C) 2009 Nokia Corporation
 * Paul Walmsley
 */

#include <linux/err.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/mfd/twl.h>

#include "soc.h"
#include "voltage.h"

#include "pm.h"

#define OMAP3_SRI2C_SLAVE_ADDR		0x12
#define OMAP3_VDD_MPU_SR_CONTROL_REG	0x00
#define OMAP3_VDD_CORE_SR_CONTROL_REG	0x01
#define OMAP3_VP_CONFIG_ERROROFFSET	0x00
#define OMAP3_VP_VSTEPMIN_VSTEPMIN	0x1
#define OMAP3_VP_VSTEPMAX_VSTEPMAX	0x04
#define OMAP3_VP_VLIMITTO_TIMEOUT_US	200

#define OMAP4_SRI2C_SLAVE_ADDR		0x12
#define OMAP4_VDD_MPU_SR_VOLT_REG	0x55
#define OMAP4_VDD_MPU_SR_CMD_REG	0x56
#define OMAP4_VDD_IVA_SR_VOLT_REG	0x5B
#define OMAP4_VDD_IVA_SR_CMD_REG	0x5C
#define OMAP4_VDD_CORE_SR_VOLT_REG	0x61
#define OMAP4_VDD_CORE_SR_CMD_REG	0x62

static bool is_offset_valid;
static u8 smps_offset;

#define REG_SMPS_OFFSET         0xE0

static unsigned long twl4030_vsel_to_uv(const u8 vsel)
{
	return (((vsel * 125) + 6000)) * 100;
}

static u8 twl4030_uv_to_vsel(unsigned long uv)
{
	return DIV_ROUND_UP(uv - 600000, 12500);
}

static unsigned long twl6030_vsel_to_uv(const u8 vsel)
{
	/*
	 * In TWL6030 depending on the value of SMPS_OFFSET
	 * efuse register the voltage range supported in
	 * standard mode can be either between 0.6V - 1.3V or
	 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
	 * is programmed to all 0's where as starting from
	 * TWL6030 ES1.1 the efuse is programmed to 1
	 */
	if (!is_offset_valid) {
		twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
				REG_SMPS_OFFSET);
		is_offset_valid = true;
	}

	if (!vsel)
		return 0;
	/*
	 * There is no specific formula for voltage to vsel
	 * conversion above 1.3V. There are special hardcoded
	 * values for voltages above 1.3V. Currently we are
	 * hardcoding only for 1.35 V which is used for 1GH OPP for
	 * OMAP4430.
	 */
	if (vsel == 0x3A)
		return 1350000;

	if (smps_offset & 0x8)
		return ((((vsel - 1) * 1266) + 70900)) * 10;
	else
		return ((((vsel - 1) * 1266) + 60770)) * 10;
}

static u8 twl6030_uv_to_vsel(unsigned long uv)
{
	/*
	 * In TWL6030 depending on the value of SMPS_OFFSET
	 * efuse register the voltage range supported in
	 * standard mode can be either between 0.6V - 1.3V or
	 * 0.7V - 1.4V. In TWL6030 ES1.0 SMPS_OFFSET efuse
	 * is programmed to all 0's where as starting from
	 * TWL6030 ES1.1 the efuse is programmed to 1
	 */
	if (!is_offset_valid) {
		twl_i2c_read_u8(TWL6030_MODULE_ID0, &smps_offset,
				REG_SMPS_OFFSET);
		is_offset_valid = true;
	}

	if (!uv)
		return 0x00;
	/*
	 * There is no specific formula for voltage to vsel
	 * conversion above 1.3V. There are special hardcoded
	 * values for voltages above 1.3V. Currently we are
	 * hardcoding only for 1.35 V which is used for 1GH OPP for
	 * OMAP4430.
	 */
	if (uv > twl6030_vsel_to_uv(0x39)) {
		if (uv == 1350000)
			return 0x3A;
		pr_err("%s:OUT OF RANGE! non mapped vsel for %ld Vs max %ld\n",
			__func__, uv, twl6030_vsel_to_uv(0x39));
		return 0x3A;
	}

	if (smps_offset & 0x8)
		return DIV_ROUND_UP(uv - 709000, 12660) + 1;
	else
		return DIV_ROUND_UP(uv - 607700, 12660) + 1;
}

static struct omap_voltdm_pmic omap3_mpu_pmic = {
	.slew_rate		= 4000,
	.step_size		= 12500,
	.vp_erroroffset		= OMAP3_VP_CONFIG_ERROROFFSET,
	.vp_vstepmin		= OMAP3_VP_VSTEPMIN_VSTEPMIN,
	.vp_vstepmax		= OMAP3_VP_VSTEPMAX_VSTEPMAX,
	.vddmin			= 600000,
	.vddmax			= 1450000,
	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
	.volt_reg_addr		= OMAP3_VDD_MPU_SR_CONTROL_REG,
	.i2c_high_speed		= true,
	.vsel_to_uv		= twl4030_vsel_to_uv,
	.uv_to_vsel		= twl4030_uv_to_vsel,
};

static struct omap_voltdm_pmic omap3_core_pmic = {
	.slew_rate		= 4000,
	.step_size		= 12500,
	.vp_erroroffset		= OMAP3_VP_CONFIG_ERROROFFSET,
	.vp_vstepmin		= OMAP3_VP_VSTEPMIN_VSTEPMIN,
	.vp_vstepmax		= OMAP3_VP_VSTEPMAX_VSTEPMAX,
	.vddmin			= 600000,
	.vddmax			= 1450000,
	.vp_timeout_us		= OMAP3_VP_VLIMITTO_TIMEOUT_US,
	.i2c_slave_addr		= OMAP3_SRI2C_SLAVE_ADDR,
	.volt_reg_addr		= OMAP3_VDD_CORE_SR_CONTROL_REG,
	.i2c_high_speed		= true,
	.vsel_to_uv		= twl4030_vsel_to_uv,
	.uv_to_vsel		= twl4030_uv_to_vsel,
};

static struct omap_voltdm_pmic omap4_mpu_pmic = {
	.slew_rate		= 4000,
	.step_size		= 12660,
	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
	.vddmin			= 0,
	.vddmax			= 2100000,
	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
	.volt_reg_addr		= OMAP4_VDD_MPU_SR_VOLT_REG,
	.cmd_reg_addr		= OMAP4_VDD_MPU_SR_CMD_REG,
	.i2c_high_speed		= true,
	.i2c_pad_load		= 3,
	.vsel_to_uv		= twl6030_vsel_to_uv,
	.uv_to_vsel		= twl6030_uv_to_vsel,
};

static struct omap_voltdm_pmic omap4_iva_pmic = {
	.slew_rate		= 4000,
	.step_size		= 12660,
	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
	.vddmin			= 0,
	.vddmax			= 2100000,
	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
	.volt_reg_addr		= OMAP4_VDD_IVA_SR_VOLT_REG,
	.cmd_reg_addr		= OMAP4_VDD_IVA_SR_CMD_REG,
	.i2c_high_speed		= true,
	.i2c_pad_load		= 3,
	.vsel_to_uv		= twl6030_vsel_to_uv,
	.uv_to_vsel		= twl6030_uv_to_vsel,
};

static struct omap_voltdm_pmic omap4_core_pmic = {
	.slew_rate		= 4000,
	.step_size		= 12660,
	.vp_erroroffset		= OMAP4_VP_CONFIG_ERROROFFSET,
	.vp_vstepmin		= OMAP4_VP_VSTEPMIN_VSTEPMIN,
	.vp_vstepmax		= OMAP4_VP_VSTEPMAX_VSTEPMAX,
	.vddmin			= 0,
	.vddmax			= 2100000,
	.vp_timeout_us		= OMAP4_VP_VLIMITTO_TIMEOUT_US,
	.i2c_slave_addr		= OMAP4_SRI2C_SLAVE_ADDR,
	.volt_reg_addr		= OMAP4_VDD_CORE_SR_VOLT_REG,
	.cmd_reg_addr		= OMAP4_VDD_CORE_SR_CMD_REG,
	.i2c_high_speed		= true,
	.i2c_pad_load		= 3,
	.vsel_to_uv		= twl6030_vsel_to_uv,
	.uv_to_vsel		= twl6030_uv_to_vsel,
};

int __init omap4_twl_init(void)
{
	struct voltagedomain *voltdm;

	if (!cpu_is_omap44xx() ||
	    of_find_compatible_node(NULL, NULL, "motorola,cpcap"))
		return -ENODEV;

	voltdm = voltdm_lookup("mpu");
	omap_voltage_register_pmic(voltdm, &omap4_mpu_pmic);

	voltdm = voltdm_lookup("iva");
	omap_voltage_register_pmic(voltdm, &omap4_iva_pmic);

	voltdm = voltdm_lookup("core");
	omap_voltage_register_pmic(voltdm, &omap4_core_pmic);

	return 0;
}

int __init omap3_twl_init(void)
{
	struct voltagedomain *voltdm;

	if (!cpu_is_omap34xx())
		return -ENODEV;

	voltdm = voltdm_lookup("mpu_iva");
	omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);

	voltdm = voltdm_lookup("core");
	omap_voltage_register_pmic(voltdm, &omap3_core_pmic);

	return 0;
}


code:
// SPDX-License-Identifier: GPL-2.0
/*
 * opp2420_data.c - old-style "OPP" table for OMAP2420
 *
 * Copyright (C) 2005-2009 Texas Instruments, Inc.
 * Copyright (C) 2004-2009 Nokia Corporation
 *
 * Richard Woodruff <r-woodruff2@ti.com>
 *
 * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
 * These configurations are characterized by voltage and speed for clocks.
 * The device is only validated for certain combinations. One way to express
 * these combinations is via the 'ratios' which the clocks operate with
 * respect to each other. These ratio sets are for a given voltage/DPLL
 * setting. All configurations can be described by a DPLL setting and a ratio.
 *
 * XXX Missing voltage data.
 * XXX Missing 19.2MHz sys_clk rate sets (needed for N800/N810)
 *
 * THe format described in this file is deprecated.  Once a reasonable
 * OPP API exists, the data in this file should be converted to use it.
 *
 * This is technically part of the OMAP2xxx clock code.
 *
 * Considerable work is still needed to fully support dynamic frequency
 * changes on OMAP2xxx-series chips.  Readers interested in such a
 * project are encouraged to review the Maemo Diablo RX-34 and RX-44
 * kernel source at:
 *     http://repository.maemo.org/pool/diablo/free/k/kernel-source-diablo/
 */

#include <linux/kernel.h>

#include "opp2xxx.h"
#include "sdrc.h"
#include "clock.h"

/*
 * Key dividers which make up a PRCM set. Ratios for a PRCM are mandated.
 * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
 * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
 * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
 *
 * Filling in table based on H4 boards available.  There are quite a
 * few more rate combinations which could be defined.
 *
 * When multiple values are defined the start up will try and choose
 * the fastest one. If a 'fast' value is defined, then automatically,
 * the /2 one should be included as it can be used.  Generally having
 * more than one fast set does not make sense, as static timings need
 * to be changed to change the set.  The exception is the bypass
 * setting which is available for low power bypass.
 *
 * Note: This table needs to be sorted, fastest to slowest.
 **/
const struct prcm_config omap2420_rate_table[] = {
	/* PRCM I - FAST */
	{S12M, S660M, S330M, RI_CM_CLKSEL_MPU_VAL,		/* 330MHz ARM */
		RI_CM_CLKSEL_DSP_VAL, RI_CM_CLKSEL_GFX_VAL,
		RI_CM_CLKSEL1_CORE_VAL, MI_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_165MHz,
		RATE_IN_242X},

	/* PRCM II - FAST */
	{S12M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,		/* 300MHz ARM */
		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
		RATE_IN_242X},

	{S13M, S600M, S300M, RII_CM_CLKSEL_MPU_VAL,		/* 300MHz ARM */
		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
		RATE_IN_242X},

	/* PRCM III - FAST */
	{S12M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
		RATE_IN_242X},

	{S13M, S532M, S266M, RIII_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
		RATE_IN_242X},

	/* PRCM II - SLOW */
	{S12M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,		/* 150MHz ARM */
		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
		RATE_IN_242X},

	{S13M, S300M, S150M, RII_CM_CLKSEL_MPU_VAL,		/* 150MHz ARM */
		RII_CM_CLKSEL_DSP_VAL, RII_CM_CLKSEL_GFX_VAL,
		RII_CM_CLKSEL1_CORE_VAL, MII_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_100MHz,
		RATE_IN_242X},

	/* PRCM III - SLOW */
	{S12M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
		RATE_IN_242X},

	{S13M, S266M, S133M, RIII_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
		RIII_CM_CLKSEL_DSP_VAL, RIII_CM_CLKSEL_GFX_VAL,
		RIII_CM_CLKSEL1_CORE_VAL, MIII_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_133MHz,
		RATE_IN_242X},

	/* PRCM-VII (boot-bypass) */
	{S12M, S12M, S12M, RVII_CM_CLKSEL_MPU_VAL,		/* 12MHz ARM*/
		RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
		RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS,
		RATE_IN_242X},

	/* PRCM-VII (boot-bypass) */
	{S13M, S13M, S13M, RVII_CM_CLKSEL_MPU_VAL,		/* 13MHz ARM */
		RVII_CM_CLKSEL_DSP_VAL, RVII_CM_CLKSEL_GFX_VAL,
		RVII_CM_CLKSEL1_CORE_VAL, MVII_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, 0, SDRC_RFR_CTRL_BYPASS,
		RATE_IN_242X},

	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};


code:
// SPDX-License-Identifier: GPL-2.0
/*
 * opp2430_data.c - old-style "OPP" table for OMAP2430
 *
 * Copyright (C) 2005-2009 Texas Instruments, Inc.
 * Copyright (C) 2004-2009 Nokia Corporation
 *
 * Richard Woodruff <r-woodruff2@ti.com>
 *
 * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
 * These configurations are characterized by voltage and speed for clocks.
 * The device is only validated for certain combinations. One way to express
 * these combinations is via the 'ratios' which the clocks operate with
 * respect to each other. These ratio sets are for a given voltage/DPLL
 * setting. All configurations can be described by a DPLL setting and a ratio.
 *
 * 2430 differs from 2420 in that there are no more phase synchronizers used.
 * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
 * 2430 (iva2.1, NOdsp, mdm)
 *
 * XXX Missing voltage data.
 * XXX Missing 19.2MHz sys_clk rate sets.
 *
 * THe format described in this file is deprecated.  Once a reasonable
 * OPP API exists, the data in this file should be converted to use it.
 *
 * This is technically part of the OMAP2xxx clock code.
 */

#include <linux/kernel.h>

#include "opp2xxx.h"
#include "sdrc.h"
#include "clock.h"

/*
 * Key dividers which make up a PRCM set. Ratios for a PRCM are mandated.
 * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,
 * CM_CLKSEL_DSP, CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL,
 * CM_CLKSEL2_PLL, CM_CLKSEL_MDM
 *
 * Filling in table based on 2430-SDPs variants available.  There are
 * quite a few more rate combinations which could be defined.
 *
 * When multiple values are defined the start up will try and choose
 * the fastest one. If a 'fast' value is defined, then automatically,
 * the /2 one should be included as it can be used.  Generally having
 * more than one fast set does not make sense, as static timings need
 * to be changed to change the set.  The exception is the bypass
 * setting which is available for low power bypass.
 *
 * Note: This table needs to be sorted, fastest to slowest.
 */
const struct prcm_config omap2430_rate_table[] = {
	/* PRCM #4 - ratio2 (ES2.1) - FAST */
	{S13M, S798M, S399M, R2_CM_CLKSEL_MPU_VAL,		/* 399MHz ARM */
		R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
		R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, R2_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_133MHz,
		RATE_IN_243X},

	/* PRCM #2 - ratio1 (ES2) - FAST */
	{S13M, S658M, S329M, R1_CM_CLKSEL_MPU_VAL,		/* 330MHz ARM */
		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
		R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_165MHz,
		RATE_IN_243X},

	/* PRCM #5a - ratio1 - FAST */
	{S13M, S532M, S266M, R1_CM_CLKSEL_MPU_VAL,		/* 266MHz ARM */
		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
		R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_133MHz,
		RATE_IN_243X},

	/* PRCM #5b - ratio1 - FAST */
	{S13M, S400M, S200M, R1_CM_CLKSEL_MPU_VAL,		/* 200MHz ARM */
		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
		R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, R1_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_100MHz,
		RATE_IN_243X},

	/* PRCM #4 - ratio1 (ES2.1) - SLOW */
	{S13M, S399M, S199M, R2_CM_CLKSEL_MPU_VAL,		/* 200MHz ARM */
		R2_CM_CLKSEL_DSP_VAL, R2_CM_CLKSEL_GFX_VAL,
		R2_CM_CLKSEL1_CORE_VAL, M4_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_1x_VAL, R2_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_133MHz,
		RATE_IN_243X},

	/* PRCM #2 - ratio1 (ES2) - SLOW */
	{S13M, S329M, S164M, R1_CM_CLKSEL_MPU_VAL,		/* 165MHz ARM */
		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
		R1_CM_CLKSEL1_CORE_VAL, M2_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_165MHz,
		RATE_IN_243X},

	/* PRCM #5a - ratio1 - SLOW */
	{S13M, S266M, S133M, R1_CM_CLKSEL_MPU_VAL,		/* 133MHz ARM */
		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
		R1_CM_CLKSEL1_CORE_VAL, M5A_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_133MHz,
		RATE_IN_243X},

	/* PRCM #5b - ratio1 - SLOW*/
	{S13M, S200M, S100M, R1_CM_CLKSEL_MPU_VAL,		/* 100MHz ARM */
		R1_CM_CLKSEL_DSP_VAL, R1_CM_CLKSEL_GFX_VAL,
		R1_CM_CLKSEL1_CORE_VAL, M5B_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_1x_VAL, R1_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_100MHz,
		RATE_IN_243X},

	/* PRCM-boot/bypass */
	{S13M, S13M, S13M, RB_CM_CLKSEL_MPU_VAL,		/* 13MHz */
		RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
		RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_13_VAL,
		MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_BYPASS,
		RATE_IN_243X},

	/* PRCM-boot/bypass */
	{S12M, S12M, S12M, RB_CM_CLKSEL_MPU_VAL,		/* 12MHz */
		RB_CM_CLKSEL_DSP_VAL, RB_CM_CLKSEL_GFX_VAL,
		RB_CM_CLKSEL1_CORE_VAL, MB_CM_CLKSEL1_PLL_12_VAL,
		MX_CLKSEL2_PLL_2x_VAL, RB_CM_CLKSEL_MDM_VAL,
		SDRC_RFR_CTRL_BYPASS,
		RATE_IN_243X},

	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * opp2xxx.h - macros for old-style OMAP2xxx "OPP" definitions
 *
 * Copyright (C) 2005-2009 Texas Instruments, Inc.
 * Copyright (C) 2004-2009 Nokia Corporation
 *
 * Richard Woodruff <r-woodruff2@ti.com>
 *
 * The OMAP2 processor can be run at several discrete 'PRCM configurations'.
 * These configurations are characterized by voltage and speed for clocks.
 * The device is only validated for certain combinations. One way to express
 * these combinations is via the 'ratio's' which the clocks operate with
 * respect to each other. These ratio sets are for a given voltage/DPLL
 * setting. All configurations can be described by a DPLL setting and a ratio
 * There are 3 ratio sets for the 2430 and X ratio sets for 2420.
 *
 * 2430 differs from 2420 in that there are no more phase synchronizers used.
 * They both have a slightly different clock domain setup. 2420(iva1,dsp) vs
 * 2430 (iva2.1, NOdsp, mdm)
 *
 * XXX Missing voltage data.
 *
 * THe format described in this file is deprecated.  Once a reasonable
 * OPP API exists, the data in this file should be converted to use it.
 *
 * This is technically part of the OMAP2xxx clock code.
 */

#ifndef __ARCH_ARM_MACH_OMAP2_OPP2XXX_H
#define __ARCH_ARM_MACH_OMAP2_OPP2XXX_H

/**
 * struct prcm_config - define clock rates on a per-OPP basis (24xx)
 *
 * Key dividers which make up a PRCM set. Ratio's for a PRCM are mandated.
 * xtal_speed, dpll_speed, mpu_speed, CM_CLKSEL_MPU,CM_CLKSEL_DSP
 * CM_CLKSEL_GFX, CM_CLKSEL1_CORE, CM_CLKSEL1_PLL CM_CLKSEL2_PLL, CM_CLKSEL_MDM
 *
 * This is deprecated.  As soon as we have a decent OPP API, we should
 * move all this stuff to it.
 */
struct prcm_config {
	unsigned long xtal_speed;	/* crystal rate */
	unsigned long dpll_speed;	/* dpll: out*xtal*M/(N-1)table_recalc */
	unsigned long mpu_speed;	/* speed of MPU */
	unsigned long cm_clksel_mpu;	/* mpu divider */
	unsigned long cm_clksel_dsp;	/* dsp+iva1 div(2420), iva2.1(2430) */
	unsigned long cm_clksel_gfx;	/* gfx dividers */
	unsigned long cm_clksel1_core;	/* major subsystem dividers */
	unsigned long cm_clksel1_pll;	/* m,n */
	unsigned long cm_clksel2_pll;	/* dpllx1 or x2 out */
	unsigned long cm_clksel_mdm;	/* modem dividers 2430 only */
	unsigned long base_sdrc_rfr;	/* base refresh timing for a set */
	unsigned short flags;
};

/* Core fields for cm_clksel, not ratio governed */
#define RX_CLKSEL_DSS1			(0x10 << 8)
#define RX_CLKSEL_DSS2			(0x0 << 13)
#define RX_CLKSEL_SSI			(0x5 << 20)

/*-------------------------------------------------------------------------
 * Voltage/DPLL ratios
 *-------------------------------------------------------------------------*/

/* 2430 Ratio's, 2430-Ratio Config 1 */
#define R1_CLKSEL_L3			(4 << 0)
#define R1_CLKSEL_L4			(2 << 5)
#define R1_CLKSEL_USB			(4 << 25)
#define R1_CM_CLKSEL1_CORE_VAL		(R1_CLKSEL_USB | RX_CLKSEL_SSI | \
					 RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
					 R1_CLKSEL_L4 | R1_CLKSEL_L3)
#define R1_CLKSEL_MPU			(2 << 0)
#define R1_CM_CLKSEL_MPU_VAL		R1_CLKSEL_MPU
#define R1_CLKSEL_DSP			(2 << 0)
#define R1_CLKSEL_DSP_IF		(2 << 5)
#define R1_CM_CLKSEL_DSP_VAL		(R1_CLKSEL_DSP | R1_CLKSEL_DSP_IF)
#define R1_CLKSEL_GFX			(2 << 0)
#define R1_CM_CLKSEL_GFX_VAL		R1_CLKSEL_GFX
#define R1_CLKSEL_MDM			(4 << 0)
#define R1_CM_CLKSEL_MDM_VAL		R1_CLKSEL_MDM

/* 2430-Ratio Config 2 */
#define R2_CLKSEL_L3			(6 << 0)
#define R2_CLKSEL_L4			(2 << 5)
#define R2_CLKSEL_USB			(2 << 25)
#define R2_CM_CLKSEL1_CORE_VAL		(R2_CLKSEL_USB | RX_CLKSEL_SSI | \
					 RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
					 R2_CLKSEL_L4 | R2_CLKSEL_L3)
#define R2_CLKSEL_MPU			(2 << 0)
#define R2_CM_CLKSEL_MPU_VAL		R2_CLKSEL_MPU
#define R2_CLKSEL_DSP			(2 << 0)
#define R2_CLKSEL_DSP_IF		(3 << 5)
#define R2_CM_CLKSEL_DSP_VAL		(R2_CLKSEL_DSP | R2_CLKSEL_DSP_IF)
#define R2_CLKSEL_GFX			(2 << 0)
#define R2_CM_CLKSEL_GFX_VAL		R2_CLKSEL_GFX
#define R2_CLKSEL_MDM			(6 << 0)
#define R2_CM_CLKSEL_MDM_VAL		R2_CLKSEL_MDM

/* 2430-Ratio Bootm (BYPASS) */
#define RB_CLKSEL_L3			(1 << 0)
#define RB_CLKSEL_L4			(1 << 5)
#define RB_CLKSEL_USB			(1 << 25)
#define RB_CM_CLKSEL1_CORE_VAL		(RB_CLKSEL_USB | RX_CLKSEL_SSI | \
					 RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
					 RB_CLKSEL_L4 | RB_CLKSEL_L3)
#define RB_CLKSEL_MPU			(1 << 0)
#define RB_CM_CLKSEL_MPU_VAL		RB_CLKSEL_MPU
#define RB_CLKSEL_DSP			(1 << 0)
#define RB_CLKSEL_DSP_IF		(1 << 5)
#define RB_CM_CLKSEL_DSP_VAL		(RB_CLKSEL_DSP | RB_CLKSEL_DSP_IF)
#define RB_CLKSEL_GFX			(1 << 0)
#define RB_CM_CLKSEL_GFX_VAL		RB_CLKSEL_GFX
#define RB_CLKSEL_MDM			(1 << 0)
#define RB_CM_CLKSEL_MDM_VAL		RB_CLKSEL_MDM

/* 2420 Ratio Equivalents */
#define RXX_CLKSEL_VLYNQ		(0x12 << 15)
#define RXX_CLKSEL_SSI			(0x8 << 20)

/* 2420-PRCM III 532MHz core */
#define RIII_CLKSEL_L3			(4 << 0)	/* 133MHz */
#define RIII_CLKSEL_L4			(2 << 5)	/* 66.5MHz */
#define RIII_CLKSEL_USB			(4 << 25)	/* 33.25MHz */
#define RIII_CM_CLKSEL1_CORE_VAL	(RIII_CLKSEL_USB | RXX_CLKSEL_SSI | \
					 RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
					 RX_CLKSEL_DSS1 | RIII_CLKSEL_L4 | \
					 RIII_CLKSEL_L3)
#define RIII_CLKSEL_MPU			(2 << 0)	/* 266MHz */
#define RIII_CM_CLKSEL_MPU_VAL		RIII_CLKSEL_MPU
#define RIII_CLKSEL_DSP			(3 << 0)	/* c5x - 177.3MHz */
#define RIII_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 88.67MHz */
#define RIII_SYNC_DSP			(1 << 7)	/* Enable sync */
#define RIII_CLKSEL_IVA			(6 << 8)	/* iva1 - 88.67MHz */
#define RIII_SYNC_IVA			(1 << 13)	/* Enable sync */
#define RIII_CM_CLKSEL_DSP_VAL		(RIII_SYNC_IVA | RIII_CLKSEL_IVA | \
					 RIII_SYNC_DSP | RIII_CLKSEL_DSP_IF | \
					 RIII_CLKSEL_DSP)
#define RIII_CLKSEL_GFX			(2 << 0)	/* 66.5MHz */
#define RIII_CM_CLKSEL_GFX_VAL		RIII_CLKSEL_GFX

/* 2420-PRCM II 600MHz core */
#define RII_CLKSEL_L3			(6 << 0)	/* 100MHz */
#define RII_CLKSEL_L4			(2 << 5)	/* 50MHz */
#define RII_CLKSEL_USB			(2 << 25)	/* 50MHz */
#define RII_CM_CLKSEL1_CORE_VAL		(RII_CLKSEL_USB | RXX_CLKSEL_SSI | \
					 RXX_CLKSEL_VLYNQ | RX_CLKSEL_DSS2 | \
					 RX_CLKSEL_DSS1 | RII_CLKSEL_L4 | \
					 RII_CLKSEL_L3)
#define RII_CLKSEL_MPU			(2 << 0)	/* 300MHz */
#define RII_CM_CLKSEL_MPU_VAL		RII_CLKSEL_MPU
#define RII_CLKSEL_DSP			(3 << 0)	/* c5x - 200MHz */
#define RII_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 100MHz */
#define RII_SYNC_DSP			(0 << 7)	/* Bypass sync */
#define RII_CLKSEL_IVA			(3 << 8)	/* iva1 - 200MHz */
#define RII_SYNC_IVA			(0 << 13)	/* Bypass sync */
#define RII_CM_CLKSEL_DSP_VAL		(RII_SYNC_IVA | RII_CLKSEL_IVA | \
					 RII_SYNC_DSP | RII_CLKSEL_DSP_IF | \
					 RII_CLKSEL_DSP)
#define RII_CLKSEL_GFX			(2 << 0)	/* 50MHz */
#define RII_CM_CLKSEL_GFX_VAL		RII_CLKSEL_GFX

/* 2420-PRCM I 660MHz core */
#define RI_CLKSEL_L3			(4 << 0)	/* 165MHz */
#define RI_CLKSEL_L4			(2 << 5)	/* 82.5MHz */
#define RI_CLKSEL_USB			(4 << 25)	/* 41.25MHz */
#define RI_CM_CLKSEL1_CORE_VAL		(RI_CLKSEL_USB |		\
					 RXX_CLKSEL_SSI | RXX_CLKSEL_VLYNQ | \
					 RX_CLKSEL_DSS2 | RX_CLKSEL_DSS1 | \
					 RI_CLKSEL_L4 | RI_CLKSEL_L3)
#define RI_CLKSEL_MPU			(2 << 0)	/* 330MHz */
#define RI_CM_CLKSEL_MPU_VAL		RI_CLKSEL_MPU
#define RI_CLKSEL_DSP			(3 << 0)	/* c5x - 220MHz */
#define RI_CLKSEL_DSP_IF		(2 << 5)	/* c5x - 110MHz */
#define RI_SYNC_DSP			(1 << 7)	/* Activate sync */
#define RI_CLKSEL_IVA			(4 << 8)	/* iva1 - 165MHz */
#define RI_SYNC_IVA			(0 << 13)	/* Bypass sync */
#define RI_CM_CLKSEL_DSP_VAL		(RI_SYNC_IVA | RI_CLKSEL_IVA |	\
					 RI_SYNC_DSP | RI_CLKSEL_DSP_IF | \
					 RI_CLKSEL_DSP)
#define RI_CLKSEL_GFX			(1 << 0)	/* 165MHz */
#define RI_CM_CLKSEL_GFX_VAL		RI_CLKSEL_GFX

/* 2420-PRCM VII (boot) */
#define RVII_CLKSEL_L3			(1 << 0)
#define RVII_CLKSEL_L4			(1 << 5)
#define RVII_CLKSEL_DSS1		(1 << 8)
#define RVII_CLKSEL_DSS2		(0 << 13)
#define RVII_CLKSEL_VLYNQ		(1 << 15)
#define RVII_CLKSEL_SSI			(1 << 20)
#define RVII_CLKSEL_USB			(1 << 25)

#define RVII_CM_CLKSEL1_CORE_VAL	(RVII_CLKSEL_USB | RVII_CLKSEL_SSI | \
					 RVII_CLKSEL_VLYNQ | \
					 RVII_CLKSEL_DSS2 | RVII_CLKSEL_DSS1 | \
					 RVII_CLKSEL_L4 | RVII_CLKSEL_L3)

#define RVII_CLKSEL_MPU			(1 << 0) /* all divide by 1 */
#define RVII_CM_CLKSEL_MPU_VAL		RVII_CLKSEL_MPU

#define RVII_CLKSEL_DSP			(1 << 0)
#define RVII_CLKSEL_DSP_IF		(1 << 5)
#define RVII_SYNC_DSP			(0 << 7)
#define RVII_CLKSEL_IVA			(1 << 8)
#define RVII_SYNC_IVA			(0 << 13)
#define RVII_CM_CLKSEL_DSP_VAL		(RVII_SYNC_IVA | RVII_CLKSEL_IVA | \
					 RVII_SYNC_DSP | RVII_CLKSEL_DSP_IF | \
					 RVII_CLKSEL_DSP)

#define RVII_CLKSEL_GFX			(1 << 0)
#define RVII_CM_CLKSEL_GFX_VAL		RVII_CLKSEL_GFX

/*-------------------------------------------------------------------------
 * 2430 Target modes: Along with each configuration the CPU has several
 * modes which goes along with them. Modes mainly are the addition of
 * describe DPLL combinations to go along with a ratio.
 *-------------------------------------------------------------------------*/

/* Hardware governed */
#define MX_48M_SRC			(0 << 3)
#define MX_54M_SRC			(0 << 5)
#define MX_APLLS_CLIKIN_12		(3 << 23)
#define MX_APLLS_CLIKIN_13		(2 << 23)
#define MX_APLLS_CLIKIN_19_2		(0 << 23)

/*
 * 2430 - standalone, 2*ref*M/(n+1), M/N is for exactness not relock speed
 * #5a	(ratio1) baseport-target, target DPLL = 266*2 = 532MHz
 */
#define M5A_DPLL_MULT_12		(133 << 12)
#define M5A_DPLL_DIV_12			(5 << 8)
#define M5A_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M5A_DPLL_DIV_12 | M5A_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)
#define M5A_DPLL_MULT_13		(61 << 12)
#define M5A_DPLL_DIV_13			(2 << 8)
#define M5A_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M5A_DPLL_DIV_13 | M5A_DPLL_MULT_13 | \
					 MX_APLLS_CLIKIN_13)
#define M5A_DPLL_MULT_19		(55 << 12)
#define M5A_DPLL_DIV_19			(3 << 8)
#define M5A_CM_CLKSEL1_PLL_19_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M5A_DPLL_DIV_19 | M5A_DPLL_MULT_19 | \
					 MX_APLLS_CLIKIN_19_2)
/* #5b	(ratio1) target DPLL = 200*2 = 400MHz */
#define M5B_DPLL_MULT_12		(50 << 12)
#define M5B_DPLL_DIV_12			(2 << 8)
#define M5B_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M5B_DPLL_DIV_12 | M5B_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)
#define M5B_DPLL_MULT_13		(200 << 12)
#define M5B_DPLL_DIV_13			(12 << 8)

#define M5B_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M5B_DPLL_DIV_13 | M5B_DPLL_MULT_13 | \
					 MX_APLLS_CLIKIN_13)
#define M5B_DPLL_MULT_19		(125 << 12)
#define M5B_DPLL_DIV_19			(31 << 8)
#define M5B_CM_CLKSEL1_PLL_19_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M5B_DPLL_DIV_19 | M5B_DPLL_MULT_19 | \
					 MX_APLLS_CLIKIN_19_2)
/*
 * #4	(ratio2), DPLL = 399*2 = 798MHz, L3=133MHz
 */
#define M4_DPLL_MULT_12			(133 << 12)
#define M4_DPLL_DIV_12			(3 << 8)
#define M4_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M4_DPLL_DIV_12 | M4_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)

#define M4_DPLL_MULT_13			(399 << 12)
#define M4_DPLL_DIV_13			(12 << 8)
#define M4_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M4_DPLL_DIV_13 | M4_DPLL_MULT_13 | \
					 MX_APLLS_CLIKIN_13)

#define M4_DPLL_MULT_19			(145 << 12)
#define M4_DPLL_DIV_19			(6 << 8)
#define M4_CM_CLKSEL1_PLL_19_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M4_DPLL_DIV_19 | M4_DPLL_MULT_19 | \
					 MX_APLLS_CLIKIN_19_2)

/*
 * #3	(ratio2) baseport-target, target DPLL = 330*2 = 660MHz
 */
#define M3_DPLL_MULT_12			(55 << 12)
#define M3_DPLL_DIV_12			(1 << 8)
#define M3_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M3_DPLL_DIV_12 | M3_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)
#define M3_DPLL_MULT_13			(76 << 12)
#define M3_DPLL_DIV_13			(2 << 8)
#define M3_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M3_DPLL_DIV_13 | M3_DPLL_MULT_13 | \
					 MX_APLLS_CLIKIN_13)
#define M3_DPLL_MULT_19			(17 << 12)
#define M3_DPLL_DIV_19			(0 << 8)
#define M3_CM_CLKSEL1_PLL_19_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M3_DPLL_DIV_19 | M3_DPLL_MULT_19 | \
					 MX_APLLS_CLIKIN_19_2)

/*
 * #2   (ratio1) DPLL = 330*2 = 660MHz, L3=165MHz
 */
#define M2_DPLL_MULT_12		        (55 << 12)
#define M2_DPLL_DIV_12		        (1 << 8)
#define M2_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M2_DPLL_DIV_12 | M2_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)

/* Speed changes - Used 658.7MHz instead of 660MHz for LP-Refresh M=76 N=2,
 * relock time issue */
/* Core frequency changed from 330/165 to 329/164 MHz*/
#define M2_DPLL_MULT_13		        (76 << 12)
#define M2_DPLL_DIV_13		        (2 << 8)
#define M2_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M2_DPLL_DIV_13 | M2_DPLL_MULT_13 | \
					 MX_APLLS_CLIKIN_13)

#define M2_DPLL_MULT_19		        (17 << 12)
#define M2_DPLL_DIV_19		        (0 << 8)
#define M2_CM_CLKSEL1_PLL_19_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 M2_DPLL_DIV_19 | M2_DPLL_MULT_19 | \
					 MX_APLLS_CLIKIN_19_2)

/* boot (boot) */
#define MB_DPLL_MULT			(1 << 12)
#define MB_DPLL_DIV			(0 << 8)
#define MB_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 MB_DPLL_DIV | MB_DPLL_MULT | \
					 MX_APLLS_CLIKIN_12)

#define MB_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 MB_DPLL_DIV | MB_DPLL_MULT | \
					 MX_APLLS_CLIKIN_13)

#define MB_CM_CLKSEL1_PLL_19_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 MB_DPLL_DIV | MB_DPLL_MULT | \
					 MX_APLLS_CLIKIN_19)

/*
 * 2430 - chassis (sedna)
 * 165 (ratio1) same as above #2
 * 150 (ratio1)
 * 133 (ratio2) same as above #4
 * 110 (ratio2) same as above #3
 * 104 (ratio2)
 * boot (boot)
 */

/* PRCM I target DPLL = 2*330MHz = 660MHz */
#define MI_DPLL_MULT_12			(55 << 12)
#define MI_DPLL_DIV_12			(1 << 8)
#define MI_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC | \
					 MI_DPLL_DIV_12 | MI_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)

/*
 * 2420 Equivalent - mode registers
 * PRCM II , target DPLL = 2*300MHz = 600MHz
 */
#define MII_DPLL_MULT_12		(50 << 12)
#define MII_DPLL_DIV_12			(1 << 8)
#define MII_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC |	\
					 MII_DPLL_DIV_12 | MII_DPLL_MULT_12 | \
					 MX_APLLS_CLIKIN_12)
#define MII_DPLL_MULT_13		(300 << 12)
#define MII_DPLL_DIV_13			(12 << 8)
#define MII_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC |	\
					 MII_DPLL_DIV_13 | MII_DPLL_MULT_13 | \
					 MX_APLLS_CLIKIN_13)

/* PRCM III target DPLL = 2*266 = 532MHz*/
#define MIII_DPLL_MULT_12		(133 << 12)
#define MIII_DPLL_DIV_12		(5 << 8)
#define MIII_CM_CLKSEL1_PLL_12_VAL	(MX_48M_SRC | MX_54M_SRC |	\
					 MIII_DPLL_DIV_12 | \
					 MIII_DPLL_MULT_12 | MX_APLLS_CLIKIN_12)
#define MIII_DPLL_MULT_13		(266 << 12)
#define MIII_DPLL_DIV_13		(12 << 8)
#define MIII_CM_CLKSEL1_PLL_13_VAL	(MX_48M_SRC | MX_54M_SRC |	\
					 MIII_DPLL_DIV_13 | \
					 MIII_DPLL_MULT_13 | MX_APLLS_CLIKIN_13)

/* PRCM VII (boot bypass) */
#define MVII_CM_CLKSEL1_PLL_12_VAL	MB_CM_CLKSEL1_PLL_12_VAL
#define MVII_CM_CLKSEL1_PLL_13_VAL	MB_CM_CLKSEL1_PLL_13_VAL

/* High and low operation value */
#define MX_CLKSEL2_PLL_2x_VAL		(2 << 0)
#define MX_CLKSEL2_PLL_1x_VAL		(1 << 0)

/* MPU speed defines */
#define S12M	12000000
#define S13M	13000000
#define S19M	19200000
#define S26M	26000000
#define S100M	100000000
#define S133M	133000000
#define S150M	150000000
#define S164M	164000000
#define S165M	165000000
#define S199M	199000000
#define S200M	200000000
#define S266M	266000000
#define S300M	300000000
#define S329M	329000000
#define S330M	330000000
#define S399M	399000000
#define S400M	400000000
#define S532M	532000000
#define S600M	600000000
#define S658M	658000000
#define S660M	660000000
#define S798M	798000000

extern const struct prcm_config omap2420_rate_table[];

#ifdef CONFIG_SOC_OMAP2430
extern const struct prcm_config omap2430_rate_table[];
#else
#define omap2430_rate_table	NULL
#endif
extern const struct prcm_config *rate_table;
extern const struct prcm_config *curr_prcm_set;

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * OMAP3 OPP table definitions.
 *
 * Copyright (C) 2009-2010 Texas Instruments Incorporated - https://www.ti.com/
 *	Nishanth Menon
 *	Kevin Hilman
 * Copyright (C) 2010-2011 Nokia Corporation.
 *      Eduardo Valentin
 *      Paul Walmsley
 */
#include <linux/module.h>

#include "soc.h"
#include "control.h"
#include "omap_opp_data.h"
#include "pm.h"

/* 34xx */

/* VDD1 */

#define OMAP3430_VDD_MPU_OPP1_UV		975000
#define OMAP3430_VDD_MPU_OPP2_UV		1075000
#define OMAP3430_VDD_MPU_OPP3_UV		1200000
#define OMAP3430_VDD_MPU_OPP4_UV		1270000
#define OMAP3430_VDD_MPU_OPP5_UV		1350000

struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

/* VDD2 */

#define OMAP3430_VDD_CORE_OPP1_UV		975000
#define OMAP3430_VDD_CORE_OPP2_UV		1050000
#define OMAP3430_VDD_CORE_OPP3_UV		1150000

struct omap_volt_data omap34xx_vddcore_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

/* 36xx */

/* VDD1 */

#define OMAP3630_VDD_MPU_OPP50_UV		1012500
#define OMAP3630_VDD_MPU_OPP100_UV		1200000
#define OMAP3630_VDD_MPU_OPP120_UV		1325000
#define OMAP3630_VDD_MPU_OPP1G_UV		1375000

struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

/* VDD2 */

#define OMAP3630_VDD_CORE_OPP50_UV		1000000
#define OMAP3630_VDD_CORE_OPP100_UV		1200000

struct omap_volt_data omap36xx_vddcore_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * OMAP4 OPP table definitions.
 *
 * Copyright (C) 2010-2012 Texas Instruments Incorporated - https://www.ti.com/
 *	Nishanth Menon
 *	Kevin Hilman
 *	Thara Gopinath
 * Copyright (C) 2010-2011 Nokia Corporation.
 *      Eduardo Valentin
 *      Paul Walmsley
 */
#include <linux/module.h>

#include "soc.h"
#include "control.h"
#include "omap_opp_data.h"
#include "pm.h"

/*
 * Structures containing OMAP4430 voltage supported and various
 * voltage dependent data for each VDD.
 */

#define OMAP4430_VDD_MPU_OPP50_UV		1025000
#define OMAP4430_VDD_MPU_OPP100_UV		1200000
#define OMAP4430_VDD_MPU_OPPTURBO_UV		1325000
#define OMAP4430_VDD_MPU_OPPNITRO_UV		1388000
#define OMAP4430_VDD_MPU_OPPNITROSB_UV		1398000

struct omap_volt_data omap443x_vdd_mpu_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITROSB_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITROSB, 0xfa, 0x27),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

#define OMAP4430_VDD_IVA_OPP50_UV		 950000
#define OMAP4430_VDD_IVA_OPP100_UV		1114000
#define OMAP4430_VDD_IVA_OPPTURBO_UV		1291000

struct omap_volt_data omap443x_vdd_iva_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

#define OMAP4430_VDD_CORE_OPP50_UV		 962000
#define OMAP4430_VDD_CORE_OPP100_UV		1127000

struct omap_volt_data omap443x_vdd_core_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

#define OMAP4460_VDD_MPU_OPP50_UV		1025000
#define OMAP4460_VDD_MPU_OPP100_UV		1200000
#define OMAP4460_VDD_MPU_OPPTURBO_UV		1313000
#define OMAP4460_VDD_MPU_OPPNITRO_UV		1375000

struct omap_volt_data omap446x_vdd_mpu_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
	VOLT_DATA_DEFINE(OMAP4460_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

#define OMAP4460_VDD_IVA_OPP50_UV		1025000
#define OMAP4460_VDD_IVA_OPP100_UV		1200000
#define OMAP4460_VDD_IVA_OPPTURBO_UV		1313000
#define OMAP4460_VDD_IVA_OPPNITRO_UV		1375000

struct omap_volt_data omap446x_vdd_iva_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
	VOLT_DATA_DEFINE(OMAP4460_VDD_IVA_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPNITRO, 0xfa, 0x23),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};

#define OMAP4460_VDD_CORE_OPP50_UV		1025000
#define OMAP4460_VDD_CORE_OPP100_UV		1200000
#define OMAP4460_VDD_CORE_OPP100_OV_UV		1250000

struct omap_volt_data omap446x_vdd_core_volt_data[] = {
	VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
	VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
	VOLT_DATA_DEFINE(OMAP4460_VDD_CORE_OPP100_OV_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100OV, 0xf9, 0x16),
	VOLT_DATA_DEFINE(0, 0, 0, 0),
};


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Legacy platform_data quirks
 *
 * Copyright (C) 2013 Texas Instruments
 */
#include <linux/clk.h>
#include <linux/davinci_emac.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of_platform.h>
#include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/power/smartreflex.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>

#include <linux/platform_data/pinctrl-single.h>
#include <linux/platform_data/hsmmc-omap.h>
#include <linux/platform_data/iommu-omap.h>
#include <linux/platform_data/ti-sysc.h>
#include <linux/platform_data/wkup_m3.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include <linux/platform_data/ti-prm.h>

#include "clockdomain.h"
#include "common.h"
#include "common-board-devices.h"
#include "control.h"
#include "omap_device.h"
#include "omap-secure.h"
#include "soc.h"

static struct omap_hsmmc_platform_data __maybe_unused mmc_pdata[2];

struct pdata_init {
	const char *compatible;
	void (*fn)(void);
};

static struct of_dev_auxdata omap_auxdata_lookup[];
static struct twl4030_gpio_platform_data twl_gpio_auxdata;

#ifdef CONFIG_MACH_NOKIA_N8X0
static void __init omap2420_n8x0_legacy_init(void)
{
	omap_auxdata_lookup[0].platform_data = n8x0_legacy_init();
}
#else
#define omap2420_n8x0_legacy_init	NULL
#endif

#ifdef CONFIG_ARCH_OMAP3
/*
 * Configures GPIOs 126, 127 and 129 to 1.8V mode instead of 3.0V
 * mode for MMC1 in case bootloader did not configure things.
 * Note that if the pins are used for MMC1, pbias-regulator
 * manages the IO voltage.
 */
static void __init omap3_gpio126_127_129(void)
{
	u32 reg;

	reg = omap_ctrl_readl(OMAP343X_CONTROL_PBIAS_LITE);
	reg &= ~OMAP343X_PBIASLITEVMODE1;
	reg |= OMAP343X_PBIASLITEPWRDNZ1;
	omap_ctrl_writel(reg, OMAP343X_CONTROL_PBIAS_LITE);
	if (cpu_is_omap3630()) {
		reg = omap_ctrl_readl(OMAP34XX_CONTROL_WKUP_CTRL);
		reg |= OMAP36XX_GPIO_IO_PWRDNZ;
		omap_ctrl_writel(reg, OMAP34XX_CONTROL_WKUP_CTRL);
	}
}

static void __init hsmmc2_internal_input_clk(void)
{
	u32 reg;

	reg = omap_ctrl_readl(OMAP343X_CONTROL_DEVCONF1);
	reg |= OMAP2_MMCSDIO2ADPCLKISEL;
	omap_ctrl_writel(reg, OMAP343X_CONTROL_DEVCONF1);
}

#ifdef CONFIG_OMAP_HWMOD
static struct iommu_platform_data omap3_iommu_pdata = {
	.reset_name = "mmu",
	.assert_reset = omap_device_assert_hardreset,
	.deassert_reset = omap_device_deassert_hardreset,
	.device_enable = omap_device_enable,
	.device_idle = omap_device_idle,
};

static struct iommu_platform_data omap3_iommu_isp_pdata = {
	.device_enable = omap_device_enable,
	.device_idle = omap_device_idle,
};
#endif

static int omap3_sbc_t3730_twl_callback(struct device *dev,
					   unsigned gpio,
					   unsigned ngpio)
{
	int res;

	res = gpio_request_one(gpio + 2, GPIOF_OUT_INIT_HIGH,
			       "wlan pwr");
	if (res)
		return res;

	gpio_export(gpio, 0);

	return 0;
}

static void __init omap3_sbc_t3x_usb_hub_init(int gpio, char *hub_name)
{
	int err = gpio_request_one(gpio, GPIOF_OUT_INIT_LOW, hub_name);

	if (err) {
		pr_err("SBC-T3x: %s reset gpio request failed: %d\n",
			hub_name, err);
		return;
	}

	gpio_export(gpio, 0);

	udelay(10);
	gpio_set_value(gpio, 1);
	msleep(1);
}

static void __init omap3_sbc_t3730_twl_init(void)
{
	twl_gpio_auxdata.setup = omap3_sbc_t3730_twl_callback;
}

static void __init omap3_sbc_t3730_legacy_init(void)
{
	omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub");
}

static void __init omap3_sbc_t3530_legacy_init(void)
{
	omap3_sbc_t3x_usb_hub_init(167, "sb-t35 usb hub");
}

static void __init omap3_evm_legacy_init(void)
{
	hsmmc2_internal_input_clk();
}

static void am35xx_enable_emac_int(void)
{
	u32 v;

	v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
	v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR |
	      AM35XX_CPGMAC_C0_MISC_PULSE_CLR | AM35XX_CPGMAC_C0_RX_THRESH_CLR);
	omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR);
	omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */
}

static void am35xx_disable_emac_int(void)
{
	u32 v;

	v = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
	v |= (AM35XX_CPGMAC_C0_RX_PULSE_CLR | AM35XX_CPGMAC_C0_TX_PULSE_CLR);
	omap_ctrl_writel(v, AM35XX_CONTROL_LVL_INTR_CLEAR);
	omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR); /* OCP barrier */
}

static struct emac_platform_data am35xx_emac_pdata = {
	.interrupt_enable	= am35xx_enable_emac_int,
	.interrupt_disable	= am35xx_disable_emac_int,
};

static void __init am35xx_emac_reset(void)
{
	u32 v;

	v = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
	v &= ~AM35XX_CPGMACSS_SW_RST;
	omap_ctrl_writel(v, AM35XX_CONTROL_IP_SW_RESET);
	omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET); /* OCP barrier */
}

static struct gpio cm_t3517_wlan_gpios[] __initdata = {
	{ 56,	GPIOF_OUT_INIT_HIGH,	"wlan pwr" },
	{ 4,	GPIOF_OUT_INIT_HIGH,	"xcvr noe" },
};

static void __init omap3_sbc_t3517_wifi_init(void)
{
	int err = gpio_request_array(cm_t3517_wlan_gpios,
				ARRAY_SIZE(cm_t3517_wlan_gpios));
	if (err) {
		pr_err("SBC-T3517: wl12xx gpios request failed: %d\n", err);
		return;
	}

	gpio_export(cm_t3517_wlan_gpios[0].gpio, 0);
	gpio_export(cm_t3517_wlan_gpios[1].gpio, 0);

	msleep(100);
	gpio_set_value(cm_t3517_wlan_gpios[1].gpio, 0);
}

static void __init omap3_sbc_t3517_legacy_init(void)
{
	omap3_sbc_t3x_usb_hub_init(152, "cm-t3517 usb hub");
	omap3_sbc_t3x_usb_hub_init(98, "sb-t35 usb hub");
	am35xx_emac_reset();
	hsmmc2_internal_input_clk();
	omap3_sbc_t3517_wifi_init();
}

static void __init am3517_evm_legacy_init(void)
{
	am35xx_emac_reset();
}

static void __init nokia_n900_legacy_init(void)
{
	hsmmc2_internal_input_clk();
	mmc_pdata[0].name = "external";
	mmc_pdata[1].name = "internal";

	if (omap_type() != OMAP2_DEVICE_TYPE_GP) {
		if (IS_ENABLED(CONFIG_ARM_ERRATA_430973)) {
			pr_info("RX-51: Enabling ARM errata 430973 workaround\n");
			/* set IBE to 1 */
			rx51_secure_update_aux_cr(BIT(6), 0);
		} else {
			pr_warn("RX-51: Not enabling ARM errata 430973 workaround\n");
			pr_warn("Thumb binaries may crash randomly without this workaround\n");
		}
	}
}

static void __init omap3_tao3530_legacy_init(void)
{
	hsmmc2_internal_input_clk();
}

static void __init omap3_logicpd_torpedo_init(void)
{
	omap3_gpio126_127_129();
}

/* omap3pandora legacy devices */

static struct platform_device pandora_backlight = {
	.name	= "pandora-backlight",
	.id	= -1,
};

static void __init omap3_pandora_legacy_init(void)
{
	platform_device_register(&pandora_backlight);
}
#endif /* CONFIG_ARCH_OMAP3 */

#ifdef CONFIG_SOC_DRA7XX
static struct iommu_platform_data dra7_ipu1_dsp_iommu_pdata = {
	.set_pwrdm_constraint = omap_iommu_set_pwrdm_constraint,
};
#endif

static struct clockdomain *ti_sysc_find_one_clockdomain(struct clk *clk)
{
	struct clk_hw *hw = __clk_get_hw(clk);
	struct clockdomain *clkdm = NULL;
	struct clk_hw_omap *hwclk;

	hwclk = to_clk_hw_omap(hw);
	if (!omap2_clk_is_hw_omap(hw))
		return NULL;

	if (hwclk && hwclk->clkdm_name)
		clkdm = clkdm_lookup(hwclk->clkdm_name);

	return clkdm;
}

/**
 * ti_sysc_clkdm_init - find clockdomain based on clock
 * @fck: device functional clock
 * @ick: device interface clock
 * @dev: struct device
 *
 * Populate clockdomain based on clock. It is needed for
 * clkdm_deny_idle() and clkdm_allow_idle() for blocking clockdomain
 * clockdomain idle during reset, enable and idle.
 *
 * Note that we assume interconnect driver manages the clocks
 * and do not need to populate oh->_clk for dynamically
 * allocated modules.
 */
static int ti_sysc_clkdm_init(struct device *dev,
			      struct clk *fck, struct clk *ick,
			      struct ti_sysc_cookie *cookie)
{
	if (!IS_ERR(fck))
		cookie->clkdm = ti_sysc_find_one_clockdomain(fck);
	if (cookie->clkdm)
		return 0;
	if (!IS_ERR(ick))
		cookie->clkdm = ti_sysc_find_one_clockdomain(ick);
	if (cookie->clkdm)
		return 0;

	return -ENODEV;
}

static void ti_sysc_clkdm_deny_idle(struct device *dev,
				    const struct ti_sysc_cookie *cookie)
{
	if (cookie->clkdm)
		clkdm_deny_idle(cookie->clkdm);
}

static void ti_sysc_clkdm_allow_idle(struct device *dev,
				     const struct ti_sysc_cookie *cookie)
{
	if (cookie->clkdm)
		clkdm_allow_idle(cookie->clkdm);
}

#ifdef CONFIG_OMAP_HWMOD
static int ti_sysc_enable_module(struct device *dev,
				 const struct ti_sysc_cookie *cookie)
{
	if (!cookie->data)
		return -EINVAL;

	return omap_hwmod_enable(cookie->data);
}

static int ti_sysc_idle_module(struct device *dev,
			       const struct ti_sysc_cookie *cookie)
{
	if (!cookie->data)
		return -EINVAL;

	return omap_hwmod_idle(cookie->data);
}

static int ti_sysc_shutdown_module(struct device *dev,
				   const struct ti_sysc_cookie *cookie)
{
	if (!cookie->data)
		return -EINVAL;

	return omap_hwmod_shutdown(cookie->data);
}
#endif	/* CONFIG_OMAP_HWMOD */

static bool ti_sysc_soc_type_gp(void)
{
	return omap_type() == OMAP2_DEVICE_TYPE_GP;
}

static struct of_dev_auxdata omap_auxdata_lookup[];

static struct ti_sysc_platform_data ti_sysc_pdata = {
	.auxdata = omap_auxdata_lookup,
	.soc_type_gp = ti_sysc_soc_type_gp,
	.init_clockdomain = ti_sysc_clkdm_init,
	.clkdm_deny_idle = ti_sysc_clkdm_deny_idle,
	.clkdm_allow_idle = ti_sysc_clkdm_allow_idle,
#ifdef CONFIG_OMAP_HWMOD
	.init_module = omap_hwmod_init_module,
	.enable_module = ti_sysc_enable_module,
	.idle_module = ti_sysc_idle_module,
	.shutdown_module = ti_sysc_shutdown_module,
#endif
};

static struct pcs_pdata pcs_pdata;

void omap_pcs_legacy_init(int irq, void (*rearm)(void))
{
	pcs_pdata.irq = irq;
	pcs_pdata.rearm = rearm;
}

static struct ti_prm_platform_data ti_prm_pdata = {
	.clkdm_deny_idle = clkdm_deny_idle,
	.clkdm_allow_idle = clkdm_allow_idle,
	.clkdm_lookup = clkdm_lookup,
};

/*
 * GPIOs for TWL are initialized by the I2C bus and need custom
 * handing until DSS has device tree bindings.
 */
void omap_auxdata_legacy_init(struct device *dev)
{
	if (dev->platform_data)
		return;

	if (strcmp("twl4030-gpio", dev_name(dev)))
		return;

	dev->platform_data = &twl_gpio_auxdata;
}

#if defined(CONFIG_ARCH_OMAP3) && IS_ENABLED(CONFIG_SND_SOC_OMAP_MCBSP)
static struct omap_mcbsp_platform_data mcbsp_pdata;
static void __init omap3_mcbsp_init(void)
{
	omap3_mcbsp_init_pdata_callback(&mcbsp_pdata);
}
#else
static void __init omap3_mcbsp_init(void) {}
#endif

/*
 * Few boards still need auxdata populated before we populate
 * the dev entries in of_platform_populate().
 */
static struct pdata_init auxdata_quirks[] __initdata = {
#ifdef CONFIG_SOC_OMAP2420
	{ "nokia,n800", omap2420_n8x0_legacy_init, },
	{ "nokia,n810", omap2420_n8x0_legacy_init, },
	{ "nokia,n810-wimax", omap2420_n8x0_legacy_init, },
#endif
#ifdef CONFIG_ARCH_OMAP3
	{ "compulab,omap3-sbc-t3730", omap3_sbc_t3730_twl_init, },
#endif
	{ /* sentinel */ },
};

struct omap_sr_data __maybe_unused omap_sr_pdata[OMAP_SR_NR];

static struct of_dev_auxdata omap_auxdata_lookup[] = {
#ifdef CONFIG_MACH_NOKIA_N8X0
	OF_DEV_AUXDATA("ti,omap2420-mmc", 0x4809c000, "mmci-omap.0", NULL),
	OF_DEV_AUXDATA("menelaus", 0x72, "1-0072", &n8x0_menelaus_platform_data),
#endif
#ifdef CONFIG_ARCH_OMAP3
	OF_DEV_AUXDATA("ti,omap2-iommu", 0x5d000000, "5d000000.mmu",
		       &omap3_iommu_pdata),
	OF_DEV_AUXDATA("ti,omap2-iommu", 0x480bd400, "480bd400.mmu",
		       &omap3_iommu_isp_pdata),
	OF_DEV_AUXDATA("ti,omap3-smartreflex-core", 0x480cb000,
		       "480cb000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]),
	OF_DEV_AUXDATA("ti,omap3-smartreflex-mpu-iva", 0x480c9000,
		       "480c9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]),
	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x4809c000, "4809c000.mmc", &mmc_pdata[0]),
	OF_DEV_AUXDATA("ti,omap3-hsmmc", 0x480b4000, "480b4000.mmc", &mmc_pdata[1]),
	/* Only on am3517 */
	OF_DEV_AUXDATA("ti,davinci_mdio", 0x5c030000, "davinci_mdio.0", NULL),
	OF_DEV_AUXDATA("ti,am3517-emac", 0x5c000000, "davinci_emac.0",
		       &am35xx_emac_pdata),
	OF_DEV_AUXDATA("nokia,n900-rom-rng", 0, NULL, rx51_secure_rng_call),
	/* McBSP modules with sidetone core */
#if IS_ENABLED(CONFIG_SND_SOC_OMAP_MCBSP)
	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49022000, "49022000.mcbsp", &mcbsp_pdata),
	OF_DEV_AUXDATA("ti,omap3-mcbsp", 0x49024000, "49024000.mcbsp", &mcbsp_pdata),
#endif
#endif
#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
	OF_DEV_AUXDATA("ti,omap4-smartreflex-iva", 0x4a0db000,
		       "4a0db000.smartreflex", &omap_sr_pdata[OMAP_SR_IVA]),
	OF_DEV_AUXDATA("ti,omap4-smartreflex-core", 0x4a0dd000,
		       "4a0dd000.smartreflex", &omap_sr_pdata[OMAP_SR_CORE]),
	OF_DEV_AUXDATA("ti,omap4-smartreflex-mpu", 0x4a0d9000,
		       "4a0d9000.smartreflex", &omap_sr_pdata[OMAP_SR_MPU]),
#endif
#ifdef CONFIG_SOC_DRA7XX
	OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x40d01000, "40d01000.mmu",
		       &dra7_ipu1_dsp_iommu_pdata),
	OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x41501000, "41501000.mmu",
		       &dra7_ipu1_dsp_iommu_pdata),
	OF_DEV_AUXDATA("ti,dra7-iommu", 0x58882000, "58882000.mmu",
		       &dra7_ipu1_dsp_iommu_pdata),
#endif
	/* Common auxdata */
	OF_DEV_AUXDATA("simple-pm-bus", 0, NULL, omap_auxdata_lookup),
	OF_DEV_AUXDATA("ti,sysc", 0, NULL, &ti_sysc_pdata),
	OF_DEV_AUXDATA("pinctrl-single", 0, NULL, &pcs_pdata),
	OF_DEV_AUXDATA("ti,omap-prm-inst", 0, NULL, &ti_prm_pdata),
	OF_DEV_AUXDATA("ti,omap-sdma", 0, NULL, &dma_plat_info),
	{ /* sentinel */ },
};

/*
 * Few boards still need to initialize some legacy devices with
 * platform data until the drivers support device tree.
 */
static struct pdata_init pdata_quirks[] __initdata = {
#ifdef CONFIG_ARCH_OMAP3
	{ "compulab,omap3-sbc-t3517", omap3_sbc_t3517_legacy_init, },
	{ "compulab,omap3-sbc-t3530", omap3_sbc_t3530_legacy_init, },
	{ "compulab,omap3-sbc-t3730", omap3_sbc_t3730_legacy_init, },
	{ "nokia,omap3-n900", nokia_n900_legacy_init, },
	{ "nokia,omap3-n9", hsmmc2_internal_input_clk, },
	{ "nokia,omap3-n950", hsmmc2_internal_input_clk, },
	{ "logicpd,dm3730-torpedo-devkit", omap3_logicpd_torpedo_init, },
	{ "ti,omap3-evm-37xx", omap3_evm_legacy_init, },
	{ "ti,am3517-evm", am3517_evm_legacy_init, },
	{ "technexion,omap3-tao3530", omap3_tao3530_legacy_init, },
	{ "openpandora,omap3-pandora-600mhz", omap3_pandora_legacy_init, },
	{ "openpandora,omap3-pandora-1ghz", omap3_pandora_legacy_init, },
#endif
	{ /* sentinel */ },
};

static void pdata_quirks_check(struct pdata_init *quirks)
{
	while (quirks->compatible) {
		if (of_machine_is_compatible(quirks->compatible)) {
			if (quirks->fn)
				quirks->fn();
		}
		quirks++;
	}
}

static const char * const pdata_quirks_init_nodes[] = {
	"prcm",
	"prm",
};

static void __init
pdata_quirks_init_clocks(const struct of_device_id *omap_dt_match_table)
{
	struct device_node *np;
	int i;

	for (i = 0; i < ARRAY_SIZE(pdata_quirks_init_nodes); i++) {
		np = of_find_node_by_name(NULL, pdata_quirks_init_nodes[i]);
		if (!np)
			continue;

		of_platform_populate(np, omap_dt_match_table,
				     omap_auxdata_lookup, NULL);

		of_node_put(np);
	}
}

void __init pdata_quirks_init(const struct of_device_id *omap_dt_match_table)
{
	/*
	 * We still need this for omap2420 and omap3 PM to work, others are
	 * using drivers/misc/sram.c already.
	 */
	if (of_machine_is_compatible("ti,omap2420") ||
	    of_machine_is_compatible("ti,omap3"))
		omap_sdrc_init(NULL, NULL);

	if (of_machine_is_compatible("ti,omap3"))
		omap3_mcbsp_init();
	pdata_quirks_check(auxdata_quirks);

	pdata_quirks_init_clocks(omap_dt_match_table);

	of_platform_populate(NULL, omap_dt_match_table,
			     omap_auxdata_lookup, NULL);
	pdata_quirks_check(pdata_quirks);
}


code:
// SPDX-License-Identifier: GPL-2.0
/*
 * TI AM33XX and AM43XX PM Assembly Offsets
 *
 * Copyright (C) 2017-2018 Texas Instruments Inc.
 */

#include <linux/kbuild.h>
#include <linux/platform_data/pm33xx.h>
#include <linux/ti-emif-sram.h>

int main(void)
{
	ti_emif_asm_offsets();

	DEFINE(AMX3_PM_WFI_FLAGS_OFFSET,
	       offsetof(struct am33xx_pm_sram_data, wfi_flags));
	DEFINE(AMX3_PM_L2_AUX_CTRL_VAL_OFFSET,
	       offsetof(struct am33xx_pm_sram_data, l2_aux_ctrl_val));
	DEFINE(AMX3_PM_L2_PREFETCH_CTRL_VAL_OFFSET,
	       offsetof(struct am33xx_pm_sram_data, l2_prefetch_ctrl_val));
	DEFINE(AMX3_PM_SRAM_DATA_SIZE, sizeof(struct am33xx_pm_sram_data));

	BLANK();

	DEFINE(AMX3_PM_RO_SRAM_DATA_VIRT_OFFSET,
	       offsetof(struct am33xx_pm_ro_sram_data, amx3_pm_sram_data_virt));
	DEFINE(AMX3_PM_RO_SRAM_DATA_PHYS_OFFSET,
	       offsetof(struct am33xx_pm_ro_sram_data, amx3_pm_sram_data_phys));
	DEFINE(AMX3_PM_RTC_BASE_VIRT_OFFSET,
	       offsetof(struct am33xx_pm_ro_sram_data, rtc_base_virt));
	DEFINE(AMX3_PM_RO_SRAM_DATA_SIZE,
	       sizeof(struct am33xx_pm_ro_sram_data));

	return 0;
}


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * OMAP Power Management debug routines
 *
 * Copyright (C) 2005 Texas Instruments, Inc.
 * Copyright (C) 2006-2008 Nokia Corporation
 *
 * Written by:
 * Richard Woodruff <r-woodruff2@ti.com>
 * Tony Lindgren
 * Juha Yrjola
 * Amit Kucheria <amit.kucheria@nokia.com>
 * Igor Stoppa <igor.stoppa@nokia.com>
 * Jouni Hogander
 *
 * Based on pm.c for omap2
 */

#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/sched/clock.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/slab.h>

#include "clock.h"
#include "powerdomain.h"
#include "clockdomain.h"

#include "soc.h"
#include "cm2xxx_3xxx.h"
#include "prm2xxx_3xxx.h"
#include "pm.h"

#ifdef CONFIG_DEBUG_FS
#include <linux/debugfs.h>
#include <linux/seq_file.h>

static int pm_dbg_init_done;

static int pm_dbg_init(void);

static const char pwrdm_state_names[][PWRDM_MAX_PWRSTS] = {
	"OFF",
	"RET",
	"INA",
	"ON"
};

void pm_dbg_update_time(struct powerdomain *pwrdm, int prev)
{
	s64 t;

	if (!pm_dbg_init_done)
		return ;

	/* Update timer for previous state */
	t = sched_clock();

	pwrdm->state_timer[prev] += t - pwrdm->timer;

	pwrdm->timer = t;
}

static int clkdm_dbg_show_counter(struct clockdomain *clkdm, void *user)
{
	struct seq_file *s = (struct seq_file *)user;

	if (strcmp(clkdm->name, "emu_clkdm") == 0 ||
		strcmp(clkdm->name, "wkup_clkdm") == 0 ||
		strncmp(clkdm->name, "dpll", 4) == 0)
		return 0;

	seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
		   clkdm->usecount);

	return 0;
}

static int pwrdm_dbg_show_counter(struct powerdomain *pwrdm, void *user)
{
	struct seq_file *s = (struct seq_file *)user;
	int i;

	if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
		strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
		strncmp(pwrdm->name, "dpll", 4) == 0)
		return 0;

	if (pwrdm->state != pwrdm_read_pwrst(pwrdm))
		printk(KERN_ERR "pwrdm state mismatch(%s) %d != %d\n",
			pwrdm->name, pwrdm->state, pwrdm_read_pwrst(pwrdm));

	seq_printf(s, "%s (%s)", pwrdm->name,
			pwrdm_state_names[pwrdm->state]);
	for (i = 0; i < PWRDM_MAX_PWRSTS; i++)
		seq_printf(s, ",%s:%d", pwrdm_state_names[i],
			pwrdm->state_counter[i]);

	seq_printf(s, ",RET-LOGIC-OFF:%d", pwrdm->ret_logic_off_counter);
	for (i = 0; i < pwrdm->banks; i++)
		seq_printf(s, ",RET-MEMBANK%d-OFF:%d", i + 1,
				pwrdm->ret_mem_off_counter[i]);

	seq_putc(s, '\n');
	return 0;
}

static int pwrdm_dbg_show_timer(struct powerdomain *pwrdm, void *user)
{
	struct seq_file *s = (struct seq_file *)user;
	int i;

	if (strcmp(pwrdm->name, "emu_pwrdm") == 0 ||
		strcmp(pwrdm->name, "wkup_pwrdm") == 0 ||
		strncmp(pwrdm->name, "dpll", 4) == 0)
		return 0;

	pwrdm_state_switch(pwrdm);

	seq_printf(s, "%s (%s)", pwrdm->name,
		pwrdm_state_names[pwrdm->state]);

	for (i = 0; i < 4; i++)
		seq_printf(s, ",%s:%lld", pwrdm_state_names[i],
			pwrdm->state_timer[i]);

	seq_putc(s, '\n');
	return 0;
}

static int pm_dbg_counters_show(struct seq_file *s, void *unused)
{
	pwrdm_for_each(pwrdm_dbg_show_counter, s);
	clkdm_for_each(clkdm_dbg_show_counter, s);

	return 0;
}
DEFINE_SHOW_ATTRIBUTE(pm_dbg_counters);

static int pm_dbg_timers_show(struct seq_file *s, void *unused)
{
	pwrdm_for_each(pwrdm_dbg_show_timer, s);
	return 0;
}
DEFINE_SHOW_ATTRIBUTE(pm_dbg_timers);

static int pwrdm_suspend_get(void *data, u64 *val)
{
	int ret = -EINVAL;

	if (cpu_is_omap34xx())
		ret = omap3_pm_get_suspend_state((struct powerdomain *)data);
	*val = ret;

	if (ret >= 0)
		return 0;
	return *val;
}

static int pwrdm_suspend_set(void *data, u64 val)
{
	if (cpu_is_omap34xx())
		return omap3_pm_set_suspend_state(
			(struct powerdomain *)data, (int)val);
	return -EINVAL;
}

DEFINE_DEBUGFS_ATTRIBUTE(pwrdm_suspend_fops, pwrdm_suspend_get,
			  pwrdm_suspend_set, "%llu\n");

static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
{
	int i;
	s64 t;
	struct dentry *d;

	t = sched_clock();

	for (i = 0; i < 4; i++)
		pwrdm->state_timer[i] = 0;

	pwrdm->timer = t;

	if (strncmp(pwrdm->name, "dpll", 4) == 0)
		return 0;

	d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
	debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d, pwrdm,
			    &pwrdm_suspend_fops);

	return 0;
}

static int option_get(void *data, u64 *val)
{
	u32 *option = data;

	*val = *option;

	return 0;
}

static int option_set(void *data, u64 val)
{
	u32 *option = data;

	*option = val;

	if (option == &enable_off_mode) {
		if (cpu_is_omap34xx())
			omap3_pm_off_mode_enable(val);
	}

	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(pm_dbg_option_fops, option_get, option_set, "%llu\n");

static int __init pm_dbg_init(void)
{
	struct dentry *d;

	if (pm_dbg_init_done)
		return 0;

	d = debugfs_create_dir("pm_debug", NULL);

	debugfs_create_file("count", 0444, d, NULL, &pm_dbg_counters_fops);
	debugfs_create_file("time", 0444, d, NULL, &pm_dbg_timers_fops);

	pwrdm_for_each(pwrdms_setup, (void *)d);

	debugfs_create_file("enable_off_mode", S_IRUGO | S_IWUSR, d,
			    &enable_off_mode, &pm_dbg_option_fops);
	pm_dbg_init_done = 1;

	return 0;
}
omap_arch_initcall(pm_dbg_init);

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * pm.c - Common OMAP2+ power management-related code
 *
 * Copyright (C) 2010 Texas Instruments, Inc.
 * Copyright (C) 2010 Nokia Corporation
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/pm_opp.h>
#include <linux/export.h>
#include <linux/suspend.h>
#include <linux/clk.h>
#include <linux/cpu.h>

#include <asm/system_misc.h>

#include "omap_device.h"
#include "common.h"

#include "soc.h"
#include "prcm-common.h"
#include "voltage.h"
#include "powerdomain.h"
#include "clockdomain.h"
#include "pm.h"

u32 enable_off_mode;

#ifdef CONFIG_SUSPEND
/*
 * omap_pm_suspend: points to a function that does the SoC-specific
 * suspend work
 */
static int (*omap_pm_suspend)(void);
#endif

#ifdef CONFIG_PM
/**
 * struct omap2_oscillator - Describe the board main oscillator latencies
 * @startup_time: oscillator startup latency
 * @shutdown_time: oscillator shutdown latency
 */
struct omap2_oscillator {
	u32 startup_time;
	u32 shutdown_time;
};

static struct omap2_oscillator oscillator = {
	.startup_time = ULONG_MAX,
	.shutdown_time = ULONG_MAX,
};

void omap_pm_setup_oscillator(u32 tstart, u32 tshut)
{
	oscillator.startup_time = tstart;
	oscillator.shutdown_time = tshut;
}

void omap_pm_get_oscillator(u32 *tstart, u32 *tshut)
{
	if (!tstart || !tshut)
		return;

	*tstart = oscillator.startup_time;
	*tshut = oscillator.shutdown_time;
}
#endif

int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
{
	clkdm_allow_idle(clkdm);
	return 0;
}

#ifdef CONFIG_SUSPEND
static int omap_pm_enter(suspend_state_t suspend_state)
{
	int ret = 0;

	if (!omap_pm_suspend)
		return -ENOENT; /* XXX doublecheck */

	switch (suspend_state) {
	case PM_SUSPEND_MEM:
		ret = omap_pm_suspend();
		break;
	default:
		ret = -EINVAL;
	}

	return ret;
}

static int omap_pm_begin(suspend_state_t state)
{
	cpu_idle_poll_ctrl(true);
	if (soc_is_omap34xx())
		omap_prcm_irq_prepare();
	return 0;
}

static void omap_pm_end(void)
{
	cpu_idle_poll_ctrl(false);
}

static void omap_pm_wake(void)
{
	if (soc_is_omap34xx())
		omap_prcm_irq_complete();
}

static const struct platform_suspend_ops omap_pm_ops = {
	.begin		= omap_pm_begin,
	.end		= omap_pm_end,
	.enter		= omap_pm_enter,
	.wake		= omap_pm_wake,
	.valid		= suspend_valid_only_mem,
};

/**
 * omap_common_suspend_init - Set common suspend routines for OMAP SoCs
 * @pm_suspend: function pointer to SoC specific suspend function
 */
void omap_common_suspend_init(void *pm_suspend)
{
	omap_pm_suspend = pm_suspend;
	suspend_set_ops(&omap_pm_ops);
}
#endif /* CONFIG_SUSPEND */

int __maybe_unused omap_pm_nop_init(void)
{
	return 0;
}

int (*omap_pm_soc_init)(void);

int __init omap2_common_pm_late_init(void)
{
	int error;

	if (!omap_pm_soc_init)
		return 0;

	/* Init the voltage layer */
	omap3_twl_init();
	omap4_twl_init();
	omap4_cpcap_init();
	omap_voltage_late_init();

	/* Smartreflex device init */
	omap_devinit_smartreflex();

	error = omap_pm_soc_init();
	if (error)
		pr_warn("%s: pm soc init failed: %i\n", __func__, error);

	omap2_clk_enable_autoidle_all();

	return 0;
}
omap_late_initcall(omap2_common_pm_late_init);


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * OMAP2/3 Power Management Routines
 *
 * Copyright (C) 2008 Nokia Corporation
 * Jouni Hogander
 */
#ifndef __ARCH_ARM_MACH_OMAP2_PM_H
#define __ARCH_ARM_MACH_OMAP2_PM_H

#include <linux/err.h>

#include "powerdomain.h"

#ifdef CONFIG_CPU_IDLE
extern int __init omap3_idle_init(void);
extern int __init omap4_idle_init(void);
#else
static inline int omap3_idle_init(void)
{
	return 0;
}

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

extern void *omap3_secure_ram_storage;
extern void omap3_pm_off_mode_enable(int);
extern void omap_sram_idle(void);
extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);

#if defined(CONFIG_PM_OPP)
extern int omap3_opp_init(void);
extern int omap4_opp_init(void);
#else
static inline int omap3_opp_init(void)
{
	return -EINVAL;
}
static inline int omap4_opp_init(void)
{
	return -EINVAL;
}
#endif

extern int omap3_pm_get_suspend_state(struct powerdomain *pwrdm);
extern int omap3_pm_set_suspend_state(struct powerdomain *pwrdm, int state);

extern u32 enable_off_mode;

#if defined(CONFIG_PM_DEBUG) && defined(CONFIG_DEBUG_FS)
extern void pm_dbg_update_time(struct powerdomain *pwrdm, int prev);
#else
#define pm_dbg_update_time(pwrdm, prev) do {} while (0);
#endif /* CONFIG_PM_DEBUG */

/* 24xx */
extern void omap24xx_idle_loop_suspend(void);
extern unsigned int omap24xx_idle_loop_suspend_sz;

extern void omap24xx_cpu_suspend(u32 dll_ctrl, void __iomem *sdrc_dlla_ctrl,
					void __iomem *sdrc_power);
extern unsigned int omap24xx_cpu_suspend_sz;

/* 3xxx */
extern void omap34xx_cpu_suspend(int save_state);

/* omap3_do_wfi function pointer and size, for copy to SRAM */
extern void omap3_do_wfi(void);
extern unsigned int omap3_do_wfi_sz;
/* ... and its pointer from SRAM after copy */
extern void (*omap3_do_wfi_sram)(void);

extern struct am33xx_pm_sram_addr am33xx_pm_sram;
extern struct am33xx_pm_sram_addr am43xx_pm_sram;

extern void omap3_save_scratchpad_contents(void);

#define PM_RTA_ERRATUM_i608		(1 << 0)
#define PM_SDRC_WAKEUP_ERRATUM_i583	(1 << 1)
#define PM_PER_MEMORIES_ERRATUM_i582	(1 << 2)

#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3)
extern u16 pm34xx_errata;
#define IS_PM34XX_ERRATUM(id)		(pm34xx_errata & (id))
extern void enable_omap3630_toggle_l2_on_restore(void);
#else
#define IS_PM34XX_ERRATUM(id)		0
static inline void enable_omap3630_toggle_l2_on_restore(void) { }
#endif		/* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */

#define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD	(1 << 0)
#define PM_OMAP4_CPU_OSWR_DISABLE		(1 << 1)

#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_OMAP4) ||\
	   defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX))
extern u16 pm44xx_errata;
#define IS_PM44XX_ERRATUM(id)		(pm44xx_errata & (id))
#else
#define IS_PM44XX_ERRATUM(id)		0
#endif

#define OMAP4_VP_CONFIG_ERROROFFSET	0x00
#define OMAP4_VP_VSTEPMIN_VSTEPMIN	0x01
#define OMAP4_VP_VSTEPMAX_VSTEPMAX	0x04
#define OMAP4_VP_VLIMITTO_TIMEOUT_US	200

#ifdef CONFIG_POWER_AVS_OMAP
extern int omap_devinit_smartreflex(void);
extern void omap_enable_smartreflex_on_init(void);
#else
static inline int omap_devinit_smartreflex(void)
{
	return -EINVAL;
}

static inline void omap_enable_smartreflex_on_init(void) {}
#endif

#ifdef CONFIG_TWL4030_CORE
extern int omap3_twl_init(void);
extern int omap4_twl_init(void);
extern int omap3_twl_set_sr_bit(bool enable);
#else
static inline int omap3_twl_init(void)
{
	return -EINVAL;
}
static inline int omap4_twl_init(void)
{
	return -EINVAL;
}
#endif

#if IS_ENABLED(CONFIG_MFD_CPCAP)
extern int omap4_cpcap_init(void);
#else
static inline int omap4_cpcap_init(void)
{
	return -EINVAL;
}
#endif

#ifdef CONFIG_PM
extern void omap_pm_setup_oscillator(u32 tstart, u32 tshut);
extern void omap_pm_get_oscillator(u32 *tstart, u32 *tshut);
extern void omap_pm_setup_sr_i2c_pcb_length(u32 mm);
#else
static inline void omap_pm_setup_oscillator(u32 tstart, u32 tshut) { }
static inline void omap_pm_get_oscillator(u32 *tstart, u32 *tshut) { *tstart = *tshut = 0; }
static inline void omap_pm_setup_sr_i2c_pcb_length(u32 mm) { }
#endif

#ifdef CONFIG_SUSPEND
void omap_common_suspend_init(void *pm_suspend);
#else
static inline void omap_common_suspend_init(void *pm_suspend)
{
}
#endif /* CONFIG_SUSPEND */
#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * OMAP2 Power Management Routines
 *
 * Copyright (C) 2005 Texas Instruments, Inc.
 * Copyright (C) 2006-2008 Nokia Corporation
 *
 * Written by:
 * Richard Woodruff <r-woodruff2@ti.com>
 * Tony Lindgren
 * Juha Yrjola
 * Amit Kucheria <amit.kucheria@nokia.com>
 * Igor Stoppa <igor.stoppa@nokia.com>
 *
 * Based on pm.c for omap1
 */

#include <linux/cpu_pm.h>
#include <linux/suspend.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/interrupt.h>
#include <linux/sysfs.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/irq.h>
#include <linux/time.h>

#include <asm/fncpy.h>

#include <asm/mach/time.h>
#include <asm/mach/irq.h>
#include <asm/mach-types.h>
#include <asm/system_misc.h>

#include <linux/omap-dma.h>

#include "soc.h"
#include "common.h"
#include "clock.h"
#include "prm2xxx.h"
#include "prm-regbits-24xx.h"
#include "cm2xxx.h"
#include "cm-regbits-24xx.h"
#include "sdrc.h"
#include "sram.h"
#include "pm.h"
#include "control.h"
#include "powerdomain.h"
#include "clockdomain.h"

static void (*omap2_sram_suspend)(u32 dllctrl, void __iomem *sdrc_dlla_ctrl,
				  void __iomem *sdrc_power);

static struct powerdomain *mpu_pwrdm, *core_pwrdm;
static struct clockdomain *dsp_clkdm, *mpu_clkdm, *wkup_clkdm, *gfx_clkdm;

static struct clk *osc_ck, *emul_ck;

static int omap2_enter_full_retention(void)
{
	u32 l;

	/* There is 1 reference hold for all children of the oscillator
	 * clock, the following will remove it. If no one else uses the
	 * oscillator itself it will be disabled if/when we enter retention
	 * mode.
	 */
	clk_disable(osc_ck);

	/* Clear old wake-up events */
	/* REVISIT: These write to reserved bits? */
	omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
	omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
	omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);

	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);

	/* Workaround to kill USB */
	l = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0) | OMAP24XX_USBSTANDBYCTRL;
	omap_ctrl_writel(l, OMAP2_CONTROL_DEVCONF0);

	/* One last check for pending IRQs to avoid extra latency due
	 * to sleeping unnecessarily. */
	if (omap_irq_pending())
		goto no_sleep;

	/* Jump to SRAM suspend code */
	omap2_sram_suspend(sdrc_read_reg(SDRC_DLLA_CTRL),
			   OMAP_SDRC_REGADDR(SDRC_DLLA_CTRL),
			   OMAP_SDRC_REGADDR(SDRC_POWER));

no_sleep:
	clk_enable(osc_ck);

	/* clear CORE wake-up events */
	omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
	omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);

	/* wakeup domain events - bit 1: GPT1, bit5 GPIO */
	omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, 0x4 | 0x1);

	/* MPU domain wake events */
	omap_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET, 0x1);

	omap_prm_clear_mod_irqs(OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET, 0x20);

	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);

	return 0;
}

static int sti_console_enabled;

static int omap2_allow_mpu_retention(void)
{
	if (!omap2xxx_cm_mpu_retention_allowed())
		return 0;
	if (sti_console_enabled)
		return 0;

	return 1;
}

static void omap2_enter_mpu_retention(void)
{
	const int zero = 0;

	/* The peripherals seem not to be able to wake up the MPU when
	 * it is in retention mode. */
	if (omap2_allow_mpu_retention()) {
		/* REVISIT: These write to reserved bits? */
		omap_prm_clear_mod_irqs(CORE_MOD, PM_WKST1, ~0);
		omap_prm_clear_mod_irqs(CORE_MOD, OMAP24XX_PM_WKST2, ~0);
		omap_prm_clear_mod_irqs(WKUP_MOD, PM_WKST, ~0);

		/* Try to enter MPU retention */
		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);

	} else {
		/* Block MPU retention */
		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
	}

	/* WFI */
	asm("mcr p15, 0, %0, c7, c0, 4" : : "r" (zero) : "memory", "cc");

	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
}

static int omap2_can_sleep(void)
{
	if (omap2xxx_cm_fclks_active())
		return 0;
	if (__clk_is_enabled(osc_ck))
		return 0;

	return 1;
}

static void omap2_pm_idle(void)
{
	int error;

	if (omap_irq_pending())
		return;

	error = cpu_cluster_pm_enter();
	if (error || !omap2_can_sleep()) {
		omap2_enter_mpu_retention();
		goto out_cpu_cluster_pm;
	}

	omap2_enter_full_retention();

out_cpu_cluster_pm:
	cpu_cluster_pm_exit();
}

static void __init prcm_setup_regs(void)
{
	int i, num_mem_banks;
	struct powerdomain *pwrdm;

	/*
	 * Enable autoidle
	 * XXX This should be handled by hwmod code or PRCM init code
	 */
	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
			  OMAP2_PRCM_SYSCONFIG_OFFSET);

	/*
	 * Set CORE powerdomain memory banks to retain their contents
	 * during RETENTION
	 */
	num_mem_banks = pwrdm_get_mem_bank_count(core_pwrdm);
	for (i = 0; i < num_mem_banks; i++)
		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);

	pwrdm_set_logic_retst(core_pwrdm, PWRDM_POWER_RET);

	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);

	/* Force-power down DSP, GFX powerdomains */

	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);

	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);

	/* Enable hardware-supervised idle for all clkdms */
	clkdm_for_each(omap_pm_clkdms_setup, NULL);
	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);

	omap_common_suspend_init(omap2_enter_full_retention);

	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
	 * stabilisation */
	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
				OMAP2_PRCM_CLKSSETUP_OFFSET);

	/* Configure automatic voltage transition */
	omap2_prm_write_mod_reg(2 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
				OMAP2_PRCM_VOLTSETUP_OFFSET);
	omap2_prm_write_mod_reg(OMAP24XX_AUTO_EXTVOLT_MASK |
				(0x1 << OMAP24XX_SETOFF_LEVEL_SHIFT) |
				OMAP24XX_MEMRETCTRL_MASK |
				(0x1 << OMAP24XX_SETRET_LEVEL_SHIFT) |
				(0x0 << OMAP24XX_VOLT_LEVEL_SHIFT),
				OMAP24XX_GR_MOD, OMAP2_PRCM_VOLTCTRL_OFFSET);

	/* Enable wake-up events */
	omap2_prm_write_mod_reg(OMAP24XX_EN_GPIOS_MASK | OMAP24XX_EN_GPT1_MASK,
				WKUP_MOD, PM_WKEN);

	/* Enable SYS_CLKEN control when all domains idle */
	omap2_prm_set_mod_reg_bits(OMAP_AUTOEXTCLKMODE_MASK, OMAP24XX_GR_MOD,
				   OMAP2_PRCM_CLKSRC_CTRL_OFFSET);
}

int __init omap2_pm_init(void)
{
	u32 l;

	printk(KERN_INFO "Power Management for OMAP2 initializing\n");
	l = omap2_prm_read_mod_reg(OCP_MOD, OMAP2_PRCM_REVISION_OFFSET);
	printk(KERN_INFO "PRCM revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);

	/* Look up important powerdomains */

	mpu_pwrdm = pwrdm_lookup("mpu_pwrdm");
	if (!mpu_pwrdm)
		pr_err("PM: mpu_pwrdm not found\n");

	core_pwrdm = pwrdm_lookup("core_pwrdm");
	if (!core_pwrdm)
		pr_err("PM: core_pwrdm not found\n");

	/* Look up important clockdomains */

	mpu_clkdm = clkdm_lookup("mpu_clkdm");
	if (!mpu_clkdm)
		pr_err("PM: mpu_clkdm not found\n");

	wkup_clkdm = clkdm_lookup("wkup_clkdm");
	if (!wkup_clkdm)
		pr_err("PM: wkup_clkdm not found\n");

	dsp_clkdm = clkdm_lookup("dsp_clkdm");
	if (!dsp_clkdm)
		pr_err("PM: dsp_clkdm not found\n");

	gfx_clkdm = clkdm_lookup("gfx_clkdm");
	if (!gfx_clkdm)
		pr_err("PM: gfx_clkdm not found\n");

	osc_ck = clk_get(NULL, "osc_ck");
	if (IS_ERR(osc_ck)) {
		printk(KERN_ERR "could not get osc_ck\n");
		return -ENODEV;
	}

	if (cpu_is_omap242x()) {
		emul_ck = clk_get(NULL, "emul_ck");
		if (IS_ERR(emul_ck)) {
			printk(KERN_ERR "could not get emul_ck\n");
			clk_put(osc_ck);
			return -ENODEV;
		}
	}

	prcm_setup_regs();

	/*
	 * We copy the assembler sleep/wakeup routines to SRAM.
	 * These routines need to be in SRAM as that's the only
	 * memory the MPU can see when it wakes up after the entire
	 * chip enters idle.
	 */
	omap2_sram_suspend = omap_sram_push(omap24xx_cpu_suspend,
					    omap24xx_cpu_suspend_sz);

	arm_pm_idle = omap2_pm_idle;

	return 0;
}