code:
/* SPDX-License-Identifier: GPL-2.0-only */
/* IRQ definitions for Marvell Dove 88AP510 SoC */

#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H

/*
 * Dove Low Interrupt Controller
 */
#define IRQ_DOVE_BRIDGE		(1 + 0)
#define IRQ_DOVE_H2C		(1 + 1)
#define IRQ_DOVE_C2H		(1 + 2)
#define IRQ_DOVE_NAND		(1 + 3)
#define IRQ_DOVE_PDMA		(1 + 4)
#define IRQ_DOVE_SPI1		(1 + 5)
#define IRQ_DOVE_SPI0		(1 + 6)
#define IRQ_DOVE_UART_0		(1 + 7)
#define IRQ_DOVE_UART_1		(1 + 8)
#define IRQ_DOVE_UART_2		(1 + 9)
#define IRQ_DOVE_UART_3		(1 + 10)
#define IRQ_DOVE_I2C		(1 + 11)
#define IRQ_DOVE_GPIO_0_7	(1 + 12)
#define IRQ_DOVE_GPIO_8_15	(1 + 13)
#define IRQ_DOVE_GPIO_16_23	(1 + 14)
#define IRQ_DOVE_PCIE0_ERR	(1 + 15)
#define IRQ_DOVE_PCIE0		(1 + 16)
#define IRQ_DOVE_PCIE1_ERR	(1 + 17)
#define IRQ_DOVE_PCIE1		(1 + 18)
#define IRQ_DOVE_I2S0		(1 + 19)
#define IRQ_DOVE_I2S0_ERR	(1 + 20)
#define IRQ_DOVE_I2S1		(1 + 21)
#define IRQ_DOVE_I2S1_ERR	(1 + 22)
#define IRQ_DOVE_USB_ERR	(1 + 23)
#define IRQ_DOVE_USB0		(1 + 24)
#define IRQ_DOVE_USB1		(1 + 25)
#define IRQ_DOVE_GE00_RX	(1 + 26)
#define IRQ_DOVE_GE00_TX	(1 + 27)
#define IRQ_DOVE_GE00_MISC	(1 + 28)
#define IRQ_DOVE_GE00_SUM	(1 + 29)
#define IRQ_DOVE_GE00_ERR	(1 + 30)
#define IRQ_DOVE_CRYPTO		(1 + 31)

/*
 * Dove High Interrupt Controller
 */
#define IRQ_DOVE_AC97		(1 + 32)
#define IRQ_DOVE_PMU		(1 + 33)
#define IRQ_DOVE_CAM		(1 + 34)
#define IRQ_DOVE_SDIO0		(1 + 35)
#define IRQ_DOVE_SDIO1		(1 + 36)
#define IRQ_DOVE_SDIO0_WAKEUP	(1 + 37)
#define IRQ_DOVE_SDIO1_WAKEUP	(1 + 38)
#define IRQ_DOVE_XOR_00		(1 + 39)
#define IRQ_DOVE_XOR_01		(1 + 40)
#define IRQ_DOVE_XOR0_ERR	(1 + 41)
#define IRQ_DOVE_XOR_10		(1 + 42)
#define IRQ_DOVE_XOR_11		(1 + 43)
#define IRQ_DOVE_XOR1_ERR	(1 + 44)
#define IRQ_DOVE_LCD_DCON	(1 + 45)
#define IRQ_DOVE_LCD1		(1 + 46)
#define IRQ_DOVE_LCD0		(1 + 47)
#define IRQ_DOVE_GPU		(1 + 48)
#define IRQ_DOVE_PERFORM_MNTR	(1 + 49)
#define IRQ_DOVE_VPRO_DMA1	(1 + 51)
#define IRQ_DOVE_SSP_TIMER	(1 + 54)
#define IRQ_DOVE_SSP		(1 + 55)
#define IRQ_DOVE_MC_L2_ERR	(1 + 56)
#define IRQ_DOVE_CRYPTO_ERR	(1 + 59)
#define IRQ_DOVE_GPIO_24_31	(1 + 60)
#define IRQ_DOVE_HIGH_GPIO	(1 + 61)
#define IRQ_DOVE_SATA		(1 + 62)

/*
 * DOVE General Purpose Pins
 */
#define IRQ_DOVE_GPIO_START	65
#define NR_GPIO_IRQS		64

/*
 * PMU interrupts
 */
#define IRQ_DOVE_PMU_START	(IRQ_DOVE_GPIO_START + NR_GPIO_IRQS)
#define NR_PMU_IRQS		7
#define IRQ_DOVE_RTC		(IRQ_DOVE_PMU_START + 5)

#define DOVE_NR_IRQS		(IRQ_DOVE_PMU_START + NR_PMU_IRQS)

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * arch/arm/mach-dove/mpp.c
 *
 * MPP functions for Marvell Dove SoCs
 */

#include <linux/kernel.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <plat/mpp.h>
#include <plat/orion-gpio.h>
#include "dove.h"
#include "mpp.h"

struct dove_mpp_grp {
	int start;
	int end;
};

/* Map a group to a range of GPIO pins in that group */
static const struct dove_mpp_grp dove_mpp_grp[] = {
	[MPP_24_39] = {
		.start	= 24,
		.end	= 39,
	},
	[MPP_40_45] = {
		.start	= 40,
		.end	= 45,
	},
	[MPP_46_51] = {
		.start	= 46,
		.end	= 51,
	},
	[MPP_58_61] = {
		.start	= 58,
		.end	= 61,
	},
	[MPP_62_63] = {
		.start	= 62,
		.end	= 63,
	},
};

/* Enable gpio for a range of pins. mode should be a combination of
   GPIO_OUTPUT_OK | GPIO_INPUT_OK */
static void __init dove_mpp_gpio_mode(int start, int end, int gpio_mode)
{
	int i;

	for (i = start; i <= end; i++)
		orion_gpio_set_valid(i, gpio_mode);
}

/* Dump all the extra MPP registers. The platform code will dump the
   registers for pins 0-23. */
static void __init dove_mpp_dump_regs(void)
{
	pr_debug("PMU_CTRL4_CTRL: %08x\n",
		 readl(DOVE_MPP_CTRL4_VIRT_BASE));

	pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n",
		 readl(DOVE_PMU_MPP_GENERAL_CTRL));

	pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
}

static void __init dove_mpp_cfg_nfc(int sel)
{
	u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);

	mpp_gen_cfg &= ~0x1;
	mpp_gen_cfg |= sel;
	writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);

	dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
}

static void __init dove_mpp_cfg_au1(int sel)
{
	u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
	u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
	u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE);
	u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2);

	mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL);
	ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1);
	mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN);
	global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO);

	if (!sel || sel == 0x2)
		dove_mpp_gpio_mode(52, 57, 0);
	else
		dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);

	if (sel & 0x1) {
		global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
		dove_mpp_gpio_mode(56, 57, 0);
	}
	if (sel & 0x2) {
		mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
		dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
	}
	if (sel & 0x4) {
		ssp_ctrl1 |= DOVE_SSP_ON_AU1;
		dove_mpp_gpio_mode(52, 55, 0);
	}
	if (sel & 0x8)
		mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;

	writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
	writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1);
	writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE);
	writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2);
}

/* Configure the group registers, enabling GPIO if sel indicates the
   pin is to be used for GPIO */
static void __init dove_mpp_conf_grp(unsigned int *mpp_grp_list)
{
	u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
	int gpio_mode;

	for ( ; *mpp_grp_list; mpp_grp_list++) {
		unsigned int num = MPP_NUM(*mpp_grp_list);
		unsigned int sel = MPP_SEL(*mpp_grp_list);

		if (num > MPP_GRP_MAX) {
			pr_err("dove: invalid MPP GRP number (%u)\n", num);
			continue;
		}

		mpp_ctrl4 &= ~(0x1 << num);
		mpp_ctrl4 |= sel << num;

		gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0;
		dove_mpp_gpio_mode(dove_mpp_grp[num].start,
				   dove_mpp_grp[num].end, gpio_mode);
	}
	writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
}

/* Configure the various MPP pins on Dove */
void __init dove_mpp_conf(unsigned int *mpp_list,
			  unsigned int *mpp_grp_list,
			  unsigned int grp_au1_52_57,
			  unsigned int grp_nfc_64_71)
{
	dove_mpp_dump_regs();

	/* Use platform code for pins 0-23 */
	orion_mpp_conf(mpp_list, 0, MPP_MAX, DOVE_MPP_VIRT_BASE);

	dove_mpp_conf_grp(mpp_grp_list);
	dove_mpp_cfg_au1(grp_au1_52_57);
	dove_mpp_cfg_nfc(grp_nfc_64_71);

	dove_mpp_dump_regs();
}

repo_name: angery/linux


code:
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ARCH_DOVE_MPP_CODED_H
#define __ARCH_DOVE_MPP_CODED_H

#define MPP(_num, _sel, _in, _out) ( \
	/* MPP number */		((_num) & 0xff) | \
	/* MPP select value */		(((_sel) & 0xf) << 8) | \
	/* may be input signal */	((!!(_in)) << 12) | \
	/* may be output signal */	((!!(_out)) << 13))

#define MPP0_GPIO0		MPP(0, 0x0, 1, 1)
#define MPP0_UA2_RTSn		MPP(0, 0x2, 0, 0)
#define MPP0_SDIO0_CD		MPP(0, 0x3, 0, 0)
#define MPP0_LCD0_PWM		MPP(0, 0xf, 0, 0)

#define MPP1_GPIO1		MPP(1, 0x0, 1, 1)
#define MPP1_UA2_CTSn		MPP(1, 0x2, 0, 0)
#define MPP1_SDIO0_WP		MPP(1, 0x3, 0, 0)
#define MPP1_LCD1_PWM		MPP(1, 0xf, 0, 0)

#define MPP2_GPIO2		MPP(2, 0x0, 1, 1)
#define MPP2_SATA_PRESENT	MPP(2, 0x1, 0, 0)
#define MPP2_UA2_TXD		MPP(2, 0x2, 0, 0)
#define MPP2_SDIO0_BUS_POWER	MPP(2, 0x3, 0, 0)
#define MPP2_UA_RTSn1		MPP(2, 0x4, 0, 0)

#define MPP3_GPIO3		MPP(3, 0x0, 1, 1)
#define MPP3_SATA_ACT		MPP(3, 0x1, 0, 0)
#define MPP3_UA2_RXD		MPP(3, 0x2, 0, 0)
#define MPP3_SDIO0_LED_CTRL	MPP(3, 0x3, 0, 0)
#define MPP3_UA_CTSn1		MPP(3, 0x4, 0, 0)
#define MPP3_SPI_LCD_CS1	MPP(3, 0xf, 0, 0)

#define MPP4_GPIO4		MPP(4, 0x0, 1, 1)
#define MPP4_UA3_RTSn		MPP(4, 0x2, 0, 0)
#define MPP4_SDIO1_CD		MPP(4, 0x3, 0, 0)
#define MPP4_SPI_1_MISO		MPP(4, 0x4, 0, 0)

#define MPP5_GPIO5		MPP(5, 0x0, 1, 1)
#define MPP5_UA3_CTSn		MPP(5, 0x2, 0, 0)
#define MPP5_SDIO1_WP		MPP(5, 0x3, 0, 0)
#define MPP5_SPI_1_CS		MPP(5, 0x4, 0, 0)

#define MPP6_GPIO6		MPP(6, 0x0, 1, 1)
#define MPP6_UA3_TXD		MPP(6, 0x2, 0, 0)
#define MPP6_SDIO1_BUS_POWER	MPP(6, 0x3, 0, 0)
#define MPP6_SPI_1_MOSI		MPP(6, 0x4, 0, 0)

#define MPP7_GPIO7		MPP(7, 0x0, 1, 1)
#define MPP7_UA3_RXD		MPP(7, 0x2, 0, 0)
#define MPP7_SDIO1_LED_CTRL	MPP(7, 0x3, 0, 0)
#define MPP7_SPI_1_SCK		MPP(7, 0x4, 0, 0)

#define MPP8_GPIO8		MPP(8, 0x0, 1, 1)
#define MPP8_WD_RST_OUT		MPP(8, 0x1, 0, 0)

#define MPP9_GPIO9		MPP(9, 0x0, 1, 1)
#define MPP9_PEX1_CLKREQn	MPP(9, 0x5, 0, 0)

#define MPP10_GPIO10		MPP(10, 0x0, 1, 1)
#define MPP10_SSP_SCLK		MPP(10, 0x5, 0, 0)

#define MPP11_GPIO11		MPP(11, 0x0, 1, 1)
#define MPP11_SATA_PRESENT	MPP(11, 0x1, 0, 0)
#define MPP11_SATA_ACT		MPP(11, 0x2, 0, 0)
#define MPP11_SDIO0_LED_CTRL	MPP(11, 0x3, 0, 0)
#define MPP11_SDIO1_LED_CTRL	MPP(11, 0x4, 0, 0)
#define MPP11_PEX0_CLKREQn	MPP(11, 0x5, 0, 0)

#define MPP12_GPIO12		MPP(12, 0x0, 1, 1)
#define MPP12_SATA_ACT		MPP(12, 0x1, 0, 0)
#define MPP12_UA2_RTSn		MPP(12, 0x2, 0, 0)
#define MPP12_AD0_I2S_EXT_MCLK	MPP(12, 0x3, 0, 0)
#define MPP12_SDIO1_CD		MPP(12, 0x4, 0, 0)

#define MPP13_GPIO13		MPP(13, 0x0, 1, 1)
#define MPP13_UA2_CTSn		MPP(13, 0x2, 0, 0)
#define MPP13_AD1_I2S_EXT_MCLK	MPP(13, 0x3, 0, 0)
#define MPP13_SDIO1WP		MPP(13, 0x4, 0, 0)
#define MPP13_SSP_EXTCLK	MPP(13, 0x5, 0, 0)

#define MPP14_GPIO14		MPP(14, 0x0, 1, 1)
#define MPP14_UA2_TXD		MPP(14, 0x2, 0, 0)
#define MPP14_SDIO1_BUS_POWER	MPP(14, 0x4, 0, 0)
#define MPP14_SSP_RXD		MPP(14, 0x5, 0, 0)

#define MPP15_GPIO15		MPP(15, 0x0, 1, 1)
#define MPP15_UA2_RXD		MPP(15, 0x2, 0, 0)
#define MPP15_SDIO1_LED_CTRL	MPP(15, 0x4, 0, 0)
#define MPP15_SSP_SFRM		MPP(15, 0x5, 0, 0)

#define MPP16_GPIO16		MPP(16, 0x0, 1, 1)
#define MPP16_UA3_RTSn		MPP(16, 0x2, 0, 0)
#define MPP16_SDIO0_CD		MPP(16, 0x3, 0, 0)
#define MPP16_SPI_LCD_CS1	MPP(16, 0x4, 0, 0)
#define MPP16_AC97_SDATA_IN1	MPP(16, 0x5, 0, 0)

#define MPP17_GPIO17		MPP(17, 0x0, 1, 1)
#define MPP17_AC97_SYSCLK_OUT	MPP(17, 0x1, 0, 0)
#define MPP17_UA3_CTSn		MPP(17, 0x2, 0, 0)
#define MPP17_SDIO0_WP		MPP(17, 0x3, 0, 0)
#define MPP17_TW_SDA2		MPP(17, 0x4, 0, 0)
#define MPP17_AC97_SDATA_IN2	MPP(17, 0x5, 0, 0)

