code:
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_OMAP1
	bool "TI OMAP1"
	depends on ARCH_MULTI_V4T || ARCH_MULTI_V5
	depends on CPU_LITTLE_ENDIAN
	depends on ATAGS
	select ARCH_HAS_HOLES_MEMORYMODEL
	select ARCH_OMAP
	select CLKSRC_MMIO
	select FORCE_PCI if PCCARD
	select GPIOLIB
	help
	  Support for older TI OMAP1 (omap7xx, omap15xx or omap16xx)

if ARCH_OMAP1

menu "TI OMAP1 specific features"

comment "OMAP Core Type"

config ARCH_OMAP730
	depends on ARCH_MULTI_V5
	bool "OMAP730 Based System"
	select ARCH_OMAP_OTG
	select CPU_ARM926T
	select OMAP_MPU_TIMER

config ARCH_OMAP850
	depends on ARCH_MULTI_V5
	bool "OMAP850 Based System"
	select ARCH_OMAP_OTG
	select CPU_ARM926T

config ARCH_OMAP15XX
	depends on ARCH_MULTI_V4T
	default y
	bool "OMAP15xx Based System"
	select CPU_ARM925T
	select OMAP_MPU_TIMER

config ARCH_OMAP16XX
	depends on ARCH_MULTI_V5
	bool "OMAP16xx Based System"
	select ARCH_OMAP_OTG
	select CPU_ARM926T
	select OMAP_DM_TIMER

config ARCH_OMAP1_ANY
	select ARCH_OMAP
	def_bool ARCH_OMAP730 || ARCH_OMAP850 || ARCH_OMAP15XX || ARCH_OMAP16XX

config ARCH_OMAP
	bool

comment "OMAP Feature Selections"

config OMAP_MUX
	bool "OMAP multiplexing support"
	default y
	help
	  Pin multiplexing support for OMAP boards. If your bootloader
	  sets the multiplexing correctly, say N. Otherwise, or if unsure,
	  say Y.

config OMAP_MUX_DEBUG
	bool "Multiplexing debug output"
	depends on OMAP_MUX
	help
	  Makes the multiplexing functions print out a lot of debug info.
	  This is useful if you want to find out the correct values of the
	  multiplexing registers.

config OMAP_MUX_WARNINGS
	bool "Warn about pins the bootloader didn't set up"
	depends on OMAP_MUX
	default y
	help
	  Choose Y here to warn whenever driver initialization logic needs
	  to change the pin multiplexing setup.	 When there are no warnings
	  printed, it's safe to deselect OMAP_MUX for your product.

config OMAP_32K_TIMER
	bool "Use 32KHz timer"
	depends on ARCH_OMAP16XX
	default ARCH_OMAP16XX
	help
	  Select this option if you want to enable the OMAP 32KHz timer.
	  This timer saves power compared to the OMAP_MPU_TIMER, and has
	  support for no tick during idle. The 32KHz timer provides less
	  intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
	  currently only available for OMAP16XX, 24XX, 34XX, OMAP4/5 and DRA7XX.

	  On OMAP2PLUS this value is only used for CONFIG_HZ and
	  CLOCK_TICK_RATE compile time calculation.
	  The actual timer selection is done in the board file
	  through the (DT_)MACHINE_START structure.

config OMAP_MPU_TIMER
	bool "Use mpu timer"
	depends on ARCH_OMAP1
	help
	  Select this option if you want to use the OMAP mpu timer. This
	  timer provides more intra-tick resolution than the 32KHz timer,
	  but consumes more power.

config OMAP_SERIAL_WAKE
	bool "Enable wake-up events for serial ports"
	depends on ARCH_OMAP1 && OMAP_MUX
	default y
	help
	  Select this option if you want to have your system wake up
	  to data on the serial RX line. This allows you to wake the
	  system from serial console.

config OMAP_RESET_CLOCKS
	bool "Reset unused clocks during boot"
	depends on ARCH_OMAP
	help
	  Say Y if you want to reset unused clocks during boot.
	  This option saves power, but assumes all drivers are
	  using the clock framework. Broken drivers that do not
	  yet use clock framework may not work with this option.
	  If you are booting from another operating system, you
	  probably do not want this option enabled until your
	  device drivers work properly.

config ARCH_OMAP_OTG
	bool

comment "OMAP Board Type"

config MACH_OMAP_INNOVATOR
	bool "TI Innovator"
	depends on ARCH_OMAP15XX || ARCH_OMAP16XX
	depends on UNUSED_BOARD_FILES
	help
          TI OMAP 1510 or 1610 Innovator board support. Say Y here if you
          have such a board.

config MACH_OMAP_H2
	bool "TI H2 Support"
	depends on ARCH_OMAP16XX
	depends on UNUSED_BOARD_FILES
	help
	  TI OMAP 1610/1611B H2 board support. Say Y here if you have such
	  a board.

config MACH_OMAP_H3
	bool "TI H3 Support"
	depends on ARCH_OMAP16XX
	depends on UNUSED_BOARD_FILES
	help
	  TI OMAP 1710 H3 board support. Say Y here if you have such
	  a board.

config MACH_HERALD
	bool "HTC Herald"
	depends on ARCH_OMAP850
	depends on UNUSED_BOARD_FILES
	help
	  HTC Herald smartphone support (AKA T-Mobile Wing, ...)

config MACH_OMAP_OSK
	bool "TI OSK Support"
	depends on ARCH_OMAP16XX
	help
	  TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here
          if you have such a board.

config OMAP_OSK_MISTRAL
	bool "Mistral QVGA board Support"
	depends on MACH_OMAP_OSK
	depends on UNUSED_BOARD_FILES
	help
	  The OSK supports an optional add-on board with a Quarter-VGA
	  touchscreen, PDA-ish buttons, a resume button, bicolor LED,
	  and camera connector.  Say Y here if you have this board.

config MACH_OMAP_PERSEUS2
	bool "TI Perseus2"
	depends on ARCH_OMAP730
	depends on UNUSED_BOARD_FILES
	help
	  Support for TI OMAP 730 Perseus2 board. Say Y here if you have such
	  a board.

config MACH_OMAP_FSAMPLE
	bool "TI F-Sample"
	depends on ARCH_OMAP730
	depends on UNUSED_BOARD_FILES
	help
	  Support for TI OMAP 850 F-Sample board. Say Y here if you have such
	  a board.

config MACH_OMAP_PALMTE
	bool "Palm Tungsten E"
	depends on ARCH_OMAP15XX
	help
	  Support for the Palm Tungsten E PDA.  To boot the kernel, you'll
	  need a PalmOS compatible bootloader; check out
	  http://palmtelinux.sourceforge.net/ for more information.
	  Say Y here if you have this PDA model, say N otherwise.

config MACH_OMAP_PALMZ71
	bool "Palm Zire71"
	depends on ARCH_OMAP15XX
	depends on UNUSED_BOARD_FILES
	help
	 Support for the Palm Zire71 PDA. To boot the kernel,
	 you'll need a PalmOS compatible bootloader; check out
	 http://hackndev.com/palm/z71 for more information.
	 Say Y here if you have such a PDA, say N otherwise.

config MACH_OMAP_PALMTT
	bool "Palm Tungsten|T"
	depends on ARCH_OMAP15XX
	depends on UNUSED_BOARD_FILES
	help
	  Support for the Palm Tungsten|T PDA. To boot the kernel, you'll
	  need a PalmOS compatible bootloader (Garux); check out
	  http://garux.sourceforge.net/ for more information.
	  Say Y here if you have this PDA model, say N otherwise.

config MACH_SX1
	bool "Siemens SX1"
	depends on ARCH_OMAP15XX
	select I2C
	help
	  Support for the Siemens SX1 phone. To boot the kernel,
	  you'll need a SX1 compatible bootloader; check out
	  http://forum.oslik.ru and
	  https://www.handhelds.org/moin/moin.cgi/SiemensSX1
	  for more information.
	  Say Y here if you have such a phone, say NO otherwise.

config MACH_NOKIA770
	bool "Nokia 770"
	depends on ARCH_OMAP16XX
	help
	  Support for the Nokia 770 Internet Tablet. Say Y here if you
	  have such a device.

config MACH_AMS_DELTA
	bool "Amstrad E3 (Delta)"
	depends on ARCH_OMAP15XX
	select FIQ
	select GPIO_GENERIC_PLATFORM
	select LEDS_GPIO_REGISTER
	select REGULATOR
	select REGULATOR_FIXED_VOLTAGE
	help
	  Support for the Amstrad E3 (codename Delta) videophone. Say Y here
	  if you have such a device.

config MACH_OMAP_GENERIC
	bool "Generic OMAP board"
	depends on ARCH_OMAP15XX || ARCH_OMAP16XX
	depends on UNUSED_BOARD_FILES
	help
          Support for generic OMAP-1510, 1610 or 1710 board with
          no FPGA. Can be used as template for porting Linux to
          custom OMAP boards. Say Y here if you have a custom
          board.

endmenu

endif


code:
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for the linux kernel.
#

ifdef CONFIG_ARCH_OMAP1_ANY

# Common support
obj-y := io.o id.o sram-init.o sram.o time.o irq.o mux.o flash.o \
	 serial.o devices.o dma.o omap-dma.o fb.o
obj-y += clock.o clock_data.o opp_data.o reset.o pm_bus.o timer.o

ifneq ($(CONFIG_SND_SOC_OMAP_MCBSP),)
obj-y += mcbsp.o
endif

obj-$(CONFIG_OMAP_32K_TIMER)	+= timer32k.o

# OCPI interconnect support for 1710, 1610 and 5912
obj-$(CONFIG_ARCH_OMAP16XX) += ocpi.o

# Power Management
obj-$(CONFIG_PM) += pm.o sleep.o

i2c-omap-$(CONFIG_I2C_OMAP)		:= i2c.o
obj-y					+= $(i2c-omap-m) $(i2c-omap-y)

led-y := leds.o

usb-fs-$(CONFIG_USB_SUPPORT)		:= usb.o
obj-y					+= $(usb-fs-m) $(usb-fs-y)

# Specific board support
obj-$(CONFIG_MACH_OMAP_H2)		+= board-h2.o board-h2-mmc.o \
					   board-nand.o
obj-$(CONFIG_MACH_OMAP_INNOVATOR)	+= board-innovator.o
obj-$(CONFIG_MACH_OMAP_GENERIC)		+= board-generic.o
obj-$(CONFIG_MACH_OMAP_PERSEUS2)	+= board-perseus2.o board-nand.o
obj-$(CONFIG_MACH_OMAP_FSAMPLE)		+= board-fsample.o board-nand.o
obj-$(CONFIG_MACH_OMAP_OSK)		+= board-osk.o
obj-$(CONFIG_MACH_OMAP_H3)		+= board-h3.o board-h3-mmc.o \
					   board-nand.o
obj-$(CONFIG_MACH_OMAP_PALMTE)		+= board-palmte.o
obj-$(CONFIG_MACH_OMAP_PALMZ71)		+= board-palmz71.o
obj-$(CONFIG_MACH_OMAP_PALMTT)		+= board-palmtt.o
obj-$(CONFIG_MACH_NOKIA770)		+= board-nokia770.o
obj-$(CONFIG_MACH_AMS_DELTA)		+= board-ams-delta.o ams-delta-fiq.o \
					   ams-delta-fiq-handler.o
obj-$(CONFIG_MACH_SX1)			+= board-sx1.o board-sx1-mmc.o
obj-$(CONFIG_MACH_HERALD)		+= board-htcherald.o

ifeq ($(CONFIG_ARCH_OMAP15XX),y)
# Innovator-1510 FPGA
obj-$(CONFIG_MACH_OMAP_INNOVATOR)	+= fpga.o
endif

# GPIO
obj-$(CONFIG_ARCH_OMAP730)		+= gpio7xx.o
obj-$(CONFIG_ARCH_OMAP850)		+= gpio7xx.o
obj-$(CONFIG_ARCH_OMAP15XX)		+= gpio15xx.o
obj-$(CONFIG_ARCH_OMAP16XX)		+= gpio16xx.o

endif

repo_name: angery/linux


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *  linux/arch/arm/mach-omap1/ams-delta-fiq-handler.S
 *
 *  Based on  linux/arch/arm/lib/floppydma.S
 *  Renamed and modified to work with 2.6 kernel by Matt Callow
 *  Copyright (C) 1995, 1996 Russell King
 *  Copyright (C) 2004 Pete Trapps
 *  Copyright (C) 2006 Matt Callow
 *  Copyright (C) 2010 Janusz Krzysztofik
 */

#include <linux/linkage.h>
#include <linux/platform_data/ams-delta-fiq.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/soc/ti/omap1-io.h>

#include <asm/assembler.h>
#include <asm/irq.h>

#include "hardware.h"
#include "ams-delta-fiq.h"
#include "board-ams-delta.h"
#include "iomap.h"

/*
 * OMAP1510 GPIO related symbol copied from arch/arm/mach-omap1/gpio15xx.c.
 * Unfortunately, it was not placed in a separate header file.
 */
#define OMAP1510_GPIO_BASE		0xFFFCE000

/* GPIO register bitmasks */
#define KEYBRD_DATA_MASK		(0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_DATA)
#define KEYBRD_CLK_MASK			(0x1 << AMS_DELTA_GPIO_PIN_KEYBRD_CLK)
#define MODEM_IRQ_MASK			(0x1 << AMS_DELTA_GPIO_PIN_MODEM_IRQ)
#define HOOK_SWITCH_MASK		(0x1 << AMS_DELTA_GPIO_PIN_HOOK_SWITCH)
#define OTHERS_MASK			(MODEM_IRQ_MASK | HOOK_SWITCH_MASK)

/* IRQ handler register bitmasks */
#define DEFERRED_FIQ_MASK		OMAP_IRQ_BIT(INT_DEFERRED_FIQ)
#define GPIO_BANK1_MASK  		OMAP_IRQ_BIT(INT_GPIO_BANK1)

