code:
# SPDX-License-Identifier: GPL-2.0-only
menuconfig ARCH_PXA
	bool "PXA2xx/PXA3xx-based"
	depends on ARCH_MULTI_V5
	depends on CPU_LITTLE_ENDIAN
	select ARM_CPU_SUSPEND if PM
	select CLKSRC_PXA
	select CLKSRC_MMIO
	select TIMER_OF
	select CPU_XSCALE if !CPU_XSC3
	select GPIO_PXA
	select GPIOLIB
	select PLAT_PXA
	help
	  Support for Intel/Marvell's PXA2xx/PXA3xx processor line.

if ARCH_PXA

menu "Intel PXA2xx/PXA3xx Implementations"

comment "Intel/Marvell Dev Platforms (sorted by hardware release time)"

config MACH_PXA25X_DT
	bool "Support PXA25x platforms from device tree"
	select PINCTRL
	select POWER_SUPPLY
	select PXA25x
	select USE_OF
	help
	  Include support for Marvell PXA25x based platforms using
	  the device tree. Needn't select any other machine while
	  MACH_PXA25x_DT is enabled.

config MACH_PXA27X_DT
	bool "Support PXA27x platforms from device tree"
	select PINCTRL
	select POWER_SUPPLY
	select PXA27x
	select USE_OF
	help
	  Include support for Marvell PXA27x based platforms using
	  the device tree. Needn't select any other machine while
	  MACH_PXA27X_DT is enabled.

config MACH_PXA3XX_DT
	bool "Support PXA3xx platforms from device tree"
	select CPU_PXA300
	select PINCTRL
	select POWER_SUPPLY
	select PXA3xx
	select USE_OF
	help
	  Include support for Marvell PXA3xx based platforms using
	  the device tree. Needn't select any other machine while
	  MACH_PXA3XX_DT is enabled.

if ATAGS

config ARCH_LUBBOCK
	bool "Intel DBPXA250 Development Platform (aka Lubbock)"
	depends on UNUSED_BOARD_FILES
	select GPIO_REG
	select PXA25x
	select SA1111

config MACH_MAINSTONE
	bool "Intel HCDDBBVA0 Development Platform (aka Mainstone)"
	depends on UNUSED_BOARD_FILES
	select GPIO_REG
	select PXA27x

config MACH_ZYLONITE
	bool
	select PXA3xx

config MACH_ZYLONITE300
	bool "PXA3xx Development Platform (aka Zylonite) PXA300/310"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA300
	select CPU_PXA310
	select MACH_ZYLONITE

config MACH_ZYLONITE320
	bool "PXA3xx Development Platform (aka Zylonite) PXA320"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA320
	select MACH_ZYLONITE

config MACH_LITTLETON
	bool "PXA3xx Form Factor Platform (aka Littleton)"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA300
	select CPU_PXA310
	select PXA3xx

config MACH_TAVOREVB
	bool "PXA930 Evaluation Board (aka TavorEVB)"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA930
	select CPU_PXA935
	select PXA3xx
	select FB
	select FB_PXA

config MACH_SAAR
	bool "PXA930 Handheld Platform (aka SAAR)"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA930
	select CPU_PXA935
	select PXA3xx
	select FB
	select FB_PXA

comment "Third Party Dev Platforms (sorted by vendor name)"

config ARCH_PXA_IDP
	bool "Accelent Xscale IDP"
	depends on UNUSED_BOARD_FILES
	select PXA25x

config ARCH_VIPER
	bool "Arcom/Eurotech VIPER SBC"
	depends on UNUSED_BOARD_FILES
	select ARCOM_PCMCIA
	select I2C_GPIO if I2C=y
	select ISA
	select PXA25x

config MACH_ARCOM_ZEUS
	bool "Arcom/Eurotech ZEUS SBC"
	depends on UNUSED_BOARD_FILES
	select ARCOM_PCMCIA
	select ISA
	select PXA27x

config MACH_BALLOON3
	bool "Balloon 3 board"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x

config MACH_CSB726
	bool "Enable Cogent CSB726 System On a Module"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on a Cogent
	  CSB726 System On Module.

config CSB726_CSB701
	bool "Enable support for CSB701 baseboard"
	depends on UNUSED_BOARD_FILES
	depends on MACH_CSB726

config MACH_CM_X300
	bool "CompuLab CM-X300 modules"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA300
	select CPU_PXA310
	select PXA3xx

config MACH_CAPC7117
	bool "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA320
	select PXA3xx

config ARCH_GUMSTIX
	bool "Gumstix XScale 255 boards"
	select PXA25x
	help
	  Say Y here if you intend to run this kernel on
	  Basix, Connex, ws-200ax, ws-400ax systems

choice
	prompt "Gumstix Carrier/Expansion Board"
	depends on ARCH_GUMSTIX

config GUMSTIX_AM200EPD
	bool "Enable AM200EPD board support"

config GUMSTIX_AM300EPD
	bool "Enable AM300EPD board support"

endchoice

config MACH_XCEP
	bool "Iskratel Electronics XCEP"
	depends on UNUSED_BOARD_FILES
	select MTD
	select MTD_CFI
	select MTD_CFI_INTELEXT
	select MTD_PHYSMAP
	select PXA25x
	help
	  PXA255 based Single Board Computer with SMC 91C111 ethernet chip and 64 MB of flash.
	  Tuned for usage in Libera instruments for particle accelerators.

config TRIZEPS_PXA
	bool "PXA based Keith und Koep Trizeps DIMM-Modules"
	depends on UNUSED_BOARD_FILES

config MACH_TRIZEPS4
	bool "Keith und Koep Trizeps4 DIMM-Module"
	depends on TRIZEPS_PXA
	select PXA27x
	select TRIZEPS_PCMCIA

config MACH_TRIZEPS4WL
	bool "Keith und Koep Trizeps4-WL DIMM-Module"
	depends on TRIZEPS_PXA
	select MACH_TRIZEPS4
	select PXA27x
	select TRIZEPS_PCMCIA

choice
	prompt "Select base board for Trizeps module"
	depends on TRIZEPS_PXA

config MACH_TRIZEPS_CONXS
	bool "ConXS Eval Board"

config MACH_TRIZEPS_UCONXS
	bool "uConXS Eval Board"

config MACH_TRIZEPS_ANY
	bool "another Board"

endchoice

config ARCOM_PCMCIA
	bool
	help
	  Generic option for Arcom Viper/Zeus PCMCIA

config TRIZEPS_PCMCIA
	bool
	help
	  Enable PCMCIA support for Trizeps modules

config MACH_LOGICPD_PXA270
	bool "LogicPD PXA270 Card Engine Development Platform"
	depends on UNUSED_BOARD_FILES
	select PXA27x

config MACH_PCM027
	bool "Phytec phyCORE-PXA270 CPU module (PCM-027)"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x

config MACH_PCM990_BASEBOARD
	bool "PHYTEC PCM-990 development board"
	depends on UNUSED_BOARD_FILES
	depends on MACH_PCM027

choice
	prompt "display on pcm990"
	depends on MACH_PCM990_BASEBOARD

config PCM990_DISPLAY_SHARP
	bool "sharp lq084v1dg21 stn display"

config PCM990_DISPLAY_NEC
	bool "nec nl6448bc20_18d tft display"

config PCM990_DISPLAY_NONE
	bool "no display"

endchoice

config MACH_COLIBRI
	bool "Toradex Colibri PXA270"
	depends on UNUSED_BOARD_FILES
	select PXA27x

config MACH_COLIBRI_PXA270_INCOME
	bool "Income s.r.o. PXA270 SBC"
	depends on UNUSED_BOARD_FILES
	depends on MACH_COLIBRI
	select PXA27x

config MACH_COLIBRI300
	bool "Toradex Colibri PXA300/310"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA300
	select CPU_PXA310
	select PXA3xx

config MACH_COLIBRI320
	bool "Toradex Colibri PXA320"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA320
	select PXA3xx

config MACH_COLIBRI_EVALBOARD
	bool "Toradex Colibri Evaluation Carrier Board support"
	depends on UNUSED_BOARD_FILES
	depends on MACH_COLIBRI || MACH_COLIBRI300 || MACH_COLIBRI320

config MACH_VPAC270
	bool "Voipac PXA270"
	depends on UNUSED_BOARD_FILES
	select HAVE_PATA_PLATFORM
	select PXA27x
	help
	  PXA270 based Single Board Computer.

comment "End-user Products (sorted by vendor name)"

config MACH_H4700
	bool "HP iPAQ hx4700"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x

config MACH_H5000
	bool "HP iPAQ h5000"
	depends on UNUSED_BOARD_FILES
	select PXA25x

config MACH_HIMALAYA
	bool "HTC Himalaya Support"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA26x

config MACH_MAGICIAN
	bool "Enable HTC Magician Support"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x

config MACH_MIOA701
	bool "Mitac Mio A701 Support"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on a
	  MIO A701. Currently there is only basic support
	  for this PDA.

config PXA_EZX
	bool "Motorola EZX Platform"
	depends on UNUSED_BOARD_FILES
	select IWMMXT
	select PXA27x

config MACH_EZX_A780
	bool "Motorola EZX A780"
	default y
	depends on PXA_EZX

config MACH_EZX_E680
	bool "Motorola EZX E680"
	default y
	depends on PXA_EZX

config MACH_EZX_A1200
	bool "Motorola EZX A1200"
	default y
	depends on PXA_EZX

config MACH_EZX_A910
	bool "Motorola EZX A910"
	default y
	depends on PXA_EZX

config MACH_EZX_E6
	bool "Motorola EZX E6"
	default y
	depends on PXA_EZX

config MACH_EZX_E2
	bool "Motorola EZX E2"
	default y
	depends on PXA_EZX

config MACH_MP900C
	bool "Nec Mobilepro 900/c"
	depends on UNUSED_BOARD_FILES
	select PXA25x

config ARCH_PXA_PALM
	bool "PXA based Palm PDAs"
	depends on UNUSED_BOARD_FILES

config MACH_PALM27X
	bool

config MACH_PALMTE2
	bool "Palm Tungsten|E2"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select PXA25x
	help
	  Say Y here if you intend to run this kernel on a Palm Tungsten|E2
	  handheld computer.

config MACH_PALMTC
	bool "Palm Tungsten|C"
	default y
	depends on ARCH_PXA_PALM
	select PXA25x
	help
	  Say Y here if you intend to run this kernel on a Palm Tungsten|C
	  handheld computer.

config MACH_PALMT5
	bool "Palm Tungsten|T5"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select IWMMXT
	select MACH_PALM27X
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on a Palm Tungsten|T5
	  handheld computer.

config MACH_PALMTX
	bool "Palm T|X"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select IWMMXT
	select MACH_PALM27X
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on a Palm T|X
	  handheld computer.

config MACH_PALMZ72
	bool "Palm Zire 72"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select IWMMXT
	select MACH_PALM27X
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on Palm Zire 72
	  handheld computer.

config MACH_PALMLD
	bool "Palm LifeDrive"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select IWMMXT
	select MACH_PALM27X
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on a Palm LifeDrive
	  handheld computer.

config PALM_TREO
	bool
	depends on ARCH_PXA_PALM

config MACH_CENTRO
	bool "Palm Centro 685 (GSM)"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select IWMMXT
	select MACH_PALM27X
	select PALM_TREO
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on Palm Centro 685 (GSM)
	  smartphone.

config MACH_TREO680
	bool "Palm Treo 680"
	depends on UNUSED_BOARD_FILES
	default y
	depends on ARCH_PXA_PALM
	select IWMMXT
	select MACH_PALM27X
	select PALM_TREO
	select PXA27x
	help
	  Say Y here if you intend to run this kernel on Palm Treo 680
	  smartphone.

config PXA_SHARPSL
	bool "SHARP Zaurus SL-5600, SL-C7xx and SL-Cxx00 Models"
	select SHARP_PARAM
	select SHARP_SCOOP
	help
	  Say Y here if you intend to run this kernel on a
	  Sharp Zaurus SL-5600 (Poodle), SL-C700 (Corgi),
	  SL-C750 (Shepherd), SL-C760 (Husky), SL-C1000 (Akita),
	  SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa)
	  handheld computer.

config PXA_SHARPSL_DETECT_MACH_ID
	bool "Detect machine ID at run-time in the decompressor"
	depends on PXA_SHARPSL
	help
	  Say Y here if you want the zImage decompressor to detect
	  the Zaurus machine ID at run-time. For latest kexec-based
	  boot loader, this is not necessary.

config MACH_POODLE
	bool "Enable Sharp SL-5600 (Poodle) Support"
	depends on PXA_SHARPSL
	depends on UNUSED_BOARD_FILES
	select PXA25x
	select SHARP_LOCOMO

config MACH_CORGI
	bool "Enable Sharp SL-C700 (Corgi) Support"
	depends on PXA_SHARPSL
	depends on UNUSED_BOARD_FILES
	select PXA25x
	select PXA_SHARP_C7xx

config MACH_SHEPHERD
	bool "Enable Sharp SL-C750 (Shepherd) Support"
	depends on PXA_SHARPSL
	depends on UNUSED_BOARD_FILES
	select PXA25x
	select PXA_SHARP_C7xx

config MACH_HUSKY
	bool "Enable Sharp SL-C760 (Husky) Support"
	depends on PXA_SHARPSL
	depends on UNUSED_BOARD_FILES
	select PXA25x
	select PXA_SHARP_C7xx

config MACH_AKITA
	bool "Enable Sharp SL-1000 (Akita) Support"
	depends on PXA_SHARPSL
	select I2C
	select I2C_PXA
	select MACH_SPITZ
	select PXA27x
	select PXA_SHARP_Cxx00

config MACH_SPITZ
	bool "Enable Sharp Zaurus SL-3000 (Spitz) Support"
	depends on PXA_SHARPSL
	select PXA27x
	select PXA_SHARP_Cxx00

config MACH_BORZOI
	bool "Enable Sharp Zaurus SL-3100 (Borzoi) Support"
	depends on PXA_SHARPSL
	select PXA27x
	select PXA_SHARP_Cxx00

config MACH_TOSA
	bool "Enable Sharp SL-6000x (Tosa) Support"
	depends on UNUSED_BOARD_FILES
	depends on PXA_SHARPSL
	select PXA25x

config TOSA_BT
	tristate "Control the state of built-in bluetooth chip on Sharp SL-6000"
	depends on MACH_TOSA && NET
	select RFKILL
	help
	  This is a simple driver that is able to control
	  the state of built in bluetooth chip on tosa.

config TOSA_USE_EXT_KEYCODES
	bool "Tosa keyboard: use extended keycodes"
	depends on MACH_TOSA
	help
	  Say Y here to enable the tosa keyboard driver to generate extended
	  (>= 127) keycodes. Be aware, that they can't be correctly interpreted
	  by either console keyboard driver or by Kdrive keybd driver.

	  Say Y only if you know, what you are doing!

config MACH_ICONTROL
	bool "TMT iControl/SafeTCam based on the MXM-8x10 CoM"
	depends on UNUSED_BOARD_FILES
	select CPU_PXA320
	select PXA3xx

