code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/drivers/pcmcia/pxa2xx_colibri.c
 *
 * Driver for Toradex Colibri PXA270 CF socket
 *
 * Copyright (C) 2010 Marek Vasut <marek.vasut@gmail.com>
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/gpio.h>

#include <asm/mach-types.h>

#include <pcmcia/soc_common.h>

#define	COLIBRI270_RESET_GPIO	53
#define	COLIBRI270_PPEN_GPIO	107
#define	COLIBRI270_BVD1_GPIO	83
#define	COLIBRI270_BVD2_GPIO	82
#define	COLIBRI270_DETECT_GPIO	84
#define	COLIBRI270_READY_GPIO	1

#define	COLIBRI320_RESET_GPIO	77
#define	COLIBRI320_PPEN_GPIO	57
#define	COLIBRI320_BVD1_GPIO	53
#define	COLIBRI320_BVD2_GPIO	79
#define	COLIBRI320_DETECT_GPIO	81
#define	COLIBRI320_READY_GPIO	29

enum {
	DETECT = 0,
	READY = 1,
	BVD1 = 2,
	BVD2 = 3,
	PPEN = 4,
	RESET = 5,
};

/* Contents of this array are configured on-the-fly in init function */
static struct gpio colibri_pcmcia_gpios[] = {
	{ 0,	GPIOF_IN,	"PCMCIA Detect" },
	{ 0,	GPIOF_IN,	"PCMCIA Ready" },
	{ 0,	GPIOF_IN,	"PCMCIA BVD1" },
	{ 0,	GPIOF_IN,	"PCMCIA BVD2" },
	{ 0,	GPIOF_INIT_LOW,	"PCMCIA PPEN" },
	{ 0,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
};

static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
	int ret;

	ret = gpio_request_array(colibri_pcmcia_gpios,
				ARRAY_SIZE(colibri_pcmcia_gpios));
	if (ret)
		goto err1;

	skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpios[READY].gpio);
	skt->stat[SOC_STAT_CD].irq = gpio_to_irq(colibri_pcmcia_gpios[DETECT].gpio);
	skt->stat[SOC_STAT_CD].name = "PCMCIA CD";

err1:
	return ret;
}

static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
{
	gpio_free_array(colibri_pcmcia_gpios,
			ARRAY_SIZE(colibri_pcmcia_gpios));
}

static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
					struct pcmcia_state *state)
{

	state->detect = !!gpio_get_value(colibri_pcmcia_gpios[DETECT].gpio);
	state->ready  = !!gpio_get_value(colibri_pcmcia_gpios[READY].gpio);
	state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpios[BVD1].gpio);
	state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpios[BVD2].gpio);
	state->vs_3v  = 1;
	state->vs_Xv  = 0;
}

static int
colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
				const socket_state_t *state)
{
	gpio_set_value(colibri_pcmcia_gpios[PPEN].gpio,
			!(state->Vcc == 33 && state->Vpp < 50));
	gpio_set_value(colibri_pcmcia_gpios[RESET].gpio,
			state->flags & SS_RESET);
	return 0;
}

static struct pcmcia_low_level colibri_pcmcia_ops = {
	.owner			= THIS_MODULE,

	.first			= 0,
	.nr			= 1,

	.hw_init		= colibri_pcmcia_hw_init,
	.hw_shutdown		= colibri_pcmcia_hw_shutdown,

	.socket_state		= colibri_pcmcia_socket_state,
	.configure_socket	= colibri_pcmcia_configure_socket,
};

static struct platform_device *colibri_pcmcia_device;

static int __init colibri_pcmcia_init(void)
{
	int ret;

	if (!machine_is_colibri() && !machine_is_colibri320())
		return -ENODEV;

	colibri_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
	if (!colibri_pcmcia_device)
		return -ENOMEM;

	/* Colibri PXA270 */
	if (machine_is_colibri()) {
		colibri_pcmcia_gpios[RESET].gpio	= COLIBRI270_RESET_GPIO;
		colibri_pcmcia_gpios[PPEN].gpio		= COLIBRI270_PPEN_GPIO;
		colibri_pcmcia_gpios[BVD1].gpio		= COLIBRI270_BVD1_GPIO;
		colibri_pcmcia_gpios[BVD2].gpio		= COLIBRI270_BVD2_GPIO;
		colibri_pcmcia_gpios[DETECT].gpio	= COLIBRI270_DETECT_GPIO;
		colibri_pcmcia_gpios[READY].gpio	= COLIBRI270_READY_GPIO;
	/* Colibri PXA320 */
	} else if (machine_is_colibri320()) {
		colibri_pcmcia_gpios[RESET].gpio	= COLIBRI320_RESET_GPIO;
		colibri_pcmcia_gpios[PPEN].gpio		= COLIBRI320_PPEN_GPIO;
		colibri_pcmcia_gpios[BVD1].gpio		= COLIBRI320_BVD1_GPIO;
		colibri_pcmcia_gpios[BVD2].gpio		= COLIBRI320_BVD2_GPIO;
		colibri_pcmcia_gpios[DETECT].gpio	= COLIBRI320_DETECT_GPIO;
		colibri_pcmcia_gpios[READY].gpio	= COLIBRI320_READY_GPIO;
	}

	ret = platform_device_add_data(colibri_pcmcia_device,
		&colibri_pcmcia_ops, sizeof(colibri_pcmcia_ops));

	if (!ret)
		ret = platform_device_add(colibri_pcmcia_device);

	if (ret)
		platform_device_put(colibri_pcmcia_device);

	return ret;
}

static void __exit colibri_pcmcia_exit(void)
{
	platform_device_unregister(colibri_pcmcia_device);
}

module_init(colibri_pcmcia_init);
module_exit(colibri_pcmcia_exit);

MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
MODULE_DESCRIPTION("PCMCIA support for Toradex Colibri PXA270/PXA320");
MODULE_ALIAS("platform:pxa2xx-pcmcia");
MODULE_LICENSE("GPL");


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-pxa/income.c
 *
 * Support for Income s.r.o. SH-Dmaster PXA270 SBC
 *
 * Copyright (C) 2010
 * Marek Vasut <marek.vasut@gmail.com>
 * Pavel Revak <palo@bielyvlk.sk>
 */

#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/gpio/machine.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>
#include <linux/platform_data/i2c-pxa.h>

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

#include <linux/platform_data/mmc-pxamci.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include "pxa27x.h"
#include "pxa27x-udc.h"
#include <linux/platform_data/video-pxafb.h>

#include "devices.h"
#include "generic.h"

#define GPIO114_INCOME_ETH_IRQ  (114)
#define GPIO0_INCOME_SD_DETECT  (0)
#define GPIO0_INCOME_SD_RO      (1)
#define GPIO54_INCOME_LED_A     (54)
#define GPIO55_INCOME_LED_B     (55)
#define GPIO113_INCOME_TS_IRQ   (113)

/******************************************************************************
 * SD/MMC card controller
 ******************************************************************************/
#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
static struct pxamci_platform_data income_mci_platform_data = {
	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
	.detect_delay_ms	= 200,
};

static struct gpiod_lookup_table income_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		/* Card detect on GPIO 0 */
		GPIO_LOOKUP("gpio-pxa", GPIO0_INCOME_SD_DETECT,
			    "cd", GPIO_ACTIVE_LOW),
		/* Write protect on GPIO 1 */
		GPIO_LOOKUP("gpio-pxa", GPIO0_INCOME_SD_RO,
			    "wp", GPIO_ACTIVE_LOW),
		{ },
	},
};

static void __init income_mmc_init(void)
{
	gpiod_add_lookup_table(&income_mci_gpio_table);
	pxa_set_mci_info(&income_mci_platform_data);
}
#else
static inline void income_mmc_init(void) {}
#endif

/******************************************************************************
 * USB Host
 ******************************************************************************/
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static struct pxaohci_platform_data income_ohci_info = {
	.port_mode	= PMM_PERPORT_MODE,
	.flags		= ENABLE_PORT1 | POWER_CONTROL_LOW | POWER_SENSE_LOW,
};

static void __init income_uhc_init(void)
{
	pxa_set_ohci_info(&income_ohci_info);
}
#else
static inline void income_uhc_init(void) {}
#endif

/******************************************************************************
 * LED
 ******************************************************************************/
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
struct gpio_led income_gpio_leds[] = {
	{
		.name			= "income:green:leda",
		.default_trigger	= "none",
		.gpio			= GPIO54_INCOME_LED_A,
		.active_low		= 1,
	},
	{
		.name			= "income:green:ledb",
		.default_trigger	= "none",
		.gpio			= GPIO55_INCOME_LED_B,
		.active_low		= 1,
	}
};

static struct gpio_led_platform_data income_gpio_led_info = {
	.leds		= income_gpio_leds,
	.num_leds	= ARRAY_SIZE(income_gpio_leds),
};

static struct platform_device income_leds = {
	.name	= "leds-gpio",
	.id	= -1,
	.dev	= {
		.platform_data	= &income_gpio_led_info,
	}
};

static void __init income_led_init(void)
{
	platform_device_register(&income_leds);
}
#else
static inline void income_led_init(void) {}
#endif

/******************************************************************************
 * I2C
 ******************************************************************************/
#if defined(CONFIG_I2C_PXA) || defined(CONFIG_I2C_PXA_MODULE)
static struct i2c_board_info __initdata income_i2c_devs[] = {
	{
		I2C_BOARD_INFO("ds1340", 0x68),
	}, {
		I2C_BOARD_INFO("lm75", 0x4f),
	},
};

static void __init income_i2c_init(void)
{
	pxa_set_i2c_info(NULL);
	pxa27x_set_i2c_power_info(NULL);
	i2c_register_board_info(0, ARRAY_AND_SIZE(income_i2c_devs));
}
#else
static inline void income_i2c_init(void) {}
#endif

/******************************************************************************
 * Framebuffer
 ******************************************************************************/
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct pxafb_mode_info income_lcd_modes[] = {
{
	.pixclock	= 144700,
	.xres		= 320,
	.yres		= 240,
	.bpp		= 32,
	.depth		= 18,

	.left_margin	= 10,
	.right_margin	= 10,
	.upper_margin	= 7,
	.lower_margin	= 8,

	.hsync_len	= 20,
	.vsync_len	= 2,

	.sync		= FB_SYNC_VERT_HIGH_ACT,
},
};

static struct pxafb_mach_info income_lcd_screen = {
	.modes		= income_lcd_modes,
	.num_modes	= ARRAY_SIZE(income_lcd_modes),
	.lcd_conn	= LCD_COLOR_TFT_18BPP | LCD_PCLK_EDGE_FALL,
};

static void __init income_lcd_init(void)
{
	pxa_set_fb_info(NULL, &income_lcd_screen);
}
#else
static inline void income_lcd_init(void) {}
#endif

/******************************************************************************
 * Backlight
 ******************************************************************************/
#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
static struct pwm_lookup income_pwm_lookup[] = {
	PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight.0", NULL, 1000000,
		   PWM_POLARITY_NORMAL),
};

static struct platform_pwm_backlight_data income_backlight_data = {
	.max_brightness	= 0x3ff,
	.dft_brightness	= 0x1ff,
};

static struct platform_device income_backlight = {
	.name	= "pwm-backlight",
	.dev	= {
		.parent		= &pxa27x_device_pwm0.dev,
		.platform_data	= &income_backlight_data,
	},
};

static void __init income_pwm_init(void)
{
	pwm_add_table(income_pwm_lookup, ARRAY_SIZE(income_pwm_lookup));
	platform_device_register(&income_backlight);
}
#else
static inline void income_pwm_init(void) {}
#endif

void __init colibri_pxa270_income_boardinit(void)
{
	pxa_set_ffuart_info(NULL);
	pxa_set_btuart_info(NULL);
	pxa_set_stuart_info(NULL);

	income_mmc_init();
	income_uhc_init();
	income_led_init();
	income_i2c_init();
	income_lcd_init();
	income_pwm_init();
}

repo_name: angery/linux


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  linux/arch/arm/mach-pxa/colibri-pxa270.c
 *
 *  Support for Toradex PXA270 based Colibri module
 *  Daniel Mack <daniel@caiaq.de>
 *  Marek Vasut <marek.vasut@gmail.com>
 */

#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/platform_device.h>
#include <linux/regulator/machine.h>
#include <linux/ucb1400.h>

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

#include <linux/platform_data/asoc-pxa.h>
#include "colibri.h"
#include "pxa27x.h"

#include "devices.h"
#include "generic.h"

/******************************************************************************
 * Evaluation board MFP
 ******************************************************************************/
#ifdef	 CONFIG_MACH_COLIBRI_EVALBOARD
static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {
	/* MMC */
	GPIO32_MMC_CLK,
	GPIO92_MMC_DAT_0,
	GPIO109_MMC_DAT_1,
	GPIO110_MMC_DAT_2,
	GPIO111_MMC_DAT_3,
	GPIO112_MMC_CMD,
	GPIO0_GPIO,	/* SD detect */

	/* FFUART */
	GPIO39_FFUART_TXD,
	GPIO34_FFUART_RXD,

	/* UHC */
	GPIO88_USBH1_PWR,
	GPIO89_USBH1_PEN,
	GPIO119_USBH2_PWR,
	GPIO120_USBH2_PEN,

	/* PCMCIA */
	GPIO85_nPCE_1,
	GPIO54_nPCE_2,
	GPIO55_nPREG,
	GPIO50_nPIOR,
	GPIO51_nPIOW,
	GPIO49_nPWE,
	GPIO48_nPOE,
	GPIO57_nIOIS16,
	GPIO56_nPWAIT,
	GPIO104_PSKTSEL,
	GPIO53_GPIO,	/* RESET */
	GPIO83_GPIO,	/* BVD1 */
	GPIO82_GPIO,	/* BVD2 */
	GPIO1_GPIO,	/* READY */
	GPIO84_GPIO,	/* DETECT */
	GPIO107_GPIO,	/* PPEN */

	/* I2C */
	GPIO117_I2C_SCL,
	GPIO118_I2C_SDA,
};
#else
static mfp_cfg_t colibri_pxa270_evalboard_pin_config[] __initdata = {};
#endif

#ifdef	CONFIG_MACH_COLIBRI_PXA270_INCOME
static mfp_cfg_t income_pin_config[] __initdata = {
	/* MMC */
	GPIO32_MMC_CLK,
	GPIO92_MMC_DAT_0,
	GPIO109_MMC_DAT_1,
	GPIO110_MMC_DAT_2,
	GPIO111_MMC_DAT_3,
	GPIO112_MMC_CMD,
	GPIO0_GPIO,	/* SD detect */
	GPIO1_GPIO,	/* SD read-only */

	/* FFUART */
	GPIO39_FFUART_TXD,
	GPIO34_FFUART_RXD,

	/* BFUART */
	GPIO42_BTUART_RXD,
	GPIO43_BTUART_TXD,
	GPIO45_BTUART_RTS,

	/* STUART */
	GPIO46_STUART_RXD,
	GPIO47_STUART_TXD,

	/* UHC */
	GPIO88_USBH1_PWR,
	GPIO89_USBH1_PEN,

	/* LCD */
	GPIOxx_LCD_TFT_16BPP,

	/* PWM */
	GPIO16_PWM0_OUT,

	/* I2C */
	GPIO117_I2C_SCL,
	GPIO118_I2C_SDA,

	/* LED */
	GPIO54_GPIO,	/* LED A */
	GPIO55_GPIO,	/* LED B */
};
#else
static mfp_cfg_t income_pin_config[] __initdata = {};
#endif

/******************************************************************************
 * Pin configuration
 ******************************************************************************/
static mfp_cfg_t colibri_pxa270_pin_config[] __initdata = {
	/* Ethernet */
	GPIO78_nCS_2,	/* Ethernet CS */
	GPIO114_GPIO,	/* Ethernet IRQ */

	/* AC97 */
	GPIO28_AC97_BITCLK,
	GPIO29_AC97_SDATA_IN_0,
	GPIO30_AC97_SDATA_OUT,
	GPIO31_AC97_SYNC,
	GPIO95_AC97_nRESET,
	GPIO98_AC97_SYSCLK,
	GPIO113_GPIO,	/* Touchscreen IRQ */
};