#define MPP18_GPIO18		MPP(18, 0x0, 1, 1)
#define MPP18_UA3_TXD		MPP(18, 0x2, 0, 0)
#define MPP18_SDIO0_BUS_POWER	MPP(18, 0x3, 0, 0)
#define MPP18_LCD0_PWM		MPP(18, 0x4, 0, 0)
#define MPP18_AC_SDATA_IN3	MPP(18, 0x5, 0, 0)

#define MPP19_GPIO19		MPP(19, 0x0, 1, 1)
#define MPP19_UA3_RXD		MPP(19, 0x2, 0, 0)
#define MPP19_SDIO0_LED_CTRL	MPP(19, 0x3, 0, 0)
#define MPP19_TW_SCK2		MPP(19, 0x4, 0, 0)

#define MPP20_GPIO20		MPP(20, 0x0, 1, 1)
#define MPP20_AC97_SYSCLK_OUT	MPP(20, 0x1, 0, 0)
#define MPP20_SPI_LCD_MISO	MPP(20, 0x2, 0, 0)
#define MPP20_SDIO1_CD		MPP(20, 0x3, 0, 0)
#define MPP20_SDIO0_CD		MPP(20, 0x5, 0, 0)
#define MPP20_SPI_1_MISO	MPP(20, 0x6, 0, 0)

#define MPP21_GPIO21		MPP(21, 0x0, 1, 1)
#define MPP21_UA1_RTSn		MPP(21, 0x1, 0, 0)
#define MPP21_SPI_LCD_CS0	MPP(21, 0x2, 0, 0)
#define MPP21_SDIO1_WP		MPP(21, 0x3, 0, 0)
#define MPP21_SSP_SFRM		MPP(21, 0x4, 0, 0)
#define MPP21_SDIO0_WP		MPP(21, 0x5, 0, 0)
#define MPP21_SPI_1_CS		MPP(21, 0x6, 0, 0)

#define MPP22_GPIO22		MPP(22, 0x0, 1, 1)
#define MPP22_UA1_CTSn		MPP(22, 0x1, 0, 0)
#define MPP22_SPI_LCD_MOSI	MPP(22, 0x2, 0, 0)
#define MPP22_SDIO1_BUS_POWER	MPP(22, 0x3, 0, 0)
#define MPP22_SSP_TXD		MPP(22, 0x4, 0, 0)
#define MPP22_SDIO0_BUS_POWER	MPP(22, 0x5, 0, 0)
#define MPP22_SPI_1_MOSI	MPP(22, 0x6, 0, 0)

#define MPP23_GPIO23		MPP(23, 0x0, 1, 1)
#define MPP23_SPI_LCD_SCK	MPP(23, 0x2, 0, 0)
#define MPP23_SDIO1_LED_CTRL	MPP(23, 0x3, 0, 0)
#define MPP23_SSP_SCLK		MPP(23, 0x4, 0, 0)
#define MPP23_SDIO0_LED_CTRL	MPP(23, 0x5, 0, 0)
#define MPP23_SPI_1_SCK		MPP(23, 0x6, 0, 0)

#define MPP_MAX			23

#define MPP_GRP(_grp, _mode)	MPP((_grp), (_mode), 0, 0)

/* for MPP groups _num is a group index */
enum dove_mpp_grp_idx {
	MPP_24_39 = 2,
	MPP_40_45 = 0,
	MPP_46_51 = 1,
	MPP_58_61 = 5,
	MPP_62_63 = 4,
	MPP_GRP_MAX = 5,
};

#define MPP_GRP_24_39_GPIO		MPP_GRP(MPP_24_39, 0x1)
#define MPP_GRP_24_39_CAM		MPP_GRP(MPP_24_39, 0x0)

#define MPP_GRP_40_45_GPIO		MPP_GRP(MPP_40_45, 0x1)
#define MPP_GRP_40_45_SD0		MPP_GRP(MPP_40_45, 0x0)

#define MPP_GRP_46_51_GPIO		MPP_GRP(MPP_46_51, 0x1)
#define MPP_GRP_46_51_SD1		MPP_GRP(MPP_46_51, 0x0)

#define MPP_GRP_58_61_GPIO		MPP_GRP(MPP_58_61, 0x1)
#define MPP_GRP_58_61_SPI		MPP_GRP(MPP_58_61, 0x0)

#define MPP_GRP_62_63_GPIO		MPP_GRP(MPP_62_63, 0x1)
#define MPP_GRP_62_63_UA1		MPP_GRP(MPP_62_63, 0x0)

/* The MPP[64:71] control differs from other groups */
#define MPP_GRP_NFC_64_71_GPO		0x1
#define MPP_GRP_NFC_64_71_NFC		0x0

/*
 * The MPP[52:57] functionality is encoded by 4 bits in different
 * registers. The _num field in this case encodes those bits in
 * correspodence with Table 135 of 88AP510 Functional specification
 */
#define MPP_GRP_AU1_52_57_AU1		0x0
#define MPP_GRP_AU1_52_57_AU1_GPIO57	0x2
#define MPP_GRP_AU1_52_57_GPIO		0xa
#define MPP_GRP_AU1_52_57_TW_GPIO	0xb
#define MPP_GRP_AU1_52_57_AU1_SSP	0xc
#define MPP_GRP_AU1_52_57_SSP_GPIO	0xe
#define MPP_GRP_AU1_52_57_SSP_TW	0xf

void dove_mpp_conf(unsigned int *mpp_list,
		   unsigned int *mpp_grp_list,
		   unsigned int grp_au1_52_57,
		   unsigned int grp_nfc_64_71);

#endif	/* __ARCH_DOVE_MPP_CODED_H */


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * arch/arm/mach-dove/pcie.c
 *
 * PCIe functions for Marvell Dove 88AP510 SoC
 */

#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/clk.h>
#include <video/vga.h>
#include <asm/mach/pci.h>
#include <asm/mach/arch.h>
#include <asm/setup.h>
#include <asm/delay.h>
#include <plat/pcie.h>
#include <plat/addr-map.h>
#include "irqs.h"
#include "bridge-regs.h"
#include "common.h"

struct pcie_port {
	u8			index;
	u8			root_bus_nr;
	void __iomem		*base;
	spinlock_t		conf_lock;
	char			mem_space_name[16];
	struct resource		res;
};

static struct pcie_port pcie_port[2];
static int num_pcie_ports;

static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
{
	struct pcie_port *pp;
	struct resource realio;

	if (nr >= num_pcie_ports)
		return 0;

	pp = &pcie_port[nr];
	sys->private_data = pp;
	pp->root_bus_nr = sys->busnr;

	/*
	 * Generic PCIe unit setup.
	 */
	orion_pcie_set_local_bus_nr(pp->base, sys->busnr);

	orion_pcie_setup(pp->base);

	realio.start = sys->busnr * SZ_64K;
	realio.end = realio.start + SZ_64K - 1;
	pci_remap_iospace(&realio, pp->index == 0 ? DOVE_PCIE0_IO_PHYS_BASE :
						    DOVE_PCIE1_IO_PHYS_BASE);

	/*
	 * IORESOURCE_MEM
	 */
	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
		 "PCIe %d MEM", pp->index);
	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
	pp->res.name = pp->mem_space_name;
	if (pp->index == 0) {
		pp->res.start = DOVE_PCIE0_MEM_PHYS_BASE;
		pp->res.end = pp->res.start + DOVE_PCIE0_MEM_SIZE - 1;
	} else {
		pp->res.start = DOVE_PCIE1_MEM_PHYS_BASE;
		pp->res.end = pp->res.start + DOVE_PCIE1_MEM_SIZE - 1;
	}
	pp->res.flags = IORESOURCE_MEM;
	if (request_resource(&iomem_resource, &pp->res))
		panic("Request PCIe Memory resource failed\n");
	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);

	return 1;
}

static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
{
	/*
	 * Don't go out when trying to access nonexisting devices
	 * on the local bus.
	 */
	if (bus == pp->root_bus_nr && dev > 1)
		return 0;

	return 1;
}

static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
			int size, u32 *val)
{
	struct pci_sys_data *sys = bus->sysdata;
	struct pcie_port *pp = sys->private_data;
	unsigned long flags;
	int ret;

	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
		*val = 0xffffffff;
		return PCIBIOS_DEVICE_NOT_FOUND;
	}

	spin_lock_irqsave(&pp->conf_lock, flags);
	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
	spin_unlock_irqrestore(&pp->conf_lock, flags);

	return ret;
}

static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
			int where, int size, u32 val)
{
	struct pci_sys_data *sys = bus->sysdata;
	struct pcie_port *pp = sys->private_data;
	unsigned long flags;
	int ret;

	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
		return PCIBIOS_DEVICE_NOT_FOUND;

	spin_lock_irqsave(&pp->conf_lock, flags);
	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
	spin_unlock_irqrestore(&pp->conf_lock, flags);

	return ret;
}

static struct pci_ops pcie_ops = {
	.read = pcie_rd_conf,
	.write = pcie_wr_conf,
};

/*
 * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
 * is operating as a root complex this needs to be switched to
 * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
 * the device. Decoding setup is handled by the orion code.
 */
static void rc_pci_fixup(struct pci_dev *dev)
{
	if (dev->bus->parent == NULL && dev->devfn == 0) {
		int i;

		dev->class &= 0xff;
		dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
			dev->resource[i].start = 0;
			dev->resource[i].end   = 0;
			dev->resource[i].flags = 0;
		}
	}
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);

static int __init
dove_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
{
	struct pci_sys_data *sys = pci_host_bridge_priv(bridge);

	if (nr >= num_pcie_ports) {
		BUG();
		return -EINVAL;
	}

	list_splice_init(&sys->resources, &bridge->windows);
	bridge->dev.parent = NULL;
	bridge->sysdata = sys;
	bridge->busnr = sys->busnr;
	bridge->ops = &pcie_ops;

	return pci_scan_root_bus_bridge(bridge);
}

static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
{
	struct pci_sys_data *sys = dev->sysdata;
	struct pcie_port *pp = sys->private_data;

	return pp->index ? IRQ_DOVE_PCIE1 : IRQ_DOVE_PCIE0;
}

static struct hw_pci dove_pci __initdata = {
	.nr_controllers	= 2,
	.setup		= dove_pcie_setup,
	.scan		= dove_pcie_scan_bus,
	.map_irq	= dove_pcie_map_irq,
};

static void __init add_pcie_port(int index, void __iomem *base)
{
	printk(KERN_INFO "Dove PCIe port %d: ", index);

	if (orion_pcie_link_up(base)) {
		struct pcie_port *pp = &pcie_port[num_pcie_ports++];
		struct clk *clk = clk_get_sys("pcie", (index ? "1" : "0"));

		if (!IS_ERR(clk))
			clk_prepare_enable(clk);

		printk(KERN_INFO "link up\n");

		pp->index = index;
		pp->root_bus_nr = -1;
		pp->base = base;
		spin_lock_init(&pp->conf_lock);
		memset(&pp->res, 0, sizeof(pp->res));
	} else {
		printk(KERN_INFO "link down, ignoring\n");
	}
}

void __init dove_pcie_init(int init_port0, int init_port1)
{
	vga_base = DOVE_PCIE0_MEM_PHYS_BASE;

	if (init_port0)
		add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);

	if (init_port1)
		add_pcie_port(1, DOVE_PCIE1_VIRT_BASE);

	pci_common_init(&dove_pci);
}


code:
/* SPDX-License-Identifier: GPL-2.0-only */

#ifndef __ASM_ARCH_PM_H
#define __ASM_ARCH_PM_H

#include <asm/errno.h>
#include "irqs.h"

#define CLOCK_GATING_CONTROL	(DOVE_PMU_VIRT_BASE + 0x38)
#define  CLOCK_GATING_BIT_USB0		0
#define  CLOCK_GATING_BIT_USB1		1
#define  CLOCK_GATING_BIT_GBE		2
#define  CLOCK_GATING_BIT_SATA		3
#define  CLOCK_GATING_BIT_PCIE0		4
#define  CLOCK_GATING_BIT_PCIE1		5
#define  CLOCK_GATING_BIT_SDIO0		8
#define  CLOCK_GATING_BIT_SDIO1		9
#define  CLOCK_GATING_BIT_NAND		10
#define  CLOCK_GATING_BIT_CAMERA	11
#define  CLOCK_GATING_BIT_I2S0		12
#define  CLOCK_GATING_BIT_I2S1		13
#define  CLOCK_GATING_BIT_CRYPTO	15
#define  CLOCK_GATING_BIT_AC97		21
#define  CLOCK_GATING_BIT_PDMA		22
#define  CLOCK_GATING_BIT_XOR0		23
#define  CLOCK_GATING_BIT_XOR1		24
#define  CLOCK_GATING_BIT_GIGA_PHY	30
#define  CLOCK_GATING_USB0_MASK		(1 << CLOCK_GATING_BIT_USB0)
#define  CLOCK_GATING_USB1_MASK		(1 << CLOCK_GATING_BIT_USB1)
#define  CLOCK_GATING_GBE_MASK		(1 << CLOCK_GATING_BIT_GBE)
#define  CLOCK_GATING_SATA_MASK		(1 << CLOCK_GATING_BIT_SATA)
#define  CLOCK_GATING_PCIE0_MASK	(1 << CLOCK_GATING_BIT_PCIE0)
#define  CLOCK_GATING_PCIE1_MASK	(1 << CLOCK_GATING_BIT_PCIE1)
#define  CLOCK_GATING_SDIO0_MASK	(1 << CLOCK_GATING_BIT_SDIO0)
#define  CLOCK_GATING_SDIO1_MASK	(1 << CLOCK_GATING_BIT_SDIO1)
#define  CLOCK_GATING_NAND_MASK		(1 << CLOCK_GATING_BIT_NAND)
#define  CLOCK_GATING_CAMERA_MASK	(1 << CLOCK_GATING_BIT_CAMERA)
#define  CLOCK_GATING_I2S0_MASK		(1 << CLOCK_GATING_BIT_I2S0)
#define  CLOCK_GATING_I2S1_MASK		(1 << CLOCK_GATING_BIT_I2S1)
#define  CLOCK_GATING_CRYPTO_MASK	(1 << CLOCK_GATING_BIT_CRYPTO)
#define  CLOCK_GATING_AC97_MASK		(1 << CLOCK_GATING_BIT_AC97)
#define  CLOCK_GATING_PDMA_MASK		(1 << CLOCK_GATING_BIT_PDMA)
#define  CLOCK_GATING_XOR0_MASK		(1 << CLOCK_GATING_BIT_XOR0)
#define  CLOCK_GATING_XOR1_MASK		(1 << CLOCK_GATING_BIT_XOR1)
#define  CLOCK_GATING_GIGA_PHY_MASK	(1 << CLOCK_GATING_BIT_GIGA_PHY)

#define PMU_INTERRUPT_CAUSE	(DOVE_PMU_VIRT_BASE + 0x50)

#define  PMU_SW_RST_VIDEO_MASK		BIT(16)
#define  PMU_SW_RST_GPU_MASK		BIT(18)

#define  PMU_PWR_GPU_PWR_DWN_MASK	BIT(2)
#define  PMU_PWR_VPU_PWR_DWN_MASK	BIT(3)