config ARCH_PXA_ESERIES
	bool "PXA based Toshiba e-series PDAs"
	depends on UNUSED_BOARD_FILES
	select FB_W100
	select FB
	select PXA25x

config MACH_E330
	bool "Toshiba e330"
	default y
	depends on ARCH_PXA_ESERIES
	help
	  Say Y here if you intend to run this kernel on a Toshiba
	  e330 family PDA.

config MACH_E350
	bool "Toshiba e350"
	default y
	depends on ARCH_PXA_ESERIES
	help
	  Say Y here if you intend to run this kernel on a Toshiba
	  e350 family PDA.

config MACH_E740
	bool "Toshiba e740"
	default y
	depends on ARCH_PXA_ESERIES
	help
	  Say Y here if you intend to run this kernel on a Toshiba
	  e740 family PDA.

config MACH_E750
	bool "Toshiba e750"
	default y
	depends on ARCH_PXA_ESERIES
	help
	  Say Y here if you intend to run this kernel on a Toshiba
	  e750 family PDA.

config MACH_E400
	bool "Toshiba e400"
	default y
	depends on ARCH_PXA_ESERIES
	help
	  Say Y here if you intend to run this kernel on a Toshiba
	  e400 family PDA.

config MACH_E800
	bool "Toshiba e800"
	default y
	depends on ARCH_PXA_ESERIES
	help
	  Say Y here if you intend to run this kernel on a Toshiba
	  e800 family PDA.

config MACH_ZIPIT2
	bool "Zipit Z2 Handheld"
	depends on UNUSED_BOARD_FILES
	select PXA27x

endif # ATAGS
endmenu

config PXA25x
	bool
	select CPU_XSCALE
	help
	  Select code specific to PXA21x/25x/26x variants

config PXA27x
	bool
	select CPU_XSCALE
	help
	  Select code specific to PXA27x variants

config CPU_PXA26x
	bool
	select PXA25x
	help
	  Select code specific to PXA26x (codename Dalhart)

config PXA3xx
	bool
	select CPU_XSC3
	help
	  Select code specific to PXA3xx variants

config CPU_PXA300
	bool
	select PXA3xx
	help
	  PXA300 (codename Monahans-L)

config CPU_PXA310
	bool
	select CPU_PXA300
	select PXA310_ULPI if USB_ULPI
	help
	  PXA310 (codename Monahans-LV)

config CPU_PXA320
	bool
	select PXA3xx
	help
	  PXA320 (codename Monahans-P)

config CPU_PXA930
	bool
	select PXA3xx
	help
	  PXA930 (codename Tavor-P)

config CPU_PXA935
	bool
	select CPU_PXA930
	help
	  PXA935 (codename Tavor-P65)

config PXA_SHARP_C7xx
	bool
	select SHARPSL_PM
	help
	  Enable support for all Sharp C7xx models

config PXA_SHARP_Cxx00
	bool
	select SHARPSL_PM
	help
	  Enable common support for Sharp Cxx00 models

config SHARPSL_PM
	bool
	select APM_EMULATION
	select SHARPSL_PM_MAX1111

config SHARPSL_PM_MAX1111
	bool
	select HWMON
	select SENSORS_MAX1111
	select SPI
	select SPI_MASTER

config PXA310_ULPI
	bool

config PXA_SYSTEMS_CPLDS
	tristate "Motherboard cplds"
	default ARCH_LUBBOCK || MACH_MAINSTONE
	help
	  This driver supports the Lubbock and Mainstone multifunction chip
	  found on the pxa25x development platform system (Lubbock) and pxa27x
	  development platform system (Mainstone). This IO board supports the
	  interrupts handling, ethernet controller, flash chips, etc ...

endif

path: arch/arm/mach-pxa/Kconfig


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

# Common support (must be linked before board specific support)
obj-y				+= devices.o generic.o irq.o reset.o
obj-$(CONFIG_PM)		+= pm.o sleep.o standby.o

# Generic drivers that other drivers may depend upon

# SoC-specific code
obj-$(CONFIG_PXA25x)		+= mfp-pxa2xx.o pxa2xx.o pxa25x.o
obj-$(CONFIG_PXA27x)		+= mfp-pxa2xx.o pxa2xx.o pxa27x.o
obj-$(CONFIG_PXA3xx)		+= mfp-pxa3xx.o pxa3xx.o smemc.o pxa3xx-ulpi.o
obj-$(CONFIG_CPU_PXA300)	+= pxa300.o
obj-$(CONFIG_CPU_PXA320)	+= pxa320.o
obj-$(CONFIG_CPU_PXA930)	+= pxa930.o

# NOTE: keep the order of boards in accordance to their order in Kconfig

# Device Tree support
obj-$(CONFIG_MACH_PXA25X_DT)	+= pxa-dt.o
obj-$(CONFIG_MACH_PXA27X_DT)	+= pxa-dt.o
obj-$(CONFIG_MACH_PXA3XX_DT)	+= pxa-dt.o

# Intel/Marvell Dev Platforms
obj-$(CONFIG_ARCH_LUBBOCK)	+= lubbock.o
obj-$(CONFIG_MACH_MAINSTONE)	+= mainstone.o
obj-$(CONFIG_MACH_ZYLONITE300)	+= zylonite.o zylonite_pxa300.o
obj-$(CONFIG_MACH_ZYLONITE320)	+= zylonite.o zylonite_pxa320.o
obj-$(CONFIG_MACH_LITTLETON)	+= littleton.o
obj-$(CONFIG_MACH_TAVOREVB)	+= tavorevb.o
obj-$(CONFIG_MACH_SAAR)		+= saar.o

# 3rd Party Dev Platforms
obj-$(CONFIG_ARCH_PXA_IDP)	+= idp.o
obj-$(CONFIG_ARCH_VIPER)	+= viper.o
obj-$(CONFIG_MACH_ARCOM_ZEUS)	+= zeus.o
obj-$(CONFIG_ARCOM_PCMCIA)	+= viper-pcmcia.o
obj-$(CONFIG_MACH_BALLOON3)	+= balloon3.o balloon3-pcmcia.o
obj-$(CONFIG_MACH_CSB726)	+= csb726.o
obj-$(CONFIG_CSB726_CSB701)	+= csb701.o
obj-$(CONFIG_MACH_CM_X300)      += cm-x300.o
obj-$(CONFIG_MACH_CAPC7117)     += capc7117.o mxm8x10.o
obj-$(CONFIG_ARCH_GUMSTIX)	+= gumstix.o
obj-$(CONFIG_GUMSTIX_AM200EPD)	+= am200epd.o
obj-$(CONFIG_GUMSTIX_AM300EPD)	+= am300epd.o
obj-$(CONFIG_MACH_XCEP)         += xcep.o
obj-$(CONFIG_MACH_TRIZEPS4)	+= trizeps4.o
obj-$(CONFIG_TRIZEPS_PCMCIA)	+= trizeps4-pcmcia.o
obj-$(CONFIG_MACH_LOGICPD_PXA270)	+= lpd270.o
obj-$(CONFIG_MACH_PCM027)		+= pcm027.o
obj-$(CONFIG_MACH_PCM990_BASEBOARD)	+= pcm990-baseboard.o
obj-$(CONFIG_MACH_COLIBRI)		+= colibri-pxa270.o colibri-pcmcia.o
obj-$(CONFIG_MACH_COLIBRI_EVALBOARD)	+= colibri-evalboard.o
obj-$(CONFIG_MACH_COLIBRI_PXA270_INCOME)	+= colibri-pxa270-income.o
obj-$(CONFIG_MACH_COLIBRI300)	+= colibri-pxa3xx.o colibri-pxa300.o
obj-$(CONFIG_MACH_COLIBRI320)	+= colibri-pxa3xx.o colibri-pxa320.o colibri-pcmcia.o
obj-$(CONFIG_MACH_VPAC270)	+= vpac270.o vpac270-pcmcia.o

# End-user Products
obj-$(CONFIG_MACH_H4700)	+= hx4700.o
obj-$(CONFIG_MACH_H4700)	+= hx4700-pcmcia.o
obj-$(CONFIG_MACH_H5000)	+= h5000.o
obj-$(CONFIG_MACH_HIMALAYA)	+= himalaya.o
obj-$(CONFIG_MACH_MAGICIAN)	+= magician.o
obj-$(CONFIG_MACH_MIOA701)	+= mioa701.o mioa701_bootresume.o
obj-$(CONFIG_PXA_EZX)           += ezx.o
obj-$(CONFIG_MACH_MP900C)	+= mp900.o
obj-$(CONFIG_MACH_PALMTE2)	+= palmte2.o
obj-$(CONFIG_MACH_PALMTC)	+= palmtc.o palmtc-pcmcia.o
obj-$(CONFIG_MACH_PALM27X)	+= palm27x.o
obj-$(CONFIG_MACH_PALMT5)	+= palmt5.o
obj-$(CONFIG_MACH_PALMTX)	+= palmtx.o palmtx-pcmcia.o
obj-$(CONFIG_MACH_PALMZ72)	+= palmz72.o
obj-$(CONFIG_MACH_PALMLD)	+= palmld.o palmld-pcmcia.o
obj-$(CONFIG_PALM_TREO)		+= palmtreo.o
obj-$(CONFIG_PXA_SHARP_C7xx)	+= corgi.o sharpsl_pm.o corgi_pm.o
obj-$(CONFIG_PXA_SHARP_Cxx00)	+= spitz.o sharpsl_pm.o spitz_pm.o
obj-$(CONFIG_MACH_POODLE)	+= poodle.o
obj-$(CONFIG_MACH_TOSA)		+= tosa.o
obj-$(CONFIG_MACH_ICONTROL)     += icontrol.o mxm8x10.o
obj-$(CONFIG_ARCH_PXA_ESERIES)	+= eseries.o
obj-$(CONFIG_MACH_E740)		+= e740-pcmcia.o
obj-$(CONFIG_MACH_ZIPIT2)	+= z2.o

obj-$(CONFIG_PXA_SYSTEMS_CPLDS)	+= pxa_cplds_irqs.o
obj-$(CONFIG_TOSA_BT)		+= tosa-bt.o

repo_name: angery/linux

path: arch/arm/mach-pxa/Makefile


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

/*
 * Chip Selects
 */
#define PXA_CS0_PHYS		0x00000000
#define PXA_CS1_PHYS		0x04000000
#define PXA_CS2_PHYS		0x08000000
#define PXA_CS3_PHYS		0x0C000000
#define PXA_CS4_PHYS		0x10000000
#define PXA_CS5_PHYS		0x14000000

#define PXA300_CS0_PHYS		0x00000000	/* PXA300/PXA310 _only_ */
#define PXA300_CS1_PHYS		0x30000000	/* PXA300/PXA310 _only_ */
#define PXA3xx_CS2_PHYS		0x10000000
#define PXA3xx_CS3_PHYS		0x14000000

/*
 * Peripheral Bus
 */
#define PERIPH_PHYS		0x40000000
#define PERIPH_VIRT		IOMEM(0xf2000000)
#define PERIPH_SIZE		0x02000000

/*
 * Static Memory Controller (w/ SDRAM controls on PXA25x/PXA27x)
 */
#define PXA2XX_SMEMC_PHYS	0x48000000
#define PXA3XX_SMEMC_PHYS	0x4a000000
#define SMEMC_VIRT		IOMEM(0xf6000000)
#define SMEMC_SIZE		0x00100000

/*
 * Dynamic Memory Controller (only on PXA3xx)
 */
#define DMEMC_PHYS		0x48100000
#define DMEMC_VIRT		IOMEM(0xf6100000)
#define DMEMC_SIZE		0x00100000

/*
 * Reserved space for low level debug virtual addresses within
 * 0xf6200000..0xf6201000
 */

/*
 * DFI Bus for NAND, PXA3xx only
 */
#define NAND_PHYS		0x43100000
#define NAND_VIRT		IOMEM(0xf6300000)
#define NAND_SIZE		0x00100000

/*
 * Internal Memory Controller (PXA27x and later)
 */
#define IMEMC_PHYS		0x58000000
#define IMEMC_VIRT		IOMEM(0xfe000000)
#define IMEMC_SIZE		0x00100000

#endif /* __ASM_MACH_ADDR_MAP_H */


code:
/*
 * am200epd.c -- Platform device for AM200 EPD kit
 *
 * Copyright (C) 2008, Jaya Kumar
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 * Layout is based on skeletonfb.c by James Simmons and Geert Uytterhoeven.
 *
 * This work was made possible by help and equipment support from E-Ink
 * Corporation. http://support.eink.com/community
 *
 * This driver is written to be used with the Metronome display controller.
 * on the AM200 EPD prototype kit/development kit with an E-Ink 800x600
 * Vizplex EPD on a Gumstix board using the Lyre interface board.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/gpio.h>

#include "pxa25x.h"
#include "gumstix.h"
#include <linux/platform_data/video-pxafb.h>

#include "generic.h"

#include <video/metronomefb.h>

static unsigned int panel_type = 6;
static struct platform_device *am200_device;
static struct metronome_board am200_board;

static struct pxafb_mode_info am200_fb_mode_9inch7 = {
	.pixclock	= 40000,
	.xres		= 1200,
	.yres		= 842,
	.bpp		= 16,
	.hsync_len	= 2,
	.left_margin	= 2,
	.right_margin	= 2,
	.vsync_len	= 1,
	.upper_margin	= 2,
	.lower_margin	= 25,
	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
};

static struct pxafb_mode_info am200_fb_mode_8inch = {
	.pixclock	= 40000,
	.xres		= 1088,
	.yres		= 791,
	.bpp		= 16,
	.hsync_len	= 28,
	.left_margin	= 8,
	.right_margin	= 30,
	.vsync_len	= 8,
	.upper_margin	= 10,
	.lower_margin	= 8,
	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
};

static struct pxafb_mode_info am200_fb_mode_6inch = {
	.pixclock	= 40189,
	.xres		= 832,
	.yres		= 622,
	.bpp		= 16,
	.hsync_len	= 28,
	.left_margin	= 34,
	.right_margin	= 34,
	.vsync_len	= 25,
	.upper_margin	= 0,
	.lower_margin	= 2,
	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
};

static struct pxafb_mach_info am200_fb_info = {
	.modes		= &am200_fb_mode_6inch,
	.num_modes	= 1,
	.lcd_conn	= LCD_TYPE_COLOR_TFT | LCD_PCLK_EDGE_FALL |
			  LCD_AC_BIAS_FREQ(24),
};

/* register offsets for gpio control */
#define LED_GPIO_PIN 51
#define STDBY_GPIO_PIN 48
#define RST_GPIO_PIN 49
#define RDY_GPIO_PIN 32
#define ERR_GPIO_PIN 17
#define PCBPWR_GPIO_PIN 16
static int gpios[] = { LED_GPIO_PIN , STDBY_GPIO_PIN , RST_GPIO_PIN,
			RDY_GPIO_PIN, ERR_GPIO_PIN, PCBPWR_GPIO_PIN };
static char *gpio_names[] = { "LED" , "STDBY" , "RST", "RDY", "ERR", "PCBPWR" };