/******************************************************************************
 * NOR Flash
 ******************************************************************************/
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
static struct mtd_partition colibri_partitions[] = {
	{
		.name =		"Bootloader",
		.offset =	0x00000000,
		.size =		0x00040000,
		.mask_flags =	MTD_WRITEABLE	/* force read-only */
	}, {
		.name =		"Kernel",
		.offset =	0x00040000,
		.size =		0x00400000,
		.mask_flags =	0
	}, {
		.name =		"Rootfs",
		.offset =	0x00440000,
		.size =		MTDPART_SIZ_FULL,
		.mask_flags =	0
	}
};

static struct physmap_flash_data colibri_flash_data[] = {
	{
		.width		= 4,			/* bankwidth in bytes */
		.parts		= colibri_partitions,
		.nr_parts	= ARRAY_SIZE(colibri_partitions)
	}
};

static struct resource colibri_pxa270_flash_resource = {
	.start	= PXA_CS0_PHYS,
	.end	= PXA_CS0_PHYS + SZ_32M - 1,
	.flags	= IORESOURCE_MEM,
};

static struct platform_device colibri_pxa270_flash_device = {
	.name	= "physmap-flash",
	.id	= 0,
	.dev 	= {
		.platform_data = colibri_flash_data,
	},
	.resource = &colibri_pxa270_flash_resource,
	.num_resources = 1,
};

static void __init colibri_pxa270_nor_init(void)
{
	platform_device_register(&colibri_pxa270_flash_device);
}
#else
static inline void colibri_pxa270_nor_init(void) {}
#endif

/******************************************************************************
 * Ethernet
 ******************************************************************************/
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
static struct resource colibri_pxa270_dm9000_resources[] = {
	{
		.start	= PXA_CS2_PHYS,
		.end	= PXA_CS2_PHYS + 3,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= PXA_CS2_PHYS + 4,
		.end	= PXA_CS2_PHYS + 4 + 500,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ),
		.end	= PXA_GPIO_TO_IRQ(GPIO114_COLIBRI_PXA270_ETH_IRQ),
		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_RISING,
	},
};

static struct platform_device colibri_pxa270_dm9000_device = {
	.name		= "dm9000",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(colibri_pxa270_dm9000_resources),
	.resource	= colibri_pxa270_dm9000_resources,
};

static void __init colibri_pxa270_eth_init(void)
{
	platform_device_register(&colibri_pxa270_dm9000_device);
}
#else
static inline void colibri_pxa270_eth_init(void) {}
#endif

/******************************************************************************
 * Audio and Touchscreen
 ******************************************************************************/
#if	defined(CONFIG_TOUCHSCREEN_UCB1400) || \
	defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
static pxa2xx_audio_ops_t colibri_pxa270_ac97_pdata = {
	.reset_gpio	= 95,
};

static struct ucb1400_pdata colibri_pxa270_ucb1400_pdata = {
	.irq		= PXA_GPIO_TO_IRQ(GPIO113_COLIBRI_PXA270_TS_IRQ),
};

static struct platform_device colibri_pxa270_ucb1400_device = {
	.name		= "ucb1400_core",
	.id		= -1,
	.dev		= {
		.platform_data = &colibri_pxa270_ucb1400_pdata,
	},
};

static void __init colibri_pxa270_tsc_init(void)
{
	pxa_set_ac97_info(&colibri_pxa270_ac97_pdata);
	platform_device_register(&colibri_pxa270_ucb1400_device);
}
#else
static inline void colibri_pxa270_tsc_init(void) {}
#endif

static int colibri_pxa270_baseboard;
core_param(colibri_pxa270_baseboard, colibri_pxa270_baseboard, int, 0444);

static void __init colibri_pxa270_init(void)
{
	pxa2xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa270_pin_config));

	colibri_pxa270_nor_init();
	colibri_pxa270_eth_init();
	colibri_pxa270_tsc_init();

	switch (colibri_pxa270_baseboard) {
	case COLIBRI_EVALBOARD:
		pxa2xx_mfp_config(ARRAY_AND_SIZE(
			colibri_pxa270_evalboard_pin_config));
		colibri_evalboard_init();
		break;
	case COLIBRI_PXA270_INCOME:
		pxa2xx_mfp_config(ARRAY_AND_SIZE(income_pin_config));
		colibri_pxa270_income_boardinit();
		break;
	default:
		printk(KERN_ERR "Illegal colibri_pxa270_baseboard type %d\n",
				colibri_pxa270_baseboard);
	}

	regulator_has_full_constraints();
}

/* The "Income s.r.o. SH-Dmaster PXA270 SBC" board can be booted either
 * with the INCOME mach type or with COLIBRI and the kernel parameter
 * "colibri_pxa270_baseboard=1"
 */
static void __init colibri_pxa270_income_init(void)
{
	colibri_pxa270_baseboard = COLIBRI_PXA270_INCOME;
	colibri_pxa270_init();
}

MACHINE_START(COLIBRI, "Toradex Colibri PXA270")
	.atag_offset	= 0x100,
	.init_machine	= colibri_pxa270_init,
	.map_io		= pxa27x_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa27x_init_irq,
	.handle_irq	= pxa27x_handle_irq,
	.init_time	= pxa_timer_init,
	.restart	= pxa_restart,
MACHINE_END

MACHINE_START(INCOME, "Income s.r.o. SH-Dmaster PXA270 SBC")
	.atag_offset	= 0x100,
	.init_machine	= colibri_pxa270_income_init,
	.map_io		= pxa27x_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa27x_init_irq,
	.handle_irq	= pxa27x_handle_irq,
	.init_time	= pxa_timer_init,
	.restart	= pxa_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  arch/arm/mach-pxa/colibri-pxa300.c
 *
 *  Support for Toradex PXA300/310 based Colibri module
 *
 *  Daniel Mack <daniel@caiaq.de>
 *  Matthias Meier <matthias.j.meier@gmx.net>
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>
#include <linux/soc/pxa/cpu.h>

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

#include "pxa300.h"
#include "colibri.h"
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/asoc-pxa.h>

#include "generic.h"
#include "devices.h"

#ifdef CONFIG_MACH_COLIBRI_EVALBOARD
static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = {
	/* MMC */
	GPIO7_MMC1_CLK,
	GPIO14_MMC1_CMD,
	GPIO3_MMC1_DAT0,
	GPIO4_MMC1_DAT1,
	GPIO5_MMC1_DAT2,
	GPIO6_MMC1_DAT3,
	GPIO13_GPIO,	/* GPIO13_COLIBRI_PXA300_SD_DETECT */

	/* UHC */
	GPIO0_2_USBH_PEN,
	GPIO1_2_USBH_PWR,
	GPIO77_USB_P3_1,
	GPIO78_USB_P3_2,
	GPIO79_USB_P3_3,
	GPIO80_USB_P3_4,
	GPIO81_USB_P3_5,
	GPIO82_USB_P3_6,

	/* I2C */
	GPIO21_I2C_SCL,
	GPIO22_I2C_SDA,
};
#else
static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = {};
#endif

#if defined(CONFIG_AX88796)
#define COLIBRI_ETH_IRQ_GPIO	mfp_to_gpio(GPIO26_GPIO)
/*
 * Asix AX88796 Ethernet
 */
static struct ax_plat_data colibri_asix_platdata = {
	.flags		= 0, /* defined later */
	.wordlength	= 2,
};

static struct resource colibri_asix_resource[] = {
	[0] = {
		.start = PXA3xx_CS2_PHYS,
		.end   = PXA3xx_CS2_PHYS + (0x20 * 2) - 1,
		.flags = IORESOURCE_MEM,
	},
	[1] = {
		.start = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO),
		.end   = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO),
		.flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
	}
};

static struct platform_device asix_device = {
	.name		= "ax88796",
	.id		= 0,
	.num_resources 	= ARRAY_SIZE(colibri_asix_resource),
	.resource	= colibri_asix_resource,
	.dev		= {
		.platform_data = &colibri_asix_platdata
	}
};

static mfp_cfg_t colibri_pxa300_eth_pin_config[] __initdata = {
	GPIO1_nCS2,			/* AX88796 chip select */
	GPIO26_GPIO | MFP_PULL_HIGH	/* AX88796 IRQ */
};

static void __init colibri_pxa300_init_eth(void)
{
	colibri_pxa3xx_init_eth(&colibri_asix_platdata);
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_eth_pin_config));
	platform_device_register(&asix_device);
}
#else
static inline void __init colibri_pxa300_init_eth(void) {}
#endif /* CONFIG_AX88796 */

#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static mfp_cfg_t colibri_pxa300_lcd_pin_config[] __initdata = {
	GPIO54_LCD_LDD_0,
	GPIO55_LCD_LDD_1,
	GPIO56_LCD_LDD_2,
	GPIO57_LCD_LDD_3,
	GPIO58_LCD_LDD_4,
	GPIO59_LCD_LDD_5,
	GPIO60_LCD_LDD_6,
	GPIO61_LCD_LDD_7,
	GPIO62_LCD_LDD_8,
	GPIO63_LCD_LDD_9,
	GPIO64_LCD_LDD_10,
	GPIO65_LCD_LDD_11,
	GPIO66_LCD_LDD_12,
	GPIO67_LCD_LDD_13,
	GPIO68_LCD_LDD_14,
	GPIO69_LCD_LDD_15,
	GPIO70_LCD_LDD_16,
	GPIO71_LCD_LDD_17,
	GPIO62_LCD_CS_N,
	GPIO72_LCD_FCLK,
	GPIO73_LCD_LCLK,
	GPIO74_LCD_PCLK,
	GPIO75_LCD_BIAS,
	GPIO76_LCD_VSYNC,
};

static void __init colibri_pxa300_init_lcd(void)
{
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_lcd_pin_config));
}

#else
static inline void colibri_pxa300_init_lcd(void) {}
#endif /* CONFIG_FB_PXA || CONFIG_FB_PXA_MODULE */

#if defined(CONFIG_SND_AC97_CODEC) || defined(CONFIG_SND_AC97_CODEC_MODULE)
static mfp_cfg_t colibri_pxa310_ac97_pin_config[] __initdata = {
	GPIO24_AC97_SYSCLK,
	GPIO23_AC97_nACRESET,
	GPIO25_AC97_SDATA_IN_0,
	GPIO27_AC97_SDATA_OUT,
	GPIO28_AC97_SYNC,
	GPIO29_AC97_BITCLK
};

static inline void __init colibri_pxa310_init_ac97(void)
{
	/* no AC97 codec on Colibri PXA300 */
	if (!cpu_is_pxa310())
		return;

	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa310_ac97_pin_config));
	pxa_set_ac97_info(NULL);
}
#else
static inline void colibri_pxa310_init_ac97(void) {}
#endif

void __init colibri_pxa300_init(void)
{
	colibri_pxa300_init_eth();
	colibri_pxa3xx_init_nand();
	colibri_pxa300_init_lcd();
	colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO39_GPIO));
	colibri_pxa310_init_ac97();

	/* Evalboard init */
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa300_evalboard_pin_config));
	colibri_evalboard_init();
}

MACHINE_START(COLIBRI300, "Toradex Colibri PXA300")
	.atag_offset	= 0x100,
	.init_machine	= colibri_pxa300_init,
	.map_io		= pxa3xx_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa3xx_init_irq,
	.handle_irq	= pxa3xx_handle_irq,
	.init_time	= pxa_timer_init,
	.restart	= pxa_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  arch/arm/mach-pxa/colibri-pxa320.c
 *
 *  Support for Toradex PXA320/310 based Colibri module
 *
 *  Daniel Mack <daniel@caiaq.de>
 *  Matthias Meier <matthias.j.meier@gmx.net>
 */

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

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

#include "pxa320.h"
#include "colibri.h"
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/asoc-pxa.h>
#include "pxa27x-udc.h"
#include "udc.h"

#include "generic.h"
#include "devices.h"

#ifdef	CONFIG_MACH_COLIBRI_EVALBOARD
static mfp_cfg_t colibri_pxa320_evalboard_pin_config[] __initdata = {
	/* MMC */
	GPIO22_MMC1_CLK,
	GPIO23_MMC1_CMD,
	GPIO18_MMC1_DAT0,
	GPIO19_MMC1_DAT1,
	GPIO20_MMC1_DAT2,
	GPIO21_MMC1_DAT3,
	GPIO28_GPIO,	/* SD detect */

	/* UART 1 configuration (may be set by bootloader) */
	GPIO99_UART1_CTS,
	GPIO104_UART1_RTS,
	GPIO97_UART1_RXD,
	GPIO98_UART1_TXD,
	GPIO101_UART1_DTR,
	GPIO103_UART1_DSR,
	GPIO100_UART1_DCD,
	GPIO102_UART1_RI,

	/* UART 2 configuration */
	GPIO109_UART2_CTS,
	GPIO112_UART2_RTS,
	GPIO110_UART2_RXD,
	GPIO111_UART2_TXD,

	/* UART 3 configuration */
	GPIO30_UART3_RXD,
	GPIO31_UART3_TXD,

	/* UHC */
	GPIO2_2_USBH_PEN,
	GPIO3_2_USBH_PWR,

	/* I2C */
	GPIO32_I2C_SCL,
	GPIO33_I2C_SDA,

	/* PCMCIA */
	MFP_CFG(GPIO59, AF7),	/* PRST ; AF7 to tristate */
	MFP_CFG(GPIO61, AF7),	/* PCE1 ; AF7 to tristate */
	MFP_CFG(GPIO60, AF7),	/* PCE2 ; AF7 to tristate */
	MFP_CFG(GPIO62, AF7),	/* PCD ; AF7 to tristate */
	MFP_CFG(GPIO56, AF7),	/* PSKTSEL ; AF7 to tristate */
	GPIO27_GPIO,		/* RDnWR ; input/tristate */
	GPIO50_GPIO,		/* PREG ; input/tristate */
	GPIO2_RDY,
	GPIO5_NPIOR,
	GPIO6_NPIOW,
	GPIO7_NPIOS16,
	GPIO8_NPWAIT,
	GPIO29_GPIO,		/* PRDY (READY GPIO) */
	GPIO57_GPIO,		/* PPEN (POWER GPIO) */
	GPIO81_GPIO,		/* PCD (DETECT GPIO) */
	GPIO77_GPIO,		/* PRST (RESET GPIO) */
	GPIO53_GPIO,		/* PBVD1 */
	GPIO79_GPIO,		/* PBVD2 */
	GPIO54_GPIO,		/* POE */
};
#else
static mfp_cfg_t colibri_pxa320_evalboard_pin_config[] __initdata = {};
#endif

#if defined(CONFIG_AX88796)
#define COLIBRI_ETH_IRQ_GPIO	mfp_to_gpio(GPIO36_GPIO)
/*
 * Asix AX88796 Ethernet
 */
static struct ax_plat_data colibri_asix_platdata = {
	.flags		= 0, /* defined later */
	.wordlength	= 2,
};

static struct resource colibri_asix_resource[] = {
	[0] = {
		.start = PXA3xx_CS2_PHYS,
		.end   = PXA3xx_CS2_PHYS + (0x20 * 2) - 1,
		.flags = IORESOURCE_MEM,
	},
	[1] = {
		.start = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO),
		.end   = PXA_GPIO_TO_IRQ(COLIBRI_ETH_IRQ_GPIO),
		.flags = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
	}
};

static struct platform_device asix_device = {
	.name		= "ax88796",
	.id		= 0,
	.num_resources 	= ARRAY_SIZE(colibri_asix_resource),
	.resource	= colibri_asix_resource,
	.dev		= {
		.platform_data = &colibri_asix_platdata
	}
};

static mfp_cfg_t colibri_pxa320_eth_pin_config[] __initdata = {
	GPIO3_nCS2,			/* AX88796 chip select */
	GPIO36_GPIO | MFP_PULL_HIGH	/* AX88796 IRQ */
};