#define  PMU_ISO_VIDEO_MASK		BIT(0)
#define  PMU_ISO_GPU_MASK		BIT(1)

#endif


code:
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_EP93XX
	bool "EP93xx-based"
	depends on ATAGS
	depends on ARCH_MULTI_V4T
	depends on CPU_LITTLE_ENDIAN
	select ARCH_SPARSEMEM_ENABLE
	select ARM_AMBA
	select ARM_VIC
	select CLKSRC_MMIO
	select CPU_ARM920T
	select GPIOLIB
	help
	  This enables support for the Cirrus EP93xx series of CPUs.

if ARCH_EP93XX

menu "Cirrus EP93xx Implementation Options"

config EP93XX_SOC_COMMON
	bool
	default y
	select SOC_BUS
	select LEDS_GPIO_REGISTER

comment "EP93xx Platforms"

config MACH_ADSSPHERE
	bool "Support ADS Sphere"
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the ADS
	  Sphere board.

config MACH_BK3
	bool "Support Liebherr BK3.1"
	select MACH_TS72XX
	help
	  Say 'Y' here if you want your kernel to support the
	  Liebherr controller BK3.1.

config MACH_EDB93XX
	bool

config MACH_EDB9301
	bool "Support Cirrus Logic EDB9301"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9301 Evaluation Board.

config MACH_EDB9302
	bool "Support Cirrus Logic EDB9302"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9302 Evaluation Board.

config MACH_EDB9302A
	bool "Support Cirrus Logic EDB9302A"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9302A Evaluation Board.

config MACH_EDB9307
	bool "Support Cirrus Logic EDB9307"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9307 Evaluation Board.

config MACH_EDB9307A
	bool "Support Cirrus Logic EDB9307A"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9307A Evaluation Board.

config MACH_EDB9312
	bool "Support Cirrus Logic EDB9312"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9312 Evaluation Board.

config MACH_EDB9315
	bool "Support Cirrus Logic EDB9315"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9315 Evaluation Board.

config MACH_EDB9315A
	bool "Support Cirrus Logic EDB9315A"
	select MACH_EDB93XX
	help
	  Say 'Y' here if you want your kernel to support the Cirrus
	  Logic EDB9315A Evaluation Board.

config MACH_GESBC9312
	bool "Support Glomation GESBC-9312-sx"
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the Glomation
	  GESBC-9312-sx board.

config MACH_MICRO9
	bool

config MACH_MICRO9H
	bool "Support Contec Micro9-High"
	select MACH_MICRO9
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the
	  Contec Micro9-High board.

config MACH_MICRO9M
	bool "Support Contec Micro9-Mid"
	select MACH_MICRO9
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the
	  Contec Micro9-Mid board.

config MACH_MICRO9L
	bool "Support Contec Micro9-Lite"
	select MACH_MICRO9
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the
	  Contec Micro9-Lite board.

config MACH_MICRO9S
	bool "Support Contec Micro9-Slim"
	select MACH_MICRO9
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the
	  Contec Micro9-Slim board.

config MACH_SIM_ONE
        bool "Support Simplemachines Sim.One board"
	depends on UNUSED_BOARD_FILES
        help
          Say 'Y' here if you want your kernel to support the
          Simplemachines Sim.One board.

config MACH_SNAPPER_CL15
	bool "Support Bluewater Systems Snapper CL15 Module"
	depends on UNUSED_BOARD_FILES
	help
	  Say 'Y' here if you want your kernel to support the Bluewater
	  Systems Snapper CL15 Module.

config MACH_TS72XX
	bool "Support Technologic Systems TS-72xx SBC"
	help
	  Say 'Y' here if you want your kernel to support the
	  Technologic Systems TS-72xx board.

config MACH_VISION_EP9307
	bool "Support Vision Engraving Systems EP9307 SoM"
	help
	  Say 'Y' here if you want your kernel to support the
	  Vision Engraving Systems EP9307 SoM.

endmenu

endif


code:
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the linux kernel.
#
obj-y			:= core.o clock.o timer-ep93xx.o

obj-$(CONFIG_EP93XX_DMA)	+= dma.o

obj-$(CONFIG_MACH_ADSSPHERE)	+= adssphere.o
obj-$(CONFIG_MACH_EDB93XX)	+= edb93xx.o
obj-$(CONFIG_MACH_GESBC9312)	+= gesbc9312.o
obj-$(CONFIG_MACH_MICRO9)	+= micro9.o
obj-$(CONFIG_MACH_SIM_ONE)	+= simone.o
obj-$(CONFIG_MACH_SNAPPER_CL15)	+= snappercl15.o
obj-$(CONFIG_MACH_TS72XX)	+= ts72xx.o
obj-$(CONFIG_MACH_VISION_EP9307)+= vision_ep9307.o


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * arch/arm/mach-ep93xx/adssphere.c
 * ADS Sphere support.
 *
 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>

#include "hardware.h"

#include <asm/mach-types.h>
#include <asm/mach/arch.h>

#include "soc.h"

static struct ep93xx_eth_data __initdata adssphere_eth_data = {
	.phy_id		= 1,
};

static void __init adssphere_init_machine(void)
{
	ep93xx_init_devices();
	ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
	ep93xx_register_eth(&adssphere_eth_data, 1);
}

MACHINE_START(ADSSPHERE, "ADS Sphere board")
	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= adssphere_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * arch/arm/mach-ep93xx/clock.c
 * Clock control for Cirrus EP93xx chips.
 *
 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 */

#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/soc/cirrus/ep93xx.h>

#include "hardware.h"

#include <asm/div64.h>

#include "soc.h"

static DEFINE_SPINLOCK(clk_lock);

static char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
static char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
static char pclk_divisors[] = { 1, 2, 4, 8 };

static char adc_divisors[] = { 16, 4 };
static char sclk_divisors[] = { 2, 4 };
static char lrclk_divisors[] = { 32, 64, 128 };

static const char * const mux_parents[] = {
	"xtali",
	"pll1",
	"pll2"
};

/*
 * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
 */
static unsigned long calc_pll_rate(unsigned long long rate, u32 config_word)
{
	int i;

	rate *= ((config_word >> 11) & 0x1f) + 1;		/* X1FBD */
	rate *= ((config_word >> 5) & 0x3f) + 1;		/* X2FBD */
	do_div(rate, (config_word & 0x1f) + 1);			/* X2IPD */
	for (i = 0; i < ((config_word >> 16) & 3); i++)		/* PS */
		rate >>= 1;

	return (unsigned long)rate;
}

struct clk_psc {
	struct clk_hw hw;
	void __iomem *reg;
	u8 bit_idx;
	u32 mask;
	u8 shift;
	u8 width;
	char *div;
	u8 num_div;
	spinlock_t *lock;
};

#define to_clk_psc(_hw) container_of(_hw, struct clk_psc, hw)

static int ep93xx_clk_is_enabled(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	u32 val = readl(psc->reg);

	return (val & BIT(psc->bit_idx)) ? 1 : 0;
}

static int ep93xx_clk_enable(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	unsigned long flags = 0;
	u32 val;

	if (psc->lock)
		spin_lock_irqsave(psc->lock, flags);

	val = __raw_readl(psc->reg);
	val |= BIT(psc->bit_idx);

	ep93xx_syscon_swlocked_write(val, psc->reg);

	if (psc->lock)
		spin_unlock_irqrestore(psc->lock, flags);

	return 0;
}

static void ep93xx_clk_disable(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	unsigned long flags = 0;
	u32 val;

	if (psc->lock)
		spin_lock_irqsave(psc->lock, flags);

	val = __raw_readl(psc->reg);
	val &= ~BIT(psc->bit_idx);

	ep93xx_syscon_swlocked_write(val, psc->reg);

	if (psc->lock)
		spin_unlock_irqrestore(psc->lock, flags);
}

static const struct clk_ops clk_ep93xx_gate_ops = {
	.enable = ep93xx_clk_enable,
	.disable = ep93xx_clk_disable,
	.is_enabled = ep93xx_clk_is_enabled,
};

static struct clk_hw *ep93xx_clk_register_gate(const char *name,
				    const char *parent_name,
				    void __iomem *reg,
				    u8 bit_idx)
{
	struct clk_init_data init;
	struct clk_psc *psc;
	struct clk *clk;

	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
	if (!psc)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.ops = &clk_ep93xx_gate_ops;
	init.flags = CLK_SET_RATE_PARENT;
	init.parent_names = (parent_name ? &parent_name : NULL);
	init.num_parents = (parent_name ? 1 : 0);

	psc->reg = reg;
	psc->bit_idx = bit_idx;
	psc->hw.init = &init;
	psc->lock = &clk_lock;

	clk = clk_register(NULL, &psc->hw);
	if (IS_ERR(clk)) {
		kfree(psc);
		return ERR_CAST(clk);
	}

	return &psc->hw;
}

static u8 ep93xx_mux_get_parent(struct clk_hw *hw)
{
	struct clk_psc *psc = to_clk_psc(hw);
	u32 val = __raw_readl(psc->reg);

	if (!(val & EP93XX_SYSCON_CLKDIV_ESEL))
		return 0;

	if (!(val & EP93XX_SYSCON_CLKDIV_PSEL))
		return 1;

	return 2;
}

static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index)
{
	struct clk_psc *psc = to_clk_psc(hw);
	unsigned long flags = 0;
	u32 val;

	if (index >= ARRAY_SIZE(mux_parents))
		return -EINVAL;

	if (psc->lock)
		spin_lock_irqsave(psc->lock, flags);

	val = __raw_readl(psc->reg);
	val &= ~(EP93XX_SYSCON_CLKDIV_ESEL | EP93XX_SYSCON_CLKDIV_PSEL);

	if (index != 0) {
		val |= EP93XX_SYSCON_CLKDIV_ESEL;
		val |= (index - 1) ? EP93XX_SYSCON_CLKDIV_PSEL : 0;
	}

	ep93xx_syscon_swlocked_write(val, psc->reg);

	if (psc->lock)
		spin_unlock_irqrestore(psc->lock, flags);

	return 0;
}

static bool is_best(unsigned long rate, unsigned long now,
		     unsigned long best)
{
	return abs(rate - now) < abs(rate - best);
}

static int ep93xx_mux_determine_rate(struct clk_hw *hw,
				struct clk_rate_request *req)
{
	unsigned long rate = req->rate;
	struct clk *best_parent = NULL;
	unsigned long __parent_rate;
	unsigned long best_rate = 0, actual_rate, mclk_rate;
	unsigned long best_parent_rate;
	int __div = 0, __pdiv = 0;
	int i;

	/*
	 * Try the two pll's and the external clock
	 * Because the valid predividers are 2, 2.5 and 3, we multiply
	 * all the clocks by 2 to avoid floating point math.
	 *
	 * This is based on the algorithm in the ep93xx raster guide:
	 * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
	 *
	 */
	for (i = 0; i < ARRAY_SIZE(mux_parents); i++) {
		struct clk *parent = clk_get_sys(mux_parents[i], NULL);

		__parent_rate = clk_get_rate(parent);
		mclk_rate = __parent_rate * 2;

		/* Try each predivider value */
		for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
			__div = mclk_rate / (rate * __pdiv);
			if (__div < 2 || __div > 127)
				continue;

			actual_rate = mclk_rate / (__pdiv * __div);
			if (is_best(rate, actual_rate, best_rate)) {
				best_rate = actual_rate;
				best_parent_rate = __parent_rate;
				best_parent = parent;
			}
		}
	}

	if (!best_parent)
		return -EINVAL;

	req->best_parent_rate = best_parent_rate;
	req->best_parent_hw = __clk_get_hw(best_parent);
	req->rate = best_rate;

	return 0;
}

static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw,
						unsigned long parent_rate)
{
	struct clk_psc *psc = to_clk_psc(hw);
	unsigned long rate = 0;
	u32 val = __raw_readl(psc->reg);
	int __pdiv = ((val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & 0x03);
	int __div = val & 0x7f;

	if (__div > 0)
		rate = (parent_rate * 2) / ((__pdiv + 3) * __div);

	return rate;
}

static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
				unsigned long parent_rate)
{
	struct clk_psc *psc = to_clk_psc(hw);
	int pdiv = 0, div = 0;
	unsigned long best_rate = 0, actual_rate, mclk_rate;
	int __div = 0, __pdiv = 0;
	u32 val;

	mclk_rate = parent_rate * 2;

	for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
		__div = mclk_rate / (rate * __pdiv);
		if (__div < 2 || __div > 127)
			continue;

		actual_rate = mclk_rate / (__pdiv * __div);
		if (is_best(rate, actual_rate, best_rate)) {
			pdiv = __pdiv - 3;
			div = __div;
			best_rate = actual_rate;
		}
	}

	if (!best_rate)
		return -EINVAL;

	val = __raw_readl(psc->reg);

	/* Clear old dividers */
	val &= ~0x37f;

	/* Set the new pdiv and div bits for the new clock rate */
	val |= (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
	ep93xx_syscon_swlocked_write(val, psc->reg);

	return 0;
}

static const struct clk_ops clk_ddiv_ops = {
	.enable = ep93xx_clk_enable,
	.disable = ep93xx_clk_disable,
	.is_enabled = ep93xx_clk_is_enabled,
	.get_parent = ep93xx_mux_get_parent,
	.set_parent = ep93xx_mux_set_parent_lock,
	.determine_rate = ep93xx_mux_determine_rate,
	.recalc_rate = ep93xx_ddiv_recalc_rate,
	.set_rate = ep93xx_ddiv_set_rate,
};

static struct clk_hw *clk_hw_register_ddiv(const char *name,
					  void __iomem *reg,
					  u8 bit_idx)
{
	struct clk_init_data init;
	struct clk_psc *psc;
	struct clk *clk;

	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
	if (!psc)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.ops = &clk_ddiv_ops;
	init.flags = 0;
	init.parent_names = mux_parents;
	init.num_parents = ARRAY_SIZE(mux_parents);

	psc->reg = reg;
	psc->bit_idx = bit_idx;
	psc->lock = &clk_lock;
	psc->hw.init = &init;

	clk = clk_register(NULL, &psc->hw);
	if (IS_ERR(clk)) {
		kfree(psc);
		return ERR_CAST(clk);
	}
	return &psc->hw;
}

static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
					    unsigned long parent_rate)
{
	struct clk_psc *psc = to_clk_psc(hw);
	u32 val = __raw_readl(psc->reg);
	u8 index = (val & psc->mask) >> psc->shift;

	if (index > psc->num_div)
		return 0;

	return DIV_ROUND_UP_ULL(parent_rate, psc->div[index]);
}

static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
				   unsigned long *parent_rate)
{
	struct clk_psc *psc = to_clk_psc(hw);
	unsigned long best = 0, now, maxdiv;
	int i;

	maxdiv = psc->div[psc->num_div - 1];

	for (i = 0; i < psc->num_div; i++) {
		if ((rate * psc->div[i]) == *parent_rate)
			return DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]);

		now = DIV_ROUND_UP_ULL((u64)*parent_rate, psc->div[i]);

		if (is_best(rate, now, best))
			best = now;
	}

	if (!best)
		best = DIV_ROUND_UP_ULL(*parent_rate, maxdiv);

	return best;
}