static int am200_init_gpio_regs(struct metronomefb_par *par)
{
	int i;
	int err;

	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
		err = gpio_request(gpios[i], gpio_names[i]);
		if (err) {
			dev_err(&am200_device->dev, "failed requesting "
				"gpio %s, err=%d\n", gpio_names[i], err);
			goto err_req_gpio;
		}
	}

	gpio_direction_output(LED_GPIO_PIN, 0);
	gpio_direction_output(STDBY_GPIO_PIN, 0);
	gpio_direction_output(RST_GPIO_PIN, 0);

	gpio_direction_input(RDY_GPIO_PIN);
	gpio_direction_input(ERR_GPIO_PIN);

	gpio_direction_output(PCBPWR_GPIO_PIN, 0);

	return 0;

err_req_gpio:
	while (--i >= 0)
		gpio_free(gpios[i]);

	return err;
}

static void am200_cleanup(struct metronomefb_par *par)
{
	int i;

	free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par);

	for (i = 0; i < ARRAY_SIZE(gpios); i++)
		gpio_free(gpios[i]);
}

static int am200_share_video_mem(struct fb_info *info)
{
	/* rough check if this is our desired fb and not something else */
	if ((info->var.xres != am200_fb_info.modes->xres)
		|| (info->var.yres != am200_fb_info.modes->yres))
		return 0;

	/* we've now been notified that we have our new fb */
	am200_board.metromem = info->screen_base;
	am200_board.host_fbinfo = info;

	/* try to refcount host drv since we are the consumer after this */
	if (!try_module_get(info->fbops->owner))
		return -ENODEV;

	return 0;
}

static int am200_unshare_video_mem(struct fb_info *info)
{
	dev_dbg(&am200_device->dev, "ENTER %s\n", __func__);

	if (info != am200_board.host_fbinfo)
		return 0;

	module_put(am200_board.host_fbinfo->fbops->owner);
	return 0;
}

static int am200_fb_notifier_callback(struct notifier_block *self,
				 unsigned long event, void *data)
{
	struct fb_event *evdata = data;
	struct fb_info *info = evdata->info;

	dev_dbg(&am200_device->dev, "ENTER %s\n", __func__);

	if (event == FB_EVENT_FB_REGISTERED)
		return am200_share_video_mem(info);
	else if (event == FB_EVENT_FB_UNREGISTERED)
		return am200_unshare_video_mem(info);

	return 0;
}

static struct notifier_block am200_fb_notif = {
	.notifier_call = am200_fb_notifier_callback,
};

/* this gets called as part of our init. these steps must be done now so
 * that we can use pxa_set_fb_info */
static void __init am200_presetup_fb(void)
{
	int fw;
	int fh;
	int padding_size;
	int totalsize;

	switch (panel_type) {
	case 6:
		am200_fb_info.modes = &am200_fb_mode_6inch;
		break;
	case 8:
		am200_fb_info.modes = &am200_fb_mode_8inch;
		break;
	case 97:
		am200_fb_info.modes = &am200_fb_mode_9inch7;
		break;
	default:
		dev_err(&am200_device->dev, "invalid panel_type selection,"
						" setting to 6\n");
		am200_fb_info.modes = &am200_fb_mode_6inch;
		break;
	}

	/* the frame buffer is divided as follows:
	command | CRC | padding
	16kb waveform data | CRC | padding
	image data | CRC
	*/

	fw = am200_fb_info.modes->xres;
	fh = am200_fb_info.modes->yres;

	/* waveform must be 16k + 2 for checksum */
	am200_board.wfm_size = roundup(16*1024 + 2, fw);

	padding_size = PAGE_SIZE + (4 * fw);

	/* total is 1 cmd , 1 wfm, padding and image */
	totalsize = fw + am200_board.wfm_size + padding_size + (fw*fh);

	/* save this off because we're manipulating fw after this and
	 * we'll need it when we're ready to setup the framebuffer */
	am200_board.fw = fw;
	am200_board.fh = fh;

	/* the reason we do this adjustment is because we want to acquire
	 * more framebuffer memory without imposing custom awareness on the
	 * underlying pxafb driver */
	am200_fb_info.modes->yres = DIV_ROUND_UP(totalsize, fw);

	/* we divide since we told the LCD controller we're 16bpp */
	am200_fb_info.modes->xres /= 2;

	pxa_set_fb_info(NULL, &am200_fb_info);

}

/* this gets called by metronomefb as part of its init, in our case, we
 * have already completed initial framebuffer init in presetup_fb so we
 * can just setup the fb access pointers */
static int am200_setup_fb(struct metronomefb_par *par)
{
	int fw;
	int fh;

	fw = am200_board.fw;
	fh = am200_board.fh;

	/* metromem was set up by the notifier in share_video_mem so now
	 * we can use its value to calculate the other entries */
	par->metromem_cmd = (struct metromem_cmd *) am200_board.metromem;
	par->metromem_wfm = am200_board.metromem + fw;
	par->metromem_img = par->metromem_wfm + am200_board.wfm_size;
	par->metromem_img_csum = (u16 *) (par->metromem_img + (fw * fh));
	par->metromem_dma = am200_board.host_fbinfo->fix.smem_start;

	return 0;
}

static int am200_get_panel_type(void)
{
	return panel_type;
}

static irqreturn_t am200_handle_irq(int irq, void *dev_id)
{
	struct metronomefb_par *par = dev_id;

	wake_up_interruptible(&par->waitq);
	return IRQ_HANDLED;
}

static int am200_setup_irq(struct fb_info *info)
{
	int ret;

	ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am200_handle_irq,
				IRQF_TRIGGER_FALLING, "AM200", info->par);
	if (ret)
		dev_err(&am200_device->dev, "request_irq failed: %d\n", ret);

	return ret;
}

static void am200_set_rst(struct metronomefb_par *par, int state)
{
	gpio_set_value(RST_GPIO_PIN, state);
}

static void am200_set_stdby(struct metronomefb_par *par, int state)
{
	gpio_set_value(STDBY_GPIO_PIN, state);
}

static int am200_wait_event(struct metronomefb_par *par)
{
	return wait_event_timeout(par->waitq, gpio_get_value(RDY_GPIO_PIN), HZ);
}

static int am200_wait_event_intr(struct metronomefb_par *par)
{
	return wait_event_interruptible_timeout(par->waitq,
					gpio_get_value(RDY_GPIO_PIN), HZ);
}

static struct metronome_board am200_board = {
	.owner			= THIS_MODULE,
	.setup_irq		= am200_setup_irq,
	.setup_io		= am200_init_gpio_regs,
	.setup_fb		= am200_setup_fb,
	.set_rst		= am200_set_rst,
	.set_stdby		= am200_set_stdby,
	.met_wait_event		= am200_wait_event,
	.met_wait_event_intr	= am200_wait_event_intr,
	.get_panel_type		= am200_get_panel_type,
	.cleanup		= am200_cleanup,
};

static unsigned long am200_pin_config[] __initdata = {
	GPIO51_GPIO,
	GPIO49_GPIO,
	GPIO48_GPIO,
	GPIO32_GPIO,
	GPIO17_GPIO,
	GPIO16_GPIO,
};

int __init am200_init(void)
{
	int ret;

	/*
	 * Before anything else, we request notification for any fb
	 * creation events.
	 *
	 * FIXME: This is terrible and needs to be nuked. The notifier is used
	 * to get at the fb base address from the boot splash fb driver, which
	 * is then passed to metronomefb. Instaed of metronomfb or this board
	 * support file here figuring this out on their own.
	 *
	 * See also the #ifdef in fbmem.c.
	 */
	fb_register_client(&am200_fb_notif);

	pxa2xx_mfp_config(ARRAY_AND_SIZE(am200_pin_config));

	/* request our platform independent driver */
	request_module("metronomefb");

	am200_device = platform_device_alloc("metronomefb", -1);
	if (!am200_device)
		return -ENOMEM;

	/* the am200_board that will be seen by metronomefb is a copy */
	platform_device_add_data(am200_device, &am200_board,
					sizeof(am200_board));

	/* this _add binds metronomefb to am200. metronomefb refcounts am200 */
	ret = platform_device_add(am200_device);

	if (ret) {
		platform_device_put(am200_device);
		fb_unregister_client(&am200_fb_notif);
		return ret;
	}

	am200_presetup_fb();

	return 0;
}

module_param(panel_type, uint, 0);
MODULE_PARM_DESC(panel_type, "Select the panel type: 6, 8, 97");

MODULE_DESCRIPTION("board driver for am200 metronome epd kit");
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");


code:
/*
 * am300epd.c -- Platform device for AM300 EPD kit
 *
 * Copyright (C) 2008, Jaya Kumar
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License. See the file COPYING in the main directory of this archive for
 * more details.
 *
 * This work was made possible by help and equipment support from E-Ink
 * Corporation. http://support.eink.com/community
 *
 * This driver is written to be used with the Broadsheet display controller.
 * on the AM300 EPD prototype kit/development kit with an E-Ink 800x600
 * Vizplex EPD on a Gumstix board using the Broadsheet interface board.
 *
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/gpio.h>

#include "gumstix.h"
#include "mfp-pxa25x.h"
#include "irqs.h"
#include <linux/platform_data/video-pxafb.h>

#include "generic.h"

#include <video/broadsheetfb.h>

static unsigned int panel_type = 6;
static struct platform_device *am300_device;
static struct broadsheet_board am300_board;

static unsigned long am300_pin_config[] __initdata = {
	GPIO16_GPIO,
	GPIO17_GPIO,
	GPIO32_GPIO,
	GPIO48_GPIO,
	GPIO49_GPIO,
	GPIO51_GPIO,
	GPIO74_GPIO,
	GPIO75_GPIO,
	GPIO76_GPIO,
	GPIO77_GPIO,

	/* this is the 16-bit hdb bus 58-73 */
	GPIO58_GPIO,
	GPIO59_GPIO,
	GPIO60_GPIO,
	GPIO61_GPIO,

	GPIO62_GPIO,
	GPIO63_GPIO,
	GPIO64_GPIO,
	GPIO65_GPIO,

	GPIO66_GPIO,
	GPIO67_GPIO,
	GPIO68_GPIO,
	GPIO69_GPIO,

	GPIO70_GPIO,
	GPIO71_GPIO,
	GPIO72_GPIO,
	GPIO73_GPIO,
};

/* register offsets for gpio control */
#define PWR_GPIO_PIN	16
#define CFG_GPIO_PIN	17
#define RDY_GPIO_PIN	32
#define DC_GPIO_PIN	48
#define RST_GPIO_PIN	49
#define LED_GPIO_PIN	51
#define RD_GPIO_PIN	74
#define WR_GPIO_PIN	75
#define CS_GPIO_PIN	76
#define IRQ_GPIO_PIN	77

/* hdb bus */
#define DB0_GPIO_PIN	58
#define DB15_GPIO_PIN	73

static int gpios[] = { PWR_GPIO_PIN, CFG_GPIO_PIN, RDY_GPIO_PIN, DC_GPIO_PIN,
			RST_GPIO_PIN, RD_GPIO_PIN, WR_GPIO_PIN, CS_GPIO_PIN,
			IRQ_GPIO_PIN, LED_GPIO_PIN };
static char *gpio_names[] = { "PWR", "CFG", "RDY", "DC", "RST", "RD", "WR",
				"CS", "IRQ", "LED" };

static int am300_wait_event(struct broadsheetfb_par *par)
{
	/* todo: improve err recovery */
	wait_event(par->waitq, gpio_get_value(RDY_GPIO_PIN));
	return 0;
}

static int am300_init_gpio_regs(struct broadsheetfb_par *par)
{
	int i;
	int err;
	char dbname[8];

	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
		err = gpio_request(gpios[i], gpio_names[i]);
		if (err) {
			dev_err(&am300_device->dev, "failed requesting "
				"gpio %s, err=%d\n", gpio_names[i], err);
			goto err_req_gpio;
		}
	}

	/* we also need to take care of the hdb bus */
	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++) {
		sprintf(dbname, "DB%d", i);
		err = gpio_request(i, dbname);
		if (err) {
			dev_err(&am300_device->dev, "failed requesting "
				"gpio %d, err=%d\n", i, err);
			goto err_req_gpio2;
		}
	}

	/* setup the outputs and init values */
	gpio_direction_output(PWR_GPIO_PIN, 0);
	gpio_direction_output(CFG_GPIO_PIN, 1);
	gpio_direction_output(DC_GPIO_PIN, 0);
	gpio_direction_output(RD_GPIO_PIN, 1);
	gpio_direction_output(WR_GPIO_PIN, 1);
	gpio_direction_output(CS_GPIO_PIN, 1);
	gpio_direction_output(RST_GPIO_PIN, 0);

	/* setup the inputs */
	gpio_direction_input(RDY_GPIO_PIN);
	gpio_direction_input(IRQ_GPIO_PIN);

	/* start the hdb bus as an input */
	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
		gpio_direction_output(i, 0);

	/* go into command mode */
	gpio_set_value(CFG_GPIO_PIN, 1);
	gpio_set_value(RST_GPIO_PIN, 0);
	msleep(10);
	gpio_set_value(RST_GPIO_PIN, 1);
	msleep(10);
	am300_wait_event(par);

	return 0;

err_req_gpio2:
	while (--i >= DB0_GPIO_PIN)
		gpio_free(i);
	i = ARRAY_SIZE(gpios);
err_req_gpio:
	while (--i >= 0)
		gpio_free(gpios[i]);

	return err;
}

static int am300_init_board(struct broadsheetfb_par *par)
{
	return am300_init_gpio_regs(par);
}

static void am300_cleanup(struct broadsheetfb_par *par)
{
	int i;

	free_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), par);

	for (i = 0; i < ARRAY_SIZE(gpios); i++)
		gpio_free(gpios[i]);

	for (i = DB0_GPIO_PIN; i <= DB15_GPIO_PIN; i++)
		gpio_free(i);

}

static u16 am300_get_hdb(struct broadsheetfb_par *par)
{
	u16 res = 0;
	int i;

	for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
		res |= (gpio_get_value(DB0_GPIO_PIN + i)) ? (1 << i) : 0;

	return res;
}

static void am300_set_hdb(struct broadsheetfb_par *par, u16 data)
{
	int i;

	for (i = 0; i <= (DB15_GPIO_PIN - DB0_GPIO_PIN) ; i++)
		gpio_set_value(DB0_GPIO_PIN + i, (data >> i) & 0x01);
}

static void am300_set_ctl(struct broadsheetfb_par *par, unsigned char bit,
				u8 state)
{
	switch (bit) {
	case BS_CS:
		gpio_set_value(CS_GPIO_PIN, state);
		break;
	case BS_DC:
		gpio_set_value(DC_GPIO_PIN, state);
		break;
	case BS_WR:
		gpio_set_value(WR_GPIO_PIN, state);
		break;
	}
}

static int am300_get_panel_type(void)
{
	return panel_type;
}

static irqreturn_t am300_handle_irq(int irq, void *dev_id)
{
	struct broadsheetfb_par *par = dev_id;

	wake_up(&par->waitq);
	return IRQ_HANDLED;
}