static void __init colibri_pxa320_init_eth(void)
{
	colibri_pxa3xx_init_eth(&colibri_asix_platdata);
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_eth_pin_config));
	platform_device_register(&asix_device);
}
#else
static inline void __init colibri_pxa320_init_eth(void) {}
#endif /* CONFIG_AX88796 */

#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
static struct gpiod_lookup_table gpio_vbus_gpiod_table = {
	.dev_id = "gpio-vbus",
	.table = {
		GPIO_LOOKUP("gpio-pxa", MFP_PIN_GPIO96,
			    "vbus", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct platform_device colibri_pxa320_gpio_vbus = {
	.name	= "gpio-vbus",
	.id	= -1,
};

static void colibri_pxa320_udc_command(int cmd)
{
	if (cmd == PXA2XX_UDC_CMD_CONNECT)
		UP2OCR = UP2OCR_HXOE | UP2OCR_DPPUE;
	else if (cmd == PXA2XX_UDC_CMD_DISCONNECT)
		UP2OCR = UP2OCR_HXOE;
}

static struct pxa2xx_udc_mach_info colibri_pxa320_udc_info __initdata = {
	.udc_command		= colibri_pxa320_udc_command,
	.gpio_pullup		= -1,
};

static void __init colibri_pxa320_init_udc(void)
{
	pxa_set_udc_info(&colibri_pxa320_udc_info);
	gpiod_add_lookup_table(&gpio_vbus_gpiod_table);
	platform_device_register(&colibri_pxa320_gpio_vbus);
}
#else
static inline void colibri_pxa320_init_udc(void) {}
#endif

#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static mfp_cfg_t colibri_pxa320_lcd_pin_config[] __initdata = {
	GPIO6_2_LCD_LDD_0,
	GPIO7_2_LCD_LDD_1,
	GPIO8_2_LCD_LDD_2,
	GPIO9_2_LCD_LDD_3,
	GPIO10_2_LCD_LDD_4,
	GPIO11_2_LCD_LDD_5,
	GPIO12_2_LCD_LDD_6,
	GPIO13_2_LCD_LDD_7,
	GPIO63_LCD_LDD_8,
	GPIO64_LCD_LDD_9,
	GPIO65_LCD_LDD_10,
	GPIO66_LCD_LDD_11,
	GPIO67_LCD_LDD_12,
	GPIO68_LCD_LDD_13,
	GPIO69_LCD_LDD_14,
	GPIO70_LCD_LDD_15,
	GPIO71_LCD_LDD_16,
	GPIO72_LCD_LDD_17,
	GPIO73_LCD_CS_N,
	GPIO74_LCD_VSYNC,
	GPIO14_2_LCD_FCLK,
	GPIO15_2_LCD_LCLK,
	GPIO16_2_LCD_PCLK,
	GPIO17_2_LCD_BIAS,
};

static void __init colibri_pxa320_init_lcd(void)
{
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_lcd_pin_config));
}
#else
static inline void colibri_pxa320_init_lcd(void) {}
#endif

#if	defined(CONFIG_SND_AC97_CODEC) || \
	defined(CONFIG_SND_AC97_CODEC_MODULE)
static mfp_cfg_t colibri_pxa320_ac97_pin_config[] __initdata = {
	GPIO34_AC97_SYSCLK,
	GPIO35_AC97_SDATA_IN_0,
	GPIO37_AC97_SDATA_OUT,
	GPIO38_AC97_SYNC,
	GPIO39_AC97_BITCLK,
	GPIO40_AC97_nACRESET
};

static inline void __init colibri_pxa320_init_ac97(void)
{
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_ac97_pin_config));
	pxa_set_ac97_info(NULL);
}
#else
static inline void colibri_pxa320_init_ac97(void) {}
#endif

void __init colibri_pxa320_init(void)
{
	colibri_pxa320_init_eth();
	colibri_pxa3xx_init_nand();
	colibri_pxa320_init_lcd();
	colibri_pxa3xx_init_lcd(mfp_to_gpio(GPIO49_GPIO));
	colibri_pxa320_init_ac97();
	colibri_pxa320_init_udc();

	/* Evalboard init */
	pxa3xx_mfp_config(ARRAY_AND_SIZE(colibri_pxa320_evalboard_pin_config));
	colibri_evalboard_init();
}

MACHINE_START(COLIBRI320, "Toradex Colibri PXA320")
	.atag_offset	= 0x100,
	.init_machine	= colibri_pxa320_init,
	.map_io		= pxa3xx_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa3xx_init_irq,
	.handle_irq	= pxa3xx_handle_irq,
	.init_time	= pxa_timer_init,
	.restart	= pxa_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  arch/arm/mach-pxa/colibri-pxa3xx.c
 *
 *  Common functions for all Toradex PXA3xx modules
 *
 *  Daniel Mack <daniel@caiaq.de>
 */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/etherdevice.h>
#include <asm/mach-types.h>
#include <linux/sizes.h>
#include <asm/system_info.h>
#include <asm/mach/arch.h>
#include <asm/mach/irq.h>
#include "pxa3xx-regs.h"
#include "mfp-pxa300.h"
#include "colibri.h"
#include <linux/platform_data/mmc-pxamci.h>
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/mtd-nand-pxa3xx.h>

#include "generic.h"
#include "devices.h"

#if defined(CONFIG_AX88796)
#define ETHER_ADDR_LEN 6
static u8 ether_mac_addr[ETHER_ADDR_LEN];

void __init colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data)
{
	int i;
	u64 serial = ((u64) system_serial_high << 32) | system_serial_low;

	/*
	 * If the bootloader passed in a serial boot tag, which contains a
	 * valid ethernet MAC, pass it to the interface. Toradex ships the
	 * modules with their own bootloader which provides a valid MAC
	 * this way.
	 */

	for (i = 0; i < ETHER_ADDR_LEN; i++) {
		ether_mac_addr[i] = serial & 0xff;
		serial >>= 8;
	}

	if (is_valid_ether_addr(ether_mac_addr)) {
		plat_data->flags |= AXFLG_MAC_FROMPLATFORM;
		plat_data->mac_addr = ether_mac_addr;
		printk(KERN_INFO "%s(): taking MAC from serial boot tag\n",
			__func__);
	} else {
		plat_data->flags |= AXFLG_MAC_FROMDEV;
		printk(KERN_INFO "%s(): no valid serial boot tag found, "
			"taking MAC from device\n", __func__);
	}
}
#endif

#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static int lcd_bl_pin;

/*
 * LCD panel (Sharp LQ043T3DX02)
 */
static void colibri_lcd_backlight(int on)
{
	gpio_set_value(lcd_bl_pin, !!on);
}

static struct pxafb_mode_info sharp_lq43_mode = {
	.pixclock	= 101936,
	.xres		= 480,
	.yres		= 272,
	.bpp		= 32,
	.depth		= 18,
	.hsync_len      = 41,
	.left_margin    = 2,
	.right_margin   = 2,
	.vsync_len      = 10,
	.upper_margin   = 2,
	.lower_margin   = 2,
	.sync	   	= 0,
	.cmap_greyscale = 0,
};

static struct pxafb_mach_info sharp_lq43_info = {
	.modes		= &sharp_lq43_mode,
	.num_modes	= 1,
	.cmap_inverse	= 0,
	.cmap_static	= 0,
	.lcd_conn	= LCD_COLOR_TFT_18BPP,
	.pxafb_backlight_power = colibri_lcd_backlight,
};

void __init colibri_pxa3xx_init_lcd(int bl_pin)
{
	lcd_bl_pin = bl_pin;
	gpio_request(bl_pin, "lcd backlight");
	gpio_direction_output(bl_pin, 0);
	pxa_set_fb_info(NULL, &sharp_lq43_info);
}
#endif

#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
static struct mtd_partition colibri_nand_partitions[] = {
	{
		.name        = "bootloader",
		.offset      = 0,
		.size        = SZ_512K,
		.mask_flags  = MTD_WRITEABLE, /* force read-only */
	},
	{
		.name        = "kernel",
		.offset      = MTDPART_OFS_APPEND,
		.size        = SZ_4M,
		.mask_flags  = MTD_WRITEABLE, /* force read-only */
	},
	{
		.name        = "reserved",
		.offset      = MTDPART_OFS_APPEND,
		.size        = SZ_1M,
		.mask_flags  = MTD_WRITEABLE, /* force read-only */
	},
	{
		.name        = "fs",
		.offset      = MTDPART_OFS_APPEND,
		.size        = MTDPART_SIZ_FULL,
	},
};

static struct pxa3xx_nand_platform_data colibri_nand_info = {
	.keep_config	= 1,
	.parts		= colibri_nand_partitions,
	.nr_parts	= ARRAY_SIZE(colibri_nand_partitions),
};

void __init colibri_pxa3xx_init_nand(void)
{
	pxa3xx_set_nand_info(&colibri_nand_info);
}
#endif


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

#include <net/ax88796.h>
#include "mfp.h"

/*
 * base board glue for PXA270 module
 */

enum {
	COLIBRI_EVALBOARD = 0,
	COLIBRI_PXA270_INCOME,
};

#if defined(CONFIG_MACH_COLIBRI_EVALBOARD)
extern void colibri_evalboard_init(void);
#else
static inline void colibri_evalboard_init(void) {}
#endif

#if defined(CONFIG_MACH_COLIBRI_PXA270_INCOME)
extern void colibri_pxa270_income_boardinit(void);
#else
static inline void colibri_pxa270_income_boardinit(void) {}
#endif

/*
 * common settings for all modules
 */

#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
extern void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin);
#else
static inline void colibri_pxa3xx_init_mmc(mfp_cfg_t *pins, int len, int detect_pin) {}
#endif

#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
extern void colibri_pxa3xx_init_lcd(int bl_pin);
#else
static inline void colibri_pxa3xx_init_lcd(int bl_pin) {}
#endif

#if defined(CONFIG_AX88796)
extern void colibri_pxa3xx_init_eth(struct ax_plat_data *plat_data);
#endif

#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
extern void colibri_pxa3xx_init_nand(void);
#else
static inline void colibri_pxa3xx_init_nand(void) {}
#endif

/* physical memory regions */
#define COLIBRI_SDRAM_BASE	0xa0000000      /* SDRAM region */

/* GPIO definitions for Colibri PXA270 */
#define GPIO114_COLIBRI_PXA270_ETH_IRQ	114
#define GPIO0_COLIBRI_PXA270_SD_DETECT	0
#define GPIO113_COLIBRI_PXA270_TS_IRQ	113

/* GPIO definitions for Colibri PXA300/310 */
#define GPIO13_COLIBRI_PXA300_SD_DETECT	13

/* GPIO definitions for Colibri PXA320 */
#define GPIO28_COLIBRI_PXA320_SD_DETECT	28

#endif /* _COLIBRI_H_ */


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Support for Sharp SL-C7xx PDAs
 * Models: SL-C700 (Corgi), SL-C750 (Shepherd), SL-C760 (Husky)
 *
 * Copyright (c) 2004-2005 Richard Purdie
 *
 * Based on Sharp's 2.4 kernel patches/lubbock.c
 */

#include <linux/kernel.h>
#include <linux/module.h>	/* symbol_get ; symbol_put */
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/major.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/mmc/host.h>
#include <linux/mtd/physmap.h>
#include <linux/pm.h>
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/backlight.h>
#include <linux/i2c.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/io.h>
#include <linux/regulator/machine.h>
#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
#include <linux/spi/corgi_lcd.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/mtd/sharpsl.h>
#include <linux/input/matrix_keypad.h>
#include <linux/gpio_keys.h>
#include <linux/memblock.h>
#include <video/w100fb.h>

#include <asm/setup.h>
#include <asm/memory.h>
#include <asm/mach-types.h>
#include <asm/irq.h>

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

#include "pxa25x.h"
#include <linux/platform_data/irda-pxaficp.h>
#include <linux/platform_data/mmc-pxamci.h>
#include "udc.h"
#include "corgi.h"
#include "sharpsl_pm.h"

#include <asm/mach/sharpsl_param.h>
#include <asm/hardware/scoop.h>

#include "generic.h"
#include "devices.h"

static unsigned long corgi_pin_config[] __initdata = {
	/* Static Memory I/O */
	GPIO78_nCS_2,	/* w100fb */
	GPIO80_nCS_4,	/* scoop */

	/* SSP1 */
	GPIO23_SSP1_SCLK,
	GPIO25_SSP1_TXD,
	GPIO26_SSP1_RXD,
	GPIO24_GPIO,	/* CORGI_GPIO_ADS7846_CS - SFRM as chip select */

	/* I2S */
	GPIO28_I2S_BITCLK_OUT,
	GPIO29_I2S_SDATA_IN,
	GPIO30_I2S_SDATA_OUT,
	GPIO31_I2S_SYNC,
	GPIO32_I2S_SYSCLK,

	/* Infra-Red */
	GPIO47_FICP_TXD,
	GPIO46_FICP_RXD,

	/* FFUART */
	GPIO40_FFUART_DTR,
	GPIO41_FFUART_RTS,
	GPIO39_FFUART_TXD,
	GPIO37_FFUART_DSR,
	GPIO34_FFUART_RXD,
	GPIO35_FFUART_CTS,

	/* PC Card */
	GPIO48_nPOE,
	GPIO49_nPWE,
	GPIO50_nPIOR,
	GPIO51_nPIOW,
	GPIO52_nPCE_1,
	GPIO53_nPCE_2,
	GPIO54_nPSKTSEL,
	GPIO55_nPREG,
	GPIO56_nPWAIT,
	GPIO57_nIOIS16,

	/* MMC */
	GPIO6_MMC_CLK,
	GPIO8_MMC_CS0,

	/* GPIO Matrix Keypad */
	GPIO66_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 0 */
	GPIO67_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 1 */
	GPIO68_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 2 */
	GPIO69_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 3 */
	GPIO70_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 4 */
	GPIO71_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 5 */
	GPIO72_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 6 */
	GPIO73_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 7 */
	GPIO74_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 8 */
	GPIO75_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 9 */
	GPIO76_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 10 */
	GPIO77_GPIO | MFP_LPM_DRIVE_HIGH,	/* column 11 */
	GPIO58_GPIO,	/* row 0 */
	GPIO59_GPIO,	/* row 1 */
	GPIO60_GPIO,	/* row 2 */
	GPIO61_GPIO,	/* row 3 */
	GPIO62_GPIO,	/* row 4 */
	GPIO63_GPIO,	/* row 5 */
	GPIO64_GPIO,	/* row 6 */
	GPIO65_GPIO,	/* row 7 */

	/* GPIO */
	GPIO9_GPIO,				/* CORGI_GPIO_nSD_DETECT */
	GPIO7_GPIO,				/* CORGI_GPIO_nSD_WP */
	GPIO11_GPIO | WAKEUP_ON_EDGE_BOTH,	/* CORGI_GPIO_MAIN_BAT_{LOW,COVER} */
	GPIO13_GPIO | MFP_LPM_KEEP_OUTPUT,	/* CORGI_GPIO_LED_ORANGE */
	GPIO21_GPIO,				/* CORGI_GPIO_ADC_TEMP */
	GPIO22_GPIO,				/* CORGI_GPIO_IR_ON */
	GPIO33_GPIO,				/* CORGI_GPIO_SD_PWR */
	GPIO38_GPIO | MFP_LPM_KEEP_OUTPUT,	/* CORGI_GPIO_CHRG_ON */
	GPIO43_GPIO | MFP_LPM_KEEP_OUTPUT,	/* CORGI_GPIO_CHRG_UKN */
	GPIO44_GPIO,				/* CORGI_GPIO_HSYNC */

	GPIO0_GPIO | WAKEUP_ON_EDGE_BOTH,	/* CORGI_GPIO_KEY_INT */
	GPIO1_GPIO | WAKEUP_ON_EDGE_RISE,	/* CORGI_GPIO_AC_IN */
	GPIO3_GPIO | WAKEUP_ON_EDGE_BOTH,	/* CORGI_GPIO_WAKEUP */
};