static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
			       unsigned long parent_rate)
{
	struct clk_psc *psc = to_clk_psc(hw);
	u32 val = __raw_readl(psc->reg) & ~psc->mask;
	int i;

	for (i = 0; i < psc->num_div; i++)
		if (rate == parent_rate / psc->div[i]) {
			val |= i << psc->shift;
			break;
		}

	if (i == psc->num_div)
		return -EINVAL;

	ep93xx_syscon_swlocked_write(val, psc->reg);

	return 0;
}

static const struct clk_ops ep93xx_div_ops = {
	.enable = ep93xx_clk_enable,
	.disable = ep93xx_clk_disable,
	.is_enabled = ep93xx_clk_is_enabled,
	.recalc_rate = ep93xx_div_recalc_rate,
	.round_rate = ep93xx_div_round_rate,
	.set_rate = ep93xx_div_set_rate,
};

static struct clk_hw *clk_hw_register_div(const char *name,
					  const char *parent_name,
					  void __iomem *reg,
					  u8 enable_bit,
					  u8 shift,
					  u8 width,
					  char *clk_divisors,
					  u8 num_div)
{
	struct clk_init_data init;
	struct clk_psc *psc;
	struct clk *clk;

	psc = kzalloc(sizeof(*psc), GFP_KERNEL);
	if (!psc)
		return ERR_PTR(-ENOMEM);

	init.name = name;
	init.ops = &ep93xx_div_ops;
	init.flags = 0;
	init.parent_names = (parent_name ? &parent_name : NULL);
	init.num_parents = 1;

	psc->reg = reg;
	psc->bit_idx = enable_bit;
	psc->mask = GENMASK(shift + width - 1, shift);
	psc->shift = shift;
	psc->div = clk_divisors;
	psc->num_div = num_div;
	psc->lock = &clk_lock;
	psc->hw.init = &init;

	clk = clk_register(NULL, &psc->hw);
	if (IS_ERR(clk)) {
		kfree(psc);
		return ERR_CAST(clk);
	}
	return &psc->hw;
}

struct ep93xx_gate {
	unsigned int bit;
	const char *dev_id;
	const char *con_id;
};

static struct ep93xx_gate ep93xx_uarts[] = {
	{EP93XX_SYSCON_DEVCFG_U1EN, "apb:uart1", NULL},
	{EP93XX_SYSCON_DEVCFG_U2EN, "apb:uart2", NULL},
	{EP93XX_SYSCON_DEVCFG_U3EN, "apb:uart3", NULL},
};

static void __init ep93xx_uart_clock_init(void)
{
	unsigned int i;
	struct clk_hw *hw;
	u32 value;
	unsigned int clk_uart_div;

	value = __raw_readl(EP93XX_SYSCON_PWRCNT);
	if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD)
		clk_uart_div = 1;
	else
		clk_uart_div = 2;

	hw = clk_hw_register_fixed_factor(NULL, "uart", "xtali", 0, 1, clk_uart_div);

	/* parenting uart gate clocks to uart clock */
	for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) {
		hw = ep93xx_clk_register_gate(ep93xx_uarts[i].dev_id,
					"uart",
					EP93XX_SYSCON_DEVCFG,
					ep93xx_uarts[i].bit);

		clk_hw_register_clkdev(hw, NULL, ep93xx_uarts[i].dev_id);
	}
}

static struct ep93xx_gate ep93xx_dmas[] = {
	{EP93XX_SYSCON_PWRCNT_DMA_M2P0, NULL, "m2p0"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P1, NULL, "m2p1"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P2, NULL, "m2p2"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P3, NULL, "m2p3"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P4, NULL, "m2p4"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P5, NULL, "m2p5"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P6, NULL, "m2p6"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P7, NULL, "m2p7"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P8, NULL, "m2p8"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2P9, NULL, "m2p9"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2M0, NULL, "m2m0"},
	{EP93XX_SYSCON_PWRCNT_DMA_M2M1, NULL, "m2m1"},
};

static void __init ep93xx_dma_clock_init(void)
{
	unsigned int i;
	struct clk_hw *hw;
	int ret;

	for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) {
		hw = clk_hw_register_gate(NULL, ep93xx_dmas[i].con_id,
					"hclk", 0,
					EP93XX_SYSCON_PWRCNT,
					ep93xx_dmas[i].bit,
					0,
					&clk_lock);

		ret = clk_hw_register_clkdev(hw, ep93xx_dmas[i].con_id, NULL);
		if (ret)
			pr_err("%s: failed to register lookup %s\n",
			       __func__, ep93xx_dmas[i].con_id);
	}
}

static int __init ep93xx_clock_init(void)
{
	u32 value;
	struct clk_hw *hw;
	unsigned long clk_pll1_rate;
	unsigned long clk_f_rate;
	unsigned long clk_h_rate;
	unsigned long clk_p_rate;
	unsigned long clk_pll2_rate;
	unsigned int clk_f_div;
	unsigned int clk_h_div;
	unsigned int clk_p_div;
	unsigned int clk_usb_div;
	unsigned long clk_spi_div;

	hw = clk_hw_register_fixed_rate(NULL, "xtali", NULL, 0, EP93XX_EXT_CLK_RATE);
	clk_hw_register_clkdev(hw, NULL, "xtali");

	/* Determine the bootloader configured pll1 rate */
	value = __raw_readl(EP93XX_SYSCON_CLKSET1);
	if (!(value & EP93XX_SYSCON_CLKSET1_NBYP1))
		clk_pll1_rate = EP93XX_EXT_CLK_RATE;
	else
		clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);

	hw = clk_hw_register_fixed_rate(NULL, "pll1", "xtali", 0, clk_pll1_rate);
	clk_hw_register_clkdev(hw, NULL, "pll1");

	/* Initialize the pll1 derived clocks */
	clk_f_div = fclk_divisors[(value >> 25) & 0x7];
	clk_h_div = hclk_divisors[(value >> 20) & 0x7];
	clk_p_div = pclk_divisors[(value >> 18) & 0x3];

	hw = clk_hw_register_fixed_factor(NULL, "fclk", "pll1", 0, 1, clk_f_div);
	clk_f_rate = clk_get_rate(hw->clk);
	hw = clk_hw_register_fixed_factor(NULL, "hclk", "pll1", 0, 1, clk_h_div);
	clk_h_rate = clk_get_rate(hw->clk);
	hw = clk_hw_register_fixed_factor(NULL, "pclk", "hclk", 0, 1, clk_p_div);
	clk_p_rate = clk_get_rate(hw->clk);

	clk_hw_register_clkdev(hw, "apb_pclk", NULL);

	ep93xx_dma_clock_init();

	/* Determine the bootloader configured pll2 rate */
	value = __raw_readl(EP93XX_SYSCON_CLKSET2);
	if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
		clk_pll2_rate = EP93XX_EXT_CLK_RATE;
	else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
		clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
	else
		clk_pll2_rate = 0;

	hw = clk_hw_register_fixed_rate(NULL, "pll2", "xtali", 0, clk_pll2_rate);
	clk_hw_register_clkdev(hw, NULL, "pll2");

	/* Initialize the pll2 derived clocks */
	/*
	 * These four bits set the divide ratio between the PLL2
	 * output and the USB clock.
	 * 0000 - Divide by 1
	 * 0001 - Divide by 2
	 * 0010 - Divide by 3
	 * 0011 - Divide by 4
	 * 0100 - Divide by 5
	 * 0101 - Divide by 6
	 * 0110 - Divide by 7
	 * 0111 - Divide by 8
	 * 1000 - Divide by 9
	 * 1001 - Divide by 10
	 * 1010 - Divide by 11
	 * 1011 - Divide by 12
	 * 1100 - Divide by 13
	 * 1101 - Divide by 14
	 * 1110 - Divide by 15
	 * 1111 - Divide by 1
	 * On power-on-reset these bits are reset to 0000b.
	 */
	clk_usb_div = (((value >> 28) & 0xf) + 1);
	hw = clk_hw_register_fixed_factor(NULL, "usb_clk", "pll2", 0, 1, clk_usb_div);
	hw = clk_hw_register_gate(NULL, "ohci-platform",
				"usb_clk", 0,
				EP93XX_SYSCON_PWRCNT,
				EP93XX_SYSCON_PWRCNT_USH_EN,
				0,
				&clk_lock);
	clk_hw_register_clkdev(hw, NULL, "ohci-platform");

	/*
	 * EP93xx SSP clock rate was doubled in version E2. For more information
	 * see:
	 *     http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
	 */
	clk_spi_div = 1;
	if (ep93xx_chip_revision() < EP93XX_CHIP_REV_E2)
		clk_spi_div = 2;
	hw = clk_hw_register_fixed_factor(NULL, "ep93xx-spi.0", "xtali", 0, 1, clk_spi_div);
	clk_hw_register_clkdev(hw, NULL, "ep93xx-spi.0");

	/* pwm clock */
	hw = clk_hw_register_fixed_factor(NULL, "pwm_clk", "xtali", 0, 1, 1);
	clk_hw_register_clkdev(hw, "pwm_clk", NULL);

	pr_info("PLL1 running at %ld MHz, PLL2 at %ld MHz\n",
		clk_pll1_rate / 1000000, clk_pll2_rate / 1000000);
	pr_info("FCLK %ld MHz, HCLK %ld MHz, PCLK %ld MHz\n",
		clk_f_rate / 1000000, clk_h_rate / 1000000,
		clk_p_rate / 1000000);

	ep93xx_uart_clock_init();

	/* touchscreen/adc clock */
	hw = clk_hw_register_div("ep93xx-adc",
				"xtali",
				EP93XX_SYSCON_KEYTCHCLKDIV,
				EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
				EP93XX_SYSCON_KEYTCHCLKDIV_ADIV,
				1,
				adc_divisors,
				ARRAY_SIZE(adc_divisors));

	clk_hw_register_clkdev(hw, NULL, "ep93xx-adc");

	/* keypad clock */
	hw = clk_hw_register_div("ep93xx-keypad",
				"xtali",
				EP93XX_SYSCON_KEYTCHCLKDIV,
				EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
				EP93XX_SYSCON_KEYTCHCLKDIV_KDIV,
				1,
				adc_divisors,
				ARRAY_SIZE(adc_divisors));

	clk_hw_register_clkdev(hw, NULL, "ep93xx-keypad");

	/* On reset PDIV and VDIV is set to zero, while PDIV zero
	 * means clock disable, VDIV shouldn't be zero.
	 * So i set both dividers to minimum.
	 */
	/* ENA - Enable CLK divider. */
	/* PDIV - 00 - Disable clock */
	/* VDIV - at least 2 */
	/* Check and enable video clk registers */
	value = __raw_readl(EP93XX_SYSCON_VIDCLKDIV);
	value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
	ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_VIDCLKDIV);

	/* check and enable i2s clk registers */
	value = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
	value |= (1 << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
	ep93xx_syscon_swlocked_write(value, EP93XX_SYSCON_I2SCLKDIV);

	/* video clk */
	hw = clk_hw_register_ddiv("ep93xx-fb",
				EP93XX_SYSCON_VIDCLKDIV,
				EP93XX_SYSCON_CLKDIV_ENABLE);

	clk_hw_register_clkdev(hw, NULL, "ep93xx-fb");

	/* i2s clk */
	hw = clk_hw_register_ddiv("mclk",
				EP93XX_SYSCON_I2SCLKDIV,
				EP93XX_SYSCON_CLKDIV_ENABLE);

	clk_hw_register_clkdev(hw, "mclk", "ep93xx-i2s");

	/* i2s sclk */
#define EP93XX_I2SCLKDIV_SDIV_SHIFT	16
#define EP93XX_I2SCLKDIV_SDIV_WIDTH	1
	hw = clk_hw_register_div("sclk",
				"mclk",
				EP93XX_SYSCON_I2SCLKDIV,
				EP93XX_SYSCON_I2SCLKDIV_SENA,
				EP93XX_I2SCLKDIV_SDIV_SHIFT,
				EP93XX_I2SCLKDIV_SDIV_WIDTH,
				sclk_divisors,
				ARRAY_SIZE(sclk_divisors));

	clk_hw_register_clkdev(hw, "sclk", "ep93xx-i2s");

	/* i2s lrclk */
#define EP93XX_I2SCLKDIV_LRDIV32_SHIFT	17
#define EP93XX_I2SCLKDIV_LRDIV32_WIDTH	3
	hw = clk_hw_register_div("lrclk",
				"sclk",
				EP93XX_SYSCON_I2SCLKDIV,
				EP93XX_SYSCON_I2SCLKDIV_SENA,
				EP93XX_I2SCLKDIV_LRDIV32_SHIFT,
				EP93XX_I2SCLKDIV_LRDIV32_WIDTH,
				lrclk_divisors,
				ARRAY_SIZE(lrclk_divisors));

	clk_hw_register_clkdev(hw, "lrclk", "ep93xx-i2s");

	return 0;
}
postcore_initcall(ep93xx_clock_init);


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * arch/arm/mach-ep93xx/core.c
 * Core routines for Cirrus EP93xx chips.
 *
 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
 *
 * Thanks go to Michael Burian and Ray Lehtiniemi for their key
 * role in the ep93xx linux community.
 */

#define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/sys_soc.h>
#include <linux/irq.h>
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/leds.h>
#include <linux/uaccess.h>
#include <linux/termios.h>
#include <linux/amba/bus.h>
#include <linux/amba/serial.h>
#include <linux/mtd/physmap.h>
#include <linux/i2c.h>
#include <linux/gpio/machine.h>
#include <linux/spi/spi.h>
#include <linux/export.h>
#include <linux/irqchip/arm-vic.h>
#include <linux/reboot.h>
#include <linux/usb/ohci_pdriver.h>
#include <linux/random.h>

#include "hardware.h"
#include <linux/platform_data/video-ep93xx.h>
#include <linux/platform_data/keypad-ep93xx.h>
#include <linux/platform_data/spi-ep93xx.h>
#include <linux/soc/cirrus/ep93xx.h>

#include "gpio-ep93xx.h"

#include <asm/mach/arch.h>
#include <asm/mach/map.h>

#include "soc.h"
#include "irqs.h"

/*************************************************************************
 * Static I/O mappings that are needed for all EP93xx platforms
 *************************************************************************/
static struct map_desc ep93xx_io_desc[] __initdata = {
	{
		.virtual	= EP93XX_AHB_VIRT_BASE,
		.pfn		= __phys_to_pfn(EP93XX_AHB_PHYS_BASE),
		.length		= EP93XX_AHB_SIZE,
		.type		= MT_DEVICE,
	}, {
		.virtual	= EP93XX_APB_VIRT_BASE,
		.pfn		= __phys_to_pfn(EP93XX_APB_PHYS_BASE),
		.length		= EP93XX_APB_SIZE,
		.type		= MT_DEVICE,
	},
};

void __init ep93xx_map_io(void)
{
	iotable_init(ep93xx_io_desc, ARRAY_SIZE(ep93xx_io_desc));
}

/*************************************************************************
 * EP93xx IRQ handling
 *************************************************************************/
void __init ep93xx_init_irq(void)
{
	vic_init(EP93XX_VIC1_BASE, IRQ_EP93XX_VIC0, EP93XX_VIC1_VALID_IRQ_MASK, 0);
	vic_init(EP93XX_VIC2_BASE, IRQ_EP93XX_VIC1, EP93XX_VIC2_VALID_IRQ_MASK, 0);
}

/*************************************************************************
 * EP93xx System Controller Software Locked register handling
 *************************************************************************/

/*
 * syscon_swlock prevents anything else from writing to the syscon
 * block while a software locked register is being written.
 */