static int am300_setup_irq(struct fb_info *info)
{
	int ret;
	struct broadsheetfb_par *par = info->par;

	ret = request_irq(PXA_GPIO_TO_IRQ(RDY_GPIO_PIN), am300_handle_irq,
				IRQF_TRIGGER_RISING, "AM300", par);
	if (ret)
		dev_err(&am300_device->dev, "request_irq failed: %d\n", ret);

	return ret;
}

static struct broadsheet_board am300_board = {
	.owner			= THIS_MODULE,
	.init			= am300_init_board,
	.cleanup		= am300_cleanup,
	.set_hdb		= am300_set_hdb,
	.get_hdb		= am300_get_hdb,
	.set_ctl		= am300_set_ctl,
	.wait_for_rdy		= am300_wait_event,
	.get_panel_type		= am300_get_panel_type,
	.setup_irq		= am300_setup_irq,
};

int __init am300_init(void)
{
	int ret;

	pxa2xx_mfp_config(ARRAY_AND_SIZE(am300_pin_config));

	/* request our platform independent driver */
	request_module("broadsheetfb");

	am300_device = platform_device_alloc("broadsheetfb", -1);
	if (!am300_device)
		return -ENOMEM;

	/* the am300_board that will be seen by broadsheetfb is a copy */
	platform_device_add_data(am300_device, &am300_board,
					sizeof(am300_board));

	ret = platform_device_add(am300_device);

	if (ret) {
		platform_device_put(am300_device);
		return ret;
	}

	return 0;
}

module_param(panel_type, uint, 0);
MODULE_PARM_DESC(panel_type, "Select the panel type: 37, 6, 97");

MODULE_DESCRIPTION("board driver for am300 epd kit");
MODULE_AUTHOR("Jaya Kumar");
MODULE_LICENSE("GPL");


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/drivers/pcmcia/pxa2xx_balloon3.c
 *
 * Balloon3 PCMCIA specific routines.
 *
 *  Author:	Nick Bane
 *  Created:	June, 2006
 *  Copyright:	Toby Churchill Ltd
 *  Derived from pxa2xx_mainstone.c, by Nico Pitre
 *
 * Various modification by Marek Vasut <marek.vasut@gmail.com>
 */

#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/errno.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/io.h>

#include "balloon3.h"

#include <asm/mach-types.h>

#include <pcmcia/soc_common.h>

static int balloon3_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
{
	uint16_t ver;

	ver = __raw_readw(BALLOON3_FPGA_VER);
	if (ver < 0x4f08)
		pr_warn("The FPGA code, version 0x%04x, is too old. "
			"PCMCIA/CF support might be broken in this version!",
			ver);

	skt->socket.pci_irq = BALLOON3_BP_CF_NRDY_IRQ;
	skt->stat[SOC_STAT_CD].gpio = BALLOON3_GPIO_S0_CD;
	skt->stat[SOC_STAT_CD].name = "PCMCIA0 CD";
	skt->stat[SOC_STAT_BVD1].irq = BALLOON3_BP_NSTSCHG_IRQ;
	skt->stat[SOC_STAT_BVD1].name = "PCMCIA0 STSCHG";

	return 0;
}

static unsigned long balloon3_pcmcia_status[2] = {
	BALLOON3_CF_nSTSCHG_BVD1,
	BALLOON3_CF_nSTSCHG_BVD1
};

static void balloon3_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
				    struct pcmcia_state *state)
{
	uint16_t status;
	int flip;

	/* This actually reads the STATUS register */
	status = __raw_readw(BALLOON3_CF_STATUS_REG);
	flip = (status ^ balloon3_pcmcia_status[skt->nr])
		& BALLOON3_CF_nSTSCHG_BVD1;
	/*
	 * Workaround for STSCHG which can't be deasserted:
	 * We therefore disable/enable corresponding IRQs
	 * as needed to avoid IRQ locks.
	 */
	if (flip) {
		balloon3_pcmcia_status[skt->nr] = status;
		if (status & BALLOON3_CF_nSTSCHG_BVD1)
			enable_irq(BALLOON3_BP_NSTSCHG_IRQ);
		else
			disable_irq(BALLOON3_BP_NSTSCHG_IRQ);
	}

	state->ready	= !!(status & BALLOON3_CF_nIRQ);
	state->bvd1	= !!(status & BALLOON3_CF_nSTSCHG_BVD1);
	state->bvd2	= 0;	/* not available */
	state->vs_3v	= 1;	/* Always true its a CF card */
	state->vs_Xv	= 0;	/* not available */
}

static int balloon3_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
				       const socket_state_t *state)
{
	__raw_writew(BALLOON3_CF_RESET, BALLOON3_CF_CONTROL_REG +
			((state->flags & SS_RESET) ?
			BALLOON3_FPGA_SETnCLR : 0));
	return 0;
}

static struct pcmcia_low_level balloon3_pcmcia_ops = {
	.owner			= THIS_MODULE,
	.hw_init		= balloon3_pcmcia_hw_init,
	.socket_state		= balloon3_pcmcia_socket_state,
	.configure_socket	= balloon3_pcmcia_configure_socket,
	.first			= 0,
	.nr			= 1,
};

static struct platform_device *balloon3_pcmcia_device;

static int __init balloon3_pcmcia_init(void)
{
	int ret;

	if (!machine_is_balloon3())
		return -ENODEV;

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

	ret = platform_device_add_data(balloon3_pcmcia_device,
			&balloon3_pcmcia_ops, sizeof(balloon3_pcmcia_ops));

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

	if (ret)
		platform_device_put(balloon3_pcmcia_device);

	return ret;
}

static void __exit balloon3_pcmcia_exit(void)
{
	platform_device_unregister(balloon3_pcmcia_device);
}

module_init(balloon3_pcmcia_init);
module_exit(balloon3_pcmcia_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nick Bane <nick@cecomputing.co.uk>");
MODULE_ALIAS("platform:pxa2xx-pcmcia");
MODULE_DESCRIPTION("Balloon3 board CF/PCMCIA driver");


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 *  linux/arch/arm/mach-pxa/balloon3.c
 *
 *  Support for Balloonboard.org Balloon3 board.
 *
 *  Author:	Nick Bane, Wookey, Jonathan McDowell
 *  Created:	June, 2006
 *  Copyright:	Toby Churchill Ltd
 *  Derived from mainstone.c, by Nico Pitre
 */

#include <linux/export.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/leds.h>
#include <linux/sched.h>
#include <linux/bitops.h>
#include <linux/fb.h>
#include <linux/gpio.h>
#include <linux/ioport.h>
#include <linux/ucb1400.h>
#include <linux/mtd/mtd.h>
#include <linux/types.h>
#include <linux/platform_data/pcf857x.h>
#include <linux/platform_data/i2c-pxa.h>
#include <linux/mtd/platnand.h>
#include <linux/mtd/physmap.h>
#include <linux/regulator/max1586.h>

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

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

#include "pxa27x.h"
#include "balloon3.h"
#include <linux/platform_data/asoc-pxa.h>
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/mmc-pxamci.h>
#include "udc.h"
#include "pxa27x-udc.h"
#include <linux/platform_data/irda-pxaficp.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>

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

/******************************************************************************
 * Pin configuration
 ******************************************************************************/
static unsigned long balloon3_pin_config[] __initdata = {
	/* Select BTUART 'COM1/ttyS0' as IO option for pins 42/43/44/45 */
	GPIO42_BTUART_RXD,
	GPIO43_BTUART_TXD,
	GPIO44_BTUART_CTS,
	GPIO45_BTUART_RTS,

	/* Reset, configured as GPIO wakeup source */
	GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH,
};

/******************************************************************************
 * Compatibility: Parameter parsing
 ******************************************************************************/
static unsigned long balloon3_irq_enabled;

static unsigned long balloon3_features_present =
		(1 << BALLOON3_FEATURE_OHCI) | (1 << BALLOON3_FEATURE_CF) |
		(1 << BALLOON3_FEATURE_AUDIO) |
		(1 << BALLOON3_FEATURE_TOPPOLY);

int balloon3_has(enum balloon3_features feature)
{
	return (balloon3_features_present & (1 << feature)) ? 1 : 0;
}
EXPORT_SYMBOL_GPL(balloon3_has);

int __init parse_balloon3_features(char *arg)
{
	if (!arg)
		return 0;

	return kstrtoul(arg, 0, &balloon3_features_present);
}
early_param("balloon3_features", parse_balloon3_features);

/******************************************************************************
 * Compact Flash slot
 ******************************************************************************/
#if	defined(CONFIG_PCMCIA_PXA2XX) || defined(CONFIG_PCMCIA_PXA2XX_MODULE)
static unsigned long balloon3_cf_pin_config[] __initdata = {
	GPIO48_nPOE,
	GPIO49_nPWE,
	GPIO50_nPIOR,
	GPIO51_nPIOW,
	GPIO85_nPCE_1,
	GPIO54_nPCE_2,
	GPIO79_PSKTSEL,
	GPIO55_nPREG,
	GPIO56_nPWAIT,
	GPIO57_nIOIS16,
};

static void __init balloon3_cf_init(void)
{
	if (!balloon3_has(BALLOON3_FEATURE_CF))
		return;

	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_cf_pin_config));
}
#else
static inline void balloon3_cf_init(void) {}
#endif

/******************************************************************************
 * NOR Flash
 ******************************************************************************/
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
static struct mtd_partition balloon3_nor_partitions[] = {
	{
		.name		= "Flash",
		.offset		= 0x00000000,
		.size		= MTDPART_SIZ_FULL,
	}
};

static struct physmap_flash_data balloon3_flash_data[] = {
	{
		.width		= 2,	/* bankwidth in bytes */
		.parts		= balloon3_nor_partitions,
		.nr_parts	= ARRAY_SIZE(balloon3_nor_partitions)
	}
};

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

static struct platform_device balloon3_flash = {
	.name		= "physmap-flash",
	.id		= 0,
	.resource	= &balloon3_flash_resource,
	.num_resources	= 1,
	.dev 		= {
		.platform_data = balloon3_flash_data,
	},
};
static void __init balloon3_nor_init(void)
{
	platform_device_register(&balloon3_flash);
}
#else
static inline void balloon3_nor_init(void) {}
#endif

/******************************************************************************
 * Audio and Touchscreen
 ******************************************************************************/
#if	defined(CONFIG_TOUCHSCREEN_UCB1400) || \
	defined(CONFIG_TOUCHSCREEN_UCB1400_MODULE)
static unsigned long balloon3_ac97_pin_config[] __initdata = {
	GPIO28_AC97_BITCLK,
	GPIO29_AC97_SDATA_IN_0,
	GPIO30_AC97_SDATA_OUT,
	GPIO31_AC97_SYNC,
	GPIO113_AC97_nRESET,
	GPIO95_GPIO,
};

static struct ucb1400_pdata vpac270_ucb1400_pdata = {
	.irq		= PXA_GPIO_TO_IRQ(BALLOON3_GPIO_CODEC_IRQ),
};

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

static void __init balloon3_ts_init(void)
{
	if (!balloon3_has(BALLOON3_FEATURE_AUDIO))
		return;

	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_ac97_pin_config));
	pxa_set_ac97_info(NULL);
	platform_device_register(&balloon3_ucb1400_device);
}
#else
static inline void balloon3_ts_init(void) {}
#endif

/******************************************************************************
 * Framebuffer
 ******************************************************************************/
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static unsigned long balloon3_lcd_pin_config[] __initdata = {
	GPIOxx_LCD_TFT_16BPP,
	GPIO99_GPIO,
};

static struct pxafb_mode_info balloon3_lcd_modes[] = {
	{
		.pixclock		= 38000,
		.xres			= 480,
		.yres			= 640,
		.bpp			= 16,
		.hsync_len		= 8,
		.left_margin		= 8,
		.right_margin		= 8,
		.vsync_len		= 2,
		.upper_margin		= 4,
		.lower_margin		= 5,
		.sync			= 0,
	},
};

static struct pxafb_mach_info balloon3_lcd_screen = {
	.modes			= balloon3_lcd_modes,
	.num_modes		= ARRAY_SIZE(balloon3_lcd_modes),
	.lcd_conn		= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
};

static void balloon3_backlight_power(int on)
{
	gpio_set_value(BALLOON3_GPIO_RUN_BACKLIGHT, on);
}

static void __init balloon3_lcd_init(void)
{
	int ret;

	if (!balloon3_has(BALLOON3_FEATURE_TOPPOLY))
		return;

	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_lcd_pin_config));

	ret = gpio_request(BALLOON3_GPIO_RUN_BACKLIGHT, "BKL-ON");
	if (ret) {
		pr_err("Requesting BKL-ON GPIO failed!\n");
		goto err;
	}

	ret = gpio_direction_output(BALLOON3_GPIO_RUN_BACKLIGHT, 1);
	if (ret) {
		pr_err("Setting BKL-ON GPIO direction failed!\n");
		goto err2;
	}

	balloon3_lcd_screen.pxafb_backlight_power = balloon3_backlight_power;
	pxa_set_fb_info(NULL, &balloon3_lcd_screen);
	return;

err2:
	gpio_free(BALLOON3_GPIO_RUN_BACKLIGHT);
err:
	return;
}
#else
static inline void balloon3_lcd_init(void) {}
#endif

/******************************************************************************
 * SD/MMC card controller
 ******************************************************************************/
#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE)
static unsigned long balloon3_mmc_pin_config[] __initdata = {
	GPIO32_MMC_CLK,
	GPIO92_MMC_DAT_0,
	GPIO109_MMC_DAT_1,
	GPIO110_MMC_DAT_2,
	GPIO111_MMC_DAT_3,
	GPIO112_MMC_CMD,
};

static struct pxamci_platform_data balloon3_mci_platform_data = {
	.ocr_mask		= MMC_VDD_32_33 | MMC_VDD_33_34,
	.detect_delay_ms	= 200,
};

static void __init balloon3_mmc_init(void)
{
	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_mmc_pin_config));
	pxa_set_mci_info(&balloon3_mci_platform_data);
}
#else
static inline void balloon3_mmc_init(void) {}
#endif

/******************************************************************************
 * USB Gadget
 ******************************************************************************/
#if defined(CONFIG_USB_PXA27X)||defined(CONFIG_USB_PXA27X_MODULE)
static void balloon3_udc_command(int cmd)
{
	if (cmd == PXA2XX_UDC_CMD_CONNECT)
		UP2OCR |= UP2OCR_DPPUE | UP2OCR_DPPUBE;
	else if (cmd == PXA2XX_UDC_CMD_DISCONNECT)
		UP2OCR &= ~UP2OCR_DPPUE;
}

static int balloon3_udc_is_connected(void)
{
	return 1;
}

static struct pxa2xx_udc_mach_info balloon3_udc_info __initdata = {
	.udc_command		= balloon3_udc_command,
	.udc_is_connected	= balloon3_udc_is_connected,
	.gpio_pullup		= -1,
};

static void __init balloon3_udc_init(void)
{
	pxa_set_udc_info(&balloon3_udc_info);
}
#else
static inline void balloon3_udc_init(void) {}
#endif

/******************************************************************************
 * IrDA
 ******************************************************************************/