/*
 * Corgi SCOOP Device
 */
static struct resource corgi_scoop_resources[] = {
	[0] = {
		.start		= 0x10800000,
		.end		= 0x10800fff,
		.flags		= IORESOURCE_MEM,
	},
};

static struct scoop_config corgi_scoop_setup = {
	.io_dir 	= CORGI_SCOOP_IO_DIR,
	.io_out		= CORGI_SCOOP_IO_OUT,
	.gpio_base	= CORGI_SCOOP_GPIO_BASE,
};

struct platform_device corgiscoop_device = {
	.name		= "sharp-scoop",
	.id		= -1,
	.dev		= {
 		.platform_data	= &corgi_scoop_setup,
	},
	.num_resources	= ARRAY_SIZE(corgi_scoop_resources),
	.resource	= corgi_scoop_resources,
};

static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = {
{
	.dev        = &corgiscoop_device.dev,
	.irq        = CORGI_IRQ_GPIO_CF_IRQ,
	.cd_irq     = CORGI_IRQ_GPIO_CF_CD,
	.cd_irq_str = "PCMCIA0 CD",
},
};

static struct scoop_pcmcia_config corgi_pcmcia_config = {
	.devs         = &corgi_pcmcia_scoop[0],
	.num_devs     = 1,
};

static struct w100_mem_info corgi_fb_mem = {
	.ext_cntl          = 0x00040003,
	.sdram_mode_reg    = 0x00650021,
	.ext_timing_cntl   = 0x10002a4a,
	.io_cntl           = 0x7ff87012,
	.size              = 0x1fffff,
};

static struct w100_gen_regs corgi_fb_regs = {
	.lcd_format    = 0x00000003,
	.lcdd_cntl1    = 0x01CC0000,
	.lcdd_cntl2    = 0x0003FFFF,
	.genlcd_cntl1  = 0x00FFFF0D,
	.genlcd_cntl2  = 0x003F3003,
	.genlcd_cntl3  = 0x000102aa,
};

static struct w100_gpio_regs corgi_fb_gpio = {
	.init_data1   = 0x000000bf,
	.init_data2   = 0x00000000,
	.gpio_dir1    = 0x00000000,
	.gpio_oe1     = 0x03c0feff,
	.gpio_dir2    = 0x00000000,
	.gpio_oe2     = 0x00000000,
};

static struct w100_mode corgi_fb_modes[] = {
{
	.xres            = 480,
	.yres            = 640,
	.left_margin     = 0x56,
	.right_margin    = 0x55,
	.upper_margin    = 0x03,
	.lower_margin    = 0x00,
	.crtc_ss         = 0x82360056,
	.crtc_ls         = 0xA0280000,
	.crtc_gs         = 0x80280028,
	.crtc_vpos_gs    = 0x02830002,
	.crtc_rev        = 0x00400008,
	.crtc_dclk       = 0xA0000000,
	.crtc_gclk       = 0x8015010F,
	.crtc_goe        = 0x80100110,
	.crtc_ps1_active = 0x41060010,
	.pll_freq        = 75,
	.fast_pll_freq   = 100,
	.sysclk_src      = CLK_SRC_PLL,
	.sysclk_divider  = 0,
	.pixclk_src      = CLK_SRC_PLL,
	.pixclk_divider  = 2,
	.pixclk_divider_rotated = 6,
},{
	.xres            = 240,
	.yres            = 320,
	.left_margin     = 0x27,
	.right_margin    = 0x2e,
	.upper_margin    = 0x01,
	.lower_margin    = 0x00,
	.crtc_ss         = 0x81170027,
	.crtc_ls         = 0xA0140000,
	.crtc_gs         = 0xC0140014,
	.crtc_vpos_gs    = 0x00010141,
	.crtc_rev        = 0x00400008,
	.crtc_dclk       = 0xA0000000,
	.crtc_gclk       = 0x8015010F,
	.crtc_goe        = 0x80100110,
	.crtc_ps1_active = 0x41060010,
	.pll_freq        = 0,
	.fast_pll_freq   = 0,
	.sysclk_src      = CLK_SRC_XTAL,
	.sysclk_divider  = 0,
	.pixclk_src      = CLK_SRC_XTAL,
	.pixclk_divider  = 1,
	.pixclk_divider_rotated = 1,
},

};

static struct w100fb_mach_info corgi_fb_info = {
	.init_mode  = INIT_MODE_ROTATED,
	.mem        = &corgi_fb_mem,
	.regs       = &corgi_fb_regs,
	.modelist   = &corgi_fb_modes[0],
	.num_modes  = 2,
	.gpio       = &corgi_fb_gpio,
	.xtal_freq  = 12500000,
	.xtal_dbl   = 0,
};

static struct resource corgi_fb_resources[] = {
	[0] = {
		.start   = 0x08000000,
		.end     = 0x08ffffff,
		.flags   = IORESOURCE_MEM,
	},
};

static struct platform_device corgifb_device = {
	.name           = "w100fb",
	.id             = -1,
	.num_resources	= ARRAY_SIZE(corgi_fb_resources),
	.resource	= corgi_fb_resources,
	.dev            = {
		.platform_data = &corgi_fb_info,
	},

};

/*
 * Corgi Keyboard Device
 */
#define CORGI_KEY_CALENDER	KEY_F1
#define CORGI_KEY_ADDRESS	KEY_F2
#define CORGI_KEY_FN		KEY_F3
#define CORGI_KEY_CANCEL	KEY_F4
#define CORGI_KEY_OFF		KEY_SUSPEND
#define CORGI_KEY_EXOK		KEY_F5
#define CORGI_KEY_EXCANCEL	KEY_F6
#define CORGI_KEY_EXJOGDOWN	KEY_F7
#define CORGI_KEY_EXJOGUP	KEY_F8
#define CORGI_KEY_JAP1		KEY_LEFTCTRL
#define CORGI_KEY_JAP2		KEY_LEFTALT
#define CORGI_KEY_MAIL		KEY_F10
#define CORGI_KEY_OK		KEY_F11
#define CORGI_KEY_MENU		KEY_F12

static const uint32_t corgikbd_keymap[] = {
	KEY(0, 1, KEY_1),
	KEY(0, 2, KEY_3),
	KEY(0, 3, KEY_5),
	KEY(0, 4, KEY_6),
	KEY(0, 5, KEY_7),
	KEY(0, 6, KEY_9),
	KEY(0, 7, KEY_0),
	KEY(0, 8, KEY_BACKSPACE),
	KEY(1, 1, KEY_2),
	KEY(1, 2, KEY_4),
	KEY(1, 3, KEY_R),
	KEY(1, 4, KEY_Y),
	KEY(1, 5, KEY_8),
	KEY(1, 6, KEY_I),
	KEY(1, 7, KEY_O),
	KEY(1, 8, KEY_P),
	KEY(2, 0, KEY_TAB),
	KEY(2, 1, KEY_Q),
	KEY(2, 2, KEY_E),
	KEY(2, 3, KEY_T),
	KEY(2, 4, KEY_G),
	KEY(2, 5, KEY_U),
	KEY(2, 6, KEY_J),
	KEY(2, 7, KEY_K),
	KEY(3, 0, CORGI_KEY_CALENDER),
	KEY(3, 1, KEY_W),
	KEY(3, 2, KEY_S),
	KEY(3, 3, KEY_F),
	KEY(3, 4, KEY_V),
	KEY(3, 5, KEY_H),
	KEY(3, 6, KEY_M),
	KEY(3, 7, KEY_L),
	KEY(3, 9, KEY_RIGHTSHIFT),
	KEY(4, 0, CORGI_KEY_ADDRESS),
	KEY(4, 1, KEY_A),
	KEY(4, 2, KEY_D),
	KEY(4, 3, KEY_C),
	KEY(4, 4, KEY_B),
	KEY(4, 5, KEY_N),
	KEY(4, 6, KEY_DOT),
	KEY(4, 8, KEY_ENTER),
	KEY(4, 10, KEY_LEFTSHIFT),
	KEY(5, 0, CORGI_KEY_MAIL),
	KEY(5, 1, KEY_Z),
	KEY(5, 2, KEY_X),
	KEY(5, 3, KEY_MINUS),
	KEY(5, 4, KEY_SPACE),
	KEY(5, 5, KEY_COMMA),
	KEY(5, 7, KEY_UP),
	KEY(5, 11, CORGI_KEY_FN),
	KEY(6, 0, KEY_SYSRQ),
	KEY(6, 1, CORGI_KEY_JAP1),
	KEY(6, 2, CORGI_KEY_JAP2),
	KEY(6, 3, CORGI_KEY_CANCEL),
	KEY(6, 4, CORGI_KEY_OK),
	KEY(6, 5, CORGI_KEY_MENU),
	KEY(6, 6, KEY_LEFT),
	KEY(6, 7, KEY_DOWN),
	KEY(6, 8, KEY_RIGHT),
	KEY(7, 0, CORGI_KEY_OFF),
	KEY(7, 1, CORGI_KEY_EXOK),
	KEY(7, 2, CORGI_KEY_EXCANCEL),
	KEY(7, 3, CORGI_KEY_EXJOGDOWN),
	KEY(7, 4, CORGI_KEY_EXJOGUP),
};

static struct matrix_keymap_data corgikbd_keymap_data = {
	.keymap		= corgikbd_keymap,
	.keymap_size	= ARRAY_SIZE(corgikbd_keymap),
};

static const int corgikbd_row_gpios[] =
		{ 58, 59, 60, 61, 62, 63, 64, 65 };
static const int corgikbd_col_gpios[] =
		{ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 };

static struct matrix_keypad_platform_data corgikbd_pdata = {
	.keymap_data		= &corgikbd_keymap_data,
	.row_gpios		= corgikbd_row_gpios,
	.col_gpios		= corgikbd_col_gpios,
	.num_row_gpios		= ARRAY_SIZE(corgikbd_row_gpios),
	.num_col_gpios		= ARRAY_SIZE(corgikbd_col_gpios),
	.col_scan_delay_us	= 10,
	.debounce_ms		= 10,
	.wakeup			= 1,
};

static struct platform_device corgikbd_device = {
	.name		= "matrix-keypad",
	.id		= -1,
	.dev		= {
		.platform_data = &corgikbd_pdata,
	},
};

static struct gpio_keys_button corgi_gpio_keys[] = {
	{
		.type	= EV_SW,
		.code	= SW_LID,
		.gpio	= CORGI_GPIO_SWA,
		.desc	= "Lid close switch",
		.debounce_interval = 500,
	},
	{
		.type	= EV_SW,
		.code	= SW_TABLET_MODE,
		.gpio	= CORGI_GPIO_SWB,
		.desc	= "Tablet mode switch",
		.debounce_interval = 500,
	},
	{
		.type	= EV_SW,
		.code	= SW_HEADPHONE_INSERT,
		.gpio	= CORGI_GPIO_AK_INT,
		.desc	= "HeadPhone insert",
		.debounce_interval = 500,
	},
};

static struct gpio_keys_platform_data corgi_gpio_keys_platform_data = {
	.buttons	= corgi_gpio_keys,
	.nbuttons	= ARRAY_SIZE(corgi_gpio_keys),
	.poll_interval	= 250,
};

static struct platform_device corgi_gpio_keys_device = {
	.name	= "gpio-keys-polled",
	.id	= -1,
	.dev	= {
		.platform_data	= &corgi_gpio_keys_platform_data,
	},
};

/*
 * Corgi LEDs
 */
static struct gpio_led corgi_gpio_leds[] = {
	{
		.name			= "corgi:amber:charge",
		.default_trigger	= "sharpsl-charge",
		.gpio			= CORGI_GPIO_LED_ORANGE,
	},
	{
		.name			= "corgi:green:mail",
		.default_trigger	= "nand-disk",
		.gpio			= CORGI_GPIO_LED_GREEN,
	},
};

static struct gpio_led_platform_data corgi_gpio_leds_info = {
	.leds		= corgi_gpio_leds,
	.num_leds	= ARRAY_SIZE(corgi_gpio_leds),
};

static struct platform_device corgiled_device = {
	.name		= "leds-gpio",
	.id		= -1,
	.dev		= {
		.platform_data = &corgi_gpio_leds_info,
	},
};

static struct gpiod_lookup_table corgi_audio_gpio_table = {
	.dev_id = "corgi-audio",
	.table = {
		GPIO_LOOKUP("sharp-scoop",
			    CORGI_GPIO_MUTE_L - CORGI_SCOOP_GPIO_BASE,
			    "mute-l", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("sharp-scoop",
			    CORGI_GPIO_MUTE_R - CORGI_SCOOP_GPIO_BASE,
			    "mute-r", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("sharp-scoop",
			    CORGI_GPIO_APM_ON - CORGI_SCOOP_GPIO_BASE,
			    "apm-on", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("sharp-scoop",
			    CORGI_GPIO_MIC_BIAS - CORGI_SCOOP_GPIO_BASE,
			    "mic-bias", GPIO_ACTIVE_HIGH),
		{ },
	},
};

/*
 * Corgi Audio
 */
static struct platform_device corgi_audio_device = {
	.name	= "corgi-audio",
	.id	= -1,
};

/*
 * MMC/SD Device
 *
 * The card detect interrupt isn't debounced so we delay it by 250ms
 * to give the card a chance to fully insert/eject.
 */
static struct pxamci_platform_data corgi_mci_platform_data = {
	.detect_delay_ms	= 250,
	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
};

static struct gpiod_lookup_table corgi_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		/* Card detect on GPIO 9 */
		GPIO_LOOKUP("gpio-pxa", CORGI_GPIO_nSD_DETECT,
			    "cd", GPIO_ACTIVE_LOW),
		/* Write protect on GPIO 7 */
		GPIO_LOOKUP("gpio-pxa", CORGI_GPIO_nSD_WP,
			    "wp", GPIO_ACTIVE_LOW),
		/* Power on GPIO 33 */
		GPIO_LOOKUP("gpio-pxa", CORGI_GPIO_SD_PWR,
			    "power", GPIO_ACTIVE_HIGH),
		{ },
	},
};

/*
 * Irda
 */
static struct pxaficp_platform_data corgi_ficp_platform_data = {
	.gpio_pwdown		= CORGI_GPIO_IR_ON,
	.transceiver_cap	= IR_SIRMODE | IR_OFF,
};

/*
 * USB Device Controller
 */
static struct pxa2xx_udc_mach_info udc_info __initdata = {
	/* no connect GPIO; corgi can't tell connection status */
	.gpio_pullup		= CORGI_GPIO_USB_PULLUP,
};

#if IS_ENABLED(CONFIG_SPI_PXA2XX)
static struct pxa2xx_spi_controller corgi_spi_info = {
	.num_chipselect	= 3,
};

static struct gpiod_lookup_table corgi_spi_gpio_table = {
	.dev_id = "spi1",
	.table = {
		GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_ADS7846_CS, "cs", 0, GPIO_ACTIVE_LOW),
		GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_LCDCON_CS, "cs", 1, GPIO_ACTIVE_LOW),
		GPIO_LOOKUP_IDX("gpio-pxa", CORGI_GPIO_MAX1111_CS, "cs", 2, GPIO_ACTIVE_LOW),
		{ },
	},
};

static void corgi_wait_for_hsync(void)
{
	while (gpio_get_value(CORGI_GPIO_HSYNC))
		cpu_relax();

	while (!gpio_get_value(CORGI_GPIO_HSYNC))
		cpu_relax();
}

static struct ads7846_platform_data corgi_ads7846_info = {
	.model			= 7846,
	.vref_delay_usecs	= 100,
	.x_plate_ohms		= 419,
	.y_plate_ohms		= 486,
	.gpio_pendown		= CORGI_GPIO_TP_INT,
	.wait_for_sync		= corgi_wait_for_hsync,
};

static void corgi_bl_kick_battery(void)
{
	void (*kick_batt)(void);

	kick_batt = symbol_get(sharpsl_battery_kick);
	if (kick_batt) {
		kick_batt();
		symbol_put(sharpsl_battery_kick);
	}
}