/* Driver buffer byte offsets */
#define BUF_MASK			(FIQ_MASK * 4)
#define BUF_STATE			(FIQ_STATE * 4)
#define BUF_KEYS_CNT			(FIQ_KEYS_CNT * 4)
#define BUF_TAIL_OFFSET			(FIQ_TAIL_OFFSET * 4)
#define BUF_HEAD_OFFSET			(FIQ_HEAD_OFFSET * 4)
#define BUF_BUF_LEN			(FIQ_BUF_LEN * 4)
#define BUF_KEY				(FIQ_KEY * 4)
#define BUF_MISSED_KEYS			(FIQ_MISSED_KEYS * 4)
#define BUF_BUFFER_START		(FIQ_BUFFER_START * 4)
#define BUF_GPIO_INT_MASK		(FIQ_GPIO_INT_MASK * 4)
#define BUF_KEYS_HICNT			(FIQ_KEYS_HICNT * 4)
#define BUF_IRQ_PEND			(FIQ_IRQ_PEND * 4)
#define BUF_SIR_CODE_L1			(FIQ_SIR_CODE_L1 * 4)
#define BUF_SIR_CODE_L2			(IRQ_SIR_CODE_L2 * 4)
#define BUF_CNT_INT_00			(FIQ_CNT_INT_00 * 4)
#define BUF_CNT_INT_KEY			(FIQ_CNT_INT_KEY * 4)
#define BUF_CNT_INT_MDM			(FIQ_CNT_INT_MDM * 4)
#define BUF_CNT_INT_03			(FIQ_CNT_INT_03 * 4)
#define BUF_CNT_INT_HSW			(FIQ_CNT_INT_HSW * 4)
#define BUF_CNT_INT_05			(FIQ_CNT_INT_05 * 4)
#define BUF_CNT_INT_06			(FIQ_CNT_INT_06 * 4)
#define BUF_CNT_INT_07			(FIQ_CNT_INT_07 * 4)
#define BUF_CNT_INT_08			(FIQ_CNT_INT_08 * 4)
#define BUF_CNT_INT_09			(FIQ_CNT_INT_09 * 4)
#define BUF_CNT_INT_10			(FIQ_CNT_INT_10 * 4)
#define BUF_CNT_INT_11			(FIQ_CNT_INT_11 * 4)
#define BUF_CNT_INT_12			(FIQ_CNT_INT_12 * 4)
#define BUF_CNT_INT_13			(FIQ_CNT_INT_13 * 4)
#define BUF_CNT_INT_14			(FIQ_CNT_INT_14 * 4)
#define BUF_CNT_INT_15			(FIQ_CNT_INT_15 * 4)
#define BUF_CIRC_BUFF			(FIQ_CIRC_BUFF * 4)

/*
 * Register usage
 * r8  - temporary
 * r9  - the driver buffer
 * r10 - temporary
 * r11 - interrupts mask
 * r12 - base pointers
 * r13 - interrupts status
 */

	.text

	.global qwerty_fiqin_end