#if defined(CONFIG_IRDA) || defined(CONFIG_IRDA_MODULE)
static struct pxaficp_platform_data balloon3_ficp_platform_data = {
	.transceiver_cap	= IR_FIRMODE | IR_SIRMODE | IR_OFF,
};

static void __init balloon3_irda_init(void)
{
	pxa_set_ficp_info(&balloon3_ficp_platform_data);
}
#else
static inline void balloon3_irda_init(void) {}
#endif

/******************************************************************************
 * USB Host
 ******************************************************************************/
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static unsigned long balloon3_uhc_pin_config[] __initdata = {
	GPIO88_USBH1_PWR,
	GPIO89_USBH1_PEN,
};

static struct pxaohci_platform_data balloon3_ohci_info = {
	.port_mode	= PMM_PERPORT_MODE,
	.flags		= ENABLE_PORT_ALL | POWER_CONTROL_LOW | POWER_SENSE_LOW,
};

static void __init balloon3_uhc_init(void)
{
	if (!balloon3_has(BALLOON3_FEATURE_OHCI))
		return;
	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_uhc_pin_config));
	pxa_set_ohci_info(&balloon3_ohci_info);
}
#else
static inline void balloon3_uhc_init(void) {}
#endif

/******************************************************************************
 * LEDs
 ******************************************************************************/
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
static unsigned long balloon3_led_pin_config[] __initdata = {
	GPIO9_GPIO,	/* NAND activity LED */
	GPIO10_GPIO,	/* Heartbeat LED */
};

struct gpio_led balloon3_gpio_leds[] = {
	{
		.name			= "balloon3:green:idle",
		.default_trigger	= "heartbeat",
		.gpio			= BALLOON3_GPIO_LED_IDLE,
		.active_low		= 1,
	}, {
		.name			= "balloon3:green:nand",
		.default_trigger	= "nand-disk",
		.gpio			= BALLOON3_GPIO_LED_NAND,
		.active_low		= 1,
	},
};

static struct gpio_led_platform_data balloon3_gpio_led_info = {
	.leds		= balloon3_gpio_leds,
	.num_leds	= ARRAY_SIZE(balloon3_gpio_leds),
};

static struct platform_device balloon3_leds = {
	.name	= "leds-gpio",
	.id	= 0,
	.dev	= {
		.platform_data	= &balloon3_gpio_led_info,
	}
};

struct gpio_led balloon3_pcf_gpio_leds[] = {
	{
		.name			= "balloon3:green:led0",
		.gpio			= BALLOON3_PCF_GPIO_LED0,
		.active_low		= 1,
	}, {
		.name			= "balloon3:green:led1",
		.gpio			= BALLOON3_PCF_GPIO_LED1,
		.active_low		= 1,
	}, {
		.name			= "balloon3:orange:led2",
		.gpio			= BALLOON3_PCF_GPIO_LED2,
		.active_low		= 1,
	}, {
		.name			= "balloon3:orange:led3",
		.gpio			= BALLOON3_PCF_GPIO_LED3,
		.active_low		= 1,
	}, {
		.name			= "balloon3:orange:led4",
		.gpio			= BALLOON3_PCF_GPIO_LED4,
		.active_low		= 1,
	}, {
		.name			= "balloon3:orange:led5",
		.gpio			= BALLOON3_PCF_GPIO_LED5,
		.active_low		= 1,
	}, {
		.name			= "balloon3:red:led6",
		.gpio			= BALLOON3_PCF_GPIO_LED6,
		.active_low		= 1,
	}, {
		.name			= "balloon3:red:led7",
		.gpio			= BALLOON3_PCF_GPIO_LED7,
		.active_low		= 1,
	},
};

static struct gpio_led_platform_data balloon3_pcf_gpio_led_info = {
	.leds		= balloon3_pcf_gpio_leds,
	.num_leds	= ARRAY_SIZE(balloon3_pcf_gpio_leds),
};

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

static void __init balloon3_leds_init(void)
{
	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_led_pin_config));
	platform_device_register(&balloon3_leds);
	platform_device_register(&balloon3_pcf_leds);
}
#else
static inline void balloon3_leds_init(void) {}
#endif

/******************************************************************************
 * FPGA IRQ
 ******************************************************************************/
static void balloon3_mask_irq(struct irq_data *d)
{
	int balloon3_irq = (d->irq - BALLOON3_IRQ(0));
	balloon3_irq_enabled &= ~(1 << balloon3_irq);
	__raw_writel(~balloon3_irq_enabled, BALLOON3_INT_CONTROL_REG);
}

static void balloon3_unmask_irq(struct irq_data *d)
{
	int balloon3_irq = (d->irq - BALLOON3_IRQ(0));
	balloon3_irq_enabled |= (1 << balloon3_irq);
	__raw_writel(~balloon3_irq_enabled, BALLOON3_INT_CONTROL_REG);
}

static struct irq_chip balloon3_irq_chip = {
	.name		= "FPGA",
	.irq_ack	= balloon3_mask_irq,
	.irq_mask	= balloon3_mask_irq,
	.irq_unmask	= balloon3_unmask_irq,
};

static void balloon3_irq_handler(struct irq_desc *desc)
{
	unsigned long pending = __raw_readl(BALLOON3_INT_CONTROL_REG) &
					balloon3_irq_enabled;
	do {
		struct irq_data *d = irq_desc_get_irq_data(desc);
		struct irq_chip *chip = irq_desc_get_chip(desc);
		unsigned int irq;

		/* clear useless edge notification */
		if (chip->irq_ack)
			chip->irq_ack(d);

		while (pending) {
			irq = BALLOON3_IRQ(0) + __ffs(pending);
			generic_handle_irq(irq);
			pending &= pending - 1;
		}
		pending = __raw_readl(BALLOON3_INT_CONTROL_REG) &
				balloon3_irq_enabled;
	} while (pending);
}

static void __init balloon3_init_irq(void)
{
	int irq;

	pxa27x_init_irq();
	/* setup extra Balloon3 irqs */
	for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) {
		irq_set_chip_and_handler(irq, &balloon3_irq_chip,
					 handle_level_irq);
		irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
	}

	irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
	irq_set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);

	pr_debug("%s: chained handler installed - irq %d automatically "
		"enabled\n", __func__, BALLOON3_AUX_NIRQ);
}

/******************************************************************************
 * GPIO expander
 ******************************************************************************/
#if defined(CONFIG_GPIO_PCF857X) || defined(CONFIG_GPIO_PCF857X_MODULE)
static struct pcf857x_platform_data balloon3_pcf857x_pdata = {
	.gpio_base	= BALLOON3_PCF_GPIO_BASE,
	.n_latch	= 0,
	.setup		= NULL,
	.teardown	= NULL,
	.context	= NULL,
};

static struct i2c_board_info __initdata balloon3_i2c_devs[] = {
	{
		I2C_BOARD_INFO("pcf8574a", 0x38),
		.platform_data	= &balloon3_pcf857x_pdata,
	},
};

static void __init balloon3_i2c_init(void)
{
	pxa_set_i2c_info(NULL);
	i2c_register_board_info(0, ARRAY_AND_SIZE(balloon3_i2c_devs));
}
#else
static inline void balloon3_i2c_init(void) {}
#endif

/******************************************************************************
 * NAND
 ******************************************************************************/
#if defined(CONFIG_MTD_NAND_PLATFORM)||defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
static void balloon3_nand_cmd_ctl(struct nand_chip *this, int cmd,
				  unsigned int ctrl)
{
	uint8_t balloon3_ctl_set = 0, balloon3_ctl_clr = 0;

	if (ctrl & NAND_CTRL_CHANGE) {
		if (ctrl & NAND_CLE)
			balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLCLE;
		else
			balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLCLE;

		if (ctrl & NAND_ALE)
			balloon3_ctl_set |= BALLOON3_NAND_CONTROL_FLALE;
		else
			balloon3_ctl_clr |= BALLOON3_NAND_CONTROL_FLALE;

		if (balloon3_ctl_clr)
			__raw_writel(balloon3_ctl_clr,
				BALLOON3_NAND_CONTROL_REG);
		if (balloon3_ctl_set)
			__raw_writel(balloon3_ctl_set,
				BALLOON3_NAND_CONTROL_REG +
				BALLOON3_FPGA_SETnCLR);
	}

	if (cmd != NAND_CMD_NONE)
		writeb(cmd, this->legacy.IO_ADDR_W);
}

static void balloon3_nand_select_chip(struct nand_chip *this, int chip)
{
	if (chip < 0 || chip > 3)
		return;

	/* Assert all nCE lines */
	__raw_writew(
		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3,
		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);

	/* Deassert correct nCE line */
	__raw_writew(BALLOON3_NAND_CONTROL_FLCE0 << chip,
		BALLOON3_NAND_CONTROL_REG);
}

static int balloon3_nand_dev_ready(struct nand_chip *this)
{
	return __raw_readl(BALLOON3_NAND_STAT_REG) & BALLOON3_NAND_STAT_RNB;
}

static int balloon3_nand_probe(struct platform_device *pdev)
{
	uint16_t ver;
	int ret;

	__raw_writew(BALLOON3_NAND_CONTROL2_16BIT,
		BALLOON3_NAND_CONTROL2_REG + BALLOON3_FPGA_SETnCLR);

	ver = __raw_readw(BALLOON3_FPGA_VER);
	if (ver < 0x4f08)
		pr_warn("The FPGA code, version 0x%04x, is too old. "
			"NAND support might be broken in this version!", ver);

	/* Power up the NAND chips */
	ret = gpio_request(BALLOON3_GPIO_RUN_NAND, "NAND");
	if (ret)
		goto err1;

	ret = gpio_direction_output(BALLOON3_GPIO_RUN_NAND, 1);
	if (ret)
		goto err2;

	gpio_set_value(BALLOON3_GPIO_RUN_NAND, 1);

	/* Deassert all nCE lines and write protect line */
	__raw_writel(
		BALLOON3_NAND_CONTROL_FLCE0 | BALLOON3_NAND_CONTROL_FLCE1 |
		BALLOON3_NAND_CONTROL_FLCE2 | BALLOON3_NAND_CONTROL_FLCE3 |
		BALLOON3_NAND_CONTROL_FLWP,
		BALLOON3_NAND_CONTROL_REG + BALLOON3_FPGA_SETnCLR);
	return 0;

err2:
	gpio_free(BALLOON3_GPIO_RUN_NAND);
err1:
	return ret;
}

static void balloon3_nand_remove(struct platform_device *pdev)
{
	/* Power down the NAND chips */
	gpio_set_value(BALLOON3_GPIO_RUN_NAND, 0);
	gpio_free(BALLOON3_GPIO_RUN_NAND);
}

static struct mtd_partition balloon3_partition_info[] = {
	[0] = {
		.name	= "Boot",
		.offset	= 0,
		.size	= SZ_4M,
	},
	[1] = {
		.name	= "RootFS",
		.offset	= MTDPART_OFS_APPEND,
		.size	= MTDPART_SIZ_FULL
	},
};

struct platform_nand_data balloon3_nand_pdata = {
	.chip = {
		.nr_chips	= 4,
		.chip_offset	= 0,
		.nr_partitions	= ARRAY_SIZE(balloon3_partition_info),
		.partitions	= balloon3_partition_info,
		.chip_delay	= 50,
	},
	.ctrl = {
		.dev_ready	= balloon3_nand_dev_ready,
		.select_chip	= balloon3_nand_select_chip,
		.cmd_ctrl	= balloon3_nand_cmd_ctl,
		.probe		= balloon3_nand_probe,
		.remove		= balloon3_nand_remove,
	},
};

static struct resource balloon3_nand_resource[] = {
	[0] = {
		.start = BALLOON3_NAND_BASE,
		.end   = BALLOON3_NAND_BASE + 0x4,
		.flags = IORESOURCE_MEM,
	},
};

static struct platform_device balloon3_nand = {
	.name		= "gen_nand",
	.num_resources	= ARRAY_SIZE(balloon3_nand_resource),
	.resource	= balloon3_nand_resource,
	.id		= -1,
	.dev		= {
		.platform_data = &balloon3_nand_pdata,
	}
};

static void __init balloon3_nand_init(void)
{
	platform_device_register(&balloon3_nand);
}
#else
static inline void balloon3_nand_init(void) {}
#endif

/******************************************************************************
 * Core power regulator
 ******************************************************************************/
#if defined(CONFIG_REGULATOR_MAX1586) || \
    defined(CONFIG_REGULATOR_MAX1586_MODULE)
static struct regulator_consumer_supply balloon3_max1587a_consumers[] = {
	REGULATOR_SUPPLY("vcc_core", NULL),
};

static struct regulator_init_data balloon3_max1587a_v3_info = {
	.constraints = {
		.name		= "vcc_core range",
		.min_uV		= 900000,
		.max_uV		= 1705000,
		.always_on	= 1,
		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
	},
	.consumer_supplies	= balloon3_max1587a_consumers,
	.num_consumer_supplies	= ARRAY_SIZE(balloon3_max1587a_consumers),
};

static struct max1586_subdev_data balloon3_max1587a_subdevs[] = {
	{
		.name		= "vcc_core",
		.id		= MAX1586_V3,
		.platform_data	= &balloon3_max1587a_v3_info,
	}
};

static struct max1586_platform_data balloon3_max1587a_info = {
	.subdevs     = balloon3_max1587a_subdevs,
	.num_subdevs = ARRAY_SIZE(balloon3_max1587a_subdevs),
	.v3_gain     = MAX1586_GAIN_R24_3k32, /* 730..1550 mV */
};

static struct i2c_board_info __initdata balloon3_pi2c_board_info[] = {
	{
		I2C_BOARD_INFO("max1586", 0x14),
		.platform_data	= &balloon3_max1587a_info,
	},
};

static void __init balloon3_pmic_init(void)
{
	pxa27x_set_i2c_power_info(NULL);
	i2c_register_board_info(1, ARRAY_AND_SIZE(balloon3_pi2c_board_info));
}
#else
static inline void balloon3_pmic_init(void) {}
#endif

/******************************************************************************
 * Machine init
 ******************************************************************************/
static void __init balloon3_init(void)
{
	ARB_CNTRL = ARB_CORE_PARK | 0x234;

	pxa2xx_mfp_config(ARRAY_AND_SIZE(balloon3_pin_config));

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

	balloon3_i2c_init();
	balloon3_irda_init();
	balloon3_lcd_init();
	balloon3_leds_init();
	balloon3_mmc_init();
	balloon3_nand_init();
	balloon3_nor_init();
	balloon3_pmic_init();
	balloon3_ts_init();
	balloon3_udc_init();
	balloon3_uhc_init();
	balloon3_cf_init();
}

static struct map_desc balloon3_io_desc[] __initdata = {
	{	/* CPLD/FPGA */
		.virtual	= (unsigned long)BALLOON3_FPGA_VIRT,
		.pfn		= __phys_to_pfn(BALLOON3_FPGA_PHYS),
		.length		= BALLOON3_FPGA_LENGTH,
		.type		= MT_DEVICE,
	},
};

static void __init balloon3_map_io(void)
{
	pxa27x_map_io();
	iotable_init(balloon3_io_desc, ARRAY_SIZE(balloon3_io_desc));
}