static struct gpiod_lookup_table corgi_lcdcon_gpio_table = {
	.dev_id = "spi1.1",
	.table = {
		GPIO_LOOKUP("gpio-pxa", CORGI_GPIO_BACKLIGHT_CONT,
			    "BL_CONT", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct corgi_lcd_platform_data corgi_lcdcon_info = {
	.init_mode		= CORGI_LCD_MODE_VGA,
	.max_intensity		= 0x2f,
	.default_intensity	= 0x1f,
	.limit_mask		= 0x0b,
	.kick_battery		= corgi_bl_kick_battery,
};

static struct spi_board_info corgi_spi_devices[] = {
	{
		.modalias	= "ads7846",
		.max_speed_hz	= 1200000,
		.bus_num	= 1,
		.chip_select	= 0,
		.platform_data	= &corgi_ads7846_info,
		.irq		= PXA_GPIO_TO_IRQ(CORGI_GPIO_TP_INT),
	}, {
		.modalias	= "corgi-lcd",
		.max_speed_hz	= 50000,
		.bus_num	= 1,
		.chip_select	= 1,
		.platform_data	= &corgi_lcdcon_info,
	}, {
		.modalias	= "max1111",
		.max_speed_hz	= 450000,
		.bus_num	= 1,
		.chip_select	= 2,
	},
};

static void __init corgi_init_spi(void)
{
	gpiod_add_lookup_table(&corgi_spi_gpio_table);
	pxa2xx_set_spi_info(1, &corgi_spi_info);
	gpiod_add_lookup_table(&corgi_lcdcon_gpio_table);
	spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices));
}
#else
static inline void corgi_init_spi(void) {}
#endif

static uint8_t scan_ff_pattern[] = { 0xff, 0xff };

static struct nand_bbt_descr sharpsl_bbt = {
	.options = 0,
	.offs = 4,
	.len = 2,
	.pattern = scan_ff_pattern
};

static const char * const probes[] = {
	"cmdlinepart",
	"ofpart",
	"sharpslpart",
	NULL,
};

static struct sharpsl_nand_platform_data sharpsl_nand_platform_data = {
	.badblock_pattern	= &sharpsl_bbt,
	.part_parsers		= probes,
};

static struct resource sharpsl_nand_resources[] = {
	{
		.start	= 0x0C000000,
		.end	= 0x0C000FFF,
		.flags	= IORESOURCE_MEM,
	},
};

static struct platform_device sharpsl_nand_device = {
	.name		= "sharpsl-nand",
	.id		= -1,
	.resource	= sharpsl_nand_resources,
	.num_resources	= ARRAY_SIZE(sharpsl_nand_resources),
	.dev.platform_data	= &sharpsl_nand_platform_data,
};

static struct mtd_partition sharpsl_rom_parts[] = {
	{
		.name	="Boot PROM Filesystem",
		.offset	= 0x00120000,
		.size	= MTDPART_SIZ_FULL,
	},
};

static struct physmap_flash_data sharpsl_rom_data = {
	.width		= 2,
	.nr_parts	= ARRAY_SIZE(sharpsl_rom_parts),
	.parts		= sharpsl_rom_parts,
};

static struct resource sharpsl_rom_resources[] = {
	{
		.start	= 0x00000000,
		.end	= 0x007fffff,
		.flags	= IORESOURCE_MEM,
	},
};

static struct platform_device sharpsl_rom_device = {
	.name	= "physmap-flash",
	.id	= -1,
	.resource = sharpsl_rom_resources,
	.num_resources = ARRAY_SIZE(sharpsl_rom_resources),
	.dev.platform_data = &sharpsl_rom_data,
};

static struct platform_device *devices[] __initdata = {
	&corgiscoop_device,
	&corgifb_device,
	&corgi_gpio_keys_device,
	&corgikbd_device,
	&corgiled_device,
	&corgi_audio_device,
	&sharpsl_nand_device,
	&sharpsl_rom_device,
};

static struct i2c_board_info __initdata corgi_i2c_devices[] = {
	{ I2C_BOARD_INFO("wm8731", 0x1b) },
};

static void corgi_poweroff(void)
{
	if (!machine_is_corgi())
		/* Green LED off tells the bootloader to halt */
		gpio_set_value(CORGI_GPIO_LED_GREEN, 0);

	pxa_restart(REBOOT_HARD, NULL);
}

static void corgi_restart(enum reboot_mode mode, const char *cmd)
{
	if (!machine_is_corgi())
		/* Green LED on tells the bootloader to reboot */
		gpio_set_value(CORGI_GPIO_LED_GREEN, 1);

	pxa_restart(REBOOT_HARD, cmd);
}

static void __init corgi_init(void)
{
	pm_power_off = corgi_poweroff;

	/* Stop 3.6MHz and drive HIGH to PCMCIA and CS */
	PCFR |= PCFR_OPDE;

	pxa2xx_mfp_config(ARRAY_AND_SIZE(corgi_pin_config));

	/* allow wakeup from various GPIOs */
	gpio_set_wake(CORGI_GPIO_KEY_INT, 1);
	gpio_set_wake(CORGI_GPIO_WAKEUP, 1);
	gpio_set_wake(CORGI_GPIO_AC_IN, 1);
	gpio_set_wake(CORGI_GPIO_CHRG_FULL, 1);

	if (!machine_is_corgi())
		gpio_set_wake(CORGI_GPIO_MAIN_BAT_LOW, 1);

	pxa_set_ffuart_info(NULL);
	pxa_set_btuart_info(NULL);
	pxa_set_stuart_info(NULL);

	corgi_init_spi();

 	pxa_set_udc_info(&udc_info);
	gpiod_add_lookup_table(&corgi_mci_gpio_table);
	gpiod_add_lookup_table(&corgi_audio_gpio_table);
	pxa_set_mci_info(&corgi_mci_platform_data);
	pxa_set_ficp_info(&corgi_ficp_platform_data);
	pxa_set_i2c_info(NULL);
	i2c_register_board_info(0, ARRAY_AND_SIZE(corgi_i2c_devices));

	platform_scoop_config = &corgi_pcmcia_config;

	platform_add_devices(devices, ARRAY_SIZE(devices));

	regulator_has_full_constraints();
}

static void __init fixup_corgi(struct tag *tags, char **cmdline)
{
	sharpsl_save_param();
	if (machine_is_corgi())
		memblock_add(0xa0000000, SZ_32M);
	else
		memblock_add(0xa0000000, SZ_64M);
}

#ifdef CONFIG_MACH_CORGI
MACHINE_START(CORGI, "SHARP Corgi")
	.fixup		= fixup_corgi,
	.map_io		= pxa25x_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa25x_init_irq,
	.handle_irq	= pxa25x_handle_irq,
	.init_machine	= corgi_init,
	.init_time	= pxa_timer_init,
	.restart	= corgi_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_SHEPHERD
MACHINE_START(SHEPHERD, "SHARP Shepherd")
	.fixup		= fixup_corgi,
	.map_io		= pxa25x_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa25x_init_irq,
	.handle_irq	= pxa25x_handle_irq,
	.init_machine	= corgi_init,
	.init_time	= pxa_timer_init,
	.restart	= corgi_restart,
MACHINE_END
#endif

#ifdef CONFIG_MACH_HUSKY
MACHINE_START(HUSKY, "SHARP Husky")
	.fixup		= fixup_corgi,
	.map_io		= pxa25x_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq	= pxa25x_init_irq,
	.handle_irq	= pxa25x_handle_irq,
	.init_machine	= corgi_init,
	.init_time	= pxa_timer_init,
	.restart	= corgi_restart,
MACHINE_END
#endif


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Hardware specific definitions for SL-C7xx series of PDAs
 *
 * Copyright (c) 2004-2005 Richard Purdie
 *
 * Based on Sharp's 2.4 kernel patches
 */
#ifndef __ASM_ARCH_CORGI_H
#define __ASM_ARCH_CORGI_H  1

#include "irqs.h" /* PXA_NR_BUILTIN_GPIO */

/*
 * Corgi (Non Standard) GPIO Definitions
 */
#define CORGI_GPIO_KEY_INT			(0)	/* Keyboard Interrupt */
#define CORGI_GPIO_AC_IN			(1) /* Charger Detection */
#define CORGI_GPIO_WAKEUP			(3) /* System wakeup notification? */
#define CORGI_GPIO_AK_INT			(4)	/* Headphone Jack Control Interrupt */
#define CORGI_GPIO_TP_INT			(5)	/* Touch Panel Interrupt */
#define CORGI_GPIO_nSD_WP			(7) /* SD Write Protect? */
#define CORGI_GPIO_nSD_DETECT		(9) /* MMC/SD Card Detect */
#define CORGI_GPIO_nSD_INT			(10) /* SD Interrupt for SDIO? */
#define CORGI_GPIO_MAIN_BAT_LOW		(11) /* Main Battery Low Notification */
#define CORGI_GPIO_BAT_COVER		(11) /* Battery Cover Detect */
#define CORGI_GPIO_LED_ORANGE		(13) /* Orange LED Control */
#define CORGI_GPIO_CF_CD			(14) /* Compact Flash Card Detect */
#define CORGI_GPIO_CHRG_FULL		(16) /* Charging Complete Notification */
#define CORGI_GPIO_CF_IRQ			(17) /* Compact Flash Interrupt */
#define CORGI_GPIO_LCDCON_CS		(19) /* LCD Control Chip Select */
#define CORGI_GPIO_MAX1111_CS		(20) /* MAX1111 Chip Select */
#define CORGI_GPIO_ADC_TEMP_ON		(21) /* Select battery voltage or temperature */
#define CORGI_GPIO_IR_ON			(22) /* Enable IR Transceiver */
#define CORGI_GPIO_ADS7846_CS		(24) /* ADS7846 Chip Select */
#define CORGI_GPIO_SD_PWR			(33) /* MMC/SD Power */
#define CORGI_GPIO_CHRG_ON			(38) /* Enable battery Charging */
#define CORGI_GPIO_DISCHARGE_ON		(42) /* Enable battery Discharge */
#define CORGI_GPIO_CHRG_UKN			(43) /* Unknown Charging (Bypass Control?) */
#define CORGI_GPIO_HSYNC			(44) /* LCD HSync Pulse */
#define CORGI_GPIO_USB_PULLUP		(45) /* USB show presence to host */

/*
 * Corgi Keyboard Definitions
 */
#define CORGI_KEY_STROBE_NUM		(12)
#define CORGI_KEY_SENSE_NUM			(8)
#define CORGI_GPIO_ALL_STROBE_BIT	(0x00003ffc)
#define CORGI_GPIO_HIGH_SENSE_BIT	(0xfc000000)
#define CORGI_GPIO_HIGH_SENSE_RSHIFT	(26)
#define CORGI_GPIO_LOW_SENSE_BIT	(0x00000003)
#define CORGI_GPIO_LOW_SENSE_LSHIFT	(6)
#define CORGI_GPIO_STROBE_BIT(a)	GPIO_bit(66+(a))
#define CORGI_GPIO_SENSE_BIT(a)		GPIO_bit(58+(a))
#define CORGI_GAFR_ALL_STROBE_BIT	(0x0ffffff0)
#define CORGI_GAFR_HIGH_SENSE_BIT	(0xfff00000)
#define CORGI_GAFR_LOW_SENSE_BIT	(0x0000000f)
#define CORGI_GPIO_KEY_SENSE(a)		(58+(a))
#define CORGI_GPIO_KEY_STROBE(a)	(66+(a))

/*
 * Corgi Interrupts
 */
#define CORGI_IRQ_GPIO_KEY_INT		PXA_GPIO_TO_IRQ(0)
#define CORGI_IRQ_GPIO_AC_IN		PXA_GPIO_TO_IRQ(1)
#define CORGI_IRQ_GPIO_WAKEUP		PXA_GPIO_TO_IRQ(3)
#define CORGI_IRQ_GPIO_AK_INT		PXA_GPIO_TO_IRQ(4)
#define CORGI_IRQ_GPIO_TP_INT		PXA_GPIO_TO_IRQ(5)
#define CORGI_IRQ_GPIO_nSD_DETECT	PXA_GPIO_TO_IRQ(9)
#define CORGI_IRQ_GPIO_nSD_INT		PXA_GPIO_TO_IRQ(10)
#define CORGI_IRQ_GPIO_MAIN_BAT_LOW	PXA_GPIO_TO_IRQ(11)
#define CORGI_IRQ_GPIO_CF_CD		PXA_GPIO_TO_IRQ(14)
#define CORGI_IRQ_GPIO_CHRG_FULL	PXA_GPIO_TO_IRQ(16)	/* Battery fully charged */
#define CORGI_IRQ_GPIO_CF_IRQ		PXA_GPIO_TO_IRQ(17)
#define CORGI_IRQ_GPIO_KEY_SENSE(a)	PXA_GPIO_TO_IRQ(58+(a))	/* Keyboard Sense lines */

/*
 * Corgi SCOOP GPIOs and Config
 */
#define CORGI_SCP_LED_GREEN		SCOOP_GPCR_PA11
#define CORGI_SCP_SWA			SCOOP_GPCR_PA12  /* Hinge Switch A */
#define CORGI_SCP_SWB			SCOOP_GPCR_PA13  /* Hinge Switch B */
#define CORGI_SCP_MUTE_L		SCOOP_GPCR_PA14
#define CORGI_SCP_MUTE_R		SCOOP_GPCR_PA15
#define CORGI_SCP_AKIN_PULLUP	SCOOP_GPCR_PA16
#define CORGI_SCP_APM_ON		SCOOP_GPCR_PA17
#define CORGI_SCP_BACKLIGHT_CONT	SCOOP_GPCR_PA18
#define CORGI_SCP_MIC_BIAS		SCOOP_GPCR_PA19

#define CORGI_SCOOP_IO_DIR	( CORGI_SCP_LED_GREEN | CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R | \
			CORGI_SCP_AKIN_PULLUP | CORGI_SCP_APM_ON | CORGI_SCP_BACKLIGHT_CONT | \
			CORGI_SCP_MIC_BIAS )
#define CORGI_SCOOP_IO_OUT	( CORGI_SCP_MUTE_L | CORGI_SCP_MUTE_R )

#define CORGI_SCOOP_GPIO_BASE		(PXA_NR_BUILTIN_GPIO)
#define CORGI_GPIO_LED_GREEN		(CORGI_SCOOP_GPIO_BASE + 0)
#define CORGI_GPIO_SWA			(CORGI_SCOOP_GPIO_BASE + 1)  /* Hinge Switch A */
#define CORGI_GPIO_SWB			(CORGI_SCOOP_GPIO_BASE + 2)  /* Hinge Switch B */
#define CORGI_GPIO_MUTE_L		(CORGI_SCOOP_GPIO_BASE + 3)
#define CORGI_GPIO_MUTE_R		(CORGI_SCOOP_GPIO_BASE + 4)
#define CORGI_GPIO_AKIN_PULLUP		(CORGI_SCOOP_GPIO_BASE + 5)
#define CORGI_GPIO_APM_ON		(CORGI_SCOOP_GPIO_BASE + 6)
#define CORGI_GPIO_BACKLIGHT_CONT	(CORGI_SCOOP_GPIO_BASE + 7)
#define CORGI_GPIO_MIC_BIAS		(CORGI_SCOOP_GPIO_BASE + 8)

#endif /* __ASM_ARCH_CORGI_H  */


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Battery and Power Management code for the Sharp SL-C7xx
 *
 * Copyright (c) 2005 Richard Purdie
 */

#include <linux/module.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/gpio-pxa.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/apm-emulation.h>
#include <linux/io.h>

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

#include "corgi.h"
#include "pxa2xx-regs.h"
#include "sharpsl_pm.h"

#include "generic.h"

#define SHARPSL_CHARGE_ON_VOLT         0x99  /* 2.9V */
#define SHARPSL_CHARGE_ON_TEMP         0xe0  /* 2.9V */
#define SHARPSL_CHARGE_ON_ACIN_HIGH    0x9b  /* 6V */
#define SHARPSL_CHARGE_ON_ACIN_LOW     0x34  /* 2V */
#define SHARPSL_FATAL_ACIN_VOLT        182   /* 3.45V */
#define SHARPSL_FATAL_NOACIN_VOLT      170   /* 3.40V */