static DEFINE_SPINLOCK(syscon_swlock);

void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg)
{
	unsigned long flags;

	spin_lock_irqsave(&syscon_swlock, flags);

	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
	__raw_writel(val, reg);

	spin_unlock_irqrestore(&syscon_swlock, flags);
}

void ep93xx_devcfg_set_clear(unsigned int set_bits, unsigned int clear_bits)
{
	unsigned long flags;
	unsigned int val;

	spin_lock_irqsave(&syscon_swlock, flags);

	val = __raw_readl(EP93XX_SYSCON_DEVCFG);
	val &= ~clear_bits;
	val |= set_bits;
	__raw_writel(0xaa, EP93XX_SYSCON_SWLOCK);
	__raw_writel(val, EP93XX_SYSCON_DEVCFG);

	spin_unlock_irqrestore(&syscon_swlock, flags);
}

/**
 * ep93xx_chip_revision() - returns the EP93xx chip revision
 *
 * See "platform.h" for more information.
 */
unsigned int ep93xx_chip_revision(void)
{
	unsigned int v;

	v = __raw_readl(EP93XX_SYSCON_SYSCFG);
	v &= EP93XX_SYSCON_SYSCFG_REV_MASK;
	v >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT;
	return v;
}
EXPORT_SYMBOL_GPL(ep93xx_chip_revision);

/*************************************************************************
 * EP93xx GPIO
 *************************************************************************/
static struct resource ep93xx_gpio_resource[] = {
	DEFINE_RES_MEM(EP93XX_GPIO_PHYS_BASE, 0xcc),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO_AB),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO0MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO1MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO2MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO3MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO4MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO5MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO6MUX),
	DEFINE_RES_IRQ(IRQ_EP93XX_GPIO7MUX),
};

static struct platform_device ep93xx_gpio_device = {
	.name		= "gpio-ep93xx",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_gpio_resource),
	.resource	= ep93xx_gpio_resource,
};

/*************************************************************************
 * EP93xx peripheral handling
 *************************************************************************/
#define EP93XX_UART_MCR_OFFSET		(0x0100)

static void ep93xx_uart_set_mctrl(struct amba_device *dev,
				  void __iomem *base, unsigned int mctrl)
{
	unsigned int mcr;

	mcr = 0;
	if (mctrl & TIOCM_RTS)
		mcr |= 2;
	if (mctrl & TIOCM_DTR)
		mcr |= 1;

	__raw_writel(mcr, base + EP93XX_UART_MCR_OFFSET);
}

static struct amba_pl010_data ep93xx_uart_data = {
	.set_mctrl	= ep93xx_uart_set_mctrl,
};

static AMBA_APB_DEVICE(uart1, "apb:uart1", 0x00041010, EP93XX_UART1_PHYS_BASE,
	{ IRQ_EP93XX_UART1 }, &ep93xx_uart_data);

static AMBA_APB_DEVICE(uart2, "apb:uart2", 0x00041010, EP93XX_UART2_PHYS_BASE,
	{ IRQ_EP93XX_UART2 }, NULL);

static AMBA_APB_DEVICE(uart3, "apb:uart3", 0x00041010, EP93XX_UART3_PHYS_BASE,
	{ IRQ_EP93XX_UART3 }, &ep93xx_uart_data);

static struct resource ep93xx_rtc_resource[] = {
	DEFINE_RES_MEM(EP93XX_RTC_PHYS_BASE, 0x10c),
};

static struct platform_device ep93xx_rtc_device = {
	.name		= "ep93xx-rtc",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_rtc_resource),
	.resource	= ep93xx_rtc_resource,
};

/*************************************************************************
 * EP93xx OHCI USB Host
 *************************************************************************/

static struct clk *ep93xx_ohci_host_clock;

static int ep93xx_ohci_power_on(struct platform_device *pdev)
{
	if (!ep93xx_ohci_host_clock) {
		ep93xx_ohci_host_clock = devm_clk_get(&pdev->dev, NULL);
		if (IS_ERR(ep93xx_ohci_host_clock))
			return PTR_ERR(ep93xx_ohci_host_clock);
	}

	return clk_prepare_enable(ep93xx_ohci_host_clock);
}

static void ep93xx_ohci_power_off(struct platform_device *pdev)
{
	clk_disable(ep93xx_ohci_host_clock);
}

static struct usb_ohci_pdata ep93xx_ohci_pdata = {
	.power_on	= ep93xx_ohci_power_on,
	.power_off	= ep93xx_ohci_power_off,
	.power_suspend	= ep93xx_ohci_power_off,
};

static struct resource ep93xx_ohci_resources[] = {
	DEFINE_RES_MEM(EP93XX_USB_PHYS_BASE, 0x1000),
	DEFINE_RES_IRQ(IRQ_EP93XX_USB),
};

static u64 ep93xx_ohci_dma_mask = DMA_BIT_MASK(32);

static struct platform_device ep93xx_ohci_device = {
	.name		= "ohci-platform",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_ohci_resources),
	.resource	= ep93xx_ohci_resources,
	.dev		= {
		.dma_mask		= &ep93xx_ohci_dma_mask,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
		.platform_data		= &ep93xx_ohci_pdata,
	},
};

/*************************************************************************
 * EP93xx physmap'ed flash
 *************************************************************************/
static struct physmap_flash_data ep93xx_flash_data;

static struct resource ep93xx_flash_resource = {
	.flags		= IORESOURCE_MEM,
};

static struct platform_device ep93xx_flash = {
	.name		= "physmap-flash",
	.id		= 0,
	.dev		= {
		.platform_data	= &ep93xx_flash_data,
	},
	.num_resources	= 1,
	.resource	= &ep93xx_flash_resource,
};

/**
 * ep93xx_register_flash() - Register the external flash device.
 * @width:	bank width in octets
 * @start:	resource start address
 * @size:	resource size
 */
void __init ep93xx_register_flash(unsigned int width,
				  resource_size_t start, resource_size_t size)
{
	ep93xx_flash_data.width		= width;

	ep93xx_flash_resource.start	= start;
	ep93xx_flash_resource.end	= start + size - 1;

	platform_device_register(&ep93xx_flash);
}

/*************************************************************************
 * EP93xx ethernet peripheral handling
 *************************************************************************/
static struct ep93xx_eth_data ep93xx_eth_data;

static struct resource ep93xx_eth_resource[] = {
	DEFINE_RES_MEM(EP93XX_ETHERNET_PHYS_BASE, 0x10000),
	DEFINE_RES_IRQ(IRQ_EP93XX_ETHERNET),
};

static u64 ep93xx_eth_dma_mask = DMA_BIT_MASK(32);

static struct platform_device ep93xx_eth_device = {
	.name		= "ep93xx-eth",
	.id		= -1,
	.dev		= {
		.platform_data		= &ep93xx_eth_data,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
		.dma_mask		= &ep93xx_eth_dma_mask,
	},
	.num_resources	= ARRAY_SIZE(ep93xx_eth_resource),
	.resource	= ep93xx_eth_resource,
};

/**
 * ep93xx_register_eth - Register the built-in ethernet platform device.
 * @data:	platform specific ethernet configuration (__initdata)
 * @copy_addr:	flag indicating that the MAC address should be copied
 *		from the IndAd registers (as programmed by the bootloader)
 */
void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr)
{
	if (copy_addr)
		memcpy_fromio(data->dev_addr, EP93XX_ETHERNET_BASE + 0x50, 6);

	ep93xx_eth_data = *data;
	platform_device_register(&ep93xx_eth_device);
}

/*************************************************************************
 * EP93xx i2c peripheral handling
 *************************************************************************/

/* All EP93xx devices use the same two GPIO pins for I2C bit-banging */
static struct gpiod_lookup_table ep93xx_i2c_gpiod_table = {
	.dev_id		= "i2c-gpio.0",
	.table		= {
		/* Use local offsets on gpiochip/port "G" */
		GPIO_LOOKUP_IDX("G", 1, NULL, 0,
				GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
		GPIO_LOOKUP_IDX("G", 0, NULL, 1,
				GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
	},
};

static struct platform_device ep93xx_i2c_device = {
	.name		= "i2c-gpio",
	.id		= 0,
	.dev		= {
		.platform_data	= NULL,
	},
};

/**
 * ep93xx_register_i2c - Register the i2c platform device.
 * @devices:	platform specific i2c bus device information (__initdata)
 * @num:	the number of devices on the i2c bus
 */
void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num)
{
	/*
	 * FIXME: this just sets the two pins as non-opendrain, as no
	 * platforms tries to do that anyway. Flag the applicable lines
	 * as open drain in the GPIO_LOOKUP above and the driver or
	 * gpiolib will handle open drain/open drain emulation as need
	 * be. Right now i2c-gpio emulates open drain which is not
	 * optimal.
	 */
	__raw_writel((0 << 1) | (0 << 0),
		     EP93XX_GPIO_EEDRIVE);

	i2c_register_board_info(0, devices, num);
	gpiod_add_lookup_table(&ep93xx_i2c_gpiod_table);
	platform_device_register(&ep93xx_i2c_device);
}

/*************************************************************************
 * EP93xx SPI peripheral handling
 *************************************************************************/
static struct ep93xx_spi_info ep93xx_spi_master_data;

static struct resource ep93xx_spi_resources[] = {
	DEFINE_RES_MEM(EP93XX_SPI_PHYS_BASE, 0x18),
	DEFINE_RES_IRQ(IRQ_EP93XX_SSP),
};

static u64 ep93xx_spi_dma_mask = DMA_BIT_MASK(32);

static struct platform_device ep93xx_spi_device = {
	.name		= "ep93xx-spi",
	.id		= 0,
	.dev		= {
		.platform_data		= &ep93xx_spi_master_data,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
		.dma_mask		= &ep93xx_spi_dma_mask,
	},
	.num_resources	= ARRAY_SIZE(ep93xx_spi_resources),
	.resource	= ep93xx_spi_resources,
};

/**
 * ep93xx_register_spi() - registers spi platform device
 * @info: ep93xx board specific spi master info (__initdata)
 * @devices: SPI devices to register (__initdata)
 * @num: number of SPI devices to register
 *
 * This function registers platform device for the EP93xx SPI controller and
 * also makes sure that SPI pins are muxed so that I2S is not using those pins.
 */
void __init ep93xx_register_spi(struct ep93xx_spi_info *info,
				struct spi_board_info *devices, int num)
{
	/*
	 * When SPI is used, we need to make sure that I2S is muxed off from
	 * SPI pins.
	 */
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONSSP);

	ep93xx_spi_master_data = *info;
	spi_register_board_info(devices, num);
	platform_device_register(&ep93xx_spi_device);
}

/*************************************************************************
 * EP93xx LEDs
 *************************************************************************/
static const struct gpio_led ep93xx_led_pins[] __initconst = {
	{
		.name	= "platform:grled",
		.gpio	= EP93XX_GPIO_LINE_GRLED,
	}, {
		.name	= "platform:rdled",
		.gpio	= EP93XX_GPIO_LINE_RDLED,
	},
};

static const struct gpio_led_platform_data ep93xx_led_data __initconst = {
	.num_leds	= ARRAY_SIZE(ep93xx_led_pins),
	.leds		= ep93xx_led_pins,
};

/*************************************************************************
 * EP93xx pwm peripheral handling
 *************************************************************************/
static struct resource ep93xx_pwm0_resource[] = {
	DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE, 0x10),
};

static struct platform_device ep93xx_pwm0_device = {
	.name		= "ep93xx-pwm",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(ep93xx_pwm0_resource),
	.resource	= ep93xx_pwm0_resource,
};

static struct resource ep93xx_pwm1_resource[] = {
	DEFINE_RES_MEM(EP93XX_PWM_PHYS_BASE + 0x20, 0x10),
};

static struct platform_device ep93xx_pwm1_device = {
	.name		= "ep93xx-pwm",
	.id		= 1,
	.num_resources	= ARRAY_SIZE(ep93xx_pwm1_resource),
	.resource	= ep93xx_pwm1_resource,
};

void __init ep93xx_register_pwm(int pwm0, int pwm1)
{
	if (pwm0)
		platform_device_register(&ep93xx_pwm0_device);

	/* NOTE: EP9307 does not have PWMOUT1 (pin EGPIO14) */
	if (pwm1)
		platform_device_register(&ep93xx_pwm1_device);
}

int ep93xx_pwm_acquire_gpio(struct platform_device *pdev)
{
	int err;

	if (pdev->id == 0) {
		err = 0;
	} else if (pdev->id == 1) {
		err = gpio_request(EP93XX_GPIO_LINE_EGPIO14,
				   dev_name(&pdev->dev));
		if (err)
			return err;
		err = gpio_direction_output(EP93XX_GPIO_LINE_EGPIO14, 0);
		if (err)
			goto fail;

		/* PWM 1 output on EGPIO[14] */
		ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_PONG);
	} else {
		err = -ENODEV;
	}

	return err;

fail:
	gpio_free(EP93XX_GPIO_LINE_EGPIO14);
	return err;
}
EXPORT_SYMBOL(ep93xx_pwm_acquire_gpio);

void ep93xx_pwm_release_gpio(struct platform_device *pdev)
{
	if (pdev->id == 1) {
		gpio_direction_input(EP93XX_GPIO_LINE_EGPIO14);
		gpio_free(EP93XX_GPIO_LINE_EGPIO14);

		/* EGPIO[14] used for GPIO */
		ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_PONG);
	}
}
EXPORT_SYMBOL(ep93xx_pwm_release_gpio);

/*************************************************************************
 * EP93xx video peripheral handling
 *************************************************************************/
static struct ep93xxfb_mach_info ep93xxfb_data;

static struct resource ep93xx_fb_resource[] = {
	DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE, 0x800),
};

static struct platform_device ep93xx_fb_device = {
	.name			= "ep93xx-fb",
	.id			= -1,
	.dev			= {
		.platform_data		= &ep93xxfb_data,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
		.dma_mask		= &ep93xx_fb_device.dev.coherent_dma_mask,
	},
	.num_resources		= ARRAY_SIZE(ep93xx_fb_resource),
	.resource		= ep93xx_fb_resource,
};

/* The backlight use a single register in the framebuffer's register space */
#define EP93XX_RASTER_REG_BRIGHTNESS 0x20

static struct resource ep93xx_bl_resources[] = {
	DEFINE_RES_MEM(EP93XX_RASTER_PHYS_BASE +
		       EP93XX_RASTER_REG_BRIGHTNESS, 0x04),
};

static struct platform_device ep93xx_bl_device = {
	.name		= "ep93xx-bl",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_bl_resources),
	.resource	= ep93xx_bl_resources,
};

/**
 * ep93xx_register_fb - Register the framebuffer platform device.
 * @data:	platform specific framebuffer configuration (__initdata)
 */
void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
{
	ep93xxfb_data = *data;
	platform_device_register(&ep93xx_fb_device);
	platform_device_register(&ep93xx_bl_device);
}

/*************************************************************************
 * EP93xx matrix keypad peripheral handling
 *************************************************************************/
static struct ep93xx_keypad_platform_data ep93xx_keypad_data;

static struct resource ep93xx_keypad_resource[] = {
	DEFINE_RES_MEM(EP93XX_KEY_MATRIX_PHYS_BASE, 0x0c),
	DEFINE_RES_IRQ(IRQ_EP93XX_KEY),
};