ENTRY(qwerty_fiqin_start)
	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
	@ FIQ intrrupt handler
	ldr r12, omap_ih1_base			@ set pointer to level1 handler

	ldr r11, [r12, #IRQ_MIR_REG_OFFSET]	@ fetch interrupts mask

	ldr r13, [r12, #IRQ_ITR_REG_OFFSET]	@ fetch interrupts status
	bics r13, r13, r11			@ clear masked - any left?
	beq exit				@ none - spurious FIQ? exit

	ldr r10, [r12, #IRQ_SIR_FIQ_REG_OFFSET]	@ get requested interrupt number

	mov r8, #2				@ reset FIQ agreement
	str r8, [r12, #IRQ_CONTROL_REG_OFFSET]

	cmp r10, #(INT_GPIO_BANK1 - NR_IRQS_LEGACY)	@ is it GPIO interrupt?
	beq gpio				@ yes - process it

	mov r8, #1
	orr r8, r11, r8, lsl r10		@ mask spurious interrupt
	str r8, [r12, #IRQ_MIR_REG_OFFSET]
exit:
	subs	pc, lr, #4			@ return from FIQ
	@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

	@@@@@@@@@@@@@@@@@@@@@@@@@@@
gpio:	@ GPIO bank interrupt handler
	ldr r12, omap1510_gpio_base		@ set base pointer to GPIO bank

	ldr r11, [r12, #OMAP1510_GPIO_INT_MASK]	@ fetch GPIO interrupts mask
restart:
	ldr r13, [r12, #OMAP1510_GPIO_INT_STATUS]	@ fetch status bits
	bics r13, r13, r11			@ clear masked - any left?
	beq exit				@ no - spurious interrupt? exit

	orr r11, r11, r13			@ mask all requested interrupts
	str r11, [r12, #OMAP1510_GPIO_INT_MASK]

	str r13, [r12, #OMAP1510_GPIO_INT_STATUS] @ ack all requested interrupts

	ands r10, r13, #KEYBRD_CLK_MASK		@ extract keyboard status - set?
	beq hksw				@ no - try next source

	@@@@@@@@@@@@@@@@@@@@@@
	@ Keyboard clock FIQ mode interrupt handler
	@ r10 now contains KEYBRD_CLK_MASK, use it
	bic r11, r11, r10				@ unmask it
	str r11, [r12, #OMAP1510_GPIO_INT_MASK]

	@ Process keyboard data
	ldr r8, [r12, #OMAP1510_GPIO_DATA_INPUT]	@ fetch GPIO input

	ldr r10, [r9, #BUF_STATE]		@ fetch kbd interface state
	cmp r10, #0				@ are we expecting start bit?
	bne data				@ no - go to data processing

	ands r8, r8, #KEYBRD_DATA_MASK		@ check start bit - detected?
	beq hksw				@ no - try next source

	@ r8 contains KEYBRD_DATA_MASK, use it
	str r8, [r9, #BUF_STATE]		@ enter data processing state
	@ r10 already contains 0, reuse it
	str r10, [r9, #BUF_KEY]			@ clear keycode
	mov r10, #2				@ reset input bit mask
	str r10, [r9, #BUF_MASK]

	@ Mask other GPIO line interrupts till key done
	str r11, [r9, #BUF_GPIO_INT_MASK]	@ save mask for later restore
	mvn r11, #KEYBRD_CLK_MASK		@ prepare all except kbd mask
	str r11, [r12, #OMAP1510_GPIO_INT_MASK]	@ store into the mask register

	b restart				@ restart

data:	ldr r10, [r9, #BUF_MASK]		@ fetch current input bit mask

	@ r8 still contains GPIO input bits
	ands r8, r8, #KEYBRD_DATA_MASK		@ is keyboard data line low?
	ldreq r8, [r9, #BUF_KEY]		@ yes - fetch collected so far,
	orreq r8, r8, r10			@ set 1 at current mask position
	streq r8, [r9, #BUF_KEY]		@ and save back

	mov r10, r10, lsl #1			@ shift mask left
	bics r10, r10, #0x800			@ have we got all the bits?
	strne r10, [r9, #BUF_MASK]		@ not yet - store the mask
	bne restart				@ and restart

	@ r10 already contains 0, reuse it
	str r10, [r9, #BUF_STATE]		@ reset state to start

	@ Key done - restore interrupt mask
	ldr r10, [r9, #BUF_GPIO_INT_MASK]	@ fetch saved mask
	and r11, r11, r10			@ unmask all saved as unmasked
	str r11, [r12, #OMAP1510_GPIO_INT_MASK]	@ restore into the mask register

	@ Try appending the keycode to the circular buffer
	ldr r10, [r9, #BUF_KEYS_CNT]		@ get saved keystrokes count
	ldr r8, [r9, #BUF_BUF_LEN]		@ get buffer size
	cmp r10, r8				@ is buffer full?
	beq hksw				@ yes - key lost, next source

	add r10, r10, #1			@ incremet keystrokes counter
	str r10, [r9, #BUF_KEYS_CNT]

	ldr r10, [r9, #BUF_TAIL_OFFSET]		@ get buffer tail offset
	@ r8 already contains buffer size
	cmp r10, r8				@ end of buffer?
	moveq r10, #0				@ yes - rewind to buffer start

	ldr r12, [r9, #BUF_BUFFER_START]	@ get buffer start address
	add r12, r12, r10, LSL #2		@ calculate buffer tail address
	ldr r8, [r9, #BUF_KEY]			@ get last keycode
	str r8, [r12]				@ append it to the buffer tail

	add r10, r10, #1			@ increment buffer tail offset
	str r10, [r9, #BUF_TAIL_OFFSET]

	ldr r10, [r9, #BUF_CNT_INT_KEY]		@ increment interrupts counter
	add r10, r10, #1
	str r10, [r9, #BUF_CNT_INT_KEY]
	@@@@@@@@@@@@@@@@@@@@@@@@

hksw:	@Is hook switch interrupt requested?
	tst r13, #HOOK_SWITCH_MASK 		@ is hook switch status bit set?
	beq mdm					@ no - try next source

	@@@@@@@@@@@@@@@@@@@@@@@@
	@ Hook switch interrupt FIQ mode simple handler

	@ Don't toggle active edge, the switch always bounces

	@ Increment hook switch interrupt counter
	ldr r10, [r9, #BUF_CNT_INT_HSW]
	add r10, r10, #1
	str r10, [r9, #BUF_CNT_INT_HSW]
	@@@@@@@@@@@@@@@@@@@@@@@@

mdm:	@Is it a modem interrupt?
	tst r13, #MODEM_IRQ_MASK 		@ is modem status bit set?
	beq irq					@ no - check for next interrupt

	@@@@@@@@@@@@@@@@@@@@@@@@
	@ Modem FIQ mode interrupt handler stub

	@ Increment modem interrupt counter
	ldr r10, [r9, #BUF_CNT_INT_MDM]
	add r10, r10, #1
	str r10, [r9, #BUF_CNT_INT_MDM]
	@@@@@@@@@@@@@@@@@@@@@@@@

irq:	@ Place deferred_fiq interrupt request
	ldr r12, deferred_fiq_ih_base		@ set pointer to IRQ handler
	mov r10, #DEFERRED_FIQ_MASK		@ set deferred_fiq bit
	str r10, [r12, #IRQ_ISR_REG_OFFSET] 	@ place it in the ISR register

	ldr r12, omap1510_gpio_base		@ set pointer back to GPIO bank
	b restart				@ check for next GPIO interrupt
	@@@@@@@@@@@@@@@@@@@@@@@@@@@

/*
 * Virtual addresses for IO
 */
omap_ih1_base:
	.word OMAP1_IO_ADDRESS(OMAP_IH1_BASE)
deferred_fiq_ih_base:
	.word OMAP1_IO_ADDRESS(DEFERRED_FIQ_IH_BASE)
omap1510_gpio_base:
	.word OMAP1_IO_ADDRESS(OMAP1510_GPIO_BASE)
qwerty_fiqin_end:

/*
 * Check the size of the FIQ,
 * it cannot go beyond 0xffff0200, and is copied to 0xffff001c
 */
.if (qwerty_fiqin_end - qwerty_fiqin_start) > (0x200 - 0x1c)
	.err
.endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  Amstrad E3 FIQ handling
 *
 *  Copyright (C) 2009 Janusz Krzysztofik
 *  Copyright (c) 2006 Matt Callow
 *  Copyright (c) 2004 Amstrad Plc
 *  Copyright (C) 2001 RidgeRun, Inc.
 *
 * Parts of this code are taken from linux/arch/arm/mach-omap/irq.c
 * in the MontaVista 2.4 kernel (and the Amstrad changes therein)
 */
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/platform_data/ams-delta-fiq.h>
#include <linux/platform_device.h>

#include <asm/fiq.h>
#include <linux/soc/ti/omap1-io.h>

#include "hardware.h"
#include "ams-delta-fiq.h"
#include "board-ams-delta.h"

static struct fiq_handler fh = {
	.name	= "ams-delta-fiq"
};

/*
 * This buffer is shared between FIQ and IRQ contexts.
 * The FIQ and IRQ isrs can both read and write it.
 * It is structured as a header section several 32bit slots,
 * followed by the circular buffer where the FIQ isr stores
 * keystrokes received from the qwerty keyboard.  See
 * <linux/platform_data/ams-delta-fiq.h> for details of offsets.
 */
static unsigned int fiq_buffer[1024];

static struct irq_chip *irq_chip;
static struct irq_data *irq_data[16];
static unsigned int irq_counter[16];

static const char *pin_name[16] __initconst = {
	[AMS_DELTA_GPIO_PIN_KEYBRD_DATA]	= "keybrd_data",
	[AMS_DELTA_GPIO_PIN_KEYBRD_CLK]		= "keybrd_clk",
};

static irqreturn_t deferred_fiq(int irq, void *dev_id)
{
	struct irq_data *d;
	int gpio, irq_num, fiq_count;

	/*
	 * For each handled GPIO interrupt, keep calling its interrupt handler
	 * until the IRQ counter catches the FIQ incremented interrupt counter.
	 */
	for (gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK;
			gpio <= AMS_DELTA_GPIO_PIN_HOOK_SWITCH; gpio++) {
		d = irq_data[gpio];
		irq_num = d->irq;
		fiq_count = fiq_buffer[FIQ_CNT_INT_00 + gpio];

		if (irq_counter[gpio] < fiq_count &&
				gpio != AMS_DELTA_GPIO_PIN_KEYBRD_CLK) {
			/*
			 * handle_simple_irq() that OMAP GPIO edge
			 * interrupts default to since commit 80ac93c27441
			 * requires interrupt already acked and unmasked.
			 */
			if (!WARN_ON_ONCE(!irq_chip->irq_unmask))
				irq_chip->irq_unmask(d);
		}
		for (; irq_counter[gpio] < fiq_count; irq_counter[gpio]++)
			generic_handle_irq(irq_num);
	}
	return IRQ_HANDLED;
}

void __init ams_delta_init_fiq(struct gpio_chip *chip,
			       struct platform_device *serio)
{
	struct gpio_desc *gpiod, *data = NULL, *clk = NULL;
	void *fiqhandler_start;
	unsigned int fiqhandler_length;
	struct pt_regs FIQ_regs;
	unsigned long val, offset;
	int i, retval;

	/* Store irq_chip location for IRQ handler use */
	irq_chip = chip->irq.chip;
	if (!irq_chip) {
		pr_err("%s: GPIO chip %s is missing IRQ function\n", __func__,
		       chip->label);
		return;
	}

	for (i = 0; i < ARRAY_SIZE(irq_data); i++) {
		gpiod = gpiochip_request_own_desc(chip, i, pin_name[i],
						  GPIO_ACTIVE_HIGH, GPIOD_IN);
		if (IS_ERR(gpiod)) {
			pr_err("%s: failed to get GPIO pin %d (%ld)\n",
			       __func__, i, PTR_ERR(gpiod));
			return;
		}
		/* Store irq_data location for IRQ handler use */
		irq_data[i] = irq_get_irq_data(gpiod_to_irq(gpiod));

		/*
		 * FIQ handler takes full control over serio data and clk GPIO
		 * pins.  Initialize them and keep requested so nobody can
		 * interfere.  Fail if any of those two couldn't be requested.
		 */
		switch (i) {
		case AMS_DELTA_GPIO_PIN_KEYBRD_DATA:
			data = gpiod;
			gpiod_direction_input(data);
			break;
		case AMS_DELTA_GPIO_PIN_KEYBRD_CLK:
			clk = gpiod;
			gpiod_direction_input(clk);
			break;
		default:
			gpiochip_free_own_desc(gpiod);
			break;
		}
	}
	if (!data || !clk)
		goto out_gpio;

	fiqhandler_start = &qwerty_fiqin_start;
	fiqhandler_length = &qwerty_fiqin_end - &qwerty_fiqin_start;
	pr_info("Installing fiq handler from %p, length 0x%x\n",
			fiqhandler_start, fiqhandler_length);

	retval = claim_fiq(&fh);
	if (retval) {
		pr_err("ams_delta_init_fiq(): couldn't claim FIQ, ret=%d\n",
				retval);
		goto out_gpio;
	}

	retval = request_irq(INT_DEFERRED_FIQ, deferred_fiq,
			IRQ_TYPE_EDGE_RISING, "deferred_fiq", NULL);
	if (retval < 0) {
		pr_err("Failed to get deferred_fiq IRQ, ret=%d\n", retval);
		release_fiq(&fh);
		goto out_gpio;
	}
	/*
	 * Since no set_type() method is provided by OMAP irq chip,
	 * switch to edge triggered interrupt type manually.
	 */
	offset = IRQ_ILR0_REG_OFFSET +
			((INT_DEFERRED_FIQ - NR_IRQS_LEGACY) & 0x1f) * 0x4;
	val = omap_readl(DEFERRED_FIQ_IH_BASE + offset) & ~(1 << 1);
	omap_writel(val, DEFERRED_FIQ_IH_BASE + offset);

	set_fiq_handler(fiqhandler_start, fiqhandler_length);

	/*
	 * Initialise the buffer which is shared
	 * between FIQ mode and IRQ mode
	 */
	fiq_buffer[FIQ_GPIO_INT_MASK]	= 0;
	fiq_buffer[FIQ_MASK]		= 0;
	fiq_buffer[FIQ_STATE]		= 0;
	fiq_buffer[FIQ_KEY]		= 0;
	fiq_buffer[FIQ_KEYS_CNT]	= 0;
	fiq_buffer[FIQ_KEYS_HICNT]	= 0;
	fiq_buffer[FIQ_TAIL_OFFSET]	= 0;
	fiq_buffer[FIQ_HEAD_OFFSET]	= 0;
	fiq_buffer[FIQ_BUF_LEN]		= 256;
	fiq_buffer[FIQ_MISSED_KEYS]	= 0;
	fiq_buffer[FIQ_BUFFER_START]	=
			(unsigned int) &fiq_buffer[FIQ_CIRC_BUFF];

	for (i = FIQ_CNT_INT_00; i <= FIQ_CNT_INT_15; i++)
		fiq_buffer[i] = 0;

	/*
	 * FIQ mode r9 always points to the fiq_buffer, because the FIQ isr
	 * will run in an unpredictable context. The fiq_buffer is the FIQ isr's
	 * only means of communication with the IRQ level and other kernel
	 * context code.
	 */
	FIQ_regs.ARM_r9 = (unsigned int)fiq_buffer;
	set_fiq_regs(&FIQ_regs);

	pr_info("request_fiq(): fiq_buffer = %p\n", fiq_buffer);

	/*
	 * Redirect GPIO interrupts to FIQ
	 */
	offset = IRQ_ILR0_REG_OFFSET + (INT_GPIO_BANK1 - NR_IRQS_LEGACY) * 0x4;
	val = omap_readl(OMAP_IH1_BASE + offset) | 1;
	omap_writel(val, OMAP_IH1_BASE + offset);

	/* Initialize serio device IRQ resource and platform_data */
	serio->resource[0].start = gpiod_to_irq(clk);
	serio->resource[0].end = serio->resource[0].start;
	serio->dev.platform_data = fiq_buffer;

	/*
	 * Since FIQ handler performs handling of GPIO registers for
	 * "keybrd_clk" IRQ pin, ams_delta_serio driver used to set
	 * handle_simple_irq() as active IRQ handler for that pin to avoid
	 * bad interaction with gpio-omap driver.  This is no longer needed
	 * as handle_simple_irq() is now the default handler for OMAP GPIO
	 * edge interrupts.
	 * This comment replaces the obsolete code which has been removed
	 * from the ams_delta_serio driver and stands here only as a reminder
	 * of that dependency on gpio-omap driver behavior.
	 */

	return;

out_gpio:
	if (data)
		gpiochip_free_own_desc(data);
	if (clk)
		gpiochip_free_own_desc(clk);
}


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

/*
 * arch/arm/mach-omap1/ams-delta-fiq.h
 *
 * Taken from the original Amstrad modifications to fiq.h
 *
 * Copyright (c) 2004 Amstrad Plc
 * Copyright (c) 2006 Matt Callow
 * Copyright (c) 2010 Janusz Krzysztofik
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#ifndef __AMS_DELTA_FIQ_H
#define __AMS_DELTA_FIQ_H

#include "irqs.h"

/*
 * Interrupt number used for passing control from FIQ to IRQ.
 * IRQ12, described as reserved, has been selected.
 */
#define INT_DEFERRED_FIQ	INT_1510_RES12
/*
 * Base address of an interrupt handler that the INT_DEFERRED_FIQ belongs to.
 */
#if (INT_DEFERRED_FIQ < IH2_BASE)
#define DEFERRED_FIQ_IH_BASE	OMAP_IH1_BASE
#else
#define DEFERRED_FIQ_IH_BASE	OMAP_IH2_BASE
#endif

#ifndef __ASSEMBLER__
extern unsigned char qwerty_fiqin_start, qwerty_fiqin_end;

extern void __init ams_delta_init_fiq(struct gpio_chip *chip,
				      struct platform_device *pdev);
#endif

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-ams-delta.c
 *
 * Modified from board-generic.c
 *
 * Board specific inits for the Amstrad E3 (codename Delta) videophone
 *
 * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
 */
#include <linux/gpio/driver.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/mtd/nand-gpio.h>
#include <linux/mtd/partitions.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/fixed.h>
#include <linux/regulator/machine.h>
#include <linux/serial_8250.h>
#include <linux/export.h>
#include <linux/omapfb.h>
#include <linux/io.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/soc/ti/omap1-mux.h>

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

#include <linux/platform_data/keypad-omap.h>

#include "hardware.h"
#include "usb.h"
#include "ams-delta-fiq.h"
#include "board-ams-delta.h"
#include "iomap.h"
#include "common.h"

static const unsigned int ams_delta_keymap[] = {
	KEY(0, 0, KEY_F1),		/* Advert    */

	KEY(0, 3, KEY_COFFEE),		/* Games     */
	KEY(0, 2, KEY_QUESTION),	/* Directory */
	KEY(2, 3, KEY_CONNECT),		/* Internet  */
	KEY(1, 2, KEY_SHOP),		/* Services  */
	KEY(1, 1, KEY_PHONE),		/* VoiceMail */

	KEY(0, 1, KEY_DELETE),		/* Delete    */
	KEY(2, 2, KEY_PLAY),		/* Play      */
	KEY(1, 0, KEY_PAGEUP),		/* Up        */
	KEY(1, 3, KEY_PAGEDOWN),	/* Down      */
	KEY(2, 0, KEY_EMAIL),		/* ReadEmail */
	KEY(2, 1, KEY_STOP),		/* Stop      */

	/* Numeric keypad portion */
	KEY(0, 7, KEY_KP1),
	KEY(0, 6, KEY_KP2),
	KEY(0, 5, KEY_KP3),
	KEY(1, 7, KEY_KP4),
	KEY(1, 6, KEY_KP5),
	KEY(1, 5, KEY_KP6),
	KEY(2, 7, KEY_KP7),
	KEY(2, 6, KEY_KP8),
	KEY(2, 5, KEY_KP9),
	KEY(3, 6, KEY_KP0),
	KEY(3, 7, KEY_KPASTERISK),
	KEY(3, 5, KEY_KPDOT),		/* # key     */
	KEY(7, 2, KEY_NUMLOCK),		/* Mute      */
	KEY(7, 1, KEY_KPMINUS),		/* Recall    */
	KEY(6, 1, KEY_KPPLUS),		/* Redial    */
	KEY(7, 6, KEY_KPSLASH),		/* Handsfree */
	KEY(6, 0, KEY_ENTER),		/* Video     */

	KEY(7, 4, KEY_CAMERA),		/* Photo     */

	KEY(0, 4, KEY_F2),		/* Home      */
	KEY(1, 4, KEY_F3),		/* Office    */
	KEY(2, 4, KEY_F4),		/* Mobile    */
	KEY(7, 7, KEY_F5),		/* SMS       */
	KEY(7, 5, KEY_F6),		/* Email     */

	/* QWERTY portion of keypad */
	KEY(3, 4, KEY_Q),
	KEY(3, 3, KEY_W),
	KEY(3, 2, KEY_E),
	KEY(3, 1, KEY_R),
	KEY(3, 0, KEY_T),
	KEY(4, 7, KEY_Y),
	KEY(4, 6, KEY_U),
	KEY(4, 5, KEY_I),
	KEY(4, 4, KEY_O),
	KEY(4, 3, KEY_P),

	KEY(4, 2, KEY_A),
	KEY(4, 1, KEY_S),
	KEY(4, 0, KEY_D),
	KEY(5, 7, KEY_F),
	KEY(5, 6, KEY_G),
	KEY(5, 5, KEY_H),
	KEY(5, 4, KEY_J),
	KEY(5, 3, KEY_K),
	KEY(5, 2, KEY_L),

	KEY(5, 1, KEY_Z),
	KEY(5, 0, KEY_X),
	KEY(6, 7, KEY_C),
	KEY(6, 6, KEY_V),
	KEY(6, 5, KEY_B),
	KEY(6, 4, KEY_N),
	KEY(6, 3, KEY_M),
	KEY(6, 2, KEY_SPACE),

	KEY(7, 0, KEY_LEFTSHIFT),	/* Vol up    */
	KEY(7, 3, KEY_LEFTCTRL),	/* Vol down  */
};

#define LATCH1_PHYS	0x01000000
#define LATCH1_VIRT	0xEA000000
#define MODEM_PHYS	0x04000000
#define MODEM_VIRT	0xEB000000
#define LATCH2_PHYS	0x08000000
#define LATCH2_VIRT	0xEC000000

static struct map_desc ams_delta_io_desc[] __initdata = {
	/* AMS_DELTA_LATCH1 */
	{
		.virtual	= LATCH1_VIRT,
		.pfn		= __phys_to_pfn(LATCH1_PHYS),
		.length		= 0x01000000,
		.type		= MT_DEVICE
	},
	/* AMS_DELTA_LATCH2 */
	{
		.virtual	= LATCH2_VIRT,
		.pfn		= __phys_to_pfn(LATCH2_PHYS),
		.length		= 0x01000000,
		.type		= MT_DEVICE
	},
	/* AMS_DELTA_MODEM */
	{
		.virtual	= MODEM_VIRT,
		.pfn		= __phys_to_pfn(MODEM_PHYS),
		.length		= 0x01000000,
		.type		= MT_DEVICE
	}
};

static const struct omap_lcd_config ams_delta_lcd_config __initconst = {
	.ctrl_name	= "internal",
};

static struct omap_usb_config ams_delta_usb_config __initdata = {
	.register_host	= 1,
	.hmc_mode	= 16,
	.pins[0]	= 2,
};

#define LATCH1_NGPIO		8

static struct resource latch1_resources[] = {
	[0] = {
		.name	= "dat",
		.start	= LATCH1_PHYS,
		.end	= LATCH1_PHYS + (LATCH1_NGPIO - 1) / 8,
		.flags	= IORESOURCE_MEM,
	},
};

#define LATCH1_LABEL	"latch1"

static struct bgpio_pdata latch1_pdata = {
	.label	= LATCH1_LABEL,
	.base	= -1,
	.ngpio	= LATCH1_NGPIO,
};

static struct platform_device latch1_gpio_device = {
	.name		= "basic-mmio-gpio",
	.id		= 0,
	.resource	= latch1_resources,
	.num_resources	= ARRAY_SIZE(latch1_resources),
	.dev		= {
		.platform_data	= &latch1_pdata,
	},
};

#define LATCH1_PIN_LED_CAMERA		0
#define LATCH1_PIN_LED_ADVERT		1
#define LATCH1_PIN_LED_MAIL		2
#define LATCH1_PIN_LED_HANDSFREE	3
#define LATCH1_PIN_LED_VOICEMAIL	4
#define LATCH1_PIN_LED_VOICE		5
#define LATCH1_PIN_DOCKIT1		6
#define LATCH1_PIN_DOCKIT2		7

#define LATCH2_NGPIO			16

static struct resource latch2_resources[] = {
	[0] = {
		.name	= "dat",
		.start	= LATCH2_PHYS,
		.end	= LATCH2_PHYS + (LATCH2_NGPIO - 1) / 8,
		.flags	= IORESOURCE_MEM,
	},
};

#define LATCH2_LABEL	"latch2"

static struct bgpio_pdata latch2_pdata = {
	.label	= LATCH2_LABEL,
	.base	= -1,
	.ngpio	= LATCH2_NGPIO,
};

static struct platform_device latch2_gpio_device = {
	.name		= "basic-mmio-gpio",
	.id		= 1,
	.resource	= latch2_resources,
	.num_resources	= ARRAY_SIZE(latch2_resources),
	.dev		= {
		.platform_data	= &latch2_pdata,
	},
};

#define LATCH2_PIN_LCD_VBLEN		0
#define LATCH2_PIN_LCD_NDISP		1
#define LATCH2_PIN_NAND_NCE		2
#define LATCH2_PIN_NAND_NRE		3
#define LATCH2_PIN_NAND_NWP		4
#define LATCH2_PIN_NAND_NWE		5
#define LATCH2_PIN_NAND_ALE		6
#define LATCH2_PIN_NAND_CLE		7
#define LATCH2_PIN_KEYBRD_PWR		8
#define LATCH2_PIN_KEYBRD_DATAOUT	9
#define LATCH2_PIN_SCARD_RSTIN		10
#define LATCH2_PIN_SCARD_CMDVCC		11
#define LATCH2_PIN_MODEM_NRESET		12
#define LATCH2_PIN_MODEM_CODEC		13
#define LATCH2_PIN_HANDSFREE_MUTE	14
#define LATCH2_PIN_HANDSET_MUTE		15

static struct regulator_consumer_supply modem_nreset_consumers[] = {
	REGULATOR_SUPPLY("RESET#", "serial8250.1"),
	REGULATOR_SUPPLY("POR", "cx20442-codec"),
};

static struct regulator_init_data modem_nreset_data = {
	.constraints		= {
		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
		.boot_on		= 1,
	},
	.num_consumer_supplies	= ARRAY_SIZE(modem_nreset_consumers),
	.consumer_supplies	= modem_nreset_consumers,
};

static struct fixed_voltage_config modem_nreset_config = {
	.supply_name		= "modem_nreset",
	.microvolts		= 3300000,
	.startup_delay		= 25000,
	.enabled_at_boot	= 1,
	.init_data		= &modem_nreset_data,
};

static struct platform_device modem_nreset_device = {
	.name	= "reg-fixed-voltage",
	.id	= -1,
	.dev	= {
		.platform_data	= &modem_nreset_config,
	},
};

static struct gpiod_lookup_table ams_delta_nreset_gpiod_table = {
	.dev_id = "reg-fixed-voltage",
	.table = {
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_NRESET,
			    NULL, GPIO_ACTIVE_HIGH),
		{ },
	},
};

struct modem_private_data {
	struct regulator *regulator;
};

static struct modem_private_data modem_priv;

/*
 * Define partitions for flash device
 */

static struct mtd_partition partition_info[] = {
	{ .name		= "Kernel",
	  .offset	= 0,
	  .size		= 3 * SZ_1M + SZ_512K },
	{ .name		= "u-boot",
	  .offset	= 3 * SZ_1M + SZ_512K,
	  .size		= SZ_256K },
	{ .name		= "u-boot params",
	  .offset	= 3 * SZ_1M + SZ_512K + SZ_256K,
	  .size		= SZ_256K },
	{ .name		= "Amstrad LDR",
	  .offset	= 4 * SZ_1M,
	  .size		= SZ_256K },
	{ .name		= "File system",
	  .offset	= 4 * SZ_1M + 1 * SZ_256K,
	  .size		= 27 * SZ_1M },
	{ .name		= "PBL reserved",
	  .offset	= 32 * SZ_1M - 3 * SZ_256K,
	  .size		=  3 * SZ_256K },
};

static struct gpio_nand_platdata nand_platdata = {
	.parts		= partition_info,
	.num_parts	= ARRAY_SIZE(partition_info),
};

static struct platform_device ams_delta_nand_device = {
	.name	= "ams-delta-nand",
	.id	= -1,
	.dev	= {
		.platform_data = &nand_platdata,
	},
};

#define OMAP_GPIO_LABEL		"gpio-0-15"
#define OMAP_MPUIO_LABEL	"mpuio"

static struct gpiod_lookup_table ams_delta_nand_gpio_table = {
	.table = {
		GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_NAND_RB, "rdy",
			    0),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NCE, "nce",
			    GPIO_ACTIVE_LOW),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NRE, "nre",
			    GPIO_ACTIVE_LOW),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWP, "nwp",
			    GPIO_ACTIVE_LOW),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_NWE, "nwe",
			    GPIO_ACTIVE_LOW),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_ALE, "ale", 0),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_NAND_CLE, "cle", 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 0, "data", 0, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 1, "data", 1, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 2, "data", 2, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 3, "data", 3, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 4, "data", 4, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 5, "data", 5, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 6, "data", 6, 0),
		GPIO_LOOKUP_IDX(OMAP_MPUIO_LABEL, 7, "data", 7, 0),
		{ },
	},
};

static struct resource ams_delta_kp_resources[] = {
	[0] = {
		.start	= INT_KEYBOARD,
		.end	= INT_KEYBOARD,
		.flags	= IORESOURCE_IRQ,
	},
};

static const struct matrix_keymap_data ams_delta_keymap_data = {
	.keymap		= ams_delta_keymap,
	.keymap_size	= ARRAY_SIZE(ams_delta_keymap),
};

static struct omap_kp_platform_data ams_delta_kp_data = {
	.rows		= 8,
	.cols		= 8,
	.keymap_data	= &ams_delta_keymap_data,
	.delay		= 9,
};

static struct platform_device ams_delta_kp_device = {
	.name		= "omap-keypad",
	.id		= -1,
	.dev		= {
		.platform_data = &ams_delta_kp_data,
	},
	.num_resources	= ARRAY_SIZE(ams_delta_kp_resources),
	.resource	= ams_delta_kp_resources,
};

static struct platform_device ams_delta_lcd_device = {
	.name	= "lcd_ams_delta",
	.id	= -1,
};

static struct gpiod_lookup_table ams_delta_lcd_gpio_table = {
	.table = {
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_VBLEN, "vblen", 0),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_LCD_NDISP, "ndisp", 0),
		{ },
	},
};

static struct gpio_led gpio_leds[] __initdata = {
	[LATCH1_PIN_LED_CAMERA] = {
		.name		 = "camera",
		.default_state	 = LEDS_GPIO_DEFSTATE_OFF,
	},
	[LATCH1_PIN_LED_ADVERT] = {
		.name		 = "advert",
		.default_state	 = LEDS_GPIO_DEFSTATE_OFF,
	},
	[LATCH1_PIN_LED_MAIL] = {
		.name		 = "email",
		.default_state	 = LEDS_GPIO_DEFSTATE_OFF,
	},
	[LATCH1_PIN_LED_HANDSFREE] = {
		.name		 = "handsfree",
		.default_state	 = LEDS_GPIO_DEFSTATE_OFF,
	},
	[LATCH1_PIN_LED_VOICEMAIL] = {
		.name		 = "voicemail",
		.default_state	 = LEDS_GPIO_DEFSTATE_OFF,
	},
	[LATCH1_PIN_LED_VOICE] = {
		.name		 = "voice",
		.default_state	 = LEDS_GPIO_DEFSTATE_OFF,
	},
};

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

static struct gpiod_lookup_table leds_gpio_table = {
	.table = {
		GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_CAMERA, NULL,
				LATCH1_PIN_LED_CAMERA, 0),
		GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_ADVERT, NULL,
				LATCH1_PIN_LED_ADVERT, 0),
		GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_MAIL, NULL,
				LATCH1_PIN_LED_MAIL, 0),
		GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_HANDSFREE, NULL,
				LATCH1_PIN_LED_HANDSFREE, 0),
		GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_VOICEMAIL, NULL,
				LATCH1_PIN_LED_VOICEMAIL, 0),
		GPIO_LOOKUP_IDX(LATCH1_LABEL, LATCH1_PIN_LED_VOICE, NULL,
				LATCH1_PIN_LED_VOICE, 0),
		{ },
	},
};

static struct platform_device ams_delta_audio_device = {
	.name   = "ams-delta-audio",
	.id     = -1,
};

static struct gpiod_lookup_table ams_delta_audio_gpio_table = {
	.table = {
		GPIO_LOOKUP(OMAP_GPIO_LABEL, AMS_DELTA_GPIO_PIN_HOOK_SWITCH,
			    "hook_switch", 0),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_MODEM_CODEC,
			    "modem_codec", 0),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSFREE_MUTE,
			    "handsfree_mute", 0),
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_HANDSET_MUTE,
			    "handset_mute", 0),
		{ },
	},
};

static struct platform_device cx20442_codec_device = {
	.name   = "cx20442-codec",
	.id     = -1,
};

static struct resource ams_delta_serio_resources[] = {
	{
		.flags	= IORESOURCE_IRQ,
		/*
		 * Initialize IRQ resource with invalid IRQ number.
		 * It will be replaced with dynamically allocated GPIO IRQ
		 * obtained from GPIO chip as soon as the chip is available.
		 */
		.start	= -EINVAL,
		.end	= -EINVAL,
	},
};

static struct platform_device ams_delta_serio_device = {
	.name		= "ams-delta-serio",
	.id		= PLATFORM_DEVID_NONE,
	.dev		= {
		/*
		 * Initialize .platform_data explicitly with NULL to
		 * indicate it is going to be used.  It will be replaced
		 * with FIQ buffer address as soon as FIQ is initialized.
		 */
		.platform_data = NULL,
	},
	.num_resources	= ARRAY_SIZE(ams_delta_serio_resources),
	.resource	= ams_delta_serio_resources,
};

static struct regulator_consumer_supply keybrd_pwr_consumers[] = {
	/*
	 * Initialize supply .dev_name with NULL.  It will be replaced
	 * with serio dev_name() as soon as the serio device is registered.
	 */
	REGULATOR_SUPPLY("vcc", NULL),
};

static struct regulator_init_data keybrd_pwr_initdata = {
	.constraints		= {
		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
	},
	.num_consumer_supplies	= ARRAY_SIZE(keybrd_pwr_consumers),
	.consumer_supplies	= keybrd_pwr_consumers,
};

static struct fixed_voltage_config keybrd_pwr_config = {
	.supply_name		= "keybrd_pwr",
	.microvolts		= 5000000,
	.init_data		= &keybrd_pwr_initdata,
};

static struct platform_device keybrd_pwr_device = {
	.name	= "reg-fixed-voltage",
	.id	= PLATFORM_DEVID_AUTO,
	.dev	= {
		.platform_data	= &keybrd_pwr_config,
	},
};

static struct gpiod_lookup_table keybrd_pwr_gpio_table = {
	.table = {
		GPIO_LOOKUP(LATCH2_LABEL, LATCH2_PIN_KEYBRD_PWR, NULL,
			    GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct platform_device *ams_delta_devices[] __initdata = {
	&latch1_gpio_device,
	&latch2_gpio_device,
	&ams_delta_kp_device,
	&ams_delta_audio_device,
	&ams_delta_serio_device,
	&ams_delta_nand_device,
	&ams_delta_lcd_device,
	&cx20442_codec_device,
};

static struct gpiod_lookup_table *ams_delta_gpio_tables[] __initdata = {
	&ams_delta_nreset_gpiod_table,
	&ams_delta_audio_gpio_table,
	&keybrd_pwr_gpio_table,
	&ams_delta_lcd_gpio_table,
	&ams_delta_nand_gpio_table,
};

/*
 * Some drivers may not use GPIO lookup tables but need to be provided
 * with GPIO numbers.  The same applies to GPIO based IRQ lines - some
 * drivers may even not use GPIO layer but expect just IRQ numbers.
 * We could either define GPIO lookup tables then use them on behalf
 * of those devices, or we can use GPIO driver level methods for
 * identification of GPIO and IRQ numbers. For the purpose of the latter,
 * defina a helper function which identifies GPIO chips by their labels.
 */
static int gpiochip_match_by_label(struct gpio_chip *chip, void *data)
{
	char *label = data;

	return !strcmp(label, chip->label);
}

static struct gpiod_hog ams_delta_gpio_hogs[] = {
	GPIO_HOG(LATCH2_LABEL, LATCH2_PIN_KEYBRD_DATAOUT, "keybrd_dataout",
		 GPIO_ACTIVE_HIGH, GPIOD_OUT_LOW),
	{},
};

static struct plat_serial8250_port ams_delta_modem_ports[];

/*
 * Obtain MODEM IRQ GPIO descriptor using its hardware pin
 * number and assign related IRQ number to the MODEM port.
 * Keep the GPIO descriptor open so nobody steps in.
 */
static void __init modem_assign_irq(struct gpio_chip *chip)
{
	struct gpio_desc *gpiod;

	gpiod = gpiochip_request_own_desc(chip, AMS_DELTA_GPIO_PIN_MODEM_IRQ,
					  "modem_irq", GPIO_ACTIVE_HIGH,
					  GPIOD_IN);
	if (IS_ERR(gpiod)) {
		pr_err("%s: modem IRQ GPIO request failed (%ld)\n", __func__,
		       PTR_ERR(gpiod));
	} else {
		ams_delta_modem_ports[0].irq = gpiod_to_irq(gpiod);
	}
}

/*
 * The purpose of this function is to take care of proper initialization of
 * devices and data structures which depend on GPIO lines provided by OMAP GPIO
 * banks but their drivers don't use GPIO lookup tables or GPIO layer at all.
 * The function may be called as soon as OMAP GPIO devices are probed.
 * Since that happens at postcore_initcall, it can be called successfully
 * from init_machine or later.
 * Dependent devices may be registered from within this function or later.
 */
static void __init omap_gpio_deps_init(void)
{
	struct gpio_chip *chip;

	chip = gpiochip_find(OMAP_GPIO_LABEL, gpiochip_match_by_label);
	if (!chip) {
		pr_err("%s: OMAP GPIO chip not found\n", __func__);
		return;
	}

	/*
	 * Start with FIQ initialization as it may have to request
	 * and release successfully each OMAP GPIO pin in turn.
	 */
	ams_delta_init_fiq(chip, &ams_delta_serio_device);

	modem_assign_irq(chip);
}

/*
 * Initialize latch2 pins with values which are safe for dependent on-board
 * devices or useful for their successull initialization even before GPIO
 * driver takes control over the latch pins:
 * - LATCH2_PIN_LCD_VBLEN	= 0
 * - LATCH2_PIN_LCD_NDISP	= 0	Keep LCD device powered off before its
 *					driver takes control over it.
 * - LATCH2_PIN_NAND_NCE	= 0
 * - LATCH2_PIN_NAND_NWP	= 0	Keep NAND device down and write-
 *					protected before its driver takes
 *					control over it.
 * - LATCH2_PIN_KEYBRD_PWR	= 0	Keep keyboard powered off before serio
 *					driver takes control over it.
 * - LATCH2_PIN_KEYBRD_DATAOUT	= 0	Keep low to avoid corruption of first
 *					byte of data received from attached
 *					keyboard when serio device is probed;
 *					the pin is also hogged low by the latch2
 *					GPIO driver as soon as it is ready.
 * - LATCH2_PIN_MODEM_NRESET	= 1	Enable voice MODEM device, allowing for
 *					its successful probe even before a
 *					regulator it depends on, which in turn
 *					takes control over the pin, is set up.
 * - LATCH2_PIN_MODEM_CODEC	= 1	Attach voice MODEM CODEC data port
 *					to the MODEM so the CODEC is under
 *					control even if audio driver doesn't
 *					take it over.
 */
static void __init ams_delta_latch2_init(void)
{
	u16 latch2 = 1 << LATCH2_PIN_MODEM_NRESET | 1 << LATCH2_PIN_MODEM_CODEC;

	__raw_writew(latch2, IOMEM(LATCH2_VIRT));
}

static void __init ams_delta_init(void)
{
	struct platform_device *leds_pdev;

	/* mux pins for uarts */
	omap_cfg_reg(UART1_TX);
	omap_cfg_reg(UART1_RTS);

	/* parallel camera interface */
	omap_cfg_reg(H19_1610_CAM_EXCLK);
	omap_cfg_reg(J15_1610_CAM_LCLK);
	omap_cfg_reg(L18_1610_CAM_VS);
	omap_cfg_reg(L15_1610_CAM_HS);
	omap_cfg_reg(L19_1610_CAM_D0);
	omap_cfg_reg(K14_1610_CAM_D1);
	omap_cfg_reg(K15_1610_CAM_D2);
	omap_cfg_reg(K19_1610_CAM_D3);
	omap_cfg_reg(K18_1610_CAM_D4);
	omap_cfg_reg(J14_1610_CAM_D5);
	omap_cfg_reg(J19_1610_CAM_D6);
	omap_cfg_reg(J18_1610_CAM_D7);

	omap_gpio_deps_init();
	ams_delta_latch2_init();
	gpiod_add_hogs(ams_delta_gpio_hogs);

	omap_serial_init();
	omap_register_i2c_bus(1, 100, NULL, 0);

	omap1_usb_init(&ams_delta_usb_config);
	platform_add_devices(ams_delta_devices, ARRAY_SIZE(ams_delta_devices));

	/*
	 * As soon as regulator consumers have been registered, assign their
	 * dev_names to consumer supply entries of respective regulators.
	 */
	keybrd_pwr_consumers[0].dev_name =
			dev_name(&ams_delta_serio_device.dev);

	/*
	 * Once consumer supply entries are populated with dev_names,
	 * register regulator devices.  At this stage only the keyboard
	 * power regulator has its consumer supply table fully populated.
	 */
	platform_device_register(&keybrd_pwr_device);

	/*
	 * As soon as GPIO consumers have been registered, assign
	 * their dev_names to respective GPIO lookup tables.
	 */
	ams_delta_audio_gpio_table.dev_id =
			dev_name(&ams_delta_audio_device.dev);
	keybrd_pwr_gpio_table.dev_id = dev_name(&keybrd_pwr_device.dev);
	ams_delta_nand_gpio_table.dev_id = dev_name(&ams_delta_nand_device.dev);
	ams_delta_lcd_gpio_table.dev_id = dev_name(&ams_delta_lcd_device.dev);

	/*
	 * Once GPIO lookup tables are populated with dev_names, register them.
	 */
	gpiod_add_lookup_tables(ams_delta_gpio_tables,
				ARRAY_SIZE(ams_delta_gpio_tables));

	leds_pdev = gpio_led_register_device(PLATFORM_DEVID_NONE, &leds_pdata);
	if (!IS_ERR_OR_NULL(leds_pdev)) {
		leds_gpio_table.dev_id = dev_name(&leds_pdev->dev);
		gpiod_add_lookup_table(&leds_gpio_table);
	}

	omap_writew(omap_readw(ARM_RSTCT1) | 0x0004, ARM_RSTCT1);

	omapfb_set_lcd_config(&ams_delta_lcd_config);
}

static void modem_pm(struct uart_port *port, unsigned int state, unsigned old)
{
	struct modem_private_data *priv = port->private_data;
	int ret;

	if (!priv)
		return;

	if (IS_ERR(priv->regulator))
		return;

	if (state == old)
		return;

	if (state == 0)
		ret = regulator_enable(priv->regulator);
	else if (old == 0)
		ret = regulator_disable(priv->regulator);
	else
		ret = 0;

	if (ret)
		dev_warn(port->dev,
			 "ams_delta modem_pm: failed to %sable regulator: %d\n",
			 state ? "dis" : "en", ret);
}

static struct plat_serial8250_port ams_delta_modem_ports[] = {
	{
		.membase	= IOMEM(MODEM_VIRT),
		.mapbase	= MODEM_PHYS,
		.irq		= IRQ_NOTCONNECTED, /* changed later */
		.flags		= UPF_BOOT_AUTOCONF,
		.irqflags	= IRQF_TRIGGER_RISING,
		.iotype		= UPIO_MEM,
		.regshift	= 1,
		.uartclk	= BASE_BAUD * 16,
		.pm		= modem_pm,
		.private_data	= &modem_priv,
	},
	{ },
};

static struct platform_device ams_delta_modem_device = {
	.name	= "serial8250",
	.id	= PLAT8250_DEV_PLATFORM1,
	.dev		= {
		.platform_data = ams_delta_modem_ports,
	},
};

static int __init modem_nreset_init(void)
{
	int err;

	err = platform_device_register(&modem_nreset_device);
	if (err)
		pr_err("Couldn't register the modem regulator device\n");

	return err;
}

/*
 * This function expects MODEM IRQ number already assigned to the port.
 * The MODEM device requires its RESET# pin kept high during probe.
 * That requirement can be fulfilled in several ways:
 * - with a descriptor of already functional modem_nreset regulator
 *   assigned to the MODEM private data,
 * - with the regulator not yet controlled by modem_pm function but
 *   already enabled by default on probe,
 * - before the modem_nreset regulator is probed, with the pin already
 *   set high explicitly.
 * The last one is already guaranteed by ams_delta_latch2_init() called
 * from machine_init.
 * In order to avoid taking over ttyS0 device slot, the MODEM device
 * should be registered after OMAP serial ports.  Since those ports
 * are registered at arch_initcall, this function can be called safely
 * at arch_initcall_sync earliest.
 */
static int __init ams_delta_modem_init(void)
{
	int err;

	if (!machine_is_ams_delta())
		return -ENODEV;

	omap_cfg_reg(M14_1510_GPIO2);

	/* Initialize the modem_nreset regulator consumer before use */
	modem_priv.regulator = ERR_PTR(-ENODEV);

	err = platform_device_register(&ams_delta_modem_device);

	return err;
}
arch_initcall_sync(ams_delta_modem_init);

static int __init late_init(void)
{
	int err;

	err = modem_nreset_init();
	if (err)
		return err;

	/*
	 * Once the modem device is registered, the modem_nreset
	 * regulator can be requested on behalf of that device.
	 */
	modem_priv.regulator = regulator_get(&ams_delta_modem_device.dev,
			"RESET#");
	if (IS_ERR(modem_priv.regulator)) {
		err = PTR_ERR(modem_priv.regulator);
		goto unregister;
	}
	return 0;

unregister:
	platform_device_unregister(&ams_delta_modem_device);
	return err;
}

static void __init ams_delta_init_late(void)
{
	omap1_init_late();
	late_init();
}

static void __init ams_delta_map_io(void)
{
	omap15xx_map_io();
	iotable_init(ams_delta_io_desc, ARRAY_SIZE(ams_delta_io_desc));
}

MACHINE_START(AMS_DELTA, "Amstrad E3 (Delta)")
	/* Maintainer: Jonathan McDowell <noodles@earth.li> */
	.atag_offset	= 0x100,
	.map_io		= ams_delta_map_io,
	.init_early	= omap1_init_early,
	.init_irq	= omap1_init_irq,
	.handle_irq	= omap1_handle_irq,
	.init_machine	= ams_delta_init,
	.init_late	= ams_delta_init_late,
	.init_time	= omap1_timer_init,
	.restart	= omap1_restart,
MACHINE_END


code:
/*
 * arch/arm/mach-omap1/board-ams-delta.h
 *
 * Copyright (C) 2006 Jonathan McDowell <noodles@earth.li>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#ifndef __ASM_ARCH_OMAP_AMS_DELTA_H
#define __ASM_ARCH_OMAP_AMS_DELTA_H

#if defined (CONFIG_MACH_AMS_DELTA)

#define AMS_DELTA_GPIO_PIN_KEYBRD_DATA	0
#define AMS_DELTA_GPIO_PIN_KEYBRD_CLK	1
#define AMS_DELTA_GPIO_PIN_MODEM_IRQ	2
#define AMS_DELTA_GPIO_PIN_HOOK_SWITCH	4
#define AMS_DELTA_GPIO_PIN_SCARD_NOFF	6
#define AMS_DELTA_GPIO_PIN_SCARD_IO	7
#define AMS_DELTA_GPIO_PIN_CONFIG	11
#define AMS_DELTA_GPIO_PIN_NAND_RB	12

#endif /* CONFIG_MACH_AMS_DELTA */

#endif /* __ASM_ARCH_OMAP_AMS_DELTA_H */


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-fsample.c
 *
 * Modified from board-perseus2.c
 *
 * Original OMAP730 support by Jean Pihet <j-pihet@ti.com>
 * Updated for 2.6 by Kevin Hilman <kjh@hilman.org>
 */
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/smc91x.h>
#include <linux/omapfb.h>

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

#include <linux/soc/ti/omap1-io.h>
#include <linux/platform_data/keypad-omap.h>
#include "tc.h"

#include "mux.h"
#include "flash.h"
#include "hardware.h"
#include "iomap.h"
#include "common.h"
#include "fpga.h"

/* fsample is pretty close to p2-sample */

#define fsample_cpld_read(reg) __raw_readb(reg)
#define fsample_cpld_write(val, reg) __raw_writeb(val, reg)

#define FSAMPLE_CPLD_BASE    0xE8100000
#define FSAMPLE_CPLD_SIZE    SZ_4K
#define FSAMPLE_CPLD_START   0x05080000

#define FSAMPLE_CPLD_REG_A   (FSAMPLE_CPLD_BASE + 0x00)
#define FSAMPLE_CPLD_SWITCH  (FSAMPLE_CPLD_BASE + 0x02)
#define FSAMPLE_CPLD_UART    (FSAMPLE_CPLD_BASE + 0x02)
#define FSAMPLE_CPLD_REG_B   (FSAMPLE_CPLD_BASE + 0x04)
#define FSAMPLE_CPLD_VERSION (FSAMPLE_CPLD_BASE + 0x06)
#define FSAMPLE_CPLD_SET_CLR (FSAMPLE_CPLD_BASE + 0x06)

#define FSAMPLE_CPLD_BIT_BT_RESET         0
#define FSAMPLE_CPLD_BIT_LCD_RESET        1
#define FSAMPLE_CPLD_BIT_CAM_PWDN         2
#define FSAMPLE_CPLD_BIT_CHARGER_ENABLE   3
#define FSAMPLE_CPLD_BIT_SD_MMC_EN        4
#define FSAMPLE_CPLD_BIT_aGPS_PWREN       5
#define FSAMPLE_CPLD_BIT_BACKLIGHT        6
#define FSAMPLE_CPLD_BIT_aGPS_EN_RESET    7
#define FSAMPLE_CPLD_BIT_aGPS_SLEEPx_N    8
#define FSAMPLE_CPLD_BIT_OTG_RESET        9

#define fsample_cpld_set(bit) \
    fsample_cpld_write((((bit) & 15) << 4) | 0x0f, FSAMPLE_CPLD_SET_CLR)

#define fsample_cpld_clear(bit) \
    fsample_cpld_write(0xf0 | ((bit) & 15), FSAMPLE_CPLD_SET_CLR)

static const unsigned int fsample_keymap[] = {
	KEY(0, 0, KEY_UP),
	KEY(1, 0, KEY_RIGHT),
	KEY(2, 0, KEY_LEFT),
	KEY(3, 0, KEY_DOWN),
	KEY(4, 0, KEY_ENTER),
	KEY(0, 1, KEY_F10),
	KEY(1, 1, KEY_SEND),
	KEY(2, 1, KEY_END),
	KEY(3, 1, KEY_VOLUMEDOWN),
	KEY(4, 1, KEY_VOLUMEUP),
	KEY(5, 1, KEY_RECORD),
	KEY(0, 2, KEY_F9),
	KEY(1, 2, KEY_3),
	KEY(2, 2, KEY_6),
	KEY(3, 2, KEY_9),
	KEY(4, 2, KEY_KPDOT),
	KEY(0, 3, KEY_BACK),
	KEY(1, 3, KEY_2),
	KEY(2, 3, KEY_5),
	KEY(3, 3, KEY_8),
	KEY(4, 3, KEY_0),
	KEY(5, 3, KEY_KPSLASH),
	KEY(0, 4, KEY_HOME),
	KEY(1, 4, KEY_1),
	KEY(2, 4, KEY_4),
	KEY(3, 4, KEY_7),
	KEY(4, 4, KEY_KPASTERISK),
	KEY(5, 4, KEY_POWER),
};

static struct smc91x_platdata smc91x_info = {
	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
	.leda	= RPC_LED_100_10,
	.ledb	= RPC_LED_TX_RX,
};

static struct resource smc91x_resources[] = {
	[0] = {
		.start	= H2P2_DBG_FPGA_ETHR_START,	/* Physical */
		.end	= H2P2_DBG_FPGA_ETHR_START + 0xf,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= INT_7XX_MPU_EXT_NIRQ,
		.end	= 0,
		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
	},
};

static void __init fsample_init_smc91x(void)
{
	__raw_writeb(1, H2P2_DBG_FPGA_LAN_RESET);
	mdelay(50);
	__raw_writeb(__raw_readb(H2P2_DBG_FPGA_LAN_RESET) & ~1,
		   H2P2_DBG_FPGA_LAN_RESET);
	mdelay(50);
}

static struct mtd_partition nor_partitions[] = {
	/* bootloader (U-Boot, etc) in first sector */
	{
	      .name		= "bootloader",
	      .offset		= 0,
	      .size		= SZ_128K,
	      .mask_flags	= MTD_WRITEABLE, /* force read-only */
	},
	/* bootloader params in the next sector */
	{
	      .name		= "params",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= SZ_128K,
	      .mask_flags	= 0,
	},
	/* kernel */
	{
	      .name		= "kernel",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= SZ_2M,
	      .mask_flags	= 0
	},
	/* rest of flash is a file system */
	{
	      .name		= "rootfs",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= MTDPART_SIZ_FULL,
	      .mask_flags	= 0
	},
};

static struct physmap_flash_data nor_data = {
	.width		= 2,
	.set_vpp	= omap1_set_vpp,
	.parts		= nor_partitions,
	.nr_parts	= ARRAY_SIZE(nor_partitions),
};

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

static struct platform_device nor_device = {
	.name		= "physmap-flash",
	.id		= 0,
	.dev		= {
		.platform_data	= &nor_data,
	},
	.num_resources	= 1,
	.resource	= &nor_resource,
};

#define FSAMPLE_NAND_RB_GPIO_PIN	62

static int nand_dev_ready(struct nand_chip *chip)
{
	return gpio_get_value(FSAMPLE_NAND_RB_GPIO_PIN);
}

static struct platform_nand_data nand_data = {
	.chip	= {
		.nr_chips		= 1,
		.chip_offset		= 0,
		.options		= NAND_SAMSUNG_LP_OPTIONS,
	},
	.ctrl	= {
		.cmd_ctrl	= omap1_nand_cmd_ctl,
		.dev_ready	= nand_dev_ready,
	},
};

static struct resource nand_resource = {
	.start		= OMAP_CS3_PHYS,
	.end		= OMAP_CS3_PHYS + SZ_4K - 1,
	.flags		= IORESOURCE_MEM,
};

static struct platform_device nand_device = {
	.name		= "gen_nand",
	.id		= 0,
	.dev		= {
		.platform_data	= &nand_data,
	},
	.num_resources	= 1,
	.resource	= &nand_resource,
};

static struct platform_device smc91x_device = {
	.name		= "smc91x",
	.id		= 0,
	.dev	= {
		.platform_data	= &smc91x_info,
	},
	.num_resources	= ARRAY_SIZE(smc91x_resources),
	.resource	= smc91x_resources,
};

static struct resource kp_resources[] = {
	[0] = {
		.start	= INT_7XX_MPUIO_KEYPAD,
		.end	= INT_7XX_MPUIO_KEYPAD,
		.flags	= IORESOURCE_IRQ,
	},
};

static const struct matrix_keymap_data fsample_keymap_data = {
	.keymap		= fsample_keymap,
	.keymap_size	= ARRAY_SIZE(fsample_keymap),
};

static struct omap_kp_platform_data kp_data = {
	.rows		= 8,
	.cols		= 8,
	.keymap_data	= &fsample_keymap_data,
	.delay		= 4,
};

static struct platform_device kp_device = {
	.name		= "omap-keypad",
	.id		= -1,
	.dev		= {
		.platform_data = &kp_data,
	},
	.num_resources	= ARRAY_SIZE(kp_resources),
	.resource	= kp_resources,
};

static struct platform_device *devices[] __initdata = {
	&nor_device,
	&nand_device,
	&smc91x_device,
	&kp_device,
};

static const struct omap_lcd_config fsample_lcd_config = {
	.ctrl_name	= "internal",
};

static void __init omap_fsample_init(void)
{
	/* Early, board-dependent init */

	/*
	 * Hold GSM Reset until needed
	 */
	omap_writew(omap_readw(OMAP7XX_DSP_M_CTL) & ~1, OMAP7XX_DSP_M_CTL);

	/*
	 * UARTs -> done automagically by 8250 driver
	 */

	/*
	 * CSx timings, GPIO Mux ... setup
	 */

	/* Flash: CS0 timings setup */
	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_0);
	omap_writel(0x00000088, OMAP7XX_FLASH_ACFG_0);

	/*
	 * Ethernet support through the debug board
	 * CS1 timings setup
	 */
	omap_writel(0x0000fff3, OMAP7XX_FLASH_CFG_1);
	omap_writel(0x00000000, OMAP7XX_FLASH_ACFG_1);

	/*
	 * Configure MPU_EXT_NIRQ IO in IO_CONF9 register,
	 * It is used as the Ethernet controller interrupt
	 */
	omap_writel(omap_readl(OMAP7XX_IO_CONF_9) & 0x1FFFFFFF,
			OMAP7XX_IO_CONF_9);

	fsample_init_smc91x();

	BUG_ON(gpio_request(FSAMPLE_NAND_RB_GPIO_PIN, "NAND ready") < 0);
	gpio_direction_input(FSAMPLE_NAND_RB_GPIO_PIN);

	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
	omap_cfg_reg(M8_1610_FLASH_CS2B_WE);

	/* Mux pins for keypad */
	omap_cfg_reg(E2_7XX_KBR0);
	omap_cfg_reg(J7_7XX_KBR1);
	omap_cfg_reg(E1_7XX_KBR2);
	omap_cfg_reg(F3_7XX_KBR3);
	omap_cfg_reg(D2_7XX_KBR4);
	omap_cfg_reg(C2_7XX_KBC0);
	omap_cfg_reg(D3_7XX_KBC1);
	omap_cfg_reg(E4_7XX_KBC2);
	omap_cfg_reg(F4_7XX_KBC3);
	omap_cfg_reg(E3_7XX_KBC4);

	platform_add_devices(devices, ARRAY_SIZE(devices));

	omap_serial_init();
	omap_register_i2c_bus(1, 100, NULL, 0);

	omapfb_set_lcd_config(&fsample_lcd_config);
}

/* Only FPGA needs to be mapped here. All others are done with ioremap */
static struct map_desc omap_fsample_io_desc[] __initdata = {
	{
		.virtual	= H2P2_DBG_FPGA_BASE,
		.pfn		= __phys_to_pfn(H2P2_DBG_FPGA_START),
		.length		= H2P2_DBG_FPGA_SIZE,
		.type		= MT_DEVICE
	},
	{
		.virtual	= FSAMPLE_CPLD_BASE,
		.pfn		= __phys_to_pfn(FSAMPLE_CPLD_START),
		.length		= FSAMPLE_CPLD_SIZE,
		.type		= MT_DEVICE
	}
};

static void __init omap_fsample_map_io(void)
{
	omap15xx_map_io();
	iotable_init(omap_fsample_io_desc,
		     ARRAY_SIZE(omap_fsample_io_desc));
}

MACHINE_START(OMAP_FSAMPLE, "OMAP730 F-Sample")
/* Maintainer: Brian Swetland <swetland@google.com> */
	.atag_offset	= 0x100,
	.map_io		= omap_fsample_map_io,
	.init_early	= omap1_init_early,
	.init_irq	= omap1_init_irq,
	.handle_irq	= omap1_handle_irq,
	.init_machine	= omap_fsample_init,
	.init_late	= omap1_init_late,
	.init_time	= omap1_timer_init,
	.restart	= omap1_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-generic.c
 *
 * Modified from board-innovator1510.c
 *
 * Code for generic OMAP board. Should work on many OMAP systems where
 * the device drivers take care of all the necessary hardware initialization.
 * Do not put any board specific code to this file; create a new machine
 * type if you need custom low-level initializations.
 */
#include <linux/gpio.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>

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

#include "hardware.h"
#include "mux.h"
#include "usb.h"
#include "common.h"

/* assume no Mini-AB port */

#ifdef CONFIG_ARCH_OMAP15XX
static struct omap_usb_config generic1510_usb_config __initdata = {
	.register_host	= 1,
	.register_dev	= 1,
	.hmc_mode	= 16,
	.pins[0]	= 3,
};
#endif

#if defined(CONFIG_ARCH_OMAP16XX)
static struct omap_usb_config generic1610_usb_config __initdata = {
#ifdef CONFIG_USB_OTG
	.otg		= 1,
#endif
	.register_host	= 1,
	.register_dev	= 1,
	.hmc_mode	= 16,
	.pins[0]	= 6,
};
#endif

static void __init omap_generic_init(void)
{
#ifdef CONFIG_ARCH_OMAP15XX
	if (cpu_is_omap15xx()) {
		/* mux pins for uarts */
		omap_cfg_reg(UART1_TX);
		omap_cfg_reg(UART1_RTS);
		omap_cfg_reg(UART2_TX);
		omap_cfg_reg(UART2_RTS);
		omap_cfg_reg(UART3_TX);
		omap_cfg_reg(UART3_RX);

		omap1_usb_init(&generic1510_usb_config);
	}
#endif
#if defined(CONFIG_ARCH_OMAP16XX)
	if (!cpu_is_omap1510()) {
		omap1_usb_init(&generic1610_usb_config);
	}
#endif

	omap_serial_init();
	omap_register_i2c_bus(1, 100, NULL, 0);
}

MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710")
	/* Maintainer: Tony Lindgren <tony@atomide.com> */
	.atag_offset	= 0x100,
	.map_io		= omap16xx_map_io,
	.init_early	= omap1_init_early,
	.init_irq	= omap1_init_irq,
	.handle_irq	= omap1_handle_irq,
	.init_machine	= omap_generic_init,
	.init_late	= omap1_init_late,
	.init_time	= omap1_timer_init,
	.restart	= omap1_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-h2-mmc.c
 *
 * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
 * Author: Felipe Balbi <felipe.lima@indt.org.br>
 *
 * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
 * Copyright (C) 2006 Nokia Corporation
 */
#include <linux/gpio.h>
#include <linux/platform_device.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/mfd/tps65010.h>

#include "board-h2.h"
#include "mmc.h"

#if IS_ENABLED(CONFIG_MMC_OMAP)

static int mmc_set_power(struct device *dev, int slot, int power_on,
				int vdd)
{
	gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on);
	return 0;
}

static int mmc_late_init(struct device *dev)
{
	int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
	if (ret < 0)
		return ret;

	gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);

	return ret;
}

static void mmc_cleanup(struct device *dev)
{
	gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
}

/*
 * H2 could use the following functions tested:
 * - mmc_get_cover_state that uses OMAP_MPUIO(1)
 * - mmc_get_wp that uses OMAP_MPUIO(3)
 */
static struct omap_mmc_platform_data mmc1_data = {
	.nr_slots                       = 1,
	.init				= mmc_late_init,
	.cleanup			= mmc_cleanup,
	.slots[0]       = {
		.set_power              = mmc_set_power,
		.ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
		.name                   = "mmcblk",
	},
};

static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];

void __init h2_mmc_init(void)
{
	mmc_data[0] = &mmc1_data;
	omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
}

#else

void __init h2_mmc_init(void)
{
}

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-h2.c
 *
 * Board specific inits for OMAP-1610 H2
 *
 * Copyright (C) 2001 RidgeRun, Inc.
 * Author: Greg Lonnon <glonnon@ridgerun.com>
 *
 * Copyright (C) 2002 MontaVista Software, Inc.
 *
 * Separated FPGA interrupts from innovator1510.c and cleaned up for 2.6
 * Copyright (C) 2004 Nokia Corporation by Tony Lindrgen <tony@atomide.com>
 *
 * H2 specific changes and cleanup
 * Copyright (C) 2004 Nokia Corporation by Imre Deak <imre.deak@nokia.com>
 */
#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/mfd/tps65010.h>
#include <linux/smc91x.h>
#include <linux/omapfb.h>
#include <linux/omap-dma.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/platform_data/keypad-omap.h>
#include <linux/leds.h>

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

#include "tc.h"
#include "mux.h"
#include "flash.h"
#include "hardware.h"
#include "usb.h"
#include "common.h"
#include "board-h2.h"

/* The first 16 SoC GPIO lines are on this GPIO chip */
#define OMAP_GPIO_LABEL			"gpio-0-15"

/* At OMAP1610 Innovator the Ethernet is directly connected to CS1 */
#define OMAP1610_ETHR_START		0x04000300

static const unsigned int h2_keymap[] = {
	KEY(0, 0, KEY_LEFT),
	KEY(1, 0, KEY_RIGHT),
	KEY(2, 0, KEY_3),
	KEY(3, 0, KEY_F10),
	KEY(4, 0, KEY_F5),
	KEY(5, 0, KEY_9),
	KEY(0, 1, KEY_DOWN),
	KEY(1, 1, KEY_UP),
	KEY(2, 1, KEY_2),
	KEY(3, 1, KEY_F9),
	KEY(4, 1, KEY_F7),
	KEY(5, 1, KEY_0),
	KEY(0, 2, KEY_ENTER),
	KEY(1, 2, KEY_6),
	KEY(2, 2, KEY_1),
	KEY(3, 2, KEY_F2),
	KEY(4, 2, KEY_F6),
	KEY(5, 2, KEY_HOME),
	KEY(0, 3, KEY_8),
	KEY(1, 3, KEY_5),
	KEY(2, 3, KEY_F12),
	KEY(3, 3, KEY_F3),
	KEY(4, 3, KEY_F8),
	KEY(5, 3, KEY_END),
	KEY(0, 4, KEY_7),
	KEY(1, 4, KEY_4),
	KEY(2, 4, KEY_F11),
	KEY(3, 4, KEY_F1),
	KEY(4, 4, KEY_F4),
	KEY(5, 4, KEY_ESC),
	KEY(0, 5, KEY_F13),
	KEY(1, 5, KEY_F14),
	KEY(2, 5, KEY_F15),
	KEY(3, 5, KEY_F16),
	KEY(4, 5, KEY_SLEEP),
};

static struct mtd_partition h2_nor_partitions[] = {
	/* bootloader (U-Boot, etc) in first sector */
	{
	      .name		= "bootloader",
	      .offset		= 0,
	      .size		= SZ_128K,
	      .mask_flags	= MTD_WRITEABLE, /* force read-only */
	},
	/* bootloader params in the next sector */
	{
	      .name		= "params",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= SZ_128K,
	      .mask_flags	= 0,
	},
	/* kernel */
	{
	      .name		= "kernel",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= SZ_2M,
	      .mask_flags	= 0
	},
	/* file system */
	{
	      .name		= "filesystem",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= MTDPART_SIZ_FULL,
	      .mask_flags	= 0
	}
};

static struct physmap_flash_data h2_nor_data = {
	.width		= 2,
	.set_vpp	= omap1_set_vpp,
	.parts		= h2_nor_partitions,
	.nr_parts	= ARRAY_SIZE(h2_nor_partitions),
};

static struct resource h2_nor_resource = {
	/* This is on CS3, wherever it's mapped */
	.flags		= IORESOURCE_MEM,
};

static struct platform_device h2_nor_device = {
	.name		= "physmap-flash",
	.id		= 0,
	.dev		= {
		.platform_data	= &h2_nor_data,
	},
	.num_resources	= 1,
	.resource	= &h2_nor_resource,
};

static struct mtd_partition h2_nand_partitions[] = {
#if 0
	/* REVISIT:  enable these partitions if you make NAND BOOT
	 * work on your H2 (rev C or newer); published versions of
	 * x-load only support P2 and H3.
	 */
	{
		.name		= "xloader",
		.offset		= 0,
		.size		= 64 * 1024,
		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
	},
	{
		.name		= "bootloader",
		.offset		= MTDPART_OFS_APPEND,
		.size		= 256 * 1024,
		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
	},
	{
		.name		= "params",
		.offset		= MTDPART_OFS_APPEND,
		.size		= 192 * 1024,
	},
	{
		.name		= "kernel",
		.offset		= MTDPART_OFS_APPEND,
		.size		= 2 * SZ_1M,
	},
#endif
	{
		.name		= "filesystem",
		.size		= MTDPART_SIZ_FULL,
		.offset		= MTDPART_OFS_APPEND,
	},
};

#define H2_NAND_RB_GPIO_PIN	62

static int h2_nand_dev_ready(struct nand_chip *chip)
{
	return gpio_get_value(H2_NAND_RB_GPIO_PIN);
}

static struct platform_nand_data h2_nand_platdata = {
	.chip	= {
		.nr_chips		= 1,
		.chip_offset		= 0,
		.nr_partitions		= ARRAY_SIZE(h2_nand_partitions),
		.partitions		= h2_nand_partitions,
		.options		= NAND_SAMSUNG_LP_OPTIONS,
	},
	.ctrl	= {
		.cmd_ctrl	= omap1_nand_cmd_ctl,
		.dev_ready	= h2_nand_dev_ready,
	},
};

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

static struct platform_device h2_nand_device = {
	.name		= "gen_nand",
	.id		= 0,
	.dev		= {
		.platform_data	= &h2_nand_platdata,
	},
	.num_resources	= 1,
	.resource	= &h2_nand_resource,
};

static struct smc91x_platdata h2_smc91x_info = {
	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
	.leda	= RPC_LED_100_10,
	.ledb	= RPC_LED_TX_RX,
};

static struct resource h2_smc91x_resources[] = {
	[0] = {
		.start	= OMAP1610_ETHR_START,		/* Physical */
		.end	= OMAP1610_ETHR_START + 0xf,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
	},
};

static struct platform_device h2_smc91x_device = {
	.name		= "smc91x",
	.id		= 0,
	.dev	= {
		.platform_data	= &h2_smc91x_info,
	},
	.num_resources	= ARRAY_SIZE(h2_smc91x_resources),
	.resource	= h2_smc91x_resources,
};

static struct resource h2_kp_resources[] = {
	[0] = {
		.start	= INT_KEYBOARD,
		.end	= INT_KEYBOARD,
		.flags	= IORESOURCE_IRQ,
	},
};

static const struct matrix_keymap_data h2_keymap_data = {
	.keymap		= h2_keymap,
	.keymap_size	= ARRAY_SIZE(h2_keymap),
};

static struct omap_kp_platform_data h2_kp_data = {
	.rows		= 8,
	.cols		= 8,
	.keymap_data	= &h2_keymap_data,
	.rep		= true,
	.delay		= 9,
	.dbounce	= true,
};

static struct platform_device h2_kp_device = {
	.name		= "omap-keypad",
	.id		= -1,
	.dev		= {
		.platform_data = &h2_kp_data,
	},
	.num_resources	= ARRAY_SIZE(h2_kp_resources),
	.resource	= h2_kp_resources,
};

static const struct gpio_led h2_gpio_led_pins[] = {
	{
		.name		= "h2:red",
		.default_trigger = "heartbeat",
		.gpio		= 3,
	},
	{
		.name		= "h2:green",
		.default_trigger = "cpu0",
		.gpio		= OMAP_MPUIO(4),
	},
};

static struct gpio_led_platform_data h2_gpio_led_data = {
	.leds		= h2_gpio_led_pins,
	.num_leds	= ARRAY_SIZE(h2_gpio_led_pins),
};

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

static struct platform_device *h2_devices[] __initdata = {
	&h2_nor_device,
	&h2_nand_device,
	&h2_smc91x_device,
	&h2_kp_device,
	&h2_gpio_leds,
};

static void __init h2_init_smc91x(void)
{
	if (gpio_request(0, "SMC91x irq") < 0) {
		printk("Error requesting gpio 0 for smc91x irq\n");
		return;
	}
}

static int tps_setup(struct i2c_client *client, void *context)
{
	if (!IS_BUILTIN(CONFIG_TPS65010))
		return -ENOSYS;

	tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V |
				TPS_LDO1_ENABLE | TPS_VLDO1_3_0V);

	return 0;
}

static struct tps65010_board tps_board = {
	.base		= H2_TPS_GPIO_BASE,
	.outmask	= 0x0f,
	.setup		= tps_setup,
};

static struct i2c_board_info __initdata h2_i2c_board_info[] = {
	{
		I2C_BOARD_INFO("tps65010", 0x48),
		.platform_data	= &tps_board,
	}, {
		.type = "isp1301_omap",
		.addr = 0x2d,
		.dev_name = "isp1301",
	},
};

static struct gpiod_lookup_table isp1301_gpiod_table = {
	.dev_id = "isp1301",
	.table = {
		/* Active low since the irq triggers on falling edge */
		GPIO_LOOKUP(OMAP_GPIO_LABEL, 2,
			    NULL, GPIO_ACTIVE_LOW),
		{ },
	},
};

static struct omap_usb_config h2_usb_config __initdata = {
	/* usb1 has a Mini-AB port and external isp1301 transceiver */
	.otg		= 2,

#if IS_ENABLED(CONFIG_USB_OMAP)
	.hmc_mode	= 19,	/* 0:host(off) 1:dev|otg 2:disabled */
	/* .hmc_mode	= 21,*/	/* 0:host(off) 1:dev(loopback) 2:host(loopback) */
#elif	IS_ENABLED(CONFIG_USB_OHCI_HCD)
	/* needs OTG cable, or NONSTANDARD (B-to-MiniB) */
	.hmc_mode	= 20,	/* 1:dev|otg(off) 1:host 2:disabled */
#endif

	.pins[1]	= 3,
};

static const struct omap_lcd_config h2_lcd_config __initconst = {
	.ctrl_name	= "internal",
};

static void __init h2_init(void)
{
	h2_init_smc91x();

	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
	 * notice whether a NAND chip is enabled at probe time.
	 *
	 * FIXME revC boards (and H3) support NAND-boot, with a dip switch to
	 * put NOR on CS2B and NAND (which on H2 may be 16bit) on CS3.  Try
	 * detecting that in code here, to avoid probing every possible flash
	 * configuration...
	 */
	h2_nor_resource.end = h2_nor_resource.start = omap_cs3_phys();
	h2_nor_resource.end += SZ_32M - 1;

	h2_nand_resource.end = h2_nand_resource.start = OMAP_CS2B_PHYS;
	h2_nand_resource.end += SZ_4K - 1;
	BUG_ON(gpio_request(H2_NAND_RB_GPIO_PIN, "NAND ready") < 0);
	gpio_direction_input(H2_NAND_RB_GPIO_PIN);

	gpiod_add_lookup_table(&isp1301_gpiod_table);

	omap_cfg_reg(L3_1610_FLASH_CS2B_OE);
	omap_cfg_reg(M8_1610_FLASH_CS2B_WE);

	/* MMC:  card detect and WP */
	/* omap_cfg_reg(U19_ARMIO1); */		/* CD */
	omap_cfg_reg(BALLOUT_V8_ARMIO3);	/* WP */

	/* Mux pins for keypad */
	omap_cfg_reg(F18_1610_KBC0);
	omap_cfg_reg(D20_1610_KBC1);
	omap_cfg_reg(D19_1610_KBC2);
	omap_cfg_reg(E18_1610_KBC3);
	omap_cfg_reg(C21_1610_KBC4);
	omap_cfg_reg(G18_1610_KBR0);
	omap_cfg_reg(F19_1610_KBR1);
	omap_cfg_reg(H14_1610_KBR2);
	omap_cfg_reg(E20_1610_KBR3);
	omap_cfg_reg(E19_1610_KBR4);
	omap_cfg_reg(N19_1610_KBR5);

	/* GPIO based LEDs */
	omap_cfg_reg(P18_1610_GPIO3);
	omap_cfg_reg(MPUIO4);

	h2_smc91x_resources[1].start = gpio_to_irq(0);
	h2_smc91x_resources[1].end = gpio_to_irq(0);
	platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices));
	omap_serial_init();

	/* ISP1301 IRQ wired at M14 */
	omap_cfg_reg(M14_1510_GPIO2);
	h2_i2c_board_info[0].irq = gpio_to_irq(58);
	omap_register_i2c_bus(1, 100, h2_i2c_board_info,
			      ARRAY_SIZE(h2_i2c_board_info));
	omap1_usb_init(&h2_usb_config);
	h2_mmc_init();

	omapfb_set_lcd_config(&h2_lcd_config);
}

MACHINE_START(OMAP_H2, "TI-H2")
	/* Maintainer: Imre Deak <imre.deak@nokia.com> */
	.atag_offset	= 0x100,
	.map_io		= omap16xx_map_io,
	.init_early     = omap1_init_early,
	.init_irq	= omap1_init_irq,
	.handle_irq	= omap1_handle_irq,
	.init_machine	= h2_init,
	.init_late	= omap1_init_late,
	.init_time	= omap1_timer_init,
	.restart	= omap1_restart,
MACHINE_END


code:
/*
 * arch/arm/mach-omap1/board-h2.h
 *
 * Hardware definitions for TI OMAP1610 H2 board.
 *
 * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#ifndef __ASM_ARCH_OMAP_H2_H
#define __ASM_ARCH_OMAP_H2_H

#define H2_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
#	define H2_TPS_GPIO_MMC_PWR_EN	(H2_TPS_GPIO_BASE + 3)

extern void h2_mmc_init(void);

#endif /*  __ASM_ARCH_OMAP_H2_H */


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-h3-mmc.c
 *
 * Copyright (C) 2007 Instituto Nokia de Tecnologia - INdT
 * Author: Felipe Balbi <felipe.lima@indt.org.br>
 *
 * This code is based on linux/arch/arm/mach-omap2/board-n800-mmc.c, which is:
 * Copyright (C) 2006 Nokia Corporation
 */
#include <linux/gpio.h>
#include <linux/platform_device.h>

#include <linux/mfd/tps65010.h>

#include "common.h"
#include "board-h3.h"
#include "mmc.h"

#if IS_ENABLED(CONFIG_MMC_OMAP)

static int mmc_set_power(struct device *dev, int slot, int power_on,
				int vdd)
{
	gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on);
	return 0;
}

/*
 * H3 could use the following functions tested:
 * - mmc_get_cover_state that uses OMAP_MPUIO(1)
 * - mmc_get_wp that maybe uses OMAP_MPUIO(3)
 */
static struct omap_mmc_platform_data mmc1_data = {
	.nr_slots                       = 1,
	.slots[0]       = {
		.set_power              = mmc_set_power,
		.ocr_mask               = MMC_VDD_32_33 | MMC_VDD_33_34,
		.name                   = "mmcblk",
	},
};

static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];

void __init h3_mmc_init(void)
{
	int ret;

	ret = gpio_request(H3_TPS_GPIO_MMC_PWR_EN, "MMC power");
	if (ret < 0)
		return;
	gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);

	mmc_data[0] = &mmc1_data;
	omap1_init_mmc(mmc_data, OMAP16XX_NR_MMC);
}

#else

void __init h3_mmc_init(void)
{
}

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-omap1/board-h3.c
 *
 * This file contains OMAP1710 H3 specific code.
 *
 * Copyright (C) 2004 Texas Instruments, Inc.
 * Copyright (C) 2002 MontaVista Software, Inc.
 * Copyright (C) 2001 RidgeRun, Inc.
 * Author: RidgeRun, Inc.
 *         Greg Lonnon (glonnon@ridgerun.com) or info@ridgerun.com
 */
#include <linux/gpio.h>
#include <linux/types.h>
#include <linux/init.h>
#include <linux/major.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/errno.h>
#include <linux/workqueue.h>
#include <linux/i2c.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/spi/spi.h>
#include <linux/mfd/tps65010.h>
#include <linux/smc91x.h>
#include <linux/omapfb.h>
#include <linux/platform_data/gpio-omap.h>
#include <linux/platform_data/keypad-omap.h>
#include <linux/omap-dma.h>
#include <linux/leds.h>

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

#include "tc.h"
#include "mux.h"
#include "flash.h"
#include "hardware.h"
#include "irqs.h"
#include "usb.h"
#include "common.h"
#include "board-h3.h"

/* In OMAP1710 H3 the Ethernet is directly connected to CS1 */
#define OMAP1710_ETHR_START		0x04000300

#define H3_TS_GPIO	48

static const unsigned int h3_keymap[] = {
	KEY(0, 0, KEY_LEFT),
	KEY(1, 0, KEY_RIGHT),
	KEY(2, 0, KEY_3),
	KEY(3, 0, KEY_F10),
	KEY(4, 0, KEY_F5),
	KEY(5, 0, KEY_9),
	KEY(0, 1, KEY_DOWN),
	KEY(1, 1, KEY_UP),
	KEY(2, 1, KEY_2),
	KEY(3, 1, KEY_F9),
	KEY(4, 1, KEY_F7),
	KEY(5, 1, KEY_0),
	KEY(0, 2, KEY_ENTER),
	KEY(1, 2, KEY_6),
	KEY(2, 2, KEY_1),
	KEY(3, 2, KEY_F2),
	KEY(4, 2, KEY_F6),
	KEY(5, 2, KEY_HOME),
	KEY(0, 3, KEY_8),
	KEY(1, 3, KEY_5),
	KEY(2, 3, KEY_F12),
	KEY(3, 3, KEY_F3),
	KEY(4, 3, KEY_F8),
	KEY(5, 3, KEY_END),
	KEY(0, 4, KEY_7),
	KEY(1, 4, KEY_4),
	KEY(2, 4, KEY_F11),
	KEY(3, 4, KEY_F1),
	KEY(4, 4, KEY_F4),
	KEY(5, 4, KEY_ESC),
	KEY(0, 5, KEY_F13),
	KEY(1, 5, KEY_F14),
	KEY(2, 5, KEY_F15),
	KEY(3, 5, KEY_F16),
	KEY(4, 5, KEY_SLEEP),
};

static struct mtd_partition nor_partitions[] = {
	/* bootloader (U-Boot, etc) in first sector */
	{
	      .name		= "bootloader",
	      .offset		= 0,
	      .size		= SZ_128K,
	      .mask_flags	= MTD_WRITEABLE, /* force read-only */
	},
	/* bootloader params in the next sector */
	{
	      .name		= "params",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= SZ_128K,
	      .mask_flags	= 0,
	},
	/* kernel */
	{
	      .name		= "kernel",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= SZ_2M,
	      .mask_flags	= 0
	},
	/* file system */
	{
	      .name		= "filesystem",
	      .offset		= MTDPART_OFS_APPEND,
	      .size		= MTDPART_SIZ_FULL,
	      .mask_flags	= 0
	}
};

static struct physmap_flash_data nor_data = {
	.width		= 2,
	.set_vpp	= omap1_set_vpp,
	.parts		= nor_partitions,
	.nr_parts	= ARRAY_SIZE(nor_partitions),
};

static struct resource nor_resource = {
	/* This is on CS3, wherever it's mapped */
	.flags		= IORESOURCE_MEM,
};

static struct platform_device nor_device = {
	.name		= "physmap-flash",
	.id		= 0,
	.dev		= {
		.platform_data	= &nor_data,
	},
	.num_resources	= 1,
	.resource	= &nor_resource,
};

static struct mtd_partition nand_partitions[] = {
#if 0
	/* REVISIT: enable these partitions if you make NAND BOOT work */
	{
		.name		= "xloader",
		.offset		= 0,
		.size		= 64 * 1024,
		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
	},
	{
		.name		= "bootloader",
		.offset		= MTDPART_OFS_APPEND,
		.size		= 256 * 1024,
		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
	},
	{
		.name		= "params",
		.offset		= MTDPART_OFS_APPEND,
		.size		= 192 * 1024,
	},
	{
		.name		= "kernel",
		.offset		= MTDPART_OFS_APPEND,
		.size		= 2 * SZ_1M,
	},
#endif
	{
		.name		= "filesystem",
		.size		= MTDPART_SIZ_FULL,
		.offset		= MTDPART_OFS_APPEND,
	},
};

#define H3_NAND_RB_GPIO_PIN	10

static int nand_dev_ready(struct nand_chip *chip)
{
	return gpio_get_value(H3_NAND_RB_GPIO_PIN);
}

static struct platform_nand_data nand_platdata = {
	.chip	= {
		.nr_chips		= 1,
		.chip_offset		= 0,
		.nr_partitions		= ARRAY_SIZE(nand_partitions),
		.partitions		= nand_partitions,
		.options		= NAND_SAMSUNG_LP_OPTIONS,
	},
	.ctrl	= {
		.cmd_ctrl	= omap1_nand_cmd_ctl,
		.dev_ready	= nand_dev_ready,

	},
};

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

static struct platform_device nand_device = {
	.name		= "gen_nand",
	.id		= 0,
	.dev		= {
		.platform_data	= &nand_platdata,
	},
	.num_resources	= 1,
	.resource	= &nand_resource,
};

static struct smc91x_platdata smc91x_info = {
	.flags	= SMC91X_USE_16BIT | SMC91X_NOWAIT,
	.leda	= RPC_LED_100_10,
	.ledb	= RPC_LED_TX_RX,
};

static struct resource smc91x_resources[] = {
	[0] = {
		.start	= OMAP1710_ETHR_START,		/* Physical */
		.end	= OMAP1710_ETHR_START + 0xf,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
	},
};

static struct platform_device smc91x_device = {
	.name		= "smc91x",
	.id		= 0,
	.dev	= {
		.platform_data	= &smc91x_info,
	},
	.num_resources	= ARRAY_SIZE(smc91x_resources),
	.resource	= smc91x_resources,
};

static void __init h3_init_smc91x(void)
{
	omap_cfg_reg(W15_1710_GPIO40);
	if (gpio_request(40, "SMC91x irq") < 0) {
		printk("Error requesting gpio 40 for smc91x irq\n");
		return;
	}
}

#define GPTIMER_BASE		0xFFFB1400
#define GPTIMER_REGS(x)	(0xFFFB1400 + (x * 0x800))
#define GPTIMER_REGS_SIZE	0x46

static struct resource intlat_resources[] = {
	[0] = {
		.start  = GPTIMER_REGS(0),	      /* Physical */
		.end    = GPTIMER_REGS(0) + GPTIMER_REGS_SIZE,
		.flags  = IORESOURCE_MEM,
	},
	[1] = {
		.start  = INT_1610_GPTIMER1,
		.end    = INT_1610_GPTIMER1,
		.flags  = IORESOURCE_IRQ,
	},
};

static struct platform_device intlat_device = {
	.name	   = "omap_intlat",
	.id	     = 0,
	.num_resources  = ARRAY_SIZE(intlat_resources),
	.resource       = intlat_resources,
};

static struct resource h3_kp_resources[] = {
	[0] = {
		.start	= INT_KEYBOARD,
		.end	= INT_KEYBOARD,
		.flags	= IORESOURCE_IRQ,
	},
};

static const struct matrix_keymap_data h3_keymap_data = {
	.keymap		= h3_keymap,
	.keymap_size	= ARRAY_SIZE(h3_keymap),
};

static struct omap_kp_platform_data h3_kp_data = {
	.rows		= 8,
	.cols		= 8,
	.keymap_data	= &h3_keymap_data,
	.rep		= true,
	.delay		= 9,
	.dbounce	= true,
};

static struct platform_device h3_kp_device = {
	.name		= "omap-keypad",
	.id		= -1,
	.dev		= {
		.platform_data = &h3_kp_data,
	},
	.num_resources	= ARRAY_SIZE(h3_kp_resources),
	.resource	= h3_kp_resources,
};

static struct platform_device h3_lcd_device = {
	.name		= "lcd_h3",
	.id		= -1,
};

static struct spi_board_info h3_spi_board_info[] __initdata = {
	[0] = {
		.modalias	= "tsc2101",
		.bus_num	= 2,
		.chip_select	= 0,
		.max_speed_hz	= 16000000,
		/* .platform_data	= &tsc_platform_data, */
	},
};

static const struct gpio_led h3_gpio_led_pins[] = {
	{
		.name		= "h3:red",
		.default_trigger = "heartbeat",
		.gpio		= 3,
	},
	{
		.name		= "h3:green",
		.default_trigger = "cpu0",
		.gpio		= OMAP_MPUIO(4),
	},
};

static struct gpio_led_platform_data h3_gpio_led_data = {
	.leds		= h3_gpio_led_pins,
	.num_leds	= ARRAY_SIZE(h3_gpio_led_pins),
};

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

static struct platform_device *devices[] __initdata = {
	&nor_device,
	&nand_device,
        &smc91x_device,
	&intlat_device,
	&h3_kp_device,
	&h3_lcd_device,
	&h3_gpio_leds,
};

static struct omap_usb_config h3_usb_config __initdata = {
	/* usb1 has a Mini-AB port and external isp1301 transceiver */
	.otg	    = 2,

#if IS_ENABLED(CONFIG_USB_OMAP)
	.hmc_mode       = 19,   /* 0:host(off) 1:dev|otg 2:disabled */
#elif IS_ENABLED(CONFIG_USB_OHCI_HCD)
	/* NONSTANDARD CABLE NEEDED (B-to-Mini-B) */
	.hmc_mode       = 20,   /* 1:dev|otg(off) 1:host 2:disabled */
#endif

	.pins[1]	= 3,
};

static const struct omap_lcd_config h3_lcd_config __initconst = {
	.ctrl_name	= "internal",
};

static struct i2c_board_info __initdata h3_i2c_board_info[] = {
       {
		I2C_BOARD_INFO("tps65013", 0x48),
       },
	{
		I2C_BOARD_INFO("isp1301_omap", 0x2d),
	},
};

static void __init h3_init(void)
{
	h3_init_smc91x();

	/* Here we assume the NOR boot config:  NOR on CS3 (possibly swapped
	 * to address 0 by a dip switch), NAND on CS2B.  The NAND driver will
	 * notice whether a NAND chip is enabled at probe time.
	 *
	 * H3 support NAND-boot, with a dip switch to put NOR on CS2B and NAND
	 * (which on H2 may be 16bit) on CS3.  Try detecting that in code here,
	 * to avoid probing every possible flash configuration...
	 */
	nor_resource.end = nor_resource.start = omap_cs3_phys();
	nor_resource.end += SZ_32M - 1;

	nand_resource.end = nand_resource.start = OMAP_CS2B_PHYS;
	nand_resource.end += SZ_4K - 1;
	BUG_ON(gpio_request(H3_NAND_RB_GPIO_PIN, "NAND ready") < 0);
	gpio_direction_input(H3_NAND_RB_GPIO_PIN);

	/* GPIO10 Func_MUX_CTRL reg bit 29:27, Configure V2 to mode1 as GPIO */
	/* GPIO10 pullup/down register, Enable pullup on GPIO10 */
	omap_cfg_reg(V2_1710_GPIO10);

	/* Mux pins for keypad */
	omap_cfg_reg(F18_1610_KBC0);
	omap_cfg_reg(D20_1610_KBC1);
	omap_cfg_reg(D19_1610_KBC2);
	omap_cfg_reg(E18_1610_KBC3);
	omap_cfg_reg(C21_1610_KBC4);
	omap_cfg_reg(G18_1610_KBR0);
	omap_cfg_reg(F19_1610_KBR1);
	omap_cfg_reg(H14_1610_KBR2);
	omap_cfg_reg(E20_1610_KBR3);
	omap_cfg_reg(E19_1610_KBR4);
	omap_cfg_reg(N19_1610_KBR5);

	/* GPIO based LEDs */
	omap_cfg_reg(P18_1610_GPIO3);
	omap_cfg_reg(MPUIO4);

	smc91x_resources[1].start = gpio_to_irq(40);
	smc91x_resources[1].end = gpio_to_irq(40);
	platform_add_devices(devices, ARRAY_SIZE(devices));
	h3_spi_board_info[0].irq = gpio_to_irq(H3_TS_GPIO);
	spi_register_board_info(h3_spi_board_info,
				ARRAY_SIZE(h3_spi_board_info));
	omap_serial_init();
	h3_i2c_board_info[1].irq = gpio_to_irq(14);
	omap_register_i2c_bus(1, 100, h3_i2c_board_info,
			      ARRAY_SIZE(h3_i2c_board_info));
	omap1_usb_init(&h3_usb_config);
	h3_mmc_init();

	omapfb_set_lcd_config(&h3_lcd_config);
}

MACHINE_START(OMAP_H3, "TI OMAP1710 H3 board")
	/* Maintainer: Texas Instruments, Inc. */
	.atag_offset	= 0x100,
	.map_io		= omap16xx_map_io,
	.init_early     = omap1_init_early,
	.init_irq	= omap1_init_irq,
	.handle_irq	= omap1_handle_irq,
	.init_machine	= h3_init,
	.init_late	= omap1_init_late,
	.init_time	= omap1_timer_init,
	.restart	= omap1_restart,
MACHINE_END


code:
/*
 * arch/arm/mach-omap1/board-h3.h
 *
 * Copyright (C) 2001 RidgeRun, Inc.
 * Copyright (C) 2004 Texas Instruments, Inc.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the  GNU General Public License along
 * with this program; if not, write  to the Free Software Foundation, Inc.,
 * 675 Mass Ave, Cambridge, MA 02139, USA.
 */
#ifndef __ASM_ARCH_OMAP_H3_H
#define __ASM_ARCH_OMAP_H3_H

#define H3_TPS_GPIO_BASE		(OMAP_MAX_GPIO_LINES + 16 /* MPUIO */)
#	define H3_TPS_GPIO_MMC_PWR_EN	(H3_TPS_GPIO_BASE + 4)

extern void h3_mmc_init(void);

#endif /*  __ASM_ARCH_OMAP_H3_H */