static struct gpio charger_gpios[] = {
	{ CORGI_GPIO_ADC_TEMP_ON, GPIOF_OUT_INIT_LOW, "ADC Temp On" },
	{ CORGI_GPIO_CHRG_ON,	  GPIOF_OUT_INIT_LOW, "Charger On" },
	{ CORGI_GPIO_CHRG_UKN,	  GPIOF_OUT_INIT_LOW, "Charger Unknown" },
	{ CORGI_GPIO_AC_IN,	  GPIOF_IN, "Charger Detection" },
	{ CORGI_GPIO_KEY_INT,	  GPIOF_IN, "Key Interrupt" },
	{ CORGI_GPIO_WAKEUP,	  GPIOF_IN, "System wakeup notification" },
};

static void corgi_charger_init(void)
{
	gpio_request_array(ARRAY_AND_SIZE(charger_gpios));
}

static void corgi_measure_temp(int on)
{
	gpio_set_value(CORGI_GPIO_ADC_TEMP_ON, on);
}

static void corgi_charge(int on)
{
	if (on) {
		if (machine_is_corgi() && (sharpsl_pm.flags & SHARPSL_SUSPENDED)) {
			gpio_set_value(CORGI_GPIO_CHRG_ON, 0);
			gpio_set_value(CORGI_GPIO_CHRG_UKN, 1);
		} else {
			gpio_set_value(CORGI_GPIO_CHRG_ON, 1);
			gpio_set_value(CORGI_GPIO_CHRG_UKN, 0);
		}
	} else {
		gpio_set_value(CORGI_GPIO_CHRG_ON, 0);
		gpio_set_value(CORGI_GPIO_CHRG_UKN, 0);
	}
}

static void corgi_discharge(int on)
{
	gpio_set_value(CORGI_GPIO_DISCHARGE_ON, on);
}

static void corgi_presuspend(void)
{
}

static void corgi_postsuspend(void)
{
}

/*
 * Check what brought us out of the suspend.
 * Return: 0 to sleep, otherwise wake
 */
static int corgi_should_wakeup(unsigned int resume_on_alarm)
{
	int is_resume = 0;

	dev_dbg(sharpsl_pm.dev, "PEDR = %x, GPIO_AC_IN = %d, "
		"GPIO_CHRG_FULL = %d, GPIO_KEY_INT = %d, GPIO_WAKEUP = %d\n",
		PEDR, gpio_get_value(CORGI_GPIO_AC_IN),
		gpio_get_value(CORGI_GPIO_CHRG_FULL),
		gpio_get_value(CORGI_GPIO_KEY_INT),
		gpio_get_value(CORGI_GPIO_WAKEUP));

	if ((PEDR & GPIO_bit(CORGI_GPIO_AC_IN))) {
		if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) {
			/* charge on */
			dev_dbg(sharpsl_pm.dev, "ac insert\n");
			sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG;
		} else {
			/* charge off */
			dev_dbg(sharpsl_pm.dev, "ac remove\n");
			sharpsl_pm_led(SHARPSL_LED_OFF);
			sharpsl_pm.machinfo->charge(0);
			sharpsl_pm.charge_mode = CHRG_OFF;
		}
	}

	if ((PEDR & GPIO_bit(CORGI_GPIO_CHRG_FULL)))
		dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n");

	if (PEDR & GPIO_bit(CORGI_GPIO_KEY_INT))
		is_resume |= GPIO_bit(CORGI_GPIO_KEY_INT);

	if (PEDR & GPIO_bit(CORGI_GPIO_WAKEUP))
		is_resume |= GPIO_bit(CORGI_GPIO_WAKEUP);

	if (resume_on_alarm && (PEDR & PWER_RTC))
		is_resume |= PWER_RTC;

	dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume);
	return is_resume;
}

static bool corgi_charger_wakeup(void)
{
	return !gpio_get_value(CORGI_GPIO_AC_IN) ||
		!gpio_get_value(CORGI_GPIO_KEY_INT) ||
		!gpio_get_value(CORGI_GPIO_WAKEUP);
}

unsigned long corgipm_read_devdata(int type)
{
	switch(type) {
	case SHARPSL_STATUS_ACIN:
		return !gpio_get_value(CORGI_GPIO_AC_IN);
	case SHARPSL_STATUS_LOCK:
		return gpio_get_value(sharpsl_pm.machinfo->gpio_batlock);
	case SHARPSL_STATUS_CHRGFULL:
		return gpio_get_value(sharpsl_pm.machinfo->gpio_batfull);
	case SHARPSL_STATUS_FATAL:
		return gpio_get_value(sharpsl_pm.machinfo->gpio_fatal);
	case SHARPSL_ACIN_VOLT:
		return sharpsl_pm_pxa_read_max1111(MAX1111_ACIN_VOLT);
	case SHARPSL_BATT_TEMP:
		return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_TEMP);
	case SHARPSL_BATT_VOLT:
	default:
		return sharpsl_pm_pxa_read_max1111(MAX1111_BATT_VOLT);
	}
}

static struct sharpsl_charger_machinfo corgi_pm_machinfo = {
	.init            = corgi_charger_init,
	.exit            = NULL,
	.gpio_batlock    = CORGI_GPIO_BAT_COVER,
	.gpio_acin       = CORGI_GPIO_AC_IN,
	.gpio_batfull    = CORGI_GPIO_CHRG_FULL,
	.discharge       = corgi_discharge,
	.charge          = corgi_charge,
	.measure_temp    = corgi_measure_temp,
	.presuspend      = corgi_presuspend,
	.postsuspend     = corgi_postsuspend,
	.read_devdata    = corgipm_read_devdata,
	.charger_wakeup  = corgi_charger_wakeup,
	.should_wakeup   = corgi_should_wakeup,
#if defined(CONFIG_LCD_CORGI)
	.backlight_limit = corgi_lcd_limit_intensity,
#endif
	.charge_on_volt	  = SHARPSL_CHARGE_ON_VOLT,
	.charge_on_temp	  = SHARPSL_CHARGE_ON_TEMP,
	.charge_acin_high = SHARPSL_CHARGE_ON_ACIN_HIGH,
	.charge_acin_low  = SHARPSL_CHARGE_ON_ACIN_LOW,
	.fatal_acin_volt  = SHARPSL_FATAL_ACIN_VOLT,
	.fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT,
	.bat_levels       = 40,
	.bat_levels_noac  = sharpsl_battery_levels_noac,
	.bat_levels_acin  = sharpsl_battery_levels_acin,
	.status_high_acin = 188,
	.status_low_acin  = 178,
	.status_high_noac = 185,
	.status_low_noac  = 175,
};

static struct platform_device *corgipm_device;

static int corgipm_init(void)
{
	int ret;

	if (!machine_is_corgi() && !machine_is_shepherd()
			&& !machine_is_husky())
		return -ENODEV;

	corgipm_device = platform_device_alloc("sharpsl-pm", -1);
	if (!corgipm_device)
		return -ENOMEM;

	if (!machine_is_corgi())
	    corgi_pm_machinfo.batfull_irq = 1;

	corgipm_device->dev.platform_data = &corgi_pm_machinfo;
	ret = platform_device_add(corgipm_device);

	if (ret)
		platform_device_put(corgipm_device);

	return ret;
}

static void corgipm_exit(void)
{
	platform_device_unregister(corgipm_device);
}

module_init(corgipm_init);
module_exit(corgipm_exit);


code:
// SPDX-License-Identifier: GPL-2.0
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/leds.h>

#include <asm/mach-types.h>

static struct gpio_keys_button csb701_buttons[] = {
	{
		.code	= 0x7,
		.gpio	= 1,
		.active_low = 1,
		.desc	= "SW2",
		.type	= EV_SW,
		.wakeup = 1,
	},
};

static struct gpio_keys_platform_data csb701_gpio_keys_data = {
	.buttons = csb701_buttons,
	.nbuttons = ARRAY_SIZE(csb701_buttons),
};

static struct gpio_led csb701_leds[] = {
	{
		.name	= "csb701:yellow:heartbeat",
		.default_trigger = "heartbeat",
		.gpio	= 11,
		.active_low = 1,
	},
};

static struct platform_device csb701_gpio_keys = {
	.name		= "gpio-keys",
	.id		= -1,
	.dev.platform_data = &csb701_gpio_keys_data,
};

static struct gpio_led_platform_data csb701_leds_gpio_data = {
	.leds		= csb701_leds,
	.num_leds	= ARRAY_SIZE(csb701_leds),
};

static struct platform_device csb701_leds_gpio = {
	.name		= "leds-gpio",
	.id		= -1,
	.dev.platform_data = &csb701_leds_gpio_data,
};

static struct platform_device *devices[] __initdata = {
	&csb701_gpio_keys,
	&csb701_leds_gpio,
};

static int __init csb701_init(void)
{
	if (!machine_is_csb726())
		return -ENODEV;

	return platform_add_devices(devices, ARRAY_SIZE(devices));
}

module_init(csb701_init);


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  Support for Cogent CSB726
 *
 *  Copyright (c) 2008 Dmitry Eremin-Solenikov
 */
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/gpio/machine.h>
#include <linux/platform_device.h>
#include <linux/mtd/physmap.h>
#include <linux/mtd/partitions.h>
#include <linux/sm501.h>
#include <linux/smsc911x.h>
#include <linux/platform_data/i2c-pxa.h>

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

#include "csb726.h"
#include "pxa27x.h"
#include <linux/platform_data/mmc-pxamci.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/asoc-pxa.h>
#include "smemc.h"

#include "generic.h"
#include "devices.h"

/*
 * n/a: 2, 5, 6, 7, 8, 23, 24, 25, 26, 27, 87, 88, 89,
 * nu: 58 -- 77, 90, 91, 93, 102, 105-108, 114-116,
 * XXX: 21,
 * XXX: 79 CS_3 for LAN9215 or PSKTSEL on R2, R3
 * XXX: 33 CS_5 for LAN9215 on R1
 */

static unsigned long csb726_pin_config[] = {
	GPIO78_nCS_2, /* EXP_CS */
	GPIO79_nCS_3, /* SMSC9215 */
	GPIO80_nCS_4, /* SM501 */

	GPIO52_GPIO, /* #SMSC9251 int */
	GPIO53_GPIO, /* SM501 int */

	GPIO1_GPIO, /* GPIO0 */
	GPIO11_GPIO, /* GPIO1 */
	GPIO9_GPIO, /* GPIO2 */
	GPIO10_GPIO, /* GPIO3 */
	GPIO16_PWM0_OUT, /* or GPIO4 */
	GPIO17_PWM1_OUT, /* or GPIO5 */
	GPIO94_GPIO, /* GPIO6 */
	GPIO95_GPIO, /* GPIO7 */
	GPIO96_GPIO, /* GPIO8 */
	GPIO97_GPIO, /* GPIO9 */
	GPIO15_GPIO, /* EXP_IRQ */
	GPIO18_RDY, /* EXP_WAIT */

	GPIO0_GPIO, /* PWR_INT */
	GPIO104_GPIO, /* PWR_OFF */

	GPIO12_GPIO, /* touch irq */

	GPIO13_SSP2_TXD,
	GPIO14_SSP2_SFRM,
	MFP_CFG_OUT(GPIO19, AF1, DRIVE_LOW),/* SSP2_SYSCLK */
	GPIO22_SSP2_SCLK,

	GPIO81_SSP3_TXD,
	GPIO82_SSP3_RXD,
	GPIO83_SSP3_SFRM,
	GPIO84_SSP3_SCLK,

	GPIO20_GPIO, /* SDIO int */
	GPIO32_MMC_CLK,
	GPIO92_MMC_DAT_0,
	GPIO109_MMC_DAT_1,
	GPIO110_MMC_DAT_2,
	GPIO111_MMC_DAT_3,
	GPIO112_MMC_CMD,
	GPIO100_GPIO, /* SD CD */
	GPIO101_GPIO, /* SD WP */

	GPIO28_AC97_BITCLK,
	GPIO29_AC97_SDATA_IN_0,
	GPIO30_AC97_SDATA_OUT,
	GPIO31_AC97_SYNC,
	GPIO113_AC97_nRESET,

	GPIO34_FFUART_RXD,
	GPIO35_FFUART_CTS,
	GPIO36_FFUART_DCD,
	GPIO37_FFUART_DSR,
	GPIO38_FFUART_RI,
	GPIO39_FFUART_TXD,
	GPIO40_FFUART_DTR,
	GPIO41_FFUART_RTS,

	GPIO42_BTUART_RXD,
	GPIO43_BTUART_TXD,
	GPIO44_BTUART_CTS,
	GPIO45_BTUART_RTS,

	GPIO46_STUART_RXD,
	GPIO47_STUART_TXD,

	GPIO48_nPOE,
	GPIO49_nPWE,
	GPIO50_nPIOR,
	GPIO51_nPIOW,
	GPIO54_nPCE_2,
	GPIO55_nPREG,
	GPIO56_nPWAIT,
	GPIO57_nIOIS16, /* maybe unused */
	GPIO85_nPCE_1,
	GPIO98_GPIO, /* CF IRQ */
	GPIO99_GPIO, /* CF CD */
	GPIO103_GPIO, /* Reset */

	GPIO117_I2C_SCL,
	GPIO118_I2C_SDA,
};

static struct pxamci_platform_data csb726_mci = {
	.detect_delay_ms	= 500,
	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
	/* FIXME setpower */
};

static struct gpiod_lookup_table csb726_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		/* Card detect on GPIO 100 */
		GPIO_LOOKUP("gpio-pxa", CSB726_GPIO_MMC_DETECT,
			    "cd", GPIO_ACTIVE_LOW),
		/* Write protect on GPIO 101 */
		GPIO_LOOKUP("gpio-pxa", CSB726_GPIO_MMC_RO,
			    "wp", GPIO_ACTIVE_LOW),
		{ },
	},
};

static struct pxaohci_platform_data csb726_ohci_platform_data = {
	.port_mode	= PMM_NPS_MODE,
	.flags		= ENABLE_PORT1 | NO_OC_PROTECTION,
};

static struct mtd_partition csb726_flash_partitions[] = {
	{
		.name		= "Bootloader",
		.offset		= 0,
		.size		= CSB726_FLASH_uMON,
		.mask_flags	= MTD_WRITEABLE  /* force read-only */
	},
	{
		.name		= "root",
		.offset		= MTDPART_OFS_APPEND,
		.size		= MTDPART_SIZ_FULL,
	}
};

static struct physmap_flash_data csb726_flash_data = {
	.width		= 2,
	.parts		= csb726_flash_partitions,
	.nr_parts	= ARRAY_SIZE(csb726_flash_partitions),
};

static struct resource csb726_flash_resources[] = {
	{
		.start          = PXA_CS0_PHYS,
		.end            = PXA_CS0_PHYS + CSB726_FLASH_SIZE - 1 ,
		.flags          = IORESOURCE_MEM,
	}
};

static struct platform_device csb726_flash = {
	.name           = "physmap-flash",
	.dev            = {
		.platform_data  = &csb726_flash_data,
	},
	.resource       = csb726_flash_resources,
	.num_resources  = ARRAY_SIZE(csb726_flash_resources),
};

static struct resource csb726_sm501_resources[] = {
	{
		.start          = PXA_CS4_PHYS,
		.end            = PXA_CS4_PHYS + SZ_8M - 1,
		.flags          = IORESOURCE_MEM,
		.name		= "sm501-localmem",
	},
	{
		.start          = PXA_CS4_PHYS + SZ_64M - SZ_2M,
		.end            = PXA_CS4_PHYS + SZ_64M - 1,
		.flags          = IORESOURCE_MEM,
		.name		= "sm501-regs",
	},
	{
		.start		= CSB726_IRQ_SM501,
		.end		= CSB726_IRQ_SM501,
		.flags		= IORESOURCE_IRQ,
	},
};