static struct platform_device ep93xx_keypad_device = {
	.name		= "ep93xx-keypad",
	.id		= -1,
	.dev		= {
		.platform_data	= &ep93xx_keypad_data,
	},
	.num_resources	= ARRAY_SIZE(ep93xx_keypad_resource),
	.resource	= ep93xx_keypad_resource,
};

/**
 * ep93xx_register_keypad - Register the keypad platform device.
 * @data:	platform specific keypad configuration (__initdata)
 */
void __init ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data)
{
	ep93xx_keypad_data = *data;
	platform_device_register(&ep93xx_keypad_device);
}

int ep93xx_keypad_acquire_gpio(struct platform_device *pdev)
{
	int err;
	int i;

	for (i = 0; i < 8; i++) {
		err = gpio_request(EP93XX_GPIO_LINE_C(i), dev_name(&pdev->dev));
		if (err)
			goto fail_gpio_c;
		err = gpio_request(EP93XX_GPIO_LINE_D(i), dev_name(&pdev->dev));
		if (err)
			goto fail_gpio_d;
	}

	/* Enable the keypad controller; GPIO ports C and D used for keypad */
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_KEYS |
				 EP93XX_SYSCON_DEVCFG_GONK);

	return 0;

fail_gpio_d:
	gpio_free(EP93XX_GPIO_LINE_C(i));
fail_gpio_c:
	for (--i; i >= 0; --i) {
		gpio_free(EP93XX_GPIO_LINE_C(i));
		gpio_free(EP93XX_GPIO_LINE_D(i));
	}
	return err;
}
EXPORT_SYMBOL(ep93xx_keypad_acquire_gpio);

void ep93xx_keypad_release_gpio(struct platform_device *pdev)
{
	int i;

	for (i = 0; i < 8; i++) {
		gpio_free(EP93XX_GPIO_LINE_C(i));
		gpio_free(EP93XX_GPIO_LINE_D(i));
	}

	/* Disable the keypad controller; GPIO ports C and D used for GPIO */
	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
			       EP93XX_SYSCON_DEVCFG_GONK);
}
EXPORT_SYMBOL(ep93xx_keypad_release_gpio);

/*************************************************************************
 * EP93xx I2S audio peripheral handling
 *************************************************************************/
static struct resource ep93xx_i2s_resource[] = {
	DEFINE_RES_MEM(EP93XX_I2S_PHYS_BASE, 0x100),
	DEFINE_RES_IRQ(IRQ_EP93XX_SAI),
};

static struct platform_device ep93xx_i2s_device = {
	.name		= "ep93xx-i2s",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_i2s_resource),
	.resource	= ep93xx_i2s_resource,
};

static struct platform_device ep93xx_pcm_device = {
	.name		= "ep93xx-pcm-audio",
	.id		= -1,
};

void __init ep93xx_register_i2s(void)
{
	platform_device_register(&ep93xx_i2s_device);
	platform_device_register(&ep93xx_pcm_device);
}

#define EP93XX_SYSCON_DEVCFG_I2S_MASK	(EP93XX_SYSCON_DEVCFG_I2SONSSP | \
					 EP93XX_SYSCON_DEVCFG_I2SONAC97)

#define EP93XX_I2SCLKDIV_MASK		(EP93XX_SYSCON_I2SCLKDIV_ORIDE | \
					 EP93XX_SYSCON_I2SCLKDIV_SPOL)

int ep93xx_i2s_acquire(void)
{
	unsigned val;

	ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_I2SONAC97,
			EP93XX_SYSCON_DEVCFG_I2S_MASK);

	/*
	 * This is potentially racy with the clock api for i2s_mclk, sclk and
	 * lrclk. Since the i2s driver is the only user of those clocks we
	 * rely on it to prevent parallel use of this function and the
	 * clock api for the i2s clocks.
	 */
	val = __raw_readl(EP93XX_SYSCON_I2SCLKDIV);
	val &= ~EP93XX_I2SCLKDIV_MASK;
	val |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
	ep93xx_syscon_swlocked_write(val, EP93XX_SYSCON_I2SCLKDIV);

	return 0;
}
EXPORT_SYMBOL(ep93xx_i2s_acquire);

void ep93xx_i2s_release(void)
{
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2S_MASK);
}
EXPORT_SYMBOL(ep93xx_i2s_release);

/*************************************************************************
 * EP93xx AC97 audio peripheral handling
 *************************************************************************/
static struct resource ep93xx_ac97_resources[] = {
	DEFINE_RES_MEM(EP93XX_AAC_PHYS_BASE, 0xac),
	DEFINE_RES_IRQ(IRQ_EP93XX_AACINTR),
};

static struct platform_device ep93xx_ac97_device = {
	.name		= "ep93xx-ac97",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_ac97_resources),
	.resource	= ep93xx_ac97_resources,
};

void __init ep93xx_register_ac97(void)
{
	/*
	 * Make sure that the AC97 pins are not used by I2S.
	 */
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_I2SONAC97);

	platform_device_register(&ep93xx_ac97_device);
	platform_device_register(&ep93xx_pcm_device);
}

/*************************************************************************
 * EP93xx Watchdog
 *************************************************************************/
static struct resource ep93xx_wdt_resources[] = {
	DEFINE_RES_MEM(EP93XX_WATCHDOG_PHYS_BASE, 0x08),
};

static struct platform_device ep93xx_wdt_device = {
	.name		= "ep93xx-wdt",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_wdt_resources),
	.resource	= ep93xx_wdt_resources,
};

/*************************************************************************
 * EP93xx IDE
 *************************************************************************/
static struct resource ep93xx_ide_resources[] = {
	DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38),
	DEFINE_RES_IRQ(IRQ_EP93XX_EXT3),
};

static struct platform_device ep93xx_ide_device = {
	.name		= "ep93xx-ide",
	.id		= -1,
	.dev		= {
		.dma_mask		= &ep93xx_ide_device.dev.coherent_dma_mask,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
	.num_resources	= ARRAY_SIZE(ep93xx_ide_resources),
	.resource	= ep93xx_ide_resources,
};

void __init ep93xx_register_ide(void)
{
	platform_device_register(&ep93xx_ide_device);
}

int ep93xx_ide_acquire_gpio(struct platform_device *pdev)
{
	int err;
	int i;

	err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev));
	if (err)
		return err;
	err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev));
	if (err)
		goto fail_egpio15;
	for (i = 2; i < 8; i++) {
		err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev));
		if (err)
			goto fail_gpio_e;
	}
	for (i = 4; i < 8; i++) {
		err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev));
		if (err)
			goto fail_gpio_g;
	}
	for (i = 0; i < 8; i++) {
		err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev));
		if (err)
			goto fail_gpio_h;
	}

	/* GPIO ports E[7:2], G[7:4] and H used by IDE */
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
				 EP93XX_SYSCON_DEVCFG_GONIDE |
				 EP93XX_SYSCON_DEVCFG_HONIDE);
	return 0;

fail_gpio_h:
	for (--i; i >= 0; --i)
		gpio_free(EP93XX_GPIO_LINE_H(i));
	i = 8;
fail_gpio_g:
	for (--i; i >= 4; --i)
		gpio_free(EP93XX_GPIO_LINE_G(i));
	i = 8;
fail_gpio_e:
	for (--i; i >= 2; --i)
		gpio_free(EP93XX_GPIO_LINE_E(i));
	gpio_free(EP93XX_GPIO_LINE_EGPIO15);
fail_egpio15:
	gpio_free(EP93XX_GPIO_LINE_EGPIO2);
	return err;
}
EXPORT_SYMBOL(ep93xx_ide_acquire_gpio);

void ep93xx_ide_release_gpio(struct platform_device *pdev)
{
	int i;

	for (i = 2; i < 8; i++)
		gpio_free(EP93XX_GPIO_LINE_E(i));
	for (i = 4; i < 8; i++)
		gpio_free(EP93XX_GPIO_LINE_G(i));
	for (i = 0; i < 8; i++)
		gpio_free(EP93XX_GPIO_LINE_H(i));
	gpio_free(EP93XX_GPIO_LINE_EGPIO15);
	gpio_free(EP93XX_GPIO_LINE_EGPIO2);

	/* GPIO ports E[7:2], G[7:4] and H used by GPIO */
	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
			       EP93XX_SYSCON_DEVCFG_GONIDE |
			       EP93XX_SYSCON_DEVCFG_HONIDE);
}
EXPORT_SYMBOL(ep93xx_ide_release_gpio);

/*************************************************************************
 * EP93xx ADC
 *************************************************************************/
static struct resource ep93xx_adc_resources[] = {
	DEFINE_RES_MEM(EP93XX_ADC_PHYS_BASE, 0x28),
	DEFINE_RES_IRQ(IRQ_EP93XX_TOUCH),
};

static struct platform_device ep93xx_adc_device = {
	.name		= "ep93xx-adc",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(ep93xx_adc_resources),
	.resource	= ep93xx_adc_resources,
};

void __init ep93xx_register_adc(void)
{
	/* Power up ADC, deactivate Touch Screen Controller */
	ep93xx_devcfg_set_clear(EP93XX_SYSCON_DEVCFG_TIN,
				EP93XX_SYSCON_DEVCFG_ADCPD);

	platform_device_register(&ep93xx_adc_device);
}

/*************************************************************************
 * EP93xx Security peripheral
 *************************************************************************/

/*
 * The Maverick Key is 256 bits of micro fuses blown at the factory during
 * manufacturing to uniquely identify a part.
 *
 * See: http://arm.cirrus.com/forum/viewtopic.php?t=486&highlight=maverick+key
 */
#define EP93XX_SECURITY_REG(x)		(EP93XX_SECURITY_BASE + (x))
#define EP93XX_SECURITY_SECFLG		EP93XX_SECURITY_REG(0x2400)
#define EP93XX_SECURITY_FUSEFLG		EP93XX_SECURITY_REG(0x2410)
#define EP93XX_SECURITY_UNIQID		EP93XX_SECURITY_REG(0x2440)
#define EP93XX_SECURITY_UNIQCHK		EP93XX_SECURITY_REG(0x2450)
#define EP93XX_SECURITY_UNIQVAL		EP93XX_SECURITY_REG(0x2460)
#define EP93XX_SECURITY_SECID1		EP93XX_SECURITY_REG(0x2500)
#define EP93XX_SECURITY_SECID2		EP93XX_SECURITY_REG(0x2504)
#define EP93XX_SECURITY_SECCHK1		EP93XX_SECURITY_REG(0x2520)
#define EP93XX_SECURITY_SECCHK2		EP93XX_SECURITY_REG(0x2524)
#define EP93XX_SECURITY_UNIQID2		EP93XX_SECURITY_REG(0x2700)
#define EP93XX_SECURITY_UNIQID3		EP93XX_SECURITY_REG(0x2704)
#define EP93XX_SECURITY_UNIQID4		EP93XX_SECURITY_REG(0x2708)
#define EP93XX_SECURITY_UNIQID5		EP93XX_SECURITY_REG(0x270c)

static char ep93xx_soc_id[33];

static const char __init *ep93xx_get_soc_id(void)
{
	unsigned int id, id2, id3, id4, id5;

	if (__raw_readl(EP93XX_SECURITY_UNIQVAL) != 1)
		return "bad Hamming code";

	id = __raw_readl(EP93XX_SECURITY_UNIQID);
	id2 = __raw_readl(EP93XX_SECURITY_UNIQID2);
	id3 = __raw_readl(EP93XX_SECURITY_UNIQID3);
	id4 = __raw_readl(EP93XX_SECURITY_UNIQID4);
	id5 = __raw_readl(EP93XX_SECURITY_UNIQID5);

	if (id != id2)
		return "invalid";

	/* Toss the unique ID into the entropy pool */
	add_device_randomness(&id2, 4);
	add_device_randomness(&id3, 4);
	add_device_randomness(&id4, 4);
	add_device_randomness(&id5, 4);

	snprintf(ep93xx_soc_id, sizeof(ep93xx_soc_id),
		 "%08x%08x%08x%08x", id2, id3, id4, id5);

	return ep93xx_soc_id;
}

static const char __init *ep93xx_get_soc_rev(void)
{
	int rev = ep93xx_chip_revision();

	switch (rev) {
	case EP93XX_CHIP_REV_D0:
		return "D0";
	case EP93XX_CHIP_REV_D1:
		return "D1";
	case EP93XX_CHIP_REV_E0:
		return "E0";
	case EP93XX_CHIP_REV_E1:
		return "E1";
	case EP93XX_CHIP_REV_E2:
		return "E2";
	default:
		return "unknown";
	}
}

static const char __init *ep93xx_get_machine_name(void)
{
	return kasprintf(GFP_KERNEL,"%s", machine_desc->name);
}

static struct device __init *ep93xx_init_soc(void)
{
	struct soc_device_attribute *soc_dev_attr;
	struct soc_device *soc_dev;

	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
	if (!soc_dev_attr)
		return NULL;

	soc_dev_attr->machine = ep93xx_get_machine_name();
	soc_dev_attr->family = "Cirrus Logic EP93xx";
	soc_dev_attr->revision = ep93xx_get_soc_rev();
	soc_dev_attr->soc_id = ep93xx_get_soc_id();

	soc_dev = soc_device_register(soc_dev_attr);
	if (IS_ERR(soc_dev)) {
		kfree(soc_dev_attr->machine);
		kfree(soc_dev_attr);
		return NULL;
	}

	return soc_device_to_device(soc_dev);
}

struct device __init *ep93xx_init_devices(void)
{
	struct device *parent;

	/* Disallow access to MaverickCrunch initially */
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_CPENA);

	/* Default all ports to GPIO */
	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
			       EP93XX_SYSCON_DEVCFG_GONK |
			       EP93XX_SYSCON_DEVCFG_EONIDE |
			       EP93XX_SYSCON_DEVCFG_GONIDE |
			       EP93XX_SYSCON_DEVCFG_HONIDE);

	parent = ep93xx_init_soc();

	/* Get the GPIO working early, other devices need it */
	platform_device_register(&ep93xx_gpio_device);

	amba_device_register(&uart1_device, &iomem_resource);
	amba_device_register(&uart2_device, &iomem_resource);
	amba_device_register(&uart3_device, &iomem_resource);

	platform_device_register(&ep93xx_rtc_device);
	platform_device_register(&ep93xx_ohci_device);
	platform_device_register(&ep93xx_wdt_device);

	gpio_led_register_device(-1, &ep93xx_led_data);

	return parent;
}

void ep93xx_restart(enum reboot_mode mode, const char *cmd)
{
	/*
	 * Set then clear the SWRST bit to initiate a software reset
	 */
	ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_SWRST);
	ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_SWRST);

	while (1)
		;
}


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * arch/arm/mach-ep93xx/dma.c
 *
 * Platform support code for the EP93xx dmaengine driver.
 *
 * Copyright (C) 2011 Mika Westerberg
 *
 * This work is based on the original dma-m2p implementation with
 * following copyrights:
 *
 *   Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 *   Copyright (C) 2006 Applied Data Systems
 *   Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com>
 */

#include <linux/dmaengine.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>

#include <linux/platform_data/dma-ep93xx.h>
#include "hardware.h"

#include "soc.h"

#define DMA_CHANNEL(_name, _base, _irq) \
	{ .name = (_name), .base = (_base), .irq = (_irq) }