MACHINE_START(BALLOON3, "Balloon3")
	/* Maintainer: Nick Bane. */
	.map_io		= balloon3_map_io,
	.nr_irqs	= BALLOON3_NR_IRQS,
	.init_irq	= balloon3_init_irq,
	.handle_irq	= pxa27x_handle_irq,
	.init_time	= pxa_timer_init,
	.init_machine	= balloon3_init,
	.atag_offset	= 0x100,
	.restart	= pxa_restart,
MACHINE_END


code:
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 *  linux/include/asm-arm/arch-pxa/balloon3.h
 *
 *  Authors:	Nick Bane and Wookey
 *  Created:	Oct, 2005
 *  Copyright:	Toby Churchill Ltd
 *  Cribbed from mainstone.c, by Nicholas Pitre
 */

#ifndef ASM_ARCH_BALLOON3_H
#define ASM_ARCH_BALLOON3_H

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

enum balloon3_features {
	BALLOON3_FEATURE_OHCI,
	BALLOON3_FEATURE_MMC,
	BALLOON3_FEATURE_CF,
	BALLOON3_FEATURE_AUDIO,
	BALLOON3_FEATURE_TOPPOLY,
};

#define BALLOON3_FPGA_PHYS	PXA_CS4_PHYS
#define BALLOON3_FPGA_VIRT	IOMEM(0xf1000000)	/* as per balloon2 */
#define BALLOON3_FPGA_LENGTH	0x01000000

#define	BALLOON3_FPGA_SETnCLR		(0x1000)

/* FPGA / CPLD registers for CF socket */
#define	BALLOON3_CF_STATUS_REG		(BALLOON3_FPGA_VIRT + 0x00e00008)
#define	BALLOON3_CF_CONTROL_REG		(BALLOON3_FPGA_VIRT + 0x00e00008)
/* FPGA / CPLD version register */
#define	BALLOON3_FPGA_VER		(BALLOON3_FPGA_VIRT + 0x00e0001c)
/* FPGA / CPLD registers for NAND flash */
#define	BALLOON3_NAND_BASE		(PXA_CS4_PHYS + 0x00e00000)
#define	BALLOON3_NAND_IO_REG		(BALLOON3_FPGA_VIRT + 0x00e00000)
#define	BALLOON3_NAND_CONTROL2_REG	(BALLOON3_FPGA_VIRT + 0x00e00010)
#define	BALLOON3_NAND_STAT_REG		(BALLOON3_FPGA_VIRT + 0x00e00014)
#define	BALLOON3_NAND_CONTROL_REG	(BALLOON3_FPGA_VIRT + 0x00e00014)

/* fpga/cpld interrupt control register */
#define BALLOON3_INT_CONTROL_REG	(BALLOON3_FPGA_VIRT + 0x00e0000C)
#define BALLOON3_VERSION_REG		(BALLOON3_FPGA_VIRT + 0x00e0001c)

#define BALLOON3_SAMOSA_ADDR_REG	(BALLOON3_FPGA_VIRT + 0x00c00000)
#define BALLOON3_SAMOSA_DATA_REG	(BALLOON3_FPGA_VIRT + 0x00c00004)
#define BALLOON3_SAMOSA_STATUS_REG	(BALLOON3_FPGA_VIRT + 0x00c0001c)

/* CF Status Register bits (read-only) bits */
#define BALLOON3_CF_nIRQ		(1 << 0)
#define BALLOON3_CF_nSTSCHG_BVD1	(1 << 1)

/* CF Control Set Register bits / CF Control Clear Register bits (write-only) */
#define BALLOON3_CF_RESET		(1 << 0)
#define BALLOON3_CF_ENABLE		(1 << 1)
#define BALLOON3_CF_ADD_ENABLE		(1 << 2)

/* CF Interrupt sources */
#define BALLOON3_BP_CF_NRDY_IRQ		BALLOON3_IRQ(0)
#define BALLOON3_BP_NSTSCHG_IRQ		BALLOON3_IRQ(1)

/* NAND Control register */
#define	BALLOON3_NAND_CONTROL_FLWP	(1 << 7)
#define	BALLOON3_NAND_CONTROL_FLSE	(1 << 6)
#define	BALLOON3_NAND_CONTROL_FLCE3	(1 << 5)
#define	BALLOON3_NAND_CONTROL_FLCE2	(1 << 4)
#define	BALLOON3_NAND_CONTROL_FLCE1	(1 << 3)
#define	BALLOON3_NAND_CONTROL_FLCE0	(1 << 2)
#define	BALLOON3_NAND_CONTROL_FLALE	(1 << 1)
#define	BALLOON3_NAND_CONTROL_FLCLE	(1 << 0)

/* NAND Status register */
#define	BALLOON3_NAND_STAT_RNB		(1 << 0)

/* NAND Control2 register */
#define	BALLOON3_NAND_CONTROL2_16BIT	(1 << 0)

/* GPIOs for irqs */
#define BALLOON3_GPIO_AUX_NIRQ		(94)
#define BALLOON3_GPIO_CODEC_IRQ		(95)

/* Timer and Idle LED locations */
#define BALLOON3_GPIO_LED_NAND		(9)
#define BALLOON3_GPIO_LED_IDLE		(10)

/* backlight control */
#define BALLOON3_GPIO_RUN_BACKLIGHT	(99)

#define BALLOON3_GPIO_S0_CD		(105)

/* NAND */
#define BALLOON3_GPIO_RUN_NAND		(102)

/* PCF8574A Leds */
#define	BALLOON3_PCF_GPIO_BASE		160
#define	BALLOON3_PCF_GPIO_LED0		(BALLOON3_PCF_GPIO_BASE + 0)
#define	BALLOON3_PCF_GPIO_LED1		(BALLOON3_PCF_GPIO_BASE + 1)
#define	BALLOON3_PCF_GPIO_LED2		(BALLOON3_PCF_GPIO_BASE + 2)
#define	BALLOON3_PCF_GPIO_LED3		(BALLOON3_PCF_GPIO_BASE + 3)
#define	BALLOON3_PCF_GPIO_LED4		(BALLOON3_PCF_GPIO_BASE + 4)
#define	BALLOON3_PCF_GPIO_LED5		(BALLOON3_PCF_GPIO_BASE + 5)
#define	BALLOON3_PCF_GPIO_LED6		(BALLOON3_PCF_GPIO_BASE + 6)
#define	BALLOON3_PCF_GPIO_LED7		(BALLOON3_PCF_GPIO_BASE + 7)

/* FPGA Interrupt Mask/Acknowledge Register */
#define BALLOON3_INT_S0_IRQ		(1 << 0)  /* PCMCIA 0 IRQ */
#define BALLOON3_INT_S0_STSCHG		(1 << 1)  /* PCMCIA 0 status changed */

/* CPLD (and FPGA) interface definitions */
#define CPLD_LCD0_DATA_SET             0x00
#define CPLD_LCD0_DATA_CLR             0x10
#define CPLD_LCD0_COMMAND_SET          0x01
#define CPLD_LCD0_COMMAND_CLR          0x11
#define CPLD_LCD1_DATA_SET             0x02
#define CPLD_LCD1_DATA_CLR             0x12
#define CPLD_LCD1_COMMAND_SET          0x03
#define CPLD_LCD1_COMMAND_CLR          0x13

#define CPLD_MISC_SET                  0x07
#define CPLD_MISC_CLR                  0x17
#define CPLD_MISC_LOON_NRESET_BIT      0
#define CPLD_MISC_LOON_UNSUSP_BIT      1
#define CPLD_MISC_RUN_5V_BIT           2
#define CPLD_MISC_CHG_D0_BIT           3
#define CPLD_MISC_CHG_D1_BIT           4
#define CPLD_MISC_DAC_NCS_BIT          5

#define CPLD_LCD_SET                   0x08
#define CPLD_LCD_CLR                   0x18
#define CPLD_LCD_BACKLIGHT_EN_0_BIT    0
#define CPLD_LCD_BACKLIGHT_EN_1_BIT    1
#define CPLD_LCD_LED_RED_BIT           4
#define CPLD_LCD_LED_GREEN_BIT         5
#define CPLD_LCD_NRESET_BIT            7

#define CPLD_LCD_RO_SET                0x09
#define CPLD_LCD_RO_CLR                0x19
#define CPLD_LCD_RO_LCD0_nWAIT_BIT     0
#define CPLD_LCD_RO_LCD1_nWAIT_BIT     1

#define CPLD_SERIAL_SET                0x0a
#define CPLD_SERIAL_CLR                0x1a
#define CPLD_SERIAL_GSM_RI_BIT         0
#define CPLD_SERIAL_GSM_CTS_BIT        1
#define CPLD_SERIAL_GSM_DTR_BIT        2
#define CPLD_SERIAL_LPR_CTS_BIT        3
#define CPLD_SERIAL_TC232_CTS_BIT      4
#define CPLD_SERIAL_TC232_DSR_BIT      5

#define CPLD_SROUTING_SET              0x0b
#define CPLD_SROUTING_CLR              0x1b
#define CPLD_SROUTING_MSP430_LPR       0
#define CPLD_SROUTING_MSP430_TC232     1
#define CPLD_SROUTING_MSP430_GSM       2
#define CPLD_SROUTING_LOON_LPR         (0 << 4)
#define CPLD_SROUTING_LOON_TC232       (1 << 4)
#define CPLD_SROUTING_LOON_GSM         (2 << 4)

#define CPLD_AROUTING_SET              0x0c
#define CPLD_AROUTING_CLR              0x1c
#define CPLD_AROUTING_MIC2PHONE_BIT    0
#define CPLD_AROUTING_PHONE2INT_BIT    1
#define CPLD_AROUTING_PHONE2EXT_BIT    2
#define CPLD_AROUTING_LOONL2INT_BIT    3
#define CPLD_AROUTING_LOONL2EXT_BIT    4
#define CPLD_AROUTING_LOONR2PHONE_BIT  5
#define CPLD_AROUTING_LOONR2INT_BIT    6
#define CPLD_AROUTING_LOONR2EXT_BIT    7

/* Balloon3 Interrupts */
#define BALLOON3_IRQ(x)		(IRQ_BOARD_START + (x))

#define BALLOON3_AUX_NIRQ	PXA_GPIO_TO_IRQ(BALLOON3_GPIO_AUX_NIRQ)
#define BALLOON3_CODEC_IRQ	PXA_GPIO_TO_IRQ(BALLOON3_GPIO_CODEC_IRQ)

#define BALLOON3_NR_IRQS	(IRQ_BOARD_START + 16)

extern int balloon3_has(enum balloon3_features feature);

#endif


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-pxa/capc7117.c
 *
 * Support for the Embedian CAPC-7117 Evaluation Kit
 * based on the Embedian MXM-8x10 Computer on Module
 *
 * Copyright (C) 2009 Embedian Inc.
 * Copyright (C) 2009 TMT Services & Supplies (Pty) Ltd.
 *
 * 2007-09-04: eric miao <eric.y.miao@gmail.com>
 *             rewrite to align with latest kernel
 *
 * 2010-01-09: Edwin Peer <epeer@tmtservices.co.za>
 *             Hennie van der Merwe <hvdmerwe@tmtservices.co.za>
 *             rework for upstream merge
 */

#include <linux/irq.h>
#include <linux/platform_device.h>
#include <linux/ata_platform.h>
#include <linux/serial_8250.h>
#include <linux/gpio.h>
#include <linux/regulator/machine.h>

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

#include "pxa320.h"
#include "mxm8x10.h"

#include "generic.h"

/* IDE (PATA) Support */
static struct pata_platform_info pata_platform_data = {
	.ioport_shift = 1
};

static struct resource capc7117_ide_resources[] = {
	[0] = {
	       .start = 0x11000020,
	       .end = 0x1100003f,
	       .flags = IORESOURCE_MEM
	},
	[1] = {
	       .start = 0x1100001c,
	       .end = 0x1100001c,
	       .flags = IORESOURCE_MEM
	},
	[2] = {
	       .start = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO76)),
	       .end = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO76)),
	       .flags = IORESOURCE_IRQ | IRQF_TRIGGER_RISING
	}
};

static struct platform_device capc7117_ide_device = {
	.name = "pata_platform",
	.num_resources = ARRAY_SIZE(capc7117_ide_resources),
	.resource = capc7117_ide_resources,
	.dev = {
		.platform_data = &pata_platform_data,
		.coherent_dma_mask = ~0		/* grumble */
	}
};

static void __init capc7117_ide_init(void)
{
	platform_device_register(&capc7117_ide_device);
}

/* TI16C752 UART support */
#define	TI16C752_FLAGS		(UPF_BOOT_AUTOCONF | \
					UPF_IOREMAP | \
					UPF_BUGGY_UART | \
					UPF_SKIP_TEST)
#define	TI16C752_UARTCLK	(22118400)
static struct plat_serial8250_port ti16c752_platform_data[] = {
	[0] = {
	       .mapbase = 0x14000000,
	       .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO78)),
	       .irqflags = IRQF_TRIGGER_RISING,
	       .flags = TI16C752_FLAGS,
	       .iotype = UPIO_MEM,
	       .regshift = 1,
	       .uartclk = TI16C752_UARTCLK
	},
	[1] = {
	       .mapbase = 0x14000040,
	       .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO79)),
	       .irqflags = IRQF_TRIGGER_RISING,
	       .flags = TI16C752_FLAGS,
	       .iotype = UPIO_MEM,
	       .regshift = 1,
	       .uartclk = TI16C752_UARTCLK
	},
	[2] = {
	       .mapbase = 0x14000080,
	       .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO80)),
	       .irqflags = IRQF_TRIGGER_RISING,
	       .flags = TI16C752_FLAGS,
	       .iotype = UPIO_MEM,
	       .regshift = 1,
	       .uartclk = TI16C752_UARTCLK
	},
	[3] = {
	       .mapbase = 0x140000c0,
	       .irq = PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO81)),
	       .irqflags = IRQF_TRIGGER_RISING,
	       .flags = TI16C752_FLAGS,
	       .iotype = UPIO_MEM,
	       .regshift = 1,
	       .uartclk = TI16C752_UARTCLK
	},
	[4] = {
	       /* end of array */
	}
};

static struct platform_device ti16c752_device = {
	.name = "serial8250",
	.id = PLAT8250_DEV_PLATFORM,
	.dev = {
		.platform_data = ti16c752_platform_data
	}
};

static void __init capc7117_uarts_init(void)
{
	platform_device_register(&ti16c752_device);
}

static void __init capc7117_init(void)
{
	/* Init CoM */
	mxm_8x10_barebones_init();

	/* Init evaluation board peripherals */
	mxm_8x10_ac97_init();
	mxm_8x10_usb_host_init();
	mxm_8x10_mmc_init();

	capc7117_uarts_init();
	capc7117_ide_init();

	regulator_has_full_constraints();
}

MACHINE_START(CAPC7117,
	      "Embedian CAPC-7117 evaluation kit based on the MXM-8x10 CoM")
	.atag_offset = 0x100,
	.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,
	.init_machine = capc7117_init,
	.restart	= pxa_restart,
MACHINE_END