static struct sm501_initdata csb726_sm501_initdata = {
/*	.devices	= SM501_USE_USB_HOST, */
	.devices	= SM501_USE_USB_HOST | SM501_USE_UART0 | SM501_USE_UART1,
};

static struct sm501_platdata csb726_sm501_platdata = {
	.init		= &csb726_sm501_initdata,
};

static struct platform_device csb726_sm501 = {
	.name		= "sm501",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(csb726_sm501_resources),
	.resource	= csb726_sm501_resources,
	.dev		= {
		.platform_data = &csb726_sm501_platdata,
	},
};

static struct resource csb726_lan_resources[] = {
	{
		.start	= PXA_CS3_PHYS,
		.end	= PXA_CS3_PHYS + SZ_64K - 1,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= CSB726_IRQ_LAN,
		.end	= CSB726_IRQ_LAN,
		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
	},
};

struct smsc911x_platform_config csb726_lan_config = {
	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_LOW,
	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
	.flags		= SMSC911X_USE_32BIT,
	.phy_interface	= PHY_INTERFACE_MODE_MII,
};

static struct platform_device csb726_lan = {
	.name		= "smsc911x",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(csb726_lan_resources),
	.resource	= csb726_lan_resources,
	.dev		= {
		.platform_data	= &csb726_lan_config,
	},
};

static struct platform_device *devices[] __initdata = {
	&csb726_flash,
	&csb726_sm501,
	&csb726_lan,
};

static void __init csb726_init(void)
{
	pxa2xx_mfp_config(ARRAY_AND_SIZE(csb726_pin_config));
/*	__raw_writel(0x7ffc3ffc, MSC1); *//* LAN9215/EXP_CS */
/*	__raw_writel(0x06697ff4, MSC2); *//* none/SM501 */
	__raw_writel((__raw_readl(MSC2) & ~0xffff) | 0x7ff4, MSC2); /* SM501 */

	pxa_set_ffuart_info(NULL);
	pxa_set_btuart_info(NULL);
	pxa_set_stuart_info(NULL);
	pxa_set_i2c_info(NULL);
	pxa27x_set_i2c_power_info(NULL);
	gpiod_add_lookup_table(&csb726_mci_gpio_table);
	pxa_set_mci_info(&csb726_mci);
	pxa_set_ohci_info(&csb726_ohci_platform_data);
	pxa_set_ac97_info(NULL);

	platform_add_devices(devices, ARRAY_SIZE(devices));
}

MACHINE_START(CSB726, "Cogent CSB726")
	.atag_offset	= 0x100,
	.map_io         = pxa27x_map_io,
	.nr_irqs	= PXA_NR_IRQS,
	.init_irq       = pxa27x_init_irq,
	.handle_irq       = pxa27x_handle_irq,
	.init_machine   = csb726_init,
	.init_time	= pxa_timer_init,
	.restart	= pxa_restart,
MACHINE_END


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *  Support for Cogent CSB726
 *
 *  Copyright (c) 2008 Dmitry Baryshkov
 */
#ifndef CSB726_H
#define CSB726_H

#include "irqs.h" /* PXA_GPIO_TO_IRQ */

#define CSB726_GPIO_IRQ_LAN	52
#define CSB726_GPIO_IRQ_SM501	53
#define CSB726_GPIO_MMC_DETECT	100
#define CSB726_GPIO_MMC_RO	101

#define CSB726_FLASH_SIZE	(64 * 1024 * 1024)
#define CSB726_FLASH_uMON	(8 * 1024 * 1024)

#define CSB726_IRQ_LAN		PXA_GPIO_TO_IRQ(CSB726_GPIO_IRQ_LAN)
#define CSB726_IRQ_SM501	PXA_GPIO_TO_IRQ(CSB726_GPIO_IRQ_SM501)

#endif


code:
// SPDX-License-Identifier: GPL-2.0
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
#include <linux/spi/pxa2xx_spi.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/soc/pxa/cpu.h>

#include "udc.h"
#include <linux/platform_data/usb-pxa3xx-ulpi.h>
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/mmc-pxamci.h>
#include <linux/platform_data/irda-pxaficp.h>
#include "irqs.h"
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/keypad-pxa27x.h>
#include <linux/platform_data/media/camera-pxa.h>
#include <linux/platform_data/asoc-pxa.h>
#include <linux/platform_data/mmp_dma.h>
#include <linux/platform_data/mtd-nand-pxa3xx.h>

#include "regs-ost.h"
#include "reset.h"
#include "devices.h"
#include "generic.h"

void __init pxa_register_device(struct platform_device *dev, void *data)
{
	int ret;

	dev->dev.platform_data = data;

	ret = platform_device_register(dev);
	if (ret)
		dev_err(&dev->dev, "unable to register device: %d\n", ret);
}

static struct resource pxa_resource_pmu = {
	.start	= IRQ_PMU,
	.end	= IRQ_PMU,
	.flags	= IORESOURCE_IRQ,
};

struct platform_device pxa_device_pmu = {
	.name		= "xscale-pmu",
	.id		= -1,
	.resource	= &pxa_resource_pmu,
	.num_resources	= 1,
};