/*
 * DMA M2P channels.
 *
 * On the EP93xx chip the following peripherals my be allocated to the 10
 * Memory to Internal Peripheral (M2P) channels (5 transmit + 5 receive).
 *
 *	I2S	contains 3 Tx and 3 Rx DMA Channels
 *	AAC	contains 3 Tx and 3 Rx DMA Channels
 *	UART1	contains 1 Tx and 1 Rx DMA Channels
 *	UART2	contains 1 Tx and 1 Rx DMA Channels
 *	UART3	contains 1 Tx and 1 Rx DMA Channels
 *	IrDA	contains 1 Tx and 1 Rx DMA Channels
 *
 * Registers are mapped statically in ep93xx_map_io().
 */
static struct ep93xx_dma_chan_data ep93xx_dma_m2p_channels[] = {
	DMA_CHANNEL("m2p0", EP93XX_DMA_BASE + 0x0000, IRQ_EP93XX_DMAM2P0),
	DMA_CHANNEL("m2p1", EP93XX_DMA_BASE + 0x0040, IRQ_EP93XX_DMAM2P1),
	DMA_CHANNEL("m2p2", EP93XX_DMA_BASE + 0x0080, IRQ_EP93XX_DMAM2P2),
	DMA_CHANNEL("m2p3", EP93XX_DMA_BASE + 0x00c0, IRQ_EP93XX_DMAM2P3),
	DMA_CHANNEL("m2p4", EP93XX_DMA_BASE + 0x0240, IRQ_EP93XX_DMAM2P4),
	DMA_CHANNEL("m2p5", EP93XX_DMA_BASE + 0x0200, IRQ_EP93XX_DMAM2P5),
	DMA_CHANNEL("m2p6", EP93XX_DMA_BASE + 0x02c0, IRQ_EP93XX_DMAM2P6),
	DMA_CHANNEL("m2p7", EP93XX_DMA_BASE + 0x0280, IRQ_EP93XX_DMAM2P7),
	DMA_CHANNEL("m2p8", EP93XX_DMA_BASE + 0x0340, IRQ_EP93XX_DMAM2P8),
	DMA_CHANNEL("m2p9", EP93XX_DMA_BASE + 0x0300, IRQ_EP93XX_DMAM2P9),
};

static struct ep93xx_dma_platform_data ep93xx_dma_m2p_data = {
	.channels		= ep93xx_dma_m2p_channels,
	.num_channels		= ARRAY_SIZE(ep93xx_dma_m2p_channels),
};

static u64 ep93xx_dma_m2p_mask = DMA_BIT_MASK(32);

static struct platform_device ep93xx_dma_m2p_device = {
	.name			= "ep93xx-dma-m2p",
	.id			= -1,
	.dev			= {
		.platform_data		= &ep93xx_dma_m2p_data,
		.dma_mask		= &ep93xx_dma_m2p_mask,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
};

/*
 * DMA M2M channels.
 *
 * There are 2 M2M channels which support memcpy/memset and in addition simple
 * hardware requests from/to SSP and IDE. We do not implement an external
 * hardware requests.
 *
 * Registers are mapped statically in ep93xx_map_io().
 */
static struct ep93xx_dma_chan_data ep93xx_dma_m2m_channels[] = {
	DMA_CHANNEL("m2m0", EP93XX_DMA_BASE + 0x0100, IRQ_EP93XX_DMAM2M0),
	DMA_CHANNEL("m2m1", EP93XX_DMA_BASE + 0x0140, IRQ_EP93XX_DMAM2M1),
};

static struct ep93xx_dma_platform_data ep93xx_dma_m2m_data = {
	.channels		= ep93xx_dma_m2m_channels,
	.num_channels		= ARRAY_SIZE(ep93xx_dma_m2m_channels),
};

static u64 ep93xx_dma_m2m_mask = DMA_BIT_MASK(32);

static struct platform_device ep93xx_dma_m2m_device = {
	.name			= "ep93xx-dma-m2m",
	.id			= -1,
	.dev			= {
		.platform_data		= &ep93xx_dma_m2m_data,
		.dma_mask		= &ep93xx_dma_m2m_mask,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
};

static int __init ep93xx_dma_init(void)
{
	platform_device_register(&ep93xx_dma_m2p_device);
	platform_device_register(&ep93xx_dma_m2m_device);
	return 0;
}
arch_initcall(ep93xx_dma_init);


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * arch/arm/mach-ep93xx/edb93xx.c
 * Cirrus Logic EDB93xx Development Board support.
 *
 * EDB93XX, EDB9301, EDB9307A
 * Copyright (C) 2008-2009 H Hartley Sweeten <hsweeten@visionengravers.com>
 *
 * EDB9302
 * Copyright (C) 2006 George Kashperko <george@chas.com.ua>
 *
 * EDB9302A, EDB9315, EDB9315A
 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 *
 * EDB9307
 * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
 *
 * EDB9312
 * Copyright (C) 2006 Infosys Technologies Limited
 *                    Toufeeq Hussain <toufeeq_hussain@infosys.com>
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <linux/gpio/machine.h>

#include <sound/cs4271.h>

#include "hardware.h"
#include <linux/platform_data/video-ep93xx.h>
#include <linux/platform_data/spi-ep93xx.h>
#include "gpio-ep93xx.h"

#include <asm/mach-types.h>
#include <asm/mach/arch.h>

#include "soc.h"

static void __init edb93xx_register_flash(void)
{
	if (machine_is_edb9307() || machine_is_edb9312() ||
	    machine_is_edb9315()) {
		ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_32M);
	} else {
		ep93xx_register_flash(2, EP93XX_CS6_PHYS_BASE, SZ_16M);
	}
}

static struct ep93xx_eth_data __initdata edb93xx_eth_data = {
	.phy_id		= 1,
};

/*************************************************************************
 * EDB93xx i2c peripheral handling
 *************************************************************************/

static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = {
	{
		I2C_BOARD_INFO("isl1208", 0x6f),
	},
};

static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = {
	{
		I2C_BOARD_INFO("ds1337", 0x68),
	},
};

static void __init edb93xx_register_i2c(void)
{
	if (machine_is_edb9302a() || machine_is_edb9307a() ||
	    machine_is_edb9315a()) {
		ep93xx_register_i2c(edb93xxa_i2c_board_info,
				    ARRAY_SIZE(edb93xxa_i2c_board_info));
	} else if (machine_is_edb9302() || machine_is_edb9307()
		|| machine_is_edb9312() || machine_is_edb9315()) {
		ep93xx_register_i2c(edb93xx_i2c_board_info,
				    ARRAY_SIZE(edb93xx_i2c_board_info));
	}
}

/*************************************************************************
 * EDB93xx SPI peripheral handling
 *************************************************************************/
static struct cs4271_platform_data edb93xx_cs4271_data = {
	.gpio_nreset	= -EINVAL,	/* filled in later */
};

static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
	{
		.modalias		= "cs4271",
		.platform_data		= &edb93xx_cs4271_data,
		.max_speed_hz		= 6000000,
		.bus_num		= 0,
		.chip_select		= 0,
		.mode			= SPI_MODE_3,
	},
};

static struct gpiod_lookup_table edb93xx_spi_cs_gpio_table = {
	.dev_id = "spi0",
	.table = {
		GPIO_LOOKUP("A", 6, "cs", GPIO_ACTIVE_LOW),
		{ },
	},
};

static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
	/* Intentionally left blank */
};

static void __init edb93xx_register_spi(void)
{
	if (machine_is_edb9301() || machine_is_edb9302())
		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO1;
	else if (machine_is_edb9302a() || machine_is_edb9307a())
		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_H(2);
	else if (machine_is_edb9315a())
		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO14;

	gpiod_add_lookup_table(&edb93xx_spi_cs_gpio_table);
	ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
			    ARRAY_SIZE(edb93xx_spi_board_info));
}

/*************************************************************************
 * EDB93xx I2S
 *************************************************************************/
static struct platform_device edb93xx_audio_device = {
	.name		= "edb93xx-audio",
	.id		= -1,
};

static int __init edb93xx_has_audio(void)
{
	return (machine_is_edb9301() || machine_is_edb9302() ||
		machine_is_edb9302a() || machine_is_edb9307a() ||
		machine_is_edb9315a());
}

static void __init edb93xx_register_i2s(void)
{
	if (edb93xx_has_audio()) {
		ep93xx_register_i2s();
		platform_device_register(&edb93xx_audio_device);
	}
}

/*************************************************************************
 * EDB93xx pwm
 *************************************************************************/
static void __init edb93xx_register_pwm(void)
{
	if (machine_is_edb9301() ||
	    machine_is_edb9302() || machine_is_edb9302a()) {
		/* EP9301 and EP9302 only have pwm.1 (EGPIO14) */
		ep93xx_register_pwm(0, 1);
	} else if (machine_is_edb9307() || machine_is_edb9307a()) {
		/* EP9307 only has pwm.0 (PWMOUT) */
		ep93xx_register_pwm(1, 0);
	} else {
		/* EP9312 and EP9315 have both */
		ep93xx_register_pwm(1, 1);
	}
}

/*************************************************************************
 * EDB93xx framebuffer
 *************************************************************************/
static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
	.flags		= 0,
};

static int __init edb93xx_has_fb(void)
{
	/* These platforms have an ep93xx with video capability */
	return machine_is_edb9307() || machine_is_edb9307a() ||
	       machine_is_edb9312() || machine_is_edb9315() ||
	       machine_is_edb9315a();
}

static void __init edb93xx_register_fb(void)
{
	if (!edb93xx_has_fb())
		return;

	if (machine_is_edb9307a() || machine_is_edb9315a())
		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
	else
		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;

	ep93xx_register_fb(&edb93xxfb_info);
}

/*************************************************************************
 * EDB93xx IDE
 *************************************************************************/
static int __init edb93xx_has_ide(void)
{
	/*
	 * Although EDB9312 and EDB9315 do have IDE capability, they have
	 * INTRQ line wired as pull-up, which makes using IDE interface
	 * problematic.
	 */
	return machine_is_edb9312() || machine_is_edb9315() ||
	       machine_is_edb9315a();
}

static void __init edb93xx_register_ide(void)
{
	if (!edb93xx_has_ide())
		return;

	ep93xx_register_ide();
}

static void __init edb93xx_init_machine(void)
{
	ep93xx_init_devices();
	edb93xx_register_flash();
	ep93xx_register_eth(&edb93xx_eth_data, 1);
	edb93xx_register_i2c();
	edb93xx_register_spi();
	edb93xx_register_i2s();
	edb93xx_register_pwm();
	edb93xx_register_fb();
	edb93xx_register_ide();
	ep93xx_register_adc();
}

#ifdef CONFIG_MACH_EDB9301
MACHINE_START(EDB9301, "Cirrus Logic EDB9301 Evaluation Board")
	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9302
MACHINE_START(EDB9302, "Cirrus Logic EDB9302 Evaluation Board")
	/* Maintainer: George Kashperko <george@chas.com.ua> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9302A
MACHINE_START(EDB9302A, "Cirrus Logic EDB9302A Evaluation Board")
	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9307
MACHINE_START(EDB9307, "Cirrus Logic EDB9307 Evaluation Board")
	/* Maintainer: Herbert Valerio Riedel <hvr@gnu.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9307A
MACHINE_START(EDB9307A, "Cirrus Logic EDB9307A Evaluation Board")
	/* Maintainer: H Hartley Sweeten <hsweeten@visionengravers.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9312
MACHINE_START(EDB9312, "Cirrus Logic EDB9312 Evaluation Board")
	/* Maintainer: Toufeeq Hussain <toufeeq_hussain@infosys.com> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9315
MACHINE_START(EDB9315, "Cirrus Logic EDB9315 Evaluation Board")
	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_EDB9315A
MACHINE_START(EDB9315A, "Cirrus Logic EDB9315A Evaluation Board")
	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= edb93xx_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END
#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_ARCH_EP93XX_REGS_H
#define __ASM_ARCH_EP93XX_REGS_H

/*
 * EP93xx linux memory map:
 *
 * virt		phys		size
 * fe800000			5M		per-platform mappings
 * fed00000	80800000	2M		APB
 * fef00000	80000000	1M		AHB
 */

#define EP93XX_AHB_PHYS_BASE		0x80000000
#define EP93XX_AHB_VIRT_BASE		0xfef00000
#define EP93XX_AHB_SIZE			0x00100000

#define EP93XX_AHB_PHYS(x)		(EP93XX_AHB_PHYS_BASE + (x))
#define EP93XX_AHB_IOMEM(x)		IOMEM(EP93XX_AHB_VIRT_BASE + (x))

#define EP93XX_APB_PHYS_BASE		0x80800000
#define EP93XX_APB_VIRT_BASE		0xfed00000
#define EP93XX_APB_SIZE			0x00200000

#define EP93XX_APB_PHYS(x)		(EP93XX_APB_PHYS_BASE + (x))
#define EP93XX_APB_IOMEM(x)		IOMEM(EP93XX_APB_VIRT_BASE + (x))

/* APB UARTs */
#define EP93XX_UART1_PHYS_BASE		EP93XX_APB_PHYS(0x000c0000)
#define EP93XX_UART1_BASE		EP93XX_APB_IOMEM(0x000c0000)

#define EP93XX_UART2_PHYS_BASE		EP93XX_APB_PHYS(0x000d0000)
#define EP93XX_UART2_BASE		EP93XX_APB_IOMEM(0x000d0000)

#define EP93XX_UART3_PHYS_BASE		EP93XX_APB_PHYS(0x000e0000)
#define EP93XX_UART3_BASE		EP93XX_APB_IOMEM(0x000e0000)

#endif


code:
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * arch/arm/mach-ep93xx/gesbc9312.c
 * Glomation GESBC-9312-sx support.
 *
 * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/sizes.h>

#include "hardware.h"

#include <asm/mach-types.h>
#include <asm/mach/arch.h>

#include "soc.h"

static struct ep93xx_eth_data __initdata gesbc9312_eth_data = {
	.phy_id		= 1,
};

static void __init gesbc9312_init_machine(void)
{
	ep93xx_init_devices();
	ep93xx_register_flash(4, EP93XX_CS6_PHYS_BASE, SZ_8M);
	ep93xx_register_eth(&gesbc9312_eth_data, 0);
}

MACHINE_START(GESBC9312, "Glomation GESBC-9312-sx")
	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
	.atag_offset	= 0x100,
	.nr_irqs	= NR_EP93XX_IRQS,
	.map_io		= ep93xx_map_io,
	.init_irq	= ep93xx_init_irq,
	.init_time	= ep93xx_timer_init,
	.init_machine	= gesbc9312_init_machine,
	.restart	= ep93xx_restart,
MACHINE_END


code:
/* SPDX-License-Identifier: GPL-2.0 */
/* Include file for the EP93XX GPIO controller machine specifics */

#ifndef __GPIO_EP93XX_H
#define __GPIO_EP93XX_H

#include "ep93xx-regs.h"

#define EP93XX_GPIO_PHYS_BASE		EP93XX_APB_PHYS(0x00040000)
#define EP93XX_GPIO_BASE		EP93XX_APB_IOMEM(0x00040000)
#define EP93XX_GPIO_REG(x)		(EP93XX_GPIO_BASE + (x))
#define EP93XX_GPIO_F_INT_STATUS	EP93XX_GPIO_REG(0x5c)
#define EP93XX_GPIO_A_INT_STATUS	EP93XX_GPIO_REG(0xa0)
#define EP93XX_GPIO_B_INT_STATUS	EP93XX_GPIO_REG(0xbc)
#define EP93XX_GPIO_EEDRIVE		EP93XX_GPIO_REG(0xc8)