code:
// SPDX-License-Identifier: GPL-2.0-only
/*
 * linux/arch/arm/mach-pxa/cm-x300.c
 *
 * Support for the CompuLab CM-X300 modules
 *
 * Copyright (C) 2008,2009 CompuLab Ltd.
 *
 * Mike Rapoport <mike@compulab.co.il>
 * Igor Grinberg <grinberg@compulab.co.il>
 */
#define pr_fmt(fmt) "%s: " fmt, __func__

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>

#include <linux/gpio.h>
#include <linux/gpio/machine.h>
#include <linux/dm9000.h>
#include <linux/leds.h>
#include <linux/platform_data/rtc-v3020.h>
#include <linux/pwm.h>
#include <linux/pwm_backlight.h>

#include <linux/i2c.h>
#include <linux/platform_data/pca953x.h>
#include <linux/platform_data/i2c-pxa.h>

#include <linux/mfd/da903x.h>
#include <linux/regulator/machine.h>
#include <linux/power_supply.h>
#include <linux/apm-emulation.h>

#include <linux/spi/spi.h>
#include <linux/spi/spi_gpio.h>
#include <linux/spi/tdo24m.h>

#include <linux/soc/pxa/cpu.h>

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

#include "pxa300.h"
#include "pxa27x-udc.h"
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/mmc-pxamci.h>
#include <linux/platform_data/usb-ohci-pxa27x.h>
#include <linux/platform_data/mtd-nand-pxa3xx.h>
#include <linux/platform_data/asoc-pxa.h>
#include <linux/platform_data/usb-pxa3xx-ulpi.h>

#include <asm/mach/map.h>

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

#define CM_X300_ETH_PHYS	0x08000010

#define GPIO82_MMC_IRQ		(82)
#define GPIO85_MMC_WP		(85)

#define	CM_X300_MMC_IRQ		PXA_GPIO_TO_IRQ(GPIO82_MMC_IRQ)

#define GPIO95_RTC_CS		(95)
#define GPIO96_RTC_WR		(96)
#define GPIO97_RTC_RD		(97)
#define GPIO98_RTC_IO		(98)

#define GPIO_ULPI_PHY_RST	(127)

static mfp_cfg_t cm_x3xx_mfp_cfg[] __initdata = {
	/* LCD */
	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,
	GPIO72_LCD_FCLK,
	GPIO73_LCD_LCLK,
	GPIO74_LCD_PCLK,
	GPIO75_LCD_BIAS,

	/* BTUART */
	GPIO111_UART2_RTS,
	GPIO112_UART2_RXD | MFP_LPM_EDGE_FALL,
	GPIO113_UART2_TXD,
	GPIO114_UART2_CTS | MFP_LPM_EDGE_BOTH,

	/* STUART */
	GPIO109_UART3_TXD,
	GPIO110_UART3_RXD | MFP_LPM_EDGE_FALL,

	/* AC97 */
	GPIO23_AC97_nACRESET,
	GPIO24_AC97_SYSCLK,
	GPIO29_AC97_BITCLK,
	GPIO25_AC97_SDATA_IN_0,
	GPIO27_AC97_SDATA_OUT,
	GPIO28_AC97_SYNC,

	/* Keypad */
	GPIO115_KP_MKIN_0 | MFP_LPM_EDGE_BOTH,
	GPIO116_KP_MKIN_1 | MFP_LPM_EDGE_BOTH,
	GPIO117_KP_MKIN_2 | MFP_LPM_EDGE_BOTH,
	GPIO118_KP_MKIN_3 | MFP_LPM_EDGE_BOTH,
	GPIO119_KP_MKIN_4 | MFP_LPM_EDGE_BOTH,
	GPIO120_KP_MKIN_5 | MFP_LPM_EDGE_BOTH,
	GPIO2_2_KP_MKIN_6 | MFP_LPM_EDGE_BOTH,
	GPIO3_2_KP_MKIN_7 | MFP_LPM_EDGE_BOTH,
	GPIO121_KP_MKOUT_0,
	GPIO122_KP_MKOUT_1,
	GPIO123_KP_MKOUT_2,
	GPIO124_KP_MKOUT_3,
	GPIO125_KP_MKOUT_4,
	GPIO4_2_KP_MKOUT_5,

	/* MMC1 */
	GPIO3_MMC1_DAT0,
	GPIO4_MMC1_DAT1 | MFP_LPM_EDGE_BOTH,
	GPIO5_MMC1_DAT2,
	GPIO6_MMC1_DAT3,
	GPIO7_MMC1_CLK,
	GPIO8_MMC1_CMD,	/* CMD0 for slot 0 */

	/* MMC2 */
	GPIO9_MMC2_DAT0,
	GPIO10_MMC2_DAT1 | MFP_LPM_EDGE_BOTH,
	GPIO11_MMC2_DAT2,
	GPIO12_MMC2_DAT3,
	GPIO13_MMC2_CLK,
	GPIO14_MMC2_CMD,

	/* FFUART */
	GPIO30_UART1_RXD | MFP_LPM_EDGE_FALL,
	GPIO31_UART1_TXD,
	GPIO32_UART1_CTS,
	GPIO37_UART1_RTS,
	GPIO33_UART1_DCD,
	GPIO34_UART1_DSR | MFP_LPM_EDGE_FALL,
	GPIO35_UART1_RI,
	GPIO36_UART1_DTR,

	/* GPIOs */
	GPIO82_GPIO | MFP_PULL_HIGH,	/* MMC CD */
	GPIO85_GPIO,			/* MMC WP */
	GPIO99_GPIO,			/* Ethernet IRQ */

	/* RTC GPIOs */
	GPIO95_GPIO | MFP_LPM_DRIVE_HIGH,	/* RTC CS */
	GPIO96_GPIO | MFP_LPM_DRIVE_HIGH,	/* RTC WR */
	GPIO97_GPIO | MFP_LPM_DRIVE_HIGH,	/* RTC RD */
	GPIO98_GPIO,				/* RTC IO */

	/* Standard I2C */
	GPIO21_I2C_SCL,
	GPIO22_I2C_SDA,

	/* PWM Backlight */
	GPIO19_PWM2_OUT,
};

static mfp_cfg_t cm_x3xx_rev_lt130_mfp_cfg[] __initdata = {
	/* GPIOs */
	GPIO79_GPIO,			/* LED */
	GPIO77_GPIO,			/* WiFi reset */
	GPIO78_GPIO,			/* BT reset */
};

static mfp_cfg_t cm_x3xx_rev_ge130_mfp_cfg[] __initdata = {
	/* GPIOs */
	GPIO76_GPIO,			/* LED */
	GPIO71_GPIO,			/* WiFi reset */
	GPIO70_GPIO,			/* BT reset */
};

static mfp_cfg_t cm_x310_mfp_cfg[] __initdata = {
	/* USB PORT 2 */
	ULPI_STP,
	ULPI_NXT,
	ULPI_DIR,
	GPIO30_ULPI_DATA_OUT_0,
	GPIO31_ULPI_DATA_OUT_1,
	GPIO32_ULPI_DATA_OUT_2,
	GPIO33_ULPI_DATA_OUT_3,
	GPIO34_ULPI_DATA_OUT_4,
	GPIO35_ULPI_DATA_OUT_5,
	GPIO36_ULPI_DATA_OUT_6,
	GPIO37_ULPI_DATA_OUT_7,
	GPIO38_ULPI_CLK,
	/* external PHY reset pin */
	GPIO127_GPIO,

	/* USB PORT 3 */
	GPIO77_USB_P3_1,
	GPIO78_USB_P3_2,
	GPIO79_USB_P3_3,
	GPIO80_USB_P3_4,
	GPIO81_USB_P3_5,
	GPIO82_USB_P3_6,
	GPIO0_2_USBH_PEN,
};

#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
static struct resource dm9000_resources[] = {
	[0] = {
		.start	= CM_X300_ETH_PHYS,
		.end	= CM_X300_ETH_PHYS + 0x3,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= CM_X300_ETH_PHYS + 0x4,
		.end	= CM_X300_ETH_PHYS + 0x4 + 500,
		.flags	= IORESOURCE_MEM,
	},
	[2] = {
		.start	= PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO99)),
		.end	= PXA_GPIO_TO_IRQ(mfp_to_gpio(MFP_PIN_GPIO99)),
		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
	}
};

static struct dm9000_plat_data cm_x300_dm9000_platdata = {
	.flags		= DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
};

static struct platform_device dm9000_device = {
	.name		= "dm9000",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(dm9000_resources),
	.resource	= dm9000_resources,
	.dev		= {
		.platform_data = &cm_x300_dm9000_platdata,
	}

};

static void __init cm_x300_init_dm9000(void)
{
	platform_device_register(&dm9000_device);
}
#else
static inline void cm_x300_init_dm9000(void) {}
#endif

/* LCD */
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct pxafb_mode_info cm_x300_lcd_modes[] = {
	[0] = {
		.pixclock	= 38250,
		.bpp		= 16,
		.xres		= 480,
		.yres		= 640,
		.hsync_len	= 8,
		.vsync_len	= 2,
		.left_margin	= 8,
		.upper_margin	= 2,
		.right_margin	= 24,
		.lower_margin	= 4,
		.cmap_greyscale	= 0,
	},
	[1] = {
		.pixclock	= 153800,
		.bpp		= 16,
		.xres		= 240,
		.yres		= 320,
		.hsync_len	= 8,
		.vsync_len	= 2,
		.left_margin	= 8,
		.upper_margin	= 2,
		.right_margin	= 88,
		.lower_margin	= 2,
		.cmap_greyscale	= 0,
	},
};

static struct pxafb_mach_info cm_x300_lcd = {
	.modes			= cm_x300_lcd_modes,
	.num_modes		= ARRAY_SIZE(cm_x300_lcd_modes),
	.lcd_conn		= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
};

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

#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
static struct pwm_lookup cm_x300_pwm_lookup[] = {
	PWM_LOOKUP("pxa27x-pwm.0", 1, "pwm-backlight.0", NULL, 10000,
		   PWM_POLARITY_NORMAL),
};

static struct platform_pwm_backlight_data cm_x300_backlight_data = {
	.max_brightness	= 100,
	.dft_brightness	= 100,
};

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

static void cm_x300_init_bl(void)
{
	pwm_add_table(cm_x300_pwm_lookup, ARRAY_SIZE(cm_x300_pwm_lookup));
	platform_device_register(&cm_x300_backlight_device);
}
#else
static inline void cm_x300_init_bl(void) {}
#endif

#if defined(CONFIG_SPI_GPIO) || defined(CONFIG_SPI_GPIO_MODULE)
#define GPIO_LCD_BASE	(144)
#define GPIO_LCD_DIN	(GPIO_LCD_BASE + 8)	/* aux_gpio3_0 */
#define GPIO_LCD_DOUT	(GPIO_LCD_BASE + 9)	/* aux_gpio3_1 */
#define GPIO_LCD_SCL	(GPIO_LCD_BASE + 10)	/* aux_gpio3_2 */
#define GPIO_LCD_CS	(GPIO_LCD_BASE + 11)	/* aux_gpio3_3 */
#define LCD_SPI_BUS_NUM	(1)

static struct spi_gpio_platform_data cm_x300_spi_gpio_pdata = {
	.num_chipselect	= 1,
};

static struct platform_device cm_x300_spi_gpio = {
	.name		= "spi_gpio",
	.id		= LCD_SPI_BUS_NUM,
	.dev		= {
		.platform_data	= &cm_x300_spi_gpio_pdata,
	},
};

static struct gpiod_lookup_table cm_x300_spi_gpiod_table = {
	.dev_id         = "spi_gpio",
	.table          = {
		GPIO_LOOKUP("pca9555.1", GPIO_LCD_SCL - GPIO_LCD_BASE,
			    "sck", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("pca9555.1", GPIO_LCD_DIN - GPIO_LCD_BASE,
			    "mosi", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("pca9555.1", GPIO_LCD_DOUT - GPIO_LCD_BASE,
			    "miso", GPIO_ACTIVE_HIGH),
		GPIO_LOOKUP("pca9555.1", GPIO_LCD_CS - GPIO_LCD_BASE,
			    "cs", GPIO_ACTIVE_HIGH),
		{ },
	},
};

static struct tdo24m_platform_data cm_x300_tdo24m_pdata = {
	.model = TDO35S,
};

static struct spi_board_info cm_x300_spi_devices[] __initdata = {
	{
		.modalias		= "tdo24m",
		.max_speed_hz		= 1000000,
		.bus_num		= LCD_SPI_BUS_NUM,
		.chip_select		= 0,
		.platform_data		= &cm_x300_tdo24m_pdata,
	},
};

static void __init cm_x300_init_spi(void)
{
	spi_register_board_info(cm_x300_spi_devices,
				ARRAY_SIZE(cm_x300_spi_devices));
	gpiod_add_lookup_table(&cm_x300_spi_gpiod_table);
	platform_device_register(&cm_x300_spi_gpio);
}
#else
static inline void cm_x300_init_spi(void) {}
#endif

#if defined(CONFIG_SND_PXA2XX_LIB_AC97)
static void __init cm_x300_init_ac97(void)
{
	pxa_set_ac97_info(NULL);
}
#else
static inline void cm_x300_init_ac97(void) {}
#endif

#if IS_ENABLED(CONFIG_MTD_NAND_MARVELL)
static struct mtd_partition cm_x300_nand_partitions[] = {
	[0] = {
		.name        = "OBM",
		.offset      = 0,
		.size        = SZ_256K,
		.mask_flags  = MTD_WRITEABLE, /* force read-only */
	},
	[1] = {
		.name        = "U-Boot",
		.offset      = MTDPART_OFS_APPEND,
		.size        = SZ_256K,
		.mask_flags  = MTD_WRITEABLE, /* force read-only */
	},
	[2] = {
		.name        = "Environment",
		.offset      = MTDPART_OFS_APPEND,
		.size        = SZ_256K,
	},
	[3] = {
		.name        = "reserved",
		.offset      = MTDPART_OFS_APPEND,
		.size        = SZ_256K + SZ_1M,
		.mask_flags  = MTD_WRITEABLE, /* force read-only */
	},
	[4] = {
		.name        = "kernel",
		.offset      = MTDPART_OFS_APPEND,
		.size        = SZ_4M,
	},
	[5] = {
		.name        = "fs",
		.offset      = MTDPART_OFS_APPEND,
		.size        = MTDPART_SIZ_FULL,
	},
};

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

static void __init cm_x300_init_nand(void)
{
	pxa3xx_set_nand_info(&cm_x300_nand_info);
}
#else
static inline void cm_x300_init_nand(void) {}
#endif

#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
static struct pxamci_platform_data cm_x300_mci_platform_data = {
	.detect_delay_ms	= 200,
	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
};

static struct gpiod_lookup_table cm_x300_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		/* Card detect on GPIO 82 */
		GPIO_LOOKUP("gpio-pxa", GPIO82_MMC_IRQ, "cd", GPIO_ACTIVE_LOW),
		/* Write protect on GPIO 85 */
		GPIO_LOOKUP("gpio-pxa", GPIO85_MMC_WP, "wp", GPIO_ACTIVE_LOW),
		{ },
	},
};