static struct resource pxamci_resources[] = {
	[0] = {
		.start	= 0x41100000,
		.end	= 0x41100fff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_MMC,
		.end	= IRQ_MMC,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 pxamci_dmamask = 0xffffffffUL;

struct platform_device pxa_device_mci = {
	.name		= "pxa2xx-mci",
	.id		= 0,
	.dev		= {
		.dma_mask = &pxamci_dmamask,
		.coherent_dma_mask = 0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(pxamci_resources),
	.resource	= pxamci_resources,
};

void __init pxa_set_mci_info(struct pxamci_platform_data *info)
{
	pxa_register_device(&pxa_device_mci, info);
}

static struct pxa2xx_udc_mach_info pxa_udc_info = {
	.gpio_pullup = -1,
};

void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info)
{
	memcpy(&pxa_udc_info, info, sizeof *info);
}

static struct resource pxa2xx_udc_resources[] = {
	[0] = {
		.start	= 0x40600000,
		.end	= 0x4060ffff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_USB,
		.end	= IRQ_USB,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 udc_dma_mask = ~(u32)0;

struct platform_device pxa25x_device_udc = {
	.name		= "pxa25x-udc",
	.id		= -1,
	.resource	= pxa2xx_udc_resources,
	.num_resources	= ARRAY_SIZE(pxa2xx_udc_resources),
	.dev		=  {
		.platform_data	= &pxa_udc_info,
		.dma_mask	= &udc_dma_mask,
	}
};

struct platform_device pxa27x_device_udc = {
	.name		= "pxa27x-udc",
	.id		= -1,
	.resource	= pxa2xx_udc_resources,
	.num_resources	= ARRAY_SIZE(pxa2xx_udc_resources),
	.dev		=  {
		.platform_data	= &pxa_udc_info,
		.dma_mask	= &udc_dma_mask,
	}
};

#ifdef CONFIG_PXA3xx
static struct resource pxa3xx_u2d_resources[] = {
	[0] = {
		.start	= 0x54100000,
		.end	= 0x54100fff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_USB2,
		.end	= IRQ_USB2,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa3xx_device_u2d = {
	.name		= "pxa3xx-u2d",
	.id		= -1,
	.resource	= pxa3xx_u2d_resources,
	.num_resources	= ARRAY_SIZE(pxa3xx_u2d_resources),
};

void __init pxa3xx_set_u2d_info(struct pxa3xx_u2d_platform_data *info)
{
	pxa_register_device(&pxa3xx_device_u2d, info);
}
#endif /* CONFIG_PXA3xx */

static struct resource pxafb_resources[] = {
	[0] = {
		.start	= 0x44000000,
		.end	= 0x4400ffff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_LCD,
		.end	= IRQ_LCD,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 fb_dma_mask = ~(u64)0;

struct platform_device pxa_device_fb = {
	.name		= "pxa2xx-fb",
	.id		= -1,
	.dev		= {
		.dma_mask	= &fb_dma_mask,
		.coherent_dma_mask = 0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(pxafb_resources),
	.resource	= pxafb_resources,
};

void __init pxa_set_fb_info(struct device *parent, struct pxafb_mach_info *info)
{
	pxa_device_fb.dev.parent = parent;
	pxa_register_device(&pxa_device_fb, info);
}

static struct resource pxa_resource_ffuart[] = {
	{
		.start	= 0x40100000,
		.end	= 0x40100023,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_FFUART,
		.end	= IRQ_FFUART,
		.flags	= IORESOURCE_IRQ,
	}
};

struct platform_device pxa_device_ffuart = {
	.name		= "pxa2xx-uart",
	.id		= 0,
	.resource	= pxa_resource_ffuart,
	.num_resources	= ARRAY_SIZE(pxa_resource_ffuart),
};

void __init pxa_set_ffuart_info(void *info)
{
	pxa_register_device(&pxa_device_ffuart, info);
}

static struct resource pxa_resource_btuart[] = {
	{
		.start	= 0x40200000,
		.end	= 0x40200023,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_BTUART,
		.end	= IRQ_BTUART,
		.flags	= IORESOURCE_IRQ,
	}
};

struct platform_device pxa_device_btuart = {
	.name		= "pxa2xx-uart",
	.id		= 1,
	.resource	= pxa_resource_btuart,
	.num_resources	= ARRAY_SIZE(pxa_resource_btuart),
};

void __init pxa_set_btuart_info(void *info)
{
	pxa_register_device(&pxa_device_btuart, info);
}

static struct resource pxa_resource_stuart[] = {
	{
		.start	= 0x40700000,
		.end	= 0x40700023,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_STUART,
		.end	= IRQ_STUART,
		.flags	= IORESOURCE_IRQ,
	}
};

struct platform_device pxa_device_stuart = {
	.name		= "pxa2xx-uart",
	.id		= 2,
	.resource	= pxa_resource_stuart,
	.num_resources	= ARRAY_SIZE(pxa_resource_stuart),
};

void __init pxa_set_stuart_info(void *info)
{
	pxa_register_device(&pxa_device_stuart, info);
}

static struct resource pxa_resource_hwuart[] = {
	{
		.start	= 0x41600000,
		.end	= 0x4160002F,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_HWUART,
		.end	= IRQ_HWUART,
		.flags	= IORESOURCE_IRQ,
	}
};

struct platform_device pxa_device_hwuart = {
	.name		= "pxa2xx-uart",
	.id		= 3,
	.resource	= pxa_resource_hwuart,
	.num_resources	= ARRAY_SIZE(pxa_resource_hwuart),
};

void __init pxa_set_hwuart_info(void *info)
{
	if (cpu_is_pxa255())
		pxa_register_device(&pxa_device_hwuart, info);
	else
		pr_info("UART: Ignoring attempt to register HWUART on non-PXA255 hardware");
}

static struct resource pxai2c_resources[] = {
	{
		.start	= 0x40301680,
		.end	= 0x403016a3,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_I2C,
		.end	= IRQ_I2C,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa_device_i2c = {
	.name		= "pxa2xx-i2c",
	.id		= 0,
	.resource	= pxai2c_resources,
	.num_resources	= ARRAY_SIZE(pxai2c_resources),
};

void __init pxa_set_i2c_info(struct i2c_pxa_platform_data *info)
{
	pxa_register_device(&pxa_device_i2c, info);
}

#ifdef CONFIG_PXA27x
static struct resource pxa27x_resources_i2c_power[] = {
	{
		.start	= 0x40f00180,
		.end	= 0x40f001a3,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_PWRI2C,
		.end	= IRQ_PWRI2C,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa27x_device_i2c_power = {
	.name		= "pxa2xx-i2c",
	.id		= 1,
	.resource	= pxa27x_resources_i2c_power,
	.num_resources	= ARRAY_SIZE(pxa27x_resources_i2c_power),
};
#endif

static struct resource pxai2s_resources[] = {
	{
		.start	= 0x40400000,
		.end	= 0x40400083,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_I2S,
		.end	= IRQ_I2S,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa_device_i2s = {
	.name		= "pxa2xx-i2s",
	.id		= -1,
	.resource	= pxai2s_resources,
	.num_resources	= ARRAY_SIZE(pxai2s_resources),
};

struct platform_device pxa_device_asoc_ssp1 = {
	.name		= "pxa-ssp-dai",
	.id		= 0,
};

struct platform_device pxa_device_asoc_ssp2= {
	.name		= "pxa-ssp-dai",
	.id		= 1,
};

struct platform_device pxa_device_asoc_ssp3 = {
	.name		= "pxa-ssp-dai",
	.id		= 2,
};

struct platform_device pxa_device_asoc_ssp4 = {
	.name		= "pxa-ssp-dai",
	.id		= 3,
};

struct platform_device pxa_device_asoc_platform = {
	.name		= "pxa-pcm-audio",
	.id		= -1,
};

static u64 pxaficp_dmamask = ~(u32)0;

static struct resource pxa_ir_resources[] = {
	[0] = {
		.start  = IRQ_STUART,
		.end    = IRQ_STUART,
		.flags  = IORESOURCE_IRQ,
	},
	[1] = {
		.start  = IRQ_ICP,
		.end    = IRQ_ICP,
		.flags  = IORESOURCE_IRQ,
	},
	[3] = {
		.start  = 0x40800000,
		.end	= 0x4080001b,
		.flags  = IORESOURCE_MEM,
	},
	[4] = {
		.start  = 0x40700000,
		.end	= 0x40700023,
		.flags  = IORESOURCE_MEM,
	},
};

struct platform_device pxa_device_ficp = {
	.name		= "pxa2xx-ir",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(pxa_ir_resources),
	.resource	= pxa_ir_resources,
	.dev		= {
		.dma_mask = &pxaficp_dmamask,
		.coherent_dma_mask = 0xffffffff,
	},
};

void __init pxa_set_ficp_info(struct pxaficp_platform_data *info)
{
	pxa_register_device(&pxa_device_ficp, info);
}

static struct resource pxa_rtc_resources[] = {
	[0] = {
		.start  = 0x40900000,
		.end	= 0x40900000 + 0x3b,
		.flags  = IORESOURCE_MEM,
	},
	[1] = {
		.start  = IRQ_RTC1Hz,
		.end    = IRQ_RTC1Hz,
		.name	= "rtc 1Hz",
		.flags  = IORESOURCE_IRQ,
	},
	[2] = {
		.start  = IRQ_RTCAlrm,
		.end    = IRQ_RTCAlrm,
		.name	= "rtc alarm",
		.flags  = IORESOURCE_IRQ,
	},
};

struct platform_device pxa_device_rtc = {
	.name		= "pxa-rtc",
	.id		= -1,
	.num_resources  = ARRAY_SIZE(pxa_rtc_resources),
	.resource       = pxa_rtc_resources,
};

struct platform_device sa1100_device_rtc = {
	.name		= "sa1100-rtc",
	.id		= -1,
	.num_resources  = ARRAY_SIZE(pxa_rtc_resources),
	.resource       = pxa_rtc_resources,
};

static struct resource pxa_ac97_resources[] = {
	[0] = {
		.start  = 0x40500000,
		.end	= 0x40500000 + 0xfff,
		.flags  = IORESOURCE_MEM,
	},
	[1] = {
		.start  = IRQ_AC97,
		.end    = IRQ_AC97,
		.flags  = IORESOURCE_IRQ,
	},
};

static u64 pxa_ac97_dmamask = 0xffffffffUL;

struct platform_device pxa_device_ac97 = {
	.name           = "pxa2xx-ac97",
	.id             = -1,
	.dev            = {
		.dma_mask = &pxa_ac97_dmamask,
		.coherent_dma_mask = 0xffffffff,
	},
	.num_resources  = ARRAY_SIZE(pxa_ac97_resources),
	.resource       = pxa_ac97_resources,
};

void __init pxa_set_ac97_info(pxa2xx_audio_ops_t *ops)
{
	int ret;

	ret = clk_add_alias("ac97_clk", "pxa2xx-ac97:0", "AC97CLK",
			   &pxa_device_ac97.dev);
	if (ret)
		pr_err("PXA AC97 clock1 alias error: %d\n", ret);

	ret = clk_add_alias("ac97_clk", "pxa2xx-ac97:1", "AC97CLK",
			    &pxa_device_ac97.dev);
	if (ret)
		pr_err("PXA AC97 clock2 alias error: %d\n", ret);

	pxa_register_device(&pxa_device_ac97, ops);
}

#ifdef CONFIG_PXA25x

static struct resource pxa25x_resource_pwm0[] = {
	[0] = {
		.start	= 0x40b00000,
		.end	= 0x40b0000f,
		.flags	= IORESOURCE_MEM,
	},
};

struct platform_device pxa25x_device_pwm0 = {
	.name		= "pxa25x-pwm",
	.id		= 0,
	.resource	= pxa25x_resource_pwm0,
	.num_resources	= ARRAY_SIZE(pxa25x_resource_pwm0),
};

static struct resource pxa25x_resource_pwm1[] = {
	[0] = {
		.start	= 0x40c00000,
		.end	= 0x40c0000f,
		.flags	= IORESOURCE_MEM,
	},
};

struct platform_device pxa25x_device_pwm1 = {
	.name		= "pxa25x-pwm",
	.id		= 1,
	.resource	= pxa25x_resource_pwm1,
	.num_resources	= ARRAY_SIZE(pxa25x_resource_pwm1),
};

static u64 pxa25x_ssp_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa25x_resource_ssp[] = {
	[0] = {
		.start	= 0x41000000,
		.end	= 0x4100001f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_SSP,
		.end	= IRQ_SSP,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa25x_device_ssp = {
	.name		= "pxa25x-ssp",
	.id		= 0,
	.dev		= {
		.dma_mask = &pxa25x_ssp_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa25x_resource_ssp,
	.num_resources	= ARRAY_SIZE(pxa25x_resource_ssp),
};

static u64 pxa25x_nssp_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa25x_resource_nssp[] = {
	[0] = {
		.start	= 0x41400000,
		.end	= 0x4140002f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_NSSP,
		.end	= IRQ_NSSP,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa25x_device_nssp = {
	.name		= "pxa25x-nssp",
	.id		= 1,
	.dev		= {
		.dma_mask = &pxa25x_nssp_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa25x_resource_nssp,
	.num_resources	= ARRAY_SIZE(pxa25x_resource_nssp),
};

static u64 pxa25x_assp_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa25x_resource_assp[] = {
	[0] = {
		.start	= 0x41500000,
		.end	= 0x4150002f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_ASSP,
		.end	= IRQ_ASSP,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa25x_device_assp = {
	/* ASSP is basically equivalent to NSSP */
	.name		= "pxa25x-nssp",
	.id		= 2,
	.dev		= {
		.dma_mask = &pxa25x_assp_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa25x_resource_assp,
	.num_resources	= ARRAY_SIZE(pxa25x_resource_assp),
};
#endif /* CONFIG_PXA25x */

#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
static struct resource pxa27x_resource_camera[] = {
	[0] = {
		.start	= 0x50000000,
		.end	= 0x50000fff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_CAMERA,
		.end	= IRQ_CAMERA,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 pxa27x_dma_mask_camera = DMA_BIT_MASK(32);

static struct platform_device pxa27x_device_camera = {
	.name		= "pxa27x-camera",
	.id		= 0, /* This is used to put cameras on this interface */
	.dev		= {
		.dma_mask      		= &pxa27x_dma_mask_camera,
		.coherent_dma_mask	= 0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(pxa27x_resource_camera),
	.resource	= pxa27x_resource_camera,
};

void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
{
	struct clk *mclk;

	/* Register a fixed-rate clock for camera sensors. */
	mclk = clk_register_fixed_rate(NULL, "pxa_camera_clk", NULL, 0,
					     info->mclk_10khz * 10000);
	if (!IS_ERR(mclk))
		clkdev_create(mclk, "mclk", NULL);
	pxa_register_device(&pxa27x_device_camera, info);
}

static u64 pxa27x_ohci_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa27x_resource_ohci[] = {
	[0] = {
		.start  = 0x4C000000,
		.end    = 0x4C00ff6f,
		.flags  = IORESOURCE_MEM,
	},
	[1] = {
		.start  = IRQ_USBH1,
		.end    = IRQ_USBH1,
		.flags  = IORESOURCE_IRQ,
	},
};

struct platform_device pxa27x_device_ohci = {
	.name		= "pxa27x-ohci",
	.id		= -1,
	.dev		= {
		.dma_mask = &pxa27x_ohci_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.num_resources  = ARRAY_SIZE(pxa27x_resource_ohci),
	.resource       = pxa27x_resource_ohci,
};

void __init pxa_set_ohci_info(struct pxaohci_platform_data *info)
{
	pxa_register_device(&pxa27x_device_ohci, info);
}
#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */

#if defined(CONFIG_PXA27x) || defined(CONFIG_PXA3xx)
static struct resource pxa27x_resource_keypad[] = {
	[0] = {
		.start	= 0x41500000,
		.end	= 0x4150004c,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_KEYPAD,
		.end	= IRQ_KEYPAD,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa27x_device_keypad = {
	.name		= "pxa27x-keypad",
	.id		= -1,
	.resource	= pxa27x_resource_keypad,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_keypad),
};

void __init pxa_set_keypad_info(struct pxa27x_keypad_platform_data *info)
{
	pxa_register_device(&pxa27x_device_keypad, info);
}

static u64 pxa27x_ssp1_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa27x_resource_ssp1[] = {
	[0] = {
		.start	= 0x41000000,
		.end	= 0x4100003f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_SSP,
		.end	= IRQ_SSP,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa27x_device_ssp1 = {
	.name		= "pxa27x-ssp",
	.id		= 0,
	.dev		= {
		.dma_mask = &pxa27x_ssp1_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa27x_resource_ssp1,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp1),
};

static u64 pxa27x_ssp2_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa27x_resource_ssp2[] = {
	[0] = {
		.start	= 0x41700000,
		.end	= 0x4170003f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_SSP2,
		.end	= IRQ_SSP2,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa27x_device_ssp2 = {
	.name		= "pxa27x-ssp",
	.id		= 1,
	.dev		= {
		.dma_mask = &pxa27x_ssp2_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa27x_resource_ssp2,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp2),
};

static u64 pxa27x_ssp3_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa27x_resource_ssp3[] = {
	[0] = {
		.start	= 0x41900000,
		.end	= 0x4190003f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_SSP3,
		.end	= IRQ_SSP3,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa27x_device_ssp3 = {
	.name		= "pxa27x-ssp",
	.id		= 2,
	.dev		= {
		.dma_mask = &pxa27x_ssp3_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa27x_resource_ssp3,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp3),
};

static struct resource pxa27x_resource_pwm0[] = {
	[0] = {
		.start	= 0x40b00000,
		.end	= 0x40b0001f,
		.flags	= IORESOURCE_MEM,
	},
};

struct platform_device pxa27x_device_pwm0 = {
	.name		= "pxa27x-pwm",
	.id		= 0,
	.resource	= pxa27x_resource_pwm0,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_pwm0),
};

static struct resource pxa27x_resource_pwm1[] = {
	[0] = {
		.start	= 0x40c00000,
		.end	= 0x40c0001f,
		.flags	= IORESOURCE_MEM,
	},
};

struct platform_device pxa27x_device_pwm1 = {
	.name		= "pxa27x-pwm",
	.id		= 1,
	.resource	= pxa27x_resource_pwm1,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_pwm1),
};
#endif /* CONFIG_PXA27x || CONFIG_PXA3xx */

#ifdef CONFIG_PXA3xx
static struct resource pxa3xx_resources_mci2[] = {
	[0] = {
		.start	= 0x42000000,
		.end	= 0x42000fff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_MMC2,
		.end	= IRQ_MMC2,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa3xx_device_mci2 = {
	.name		= "pxa2xx-mci",
	.id		= 1,
	.dev		= {
		.dma_mask = &pxamci_dmamask,
		.coherent_dma_mask =	0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(pxa3xx_resources_mci2),
	.resource	= pxa3xx_resources_mci2,
};

void __init pxa3xx_set_mci2_info(struct pxamci_platform_data *info)
{
	pxa_register_device(&pxa3xx_device_mci2, info);
}

static struct resource pxa3xx_resources_mci3[] = {
	[0] = {
		.start	= 0x42500000,
		.end	= 0x42500fff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_MMC3,
		.end	= IRQ_MMC3,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa3xx_device_mci3 = {
	.name		= "pxa2xx-mci",
	.id		= 2,
	.dev		= {
		.dma_mask = &pxamci_dmamask,
		.coherent_dma_mask = 0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(pxa3xx_resources_mci3),
	.resource	= pxa3xx_resources_mci3,
};

void __init pxa3xx_set_mci3_info(struct pxamci_platform_data *info)
{
	pxa_register_device(&pxa3xx_device_mci3, info);
}

static struct resource pxa3xx_resources_gcu[] = {
	{
		.start	= 0x54000000,
		.end	= 0x54000fff,
		.flags	= IORESOURCE_MEM,
	},
	{
		.start	= IRQ_GCU,
		.end	= IRQ_GCU,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 pxa3xx_gcu_dmamask = DMA_BIT_MASK(32);

struct platform_device pxa3xx_device_gcu = {
	.name		= "pxa3xx-gcu",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(pxa3xx_resources_gcu),
	.resource	= pxa3xx_resources_gcu,
	.dev		= {
		.dma_mask = &pxa3xx_gcu_dmamask,
		.coherent_dma_mask = 0xffffffff,
	},
};

#endif /* CONFIG_PXA3xx */

#if defined(CONFIG_PXA3xx)
static struct resource pxa3xx_resources_i2c_power[] = {
	{
		.start  = 0x40f500c0,
		.end    = 0x40f500d3,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_PWRI2C,
		.end	= IRQ_PWRI2C,
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa3xx_device_i2c_power = {
	.name		= "pxa3xx-pwri2c",
	.id		= 1,
	.resource	= pxa3xx_resources_i2c_power,
	.num_resources	= ARRAY_SIZE(pxa3xx_resources_i2c_power),
};

static struct resource pxa3xx_resources_nand[] = {
	[0] = {
		.start	= 0x43100000,
		.end	= 0x43100053,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_NAND,
		.end	= IRQ_NAND,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 pxa3xx_nand_dma_mask = DMA_BIT_MASK(32);

struct platform_device pxa3xx_device_nand = {
	.name		= "pxa3xx-nand",
	.id		= -1,
	.dev		= {
		.dma_mask = &pxa3xx_nand_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.num_resources	= ARRAY_SIZE(pxa3xx_resources_nand),
	.resource	= pxa3xx_resources_nand,
};

void __init pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info)
{
	pxa_register_device(&pxa3xx_device_nand, info);
}

static u64 pxa3xx_ssp4_dma_mask = DMA_BIT_MASK(32);

static struct resource pxa3xx_resource_ssp4[] = {
	[0] = {
		.start	= 0x41a00000,
		.end	= 0x41a0003f,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_SSP4,
		.end	= IRQ_SSP4,
		.flags	= IORESOURCE_IRQ,
	},
};

/*
 * PXA3xx SSP is basically equivalent to PXA27x.
 * However, we need to register the device by the correct name in order to
 * make the driver set the correct internal type, hence we provide specific
 * platform_devices for each of them.
 */
struct platform_device pxa3xx_device_ssp1 = {
	.name		= "pxa3xx-ssp",
	.id		= 0,
	.dev		= {
		.dma_mask = &pxa27x_ssp1_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa27x_resource_ssp1,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp1),
};

struct platform_device pxa3xx_device_ssp2 = {
	.name		= "pxa3xx-ssp",
	.id		= 1,
	.dev		= {
		.dma_mask = &pxa27x_ssp2_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa27x_resource_ssp2,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp2),
};

struct platform_device pxa3xx_device_ssp3 = {
	.name		= "pxa3xx-ssp",
	.id		= 2,
	.dev		= {
		.dma_mask = &pxa27x_ssp3_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa27x_resource_ssp3,
	.num_resources	= ARRAY_SIZE(pxa27x_resource_ssp3),
};

struct platform_device pxa3xx_device_ssp4 = {
	.name		= "pxa3xx-ssp",
	.id		= 3,
	.dev		= {
		.dma_mask = &pxa3xx_ssp4_dma_mask,
		.coherent_dma_mask = DMA_BIT_MASK(32),
	},
	.resource	= pxa3xx_resource_ssp4,
	.num_resources	= ARRAY_SIZE(pxa3xx_resource_ssp4),
};
#endif /* CONFIG_PXA3xx */

struct resource pxa_resource_gpio[] = {
	{
		.start	= 0x40e00000,
		.end	= 0x40e0ffff,
		.flags	= IORESOURCE_MEM,
	}, {
		.start	= IRQ_GPIO0,
		.end	= IRQ_GPIO0,
		.name	= "gpio0",
		.flags	= IORESOURCE_IRQ,
	}, {
		.start	= IRQ_GPIO1,
		.end	= IRQ_GPIO1,
		.name	= "gpio1",
		.flags	= IORESOURCE_IRQ,
	}, {
		.start	= IRQ_GPIO_2_x,
		.end	= IRQ_GPIO_2_x,
		.name	= "gpio_mux",
		.flags	= IORESOURCE_IRQ,
	},
};

struct platform_device pxa25x_device_gpio = {
#ifdef CONFIG_CPU_PXA26x
	.name		= "pxa26x-gpio",
#else
	.name		= "pxa25x-gpio",
#endif
	.id		= -1,
	.num_resources	= ARRAY_SIZE(pxa_resource_gpio),
	.resource	= pxa_resource_gpio,
};

struct platform_device pxa27x_device_gpio = {
	.name		= "pxa27x-gpio",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(pxa_resource_gpio),
	.resource	= pxa_resource_gpio,
};

struct platform_device pxa3xx_device_gpio = {
	.name		= "pxa3xx-gpio",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(pxa_resource_gpio),
	.resource	= pxa_resource_gpio,
};

struct platform_device pxa93x_device_gpio = {
	.name		= "pxa93x-gpio",
	.id		= -1,
	.num_resources	= ARRAY_SIZE(pxa_resource_gpio),
	.resource	= pxa_resource_gpio,
};

/* pxa2xx-spi platform-device ID equals respective SSP platform-device ID + 1.
 * See comment in arch/arm/mach-pxa/ssp.c::ssp_probe() */
void __init pxa2xx_set_spi_info(unsigned id, struct pxa2xx_spi_controller *info)
{
	struct platform_device *pd;

	pd = platform_device_alloc("pxa2xx-spi", id);
	if (pd == NULL) {
		printk(KERN_ERR "pxa2xx-spi: failed to allocate device id %d\n",
		       id);
		return;
	}

	pd->dev.platform_data = info;
	platform_device_add(pd);
}

static struct resource pxa_dma_resource[] = {
	[0] = {
		.start	= 0x40000000,
		.end	= 0x4000ffff,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= IRQ_DMA,
		.end	= IRQ_DMA,
		.flags	= IORESOURCE_IRQ,
	},
};

static u64 pxadma_dmamask = 0xffffffffUL;

static struct platform_device pxa2xx_pxa_dma = {
	.name		= "pxa-dma",
	.id		= 0,
	.dev		= {
		.dma_mask = &pxadma_dmamask,
		.coherent_dma_mask = 0xffffffff,
	},
	.num_resources	= ARRAY_SIZE(pxa_dma_resource),
	.resource	= pxa_dma_resource,
};

void __init pxa2xx_set_dmac_info(struct mmp_dma_platdata *dma_pdata)
{
	pxa_register_device(&pxa2xx_pxa_dma, dma_pdata);
}

void __init pxa_register_wdt(unsigned int reset_status)
{
	struct resource res = DEFINE_RES_MEM(OST_PHYS, OST_LEN);

	reset_status &= RESET_STATUS_WATCHDOG;
	platform_device_register_resndata(NULL, "sa1100_wdt", -1, &res, 1,
					  &reset_status, sizeof(reset_status));
}