/* GPIO port A.  */
#define EP93XX_GPIO_LINE_A(x)		((x) + 0)
#define EP93XX_GPIO_LINE_EGPIO0		EP93XX_GPIO_LINE_A(0)
#define EP93XX_GPIO_LINE_EGPIO1		EP93XX_GPIO_LINE_A(1)
#define EP93XX_GPIO_LINE_EGPIO2		EP93XX_GPIO_LINE_A(2)
#define EP93XX_GPIO_LINE_EGPIO3		EP93XX_GPIO_LINE_A(3)
#define EP93XX_GPIO_LINE_EGPIO4		EP93XX_GPIO_LINE_A(4)
#define EP93XX_GPIO_LINE_EGPIO5		EP93XX_GPIO_LINE_A(5)
#define EP93XX_GPIO_LINE_EGPIO6		EP93XX_GPIO_LINE_A(6)
#define EP93XX_GPIO_LINE_EGPIO7		EP93XX_GPIO_LINE_A(7)

/* GPIO port B.  */
#define EP93XX_GPIO_LINE_B(x)		((x) + 8)
#define EP93XX_GPIO_LINE_EGPIO8		EP93XX_GPIO_LINE_B(0)
#define EP93XX_GPIO_LINE_EGPIO9		EP93XX_GPIO_LINE_B(1)
#define EP93XX_GPIO_LINE_EGPIO10	EP93XX_GPIO_LINE_B(2)
#define EP93XX_GPIO_LINE_EGPIO11	EP93XX_GPIO_LINE_B(3)
#define EP93XX_GPIO_LINE_EGPIO12	EP93XX_GPIO_LINE_B(4)
#define EP93XX_GPIO_LINE_EGPIO13	EP93XX_GPIO_LINE_B(5)
#define EP93XX_GPIO_LINE_EGPIO14	EP93XX_GPIO_LINE_B(6)
#define EP93XX_GPIO_LINE_EGPIO15	EP93XX_GPIO_LINE_B(7)

/* GPIO port C.  */
#define EP93XX_GPIO_LINE_C(x)		((x) + 40)
#define EP93XX_GPIO_LINE_ROW0		EP93XX_GPIO_LINE_C(0)
#define EP93XX_GPIO_LINE_ROW1		EP93XX_GPIO_LINE_C(1)
#define EP93XX_GPIO_LINE_ROW2		EP93XX_GPIO_LINE_C(2)
#define EP93XX_GPIO_LINE_ROW3		EP93XX_GPIO_LINE_C(3)
#define EP93XX_GPIO_LINE_ROW4		EP93XX_GPIO_LINE_C(4)
#define EP93XX_GPIO_LINE_ROW5		EP93XX_GPIO_LINE_C(5)
#define EP93XX_GPIO_LINE_ROW6		EP93XX_GPIO_LINE_C(6)
#define EP93XX_GPIO_LINE_ROW7		EP93XX_GPIO_LINE_C(7)

/* GPIO port D.  */
#define EP93XX_GPIO_LINE_D(x)		((x) + 24)
#define EP93XX_GPIO_LINE_COL0		EP93XX_GPIO_LINE_D(0)
#define EP93XX_GPIO_LINE_COL1		EP93XX_GPIO_LINE_D(1)
#define EP93XX_GPIO_LINE_COL2		EP93XX_GPIO_LINE_D(2)
#define EP93XX_GPIO_LINE_COL3		EP93XX_GPIO_LINE_D(3)
#define EP93XX_GPIO_LINE_COL4		EP93XX_GPIO_LINE_D(4)
#define EP93XX_GPIO_LINE_COL5		EP93XX_GPIO_LINE_D(5)
#define EP93XX_GPIO_LINE_COL6		EP93XX_GPIO_LINE_D(6)
#define EP93XX_GPIO_LINE_COL7		EP93XX_GPIO_LINE_D(7)

/* GPIO port E.  */
#define EP93XX_GPIO_LINE_E(x)		((x) + 32)
#define EP93XX_GPIO_LINE_GRLED		EP93XX_GPIO_LINE_E(0)
#define EP93XX_GPIO_LINE_RDLED		EP93XX_GPIO_LINE_E(1)
#define EP93XX_GPIO_LINE_DIORn		EP93XX_GPIO_LINE_E(2)
#define EP93XX_GPIO_LINE_IDECS1n	EP93XX_GPIO_LINE_E(3)
#define EP93XX_GPIO_LINE_IDECS2n	EP93XX_GPIO_LINE_E(4)
#define EP93XX_GPIO_LINE_IDEDA0		EP93XX_GPIO_LINE_E(5)
#define EP93XX_GPIO_LINE_IDEDA1		EP93XX_GPIO_LINE_E(6)
#define EP93XX_GPIO_LINE_IDEDA2		EP93XX_GPIO_LINE_E(7)

/* GPIO port F.  */
#define EP93XX_GPIO_LINE_F(x)		((x) + 16)
#define EP93XX_GPIO_LINE_WP		EP93XX_GPIO_LINE_F(0)
#define EP93XX_GPIO_LINE_MCCD1		EP93XX_GPIO_LINE_F(1)
#define EP93XX_GPIO_LINE_MCCD2		EP93XX_GPIO_LINE_F(2)
#define EP93XX_GPIO_LINE_MCBVD1		EP93XX_GPIO_LINE_F(3)
#define EP93XX_GPIO_LINE_MCBVD2		EP93XX_GPIO_LINE_F(4)
#define EP93XX_GPIO_LINE_VS1		EP93XX_GPIO_LINE_F(5)
#define EP93XX_GPIO_LINE_READY		EP93XX_GPIO_LINE_F(6)
#define EP93XX_GPIO_LINE_VS2		EP93XX_GPIO_LINE_F(7)

/* GPIO port G.  */
#define EP93XX_GPIO_LINE_G(x)		((x) + 48)
#define EP93XX_GPIO_LINE_EECLK		EP93XX_GPIO_LINE_G(0)
#define EP93XX_GPIO_LINE_EEDAT		EP93XX_GPIO_LINE_G(1)
#define EP93XX_GPIO_LINE_SLA0		EP93XX_GPIO_LINE_G(2)
#define EP93XX_GPIO_LINE_SLA1		EP93XX_GPIO_LINE_G(3)
#define EP93XX_GPIO_LINE_DD12		EP93XX_GPIO_LINE_G(4)
#define EP93XX_GPIO_LINE_DD13		EP93XX_GPIO_LINE_G(5)
#define EP93XX_GPIO_LINE_DD14		EP93XX_GPIO_LINE_G(6)
#define EP93XX_GPIO_LINE_DD15		EP93XX_GPIO_LINE_G(7)

/* GPIO port H.  */
#define EP93XX_GPIO_LINE_H(x)		((x) + 56)
#define EP93XX_GPIO_LINE_DD0		EP93XX_GPIO_LINE_H(0)
#define EP93XX_GPIO_LINE_DD1		EP93XX_GPIO_LINE_H(1)
#define EP93XX_GPIO_LINE_DD2		EP93XX_GPIO_LINE_H(2)
#define EP93XX_GPIO_LINE_DD3		EP93XX_GPIO_LINE_H(3)
#define EP93XX_GPIO_LINE_DD4		EP93XX_GPIO_LINE_H(4)
#define EP93XX_GPIO_LINE_DD5		EP93XX_GPIO_LINE_H(5)
#define EP93XX_GPIO_LINE_DD6		EP93XX_GPIO_LINE_H(6)
#define EP93XX_GPIO_LINE_DD7		EP93XX_GPIO_LINE_H(7)

/* maximum value for gpio line identifiers */
#define EP93XX_GPIO_LINE_MAX		EP93XX_GPIO_LINE_H(7)

/* maximum value for irq capable line identifiers */
#define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)

#endif /* __GPIO_EP93XX_H */


code:
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * arch/arm/mach-ep93xx/include/mach/hardware.h
 */

#ifndef __ASM_ARCH_HARDWARE_H
#define __ASM_ARCH_HARDWARE_H

#include "platform.h"

/*
 * The EP93xx has two external crystal oscillators.  To generate the
 * required high-frequency clocks, the processor uses two phase-locked-
 * loops (PLLs) to multiply the incoming external clock signal to much
 * higher frequencies that are then divided down by programmable dividers
 * to produce the needed clocks.  The PLLs operate independently of one
 * another.
 */
#define EP93XX_EXT_CLK_RATE	14745600
#define EP93XX_EXT_RTC_RATE	32768

#define EP93XX_KEYTCHCLK_DIV4	(EP93XX_EXT_CLK_RATE / 4)
#define EP93XX_KEYTCHCLK_DIV16	(EP93XX_EXT_CLK_RATE / 16)

#endif


code:
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __ASM_ARCH_IRQS_H
#define __ASM_ARCH_IRQS_H

#define IRQ_EP93XX_VIC0			1

#define IRQ_EP93XX_COMMRX		(IRQ_EP93XX_VIC0 + 2)
#define IRQ_EP93XX_COMMTX		(IRQ_EP93XX_VIC0 + 3)
#define IRQ_EP93XX_TIMER1		(IRQ_EP93XX_VIC0 + 4)
#define IRQ_EP93XX_TIMER2		(IRQ_EP93XX_VIC0 + 5)
#define IRQ_EP93XX_AACINTR		(IRQ_EP93XX_VIC0 + 6)
#define IRQ_EP93XX_DMAM2P0		(IRQ_EP93XX_VIC0 + 7)
#define IRQ_EP93XX_DMAM2P1		(IRQ_EP93XX_VIC0 + 8)
#define IRQ_EP93XX_DMAM2P2		(IRQ_EP93XX_VIC0 + 9)
#define IRQ_EP93XX_DMAM2P3		(IRQ_EP93XX_VIC0 + 10)
#define IRQ_EP93XX_DMAM2P4		(IRQ_EP93XX_VIC0 + 11)
#define IRQ_EP93XX_DMAM2P5		(IRQ_EP93XX_VIC0 + 12)
#define IRQ_EP93XX_DMAM2P6		(IRQ_EP93XX_VIC0 + 13)
#define IRQ_EP93XX_DMAM2P7		(IRQ_EP93XX_VIC0 + 14)
#define IRQ_EP93XX_DMAM2P8		(IRQ_EP93XX_VIC0 + 15)
#define IRQ_EP93XX_DMAM2P9		(IRQ_EP93XX_VIC0 + 16)
#define IRQ_EP93XX_DMAM2M0		(IRQ_EP93XX_VIC0 + 17)
#define IRQ_EP93XX_DMAM2M1		(IRQ_EP93XX_VIC0 + 18)
#define IRQ_EP93XX_GPIO0MUX		(IRQ_EP93XX_VIC0 + 19)
#define IRQ_EP93XX_GPIO1MUX		(IRQ_EP93XX_VIC0 + 20)
#define IRQ_EP93XX_GPIO2MUX		(IRQ_EP93XX_VIC0 + 21)
#define IRQ_EP93XX_GPIO3MUX		(IRQ_EP93XX_VIC0 + 22)
#define IRQ_EP93XX_UART1RX		(IRQ_EP93XX_VIC0 + 23)
#define IRQ_EP93XX_UART1TX		(IRQ_EP93XX_VIC0 + 24)
#define IRQ_EP93XX_UART2RX		(IRQ_EP93XX_VIC0 + 25)
#define IRQ_EP93XX_UART2TX		(IRQ_EP93XX_VIC0 + 26)
#define IRQ_EP93XX_UART3RX		(IRQ_EP93XX_VIC0 + 27)
#define IRQ_EP93XX_UART3TX		(IRQ_EP93XX_VIC0 + 28)
#define IRQ_EP93XX_KEY			(IRQ_EP93XX_VIC0 + 29)
#define IRQ_EP93XX_TOUCH		(IRQ_EP93XX_VIC0 + 30)
#define EP93XX_VIC1_VALID_IRQ_MASK	0x7ffffffc

#define IRQ_EP93XX_VIC1			(IRQ_EP93XX_VIC0 + 32)

#define IRQ_EP93XX_EXT0			(IRQ_EP93XX_VIC1 + 0)
#define IRQ_EP93XX_EXT1			(IRQ_EP93XX_VIC1 + 1)
#define IRQ_EP93XX_EXT2			(IRQ_EP93XX_VIC1 + 2)
#define IRQ_EP93XX_64HZ			(IRQ_EP93XX_VIC1 + 3)
#define IRQ_EP93XX_WATCHDOG		(IRQ_EP93XX_VIC1 + 4)
#define IRQ_EP93XX_RTC			(IRQ_EP93XX_VIC1 + 5)
#define IRQ_EP93XX_IRDA			(IRQ_EP93XX_VIC1 + 6)
#define IRQ_EP93XX_ETHERNET		(IRQ_EP93XX_VIC1 + 7)
#define IRQ_EP93XX_EXT3			(IRQ_EP93XX_VIC1 + 8)
#define IRQ_EP93XX_PROG			(IRQ_EP93XX_VIC1 + 9)
#define IRQ_EP93XX_1HZ			(IRQ_EP93XX_VIC1 + 10)
#define IRQ_EP93XX_VSYNC		(IRQ_EP93XX_VIC1 + 11)
#define IRQ_EP93XX_VIDEO_FIFO		(IRQ_EP93XX_VIC1 + 12)
#define IRQ_EP93XX_SSP1RX		(IRQ_EP93XX_VIC1 + 13)
#define IRQ_EP93XX_SSP1TX		(IRQ_EP93XX_VIC1 + 14)
#define IRQ_EP93XX_GPIO4MUX		(IRQ_EP93XX_VIC1 + 15)
#define IRQ_EP93XX_GPIO5MUX		(IRQ_EP93XX_VIC1 + 16)
#define IRQ_EP93XX_GPIO6MUX		(IRQ_EP93XX_VIC1 + 17)
#define IRQ_EP93XX_GPIO7MUX		(IRQ_EP93XX_VIC1 + 18)
#define IRQ_EP93XX_TIMER3		(IRQ_EP93XX_VIC1 + 19)
#define IRQ_EP93XX_UART1		(IRQ_EP93XX_VIC1 + 20)
#define IRQ_EP93XX_SSP			(IRQ_EP93XX_VIC1 + 21)
#define IRQ_EP93XX_UART2		(IRQ_EP93XX_VIC1 + 22)
#define IRQ_EP93XX_UART3		(IRQ_EP93XX_VIC1 + 23)
#define IRQ_EP93XX_USB			(IRQ_EP93XX_VIC1 + 24)
#define IRQ_EP93XX_ETHERNET_PME		(IRQ_EP93XX_VIC1 + 25)
#define IRQ_EP93XX_DSP			(IRQ_EP93XX_VIC1 + 26)
#define IRQ_EP93XX_GPIO_AB		(IRQ_EP93XX_VIC1 + 27)
#define IRQ_EP93XX_SAI			(IRQ_EP93XX_VIC1 + 28)
#define EP93XX_VIC2_VALID_IRQ_MASK	0x1fffffff

#define NR_EP93XX_IRQS			(IRQ_EP93XX_VIC1 + 32 + 24)

#define EP93XX_BOARD_IRQ(x)		(NR_EP93XX_IRQS + (x))
#define EP93XX_BOARD_IRQS		32

#endif