/* The second MMC slot of CM-X300 is hardwired to Libertas card and has
   no detection/ro pins */
static int cm_x300_mci2_init(struct device *dev,
			     irq_handler_t cm_x300_detect_int,
	void *data)
{
	return 0;
}

static void cm_x300_mci2_exit(struct device *dev, void *data)
{
}

static struct pxamci_platform_data cm_x300_mci2_platform_data = {
	.detect_delay_ms	= 200,
	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34,
	.init 			= cm_x300_mci2_init,
	.exit			= cm_x300_mci2_exit,
};

static void __init cm_x300_init_mmc(void)
{
	gpiod_add_lookup_table(&cm_x300_mci_gpio_table);
	pxa_set_mci_info(&cm_x300_mci_platform_data);
	pxa3xx_set_mci2_info(&cm_x300_mci2_platform_data);
}
#else
static inline void cm_x300_init_mmc(void) {}
#endif

#if defined(CONFIG_PXA310_ULPI)
static struct clk *pout_clk;

static int cm_x300_ulpi_phy_reset(void)
{
	int err;

	/* reset the PHY */
	err = gpio_request_one(GPIO_ULPI_PHY_RST, GPIOF_OUT_INIT_LOW,
			       "ulpi reset");
	if (err) {
		pr_err("failed to request ULPI reset GPIO: %d\n", err);
		return err;
	}

	msleep(10);
	gpio_set_value(GPIO_ULPI_PHY_RST, 1);
	msleep(10);

	gpio_free(GPIO_ULPI_PHY_RST);

	return 0;
}

static int cm_x300_u2d_init(struct device *dev)
{
	int err = 0;

	if (cpu_is_pxa310()) {
		/* CLK_POUT is connected to the ULPI PHY */
		pout_clk = clk_get(NULL, "CLK_POUT");
		if (IS_ERR(pout_clk)) {
			err = PTR_ERR(pout_clk);
			pr_err("failed to get CLK_POUT: %d\n", err);
			return err;
		}
		clk_prepare_enable(pout_clk);

		err = cm_x300_ulpi_phy_reset();
		if (err) {
			clk_disable(pout_clk);
			clk_put(pout_clk);
		}
	}

	return err;
}

static void cm_x300_u2d_exit(struct device *dev)
{
	if (cpu_is_pxa310()) {
		clk_disable_unprepare(pout_clk);
		clk_put(pout_clk);
	}
}

static struct pxa3xx_u2d_platform_data cm_x300_u2d_platform_data = {
	.ulpi_mode	= ULPI_SER_6PIN,
	.init		= cm_x300_u2d_init,
	.exit		= cm_x300_u2d_exit,
};

static void __init cm_x300_init_u2d(void)
{
	pxa3xx_set_u2d_info(&cm_x300_u2d_platform_data);
}
#else
static inline void cm_x300_init_u2d(void) {}
#endif

#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int cm_x300_ohci_init(struct device *dev)
{
	if (cpu_is_pxa300())
		UP2OCR = UP2OCR_HXS
			| UP2OCR_HXOE | UP2OCR_DMPDE | UP2OCR_DPPDE;

	return 0;
}

static struct pxaohci_platform_data cm_x300_ohci_platform_data = {
	.port_mode	= PMM_PERPORT_MODE,
	.flags		= ENABLE_PORT_ALL | POWER_CONTROL_LOW,
	.init		= cm_x300_ohci_init,
};

static void __init cm_x300_init_ohci(void)
{
	pxa_set_ohci_info(&cm_x300_ohci_platform_data);
}
#else
static inline void cm_x300_init_ohci(void) {}
#endif

#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
static struct gpio_led cm_x300_leds[] = {
	[0] = {
		.name = "cm-x300:green",
		.default_trigger = "heartbeat",
		.active_low = 1,
	},
};

static struct gpio_led_platform_data cm_x300_gpio_led_pdata = {
	.num_leds = ARRAY_SIZE(cm_x300_leds),
	.leds = cm_x300_leds,
};

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

static void __init cm_x300_init_leds(void)
{
	if (system_rev < 130)
		cm_x300_leds[0].gpio = 79;
	else
		cm_x300_leds[0].gpio = 76;

	platform_device_register(&cm_x300_led_device);
}
#else
static inline void cm_x300_init_leds(void) {}
#endif

#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/* PCA9555 */
static struct pca953x_platform_data cm_x300_gpio_ext_pdata_0 = {
	.gpio_base = 128,
};

static struct pca953x_platform_data cm_x300_gpio_ext_pdata_1 = {
	.gpio_base = 144,
};

static struct i2c_board_info cm_x300_gpio_ext_info[] = {
	[0] = {
		I2C_BOARD_INFO("pca9555", 0x24),
		.platform_data = &cm_x300_gpio_ext_pdata_0,
	},
	[1] = {
		I2C_BOARD_INFO("pca9555", 0x25),
		.platform_data = &cm_x300_gpio_ext_pdata_1,
	},
};

static void __init cm_x300_init_i2c(void)
{
	pxa_set_i2c_info(NULL);
	i2c_register_board_info(0, cm_x300_gpio_ext_info,
				ARRAY_SIZE(cm_x300_gpio_ext_info));
}
#else
static inline void cm_x300_init_i2c(void) {}
#endif

#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
struct v3020_platform_data cm_x300_v3020_pdata = {
	.use_gpio	= 1,
	.gpio_cs	= GPIO95_RTC_CS,
	.gpio_wr	= GPIO96_RTC_WR,
	.gpio_rd	= GPIO97_RTC_RD,
	.gpio_io	= GPIO98_RTC_IO,
};

static struct platform_device cm_x300_rtc_device = {
	.name		= "v3020",
	.id		= -1,
	.dev		= {
		.platform_data = &cm_x300_v3020_pdata,
	}
};

static void __init cm_x300_init_rtc(void)
{
	platform_device_register(&cm_x300_rtc_device);
}
#else
static inline void cm_x300_init_rtc(void) {}
#endif

/* Battery */
struct power_supply_info cm_x300_psy_info = {
	.name = "battery",
	.technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
	.voltage_max_design = 4200000,
	.voltage_min_design = 3000000,
	.use_for_apm = 1,
};

static void cm_x300_battery_low(void)
{
#if defined(CONFIG_APM_EMULATION)
	apm_queue_event(APM_LOW_BATTERY);
#endif
}

static void cm_x300_battery_critical(void)
{
#if defined(CONFIG_APM_EMULATION)
	apm_queue_event(APM_CRITICAL_SUSPEND);
#endif
}

struct da9030_battery_info cm_x300_battery_info = {
	.battery_info = &cm_x300_psy_info,

	.charge_milliamp = 1000,
	.charge_millivolt = 4200,

	.vbat_low = 3600,
	.vbat_crit = 3400,
	.vbat_charge_start = 4100,
	.vbat_charge_stop = 4200,
	.vbat_charge_restart = 4000,

	.vcharge_min = 3200,
	.vcharge_max = 5500,

	.tbat_low = 197,
	.tbat_high = 78,
	.tbat_restart = 100,

	.batmon_interval = 0,

	.battery_low = cm_x300_battery_low,
	.battery_critical = cm_x300_battery_critical,
};

static struct regulator_consumer_supply buck2_consumers[] = {
	REGULATOR_SUPPLY("vcc_core", NULL),
};

static struct regulator_init_data buck2_data = {
	.constraints = {
		.min_uV = 1375000,
		.max_uV = 1375000,
		.state_mem = {
			.enabled = 0,
		},
		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
		.apply_uV = 1,
	},
	.num_consumer_supplies = ARRAY_SIZE(buck2_consumers),
	.consumer_supplies = buck2_consumers,
};

/* DA9030 */
struct da903x_subdev_info cm_x300_da9030_subdevs[] = {
	{
		.name = "da903x-battery",
		.id = DA9030_ID_BAT,
		.platform_data = &cm_x300_battery_info,
	},
	{
		.name = "da903x-regulator",
		.id = DA9030_ID_BUCK2,
		.platform_data = &buck2_data,
	},
};

static struct da903x_platform_data cm_x300_da9030_info = {
	.num_subdevs = ARRAY_SIZE(cm_x300_da9030_subdevs),
	.subdevs = cm_x300_da9030_subdevs,
};

static struct i2c_board_info cm_x300_pmic_info = {
	I2C_BOARD_INFO("da9030", 0x49),
	.irq = IRQ_WAKEUP0,
	.platform_data = &cm_x300_da9030_info,
};

static struct i2c_pxa_platform_data cm_x300_pwr_i2c_info = {
	.use_pio = 1,
};

static void __init cm_x300_init_da9030(void)
{
	pxa3xx_set_i2c_power_info(&cm_x300_pwr_i2c_info);
	i2c_register_board_info(1, &cm_x300_pmic_info, 1);
	irq_set_irq_wake(IRQ_WAKEUP0, 1);
}

/* wi2wi gpio setting for system_rev >= 130 */
static struct gpio cm_x300_wi2wi_gpios[] __initdata = {
	{ 71, GPIOF_OUT_INIT_HIGH, "wlan en" },
	{ 70, GPIOF_OUT_INIT_HIGH, "bt reset" },
};

static void __init cm_x300_init_wi2wi(void)
{
	int err;

	if (system_rev < 130) {
		cm_x300_wi2wi_gpios[0].gpio = 77;	/* wlan en */
		cm_x300_wi2wi_gpios[1].gpio = 78;	/* bt reset */
	}

	/* Libertas and CSR reset */
	err = gpio_request_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
	if (err) {
		pr_err("failed to request wifi/bt gpios: %d\n", err);
		return;
	}

	udelay(10);
	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 0);
	udelay(10);
	gpio_set_value(cm_x300_wi2wi_gpios[1].gpio, 1);

	gpio_free_array(ARRAY_AND_SIZE(cm_x300_wi2wi_gpios));
}

/* MFP */
static void __init cm_x300_init_mfp(void)
{
	/* board-processor specific GPIO initialization */
	pxa3xx_mfp_config(ARRAY_AND_SIZE(cm_x3xx_mfp_cfg));

	if (system_rev < 130)
		pxa3xx_mfp_config(ARRAY_AND_SIZE(cm_x3xx_rev_lt130_mfp_cfg));
	else
		pxa3xx_mfp_config(ARRAY_AND_SIZE(cm_x3xx_rev_ge130_mfp_cfg));

	if (cpu_is_pxa310())
		pxa3xx_mfp_config(ARRAY_AND_SIZE(cm_x310_mfp_cfg));
}

static void __init cm_x300_init(void)
{
	cm_x300_init_mfp();

	pxa_set_btuart_info(NULL);
	pxa_set_stuart_info(NULL);
	if (cpu_is_pxa300())
		pxa_set_ffuart_info(NULL);

	cm_x300_init_da9030();
	cm_x300_init_dm9000();
	cm_x300_init_lcd();
	cm_x300_init_u2d();
	cm_x300_init_ohci();
	cm_x300_init_mmc();
	cm_x300_init_nand();
	cm_x300_init_leds();
	cm_x300_init_i2c();
	cm_x300_init_spi();
	cm_x300_init_rtc();
	cm_x300_init_ac97();
	cm_x300_init_wi2wi();
	cm_x300_init_bl();

	regulator_has_full_constraints();
}

static void __init cm_x300_fixup(struct tag *tags, char **cmdline)
{
	/* Make sure that mi->bank[0].start = PHYS_ADDR */
	for (; tags->hdr.size; tags = tag_next(tags))
		if (tags->hdr.tag == ATAG_MEM &&
			tags->u.mem.start == 0x80000000) {
			tags->u.mem.start = 0xa0000000;
			break;
		}
}

MACHINE_START(CM_X300, "CM-X300 module")
	.atag_offset	= 0x100,
	.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,
	.init_machine	= cm_x300_init,
	.fixup		= cm_x300_fixup,
	.restart	= pxa_restart,
MACHINE_END


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

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/gpio/machine.h>
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <linux/i2c.h>
#include <linux/platform_data/i2c-pxa.h>
#include <asm/io.h>

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

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

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

static struct gpiod_lookup_table colibri_pxa270_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		GPIO_LOOKUP("gpio-pxa", GPIO0_COLIBRI_PXA270_SD_DETECT,
			    "cd", GPIO_ACTIVE_LOW),
		{ },
	},
};

static struct gpiod_lookup_table colibri_pxa300_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		GPIO_LOOKUP("gpio-pxa", GPIO13_COLIBRI_PXA300_SD_DETECT,
			    "cd", GPIO_ACTIVE_LOW),
		{ },
	},
};

static struct gpiod_lookup_table colibri_pxa320_mci_gpio_table = {
	.dev_id = "pxa2xx-mci.0",
	.table = {
		GPIO_LOOKUP("gpio-pxa", GPIO28_COLIBRI_PXA320_SD_DETECT,
			    "cd", GPIO_ACTIVE_LOW),
		{ },
	},
};

static void __init colibri_mmc_init(void)
{
	if (machine_is_colibri())	/* PXA270 Colibri */
		gpiod_add_lookup_table(&colibri_pxa270_mci_gpio_table);
	if (machine_is_colibri300())	/* PXA300 Colibri */
		gpiod_add_lookup_table(&colibri_pxa300_mci_gpio_table);
	else				/* PXA320 Colibri */
		gpiod_add_lookup_table(&colibri_pxa320_mci_gpio_table);

	pxa_set_mci_info(&colibri_mci_platform_data);
}
#else
static inline void colibri_mmc_init(void) {}
#endif

/******************************************************************************
 * USB Host
 ******************************************************************************/
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
static int colibri_ohci_init(struct device *dev)
{
	UP2OCR = UP2OCR_HXS | UP2OCR_HXOE | UP2OCR_DPPDE | UP2OCR_DMPDE;
	return 0;
}

static struct pxaohci_platform_data colibri_ohci_info = {
	.port_mode	= PMM_PERPORT_MODE,
	.flags		= ENABLE_PORT1 |
			  POWER_CONTROL_LOW | POWER_SENSE_LOW,
	.init		= colibri_ohci_init,
};

static void __init colibri_uhc_init(void)
{
	/* Colibri PXA270 has two usb ports, TBA for 320 */
	if (machine_is_colibri())
		colibri_ohci_info.flags	|= ENABLE_PORT2;

	pxa_set_ohci_info(&colibri_ohci_info);
}
#else
static inline void colibri_uhc_init(void) {}
#endif

/******************************************************************************
 * I2C RTC
 ******************************************************************************/
#if defined(CONFIG_RTC_DRV_DS1307) || defined(CONFIG_RTC_DRV_DS1307_MODULE)
static struct i2c_board_info __initdata colibri_i2c_devs[] = {
	{
		I2C_BOARD_INFO("m41t00", 0x68),
	},
};

static void __init colibri_rtc_init(void)
{
	pxa_set_i2c_info(NULL);
	i2c_register_board_info(0, ARRAY_AND_SIZE(colibri_i2c_devs));
}
#else
static inline void colibri_rtc_init(void) {}
#endif

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

	colibri_mmc_init();
	colibri_uhc_init();
	colibri_rtc_init();
}