summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards.dox4
-rw-r--r--Makefile2
-rw-r--r--arch/arm/Kconfig7
-rw-r--r--arch/arm/Makefile1
-rw-r--r--arch/arm/boards/Makefile2
-rw-r--r--arch/arm/boards/chumby_falconwing/falconwing.c1
-rw-r--r--arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c1
-rw-r--r--arch/arm/boards/freescale-mx21-ads/imx21ads.c1
-rw-r--r--arch/arm/boards/freescale-mx28-evk/mx28-evk.c1
-rw-r--r--arch/arm/boards/freescale-mx35-3ds/3stack.c1
-rw-r--r--arch/arm/boards/freescale-mx53-qsb/board.c3
-rw-r--r--arch/arm/boards/freescale-mx53-qsb/env/config-board1
-rw-r--r--arch/arm/boards/freescale-mx6-sabrelite/board.c64
-rw-r--r--arch/arm/boards/friendlyarm-mini2440/mini2440.c1
-rw-r--r--arch/arm/boards/guf-cupid/board.c1
-rw-r--r--arch/arm/boards/karo-tx28/tx28-stk5.c5
-rw-r--r--arch/arm/boards/phytec-phycore-imx35/pcm043.c2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/Makefile3
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/board.c29
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg6
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h2
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg6
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h95
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg6
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/lowlevel.c47
-rw-r--r--arch/arm/boards/variscite-mx6/Makefile3
-rw-r--r--arch/arm/boards/variscite-mx6/board.c135
-rw-r--r--arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg86
-rw-r--r--arch/arm/boards/variscite-mx6/lowlevel.c74
-rw-r--r--arch/arm/boards/virt2real/Makefile1
-rw-r--r--arch/arm/boards/virt2real/board.c27
-rw-r--r--arch/arm/boards/virt2real/lowlevel.c34
-rw-r--r--arch/arm/boards/virt2real/virt2real.dox41
-rw-r--r--arch/arm/configs/freescale-mx53-qsb_defconfig31
-rw-r--r--arch/arm/configs/imx_v7_defconfig26
-rw-r--r--arch/arm/configs/panda_defconfig4
-rw-r--r--arch/arm/configs/panda_xload_defconfig2
-rw-r--r--arch/arm/configs/phytec-phycore-imx35_defconfig13
-rw-r--r--arch/arm/configs/virt2real_defconfig49
-rw-r--r--arch/arm/dts/Makefile11
-rw-r--r--arch/arm/dts/dm365.dtsi28
-rw-r--r--arch/arm/dts/imx27-phytec-phycard-s-rdk-bb.dts38
-rw-r--r--arch/arm/dts/imx27-phytec-phycard-s-rdk.dts39
-rw-r--r--arch/arm/dts/imx27-phytec-phycard-s-som.dtsi (renamed from arch/arm/dts/imx27-phytec-phycard-s-som.dts)91
-rw-r--r--arch/arm/dts/imx27-pingrp.h151
-rw-r--r--arch/arm/dts/imx27.dtsi59
-rw-r--r--arch/arm/dts/imx53-qsb-common.dtsi4
-rw-r--r--arch/arm/dts/imx53.dtsi6
-rw-r--r--arch/arm/dts/imx6dl-phytec-pbab01.dts29
-rw-r--r--arch/arm/dts/imx6dl-phytec-pfla02.dtsi41
-rw-r--r--arch/arm/dts/imx6q-phytec-pbab01.dts23
-rw-r--r--arch/arm/dts/imx6q-phytec-pfla02.dtsi207
-rw-r--r--arch/arm/dts/imx6q-var-custom.dts149
-rw-r--r--arch/arm/dts/imx6q-var-som.dtsi99
-rw-r--r--arch/arm/dts/imx6q.dtsi5
-rw-r--r--arch/arm/dts/imx6qdl-phytec-pbab01.dtsi43
-rw-r--r--arch/arm/dts/imx6qdl-phytec-pfla02.dtsi171
-rw-r--r--arch/arm/dts/imx6qdl.dtsi12
-rw-r--r--arch/arm/dts/imx6s-phytec-pbab01.dts25
-rw-r--r--arch/arm/dts/imx6s-phytec-pfla02.dtsi22
-rw-r--r--arch/arm/dts/virt2real.dts35
-rw-r--r--arch/arm/include/asm/memory.h7
-rw-r--r--arch/arm/mach-arm.dox2
-rw-r--r--arch/arm/mach-at91/include/mach/cpu.h5
-rw-r--r--arch/arm/mach-at91/sama5d3.c6
-rw-r--r--arch/arm/mach-at91/setup.c3
-rw-r--r--arch/arm/mach-clps711x/clock.c4
-rw-r--r--arch/arm/mach-davinci/Kconfig16
-rw-r--r--arch/arm/mach-davinci/Makefile1
-rw-r--r--arch/arm/mach-davinci/include/mach/debug_ll.h42
-rw-r--r--arch/arm/mach-davinci/include/mach/hardware.h29
-rw-r--r--arch/arm/mach-davinci/include/mach/serial.h20
-rw-r--r--arch/arm/mach-davinci/include/mach/time.h20
-rw-r--r--arch/arm/mach-davinci/mach-davinci.dox7
-rw-r--r--arch/arm/mach-davinci/time.c209
-rw-r--r--arch/arm/mach-imx/Kconfig14
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/clk-imx6.c155
-rw-r--r--arch/arm/mach-imx/clk.h22
-rw-r--r--arch/arm/mach-imx/imx6-bbu-nand.c497
-rw-r--r--arch/arm/mach-imx/imx6.c19
-rw-r--r--arch/arm/mach-imx/include/mach/bbu.h6
-rw-r--r--arch/arm/mach-imx/include/mach/imx6-regs.h3
-rw-r--r--arch/arm/mach-zynq/clk-zynq7000.c8
-rw-r--r--arch/mips/Kconfig14
-rw-r--r--arch/mips/Makefile5
-rw-r--r--arch/mips/boards/ritmix-rzx50/Makefile1
-rw-r--r--arch/mips/boards/ritmix-rzx50/include/board/board_pbl_start.h (renamed from arch/mips/boards/rzx50/include/board/board_pbl_start.h)0
-rw-r--r--arch/mips/boards/ritmix-rzx50/include/board/debug_ll.h (renamed from arch/mips/boards/rzx50/include/board/debug_ll.h)0
-rw-r--r--arch/mips/boards/ritmix-rzx50/ritmix-rzx50.dox (renamed from arch/mips/boards/rzx50/rzx50.dox)2
-rw-r--r--arch/mips/boards/ritmix-rzx50/serial.c (renamed from arch/mips/boards/rzx50/serial.c)9
-rw-r--r--arch/mips/boards/rzx50/Makefile1
-rw-r--r--arch/mips/boards/tplink-mr3020/Makefile1
-rw-r--r--arch/mips/boards/tplink-mr3020/board.c27
-rw-r--r--arch/mips/boards/tplink-mr3020/tplink-mr3020.dox64
-rw-r--r--arch/mips/configs/ritmix-rzx50_defconfig (renamed from arch/mips/configs/rzx50_defconfig)0
-rw-r--r--arch/mips/configs/tplink-mr3020_defconfig29
-rw-r--r--arch/mips/dts/ar9331.dtsi26
l---------arch/mips/dts/include/dt-bindings1
-rw-r--r--arch/mips/dts/jz4755.dtsi35
-rw-r--r--arch/mips/dts/qemu-malta.dts8
-rw-r--r--arch/mips/dts/rzx50.dts6
-rw-r--r--arch/mips/dts/tplink-mr3020.dts16
-rw-r--r--arch/mips/include/asm/debug_ll_ns16550.h2
-rw-r--r--arch/mips/lib/barebox.lds.S2
-rw-r--r--arch/mips/mach-ath79/Kconfig15
-rw-r--r--arch/mips/mach-ath79/Makefile1
-rw-r--r--arch/mips/mach-ath79/include/mach/ar71xx_regs.h64
-rw-r--r--arch/mips/mach-ath79/include/mach/ath79.h33
-rw-r--r--arch/mips/mach-ath79/include/mach/debug_ll.h56
-rw-r--r--arch/mips/mach-ath79/reset.c32
-rw-r--r--arch/mips/mach-malta/include/mach/hardware.h3
-rw-r--r--arch/mips/mach-xburst/Makefile1
-rw-r--r--arch/mips/mach-xburst/mach-xburst.dox2
-rw-r--r--arch/mips/mach-xburst/serial.c60
-rw-r--r--commands/Kconfig8
-rw-r--r--commands/Makefile1
-rw-r--r--commands/boot.c121
-rw-r--r--commands/menutree.c60
-rw-r--r--commands/nandtest.c2
-rw-r--r--commands/partition.c15
-rw-r--r--commands/trigger.c1
-rw-r--r--commands/ubi.c4
-rw-r--r--common/Kconfig5
-rw-r--r--common/Makefile1
-rw-r--r--common/blspec.c81
-rw-r--r--common/environment.c10
-rw-r--r--common/hush.c33
-rw-r--r--common/menutree.c181
-rw-r--r--defaultenv/defaultenv-2-menu/menu/00-boot-default/action5
-rw-r--r--defaultenv/defaultenv-2-menu/menu/00-boot-default/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/10-boot-all/action3
-rw-r--r--defaultenv/defaultenv-2-menu/menu/10-boot-all/net/action5
-rw-r--r--defaultenv/defaultenv-2-menu/menu/10-boot-all/net/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/10-boot-all/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/20-settings/config/action5
-rw-r--r--defaultenv/defaultenv-2-menu/menu/20-settings/config/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/20-settings/network/action3
-rw-r--r--defaultenv/defaultenv-2-menu/menu/20-settings/network/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/20-settings/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/30-saveenv/action8
-rw-r--r--defaultenv/defaultenv-2-menu/menu/30-saveenv/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/40-shell/action5
-rw-r--r--defaultenv/defaultenv-2-menu/menu/40-shell/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/50-reset/action3
-rw-r--r--defaultenv/defaultenv-2-menu/menu/50-reset/title1
-rw-r--r--defaultenv/defaultenv-2-menu/menu/boot-entries-collect13
-rw-r--r--defaultenv/defaultenv-2-menu/menu/boot-entries-edit20
-rw-r--r--defaultenv/defaultenv-2-menu/menu/boot-entries-remove18
-rw-r--r--defaultenv/defaultenv-2-menu/menu/boot-menu-add-entry5
-rw-r--r--defaultenv/defaultenv-2-menu/menu/boot-menu-new-boot-entry21
-rw-r--r--defaultenv/defaultenv-2-menu/menu/init-entries-collect9
-rw-r--r--defaultenv/defaultenv-2-menu/menu/init-entries-edit20
-rw-r--r--defaultenv/defaultenv-2-menu/menu/init-menu-add-entry3
-rw-r--r--defaultenv/defaultenv-2-menu/menu/mainmenu20
-rw-r--r--defaultenv/defaultenv-2-menu/menu/settings21
-rw-r--r--defaultenv/defaultenv-2-menu/menu/title1
-rw-r--r--drivers/clk/Makefile3
-rw-r--r--drivers/clk/clk-ar933x.c175
-rw-r--r--drivers/clk/clk-divider-table.c119
-rw-r--r--drivers/clk/clk-divider.c234
-rw-r--r--drivers/clk/clk-fixed-factor.c33
-rw-r--r--drivers/clk/clk-gate.c13
-rw-r--r--drivers/clk/clk-mux.c10
-rw-r--r--drivers/clk/clk.c30
-rw-r--r--drivers/clk/mvebu/common.c4
-rw-r--r--drivers/clk/mxs/clk-imx28.c2
-rw-r--r--drivers/clk/mxs/clk.h6
-rw-r--r--drivers/clk/tegra/clk-periph.c4
-rw-r--r--drivers/clk/tegra/clk-tegra20.c2
-rw-r--r--drivers/clocksource/Kconfig23
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/dummy.c56
-rw-r--r--drivers/gpio/Kconfig7
-rw-r--r--drivers/gpio/Makefile1
-rw-r--r--drivers/gpio/gpio-davinci.c211
-rw-r--r--drivers/i2c/busses/i2c-imx.c2
-rw-r--r--drivers/i2c/i2c.c11
-rw-r--r--drivers/input/gpio_keys.c2
-rw-r--r--drivers/mtd/core.c2
-rw-r--r--drivers/mtd/devices/m25p80.c5
-rw-r--r--drivers/mtd/devices/mtd_dataflash.c2
-rw-r--r--drivers/mtd/mtdoob.c2
-rw-r--r--drivers/mtd/mtdraw.c2
-rw-r--r--drivers/mtd/nand/nand_mxs.c32
-rw-r--r--drivers/mtd/nand/nand_omap_gpmc.c2
-rw-r--r--drivers/mtd/partition.c4
-rw-r--r--drivers/mtd/ubi/build.c2
-rw-r--r--drivers/mtd/ubi/cdev.c2
-rw-r--r--drivers/net/ar231x.c6
-rw-r--r--drivers/net/at91_ether.c5
-rw-r--r--drivers/net/designware.c5
-rw-r--r--drivers/of/base.c7
-rw-r--r--drivers/serial/Kconfig7
-rw-r--r--drivers/serial/Makefile1
-rw-r--r--drivers/serial/serial_ar933x.c204
-rw-r--r--drivers/serial/serial_ar933x.h69
-rw-r--r--drivers/serial/serial_ns16550.c51
-rw-r--r--drivers/usb/gadget/composite.c9
-rw-r--r--drivers/usb/gadget/dfu.c4
-rw-r--r--drivers/video/Kconfig8
-rw-r--r--drivers/video/Makefile3
-rw-r--r--drivers/video/atmel_lcdfb_core.c6
-rw-r--r--drivers/video/edid.c909
-rw-r--r--drivers/video/edid.h138
-rw-r--r--drivers/video/fb.c113
-rw-r--r--drivers/video/imx-ipu-fb.c9
-rw-r--r--drivers/video/imx-ipu-v3/Kconfig14
-rw-r--r--drivers/video/imx-ipu-v3/Makefile5
-rw-r--r--drivers/video/imx-ipu-v3/imx-hdmi.c1297
-rw-r--r--drivers/video/imx-ipu-v3/imx-hdmi.h1032
-rw-r--r--drivers/video/imx-ipu-v3/imx-ipu-v3.h344
-rw-r--r--drivers/video/imx-ipu-v3/imx-ldb.c310
-rw-r--r--drivers/video/imx-ipu-v3/ipu-common.c836
-rw-r--r--drivers/video/imx-ipu-v3/ipu-dc.c392
-rw-r--r--drivers/video/imx-ipu-v3/ipu-di.c762
-rw-r--r--drivers/video/imx-ipu-v3/ipu-dmfc.c397
-rw-r--r--drivers/video/imx-ipu-v3/ipu-dp.c313
-rw-r--r--drivers/video/imx-ipu-v3/ipu-prv.h204
-rw-r--r--drivers/video/imx-ipu-v3/ipufb.c353
-rw-r--r--drivers/video/imx-ipu-v3/ipuv3-plane.c239
-rw-r--r--drivers/video/imx-ipu-v3/ipuv3-plane.h51
-rw-r--r--drivers/video/imx.c11
-rw-r--r--drivers/video/of_display_timing.c238
-rw-r--r--drivers/video/omap.c4
-rw-r--r--drivers/video/pxa.c5
-rw-r--r--drivers/video/s3c24xx.c6
-rw-r--r--drivers/video/sdl.c4
-rw-r--r--drivers/video/stm.c6
-rw-r--r--images/Makefile.imx23
-rw-r--r--include/blspec.h10
-rw-r--r--include/common.h9
-rw-r--r--include/dt-bindings/clock/ar933x-clk.h22
-rw-r--r--include/fb.h44
-rw-r--r--include/i2c/i2c.h1
-rw-r--r--include/linux/clk.h31
-rw-r--r--include/linux/const.h27
-rw-r--r--include/linux/err.h8
-rw-r--r--include/linux/mtd/mtd-abi.h12
-rw-r--r--include/linux/mtd/mtd.h15
-rw-r--r--include/menu.h2
-rw-r--r--include/mfd/imx6q-iomuxc-gpr.h34
-rw-r--r--include/param.h13
-rw-r--r--include/video/fourcc.h261
-rw-r--r--lib/libmtd.c10
-rw-r--r--lib/parameter.c87
-rw-r--r--lib/string.c2
-rw-r--r--net/eth.c14
-rw-r--r--net/netconsole.c6
-rw-r--r--scripts/omap4_usbboot/omap4_usbboot.c17
252 files changed, 13346 insertions, 1125 deletions
diff --git a/Documentation/boards.dox b/Documentation/boards.dox
index 6bcc14f68c..8d4fabbdd3 100644
--- a/Documentation/boards.dox
+++ b/Documentation/boards.dox
@@ -43,6 +43,7 @@ ARM type:
@li @subpage tny-a9263
@li @subpage usb-a9g20-lpw
@li @subpage usb-a9263
+@li @subpage virt2real
Blackfin type:
@@ -58,7 +59,8 @@ MIPS type:
@li @subpage dlink_dir_320
@li @subpage loongson_ls1b
@li @subpage qemu_malta
-@li @subpage rzx50
+@li @subpage ritmix-rzx50
+@li @subpage tplink-mr3020
*/
diff --git a/Makefile b/Makefile
index 33c30b932f..83638a06d3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2014
-PATCHLEVEL = 03
+PATCHLEVEL = 04
SUBLEVEL = 0
EXTRAVERSION =
NAME = None
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 21f90121cd..3754646235 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -54,6 +54,12 @@ config ARCH_CLPS711X
select GPIOLIB
select MFD_SYSCON
+config ARCH_DAVINCI
+ bool "TI Davinci"
+ select CPU_ARM926T
+ select HAS_DEBUG_LL
+ select GPIOLIB
+
config ARCH_EP93XX
bool "Cirrus Logic EP93xx"
select CPU_ARM920T
@@ -188,6 +194,7 @@ source arch/arm/cpu/Kconfig
source arch/arm/mach-at91/Kconfig
source arch/arm/mach-bcm2835/Kconfig
source arch/arm/mach-clps711x/Kconfig
+source arch/arm/mach-davinci/Kconfig
source arch/arm/mach-ep93xx/Kconfig
source arch/arm/mach-highbank/Kconfig
source arch/arm/mach-imx/Kconfig
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 2bbba35a67..c1bd836d9f 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -54,6 +54,7 @@ AFLAGS += -include asm/unified.h -msoft-float $(AFLAGS_THUMB2)
machine-$(CONFIG_ARCH_AT91) := at91
machine-$(CONFIG_ARCH_BCM2835) := bcm2835
machine-$(CONFIG_ARCH_CLPS711X) := clps711x
+machine-$(CONFIG_ARCH_DAVINCI) := davinci
machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_HIGHBANK) := highbank
machine-$(CONFIG_ARCH_IMX) := imx
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index 0d8c9cf4cf..16742d9138 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -99,4 +99,6 @@ obj-$(CONFIG_MACH_USB_A9263) += usb-a926x/
obj-$(CONFIG_MACH_USB_A9G20) += usb-a926x/
obj-$(CONFIG_MACH_VERSATILEPB) += versatile/
obj-$(CONFIG_MACH_VEXPRESS) += vexpress/
+obj-$(CONFIG_MACH_VIRT2REAL) += virt2real/
obj-$(CONFIG_MACH_ZEDBOARD) += avnet-zedboard/
+obj-$(CONFIG_MACH_VARISCITE_MX6) += variscite-mx6/
diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c
index 2ae902fb60..24dc6e3216 100644
--- a/arch/arm/boards/chumby_falconwing/falconwing.c
+++ b/arch/arm/boards/chumby_falconwing/falconwing.c
@@ -75,7 +75,6 @@ static struct fb_videomode falconwing_vmode = {
.lower_margin = 8,
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
};
#define MAX_FB_SIZE SZ_1M
diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c
index 3c87311600..912e13c32c 100644
--- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c
+++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c
@@ -76,7 +76,6 @@ static struct fb_videomode imxfb_mode = {
.vsync_len = 3,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
};
static void eukrea_cpuimx35_enable_display(int enable)
diff --git a/arch/arm/boards/freescale-mx21-ads/imx21ads.c b/arch/arm/boards/freescale-mx21-ads/imx21ads.c
index 1bbd8cbf2a..bd7e46e161 100644
--- a/arch/arm/boards/freescale-mx21-ads/imx21ads.c
+++ b/arch/arm/boards/freescale-mx21-ads/imx21ads.c
@@ -62,7 +62,6 @@ static struct imx_fb_videomode imx_fb_modedata = {
.vsync_len = 1,
.sync = 0,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
},
.pcr = 0xfb108bc7,
.bpp = 16,
diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
index 3bbdb1d5c9..dce6d31030 100644
--- a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
+++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
@@ -201,7 +201,6 @@ static struct fb_videomode mx28_evk_vmodes[] = {
.lower_margin = 10,
.sync = FB_SYNC_DE_HIGH_ACT | FB_SYNC_CLK_INVERT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
}
};
diff --git a/arch/arm/boards/freescale-mx35-3ds/3stack.c b/arch/arm/boards/freescale-mx35-3ds/3stack.c
index 2be1554b68..8f821adb73 100644
--- a/arch/arm/boards/freescale-mx35-3ds/3stack.c
+++ b/arch/arm/boards/freescale-mx35-3ds/3stack.c
@@ -95,7 +95,6 @@ static struct fb_videomode CTP_CLAA070LC0ACW = {
.vsync_len = 1, /* note: DE only display */
.sync = FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
};
static struct imx_ipu_fb_platform_data ipu_fb_data = {
diff --git a/arch/arm/boards/freescale-mx53-qsb/board.c b/arch/arm/boards/freescale-mx53-qsb/board.c
index 74826e4a5e..38d1ee6f7c 100644
--- a/arch/arm/boards/freescale-mx53-qsb/board.c
+++ b/arch/arm/boards/freescale-mx53-qsb/board.c
@@ -99,6 +99,7 @@ static int loco_late_init(void)
rev = readl(MX53_IIM_BASE_ADDR + 0x878);
set_board_rev(rev);
printf("MCIMX53-START-R board 1.0 rev %c\n", (rev == 1) ? 'A' : 'B' );
+ barebox_set_hostname("loco-r");
armlinux_set_revision(loco_system_rev);
/* Set VDDGP to 1.25V for 1GHz on SW1 */
mc13xxx_reg_read(mc34708, MC13892_REG_SW_0, &val);
@@ -146,8 +147,8 @@ static int loco_late_init(void)
} else {
/* so we have a DA9053 based board */
printf("MCIMX53-START board 1.0\n");
+ barebox_set_hostname("loco");
armlinux_set_revision(loco_system_rev);
- return 0;
}
/* USB PWR enable */
diff --git a/arch/arm/boards/freescale-mx53-qsb/env/config-board b/arch/arm/boards/freescale-mx53-qsb/env/config-board
index a6cf69ddbc..e8e8378f53 100644
--- a/arch/arm/boards/freescale-mx53-qsb/env/config-board
+++ b/arch/arm/boards/freescale-mx53-qsb/env/config-board
@@ -3,5 +3,4 @@
# board defaults, do not change in running system. Change /env/config
# instead
-global.hostname=loco
global.linux.bootargs.base="console=ttymxc0,115200"
diff --git a/arch/arm/boards/freescale-mx6-sabrelite/board.c b/arch/arm/boards/freescale-mx6-sabrelite/board.c
index 85c61510fa..f42489f765 100644
--- a/arch/arm/boards/freescale-mx6-sabrelite/board.c
+++ b/arch/arm/boards/freescale-mx6-sabrelite/board.c
@@ -78,8 +78,48 @@ static int ksz9021rn_phy_fixup(struct phy_device *dev)
return 0;
}
+static struct gpio fec_gpios[] = {
+ {
+ .gpio = 87,
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "phy-rst",
+ }, {
+ .gpio = 190,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "phy-addr2",
+ }, {
+ .gpio = 23,
+ .flags = GPIOF_OUT_INIT_LOW,
+ .label = "phy-led-mode",
+ }, {
+ /* MODE strap-in pins: advertise all capabilities */
+ .gpio = 185,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "phy-adv1",
+ }, {
+ .gpio = 187,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "phy-adv1",
+ }, {
+ .gpio = 188,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "phy-adv1",
+ }, {
+ .gpio = 189,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "phy-adv1",
+ }, {
+ /* Enable 125 MHz clock output */
+ .gpio = 184,
+ .flags = GPIOF_OUT_INIT_HIGH,
+ .label = "phy-125MHz",
+ },
+};
+
static int sabrelite_ksz9021rn_setup(void)
{
+ int ret;
+
if (!of_machine_is_compatible("fsl,imx6q-sabrelite") &&
!of_machine_is_compatible("fsl,imx6dl-sabrelite"))
return 0;
@@ -87,24 +127,16 @@ static int sabrelite_ksz9021rn_setup(void)
mxc_iomux_v3_setup_multiple_pads(sabrelite_enet_gpio_pads,
ARRAY_SIZE(sabrelite_enet_gpio_pads));
- gpio_direction_output(87, 0); /* GPIO 3-23 */
-
- gpio_direction_output(190, 1); /* GPIO 6-30: PHYAD2 */
-
- /* LED-Mode: Tri-Color Dual LED Mode */
- gpio_direction_output(23 , 0); /* GPIO 1-23 */
-
- /* MODE strap-in pins: advertise all capabilities */
- gpio_direction_output(185, 1); /* GPIO 6-25 */
- gpio_direction_output(187, 1); /* GPIO 6-27 */
- gpio_direction_output(188, 1); /* GPIO 6-28*/
- gpio_direction_output(189, 1); /* GPIO 6-29 */
-
- /* Enable 125 MHz clock output */
- gpio_direction_output(184, 1); /* GPIO 6-24 */
+ ret = gpio_request_array(fec_gpios, ARRAY_SIZE(fec_gpios));
+ if (ret) {
+ pr_err("Failed to request fec gpios: %s\n", strerror(-ret));
+ return ret;
+ }
mdelay(10);
- gpio_set_value(87, 1);
+
+ /* FEC driver picks up the reset gpio later and releases the phy reset */
+ gpio_free_array(fec_gpios, ARRAY_SIZE(fec_gpios));
return 0;
}
diff --git a/arch/arm/boards/friendlyarm-mini2440/mini2440.c b/arch/arm/boards/friendlyarm-mini2440/mini2440.c
index 2c2426016d..86e22ad131 100644
--- a/arch/arm/boards/friendlyarm-mini2440/mini2440.c
+++ b/arch/arm/boards/friendlyarm-mini2440/mini2440.c
@@ -85,7 +85,6 @@ static struct fb_videomode s3c24x0_fb_modes[] = {
.pixclock = 115913,
.sync = FB_SYNC_USE_PWREN,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
},
#endif
#ifdef CONFIG_MINI2440_VIDEO_A70
diff --git a/arch/arm/boards/guf-cupid/board.c b/arch/arm/boards/guf-cupid/board.c
index e171331a44..127edaa170 100644
--- a/arch/arm/boards/guf-cupid/board.c
+++ b/arch/arm/boards/guf-cupid/board.c
@@ -68,7 +68,6 @@ static struct fb_videomode guf_cupid_fb_mode = {
.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_CLK_INVERT |
FB_SYNC_OE_ACT_HIGH,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
};
#define GPIO_LCD_ENABLE (2 * 32 + 24)
diff --git a/arch/arm/boards/karo-tx28/tx28-stk5.c b/arch/arm/boards/karo-tx28/tx28-stk5.c
index 57cb0c3907..2aaceb442e 100644
--- a/arch/arm/boards/karo-tx28/tx28-stk5.c
+++ b/arch/arm/boards/karo-tx28/tx28-stk5.c
@@ -72,7 +72,6 @@ static struct fb_videomode tx28evk_vmodes[] = {
.lower_margin = 10,
.sync = FB_SYNC_DE_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
}, {
/*
* Emerging ETV570 640 x 480 display (directly connected)
@@ -93,7 +92,6 @@ static struct fb_videomode tx28evk_vmodes[] = {
.lower_margin = 10,
.sync = FB_SYNC_DE_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
/*
* This display is connected:
* display side -> CPU side
@@ -127,7 +125,6 @@ static struct fb_videomode tx28evk_vmodes[] = {
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
FB_SYNC_DE_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
}, {
/*
* Modeline "1024x768" x 60.0
@@ -149,7 +146,6 @@ static struct fb_videomode tx28evk_vmodes[] = {
.lower_margin = 3,
.sync = FB_SYNC_DE_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
}, {
/*
* Modeline "1280x1024" x 60.0
@@ -172,7 +168,6 @@ static struct fb_videomode tx28evk_vmodes[] = {
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
FB_SYNC_DE_HIGH_ACT,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
},
};
diff --git a/arch/arm/boards/phytec-phycore-imx35/pcm043.c b/arch/arm/boards/phytec-phycore-imx35/pcm043.c
index 46821a784a..c1928cc8ff 100644
--- a/arch/arm/boards/phytec-phycore-imx35/pcm043.c
+++ b/arch/arm/boards/phytec-phycore-imx35/pcm043.c
@@ -73,7 +73,6 @@ static struct fb_videomode pcm043_fb_mode[] = {
.vsync_len = 1,
.sync = FB_SYNC_VERT_HIGH_ACT | FB_SYNC_OE_ACT_HIGH,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
}, {
/* 240x320 @ 60 Hz */
.name = "Sharp-LQ035Q7",
@@ -90,7 +89,6 @@ static struct fb_videomode pcm043_fb_mode[] = {
.sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_SHARP_MODE | \
FB_SYNC_CLK_INVERT | FB_SYNC_CLK_IDLE_EN,
.vmode = FB_VMODE_NONINTERLACED,
- .flag = 0,
}
};
diff --git a/arch/arm/boards/phytec-phyflex-imx6/Makefile b/arch/arm/boards/phytec-phyflex-imx6/Makefile
index 93e73081c2..01c7a259e9 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/Makefile
+++ b/arch/arm/boards/phytec-phyflex-imx6/Makefile
@@ -1,5 +1,2 @@
obj-y += board.o
-obj-y += flash-header-phytec-pfla02-1gib.dcd.o flash-header-phytec-pfla02-2gib.dcd.o
-extra-y += flash-header-phytec-pfla02-1gib.dcd.S flash-header-phytec-pfla02-2gib.dcd.S
-extra-y += flash-header-phytec-pfla02-1gib.dcd flash-header-phytec-pfla02-2gib.dcd
lwl-y += lowlevel.o
diff --git a/arch/arm/boards/phytec-phyflex-imx6/board.c b/arch/arm/boards/phytec-phyflex-imx6/board.c
index e9bd1680fd..c11f4c46ba 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/board.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/board.c
@@ -21,6 +21,10 @@
#include <gpio.h>
#include <init.h>
#include <of.h>
+#include <mach/bbu.h>
+#include <fec.h>
+
+#include <linux/micrel_phy.h>
#include <mach/imx6.h>
@@ -36,12 +40,33 @@ static int eth_phy_reset(void)
return 0;
}
+static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
+{
+ phy_write(dev, 0x0d, device);
+ phy_write(dev, 0x0e, reg);
+ phy_write(dev, 0x0d, (1 << 14) | device);
+ phy_write(dev, 0x0e, val);
+}
+
+static int ksz9031rn_phy_fixup(struct phy_device *dev)
+{
+ mmd_write_reg(dev, 2, 8, 0x039F);
+
+ return 0;
+}
+
static int phytec_pfla02_init(void)
{
- if (!of_machine_is_compatible("phytec,imx6q-pfla02"))
+ if (!of_machine_is_compatible("phytec,imx6q-pfla02") &&
+ !of_machine_is_compatible("phytec,imx6dl-pfla02") &&
+ !of_machine_is_compatible("phytec,imx6s-pfla02"))
return 0;
eth_phy_reset();
+ phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
+ ksz9031rn_phy_fixup);
+
+ imx6_bbu_nand_register_handler("nand", BBU_HANDLER_FLAG_DEFAULT);
return 0;
}
@@ -49,7 +74,7 @@ device_initcall(phytec_pfla02_init);
static int phytec_pfla02_core_init(void)
{
- if (!of_machine_is_compatible("phytec,imx6q-pfla02"))
+ if (!of_machine_is_compatible("phytec,imx6x-pbab01"))
return 0;
imx6_init_lowlevel();
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg
index 524ebca580..d73207c364 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-1gib.imxcfg
@@ -1,5 +1,5 @@
-#define SETUP_1GIB_2GIB \
+#define SETUP_1GIB_2GIB_4GIB \
wm 32 0x021b0040 0x00000017; \
wm 32 0x021b0000 0xc21a0000
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
index bf6e0ab26b..2291b71e8c 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
@@ -1,5 +1,5 @@
-#define SETUP_1GIB_2GIB \
+#define SETUP_1GIB_2GIB_4GIB \
wm 32 0x021b0040 0x00000027; \
wm 32 0x021b0000 0xC31A0000
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
new file mode 100644
index 0000000000..c6dc775d8f
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
@@ -0,0 +1,6 @@
+
+#define SETUP_1GIB_2GIB_4GIB \
+ wm 32 0x021b0040 0x00000047; \
+ wm 32 0x021b0000 0xC41A0000
+
+#include "flash-header-phytec-pfla02.h"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h
index b90f7cb3cf..138ae36ee3 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02.h
@@ -60,7 +60,7 @@ wm 32 0x021b0030 0x005b0e21
wm 32 0x021b0008 0x09444040
wm 32 0x021b0004 0x00025576
-SETUP_1GIB_2GIB
+SETUP_1GIB_2GIB_4GIB
wm 32 0x021b001c 0x04088032
wm 32 0x021b001c 0x0408803a
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
new file mode 100644
index 0000000000..e5a729223f
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
@@ -0,0 +1,6 @@
+
+#define SETUP_S_DL_512MB_1GB \
+ wm 32 0x021b0040 0x00000017; \
+ wm 32 0x021b0000 0xc21a0000
+
+#include "flash-header-phytec-pfla02dl.h"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h
new file mode 100644
index 0000000000..0f83bc9964
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02dl.h
@@ -0,0 +1,95 @@
+soc imx6
+loadaddr 0x20000000
+dcdofs 0x400
+
+wm 32 0x020e04bc 0x00000030
+wm 32 0x020e04c0 0x00000030
+wm 32 0x020e04c4 0x00000030
+wm 32 0x020e04c8 0x00000030
+wm 32 0x020e04cc 0x00000030
+wm 32 0x020e04d0 0x00000030
+wm 32 0x020e04d4 0x00000030
+wm 32 0x020e04d8 0x00000030
+wm 32 0x020e0470 0x00020030
+wm 32 0x020e0474 0x00020030
+wm 32 0x020e0478 0x00020030
+wm 32 0x020e047c 0x00020030
+wm 32 0x020e0480 0x00020030
+wm 32 0x020e0484 0x00020030
+wm 32 0x020e0488 0x00020030
+wm 32 0x020e048c 0x00020030
+wm 32 0x020e0464 0x00020030
+wm 32 0x020e0490 0x00020030
+wm 32 0x020e04ac 0x00020030
+wm 32 0x020e04b0 0x00020030
+wm 32 0x020e0494 0x00020030
+wm 32 0x020e04a4 0x00003000
+wm 32 0x020e04a8 0x00003000
+wm 32 0x020e04a0 0x00000000
+wm 32 0x020e04b4 0x00003030
+wm 32 0x020e04b8 0x00003030
+wm 32 0x020e0764 0x00000030
+wm 32 0x020e0770 0x00000030
+wm 32 0x020e0778 0x00000030
+wm 32 0x020e077c 0x00000030
+wm 32 0x020e0780 0x00000030
+wm 32 0x020e0784 0x00000030
+wm 32 0x020e078c 0x00000030
+wm 32 0x020e0748 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e0754 0x00000000
+wm 32 0x020e0760 0x00020000
+wm 32 0x020e076c 0x00000030
+wm 32 0x020e0774 0x000c0000
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+wm 32 0x021b0824 0x33333333
+wm 32 0x021b0828 0x33333333
+wm 32 0x021b481c 0x33333333
+wm 32 0x021b4820 0x33333333
+wm 32 0x021b4824 0x33333333
+wm 32 0x021b4828 0x33333333
+wm 32 0x021b0018 0x00081740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b000c 0x555a7975
+wm 32 0x021b0010 0xff538e64
+wm 32 0x021b0014 0x01ff00db
+wm 32 0x021b002c 0x000026d2
+wm 32 0x021b0030 0x005b0e21
+wm 32 0x021b0008 0x09444040
+wm 32 0x021b0004 0x00025576
+
+SETUP_S_DL_512MB_1GB
+
+wm 32 0x021b001c 0x04088032
+wm 32 0x021b001c 0x0408803a
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x0000803b
+wm 32 0x021b001c 0x00428031
+wm 32 0x021b001c 0x00428039
+wm 32 0x021b001c 0x09408030
+wm 32 0x021b001c 0x09408038
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b001c 0x04008048
+wm 32 0x021b0800 0xa1380003
+wm 32 0x021b4800 0xa1380003
+wm 32 0x021b0020 0x00005800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b4818 0x00011117
+wm 32 0x021b083c 0x422D0230
+wm 32 0x021b0840 0x022F022E
+wm 32 0x021b483c 0x4237023D
+wm 32 0x021b4840 0x02340224
+wm 32 0x021b0848 0x38333135
+wm 32 0x021b4848 0x36353338
+wm 32 0x021b0850 0x2E2E332C
+wm 32 0x021b4850 0x3727382F
+wm 32 0x021b080c 0x000C000D
+wm 32 0x021b0810 0x0018001A
+wm 32 0x021b480c 0x00270023
+wm 32 0x021b4810 0x002F002D
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b48b8 0x00000800
+wm 32 0x021b001c 0x00000000
+wm 32 0x021b0404 0x00011006
diff --git a/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
new file mode 100644
index 0000000000..3116e3613d
--- /dev/null
+++ b/arch/arm/boards/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
@@ -0,0 +1,6 @@
+
+#define SETUP_S_DL_512MB_1GB \
+ wm 32 0x021b0040 0x00000017; \
+ wm 32 0x021b0000 0x83190000
+
+#include "flash-header-phytec-pfla02dl.h"
diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
index 6422bc4dcb..fb7b186d21 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
@@ -54,6 +54,8 @@ static inline void setup_uart(void)
}
extern char __dtb_imx6q_phytec_pbab01_start[];
+extern char __dtb_imx6dl_phytec_pbab01_start[];
+extern char __dtb_imx6s_phytec_pbab01_start[];
ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
{
@@ -86,3 +88,48 @@ ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2)
barebox_arm_entry(0x10000000, SZ_2G, fdt);
}
+
+ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2)
+{
+ uint32_t fdt;
+
+ __barebox_arm_head();
+
+ arm_cpu_lowlevel_init();
+
+ arm_setup_stack(0x00920000 - 8);
+
+ fdt = (uint32_t)__dtb_imx6q_phytec_pbab01_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, 0xEFFFFFF8, fdt);
+}
+
+ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2)
+{
+ uint32_t fdt;
+
+ __barebox_arm_head();
+
+ arm_cpu_lowlevel_init();
+
+ arm_setup_stack(0x00920000 - 8);
+
+ fdt = (uint32_t)__dtb_imx6dl_phytec_pbab01_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, SZ_1G, fdt);
+}
+
+ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2)
+{
+ uint32_t fdt;
+
+ __barebox_arm_head();
+
+ arm_cpu_lowlevel_init();
+
+ arm_setup_stack(0x00920000 - 8);
+
+ fdt = (uint32_t)__dtb_imx6s_phytec_pbab01_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, SZ_512M, fdt);
+}
diff --git a/arch/arm/boards/variscite-mx6/Makefile b/arch/arm/boards/variscite-mx6/Makefile
new file mode 100644
index 0000000000..35b114b8dd
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/Makefile
@@ -0,0 +1,3 @@
+obj-y += board.o flash-header-variscite.dcd.o
+extra-y += flash-header-variscite.dcd.S flash-header-variscite.dcd
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/variscite-mx6/board.c b/arch/arm/boards/variscite-mx6/board.c
new file mode 100644
index 0000000000..592b1116e7
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/board.c
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2013 Michael Burkey
+ * Based on code (C) Sascha Hauer, Pengutronix
+ * Based on code (C) Variscite, Ltd.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) "var-som-mx6: " fmt
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <of.h>
+#include <debug_ll.h>
+
+#include <environment.h>
+#include <asm/armlinux.h>
+#include <generated/mach-types.h>
+#include <partition.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <mach/generic.h>
+#include <sizes.h>
+#include <mach/imx6.h>
+#include <mach/devices-imx6.h>
+#include <mach/iomux-mx6.h>
+#include <spi/spi.h>
+#include <mach/spi.h>
+#include <i2c/i2c.h>
+
+#define ETH_PHY_RST IMX_GPIO_NR(1, 25)
+
+static int setup_pmic_voltages(void)
+{
+ unsigned char value, rev_id = 0 ;
+ struct i2c_adapter *adapter = NULL;
+ struct i2c_client client;
+ int addr = -1, ret, bus = 0;
+
+ /* I2C2 bus (2-1 = 1 in barebox numbering) */
+ bus = 1;
+
+ /* PFUZE100 device address is 0x08 */
+ addr = 0x08;
+
+ adapter = i2c_get_adapter(bus);
+ if (!adapter) {
+ pr_err("i2c bus %d not found\n", bus);
+ return -ENODEV;
+ }
+
+ client.adapter = adapter;
+ client.addr = addr;
+
+ /* Attempt to locate the PFUZE100 chip. */
+ if (i2c_read_reg(&client, 0x00, &value, 1) != 1) {
+ pr_err("Read device ID error!\n");
+ return -1;
+ }
+ if (i2c_read_reg(&client, 0x03, &rev_id, 1) != 1) {
+ pr_err("Read Rev ID error!\n");
+ return -1;
+ }
+
+ pr_info("Found PFUZE100! deviceid=%x,revid=%x\n", value, rev_id);
+
+ /* Set Gigabit Ethernet voltage (SOM v1.1/1.0)*/
+ value = 0x60;
+ ret = i2c_write_reg(&client, 0x4a, &value, 1);
+
+ /* set VGEN3 to 2.5V */
+ value = 0x77;
+ if (i2c_write_reg(&client, 0x6e, &value, 1) != 1) {
+ pr_err("Set VGEN3 error!\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+static int eth_phy_reset(void)
+{
+ gpio_request(ETH_PHY_RST, "phy reset");
+ gpio_direction_output(ETH_PHY_RST, 0);
+ mdelay(1);
+ gpio_set_value(ETH_PHY_RST, 1);
+
+ return 0;
+}
+
+static int variscite_custom_init(void)
+{
+ if (!of_machine_is_compatible("variscite,imx6q-custom"))
+ return 0;
+
+ barebox_set_hostname("var-som-mx6");
+
+ setup_pmic_voltages();
+
+ eth_phy_reset();
+
+ armlinux_set_architecture(MACH_TYPE_VAR_SOM_MX6);
+
+ pr_debug("Completing custom_init()\n");
+
+ return 0;
+}
+device_initcall(variscite_custom_init);
+
+static int variscite_custom_core_init(void)
+{
+ if (!of_machine_is_compatible("variscite,imx6q-custom"))
+ return 0;
+
+ imx6_init_lowlevel();
+
+ pr_debug("Completing custom_core_init()\n");
+
+ return 0;
+}
+postcore_initcall(variscite_custom_core_init);
diff --git a/arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg b/arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg
new file mode 100644
index 0000000000..ed2105792e
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/flash-header-variscite.imxcfg
@@ -0,0 +1,86 @@
+loadaddr 0x10000000
+soc imx6
+dcdofs 0x400
+wm 32 0x020e0798 0x000C0000
+wm 32 0x020e0758 0x00000000
+wm 32 0x020e0588 0x00000030
+wm 32 0x020e0594 0x00000030
+wm 32 0x020e056c 0x00000030
+wm 32 0x020e0578 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e057c 0x00000030
+wm 32 0x020e058c 0x00000000
+wm 32 0x020e059c 0x00000030
+wm 32 0x020e05a0 0x00000030
+wm 32 0x020e078c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e05a8 0x00000030
+wm 32 0x020e05b0 0x00000030
+wm 32 0x020e0524 0x00000030
+wm 32 0x020e051c 0x00000030
+wm 32 0x020e0518 0x00000030
+wm 32 0x020e050c 0x00000030
+wm 32 0x020e05b8 0x00000030
+wm 32 0x020e05c0 0x00000030
+wm 32 0x020e0774 0x00020000
+wm 32 0x020e0784 0x00000030
+wm 32 0x020e0788 0x00000030
+wm 32 0x020e0794 0x00000030
+wm 32 0x020e079c 0x00000030
+wm 32 0x020e07a0 0x00000030
+wm 32 0x020e07a4 0x00000030
+wm 32 0x020e07a8 0x00000030
+wm 32 0x020e0748 0x00000030
+wm 32 0x020e05ac 0x00000030
+wm 32 0x020e05b4 0x00000030
+wm 32 0x020e0528 0x00000030
+wm 32 0x020e0520 0x00000030
+wm 32 0x020e0514 0x00000030
+wm 32 0x020e0510 0x00000030
+wm 32 0x020e05bc 0x00000030
+wm 32 0x020e05c4 0x00000030
+wm 32 0x021b0800 0xA1390003
+wm 32 0x021b080c 0x001F001F
+wm 32 0x021b0810 0x001F001F
+wm 32 0x021b480c 0x001F001F
+wm 32 0x021b4810 0x001F001F
+wm 32 0x021b083c 0x4333033F
+wm 32 0x021b0840 0x032C031D
+wm 32 0x021b483c 0x43200332
+wm 32 0x021b4840 0x031A026A
+wm 32 0x021b0848 0x4D464746
+wm 32 0x021b4848 0x47453F4D
+wm 32 0x021b0850 0x3E434440
+wm 32 0x021b4850 0x47384839
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+wm 32 0x021b0824 0x33333333
+wm 32 0x021b0828 0x33333333
+wm 32 0x021b481c 0x33333333
+wm 32 0x021b4820 0x33333333
+wm 32 0x021b4824 0x33333333
+wm 32 0x021b4828 0x33333333
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b48b8 0x00000800
+wm 32 0x021b0004 0x00020036
+wm 32 0x021b0008 0x09444040
+wm 32 0x021b000c 0x555A7975
+wm 32 0x021b0010 0xFF538F64
+wm 32 0x021b0014 0x01FF00DB
+wm 32 0x021b0018 0x00001740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b002c 0x000026D2
+wm 32 0x021b0030 0x005A1023
+wm 32 0x021b0040 0x00000027
+wm 32 0x021b0000 0x831A0000
+wm 32 0x021b001c 0x04088032
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x09408030
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b0020 0x00005800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b4818 0x00011117
+wm 32 0x021b0004 0x00025576
+wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
diff --git a/arch/arm/boards/variscite-mx6/lowlevel.c b/arch/arm/boards/variscite-mx6/lowlevel.c
new file mode 100644
index 0000000000..e93e87484c
--- /dev/null
+++ b/arch/arm/boards/variscite-mx6/lowlevel.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright (C) 2013 Michael Burkey
+ * Based on code by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <debug_ll.h>
+#include <common.h>
+#include <sizes.h>
+#include <io.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+#include <asm/sections.h>
+#include <asm/cache.h>
+#include <asm/mmu.h>
+#include <mach/imx6-mmdc.h>
+#include <mach/imx6.h>
+
+static inline void setup_uart(void)
+{
+ void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
+ void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR;
+ void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
+
+ writel(0x03, iomuxbase + 0x0280);
+ writel(0x03, iomuxbase + 0x0284);
+
+ writel(0xffffffff, ccmbase + 0x68);
+ writel(0xffffffff, ccmbase + 0x6c);
+ writel(0xffffffff, ccmbase + 0x70);
+ writel(0xffffffff, ccmbase + 0x74);
+ writel(0xffffffff, ccmbase + 0x78);
+ writel(0xffffffff, ccmbase + 0x7c);
+ writel(0xffffffff, ccmbase + 0x80);
+
+ writel(0x00000000, uartbase + 0x80);
+ writel(0x00004027, uartbase + 0x84);
+ writel(0x00000704, uartbase + 0x88);
+ writel(0x00000a81, uartbase + 0x90);
+ writel(0x0000002b, uartbase + 0x9c);
+ writel(0x00013880, uartbase + 0xb0);
+ writel(0x0000047f, uartbase + 0xa4);
+ writel(0x0000c34f, uartbase + 0xa8);
+ writel(0x00000001, uartbase + 0x80);
+
+ putc_ll('>');
+}
+extern char __dtb_imx6q_var_custom_start[];
+
+ENTRY_FUNCTION(start_variscite_custom, r0, r1, r2)
+{
+ uint32_t fdt;
+
+ arm_cpu_lowlevel_init();
+
+ arm_setup_stack(0x00920000 - 8);
+
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
+
+ fdt = (uint32_t)__dtb_imx6q_var_custom_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, SZ_1G, fdt);
+}
diff --git a/arch/arm/boards/virt2real/Makefile b/arch/arm/boards/virt2real/Makefile
new file mode 100644
index 0000000000..b2f44bba1b
--- /dev/null
+++ b/arch/arm/boards/virt2real/Makefile
@@ -0,0 +1 @@
+obj-y += lowlevel.o board.o
diff --git a/arch/arm/boards/virt2real/board.c b/arch/arm/boards/virt2real/board.c
new file mode 100644
index 0000000000..b7f72171bb
--- /dev/null
+++ b/arch/arm/boards/virt2real/board.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+
+static int hostname_init(void)
+{
+ barebox_set_hostname("virt2real");
+
+ return 0;
+}
+core_initcall(hostname_init);
diff --git a/arch/arm/boards/virt2real/lowlevel.c b/arch/arm/boards/virt2real/lowlevel.c
new file mode 100644
index 0000000000..3c90d78678
--- /dev/null
+++ b/arch/arm/boards/virt2real/lowlevel.c
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define __LOWLEVEL_INIT__
+
+#include <common.h>
+#include <asm/barebox-arm.h>
+#include <asm/barebox-arm-head.h>
+#include <init.h>
+#include <sizes.h>
+
+#define VIRT2REAL_SRAM_BASE 0x82000000
+#define VIRT2REAL_SRAM_SIZE SZ_16M
+
+void __naked __bare_init barebox_arm_reset_vector(void)
+{
+ arm_cpu_lowlevel_init();
+
+ barebox_arm_entry(VIRT2REAL_SRAM_BASE, VIRT2REAL_SRAM_SIZE, 0);
+}
diff --git a/arch/arm/boards/virt2real/virt2real.dox b/arch/arm/boards/virt2real/virt2real.dox
new file mode 100644
index 0000000000..fc383216ec
--- /dev/null
+++ b/arch/arm/boards/virt2real/virt2real.dox
@@ -0,0 +1,41 @@
+/** @page virt2real virt2real board
+
+virt2real is a is a miniature board for creation of WiFi
+or internet controllable smart devices.
+
+The board has
+@li TI DaVinchi DM365 running at 300 MHz
+@li 128 MiB DDR2 SDRAM;
+@li 256 MiB NAND Flash Memory;
+@li 2 x UART serial interfaces;
+@li 2 x Ethernet interfaces;
+@li 1 x USB interface;
+@li microSD card slot.
+
+The board uses U-Boot as bootloader.
+
+Barebox mini-howto:
+
+1. Connect to the boards's UART0 (115200 8N1);
+Use J2.2 (GND), J2.4 (UART0_TXD), J2.6(UART0_RXD) pins.
+
+2. Turn board's power on;
+
+3. Wait 'Hit any key to stop autoboot' prompt and press the space key.
+
+4. Upload barebox.bin via Ymodem
+@verbatim
+ virt2real ># loady
+@endverbatim
+
+5. Run barebox
+@verbatim
+ virt2real ># go 0x82000000
+@endverbatim
+
+virt2real links:
+@li http://virt2real.com/
+@li http://wiki.virt2real.ru/
+@li https://github.com/virt2real
+
+*/
diff --git a/arch/arm/configs/freescale-mx53-qsb_defconfig b/arch/arm/configs/freescale-mx53-qsb_defconfig
index afe8b72c0d..8365234ea1 100644
--- a/arch/arm/configs/freescale-mx53-qsb_defconfig
+++ b/arch/arm/configs/freescale-mx53-qsb_defconfig
@@ -16,6 +16,7 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+CONFIG_BLSPEC=y
CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/freescale-mx53-qsb/env/"
@@ -25,31 +26,44 @@ CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
CONFIG_CMD_MSLEEP=y
CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_LET=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_PASSWD=y
+CONFIG_PASSWD_MODE_STAR=y
CONFIG_CMD_TIME=y
CONFIG_CMD_LN=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_FILETYPE=y
CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
CONFIG_CMD_MEMINFO=y
CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MM=y
CONFIG_CMD_CRC=y
CONFIG_CMD_CRC_CMP=y
CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA256SUM=y
+CONFIG_CMD_SHA224SUM=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_BOOTM_AIMAGE=y
CONFIG_CMD_UIMAGE=y
-# CONFIG_CMD_BOOTU is not set
+CONFIG_CMD_BOOTZ=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_OFTREE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_MEMTEST=y
CONFIG_CMD_BAREBOX_UPDATE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
@@ -64,23 +78,36 @@ CONFIG_CMD_DETECT=y
CONFIG_CMD_WD=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
+CONFIG_NET_NFS=y
CONFIG_NET_PING=y
CONFIG_NET_NETCONSOLE=y
+CONFIG_NET_RESOLV=y
CONFIG_OFDEVICE=y
CONFIG_SMSC_PHY=y
CONFIG_DRIVER_NET_FEC_IMX=y
+CONFIG_NET_USB=y
+CONFIG_NET_USB_ASIX=y
+CONFIG_NET_USB_SMSC95XX=y
# CONFIG_SPI is not set
CONFIG_I2C=y
CONFIG_I2C_IMX=y
-CONFIG_DISK_ATA=y
+CONFIG_DISK_AHCI=y
+CONFIG_DISK_AHCI_IMX=y
CONFIG_USB=y
+CONFIG_USB_IMX_CHIPIDEA=y
CONFIG_USB_EHCI=y
+CONFIG_USB_ULPI=y
CONFIG_USB_STORAGE=y
CONFIG_MCI=y
CONFIG_MCI_IMX_ESDHC=y
CONFIG_MFD_MC13XXX=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_IMX=y
+CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index e821061cf3..f29c968da6 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -12,9 +12,11 @@ CONFIG_MACH_REALQ7=y
CONFIG_MACH_GK802=y
CONFIG_MACH_TQMA6X=y
CONFIG_MACH_SABRELITE=y
+CONFIG_MACH_SABRESD=y
CONFIG_MACH_NITROGEN6X=y
CONFIG_MACH_SOLIDRUN_HUMMINGBOARD=y
CONFIG_MACH_UDOO=y
+CONFIG_MACH_VARISCITE_MX6=y
CONFIG_IMX_IIM=y
CONFIG_IMX_IIM_FUSE_BLOW=y
CONFIG_IMX_OCOTP=y
@@ -41,9 +43,11 @@ CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
CONFIG_CMD_MSLEEP=y
CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_READF=y
CONFIG_CMD_LET=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENU_MANAGEMENT=y
@@ -72,6 +76,7 @@ CONFIG_CMD_OFTREE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_SPLASH=y
CONFIG_CMD_BAREBOX_UPDATE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
@@ -94,8 +99,8 @@ CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_OFDEVICE=y
CONFIG_OF_BAREBOX_DRIVERS=y
-CONFIG_AT803X_PHY=y
CONFIG_DRIVER_NET_FEC_IMX=y
+CONFIG_AT803X_PHY=y
CONFIG_NET_USB=y
CONFIG_NET_USB_ASIX=y
CONFIG_NET_USB_SMSC95XX=y
@@ -107,6 +112,13 @@ CONFIG_MTD_RAW_DEVICE=y
CONFIG_MTD_DATAFLASH=y
CONFIG_MTD_M25P80=y
CONFIG_MTD_SST25L=y
+CONFIG_NAND=y
+CONFIG_NAND_ALLOW_ERASE_BAD=y
+CONFIG_NAND_IMX=y
+CONFIG_NAND_IMX_BBM=y
+CONFIG_NAND_MXS=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
CONFIG_DISK_AHCI=y
CONFIG_DISK_AHCI_IMX=y
CONFIG_DISK_INTF_PLATFORM_IDE=y
@@ -118,6 +130,12 @@ CONFIG_USB_ULPI=y
CONFIG_USB_STORAGE=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DFU=y
+CONFIG_VIDEO=y
+CONFIG_DRIVER_VIDEO_IMX_IPUV3=y
+CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS=y
+CONFIG_DRIVER_VIDEO_IMX_IPUV3_HDMI=y
+CONFIG_DRIVER_VIDEO_SIMPLEFB=y
+CONFIG_DRIVER_VIDEO_EDID=y
CONFIG_MCI=y
CONFIG_MCI_MMC_BOOT_PARTITIONS=y
CONFIG_MCI_IMX_ESDHC=y
@@ -133,6 +151,9 @@ CONFIG_EEPROM_AT24=y
CONFIG_KEYBOARD_GPIO=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_IMX=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX=y
+CONFIG_MXS_APBH_DMA=y
CONFIG_GPIO_STMPE=y
CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
@@ -140,4 +161,5 @@ CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
-CONFIG_LZO_DECOMPRESS=y
+CONFIG_FS_UBIFS=y
+CONFIG_FS_UBIFS_COMPRESSION_LZO=y
diff --git a/arch/arm/configs/panda_defconfig b/arch/arm/configs/panda_defconfig
index 7be86ac85f..c42140a447 100644
--- a/arch/arm/configs/panda_defconfig
+++ b/arch/arm/configs/panda_defconfig
@@ -1,5 +1,5 @@
CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP4=y
+CONFIG_MACH_PANDA=y
CONFIG_THUMB2_BAREBOX=y
CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
@@ -29,9 +29,7 @@ CONFIG_CMD_READLINE=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENU_MANAGEMENT=y
CONFIG_CMD_TIME=y
-CONFIG_CMD_DIRNAME=y
CONFIG_CMD_LN=y
-CONFIG_CMD_READLINK=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
diff --git a/arch/arm/configs/panda_xload_defconfig b/arch/arm/configs/panda_xload_defconfig
index 5cedcffdcc..29a2afda8d 100644
--- a/arch/arm/configs/panda_xload_defconfig
+++ b/arch/arm/configs/panda_xload_defconfig
@@ -1,7 +1,7 @@
CONFIG_ARCH_OMAP=y
-CONFIG_ARCH_OMAP4=y
# CONFIG_OMAP_GPMC is not set
CONFIG_OMAP_BUILD_IFT=y
+CONFIG_MACH_PANDA=y
CONFIG_THUMB2_BAREBOX=y
# CONFIG_CMD_ARM_CPUINFO is not set
CONFIG_MMU=y
diff --git a/arch/arm/configs/phytec-phycore-imx35_defconfig b/arch/arm/configs/phytec-phycore-imx35_defconfig
index 59c1b82135..6674015a6d 100644
--- a/arch/arm/configs/phytec-phycore-imx35_defconfig
+++ b/arch/arm/configs/phytec-phycore-imx35_defconfig
@@ -1,8 +1,6 @@
CONFIG_ARCH_IMX=y
CONFIG_CACHE_L2X0=y
-CONFIG_ARCH_IMX_EXTERNAL_BOOT=y
CONFIG_ARCH_IMX_EXTERNAL_BOOT_NAND=y
-CONFIG_ARCH_IMX35=y
CONFIG_MACH_PCM043=y
CONFIG_IMX_IIM=y
CONFIG_IMX_IIM_FUSE_BLOW=y
@@ -20,7 +18,6 @@ CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
CONFIG_PARTITION=y
-CONFIG_PARTITION_DISK=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/phytec-phycore-imx35/env"
CONFIG_RESET_SOURCE=y
@@ -28,16 +25,16 @@ CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
CONFIG_CMD_MSLEEP=y
CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_READF=y
CONFIG_CMD_LET=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENU_MANAGEMENT=y
CONFIG_CMD_TIME=y
-CONFIG_CMD_DIRNAME=y
CONFIG_CMD_LN=y
-CONFIG_CMD_READLINK=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_FILETYPE=y
CONFIG_CMD_ECHO_E=y
@@ -57,9 +54,9 @@ CONFIG_CMD_UIMAGE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_OFTREE=y
-CONFIG_CMD_OFTREE_PROBE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_BAREBOX_UPDATE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_MAGICVAR=y
@@ -68,6 +65,7 @@ CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_MIITOOL=y
CONFIG_CMD_CLK=y
+CONFIG_CMD_DETECT=y
CONFIG_CMD_WD=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
@@ -76,12 +74,11 @@ CONFIG_NET_PING=y
CONFIG_NET_NETCONSOLE=y
CONFIG_DRIVER_NET_FEC_IMX=y
# CONFIG_SPI is not set
+CONFIG_MTD=y
CONFIG_DRIVER_CFI=y
CONFIG_CFI_BUFFER_WRITE=y
-CONFIG_MTD=y
CONFIG_NAND=y
CONFIG_NAND_IMX=y
-CONFIG_UBI=y
CONFIG_WATCHDOG=y
CONFIG_WATCHDOG_IMX=y
CONFIG_FS_TFTP=y
diff --git a/arch/arm/configs/virt2real_defconfig b/arch/arm/configs/virt2real_defconfig
new file mode 100644
index 0000000000..a81d18b25b
--- /dev/null
+++ b/arch/arm/configs/virt2real_defconfig
@@ -0,0 +1,49 @@
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="virt2real"
+CONFIG_ARCH_DAVINCI=y
+CONFIG_AEABI=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_TEXT_BASE=0x82300000
+CONFIG_MALLOC_SIZE=0x200000
+CONFIG_MALLOC_TLSF=y
+CONFIG_PROMPT="virt2real: "
+CONFIG_LONGHELP=y
+CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+CONFIG_PASSWORD=y
+CONFIG_PARTITION=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MM=y
+# CONFIG_CMD_BOOTM is not set
+# CONFIG_CMD_BOOTU is not set
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_LED=y
+CONFIG_OFDEVICE=y
+CONFIG_OF_BAREBOX_DRIVERS=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+# CONFIG_SPI is not set
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_SHA1=y
+CONFIG_SHA256=y
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 6bac3b908f..b45c174582 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -3,8 +3,7 @@ dtb-$(CONFIG_ARCH_AM33XX) += \
am335x-boneblack.dtb \
am335x-phytec-phycore.dtb
dtb-$(CONFIG_ARCH_IMX25) += imx25-karo-tx25.dtb
-dtb-$(CONFIG_ARCH_IMX27) += imx27-phytec-phycard-s-rdk.dtb \
- imx27-phytec-phycard-s-som.dtb
+dtb-$(CONFIG_ARCH_IMX27) += imx27-phytec-phycard-s-rdk-bb.dtb
dtb-$(CONFIG_ARCH_IMX51) += imx51-babbage.dtb \
imx51-genesi-efika-sb.dtb
dtb-$(CONFIG_ARCH_IMX53) += imx53-mba53.dtb \
@@ -20,12 +19,15 @@ dtb-$(CONFIG_ARCH_IMX6) += imx6q-gk802.dtb \
imx6q-sabresd.dtb \
imx6dl-mba6x.dtb \
imx6q-mba6x.dtb \
+ imx6dl-phytec-pbab01.dtb \
imx6q-phytec-pbab01.dtb \
+ imx6s-phytec-pbab01.dtb \
imx6dl-hummingboard.dtb \
imx6q-guf-santaro.dtb \
imx6q-nitrogen6x.dtb \
imx6dl-nitrogen6x.dtb \
- imx6q-udoo.dtb
+ imx6q-udoo.dtb \
+ imx6q-var-custom.dtb
dtb-$(CONFIG_ARCH_MVEBU) += dove-cubox-bb.dtb
dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5_sockit.dtb \
socfpga_cyclone5_socrates.dtb
@@ -43,7 +45,7 @@ pbl-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o
pbl-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o
pbl-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
pbl-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o
-pbl-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6q-phytec-pbab01.dtb.o
+pbl-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o
pbl-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
pbl-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o
pbl-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o
@@ -60,6 +62,7 @@ pbl-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o
pbl-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
pbl-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
pbl-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
+pbl-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S
.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y))
diff --git a/arch/arm/dts/dm365.dtsi b/arch/arm/dts/dm365.dtsi
new file mode 100644
index 0000000000..ea69007fa8
--- /dev/null
+++ b/arch/arm/dts/dm365.dtsi
@@ -0,0 +1,28 @@
+#include "skeleton.dtsi"
+
+/ {
+ soc {
+ compatible = "simple-bus";
+ model = "TI TMS320DM365";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0x0 0x01c00000 0x400000>;
+
+ serial0: serial@1c20000 {
+ compatible = "ns16550a";
+ reg = <0x20000 0x400>;
+ reg-shift = <2>;
+ clock-frequency = <24000000>;
+ status = "disabled";
+ };
+
+ gpio: gpio@1c67000 {
+ compatible = "ti,dm6441-gpio";
+ gpio-controller;
+ reg = <0x67000 0x800>;
+ #gpio-cells = <2>;
+ ti,ngpio = <107>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/arm/dts/imx27-phytec-phycard-s-rdk-bb.dts b/arch/arm/dts/imx27-phytec-phycard-s-rdk-bb.dts
new file mode 100644
index 0000000000..cecfc5a827
--- /dev/null
+++ b/arch/arm/dts/imx27-phytec-phycard-s-rdk-bb.dts
@@ -0,0 +1,38 @@
+/*
+ * Barebox specific DT overlay for Phytec PCA100 RDK
+ */
+
+#include "imx27-phytec-phycard-s-rdk.dts"
+
+/ {
+ chosen {
+ linux,stdout-path = &uart1;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &nfc, "partname:environment";
+ };
+ };
+};
+
+&nfc {
+ partition@0 {
+ label = "boot";
+ reg = <0x0 0x80000>;
+ };
+
+ partition@1 {
+ label = "environment";
+ reg = <0x80000 0x80000>;
+ };
+
+ partition@2 {
+ label = "kernel";
+ reg = <0x100000 0x400000>;
+ };
+
+ partition@3 {
+ label = "root";
+ reg = <0x500000 0x7b00000>;
+ };
+};
diff --git a/arch/arm/dts/imx27-phytec-phycard-s-rdk.dts b/arch/arm/dts/imx27-phytec-phycard-s-rdk.dts
index fb2b874805..3c3964a996 100644
--- a/arch/arm/dts/imx27-phytec-phycard-s-rdk.dts
+++ b/arch/arm/dts/imx27-phytec-phycard-s-rdk.dts
@@ -9,7 +9,7 @@
* http://www.gnu.org/copyleft/gpl.html
*/
-#include "imx27-phytec-phycard-s-som.dts"
+#include "imx27-phytec-phycard-s-som.dtsi"
/ {
model = "Phytec pca100 rapid development kit";
@@ -76,35 +76,54 @@
&iomuxc {
imx27-phycard-s-rdk {
pinctrl_i2c1: i2c1grp {
- fsl,pins = <MX27_I2C2_PINGRP1>;
+ fsl,pins = <
+ MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
+ MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+ >;
};
pinctrl_owire1: owire1grp {
- fsl,pins = <MX27_OWIRE1_PINGRP1>;
+ fsl,pins = <
+ MX27_PAD_RTCK__OWIRE 0x0
+ >;
};
pinctrl_sdhc2: sdhc2grp {
- fsl,pins = <MX27_SDHC2_PINGRP1>;
+ fsl,pins = <
+ MX27_PAD_SD2_CLK__SD2_CLK 0x0
+ MX27_PAD_SD2_CMD__SD2_CMD 0x0
+ MX27_PAD_SD2_D0__SD2_D0 0x0
+ MX27_PAD_SD2_D1__SD2_D1 0x0
+ MX27_PAD_SD2_D2__SD2_D2 0x0
+ MX27_PAD_SD2_D3__SD2_D3 0x0
+ MX27_PAD_SSI3_RXDAT__GPIO3_29 0x0 /* CD */
+ >;
};
pinctrl_uart1: uart1grp {
fsl,pins = <
- MX27_UART1_PINGRP1
- MX27_UART1_RTSCTS_PINGRP1
+ MX27_PAD_UART1_TXD__UART1_TXD 0x0
+ MX27_PAD_UART1_RXD__UART1_RXD 0x0
+ MX27_PAD_UART1_CTS__UART1_CTS 0x0
+ MX27_PAD_UART1_RTS__UART1_RTS 0x0
>;
};
pinctrl_uart2: uart2grp {
fsl,pins = <
- MX27_UART2_PINGRP1
- MX27_UART2_RTSCTS_PINGRP1
+ MX27_PAD_UART2_TXD__UART2_TXD 0x0
+ MX27_PAD_UART2_RXD__UART2_RXD 0x0
+ MX27_PAD_UART2_CTS__UART2_CTS 0x0
+ MX27_PAD_UART2_RTS__UART2_RTS 0x0
>;
};
pinctrl_uart3: uart3grp {
fsl,pins = <
- MX27_UART3_PINGRP1
- MX27_UART3_RTSCTS_PINGRP1
+ MX27_PAD_UART3_TXD__UART3_TXD 0x0
+ MX27_PAD_UART3_RXD__UART3_RXD 0x0
+ MX27_PAD_UART3_CTS__UART3_CTS 0x0
+ MX27_PAD_UART3_RTS__UART3_RTS 0x0
>;
};
};
diff --git a/arch/arm/dts/imx27-phytec-phycard-s-som.dts b/arch/arm/dts/imx27-phytec-phycard-s-som.dtsi
index a48d4e178d..1b62480796 100644
--- a/arch/arm/dts/imx27-phytec-phycard-s-som.dts
+++ b/arch/arm/dts/imx27-phytec-phycard-s-som.dtsi
@@ -17,15 +17,6 @@
model = "Phytec pca100";
compatible = "phytec,imx27-pca100", "fsl,imx27";
- chosen {
- linux,stdout-path = &uart1;
-
- environment@0 {
- compatible = "barebox,environment";
- device-path = &nfc, "partname:environment";
- };
- };
-
memory {
reg = <0xa0000000 0x08000000>; /* 128MB */
};
@@ -38,22 +29,6 @@
status = "okay";
};
-&iomuxc {
- imx27-phycard-s-som {
- pinctrl_fec1: fec1grp {
- fsl,pins = <MX27_FEC1_PINGRP1>;
- };
-
- pinctrl_i2c2: i2c2grp {
- fsl,pins = <MX27_I2C2_PINGRP1>;
- };
-
- pinctrl_nfc: nfcgrp {
- fsl,pins = <MX27_NFC_PINGRP1>;
- };
- };
-};
-
&fec {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_fec1>;
@@ -72,6 +47,52 @@
};
};
+&iomuxc {
+ imx27-phycard-s-som {
+ pinctrl_fec1: fec1grp {
+ fsl,pins = <
+ MX27_PAD_SD3_CMD__FEC_TXD0 0x0
+ MX27_PAD_SD3_CLK__FEC_TXD1 0x0
+ MX27_PAD_ATA_DATA0__FEC_TXD2 0x0
+ MX27_PAD_ATA_DATA1__FEC_TXD3 0x0
+ MX27_PAD_ATA_DATA2__FEC_RX_ER 0x0
+ MX27_PAD_ATA_DATA3__FEC_RXD1 0x0
+ MX27_PAD_ATA_DATA4__FEC_RXD2 0x0
+ MX27_PAD_ATA_DATA5__FEC_RXD3 0x0
+ MX27_PAD_ATA_DATA6__FEC_MDIO 0x0
+ MX27_PAD_ATA_DATA7__FEC_MDC 0x0
+ MX27_PAD_ATA_DATA8__FEC_CRS 0x0
+ MX27_PAD_ATA_DATA9__FEC_TX_CLK 0x0
+ MX27_PAD_ATA_DATA10__FEC_RXD0 0x0
+ MX27_PAD_ATA_DATA11__FEC_RX_DV 0x0
+ MX27_PAD_ATA_DATA12__FEC_RX_CLK 0x0
+ MX27_PAD_ATA_DATA13__FEC_COL 0x0
+ MX27_PAD_ATA_DATA14__FEC_TX_ER 0x0
+ MX27_PAD_ATA_DATA15__FEC_TX_EN 0x0
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX27_PAD_I2C2_SDA__I2C2_SDA 0x0
+ MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
+ >;
+ };
+
+ pinctrl_nfc: nfcgrp {
+ fsl,pins = <
+ MX27_PAD_NFRB__NFRB 0x0
+ MX27_PAD_NFCLE__NFCLE 0x0
+ MX27_PAD_NFWP_B__NFWP_B 0x0
+ MX27_PAD_NFCE_B__NFCE_B 0x0
+ MX27_PAD_NFALE__NFALE 0x0
+ MX27_PAD_NFRE_B__NFRE_B 0x0
+ MX27_PAD_NFWE_B__NFWE_B 0x0
+ >;
+ };
+ };
+};
+
&nfc {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_nfc>;
@@ -79,24 +100,4 @@
nand-ecc-mode = "hw";
nand-on-flash-bbt;
status = "okay";
-
- partition@0 {
- label = "boot";
- reg = <0x0 0x80000>;
- };
-
- partition@1 {
- label = "environment";
- reg = <0x80000 0x80000>;
- };
-
- partition@2 {
- label = "kernel";
- reg = <0x100000 0x400000>;
- };
-
- partition@3 {
- label = "root";
- reg = <0x500000 0x7b00000>;
- };
};
diff --git a/arch/arm/dts/imx27-pingrp.h b/arch/arm/dts/imx27-pingrp.h
deleted file mode 100644
index 57ca02f89d..0000000000
--- a/arch/arm/dts/imx27-pingrp.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Copyright 2013 Markus Pargmann <mpa@pengutronix.de>, Pengutronix
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-#ifndef __DTS_IMX27_PINGRP_H
-#define __DTS_IMX27_PINGRP_H
-
-#include "imx27-pinfunc.h"
-
-#define MX27_CSPI1_PINGRP1 \
- MX27_PAD_CSPI1_MISO__CSPI1_MISO 0x0 \
- MX27_PAD_CSPI1_MOSI__CSPI1_MOSI 0x0 \
- MX27_PAD_CSPI1_SCLK__CSPI1_SCLK 0x0
-
-#define MX27_CSPI2_PINGRP1 \
- MX27_PAD_CSPI2_MISO__CSPI2_MISO 0x0 \
- MX27_PAD_CSPI2_MOSI__CSPI2_MOSI 0x0 \
- MX27_PAD_CSPI2_SCLK__CSPI2_SCLK 0x0
-
-#define MX27_CSPI3_PINGRP1 \
- MX27_PAD_SD1_CLK__CSPI3_SCLK 0x0 \
- MX27_PAD_SD1_D0__CSPI3_MISO 0x0 \
- MX27_PAD_SD1_CMD__CSPI3_MOSI 0x0
-
-#define MX27_FB_PINGRP1 \
- MX27_PAD_CLS__CLS 0x0 \
- MX27_PAD_CONTRAST__CONTRAST 0x0 \
- MX27_PAD_LD0__LD0 0x0 \
- MX27_PAD_LD1__LD1 0x0 \
- MX27_PAD_LD2__LD2 0x0 \
- MX27_PAD_LD3__LD3 0x0 \
- MX27_PAD_LD4__LD4 0x0 \
- MX27_PAD_LD5__LD5 0x0 \
- MX27_PAD_LD6__LD6 0x0 \
- MX27_PAD_LD7__LD7 0x0 \
- MX27_PAD_LD8__LD8 0x0 \
- MX27_PAD_LD9__LD9 0x0 \
- MX27_PAD_LD10__LD10 0x0 \
- MX27_PAD_LD11__LD11 0x0 \
- MX27_PAD_LD12__LD12 0x0 \
- MX27_PAD_LD13__LD13 0x0 \
- MX27_PAD_LD14__LD14 0x0 \
- MX27_PAD_LD15__LD15 0x0 \
- MX27_PAD_LD16__LD16 0x0 \
- MX27_PAD_LD17__LD17 0x0 \
- MX27_PAD_LSCLK__LSCLK 0x0 \
- MX27_PAD_OE_ACD__OE_ACD 0x0 \
- MX27_PAD_PS__PS 0x0 \
- MX27_PAD_REV__REV 0x0 \
- MX27_PAD_SPL_SPR__SPL_SPR 0x0 \
- MX27_PAD_HSYNC__HSYNC 0x0 \
- MX27_PAD_VSYNC__VSYNC 0x0
-
-#define MX27_FEC1_PINGRP1 \
- MX27_PAD_SD3_CMD__FEC_TXD0 0x0 \
- MX27_PAD_SD3_CLK__FEC_TXD1 0x0 \
- MX27_PAD_ATA_DATA0__FEC_TXD2 0x0 \
- MX27_PAD_ATA_DATA1__FEC_TXD3 0x0 \
- MX27_PAD_ATA_DATA2__FEC_RX_ER 0x0 \
- MX27_PAD_ATA_DATA3__FEC_RXD1 0x0 \
- MX27_PAD_ATA_DATA4__FEC_RXD2 0x0 \
- MX27_PAD_ATA_DATA5__FEC_RXD3 0x0 \
- MX27_PAD_ATA_DATA6__FEC_MDIO 0x0 \
- MX27_PAD_ATA_DATA7__FEC_MDC 0x0 \
- MX27_PAD_ATA_DATA8__FEC_CRS 0x0 \
- MX27_PAD_ATA_DATA9__FEC_TX_CLK 0x0 \
- MX27_PAD_ATA_DATA10__FEC_RXD0 0x0 \
- MX27_PAD_ATA_DATA11__FEC_RX_DV 0x0 \
- MX27_PAD_ATA_DATA12__FEC_RX_CLK 0x0 \
- MX27_PAD_ATA_DATA13__FEC_COL 0x0 \
- MX27_PAD_ATA_DATA14__FEC_TX_ER 0x0 \
- MX27_PAD_ATA_DATA15__FEC_TX_EN 0x0
-
-#define MX27_I2C1_PINGRP1 \
- MX27_PAD_I2C_DATA__I2C_DATA 0x0 \
- MX27_PAD_I2C_CLK__I2C_CLK 0x0
-
-#define MX27_I2C2_PINGRP1 \
- MX27_PAD_I2C2_SDA__I2C2_SDA 0x0 \
- MX27_PAD_I2C2_SCL__I2C2_SCL 0x0
-
-#define MX27_NFC_PINGRP1 \
- MX27_PAD_NFRB__NFRB 0x0 \
- MX27_PAD_NFCLE__NFCLE 0x0 \
- MX27_PAD_NFWP_B__NFWP_B 0x0 \
- MX27_PAD_NFCE_B__NFCE_B 0x0 \
- MX27_PAD_NFALE__NFALE 0x0 \
- MX27_PAD_NFRE_B__NFRE_B 0x0 \
- MX27_PAD_NFWE_B__NFWE_B 0x0
-
-#define MX27_OWIRE1_PINGRP1 \
- MX27_PAD_RTCK__OWIRE 0x0
-
-#define MX27_PWM_PINGRP1 \
- MX27_PAD_PWMO__PWMO 0x0
-
-#define MX27_SDHC1_PINGRP1 \
- MX27_PAD_SD1_CLK__SD1_CLK 0x0 \
- MX27_PAD_SD1_CMD__SD1_CMD 0x0 \
- MX27_PAD_SD1_D0__SD1_D0 0x0 \
- MX27_PAD_SD1_D1__SD1_D1 0x0 \
- MX27_PAD_SD1_D2__SD1_D2 0x0 \
- MX27_PAD_SD1_D3__SD1_D3 0x0
-
-#define MX27_SDHC2_PINGRP1 \
- MX27_PAD_SD2_CLK__SD2_CLK 0x0 \
- MX27_PAD_SD2_CMD__SD2_CMD 0x0 \
- MX27_PAD_SD2_D0__SD2_D0 0x0 \
- MX27_PAD_SD2_D1__SD2_D1 0x0 \
- MX27_PAD_SD2_D2__SD2_D2 0x0 \
- MX27_PAD_SD2_D3__SD2_D3 0x0
-
-#define MX27_SDHC3_PINGRP1 \
- MX27_PAD_SD3_CLK__SD3_CLK 0x0 \
- MX27_PAD_SD3_CMD__SD3_CMD 0x0 \
- MX27_PAD_SD3_D0__SD3_D0 0x0 \
- MX27_PAD_SD3_D1__SD3_D1 0x0 \
- MX27_PAD_SD3_D2__SD3_D2 0x0 \
- MX27_PAD_SD3_D3__SD3_D3 0x0
-
-#define MX27_UART1_PINGRP1 \
- MX27_PAD_UART1_TXD__UART1_TXD 0x0 \
- MX27_PAD_UART1_RXD__UART1_RXD 0x0
-
-#define MX27_UART1_RTSCTS_PINGRP1 \
- MX27_PAD_UART1_CTS__UART1_CTS 0x0 \
- MX27_PAD_UART1_RTS__UART1_RTS 0x0
-
-#define MX27_UART2_PINGRP1 \
- MX27_PAD_UART2_TXD__UART2_TXD 0x0 \
- MX27_PAD_UART2_RXD__UART2_RXD 0x0
-
-#define MX27_UART2_RTSCTS_PINGRP1 \
- MX27_PAD_UART2_CTS__UART2_CTS 0x0 \
- MX27_PAD_UART2_RTS__UART2_RTS 0x0
-
-#define MX27_UART3_PINGRP1 \
- MX27_PAD_UART3_TXD__UART3_TXD 0x0 \
- MX27_PAD_UART3_RXD__UART3_RXD 0x0
-
-#define MX27_UART3_RTSCTS_PINGRP1 \
- MX27_PAD_UART3_CTS__UART3_CTS 0x0 \
- MX27_PAD_UART3_RTS__UART3_RTS 0x0
-
-#endif /* __DTS_IMX27_PINGRP_H */
diff --git a/arch/arm/dts/imx27.dtsi b/arch/arm/dts/imx27.dtsi
index 7e98966b18..83a8247325 100644
--- a/arch/arm/dts/imx27.dtsi
+++ b/arch/arm/dts/imx27.dtsi
@@ -10,12 +10,13 @@
*/
#include "skeleton.dtsi"
-#include "imx27-pingrp.h"
+#include "imx27-pinfunc.h"
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/gpio/gpio.h>
/ {
aliases {
+ ethernet0 = &fec;
gpio0 = &gpio1;
gpio1 = &gpio2;
gpio2 = &gpio3;
@@ -70,6 +71,26 @@
};
};
+ usbphy {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ usbphy0: usbphy@0 {
+ compatible = "usb-nop-xceiv";
+ reg = <0>;
+ clocks = <&clks 75>;
+ clock-names = "main_clk";
+ };
+
+ usbphy2: usbphy@2 {
+ compatible = "usb-nop-xceiv";
+ reg = <2>;
+ clocks = <&clks 75>;
+ clock-names = "main_clk";
+ };
+ };
+
soc {
#address-cells = <1>;
#size-cells = <1>;
@@ -439,6 +460,42 @@
iram = <&iram>;
};
+ usbotg: usb@10024000 {
+ compatible = "fsl,imx27-usb";
+ reg = <0x10024000 0x200>;
+ interrupts = <56>;
+ clocks = <&clks 15>;
+ fsl,usbmisc = <&usbmisc 0>;
+ fsl,usbphy = <&usbphy0>;
+ status = "disabled";
+ };
+
+ usbh1: usb@10024200 {
+ compatible = "fsl,imx27-usb";
+ reg = <0x10024200 0x200>;
+ interrupts = <54>;
+ clocks = <&clks 15>;
+ fsl,usbmisc = <&usbmisc 1>;
+ status = "disabled";
+ };
+
+ usbh2: usb@10024400 {
+ compatible = "fsl,imx27-usb";
+ reg = <0x10024400 0x200>;
+ interrupts = <55>;
+ clocks = <&clks 15>;
+ fsl,usbmisc = <&usbmisc 2>;
+ fsl,usbphy = <&usbphy2>;
+ status = "disabled";
+ };
+
+ usbmisc: usbmisc@10024600 {
+ #index-cells = <1>;
+ compatible = "fsl,imx27-usbmisc";
+ reg = <0x10024600 0x200>;
+ clocks = <&clks 62>;
+ };
+
sahara2: sahara@10025000 {
compatible = "fsl,imx27-sahara";
reg = <0x10025000 0x1000>;
diff --git a/arch/arm/dts/imx53-qsb-common.dtsi b/arch/arm/dts/imx53-qsb-common.dtsi
index 571da92ad3..9aa0f083ff 100644
--- a/arch/arm/dts/imx53-qsb-common.dtsi
+++ b/arch/arm/dts/imx53-qsb-common.dtsi
@@ -230,3 +230,7 @@
&sata {
status = "okay";
};
+
+&sata {
+ status = "okay";
+};
diff --git a/arch/arm/dts/imx53.dtsi b/arch/arm/dts/imx53.dtsi
index 91659b8ca1..d6cdcafe76 100644
--- a/arch/arm/dts/imx53.dtsi
+++ b/arch/arm/dts/imx53.dtsi
@@ -79,15 +79,15 @@
compatible = "fsl,imx53-ahci";
reg = <0x10000000 0x1000>;
interrupts = <28>;
- clocks = <&clks 173>, <&clks 5>, <&clks 188>;
- clock-names = "sata", "ahb", "per";
+ clocks = <&clks 173>, <&clks 188>, <&clks 5>;
+ clock-names = "sata_gate", "sata_ref", "ahb";
status = "disabled";
};
ipu: ipu@18000000 {
#crtc-cells = <1>;
compatible = "fsl,imx53-ipu";
- reg = <0x18000000 0x080000000>;
+ reg = <0x18000000 0x08000000>;
interrupts = <11 10>;
clocks = <&clks 59>, <&clks 110>, <&clks 61>;
clock-names = "bus", "di0", "di1";
diff --git a/arch/arm/dts/imx6dl-phytec-pbab01.dts b/arch/arm/dts/imx6dl-phytec-pbab01.dts
new file mode 100644
index 0000000000..0e90c47768
--- /dev/null
+++ b/arch/arm/dts/imx6dl-phytec-pbab01.dts
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+
+#include "imx6dl-phytec-pfla02.dtsi"
+#include "imx6qdl-phytec-pbab01.dtsi"
+
+/ {
+ model = "Phytec phyFLEX-i.MX6 Duallite Carrier-Board";
+ compatible = "phytec,imx6x-pbab01", "phytec,imx6dl-pfla02", "fsl,imx6dl";
+
+ chosen {
+ linux,stdout-path = &uart4;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &flash, "partname:barebox-environment";
+ };
+ };
+};
diff --git a/arch/arm/dts/imx6dl-phytec-pfla02.dtsi b/arch/arm/dts/imx6dl-phytec-pfla02.dtsi
new file mode 100644
index 0000000000..fa3a49aa3c
--- /dev/null
+++ b/arch/arm/dts/imx6dl-phytec-pfla02.dtsi
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-phytec-pfla02.dtsi"
+
+/ {
+ model = "Phytec phyFLEX-i.MX6 Dual Lite";
+ compatible = "phytec,imx6dl-pfla02", "fsl,imx6dl";
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+};
+
+&ecspi3 {
+ status = "okay";
+};
+
+&flash {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x80000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x80000 0x10000>;
+ };
+};
diff --git a/arch/arm/dts/imx6q-phytec-pbab01.dts b/arch/arm/dts/imx6q-phytec-pbab01.dts
index b35b2e5c30..26046e01c3 100644
--- a/arch/arm/dts/imx6q-phytec-pbab01.dts
+++ b/arch/arm/dts/imx6q-phytec-pbab01.dts
@@ -11,10 +11,11 @@
/dts-v1/;
#include "imx6q-phytec-pfla02.dtsi"
+#include "imx6qdl-phytec-pbab01.dtsi"
/ {
model = "Phytec phyFLEX-i.MX6 Quad Carrier-Board";
- compatible = "phytec,imx6q-pbab01", "phytec,imx6q-pfla02", "fsl,imx6q";
+ compatible = "phytec,imx6x-pbab01", "phytec,imx6q-pfla02", "fsl,imx6q";
chosen {
linux,stdout-path = &uart4;
@@ -25,23 +26,3 @@
};
};
};
-
-&fec {
- status = "okay";
-};
-
-&uart1 {
- status = "okay";
-};
-
-&uart4 {
- status = "okay";
-};
-
-&usdhc2 {
- status = "okay";
-};
-
-&usdhc3 {
- status = "okay";
-};
diff --git a/arch/arm/dts/imx6q-phytec-pfla02.dtsi b/arch/arm/dts/imx6q-phytec-pfla02.dtsi
index 402eee804d..781a90ae9d 100644
--- a/arch/arm/dts/imx6q-phytec-pfla02.dtsi
+++ b/arch/arm/dts/imx6q-phytec-pfla02.dtsi
@@ -10,9 +10,10 @@
*/
#include "imx6q.dtsi"
+#include "imx6qdl-phytec-pfla02.dtsi"
/ {
- model = "Phytec phyFLEX-i.MX6 Ouad";
+ model = "Phytec phyFLEX-i.MX6 Quad";
compatible = "phytec,imx6q-pfla02", "fsl,imx6q";
memory {
@@ -21,165 +22,7 @@
};
&ecspi3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ecspi3>;
status = "okay";
- fsl,spi-num-chipselects = <1>;
- cs-gpios = <&gpio4 24 0>;
-
- flash: m25p80@0 {
- compatible = "m25p80";
- spi-max-frequency = <20000000>;
- reg = <0>;
- };
-};
-
-&i2c1 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_i2c1>;
- status = "okay";
-
- eeprom@50 {
- compatible = "atmel,24c32";
- reg = <0x50>;
- };
-
- pmic@58 {
- compatible = "dialog,da9063";
- reg = <0x58>;
- interrupt-parent = <&gpio4>;
- interrupts = <17 0x8>; /* active-low GPIO4_17 */
-
- regulators {
- vddcore_reg: bcore1 {
- regulator-min-microvolt = <730000>;
- regulator-max-microvolt = <1380000>;
- regulator-always-on;
- };
-
- vddsoc_reg: bcore2 {
- regulator-min-microvolt = <730000>;
- regulator-max-microvolt = <1380000>;
- regulator-always-on;
- };
-
- vdd_ddr3_reg: bpro {
- regulator-min-microvolt = <1500000>;
- regulator-max-microvolt = <1500000>;
- regulator-always-on;
- };
-
- vdd_3v3_reg: bperi {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vdd_buckmem_reg: bmem {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vdd_eth_reg: bio {
- regulator-min-microvolt = <1200000>;
- regulator-max-microvolt = <1200000>;
- regulator-always-on;
- };
-
- vdd_eth_io_reg: ldo4 {
- regulator-min-microvolt = <2500000>;
- regulator-max-microvolt = <2500000>;
- regulator-always-on;
- };
-
- vdd_mx6_snvs_reg: ldo5 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- regulator-always-on;
- };
-
- vdd_3v3_pmic_io_reg: ldo6 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- regulator-always-on;
- };
-
- vdd_sd0_reg: ldo9 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
-
- vdd_sd1_reg: ldo10 {
- regulator-min-microvolt = <3300000>;
- regulator-max-microvolt = <3300000>;
- };
-
- vdd_mx6_high_reg: ldo11 {
- regulator-min-microvolt = <3000000>;
- regulator-max-microvolt = <3000000>;
- regulator-always-on;
- };
- };
- };
-};
-
-&iomuxc {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_hog>;
-
- imx6q-phytec-pfla02 {
- pinctrl_hog: hoggrp {
- fsl,pins = <
- MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
- MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
- MX6QDL_PAD_DI0_PIN15__GPIO4_IO17 0x80000000 /* PMIC interrupt */
- >;
- };
-
- pinctrl_ecspi3: ecspi3grp {
- fsl,pins = <MX6QDL_ECSPI3_PINGRP1>;
- };
-
- pinctrl_enet: enetgrp {
- fsl,pins = <MX6QDL_ENET_PINGRP3>;
- };
-
- pinctrl_gpmi_nand: gpmigrp {
- fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
- };
-
- pinctrl_i2c1: i2c1grp {
- fsl,pins = <MX6QDL_I2C1_PINGRP1>;
- };
-
- pinctrl_uart4: uart4grp {
- fsl,pins = <MX6QDL_UART4_PINGRP1>;
- };
-
- pinctrl_usdhc2: usdhc2grp {
- fsl,pins = <MX6QDL_USDHC2_PINGRP_D4>;
- };
-
- pinctrl_usdhc3: usdhc3grp {
- fsl,pins = <MX6QDL_USDHC3_PINGRP_D4>;
- };
-
- pinctrl_usdhc3_cdwp: usdhc3cdwp {
- fsl,pins = <
- MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
- MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
- >;
- };
- };
-};
-
-&fec {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_enet>;
- phy-mode = "rgmii";
- phy-reset-gpios = <&gpio3 23 0>;
- status = "disabled";
};
&flash {
@@ -196,49 +39,3 @@
reg = <0x80000 0x10000>;
};
};
-
-&gpmi {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_gpmi_nand>;
- nand-on-flash-bbt;
- status = "okay";
- #address-cells = <1>;
- #size-cells = <1>;
-
- partition@0 {
- label = "barebox";
- reg = <0x0 0x200000>;
- };
-
- partition@1 {
- label = "ubi";
- reg = <0x200000 0x3fe00000>;
- };
-};
-
-&ocotp {
- barebox,provide-mac-address = <&fec 0x620>;
-};
-
-&uart4 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_uart4>;
- status = "disabled";
-};
-
-&usdhc2 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc2>;
- cd-gpios = <&gpio1 4 0>;
- wp-gpios = <&gpio1 2 0>;
- status = "disabled";
-};
-
-&usdhc3 {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_usdhc3
- &pinctrl_usdhc3_cdwp>;
- cd-gpios = <&gpio1 27 0>;
- wp-gpios = <&gpio1 29 0>;
- status = "disabled";
-};
diff --git a/arch/arm/dts/imx6q-var-custom.dts b/arch/arm/dts/imx6q-var-custom.dts
new file mode 100644
index 0000000000..bb1193f9a4
--- /dev/null
+++ b/arch/arm/dts/imx6q-var-custom.dts
@@ -0,0 +1,149 @@
+/*
+ * Copyright 2013 Michael Burkey
+ * Based on code written by Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ *
+ * environment@0 {
+ compatible = "barebox,environment";
+ device-path = &usdhc2, "partname:barebox-environment";
+ };
+
+ *
+ */
+
+/dts-v1/;
+#include "imx6q-var-som.dtsi"
+
+/ {
+ model = "Variscite i.MX6 Quad Custom Carrier-Board";
+ compatible = "variscite,imx6q-custom", "variscite,imx6q-som", "fsl,imx6q";
+
+ chosen {
+ linux,stdout-path = &uart1;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &gpmi, "partname:barebox-environment";
+ };
+
+ };
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6q-variscite-custom {
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <MX6QDL_I2C1_PINGRP1>;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <MX6QDL_I2C3_PINGRP3>;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <MX6QDL_USDHC2_PINGRP_D4>;
+ };
+
+ pinctrl_usdhc2_cd: usdhc2cd {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL4__GPIO4_IO14 0x80000000
+ MX6QDL_PAD_KEY_ROW4__GPIO4_IO15 0x80000000
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <MX6QDL_UART1_PINGRP1>;
+ };
+ };
+};
+
+&ldb {
+ status = "okay";
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "okay";
+ display-timings {
+ native-mode = &claawvga;
+ claawvga: claawvga {
+ native-mode;
+ clock-frequency = <35714000>;
+ hactive = <800>;
+ vactive = <480>;
+ hback-porch = <28>;
+ hfront-porch = <17>;
+ vback-porch = <13>;
+ vfront-porch = <20>;
+ hsync-len = <20>;
+ vsync-len = <13>;
+ };
+ };
+ };
+};
+
+&uart1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+};
+
+&usdhc2 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ cd-gpios = <&gpio4 14 0>;
+ wp-gpios = <&gpio4 15 0>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x200000 0x20000>;
+ };
+
+ partition@2 {
+ label = "kernel";
+ reg = <0x220000 0x600000>;
+ };
+
+ partition@3 {
+ label = "rootfs";
+ reg = <0x820000 0x18000000>;
+ };
+};
+
+&usbh1 {
+ status = "okay";
+ disable-over-current;
+ dr_mode = "host";
+ phy_type = "utmi";
+};
+
+&i2c1 {
+ status = "okay";
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+};
+
+&i2c3 {
+ status = "okay";
+ clock-frequency = <1000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+};
diff --git a/arch/arm/dts/imx6q-var-som.dtsi b/arch/arm/dts/imx6q-var-som.dtsi
new file mode 100644
index 0000000000..f423f27359
--- /dev/null
+++ b/arch/arm/dts/imx6q-var-som.dtsi
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2013 Michael Burkey
+ * Based on code written by Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6q.dtsi"
+
+/ {
+ model = "Variscite i.MX6 Quad SOM";
+ compatible = "variscite,imx6q-som", "fsl,imx6q";
+
+ memory {
+ reg = <0x10000000 0x40000000>;
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ status = "okay";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ nand-on-flash-bbt;
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x200000>;
+ };
+
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x200000 0x20000>;
+ };
+
+ partition@2 {
+ label = "kernel";
+ reg = <0x220000 0x600000>;
+ };
+
+ partition@3 {
+ label = "rootfs";
+ reg = <0x820000 0x1F7E0000>;
+ };
+};
+
+&hdmi {
+ status = "okay";
+ ddc-i2c-bus = <&i2c2>;
+};
+
+&i2c2 {
+ status = "okay";
+ clock-frequency = <1000000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6q-variscite-som {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x80000000
+ MX6QDL_PAD_GPIO_3__CCM_CLKO2 0x80000000
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_ENET_PINGRP_RGMII_MD(0x1b0b0, 0x1b0b0)
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x80000000 /* KSZ9031 PHY Reset */
+ >;
+ };
+
+ pinctrl_gpmi_nand: gpmigrp {
+ fsl,pins = <MX6QDL_GPMI_NAND_PINGRP1>;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <MX6QDL_I2C2_PINGRP2>;
+ };
+ };
+};
diff --git a/arch/arm/dts/imx6q.dtsi b/arch/arm/dts/imx6q.dtsi
index 52a9a2b372..2b8ec43e03 100644
--- a/arch/arm/dts/imx6q.dtsi
+++ b/arch/arm/dts/imx6q.dtsi
@@ -16,6 +16,7 @@
/ {
aliases {
spi4 = &ecspi5;
+ ipu1 = &ipu2;
};
cpus {
@@ -157,6 +158,10 @@
};
};
+&hdmi {
+ compatible = "fsl,imx6q-hdmi";
+};
+
&ldb {
clocks = <&clks 33>, <&clks 34>,
<&clks 39>, <&clks 40>, <&clks 41>, <&clks 42>,
diff --git a/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi b/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi
new file mode 100644
index 0000000000..8f5dea7407
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-phytec-pbab01.dtsi
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/ {
+ chosen {
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &flash, "partname:barebox-environment";
+ };
+ };
+};
+
+&fec {
+ status = "okay";
+};
+
+&ocotp {
+ barebox,provide-mac-address = <&fec 0x620>;
+};
+
+&uart1 {
+ status = "okay";
+};
+
+&uart4 {
+ status = "okay";
+};
+
+&usdhc2 {
+ status = "okay";
+};
+
+&usdhc3 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
new file mode 100644
index 0000000000..d1eb9d0b09
--- /dev/null
+++ b/arch/arm/dts/imx6qdl-phytec-pfla02.dtsi
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+&ecspi3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ecspi3>;
+ status = "disabled";
+ fsl,spi-num-chipselects = <1>;
+ cs-gpios = <&gpio4 24 0>;
+
+ flash: m25p80@0 {
+ compatible = "m25p80";
+ spi-max-frequency = <20000000>;
+ };
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-reset-gpios = <&gpio3 23 0>;
+ status = "disabled";
+};
+
+&gpmi {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpmi_nand>;
+ nand-on-flash-bbt;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ ecspi3 {
+ pinctrl_ecspi3: ecspi3grp {
+ fsl,pins = <
+ MX6QDL_PAD_DISP0_DAT2__ECSPI3_MISO 0x100b1
+ MX6QDL_PAD_DISP0_DAT1__ECSPI3_MOSI 0x100b1
+ MX6QDL_PAD_DISP0_DAT0__ECSPI3_SCLK 0x100b1
+ MX6QDL_PAD_DISP0_DAT3__GPIO4_IO24 0x80000000 /* SPI NOR chipselect */
+ MX6QDL_PAD_SD4_DAT3__GPIO2_IO11 0x80000000
+ >;
+ };
+ };
+
+ enet {
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0
+ >;
+ };
+ };
+
+ gpmi-nand {
+ pinctrl_gpmi_nand: gpmi-nand {
+ fsl,pins = <
+ MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1
+ MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1
+ MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1
+ MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000
+ MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS2__NAND_CE2_B 0xb0b1
+ MX6QDL_PAD_NANDF_CS3__NAND_CE3_B 0xb0b1
+ MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1
+ MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1
+ MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1
+ MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1
+ MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1
+ MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1
+ MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1
+ MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1
+ MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1
+ MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1
+ MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1
+ >;
+ };
+ };
+
+ hog {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D23__GPIO3_IO23 0x80000000
+ >;
+ };
+ };
+
+ uart4 {
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+ };
+
+ usdhc2 {
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ >;
+ };
+ };
+
+ usdhc3 {
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ MX6QDL_PAD_ENET_RXD0__GPIO1_IO27 0x80000000
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+ >;
+ };
+ };
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "disabled";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ cd-gpios = <&gpio1 4 0>;
+ wp-gpios = <&gpio1 2 0>;
+ status = "disabled";
+};
+
+&usdhc3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc3>;
+ cd-gpios = <&gpio1 27 0>;
+ wp-gpios = <&gpio1 29 0>;
+ status = "disabled";
+};
diff --git a/arch/arm/dts/imx6qdl.dtsi b/arch/arm/dts/imx6qdl.dtsi
index 70424d2cb7..8dfd7de48c 100644
--- a/arch/arm/dts/imx6qdl.dtsi
+++ b/arch/arm/dts/imx6qdl.dtsi
@@ -45,6 +45,7 @@
spi3 = &ecspi4;
usbphy0 = &usbphy1;
usbphy1 = &usbphy2;
+ ipu0 = &ipu1;
};
intc: interrupt-controller@00a01000 {
@@ -664,6 +665,17 @@
};
};
+ hdmi: hdmi@0120000 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x00120000 0x9000>;
+ interrupts = <0 115 0x04>;
+ gpr = <&gpr>;
+ clocks = <&clks 123>, <&clks 124>;
+ clock-names = "iahb", "isfr";
+ status = "disabled";
+ };
+
dcic1: dcic@020e4000 {
reg = <0x020e4000 0x4000>;
interrupts = <0 124 IRQ_TYPE_LEVEL_HIGH>;
diff --git a/arch/arm/dts/imx6s-phytec-pbab01.dts b/arch/arm/dts/imx6s-phytec-pbab01.dts
new file mode 100644
index 0000000000..95841de7b8
--- /dev/null
+++ b/arch/arm/dts/imx6s-phytec-pbab01.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+
+#include "imx6s-phytec-pfla02.dtsi"
+#include "imx6qdl-phytec-pbab01.dtsi"
+
+/ {
+ model = "Phytec phyFLEX-i.MX6 Single Carrier-Board";
+ compatible = "phytec,imx6x-pbab01", "phytec,imx6s-pfla02", "fsl,imx6dl";
+
+ chosen {
+ linux,stdout-path = &uart4;
+
+ };
+};
diff --git a/arch/arm/dts/imx6s-phytec-pfla02.dtsi b/arch/arm/dts/imx6s-phytec-pfla02.dtsi
new file mode 100644
index 0000000000..83224262b3
--- /dev/null
+++ b/arch/arm/dts/imx6s-phytec-pfla02.dtsi
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2013 Christian Hemp, Phytec Messtechnik GmbH
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include "imx6dl.dtsi"
+#include "imx6qdl-phytec-pfla02.dtsi"
+
+/ {
+ model = "Phytec phyFLEX-i.MX6 Single";
+ compatible = "phytec,imx6s-pfla02", "fsl,imx6dl";
+
+ memory {
+ reg = <0x10000000 0x20000000>;
+ };
+};
diff --git a/arch/arm/dts/virt2real.dts b/arch/arm/dts/virt2real.dts
new file mode 100644
index 0000000000..09aec1f722
--- /dev/null
+++ b/arch/arm/dts/virt2real.dts
@@ -0,0 +1,35 @@
+/dts-v1/;
+
+#include "dm365.dtsi"
+
+/ {
+ model = "virt2real";
+
+ memory {
+ reg = <0x82000000 0x01000000>;
+ };
+
+ soc {
+ serial0: serial@1c20000 {
+ status = "okay";
+ };
+
+ gpio: gpio@1c67000 {
+ status = "okay";
+ };
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ green_led {
+ label = "green-led";
+ gpios = <&gpio 73 0>;
+ };
+
+ red_led {
+ label = "red-led";
+ gpios = <&gpio 74 0>;
+ };
+ };
+};
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index 28afaa39e4..52114d0c4e 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -3,6 +3,13 @@
#include <memory.h>
+#include <linux/const.h>
+/*
+ * Allow for constants defined here to be used from assembly code
+ * by prepending the UL suffix only with actual C code compilation.
+ */
+#define UL(x) _AC(x, UL)
+
static inline void arm_add_mem_device(const char* name, resource_size_t start,
resource_size_t size)
{
diff --git a/arch/arm/mach-arm.dox b/arch/arm/mach-arm.dox
index 758df3f541..1d2de48df2 100644
--- a/arch/arm/mach-arm.dox
+++ b/arch/arm/mach-arm.dox
@@ -54,6 +54,8 @@ For details on specific architectures:
@subsection mach_arm_omap_info OMAP CPUs
+@li @subpage dev_davinci_arch
+
@li @subpage dev_omap_arch
@subsection mach_arm_s3c24xx_info S3C24XX CPUs
diff --git a/arch/arm/mach-at91/include/mach/cpu.h b/arch/arm/mach-at91/include/mach/cpu.h
index 7132489132..0e213ce9da 100644
--- a/arch/arm/mach-at91/include/mach/cpu.h
+++ b/arch/arm/mach-at91/include/mach/cpu.h
@@ -52,6 +52,7 @@
#define ARCH_EXID_SAMA5D33 0x00414300
#define ARCH_EXID_SAMA5D34 0x00414301
#define ARCH_EXID_SAMA5D35 0x00584300
+#define ARCH_EXID_SAMA5D36 0x00004301
#define ARCH_FAMILY_AT91X92 0x09200000
#define ARCH_FAMILY_AT91SAM9 0x01900000
@@ -104,7 +105,7 @@ enum at91_soc_subtype {
/* SAMA5D3 */
AT91_SOC_SAMA5D31, AT91_SOC_SAMA5D33, AT91_SOC_SAMA5D34,
- AT91_SOC_SAMA5D35,
+ AT91_SOC_SAMA5D35, AT91_SOC_SAMA5D36,
/* Unknown subtype */
AT91_SOC_SUBTYPE_NONE
@@ -206,12 +207,14 @@ static inline int at91_soc_is_detected(void)
#define cpu_is_sama5d33() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D33)
#define cpu_is_sama5d34() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D34)
#define cpu_is_sama5d35() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D35)
+#define cpu_is_sama5d36() (at91_soc_initdata.subtype == AT91_SOC_SAMA5D36)
#else
#define cpu_is_sama5d3() (0)
#define cpu_is_sama5d31() (0)
#define cpu_is_sama5d33() (0)
#define cpu_is_sama5d34() (0)
#define cpu_is_sama5d35() (0)
+#define cpu_is_sama5d36() (0)
#endif
/*
diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c
index 1bfae14f63..85efb2d78f 100644
--- a/arch/arm/mach-at91/sama5d3.c
+++ b/arch/arm/mach-at91/sama5d3.c
@@ -348,11 +348,13 @@ static void __init sama5d3_register_clocks(void)
if ( cpu_is_sama5d33()
|| cpu_is_sama5d34()
- || cpu_is_sama5d35() )
+ || cpu_is_sama5d35()
+ || cpu_is_sama5d36())
clk_register(&macb0_clk);
if ( cpu_is_sama5d31()
- || cpu_is_sama5d35() )
+ || cpu_is_sama5d35()
+ || cpu_is_sama5d36())
clk_register(&macb1_clk);
if (!cpu_is_sama5d35())
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 65d0588b43..7a7de98045 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -162,6 +162,8 @@ static void __init soc_detect(u32 dbgu_base)
break;
case ARCH_EXID_SAMA5D35:
at91_soc_initdata.subtype = AT91_SOC_SAMA5D35;
+ case ARCH_EXID_SAMA5D36:
+ at91_soc_initdata.subtype = AT91_SOC_SAMA5D36;
break;
}
}
@@ -205,6 +207,7 @@ static const char *soc_subtype_name[] = {
[AT91_SOC_SAMA5D33] = "sama5d33",
[AT91_SOC_SAMA5D34] = "sama5d34",
[AT91_SOC_SAMA5D35] = "sama5d35",
+ [AT91_SOC_SAMA5D36] = "sama5d36",
[AT91_SOC_SUBTYPE_NONE] = "Unknown"
};
diff --git a/arch/arm/mach-clps711x/clock.c b/arch/arm/mach-clps711x/clock.c
index 7658c9aa7c..548b333b11 100644
--- a/arch/arm/mach-clps711x/clock.c
+++ b/arch/arm/mach-clps711x/clock.c
@@ -95,9 +95,9 @@ static __init int clps711x_clk_init(void)
clks[timer_hf].clk = clk_fixed(clks[timer_hf].name, f_timer_hf);
clks[timer_lf].clk = clk_fixed(clks[timer_lf].name, f_timer_lf);
clks[tc1].clk = clk_mux(clks[tc1].name, IOMEM(SYSCON1), 5, 1,
- tc_sel_clks, ARRAY_SIZE(tc_sel_clks));
+ tc_sel_clks, ARRAY_SIZE(tc_sel_clks), 0);
clks[tc2].clk = clk_mux(clks[tc2].name, IOMEM(SYSCON1), 7, 1,
- tc_sel_clks, ARRAY_SIZE(tc_sel_clks));
+ tc_sel_clks, ARRAY_SIZE(tc_sel_clks), 0);
clps711x_clk_register(dummy);
clps711x_clk_register(cpu);
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
new file mode 100644
index 0000000000..3165d5086d
--- /dev/null
+++ b/arch/arm/mach-davinci/Kconfig
@@ -0,0 +1,16 @@
+if ARCH_DAVINCI
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x82000000
+
+choice
+ prompt "Davinci Board type"
+
+config MACH_VIRT2REAL
+ bool "Virt2Real"
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+
+endchoice
+
+endif
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
new file mode 100644
index 0000000000..b96d4146f6
--- /dev/null
+++ b/arch/arm/mach-davinci/Makefile
@@ -0,0 +1 @@
+obj-y += time.o
diff --git a/arch/arm/mach-davinci/include/mach/debug_ll.h b/arch/arm/mach-davinci/include/mach/debug_ll.h
new file mode 100644
index 0000000000..587f408cf8
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/debug_ll.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/** @file
+ * This File contains declaration for early output support
+ */
+#ifndef __INCLUDE_ARCH_DEBUG_LL_H__
+#define __INCLUDE_ARCH_DEBUG_LL_H__
+
+#include <asm/io.h>
+#include <mach/serial.h>
+
+#define DEBUG_LL_UART_ADDR DAVINCI_UART0_BASE
+#define DEBUG_LL_UART_RSHFT 2
+
+#define rbr (0 << DEBUG_LL_UART_RSHFT)
+#define lsr (5 << DEBUG_LL_UART_RSHFT)
+#define LSR_THRE 0x20 /* Xmit holding register empty */
+
+static inline void PUTC_LL(char ch)
+{
+ while (!(__raw_readb(DEBUG_LL_UART_ADDR + lsr) & LSR_THRE))
+ ;
+
+ __raw_writeb(ch, DEBUG_LL_UART_ADDR + rbr);
+}
+
+#endif /* __INCLUDE_ARCH_DEBUG_LL_H__ */
diff --git a/arch/arm/mach-davinci/include/mach/hardware.h b/arch/arm/mach-davinci/include/mach/hardware.h
new file mode 100644
index 0000000000..ea9f481844
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/hardware.h
@@ -0,0 +1,29 @@
+/*
+ * Hardware definitions common to all DaVinci family processors
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H
+
+#include <asm/memory.h>
+
+/*
+ * Before you add anything to this file:
+ *
+ * This header is for defines common to ALL DaVinci family chips.
+ * Anything that is chip specific should go in <chipname>.h,
+ * and the chip/board init code should then explicitly include
+ * <chipname>.h
+ */
+/*
+ * I/O mapping
+ */
+#define IO_PHYS UL(0x01c00000)
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff --git a/arch/arm/mach-davinci/include/mach/serial.h b/arch/arm/mach-davinci/include/mach/serial.h
new file mode 100644
index 0000000000..bc7449f3d7
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/serial.h
@@ -0,0 +1,20 @@
+/*
+ * DaVinci serial device definitions
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ASM_ARCH_SERIAL_H
+#define __ASM_ARCH_SERIAL_H
+
+#include <mach/hardware.h>
+
+#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
+#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
+#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800)
+
+#endif /* __ASM_ARCH_SERIAL_H */
diff --git a/arch/arm/mach-davinci/include/mach/time.h b/arch/arm/mach-davinci/include/mach/time.h
new file mode 100644
index 0000000000..34781b6ec5
--- /dev/null
+++ b/arch/arm/mach-davinci/include/mach/time.h
@@ -0,0 +1,20 @@
+/*
+ * Local header file for DaVinci time code.
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H
+#define __ARCH_ARM_MACH_DAVINCI_TIME_H
+
+#include <mach/hardware.h>
+
+#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
+#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
+#define DAVINCI_WDOG_BASE (IO_PHYS + 0x21C00)
+
+#endif /* __ARCH_ARM_MACH_DAVINCI_TIME_H */
diff --git a/arch/arm/mach-davinci/mach-davinci.dox b/arch/arm/mach-davinci/mach-davinci.dox
new file mode 100644
index 0000000000..789eacc42a
--- /dev/null
+++ b/arch/arm/mach-davinci/mach-davinci.dox
@@ -0,0 +1,7 @@
+/** @page dev_davinci_arch TI DaVinci in barebox
+
+@section davinci_boards DaVinci-based boards
+
+@li @subpage virt2real
+
+*/
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
new file mode 100644
index 0000000000..60f0d192a3
--- /dev/null
+++ b/arch/arm/mach-davinci/time.c
@@ -0,0 +1,209 @@
+/*
+ * DaVinci timer subsystem
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <common.h>
+#include <io.h>
+#include <init.h>
+#include <clock.h>
+
+#include <mach/time.h>
+
+/* Timer register offsets */
+#define PID12 0x0
+#define TIM12 0x10
+#define TIM34 0x14
+#define PRD12 0x18
+#define PRD34 0x1c
+#define TCR 0x20
+#define TGCR 0x24
+#define WDTCR 0x28
+
+/* Timer register bitfields */
+#define TCR_ENAMODE_DISABLE 0x0
+#define TCR_ENAMODE_ONESHOT 0x1
+#define TCR_ENAMODE_PERIODIC 0x2
+#define TCR_ENAMODE_MASK 0x3
+
+#define TGCR_TIMMODE_SHIFT 2
+#define TGCR_TIMMODE_64BIT_GP 0x0
+#define TGCR_TIMMODE_32BIT_UNCHAINED 0x1
+#define TGCR_TIMMODE_64BIT_WDOG 0x2
+#define TGCR_TIMMODE_32BIT_CHAINED 0x3
+
+#define TGCR_TIM12RS_SHIFT 0
+#define TGCR_TIM34RS_SHIFT 1
+#define TGCR_RESET 0x0
+#define TGCR_UNRESET 0x1
+#define TGCR_RESET_MASK 0x3
+
+#define WDTCR_WDEN_SHIFT 14
+#define WDTCR_WDEN_DISABLE 0x0
+#define WDTCR_WDEN_ENABLE 0x1
+#define WDTCR_WDKEY_SHIFT 16
+#define WDTCR_WDKEY_SEQ0 0xa5c6
+#define WDTCR_WDKEY_SEQ1 0xda7e
+
+#define DAVINCI_TIMER_CLOCK 24000000
+
+struct timer_s {
+ void __iomem *base;
+ unsigned long tim_off;
+ unsigned long prd_off;
+ unsigned long enamode_shift;
+};
+
+static struct timer_s timers[] = {
+ {
+ .base = IOMEM(DAVINCI_TIMER0_BASE),
+ .enamode_shift = 6,
+ .tim_off = TIM12,
+ .prd_off = PRD12,
+ },
+ {
+ .base = IOMEM(DAVINCI_TIMER0_BASE),
+ .enamode_shift = 22,
+ .tim_off = TIM34,
+ .prd_off = PRD34,
+ },
+ {
+ .base = IOMEM(DAVINCI_TIMER1_BASE),
+ .enamode_shift = 6,
+ .tim_off = TIM12,
+ .prd_off = PRD12,
+ },
+ {
+ .base = IOMEM(DAVINCI_TIMER1_BASE),
+ .enamode_shift = 22,
+ .tim_off = TIM34,
+ .prd_off = PRD34,
+ },
+};
+
+static struct timer_s *t = &timers[0];
+
+static uint64_t davinci_cs_read(void)
+{
+ return (uint64_t)__raw_readl(t->base + t->tim_off);
+}
+
+static struct clocksource davinci_cs = {
+ .read = davinci_cs_read,
+ .mask = CLOCKSOURCE_MASK(32),
+};
+
+static int timer32_config(struct timer_s *t)
+{
+ u32 tcr;
+
+ tcr = __raw_readl(t->base + TCR);
+
+ /* disable timer */
+ tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
+ __raw_writel(tcr, t->base + TCR);
+
+ /* reset counter to zero, set new period */
+ __raw_writel(0, t->base + t->tim_off);
+ __raw_writel(0xffffffff, t->base + t->prd_off);
+
+ /* Set enable mode for periodic timer */
+ tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
+
+ __raw_writel(tcr, t->base + TCR);
+
+ return 0;
+}
+
+/* Global init of 64-bit timer as a whole */
+static void __init timer_init(void __iomem *base)
+{
+ u32 tgcr;
+
+ /* Disabled, Internal clock source */
+ __raw_writel(0, base + TCR);
+
+ /* reset both timers, no pre-scaler for timer34 */
+ tgcr = 0;
+ __raw_writel(tgcr, base + TGCR);
+
+ /* Set both timers to unchained 32-bit */
+ tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
+ __raw_writel(tgcr, base + TGCR);
+
+ /* Unreset timers */
+ tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
+ (TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
+ __raw_writel(tgcr, base + TGCR);
+
+ /* Init both counters to zero */
+ __raw_writel(0, base + TIM12);
+ __raw_writel(0, base + TIM34);
+}
+
+static int clocksource_init(void)
+{
+ clocks_calc_mult_shift(&davinci_cs.mult, &davinci_cs.shift,
+ DAVINCI_TIMER_CLOCK, NSEC_PER_SEC, 10);
+
+ init_clock(&davinci_cs);
+
+ timer_init(IOMEM(DAVINCI_TIMER0_BASE));
+ timer_init(IOMEM(DAVINCI_TIMER1_BASE));
+
+ timer32_config(t);
+
+ return 0;
+}
+core_initcall(clocksource_init);
+
+/* reset board using watchdog timer */
+void __noreturn reset_cpu(ulong addr)
+{
+ u32 tgcr, wdtcr;
+ void __iomem *base;
+
+ base = IOMEM(DAVINCI_WDOG_BASE);
+
+ /* disable, internal clock source */
+ __raw_writel(0, base + TCR);
+
+ /* reset timer, set mode to 64-bit watchdog, and unreset */
+ tgcr = 0;
+ __raw_writel(tgcr, base + TGCR);
+ tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
+ tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
+ (TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
+ __raw_writel(tgcr, base + TGCR);
+
+ /* clear counter and period regs */
+ __raw_writel(0, base + TIM12);
+ __raw_writel(0, base + TIM34);
+ __raw_writel(0, base + PRD12);
+ __raw_writel(0, base + PRD34);
+
+ /* put watchdog in pre-active state */
+ wdtcr = __raw_readl(base + WDTCR);
+ wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
+ (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
+ __raw_writel(wdtcr, base + WDTCR);
+
+ /* put watchdog in active state */
+ wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
+ (WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
+ __raw_writel(wdtcr, base + WDTCR);
+
+ /* write an invalid value to the WDKEY field to trigger
+ * a watchdog reset */
+ wdtcr = 0x00004000;
+ __raw_writel(wdtcr, base + WDTCR);
+
+ unreachable();
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index b7e7533e84..d40c9447ea 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -39,6 +39,7 @@ config ARCH_TEXT_BASE
default 0x4fc00000 if MACH_PHYTEC_PFLA02
default 0x4fc00000 if MACH_DFI_FS700_M60
default 0x4fc00000 if MACH_UDOO
+ default 0x4fc00000 if MACH_VARISCITE_MX6
config ARCH_IMX_INTERNAL_BOOT
bool "support internal boot mode"
@@ -109,6 +110,12 @@ config BAREBOX_UPDATE_IMX_EXTERNAL_NAND
depends on BAREBOX_UPDATE
default y
+config BAREBOX_UPDATE_IMX6_NAND
+ bool
+ depends on ARCH_IMX6
+ depends on BAREBOX_UPDATE
+ default y
+
comment "Freescale i.MX System-on-Chip"
config ARCH_IMX1
@@ -202,7 +209,7 @@ config MACH_FREESCALE_MX53_VMX53
module equipped with a Freescale i.MX53 Processor
config MACH_PHYTEC_PFLA02
- bool "Phytec phyFLEX-i.MX6 Ouad"
+ bool "Phytec phyFLEX-i.MX6"
select ARCH_IMX6
config MACH_DFI_FS700_M60
@@ -247,6 +254,11 @@ config MACH_UDOO
bool "Freescale i.MX6 UDOO Board"
select ARCH_IMX6
+config MACH_VARISCITE_MX6
+ bool "Variscite i.MX6 Quad SOM"
+ select ARCH_IMX6
+
+
endif
# ----------------------------------------------------------
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index b3f00f9cc3..03e5b102fa 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -20,4 +20,5 @@ obj-y += devices.o imx.o esdctl.o
obj-y += boot.o
obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
+obj-$(CONFIG_BAREBOX_UPDATE_IMX6_NAND) += imx6-bbu-nand.o
pbl-y += esdctl.o
diff --git a/arch/arm/mach-imx/clk-imx6.c b/arch/arm/mach-imx/clk-imx6.c
index 5560fff7ce..518fc00d94 100644
--- a/arch/arm/mach-imx/clk-imx6.c
+++ b/arch/arm/mach-imx/clk-imx6.c
@@ -19,6 +19,8 @@
#include <linux/clkdev.h>
#include <linux/err.h>
#include <mach/imx6-regs.h>
+#include <mach/revision.h>
+#include <mach/imx6.h>
#include "clk.h"
@@ -84,8 +86,10 @@ enum mx6q_clks {
usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
pll4_audio, pll5_video, pll8_mlb, pll7_usb_host, pll6_enet, ssi1_ipg,
ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
- sata_ref, pcie_ref, sata_ref_100m, pcie_ref_125m, enet_ref,
- clk_max
+ sata_ref, sata_ref_100m, pcie_ref, pcie_ref_125m, enet_ref, usbphy1_gate,
+ usbphy2_gate, pll4_post_div, pll5_post_div, pll5_video_div, eim_slow,
+ spdif, cko2_sel, cko2_podf, cko2, cko, vdoa, pll4_audio_div,
+ lvds1_sel, lvds2_sel, lvds1_gate, lvds2_gate, clk_max
};
static struct clk *clks[clk_max];
@@ -171,6 +175,62 @@ static const char *cko1_sels[] = {
"pll4_audio",
};
+static const char *ipu_sels[] = {
+ "mmdc_ch0_axi_podf",
+ "pll2_pfd2_396m",
+ "pll3_120m",
+ "pll3_pfd1_540m",
+};
+
+static const char *ldb_di_sels[] = {
+ "pll5_video_div",
+ "pll2_pfd0_352m",
+ "pll2_pfd2_396m",
+ "mmdc_ch1_axi_podf",
+ "pll3_usb_otg",
+};
+
+static const char *ipu_di_pre_sels[] = {
+ "mmdc_ch0_axi",
+ "pll3_usb_otg",
+ "pll5_video_div",
+ "pll2_pfd0_352m",
+ "pll2_pfd2_396m",
+ "pll3_pfd1_540m",
+};
+
+static const char *ipu1_di0_sels[] = {
+ "ipu1_di0_pre",
+ "dummy",
+ "dummy",
+ "ldb_di0_podf",
+ "ldb_di1_podf",
+};
+
+static const char *ipu1_di1_sels[] = {
+ "ipu1_di1_pre",
+ "dummy",
+ "dummy",
+ "ldb_di0_podf",
+ "ldb_di1_podf",
+};
+
+static const char *ipu2_di0_sels[] = {
+ "ipu2_di0_pre",
+ "dummy",
+ "dummy",
+ "ldb_di0_podf",
+ "ldb_di1_podf",
+};
+
+static const char *ipu2_di1_sels[] = {
+ "ipu2_di1_pre",
+ "dummy",
+ "dummy",
+ "ldb_di0_podf",
+ "ldb_di1_podf",
+};
+
static struct clk_div_table clk_enet_ref_table[] = {
{ .val = 0, .div = 20, },
{ .val = 1, .div = 10, },
@@ -179,6 +239,86 @@ static struct clk_div_table clk_enet_ref_table[] = {
{ },
};
+static struct clk_div_table post_div_table[] = {
+ { .val = 2, .div = 1, },
+ { .val = 1, .div = 2, },
+ { .val = 0, .div = 4, },
+ { /* sentinel */ }
+};
+
+static struct clk_div_table video_div_table[] = {
+ { .val = 0, .div = 1, },
+ { .val = 1, .div = 2, },
+ { .val = 2, .div = 1, },
+ { .val = 3, .div = 4, },
+ { /* sentinel */ }
+};
+
+static void imx6_add_video_clks(void __iomem *anab, void __iomem *cb)
+{
+ clks[pll5_post_div] = imx_clk_divider_table("pll5_post_div", "pll5_video", anab + 0xa0, 19, 2, post_div_table);
+ clks[pll5_video_div] = imx_clk_divider_table("pll5_video_div", "pll5_post_div", anab + 0x170, 30, 2, video_div_table);
+
+ clks[ipu1_sel] = imx_clk_mux("ipu1_sel", cb + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
+ clks[ipu2_sel] = imx_clk_mux("ipu2_sel", cb + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
+ clks[ldb_di0_sel] = imx_clk_mux_p("ldb_di0_sel", cb + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
+ clks[ldb_di1_sel] = imx_clk_mux_p("ldb_di1_sel", cb + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
+ clks[ipu1_di0_pre_sel] = imx_clk_mux_p("ipu1_di0_pre_sel", cb + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
+ clks[ipu1_di1_pre_sel] = imx_clk_mux_p("ipu1_di1_pre_sel", cb + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
+ clks[ipu2_di0_pre_sel] = imx_clk_mux_p("ipu2_di0_pre_sel", cb + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
+ clks[ipu2_di1_pre_sel] = imx_clk_mux_p("ipu2_di1_pre_sel", cb + 0x38, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels));
+ clks[ipu1_di0_sel] = imx_clk_mux_p("ipu1_di0_sel", cb + 0x34, 0, 3, ipu1_di0_sels, ARRAY_SIZE(ipu1_di0_sels));
+ clks[ipu1_di1_sel] = imx_clk_mux_p("ipu1_di1_sel", cb + 0x34, 9, 3, ipu1_di1_sels, ARRAY_SIZE(ipu1_di1_sels));
+ clks[ipu2_di0_sel] = imx_clk_mux_p("ipu2_di0_sel", cb + 0x38, 0, 3, ipu2_di0_sels, ARRAY_SIZE(ipu2_di0_sels));
+ clks[ipu2_di1_sel] = imx_clk_mux_p("ipu2_di1_sel", cb + 0x38, 9, 3, ipu2_di1_sels, ARRAY_SIZE(ipu2_di1_sels));
+
+ clks[ipu1_podf] = imx_clk_divider("ipu1_podf", "ipu1_sel", cb + 0x3c, 11, 3);
+ clks[ipu2_podf] = imx_clk_divider("ipu2_podf", "ipu2_sel", cb + 0x3c, 16, 3);
+ clks[ldb_di0_div_3_5] = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+ clks[ldb_di0_podf] = imx_clk_divider("ldb_di0_podf", "ldb_di0_div_3_5", cb + 0x20, 10, 1);
+ clks[ldb_di1_div_3_5] = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+ clks[ldb_di1_podf] = imx_clk_divider("ldb_di1_podf", "ldb_di1_div_3_5", cb + 0x20, 11, 1);
+ clks[ipu1_di0_pre] = imx_clk_divider("ipu1_di0_pre", "ipu1_di0_pre_sel", cb + 0x34, 3, 3);
+ clks[ipu1_di1_pre] = imx_clk_divider("ipu1_di1_pre", "ipu1_di1_pre_sel", cb + 0x34, 12, 3);
+ clks[ipu2_di0_pre] = imx_clk_divider("ipu2_di0_pre", "ipu2_di0_pre_sel", cb + 0x38, 3, 3);
+ clks[ipu2_di1_pre] = imx_clk_divider("ipu2_di1_pre", "ipu2_di1_pre_sel", cb + 0x38, 12, 3);
+
+ clkdev_add_physbase(clks[ipu1_podf], MX6_IPU1_BASE_ADDR, "bus");
+ clkdev_add_physbase(clks[ipu1_di0_sel], MX6_IPU1_BASE_ADDR, "di0");
+ clkdev_add_physbase(clks[ipu1_di1_sel], MX6_IPU1_BASE_ADDR, "di1");
+ clkdev_add_physbase(clks[ipu2_podf], MX6_IPU2_BASE_ADDR, "bus");
+ clkdev_add_physbase(clks[ipu2_di0_sel], MX6_IPU2_BASE_ADDR, "di0");
+ clkdev_add_physbase(clks[ipu2_di1_sel], MX6_IPU2_BASE_ADDR, "di1");
+
+ clkdev_add_physbase(clks[ldb_di0_sel], 0x020e0008, "di0_pll");
+ clkdev_add_physbase(clks[ldb_di1_sel], 0x020e0008, "di1_pll");
+ clkdev_add_physbase(clks[ipu1_di0_sel], 0x020e0008, "di0_sel");
+ clkdev_add_physbase(clks[ipu1_di1_sel], 0x020e0008, "di1_sel");
+ clkdev_add_physbase(clks[ipu2_di0_sel], 0x020e0008, "di2_sel");
+ clkdev_add_physbase(clks[ipu2_di1_sel], 0x020e0008, "di3_sel");
+ clkdev_add_physbase(clks[ldb_di0], 0x020e0008, "di0");
+ clkdev_add_physbase(clks[ldb_di1], 0x020e0008, "di1");
+ clkdev_add_physbase(clks[ahb], 0x00120000, "iahb");
+ clkdev_add_physbase(clks[pll3_pfd1_540m], 0x00120000, "isfr");
+
+ clk_set_parent(clks[ipu1_di0_sel], clks[ipu1_di0_pre]);
+ clk_set_parent(clks[ipu1_di1_sel], clks[ipu1_di1_pre]);
+ clk_set_parent(clks[ipu2_di0_sel], clks[ipu2_di0_pre]);
+ clk_set_parent(clks[ipu2_di1_sel], clks[ipu2_di1_pre]);
+
+ clk_set_parent(clks[ipu1_di0_pre_sel], clks[pll5_video_div]);
+ clk_set_parent(clks[ipu1_di1_pre_sel], clks[pll5_video_div]);
+ clk_set_parent(clks[ipu2_di0_pre_sel], clks[pll5_video_div]);
+ clk_set_parent(clks[ipu2_di1_pre_sel], clks[pll5_video_div]);
+
+ if ((imx_silicon_revision() != IMX_CHIP_REV_1_0) ||
+ cpu_is_mx6dl()) {
+ clk_set_parent(clks[ldb_di0_sel], clks[pll5_video_div]);
+ clk_set_parent(clks[ldb_di1_sel], clks[pll5_video_div]);
+ }
+
+}
+
static int imx6_ccm_probe(struct device_d *dev)
{
void __iomem *base, *anatop_base, *ccm_base;
@@ -214,7 +354,7 @@ static int imx6_ccm_probe(struct device_d *dev)
clks[sata_ref_100m] = imx_clk_gate("sata_ref_100m", "sata_ref", base + 0xe0, 20);
clks[pcie_ref_125m] = imx_clk_gate("pcie_ref_125m", "pcie_ref", base + 0xe0, 19);
- clks[enet_ref] = clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table);
+ clks[enet_ref] = imx_clk_divider_table("enet_ref", "pll6_enet", base + 0xe0, 0, 2, clk_enet_ref_table);
/* name parent_name reg idx */
clks[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus", base + 0x100, 0);
@@ -281,7 +421,6 @@ static int imx6_ccm_probe(struct device_d *dev)
clks[arm] = imx_clk_busy_divider("arm", "pll1_sw", base + 0x10, 0, 3, base + 0x48, 16);
clks[ahb] = imx_clk_busy_divider("ahb", "periph", base + 0x14, 10, 3, base + 0x48, 1);
-
clkdev_add_physbase(clks[uart_serial_podf], MX6_UART1_BASE_ADDR, NULL);
clkdev_add_physbase(clks[uart_serial_podf], MX6_UART2_BASE_ADDR, NULL);
clkdev_add_physbase(clks[uart_serial_podf], MX6_UART3_BASE_ADDR, NULL);
@@ -310,10 +449,16 @@ static int imx6_ccm_probe(struct device_d *dev)
clkdev_add_physbase(clks[ipg_per], MX6_PWM3_BASE_ADDR, "per");
clkdev_add_physbase(clks[ipg_per], MX6_PWM4_BASE_ADDR, "per");
+ if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
+ imx6_add_video_clks(anatop_base, ccm_base);
+
writel(0xffffffff, ccm_base + CCGR0);
writel(0xf0ffffff, ccm_base + CCGR1); /* gate GPU3D, GPU2D */
writel(0xffffffff, ccm_base + CCGR2);
- writel(0x3fff0000, ccm_base + CCGR3); /* gate OpenVG, LDB, IPU1, IPU2 */
+ if (IS_ENABLED(CONFIG_DRIVER_VIDEO_IMX_IPUV3))
+ writel(0xffffffff, ccm_base + CCGR3); /* gate OpenVG */
+ else
+ writel(0x3fffffff, ccm_base + CCGR3); /* gate OpenVG, LDB, IPU1, IPU2 */
writel(0xffffffff, ccm_base + CCGR4);
writel(0xffffffff, ccm_base + CCGR5);
writel(0xffff3fff, ccm_base + CCGR6); /* gate VPU */
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index 4a7298d846..32a02db178 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -4,25 +4,39 @@
static inline struct clk *imx_clk_divider(const char *name, const char *parent,
void __iomem *reg, u8 shift, u8 width)
{
- return clk_divider(name, parent, reg, shift, width);
+ return clk_divider(name, parent, reg, shift, width, CLK_SET_RATE_PARENT);
+}
+
+static inline struct clk *imx_clk_divider_table(const char *name,
+ const char *parent, void __iomem *reg, u8 shift, u8 width,
+ const struct clk_div_table *table)
+{
+ return clk_divider_table(name, parent, reg, shift, width, table,
+ CLK_SET_RATE_PARENT);
}
static inline struct clk *imx_clk_fixed_factor(const char *name,
const char *parent, unsigned int mult, unsigned int div)
{
- return clk_fixed_factor(name, parent, mult, div);
+ return clk_fixed_factor(name, parent, mult, div, CLK_SET_RATE_PARENT);
}
static inline struct clk *imx_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parents, u8 num_parents)
{
- return clk_mux(name, reg, shift, width, parents, num_parents);
+ return clk_mux(name, reg, shift, width, parents, num_parents, 0);
+}
+
+static inline struct clk *imx_clk_mux_p(const char *name, void __iomem *reg,
+ u8 shift, u8 width, const char **parents, u8 num_parents)
+{
+ return clk_mux(name, reg, shift, width, parents, num_parents, CLK_SET_RATE_PARENT);
}
static inline struct clk *imx_clk_gate(const char *name, const char *parent,
void __iomem *reg, u8 shift)
{
- return clk_gate(name, parent, reg, shift);
+ return clk_gate(name, parent, reg, shift, CLK_SET_RATE_PARENT);
}
struct clk *imx_clk_pllv1(const char *name, const char *parent,
diff --git a/arch/arm/mach-imx/imx6-bbu-nand.c b/arch/arm/mach-imx/imx6-bbu-nand.c
new file mode 100644
index 0000000000..2d0705956c
--- /dev/null
+++ b/arch/arm/mach-imx/imx6-bbu-nand.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (C) 2014 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) "imx6-bbu-nand: " fmt
+
+#include <filetype.h>
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ioctl.h>
+#include <sizes.h>
+#include <bbu.h>
+#include <fs.h>
+#include <mach/bbu.h>
+#include <linux/mtd/mtd-abi.h>
+#include <linux/mtd/mtd.h>
+#include <linux/stat.h>
+
+struct dbbt_block {
+ uint32_t Checksum;
+ uint32_t FingerPrint;
+ uint32_t Version;
+ uint32_t reserved;
+ uint32_t DBBTNumOfPages;
+};
+
+struct fcb_block {
+ uint32_t Checksum; /* First fingerprint in first byte */
+ uint32_t FingerPrint; /* 2nd fingerprint at byte 4 */
+ uint32_t Version; /* 3rd fingerprint at byte 8 */
+ uint8_t DataSetup;
+ uint8_t DataHold;
+ uint8_t AddressSetup;
+ uint8_t DSAMPLE_TIME;
+ /* These are for application use only and not for ROM. */
+ uint8_t NandTimingState;
+ uint8_t REA;
+ uint8_t RLOH;
+ uint8_t RHOH;
+ uint32_t PageDataSize; /* 2048 for 2K pages, 4096 for 4K pages */
+ uint32_t TotalPageSize; /* 2112 for 2K pages, 4314 for 4K pages */
+ uint32_t SectorsPerBlock; /* Number of 2K sections per block */
+ uint32_t NumberOfNANDs; /* Total Number of NANDs - not used by ROM */
+ uint32_t TotalInternalDie; /* Number of separate chips in this NAND */
+ uint32_t CellType; /* MLC or SLC */
+ uint32_t EccBlockNEccType; /* Type of ECC, can be one of BCH-0-20 */
+ uint32_t EccBlock0Size; /* Number of bytes for Block0 - BCH */
+ uint32_t EccBlockNSize; /* Block size in bytes for all blocks other than Block0 - BCH */
+ uint32_t EccBlock0EccType; /* Ecc level for Block 0 - BCH */
+ uint32_t MetadataBytes; /* Metadata size - BCH */
+ uint32_t NumEccBlocksPerPage; /* Number of blocks per page for ROM use - BCH */
+ uint32_t EccBlockNEccLevelSDK; /* Type of ECC, can be one of BCH-0-20 */
+ uint32_t EccBlock0SizeSDK; /* Number of bytes for Block0 - BCH */
+ uint32_t EccBlockNSizeSDK; /* Block size in bytes for all blocks other than Block0 - BCH */
+ uint32_t EccBlock0EccLevelSDK; /* Ecc level for Block 0 - BCH */
+ uint32_t NumEccBlocksPerPageSDK;/* Number of blocks per page for SDK use - BCH */
+ uint32_t MetadataBytesSDK; /* Metadata size - BCH */
+ uint32_t EraseThreshold; /* To set into BCH_MODE register */
+ uint32_t BootPatch; /* 0 for normal boot and 1 to load patch starting next to FCB */
+ uint32_t PatchSectors; /* Size of patch in sectors */
+ uint32_t Firmware1_startingPage;/* Firmware image starts on this sector */
+ uint32_t Firmware2_startingPage;/* Secondary FW Image starting Sector */
+ uint32_t PagesInFirmware1; /* Number of sectors in firmware image */
+ uint32_t PagesInFirmware2; /* Number of sector in secondary FW image */
+ uint32_t DBBTSearchAreaStartAddress; /* Page address where dbbt search area begins */
+ uint32_t BadBlockMarkerByte; /* Byte in page data that have manufacturer marked bad block marker, */
+ /* this will be swapped with metadata[0] to complete page data. */
+ uint32_t BadBlockMarkerStartBit;/* For BCH ECC sizes other than 8 and 16 the bad block marker does not */
+ /* start at 0th bit of BadBlockMarkerByte. This field is used to get to */
+ /* the start bit of bad block marker byte with in BadBlockMarkerByte */
+ uint32_t BBMarkerPhysicalOffset;/* FCB value that gives byte offset for bad block marker on physical NAND page */
+ uint32_t BCHType;
+
+ uint32_t TMTiming2_ReadLatency;
+ uint32_t TMTiming2_PreambleDelay;
+ uint32_t TMTiming2_CEDelay;
+ uint32_t TMTiming2_PostambleDelay;
+ uint32_t TMTiming2_CmdAddPause;
+ uint32_t TMTiming2_DataPause;
+ uint32_t TMSpeed;
+ uint32_t TMTiming1_BusyTimeout;
+
+ uint32_t DISBBM; /* the flag to enable (1)/disable(0) bi swap */
+ uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
+};
+
+#define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
+#define GETBIT(v,n) (((v) >> (n)) & 0x1)
+
+static uint8_t calculate_parity_13_8(uint8_t d)
+{
+ uint8_t p = 0;
+
+ p |= (GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 3) ^ GETBIT(d, 2)) << 0;
+ p |= (GETBIT(d, 7) ^ GETBIT(d, 5) ^ GETBIT(d, 4) ^ GETBIT(d, 2) ^ GETBIT(d, 1)) << 1;
+ p |= (GETBIT(d, 7) ^ GETBIT(d, 6) ^ GETBIT(d, 5) ^ GETBIT(d, 1) ^ GETBIT(d, 0)) << 2;
+ p |= (GETBIT(d, 7) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 0)) << 3;
+ p |= (GETBIT(d, 6) ^ GETBIT(d, 4) ^ GETBIT(d, 3) ^ GETBIT(d, 2) ^ GETBIT(d, 1) ^ GETBIT(d, 0)) << 4;
+ return p;
+}
+
+static void encode_hamming_13_8(void *_src, void *_ecc, size_t size)
+{
+ int i;
+ uint8_t *src = _src;
+ uint8_t *ecc = _ecc;
+
+ for (i = 0; i < size; i++)
+ ecc[i] = calculate_parity_13_8(src[i]);
+}
+
+static uint32_t calc_chksum(void *buf, size_t size)
+{
+ u32 chksum = 0;
+ u8 *bp = buf;
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ chksum += bp[i];
+
+ return ~chksum;
+}
+
+static __maybe_unused void dump_fcb(void *buf)
+{
+ struct fcb_block *fcb = buf;
+
+ pr_debug("Checksum: 0x%08x\n", fcb->Checksum);
+ pr_debug("FingerPrint: 0x%08x\n", fcb->FingerPrint);
+ pr_debug("Version: 0x%08x\n", fcb->Version);
+ pr_debug("DataSetup: 0x%02x\n", fcb->DataSetup);
+ pr_debug("DataHold: 0x%02x\n", fcb->DataHold);
+ pr_debug("AddressSetup: 0x%02x\n", fcb->AddressSetup);
+ pr_debug("DSAMPLE_TIME: 0x%02x\n", fcb->DSAMPLE_TIME);
+ pr_debug("NandTimingState: 0x%02x\n", fcb->NandTimingState);
+ pr_debug("REA: 0x%02x\n", fcb->REA);
+ pr_debug("RLOH: 0x%02x\n", fcb->RLOH);
+ pr_debug("RHOH: 0x%02x\n", fcb->RHOH);
+ pr_debug("PageDataSize: 0x%08x\n", fcb->PageDataSize);
+ pr_debug("TotalPageSize: 0x%08x\n", fcb->TotalPageSize);
+ pr_debug("SectorsPerBlock: 0x%08x\n", fcb->SectorsPerBlock);
+ pr_debug("NumberOfNANDs: 0x%08x\n", fcb->NumberOfNANDs);
+ pr_debug("TotalInternalDie: 0x%08x\n", fcb->TotalInternalDie);
+ pr_debug("CellType: 0x%08x\n", fcb->CellType);
+ pr_debug("EccBlockNEccType: 0x%08x\n", fcb->EccBlockNEccType);
+ pr_debug("EccBlock0Size: 0x%08x\n", fcb->EccBlock0Size);
+ pr_debug("EccBlockNSize: 0x%08x\n", fcb->EccBlockNSize);
+ pr_debug("EccBlock0EccType: 0x%08x\n", fcb->EccBlock0EccType);
+ pr_debug("MetadataBytes: 0x%08x\n", fcb->MetadataBytes);
+ pr_debug("NumEccBlocksPerPage: 0x%08x\n", fcb->NumEccBlocksPerPage);
+ pr_debug("EccBlockNEccLevelSDK: 0x%08x\n", fcb->EccBlockNEccLevelSDK);
+ pr_debug("EccBlock0SizeSDK: 0x%08x\n", fcb->EccBlock0SizeSDK);
+ pr_debug("EccBlockNSizeSDK: 0x%08x\n", fcb->EccBlockNSizeSDK);
+ pr_debug("EccBlock0EccLevelSDK: 0x%08x\n", fcb->EccBlock0EccLevelSDK);
+ pr_debug("NumEccBlocksPerPageSDK: 0x%08x\n", fcb->NumEccBlocksPerPageSDK);
+ pr_debug("MetadataBytesSDK: 0x%08x\n", fcb->MetadataBytesSDK);
+ pr_debug("EraseThreshold: 0x%08x\n", fcb->EraseThreshold);
+ pr_debug("BootPatch: 0x%08x\n", fcb->BootPatch);
+ pr_debug("PatchSectors: 0x%08x\n", fcb->PatchSectors);
+ pr_debug("Firmware1_startingPage: 0x%08x\n", fcb->Firmware1_startingPage);
+ pr_debug("Firmware2_startingPage: 0x%08x\n", fcb->Firmware2_startingPage);
+ pr_debug("PagesInFirmware1: 0x%08x\n", fcb->PagesInFirmware1);
+ pr_debug("PagesInFirmware2: 0x%08x\n", fcb->PagesInFirmware2);
+ pr_debug("DBBTSearchAreaStartAddress: 0x%08x\n", fcb->DBBTSearchAreaStartAddress);
+ pr_debug("BadBlockMarkerByte: 0x%08x\n", fcb->BadBlockMarkerByte);
+ pr_debug("BadBlockMarkerStartBit: 0x%08x\n", fcb->BadBlockMarkerStartBit);
+ pr_debug("BBMarkerPhysicalOffset: 0x%08x\n", fcb->BBMarkerPhysicalOffset);
+ pr_debug("BCHType: 0x%08x\n", fcb->BCHType);
+ pr_debug("TMTiming2_ReadLatency: 0x%08x\n", fcb->TMTiming2_ReadLatency);
+ pr_debug("TMTiming2_PreambleDelay: 0x%08x\n", fcb->TMTiming2_PreambleDelay);
+ pr_debug("TMTiming2_CEDelay: 0x%08x\n", fcb->TMTiming2_CEDelay);
+ pr_debug("TMTiming2_PostambleDelay: 0x%08x\n", fcb->TMTiming2_PostambleDelay);
+ pr_debug("TMTiming2_CmdAddPause: 0x%08x\n", fcb->TMTiming2_CmdAddPause);
+ pr_debug("TMTiming2_DataPause: 0x%08x\n", fcb->TMTiming2_DataPause);
+ pr_debug("TMSpeed: 0x%08x\n", fcb->TMSpeed);
+ pr_debug("TMTiming1_BusyTimeout: 0x%08x\n", fcb->TMTiming1_BusyTimeout);
+ pr_debug("DISBBM: 0x%08x\n", fcb->DISBBM);
+ pr_debug("BBMarkerPhysOfsInSpareData: 0x%08x\n", fcb->BBMarkerPhysicalOffsetInSpareData);
+}
+
+static __maybe_unused ssize_t raw_read_page(struct mtd_info *mtd, void *dst, loff_t offset)
+{
+ struct mtd_oob_ops ops;
+ ssize_t ret;
+
+ ops.mode = MTD_OPS_RAW;
+ ops.ooboffs = 0;
+ ops.datbuf = dst;
+ ops.len = mtd->writesize;
+ ops.oobbuf = dst + mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+ ret = mtd_read_oob(mtd, offset, &ops);
+
+ return ret;
+}
+
+static ssize_t raw_write_page(struct mtd_info *mtd, void *buf, loff_t offset)
+{
+ struct mtd_oob_ops ops;
+ ssize_t ret;
+
+ ops.mode = MTD_OPS_RAW;
+ ops.ooboffs = 0;
+ ops.datbuf = buf;
+ ops.len = mtd->writesize;
+ ops.oobbuf = buf + mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+ ret = mtd_write_oob(mtd, offset, &ops);
+
+ return ret;
+}
+
+static int fcb_create(struct fcb_block *fcb, struct mtd_info *mtd)
+{
+ fcb->FingerPrint = 0x20424346;
+ fcb->Version = 0x01000000;
+ fcb->PageDataSize = mtd->writesize;
+ fcb->TotalPageSize = mtd->writesize + mtd->oobsize;
+ fcb->SectorsPerBlock = mtd->erasesize / mtd->writesize;
+
+ if (mtd->writesize == 2048) {
+ fcb->EccBlock0EccType = 4;
+ } else if (mtd->writesize == 4096) {
+ if (mtd->oobsize == 218) {
+ fcb->EccBlock0EccType = 8;
+ } else if (mtd->oobsize == 128) {
+ fcb->EccBlock0EccType = 4;
+ } else {
+ pr_err("Illegal oobsize %d\n", mtd->oobsize);
+ return -EINVAL;
+ }
+ } else {
+ pr_err("Illegal writesize %d\n", mtd->writesize);
+ return -EINVAL;
+ }
+
+ fcb->EccBlockNEccType = fcb->EccBlock0EccType;
+
+ /* Also hardcoded in kobs-ng */
+ fcb->DataSetup = 80;
+ fcb->DataHold = 60;
+ fcb->AddressSetup = 25;
+ fcb->DSAMPLE_TIME = 6;
+ fcb->MetadataBytes = 0x0000000a;
+ fcb->EccBlock0Size = 0x00000200;
+ fcb->EccBlockNSize = 0x00000200;
+
+ fcb->NumEccBlocksPerPage = mtd->writesize / fcb->EccBlock0Size - 1;
+
+ /* DBBT search area starts at third block */
+ fcb->DBBTSearchAreaStartAddress = mtd->erasesize / mtd->writesize * 2;
+
+ if (mtd->writesize == 2048) {
+ fcb->BadBlockMarkerByte = 0x000007cf;
+ } else {
+ pr_err("BadBlockMarkerByte unknown for writesize %d\n", mtd->writesize);
+ return -EINVAL;
+ }
+
+ fcb->BBMarkerPhysicalOffset = mtd->writesize;
+
+ fcb->Checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
+
+ return 0;
+}
+
+static int imx6_bbu_erase(struct mtd_info *mtd)
+{
+ uint64_t offset = 0;
+ int len = SZ_2M;
+ struct erase_info erase;
+ int ret;
+
+ while (len > 0) {
+ pr_debug("erasing at 0x%08llx\n", offset);
+ if (mtd_block_isbad(mtd, offset)) {
+ offset += mtd->erasesize;
+ pr_debug("erase skip block @ 0x%08llx\n", offset);
+ continue;
+ }
+
+ memset(&erase, 0, sizeof(erase));
+ erase.addr = offset;
+ erase.len = mtd->erasesize;
+
+ ret = mtd_erase(mtd, &erase);
+ if (ret)
+ return ret;
+
+ offset += mtd->erasesize;
+ len -= mtd->erasesize;
+ }
+
+ return 0;
+}
+
+static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, size_t len)
+{
+ uint64_t offset = block * mtd->erasesize;
+ int ret;
+ size_t written;
+
+ while (len > 0) {
+ int now = min(len, mtd->erasesize);
+
+ pr_debug("writing %p at 0x%08llx, left 0x%08x\n",
+ buf, offset, len);
+
+ if (mtd_block_isbad(mtd, offset)) {
+ offset += mtd->erasesize;
+ block++;
+ pr_debug("write skip block @ 0x%08llx\n", offset);
+ continue;
+ }
+
+ ret = mtd_write(mtd, offset, now, &written, buf);
+ if (ret)
+ return ret;
+
+ offset += now;
+ len -= now;
+ buf += now;
+ block++;
+ }
+
+ return block;
+}
+
+static int dbbt_data_create(struct mtd_info *mtd, void *buf, int block_last)
+{
+ int n;
+ int n_bad_blocks = 0;
+ uint32_t *bb = buf + 0x8;
+ uint32_t *n_bad_blocksp = buf + 0x4;
+
+ for (n = 0; n <= block_last; n++) {
+ loff_t offset = n * mtd->erasesize;
+ if (mtd_block_isbad(mtd, offset)) {
+ n_bad_blocks++;
+ *bb = n;
+ bb++;
+ }
+ }
+
+ *n_bad_blocksp = n_bad_blocks;
+
+ return n_bad_blocks;
+}
+
+static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *data)
+{
+ struct cdev *bcb_cdev;
+ struct mtd_info *mtd;
+ int ret, block_fw1, block_fw2, block_last;
+ struct fcb_block *fcb;
+ struct dbbt_block *dbbt;
+ void *fcb_raw_page, *dbbt_page, *dbbt_data_page;
+ void *ecc;
+ int written;
+ void *fw;
+ unsigned fw_size;
+ int i;
+
+ if (file_detect_type(data->image, data->len) != filetype_arm_barebox &&
+ !bbu_force(data, "Not an ARM barebox image"))
+ return -EINVAL;
+
+ ret = bbu_confirm(data);
+ if (ret)
+ return ret;
+
+ bcb_cdev = cdev_by_name("nand0");
+ if (!bcb_cdev) {
+ pr_err("%s: No FCB device!\n", __func__);
+ return -ENODEV;
+ }
+
+ mtd = bcb_cdev->mtd;
+
+ fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
+
+ fcb = fcb_raw_page + 12;
+ ecc = fcb_raw_page + 512 + 12;
+
+ dbbt_page = xzalloc(mtd->writesize);
+ dbbt_data_page = xzalloc(mtd->writesize);
+ dbbt = dbbt_page;
+
+ /*
+ * We have to write one additional page to make the ROM happy.
+ * Maybe the PagesInFirmwarex fields are really the number of pages - 1.
+ * kobs-ng has the same.
+ */
+ fw_size = ALIGN(data->len + mtd->writesize, mtd->writesize);
+ fw = xzalloc(fw_size);
+ memcpy(fw, data->image, data->len);
+
+ block_fw1 = 4;
+
+ ret = imx6_bbu_erase(mtd);
+ if (ret)
+ goto out;
+
+ ret = imx6_bbu_write_firmware(mtd, block_fw1, fw, fw_size);
+ if (ret < 0)
+ goto out;
+
+ block_fw2 = ret;
+
+ ret = imx6_bbu_write_firmware(mtd, block_fw2, fw, fw_size);
+ if (ret < 0)
+ goto out;
+
+ block_last = ret;
+
+ fcb->Firmware1_startingPage = block_fw1 * mtd->erasesize / mtd->writesize;
+ fcb->Firmware2_startingPage = block_fw2 * mtd->erasesize / mtd->writesize;
+ fcb->PagesInFirmware1 = ALIGN(data->len, mtd->writesize) / mtd->writesize;
+ fcb->PagesInFirmware2 = fcb->PagesInFirmware1;
+
+ fcb_create(fcb, mtd);
+ encode_hamming_13_8(fcb, ecc, 512);
+ ret = raw_write_page(mtd, fcb_raw_page, 0);
+ if (ret)
+ goto out;
+
+ ret = raw_write_page(mtd, fcb_raw_page, mtd->erasesize);
+ if (ret)
+ goto out;
+
+ dbbt->Checksum = 0;
+ dbbt->FingerPrint = 0x54424244;
+ dbbt->Version = 0x01000000;
+
+ ret = dbbt_data_create(mtd, dbbt_data_page, block_last);
+ if (ret < 0)
+ goto out;
+
+ if (ret > 0)
+ dbbt->DBBTNumOfPages = 1;
+
+ for (i = 2; i < 4; i++) {
+ ret = mtd_write(mtd, mtd->erasesize * i, 2048, &written, dbbt_page);
+ if (ret)
+ goto out;
+
+ if (dbbt->DBBTNumOfPages > 0) {
+ ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize * 4,
+ 2048, &written, dbbt_data_page);
+ if (ret)
+ goto out;
+ }
+ }
+
+out:
+ free(dbbt_page);
+ free(dbbt_data_page);
+ free(fcb_raw_page);
+ free(fw);
+
+ return ret;
+}
+
+int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ struct bbu_handler *handler;
+ int ret;
+
+ handler = xzalloc(sizeof(*handler));
+ handler->devicefile = "/dev/nand0";
+ handler->name = name;
+ handler->flags = flags;
+ handler->handler = imx6_bbu_nand_update;
+
+ ret = bbu_register_handler(handler);
+ if (ret)
+ free(handler);
+
+ return ret;
+}
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 304b1c0f2e..e14ce90b46 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -15,6 +15,7 @@
#include <common.h>
#include <io.h>
#include <sizes.h>
+#include <mfd/imx6q-iomuxc-gpr.h>
#include <mach/imx6.h>
#include <mach/generic.h>
#include <mach/revision.h>
@@ -28,7 +29,9 @@ void imx6_init_lowlevel(void)
{
void __iomem *aips1 = (void *)MX6_AIPS1_ON_BASE_ADDR;
void __iomem *aips2 = (void *)MX6_AIPS2_ON_BASE_ADDR;
+ void __iomem *iomux = (void *)MX6_IOMUXC_BASE_ADDR;
int is_imx6q = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
+ uint32_t val;
/*
* Set all MPROTx to be non-bufferable, trusted for R/W,
@@ -87,6 +90,22 @@ void imx6_init_lowlevel(void)
BM_ANADIG_PFD_528_PFD0_CLKGATE,
MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
+ val = readl(iomux + IOMUXC_GPR4);
+ val |= IMX6Q_GPR4_VPU_WR_CACHE_SEL | IMX6Q_GPR4_VPU_RD_CACHE_SEL |
+ IMX6Q_GPR4_VPU_P_WR_CACHE_VAL | IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
+ IMX6Q_GPR4_IPU_WR_CACHE_CTL | IMX6Q_GPR4_IPU_RD_CACHE_CTL;
+ writel(val, iomux + IOMUXC_GPR4);
+
+ /* Increase IPU read QoS priority */
+ val = readl(iomux + IOMUXC_GPR6);
+ val &= ~(IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK | IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK);
+ val |= (0xf << 16) | (0x7 << 20);
+ writel(val, iomux + IOMUXC_GPR6);
+
+ val = readl(iomux + IOMUXC_GPR7);
+ val &= ~(IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK | IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK);
+ val |= (0xf << 16) | (0x7 << 20);
+ writel(val, iomux + IOMUXC_GPR7);
}
int imx6_init(void)
diff --git a/arch/arm/mach-imx/include/mach/bbu.h b/arch/arm/mach-imx/include/mach/bbu.h
index 3cd3b1e4cf..1644d85250 100644
--- a/arch/arm/mach-imx/include/mach/bbu.h
+++ b/arch/arm/mach-imx/include/mach/bbu.h
@@ -33,6 +33,8 @@ int imx6_bbu_internal_spi_i2c_register_handler(const char *name, char *devicefil
unsigned long flags, struct imx_dcd_v2_entry *dcd, int dcdsize,
unsigned long app_dest);
+int imx6_bbu_nand_register_handler(const char *name, unsigned long flags);
+
#else
static inline int imx51_bbu_internal_mmc_register_handler(const char *name, char *devicefile,
@@ -77,6 +79,10 @@ static inline int imx6_bbu_internal_spi_i2c_register_handler(const char *name, c
return -ENOSYS;
}
+static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ return -ENOSYS;
+}
#endif
#if defined(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND)
diff --git a/arch/arm/mach-imx/include/mach/imx6-regs.h b/arch/arm/mach-imx/include/mach/imx6-regs.h
index 833280af53..facbe51b70 100644
--- a/arch/arm/mach-imx/include/mach/imx6-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx6-regs.h
@@ -26,6 +26,9 @@
#define MX6_SPBA_BASE_ADDR (MX6_ATZ1_BASE_ADDR + 0x3C000)
#define MX6_VPU_BASE_ADDR (MX6_ATZ1_BASE_ADDR + 0x40000)
+#define MX6_IPU1_BASE_ADDR 0x02400000
+#define MX6_IPU2_BASE_ADDR 0x02800000
+
/* ATZ#1- On Platform */
#define MX6_AIPS1_ON_BASE_ADDR (MX6_ATZ1_BASE_ADDR + 0x7C000)
diff --git a/arch/arm/mach-zynq/clk-zynq7000.c b/arch/arm/mach-zynq/clk-zynq7000.c
index 6472c642fd..ea637d7634 100644
--- a/arch/arm/mach-zynq/clk-zynq7000.c
+++ b/arch/arm/mach-zynq/clk-zynq7000.c
@@ -374,11 +374,11 @@ static int zynq_clock_probe(struct device_d *dev)
clks[uart_clk] = zynq_periph_clk("uart_clk", slcr_base + 0x154);
- clks[uart0] = clk_gate("uart0", "uart_clk", slcr_base + 0x154, 0);
- clks[uart1] = clk_gate("uart1", "uart_clk", slcr_base + 0x154, 1);
+ clks[uart0] = clk_gate("uart0", "uart_clk", slcr_base + 0x154, 0, 0);
+ clks[uart1] = clk_gate("uart1", "uart_clk", slcr_base + 0x154, 1, 0);
- clks[gem0] = clk_gate("gem0", "io_pll", slcr_base + 0x140, 0);
- clks[gem1] = clk_gate("gem1", "io_pll", slcr_base + 0x144, 1);
+ clks[gem0] = clk_gate("gem0", "io_pll", slcr_base + 0x140, 0, 0);
+ clks[gem1] = clk_gate("gem1", "io_pll", slcr_base + 0x144, 1, 0);
clks[cpu_clk] = zynq_cpu_clk("cpu_clk", slcr_base + 0x120);
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b819b49d1c..9a240b7822 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -54,6 +54,19 @@ config MACH_MIPS_AR231X
select DRIVER_SERIAL_NS16550
select HAS_DEBUG_LL
+config MACH_MIPS_ATH79
+ bool "Atheros AR71XX/AR724X/AR913X/AR933X based boards"
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select CSRC_R4K_LIB
+ select HAS_DEBUG_LL
+ select HAVE_CLK
+ select COMMON_CLK
+ select COMMON_CLK_OF_PROVIDER
+ select CLKDEV_LOOKUP
+ select OFTREE
+
config MACH_MIPS_BCM47XX
bool "Broadcom BCM47xx-based boards"
select CSRC_R4K_LIB
@@ -80,6 +93,7 @@ endchoice
source arch/mips/mach-malta/Kconfig
source arch/mips/mach-ar231x/Kconfig
+source arch/mips/mach-ath79/Kconfig
source arch/mips/mach-bcm47xx/Kconfig
source arch/mips/mach-loongson/Kconfig
source arch/mips/mach-xburst/Kconfig
diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 8986fcf46f..b3bacf3be1 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -78,6 +78,9 @@ board-$(CONFIG_BOARD_QEMU_MALTA) := qemu-malta
machine-$(CONFIG_MACH_MIPS_AR231X) := ar231x
board-$(CONFIG_BOARD_NETGEAR_WG102) := netgear-wg102
+machine-$(CONFIG_MACH_MIPS_ATH79) := ath79
+board-$(CONFIG_BOARD_TPLINK_MR3020) := tplink-mr3020
+
machine-$(CONFIG_MACH_MIPS_BCM47XX) := bcm47xx
board-$(CONFIG_BOARD_DLINK_DIR320) := dlink-dir-320
@@ -85,7 +88,7 @@ machine-$(CONFIG_MACH_MIPS_LOONGSON) := loongson
board-$(CONFIG_BOARD_LOONGSON_TECH_LS1B) := loongson-ls1b
machine-$(CONFIG_MACH_MIPS_XBURST) := xburst
-board-$(CONFIG_BOARD_RZX50) := rzx50
+board-$(CONFIG_BOARD_RZX50) := ritmix-rzx50
machdirs := $(patsubst %,arch/mips/mach-%/,$(machine-y))
diff --git a/arch/mips/boards/ritmix-rzx50/Makefile b/arch/mips/boards/ritmix-rzx50/Makefile
new file mode 100644
index 0000000000..31c062987f
--- /dev/null
+++ b/arch/mips/boards/ritmix-rzx50/Makefile
@@ -0,0 +1 @@
+obj-y += serial.o
diff --git a/arch/mips/boards/rzx50/include/board/board_pbl_start.h b/arch/mips/boards/ritmix-rzx50/include/board/board_pbl_start.h
index fb914d99f2..fb914d99f2 100644
--- a/arch/mips/boards/rzx50/include/board/board_pbl_start.h
+++ b/arch/mips/boards/ritmix-rzx50/include/board/board_pbl_start.h
diff --git a/arch/mips/boards/rzx50/include/board/debug_ll.h b/arch/mips/boards/ritmix-rzx50/include/board/debug_ll.h
index 7ae0e2a4fd..7ae0e2a4fd 100644
--- a/arch/mips/boards/rzx50/include/board/debug_ll.h
+++ b/arch/mips/boards/ritmix-rzx50/include/board/debug_ll.h
diff --git a/arch/mips/boards/rzx50/rzx50.dox b/arch/mips/boards/ritmix-rzx50/ritmix-rzx50.dox
index 963473cb51..5ec819462b 100644
--- a/arch/mips/boards/rzx50/rzx50.dox
+++ b/arch/mips/boards/ritmix-rzx50/ritmix-rzx50.dox
@@ -1,4 +1,4 @@
-/** @page rzx50 Ritmix RZX-50 game console
+/** @page ritmix-rzx50 Ritmix RZX-50 game console
Ritmix RZX-50 is a portable game console for the Russian market.
diff --git a/arch/mips/boards/rzx50/serial.c b/arch/mips/boards/ritmix-rzx50/serial.c
index 566356aaa5..f1e8da0072 100644
--- a/arch/mips/boards/rzx50/serial.c
+++ b/arch/mips/boards/ritmix-rzx50/serial.c
@@ -17,16 +17,11 @@
#include <common.h>
#include <init.h>
-#include <mach/devices.h>
-#include <mach/jz4750d_regs.h>
-static int rzx50_console_init(void)
+static int rzx50_hostname_init(void)
{
barebox_set_hostname("rzx50");
- /* Register the serial port */
- jz_add_uart(DEVICE_ID_DYNAMIC, UART1_BASE, 12000000);
-
return 0;
}
-console_initcall(rzx50_console_init);
+console_initcall(rzx50_hostname_init);
diff --git a/arch/mips/boards/rzx50/Makefile b/arch/mips/boards/rzx50/Makefile
deleted file mode 100644
index ff1a655afe..0000000000
--- a/arch/mips/boards/rzx50/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial.o
diff --git a/arch/mips/boards/tplink-mr3020/Makefile b/arch/mips/boards/tplink-mr3020/Makefile
new file mode 100644
index 0000000000..dcfc2937d3
--- /dev/null
+++ b/arch/mips/boards/tplink-mr3020/Makefile
@@ -0,0 +1 @@
+obj-y += board.o
diff --git a/arch/mips/boards/tplink-mr3020/board.c b/arch/mips/boards/tplink-mr3020/board.c
new file mode 100644
index 0000000000..318998cc49
--- /dev/null
+++ b/arch/mips/boards/tplink-mr3020/board.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+
+static int model_hostname_init(void)
+{
+ barebox_set_hostname("mr3020");
+
+ return 0;
+}
+postcore_initcall(model_hostname_init);
diff --git a/arch/mips/boards/tplink-mr3020/tplink-mr3020.dox b/arch/mips/boards/tplink-mr3020/tplink-mr3020.dox
new file mode 100644
index 0000000000..16fe4653d8
--- /dev/null
+++ b/arch/mips/boards/tplink-mr3020/tplink-mr3020.dox
@@ -0,0 +1,64 @@
+/** @page tplink-mr3020 TP-LINK MR3020 wireless router
+
+The router has
+@li Atheros ar9331 SoC;
+@li 32 MiB SDRAM;
+@li 4 MiB NOR type SPI Flash Memory;
+@li RS232 serial interface (LV-TTL levels on board!);
+@li 1 USB interface;
+@li 1 Ethernet interfaces;
+@li 802.11b/g/n (WiFi) interface;
+@li LEDs & buttons.
+
+The router uses U-Boot 1.1.4 as firmware.
+
+Barebox can be started from U-Boot using tftp.
+But you have to encode barebox image in a very special way.
+
+First obtain 'lzma' and 'mktplinkfw' utilities.
+
+The 'lzma' utility can be obtained in Debian/Ubuntu
+distro by installing lzma package.
+
+The 'mktplinkfw' utility can be obtained from openwrt, e.g.:
+
+@verbatim
+$ OWRTPREF=https://raw.githubusercontent.com/mirrors/openwrt/master
+$ curl -OL $OWRTPREF/tools/firmware-utils/src/mktplinkfw.c \
+ -OL $OWRTPREF/tools/firmware-utils/src/md5.c \
+ -OL $OWRTPREF/tools/firmware-utils/src/md5.h
+$ cc -o mktplinkfw mktplinkfw.c md5.c
+@endverbatim
+
+To convert your barebox.bin to U-Boot-loadable image (6F01A8C0.img)
+use this command sequence:
+
+@verbatim
+$ lzma -c -k barebox.bin > barebox.lzma
+$ ./FW/mktplinkfw -c -H 0x07200103 -W 1 -N TL-WR720N-v3 \
+ -s -F 4Mlzma -k barebox.lzma -o 6F01A8C0.img
+@endverbatim
+
+You must setup tftp-server on host 192.168.0.1.
+Put your 6F01A8C0.img to tftp-server directory
+(usual /tftpboot or /srv/tftp).
+Connect your board to your tftp-server network via Ethernet.
+
+Next, setup network on MR3020 and run 6F01A8C0.img, e.g.:
+@verbatim
+hornet> set ipaddr 192.168.0.2
+hornet> set serverip 192.168.0.1
+hornet> tftpboot 0x81000000 6F01A8C0.img
+hornet> bootm 0x81000000
+@endverbatim
+
+TP-LINK MR3020 links:
+@li http://www.tp-link.com/en/products/details/?model=TL-MR3020
+@li http://wiki.openwrt.org/toh/tp-link/tl-mr3020
+@li https://wikidevi.com/wiki/TP-LINK_TL-MR3020
+
+See also:
+@li http://www.eeboard.com/wp-content/uploads/downloads/2013/08/AR9331.pdf
+@li http://squonk42.github.io/TL-WR703N/
+
+*/
diff --git a/arch/mips/configs/rzx50_defconfig b/arch/mips/configs/ritmix-rzx50_defconfig
index 7691bae6e6..7691bae6e6 100644
--- a/arch/mips/configs/rzx50_defconfig
+++ b/arch/mips/configs/ritmix-rzx50_defconfig
diff --git a/arch/mips/configs/tplink-mr3020_defconfig b/arch/mips/configs/tplink-mr3020_defconfig
new file mode 100644
index 0000000000..2e925d9e3c
--- /dev/null
+++ b/arch/mips/configs/tplink-mr3020_defconfig
@@ -0,0 +1,29 @@
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="tplink-mr3020"
+CONFIG_MACH_MIPS_ATH79=y
+CONFIG_LONGHELP=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_GLOBAL=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_LOADY=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_SHA1SUM=y
+# CONFIG_CMD_BOOTM is not set
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_CLK=y
+CONFIG_OFDEVICE=y
+CONFIG_DRIVER_SERIAL_AR933X=y
+# CONFIG_SPI is not set
+CONFIG_MD5=y
+CONFIG_SHA224=y
+CONFIG_SHA256=y
diff --git a/arch/mips/dts/ar9331.dtsi b/arch/mips/dts/ar9331.dtsi
new file mode 100644
index 0000000000..890fda8ab5
--- /dev/null
+++ b/arch/mips/dts/ar9331.dtsi
@@ -0,0 +1,26 @@
+#include <dt-bindings/clock/ar933x-clk.h>
+
+#include "skeleton.dtsi"
+
+/ {
+ soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ device_type = "soc";
+ ranges;
+
+ serial0: serial@b8020000 {
+ compatible = "qca,ar9330-uart";
+ reg = <0xb8020000 0x14>;
+ clocks = <&ar9331_clk AR933X_CLK_UART>;
+ status = "disabled";
+ };
+
+ ar9331_clk: clock {
+ compatible = "qca,ar933x-clk";
+ reg = <0xb8050000 0x48>;
+ #clock-cells = <1>;
+ };
+ };
+};
diff --git a/arch/mips/dts/include/dt-bindings b/arch/mips/dts/include/dt-bindings
new file mode 120000
index 0000000000..0cecb3d080
--- /dev/null
+++ b/arch/mips/dts/include/dt-bindings
@@ -0,0 +1 @@
+../../../../include/dt-bindings \ No newline at end of file
diff --git a/arch/mips/dts/jz4755.dtsi b/arch/mips/dts/jz4755.dtsi
new file mode 100644
index 0000000000..44ff912916
--- /dev/null
+++ b/arch/mips/dts/jz4755.dtsi
@@ -0,0 +1,35 @@
+#include "skeleton.dtsi"
+
+/ {
+ soc {
+ compatible = "simple-bus";
+ model = "Ingenic JZ4755";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ serial0: serial@b0030000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0xb0030000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <12000000>;
+ status = "disabled";
+ };
+
+ serial1: serial@b0031000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0xb0031000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <12000000>;
+ status = "disabled";
+ };
+
+ serial2: serial@b0032000 {
+ compatible = "ingenic,jz4740-uart";
+ reg = <0xb0032000 0x20>;
+ reg-shift = <2>;
+ clock-frequency = <12000000>;
+ status = "disabled";
+ };
+ };
+};
diff --git a/arch/mips/dts/qemu-malta.dts b/arch/mips/dts/qemu-malta.dts
index b6b69c4955..67fe591f1f 100644
--- a/arch/mips/dts/qemu-malta.dts
+++ b/arch/mips/dts/qemu-malta.dts
@@ -25,6 +25,14 @@
clock-frequency = <1843200>;
};
+ uart2: serial@bf000900 {
+ compatible = "ns16550a";
+ reg = <0xbf000900 0x40>;
+ reg-shift = <3>;
+ /* no matter for emulated port */
+ clock-frequency = <1843200>;
+ };
+
nor0: flash@be000000 {
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/mips/dts/rzx50.dts b/arch/mips/dts/rzx50.dts
index 69320ddbb3..360c1bf5de 100644
--- a/arch/mips/dts/rzx50.dts
+++ b/arch/mips/dts/rzx50.dts
@@ -1,6 +1,6 @@
/dts-v1/;
-/include/ "skeleton.dtsi"
+#include "jz4755.dtsi"
/ {
model = "Ritmix RZX-50";
@@ -10,3 +10,7 @@
reg = <0x00000000 0x4000000>;
};
};
+
+&serial1 {
+ status = "okay";
+};
diff --git a/arch/mips/dts/tplink-mr3020.dts b/arch/mips/dts/tplink-mr3020.dts
new file mode 100644
index 0000000000..5d613d80bb
--- /dev/null
+++ b/arch/mips/dts/tplink-mr3020.dts
@@ -0,0 +1,16 @@
+/dts-v1/;
+
+#include <ar9331.dtsi>
+
+/ {
+ model = "TP-LINK MR3020";
+ compatible = "tplink,mr3020";
+
+ memory {
+ reg = <0x00000000 0x2000000>;
+ };
+};
+
+&serial0 {
+ status = "okay";
+};
diff --git a/arch/mips/include/asm/debug_ll_ns16550.h b/arch/mips/include/asm/debug_ll_ns16550.h
index f36010ce07..032f0a2869 100644
--- a/arch/mips/include/asm/debug_ll_ns16550.h
+++ b/arch/mips/include/asm/debug_ll_ns16550.h
@@ -59,9 +59,11 @@
static __inline__ void PUTC_LL(char ch)
{
+#ifdef CONFIG_DEBUG_LL
while (!(__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_LSR) & UART_LSR_THRE))
;
__raw_writeb(ch, (u8 *)DEBUG_LL_UART_ADDR + UART_THR);
+#endif /* CONFIG_DEBUG_LL */
}
#else /* __ASSEMBLY__ */
/*
diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S
index bc78d2be8c..4ee4252b6d 100644
--- a/arch/mips/lib/barebox.lds.S
+++ b/arch/mips/lib/barebox.lds.S
@@ -69,6 +69,8 @@ SECTIONS
__usymtab : { BAREBOX_SYMS }
__usymtab_end = .;
+ .oftables : { BAREBOX_CLK_TABLE() }
+
.dtb : { BAREBOX_DTB() }
_edata = .;
diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig
new file mode 100644
index 0000000000..96fffd3fa2
--- /dev/null
+++ b/arch/mips/mach-ath79/Kconfig
@@ -0,0 +1,15 @@
+if MACH_MIPS_ATH79
+
+config ARCH_TEXT_BASE
+ hex
+ default 0xa0800000
+
+choice
+ prompt "Board type"
+
+config BOARD_TPLINK_MR3020
+ bool "TP-LINK MR3020"
+
+endchoice
+
+endif
diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile
new file mode 100644
index 0000000000..f3cc6684b8
--- /dev/null
+++ b/arch/mips/mach-ath79/Makefile
@@ -0,0 +1 @@
+obj-y += reset.o
diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
new file mode 100644
index 0000000000..0c6ddd6388
--- /dev/null
+++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
@@ -0,0 +1,64 @@
+/*
+ * Atheros AR71XX/AR724X/AR913X SoC register definitions
+ *
+ * Copyright (C) 2010-2011 Jaiganesh Narayanan <jnarayanan@atheros.com>
+ * Copyright (C) 2008-2010 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Parts of this file are based on Atheros' 2.6.15/2.6.31 BSP
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_AR71XX_REGS_H
+#define __ASM_MACH_AR71XX_REGS_H
+
+#include <linux/bitops.h>
+
+#define AR71XX_APB_BASE 0x18000000
+
+#define AR71XX_PLL_BASE (AR71XX_APB_BASE + 0x00050000)
+#define AR71XX_PLL_SIZE 0x100
+#define AR71XX_RESET_BASE (AR71XX_APB_BASE + 0x00060000)
+#define AR71XX_RESET_SIZE 0x100
+
+#define AR933X_UART_BASE (AR71XX_APB_BASE + 0x00020000)
+#define AR933X_UART_SIZE 0x14
+
+/*
+ * PLL block
+ */
+#define AR933X_PLL_CPU_CONFIG_REG 0x00
+#define AR933X_PLL_CPU_CONFIG2_REG 0x04
+#define AR933X_PLL_CLOCK_CTRL_REG 0x08
+#define AR933X_PLL_DITHER_FRAC_REG 0x10
+#define AR933X_PLL_DITHER_REG 0x14
+
+#define AR933X_PLL_CPU_CONFIG_NINT_SHIFT 10
+#define AR933X_PLL_CPU_CONFIG_NINT_MASK 0x3f
+#define AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT 16
+#define AR933X_PLL_CPU_CONFIG_REFDIV_MASK 0x1f
+#define AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT 23
+#define AR933X_PLL_CPU_CONFIG_OUTDIV_MASK 0x7
+
+#define AR933X_PLL_CLOCK_CTRL_BYPASS BIT(2)
+#define AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT 5
+#define AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK 0x3
+#define AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT 10
+#define AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK 0x3
+#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT 15
+#define AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK 0x7
+
+/*
+ * RESET block
+ */
+#define AR933X_RESET_REG_RESET_MODULE 0x1c
+#define AR933X_RESET_REG_BOOTSTRAP 0xac
+
+#define AR71XX_RESET_FULL_CHIP BIT(24)
+
+#define AR933X_BOOTSTRAP_REF_CLK_40 BIT(0)
+
+#endif /* __ASM_MACH_AR71XX_REGS_H */
diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h
new file mode 100644
index 0000000000..ff53406fb0
--- /dev/null
+++ b/arch/mips/mach-ath79/include/mach/ath79.h
@@ -0,0 +1,33 @@
+/*
+ * Atheros AR71XX/AR724X/AR913X common definitions
+ *
+ * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_ATH79_H
+#define __ASM_MACH_ATH79_H
+
+#include <common.h>
+#include <io.h>
+#include <asm/memory.h>
+
+#include <mach/ar71xx_regs.h>
+
+static inline void ath79_reset_wr(unsigned reg, u32 val)
+{
+ __raw_writel(val, (char *)KSEG1ADDR(AR71XX_RESET_BASE + reg));
+}
+
+static inline u32 ath79_reset_rr(unsigned reg)
+{
+ return __raw_readl((char *)KSEG1ADDR(AR71XX_RESET_BASE + reg));
+}
+
+#endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/mach-ath79/include/mach/debug_ll.h b/arch/mips/mach-ath79/include/mach/debug_ll.h
new file mode 100644
index 0000000000..de4c00dfd1
--- /dev/null
+++ b/arch/mips/mach-ath79/include/mach/debug_ll.h
@@ -0,0 +1,56 @@
+/*
+ * based on linux.git/drivers/tty/serial/ar933x_uart.c
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __AR933X_DEBUG_LL__
+#define __AR933X_DEBUG_LL__
+
+#include <io.h>
+#include <linux/bitops.h>
+#include <asm/addrspace.h>
+
+#include <mach/ar71xx_regs.h>
+
+#define AR933X_UART_DATA_REG 0x00
+#define AR933X_UART_DATA_TX_RX_MASK 0xff
+#define AR933X_UART_DATA_TX_CSR BIT(9)
+
+#define DEBUG_LL_UART_ADDR KSEG1ADDR(AR933X_UART_BASE)
+
+static inline void ar933x_debug_ll_writel(u32 b, int offset)
+{
+ cpu_writel(b, (u8 *)DEBUG_LL_UART_ADDR + offset);
+}
+
+static inline u32 ar933x_debug_ll_readl(int offset)
+{
+ return cpu_readl((u8 *)DEBUG_LL_UART_ADDR + offset);
+}
+
+static inline void PUTC_LL(int ch)
+{
+ u32 data;
+
+ /* wait transmitter ready */
+ data = ar933x_debug_ll_readl(AR933X_UART_DATA_REG);
+ while (!(data & AR933X_UART_DATA_TX_CSR))
+ data = ar933x_debug_ll_readl(AR933X_UART_DATA_REG);
+
+ data = (ch & AR933X_UART_DATA_TX_RX_MASK) | AR933X_UART_DATA_TX_CSR;
+ ar933x_debug_ll_writel(data, AR933X_UART_DATA_REG);
+}
+
+#endif /* __AR933X_DEBUG_LL__ */
diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
new file mode 100644
index 0000000000..a0e9b349ca
--- /dev/null
+++ b/arch/mips/mach-ath79/reset.c
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013 Du Huanpeng <u74147@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <mach/ath79.h>
+
+void __noreturn reset_cpu(ulong addr)
+{
+ ath79_reset_wr(AR933X_RESET_REG_RESET_MODULE, AR71XX_RESET_FULL_CHIP);
+ /*
+ * Used to command a full chip reset. This is the software equivalent of
+ * pulling the reset pin. The system will reboot with PLL disabled.
+ * Always zero when read.
+ */
+ unreachable();
+ /*NOTREACHED*/
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/mips/mach-malta/include/mach/hardware.h b/arch/mips/mach-malta/include/mach/hardware.h
index 9345a67593..ba28cb86de 100644
--- a/arch/mips/mach-malta/include/mach/hardware.h
+++ b/arch/mips/mach-malta/include/mach/hardware.h
@@ -20,6 +20,9 @@
#define MALTA_PIIX4_UART0 0xb80003f8
+#define MALTA_CBUS_UART 0xbf000900
+#define MALTA_CBUS_UART_SHIFT 3
+
/*
* Reset register.
*/
diff --git a/arch/mips/mach-xburst/Makefile b/arch/mips/mach-xburst/Makefile
index 3e0cd7324e..e5634ba9cc 100644
--- a/arch/mips/mach-xburst/Makefile
+++ b/arch/mips/mach-xburst/Makefile
@@ -1,2 +1 @@
-obj-y += serial.o
obj-$(CONFIG_CPU_JZ4755) += csrc-jz4750.o reset-jz4750.o
diff --git a/arch/mips/mach-xburst/mach-xburst.dox b/arch/mips/mach-xburst/mach-xburst.dox
index a5e524d25c..052c05e7ae 100644
--- a/arch/mips/mach-xburst/mach-xburst.dox
+++ b/arch/mips/mach-xburst/mach-xburst.dox
@@ -2,6 +2,6 @@
@section xburst_boards XBurst-based boards
-@li @subpage rzx50
+@li @subpage ritmix-rzx50
*/
diff --git a/arch/mips/mach-xburst/serial.c b/arch/mips/mach-xburst/serial.c
deleted file mode 100644
index acf5648467..0000000000
--- a/arch/mips/mach-xburst/serial.c
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
- *
- * Based on the linux kernel JZ4740 serial support:
- * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
- *
- * This file is part of barebox.
- * See file CREDITS for list of people who contributed to this project.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#include <common.h>
-#include <ns16550.h>
-#include <io.h>
-#include <mach/devices.h>
-
-#define JZ_UART_SHIFT 2
-
-#define ier (1 << JZ_UART_SHIFT)
-#define fcr (2 << JZ_UART_SHIFT)
-
-static void jz_serial_reg_write(unsigned int val, unsigned long base,
- unsigned char reg_offset)
-{
- switch (reg_offset) {
- case fcr:
- val |= 0x10; /* Enable uart module */
- break;
- case ier:
- val |= (val & 0x4) << 2;
- break;
- default:
- break;
- }
-
- writeb(val & 0xff, (void *)(base + reg_offset));
-}
-
-struct device_d *jz_add_uart(int id, unsigned long base, unsigned int clock)
-{
- struct NS16550_plat *serial_plat;
-
- serial_plat = xzalloc(sizeof(*serial_plat));
-
- serial_plat->shift = JZ_UART_SHIFT;
- serial_plat->reg_write = &jz_serial_reg_write;
- serial_plat->clock = clock;
-
- return add_ns16550_device(id, base, 8 << JZ_UART_SHIFT,
- IORESOURCE_MEM_8BIT, serial_plat);
-}
diff --git a/commands/Kconfig b/commands/Kconfig
index 352e8bf46f..cc014f30ac 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -90,6 +90,14 @@ config CMD_MENU_MANAGEMENT
depends on CMD_MENU
prompt "menu scripts management"
+config CMD_MENUTREE
+ bool
+ depends on MENU
+ select MENUTREE
+ prompt "menutree"
+ help
+ The menutree command allows to create a menu from a directory structure
+
config CMD_LOGIN
tristate
select PASSWORD
diff --git a/commands/Makefile b/commands/Makefile
index 91ec0e9fa9..e463031455 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -94,3 +94,4 @@ obj-$(CONFIG_CMD_DETECT) += detect.o
obj-$(CONFIG_CMD_BOOT) += boot.o
obj-$(CONFIG_CMD_DEVINFO) += devinfo.o
obj-$(CONFIG_CMD_READF) += readf.o
+obj-$(CONFIG_CMD_MENUTREE) += menutree.o
diff --git a/commands/boot.c b/commands/boot.c
index bb8d07fce4..4a839790d1 100644
--- a/commands/boot.c
+++ b/commands/boot.c
@@ -106,6 +106,11 @@ static void bootsource_action(struct menu *m, struct menu_entry *me)
static int bootscript_create_entry(struct blspec *blspec, const char *name)
{
struct blspec_entry *be;
+ enum filetype type;
+
+ type = file_name_detect_type(name);
+ if (type != filetype_sh)
+ return -EINVAL;
be = blspec_entry_alloc(blspec);
be->me.type = MENU_ENTRY_NORMAL;
@@ -238,7 +243,7 @@ static struct blspec *bootentries_collect(char *entries[], int num_entries)
static void bootsources_menu(char *entries[], int num_entries)
{
struct blspec *blspec = NULL;
- struct blspec_entry *entry;
+ struct blspec_entry *entry, *entry_default;
struct menu_entry *back_entry;
if (!IS_ENABLED(CONFIG_MENU)) {
@@ -247,10 +252,16 @@ static void bootsources_menu(char *entries[], int num_entries)
}
blspec = bootentries_collect(entries, num_entries);
+ if (blspec)
+ return;
+
+ entry_default = blspec_entry_default(blspec);
blspec_for_each_entry(blspec, entry) {
entry->me.action = bootsource_action;
menu_add_entry(blspec->menu, &entry->me);
+ if (entry == entry_default)
+ menu_set_selected_entry(blspec->menu, &entry->me);
}
back_entry = xzalloc(sizeof(*back_entry));
@@ -275,14 +286,23 @@ static void bootsources_menu(char *entries[], int num_entries)
static void bootsources_list(char *entries[], int num_entries)
{
struct blspec *blspec;
- struct blspec_entry *entry;
+ struct blspec_entry *entry, *entry_default;
blspec = bootentries_collect(entries, num_entries);
+ if (!blspec)
+ return;
+
+ entry_default = blspec_entry_default(blspec);
- printf("%-20s %-20s %s\n", "device", "hwdevice", "title");
- printf("%-20s %-20s %s\n", "------", "--------", "-----");
+ printf(" %-20s %-20s %s\n", "device", "hwdevice", "title");
+ printf(" %-20s %-20s %s\n", "------", "--------", "-----");
blspec_for_each_entry(blspec, entry) {
+ if (entry == entry_default)
+ printf("* ");
+ else
+ printf(" ");
+
if (entry->scriptpath)
printf("%-40s %s\n", basename(entry->scriptpath), entry->me.display);
else
@@ -307,7 +327,7 @@ static void bootsources_list(char *entries[], int num_entries)
static int boot(const char *name)
{
struct blspec *blspec;
- struct blspec_entry *entry;
+ struct blspec_entry *entry, *entry_default;
int ret;
blspec = blspec_alloc();
@@ -320,7 +340,19 @@ static int boot(const char *name)
return -ENOENT;
}
+ entry_default = blspec_entry_default(blspec);
+ if (entry_default) {
+ ret = boot_entry(entry_default);
+ if (!ret)
+ return ret;
+ printf("booting %s failed: %s\n", entry_default->me.display,
+ strerror(-ret));
+ }
+
blspec_for_each_entry(blspec, entry) {
+ if (entry == entry_default)
+ continue;
+
printf("booting %s\n", entry->me.display);
ret = boot_entry(entry);
if (!ret)
@@ -333,9 +365,11 @@ static int boot(const char *name)
static int do_boot(int argc, char *argv[])
{
- const char *sources = NULL;
- char *source, *freep;
+ char *freep = NULL;
int opt, ret = 0, do_list = 0, do_menu = 0;
+ char **sources;
+ int num_sources;
+ int i;
verbose = 0;
dryrun = 0;
@@ -361,47 +395,62 @@ static int do_boot(int argc, char *argv[])
}
}
- if (do_list) {
- bootsources_list(&argv[optind], argc - optind);
- return 0;
- }
+ if (optind < argc) {
+ num_sources = argc - optind;
+ sources = xmemdup(&argv[optind], sizeof(char *) * num_sources);
+ } else {
+ const char *def;
+ char *sep;
- if (do_menu) {
- bootsources_menu(&argv[optind], argc - optind);
- return 0;
- }
+ def = getenv("global.boot.default");
+ if (!def)
+ return 0;
- if (optind < argc) {
- while (optind < argc) {
- source = argv[optind];
- optind++;
- ret = boot(source);
- if (!ret)
+ sep = freep = xstrdup(def);
+
+ num_sources = 0;
+
+ while (1) {
+ num_sources++;
+
+ sep = strchr(sep, ' ');
+ if (!sep)
break;
+ sep++;
+ }
+
+ sources = xmalloc(sizeof(char *) * num_sources);
+
+ sep = freep;
+
+ for (i = 0; i < num_sources; i++) {
+ sources[i] = sep;
+ sep = strchr(sep, ' ');
+ if (sep)
+ *sep = 0;
+ sep++;
}
- return ret;
}
- sources = getenv("global.boot.default");
- if (!sources)
- return 0;
+ if (do_list) {
+ bootsources_list(sources, num_sources);
+ goto out;
+ }
- freep = source = xstrdup(sources);
+ if (do_menu) {
+ bootsources_menu(sources, num_sources);
+ goto out;
+ }
- while (1) {
- char *sep = strchr(source, ' ');
- if (sep)
- *sep = 0;
- ret = boot(source);
+ for (i = 0; i < num_sources; i++) {
+ ret = boot(sources[i]);
if (!ret)
break;
-
- if (sep)
- source = sep + 1;
- else
- break;
+ goto out;
}
+out:
+ free(sources);
free(freep);
return ret;
diff --git a/commands/menutree.c b/commands/menutree.c
new file mode 100644
index 0000000000..3b1a263584
--- /dev/null
+++ b/commands/menutree.c
@@ -0,0 +1,60 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <command.h>
+#include <common.h>
+#include <getopt.h>
+#include <menu.h>
+
+static int do_menutree(int argc, char *argv[])
+{
+ int opt, ret;
+ char *path = "/env/menu";
+
+ while ((opt = getopt(argc, argv, "m:")) > 0) {
+ switch (opt) {
+ case 'm':
+ path = optarg;
+ break;
+ }
+ }
+
+ ret = menutree(path, 1);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(menutree)
+BAREBOX_CMD_HELP_USAGE("menutree [OPTIONS]\n")
+"\n"
+"Create a menu from a directory structure\n"
+"Each menu entry is described by a subdirectory. Each subdirectory\n"
+"can contain the following files which further describe the entry:\n"
+"\n"
+"title - A file containing the title of the entry as shown in the menu\n"
+"box - If present, the entry is a 'bool' entry. The file contains a variable\n"
+" name from which the current state of the bool is taken from and saved\n"
+" to.\n"
+"action - if present this file contains a shell script which is executed when\n"
+" when the entry is selected.\n"
+"If neither 'box' or 'action' are present this entry is considered a submenu\n"
+"containing more entries.\n"
+"\n"
+"Options:\n"
+" -m <dir> directory where the menu starts (/env/menu)\n"
+
+BAREBOX_CMD_HELP_END
+
+
+BAREBOX_CMD_START(menutree)
+ .cmd = do_menutree,
+ .usage = "create a menu from a directory structure",
+ BAREBOX_CMD_HELP(cmd_menutree_help)
+BAREBOX_CMD_END
diff --git a/commands/nandtest.c b/commands/nandtest.c
index 0da5444c02..c64f2443a8 100644
--- a/commands/nandtest.c
+++ b/commands/nandtest.c
@@ -277,7 +277,7 @@ static int do_nandtest(int argc, char *argv[])
}
if (length + flash_offset > meminfo.size) {
printf("Length 0x%08llx + offset 0x%08llx exceeds "
- "device size 0x%08x\n", length,
+ "device size 0x%08llx\n", length,
flash_offset, meminfo.size);
goto err;
}
diff --git a/commands/partition.c b/commands/partition.c
index 6d37471f4f..44b91d1a13 100644
--- a/commands/partition.c
+++ b/commands/partition.c
@@ -42,10 +42,11 @@
#define PART_ADD_DEVNAME (1 << 0)
static int mtd_part_do_parse_one(char *devname, const char *partstr,
- char **endp, unsigned long *offset,
- off_t devsize, size_t *retsize, unsigned int pflags)
+ char **endp, loff_t *offset,
+ loff_t devsize, size_t *retsize,
+ unsigned int pflags)
{
- ulong size;
+ loff_t size;
char *end;
char buf[PATH_MAX] = {};
unsigned long flags = 0;
@@ -58,11 +59,11 @@ static int mtd_part_do_parse_one(char *devname, const char *partstr,
size = SIZE_REMAINING;
end = (char *)partstr + 1;
} else {
- size = strtoul_suffix(partstr, &end, 0);
+ size = strtoull_suffix(partstr, &end, 0);
}
if (*end == '@')
- *offset = strtoul_suffix(end+1, &end, 0);
+ *offset = strtoull_suffix(end+1, &end, 0);
if (size == SIZE_REMAINING)
size = devsize - *offset;
@@ -114,8 +115,8 @@ static int do_addpart(int argc, char *argv[])
{
char *devname;
char *endp;
- unsigned long offset = 0;
- off_t devsize;
+ loff_t offset = 0;
+ loff_t devsize;
struct stat s;
int opt;
unsigned int flags = PART_ADD_DEVNAME;
diff --git a/commands/trigger.c b/commands/trigger.c
index 85f16b00bb..de50bddb05 100644
--- a/commands/trigger.c
+++ b/commands/trigger.c
@@ -34,6 +34,7 @@ static char *trigger_names[] = {
[LED_TRIGGER_NET_RX] = "net rx",
[LED_TRIGGER_NET_TX] = "net tx",
[LED_TRIGGER_NET_TXRX] = "net",
+ [LED_TRIGGER_DEFAULT_ON] = "default on",
};
static int do_trigger(int argc, char *argv[])
diff --git a/commands/ubi.c b/commands/ubi.c
index 57ae79025d..8a409c28a8 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -15,12 +15,12 @@ static int do_ubimkvol(int argc, char *argv[])
{
struct ubi_mkvol_req req;
int fd, ret;
- size_t size;
+ uint64_t size;
if (argc != 4)
return COMMAND_ERROR_USAGE;
- size = strtoul_suffix(argv[3], NULL, 0);
+ size = strtoull_suffix(argv[3], NULL, 0);
req.name_len = min_t(int, strlen(argv[2]), UBI_VOL_NAME_MAX);
strncpy(req.name, argv[2], req.name_len);
req.name[req.name_len] = 0;
diff --git a/common/Kconfig b/common/Kconfig
index 5989502a75..0031cc8770 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -62,6 +62,9 @@ config STDDEV
config BAREBOX_UPDATE
bool
+config MENUTREE
+ bool
+
menu "General Settings"
config LOCALVERSION
@@ -602,7 +605,7 @@ config DEFAULT_ENVIRONMENT_GENERIC_NEW
config DEFAULT_ENVIRONMENT_GENERIC_NEW_MENU
bool
depends on DEFAULT_ENVIRONMENT_GENERIC_NEW
- depends on CONFIG_CMD_MENU_MANAGEMENT
+ depends on CMD_MENUTREE
default y
config DEFAULT_ENVIRONMENT_GENERIC_NEW_DFU
diff --git a/common/Makefile b/common/Makefile
index 667c7b36ba..204241c919 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_RESET_SOURCE) += reset_source.o
obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_UIMAGE) += image.o uimage.o
+obj-$(CONFIG_MENUTREE) += menutree.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/blspec.c b/common/blspec.c
index 9b4b096a0a..f165b77aaa 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -235,6 +235,78 @@ out:
}
/*
+ * entry_is_of_compatible - check if a bootspec entry is compatible with
+ * the current machine.
+ *
+ * returns true is the entry is compatible, false otherwise
+ */
+static bool entry_is_of_compatible(struct blspec_entry *entry)
+{
+ const char *devicetree;
+ const char *abspath;
+ size_t size;
+ void *fdt = NULL;
+ int ret;
+ struct device_node *root = NULL, *barebox_root;
+ const char *compat;
+ char *filename;
+
+ /* If we don't have a root node every entry is compatible */
+ barebox_root = of_get_root_node();
+ if (!barebox_root)
+ return true;
+
+ ret = of_property_read_string(barebox_root, "compatible", &compat);
+ if (ret)
+ return false;
+
+ if (entry->rootpath)
+ abspath = entry->rootpath;
+ else
+ abspath = "";
+
+ /* If the entry doesn't specifiy a devicetree we are compatible */
+ devicetree = blspec_entry_var_get(entry, "devicetree");
+ if (!devicetree)
+ return true;
+
+ if (!strcmp(devicetree, "none"))
+ return true;
+
+ filename = asprintf("%s/%s", abspath, devicetree);
+
+ fdt = read_file(filename, &size);
+ if (!fdt) {
+ ret = false;
+ goto out;
+ }
+
+ root = of_unflatten_dtb(NULL, fdt);
+ if (IS_ERR(root)) {
+ ret = PTR_ERR(root);
+ goto out;
+ }
+
+ if (of_device_is_compatible(root, compat)) {
+ ret = true;
+ goto out;
+ }
+
+ pr_info("ignoring entry with incompatible devicetree \"%s\"\n",
+ (char *)of_get_property(root, "compatible", &size));
+
+ ret = false;
+
+out:
+ if (root)
+ of_delete_node(root);
+ free(filename);
+ free(fdt);
+
+ return ret;
+}
+
+/*
* blspec_scan_directory - scan over a directory
*
* Given a root path collects all blspec entries found under /blspec/entries/.
@@ -313,12 +385,17 @@ int blspec_scan_directory(struct blspec *blspec, const char *root)
continue;
}
- found++;
-
entry->rootpath = xstrdup(root);
entry->configpath = configname;
entry->cdev = get_cdev_by_mountpath(root);
+ if (!entry_is_of_compatible(entry)) {
+ blspec_entry_free(entry);
+ continue;
+ }
+
+ found++;
+
name = asprintf("%s/%s", dirname, d->d_name);
if (entry_default && !strcmp(name, entry_default))
entry->boot_default = true;
diff --git a/common/environment.c b/common/environment.c
index 776fa3ad38..9f4e098285 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -253,9 +253,9 @@ static int envfs_check_data(struct envfs_super *super, const void *buf, size_t s
return 0;
}
-static int envfs_load_data(void *buf, size_t size, const char *dir, unsigned flags)
+static int envfs_load_data(struct envfs_super *super, void *buf, size_t size,
+ const char *dir, unsigned flags)
{
- struct envfs_super super;
int fd, ret = 0;
char *str, *tmp;
int headerlen_full;
@@ -281,7 +281,7 @@ static int envfs_load_data(void *buf, size_t size, const char *dir, unsigned fla
inode_size = ENVFS_32(inode->size);
inode_headerlen = ENVFS_32(inode->headerlen);
namelen = strlen(inode->data) + 1;
- if (super.major < 1)
+ if (super->major < 1)
inode_end = &inode_end_dummy;
else
inode_end = (struct envfs_inode_end *)(buf + PAD4(namelen));
@@ -363,7 +363,7 @@ int envfs_load_from_buf(void *buf, int len, const char *dir, unsigned flags)
if (ret)
return ret;
- ret = envfs_load_data(buf, size, dir, flags);
+ ret = envfs_load_data(super, buf, size, dir, flags);
return ret;
}
@@ -415,7 +415,7 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
if (ret)
goto out;
- ret = envfs_load_data(buf, size, dir, flags);
+ ret = envfs_load_data(&super, buf, size, dir, flags);
if (ret)
goto out;
diff --git a/common/hush.c b/common/hush.c
index bd534c12f5..1447fdb7f1 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1637,6 +1637,39 @@ static void update_ifs_map(void)
mapset(ifs, 2); /* also flow through if quoted */
}
+/*
+ * shell_expand - Expand shell variables in a string.
+ * @str: The input string containing shell variables like
+ * $var or ${var}
+ * Return: The expanded string. Must be freed with free().
+ */
+char *shell_expand(char *str)
+{
+ struct p_context ctx = {};
+ o_string o = {};
+ char *res, *parsed;
+
+ remove_quotes_in_str(str);
+
+ o.quote = 1;
+
+ initialize_context(&ctx);
+
+ parse_string(&o, &ctx, str);
+
+ parsed = xmemdup(o.data, o.length + 1);
+ parsed[o.length] = 0;
+
+ res = insert_var_value(parsed);
+ if (res != parsed)
+ free(parsed);
+
+ free_pipe_list(ctx.list_head, 0);
+ b_free(&o);
+
+ return res;
+}
+
/* most recursion does not come through here, the exeception is
* from builtin_source() */
static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int flag)
diff --git a/common/menutree.c b/common/menutree.c
new file mode 100644
index 0000000000..814512d7b7
--- /dev/null
+++ b/common/menutree.c
@@ -0,0 +1,181 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <environment.h>
+#include <libbb.h>
+#include <common.h>
+#include <glob.h>
+#include <menu.h>
+#include <fs.h>
+
+#include <linux/stat.h>
+
+struct menutree {
+ char *action;
+ struct menu_entry me;
+};
+
+static void menutree_action_subdir(struct menu *m, struct menu_entry *me)
+{
+ struct menutree *mt = container_of(me, struct menutree, me);
+
+ menutree(mt->action, 0);
+}
+
+static void menutree_action(struct menu *m, struct menu_entry *me)
+{
+ struct menutree *mt = container_of(me, struct menutree, me);
+
+ run_command(mt->action);
+}
+
+static void setenv_bool(const char *var, bool val)
+{
+ const char *str;
+
+ if (val)
+ str = "1";
+ else
+ str = "0";
+
+ setenv(var, str);
+}
+
+static void menutree_box(struct menu *m, struct menu_entry *me)
+{
+ struct menutree *mt = container_of(me, struct menutree, me);
+
+ setenv_bool(mt->action, me->box_state);
+}
+
+static void menutree_entry_free(struct menu_entry *me)
+{
+ struct menutree *mt = container_of(me, struct menutree, me);
+
+ free(mt->action);
+ free(mt->me.display);
+ free(mt);
+}
+
+/*
+ * menutree - show a menu constructed from a directory structure
+ * @path: the path to the directory structure
+ *
+ * Each menu entry is described by a subdirectory. Each subdirectory
+ * can contain the following files which further describe the entry:
+ *
+ * title - A file containing the title of the entry as shown in the menu
+ * box - If present, the entry is a 'bool' entry. The file contains a variable
+ * name from which the current state of the bool is taken from and saved
+ * to.
+ * action - if present this file contains a shell script which is executed when
+ * when the entry is selected.
+ *
+ * If neither 'box' or 'action' are present this entry is considered a submenu
+ * containing more entries.
+ */
+int menutree(const char *path, int toplevel)
+{
+ int ret;
+ struct menu *menu;
+ struct stat s;
+ char *box;
+ struct menutree *mt;
+ glob_t g;
+ int i;
+ char *globpath, *display;
+
+ menu = menu_alloc();
+
+ globpath = asprintf("%s/*", path);
+ ret = glob(globpath, 0, NULL, &g);
+ free(globpath);
+ if (ret == GLOB_NOMATCH) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ display = read_file_line("%s/title", path);
+ if (!display) {
+ eprintf("no title found in %s/title\n", path);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ menu->display = shell_expand(display);
+ free(display);
+
+ for (i = 0; i < g.gl_pathc; i++) {
+ ret = stat(g.gl_pathv[i], &s);
+ if (ret)
+ goto out;
+
+ if (!S_ISDIR(s.st_mode))
+ continue;
+
+ mt = xzalloc(sizeof(*mt));
+
+ display = read_file_line("%s/title", g.gl_pathv[i]);
+ if (!display) {
+ eprintf("no title found in %s/title\n", g.gl_pathv[i]);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ mt->me.display = shell_expand(display);
+ free(display);
+ mt->me.free = menutree_entry_free;
+
+ box = read_file_line("%s/box", g.gl_pathv[i]);
+ if (box) {
+ mt->me.type = MENU_ENTRY_BOX;
+ mt->me.action = menutree_box;
+ mt->action = box;
+ getenv_bool(box, &mt->me.box_state);
+ menu_add_entry(menu, &mt->me);
+ continue;
+ }
+
+ mt->me.type = MENU_ENTRY_NORMAL;
+
+ mt->action = asprintf("%s/action", g.gl_pathv[i]);
+
+ ret = stat(mt->action, &s);
+ if (ret) {
+ mt->me.action = menutree_action_subdir;
+ free(mt->action);
+ mt->action = xstrdup(g.gl_pathv[i]);
+ } else {
+ mt->me.action = menutree_action;
+ }
+
+ menu_add_entry(menu, &mt->me);
+ }
+
+ if (!toplevel) {
+ mt = xzalloc(sizeof(*mt));
+ mt->me.display = xstrdup("back");
+ mt->me.type = MENU_ENTRY_NORMAL;
+ mt->me.non_re_ent = 1;
+ mt->me.free = menutree_entry_free;
+ menu_add_entry(menu, &mt->me);
+ }
+
+ menu_show(menu);
+
+ ret = 0;
+out:
+ menu_free(menu);
+
+ globfree(&g);
+
+ return ret;
+}
diff --git a/defaultenv/defaultenv-2-menu/menu/00-boot-default/action b/defaultenv/defaultenv-2-menu/menu/00-boot-default/action
new file mode 100644
index 0000000000..3d72ff6523
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/00-boot-default/action
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+boot
+
+readline "Booting failed. Press any key to continue" ignore
diff --git a/defaultenv/defaultenv-2-menu/menu/00-boot-default/title b/defaultenv/defaultenv-2-menu/menu/00-boot-default/title
new file mode 100644
index 0000000000..ef8c3dd1af
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/00-boot-default/title
@@ -0,0 +1 @@
+Boot default
diff --git a/defaultenv/defaultenv-2-menu/menu/10-boot-all/action b/defaultenv/defaultenv-2-menu/menu/10-boot-all/action
new file mode 100644
index 0000000000..a890ffe380
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/10-boot-all/action
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+boot -m
diff --git a/defaultenv/defaultenv-2-menu/menu/10-boot-all/net/action b/defaultenv/defaultenv-2-menu/menu/10-boot-all/net/action
new file mode 100644
index 0000000000..b31b0e409d
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/10-boot-all/net/action
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "Boot from Network...."
+
+sleep 3
diff --git a/defaultenv/defaultenv-2-menu/menu/10-boot-all/net/title b/defaultenv/defaultenv-2-menu/menu/10-boot-all/net/title
new file mode 100644
index 0000000000..79a6d8ffde
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/10-boot-all/net/title
@@ -0,0 +1 @@
+Boot from network
diff --git a/defaultenv/defaultenv-2-menu/menu/10-boot-all/title b/defaultenv/defaultenv-2-menu/menu/10-boot-all/title
new file mode 100644
index 0000000000..0f05e98eab
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/10-boot-all/title
@@ -0,0 +1 @@
+Detect bootsources
diff --git a/defaultenv/defaultenv-2-menu/menu/20-settings/config/action b/defaultenv/defaultenv-2-menu/menu/20-settings/config/action
new file mode 100644
index 0000000000..9a993af9de
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/20-settings/config/action
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+edit /env/config
+
+/env/config
diff --git a/defaultenv/defaultenv-2-menu/menu/20-settings/config/title b/defaultenv/defaultenv-2-menu/menu/20-settings/config/title
new file mode 100644
index 0000000000..a8955a90c3
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/20-settings/config/title
@@ -0,0 +1 @@
+Config settings
diff --git a/defaultenv/defaultenv-2-menu/menu/20-settings/network/action b/defaultenv/defaultenv-2-menu/menu/20-settings/network/action
new file mode 100644
index 0000000000..d27a77f706
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/20-settings/network/action
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+edit /env/network/eth0
diff --git a/defaultenv/defaultenv-2-menu/menu/20-settings/network/title b/defaultenv/defaultenv-2-menu/menu/20-settings/network/title
new file mode 100644
index 0000000000..4641d480ea
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/20-settings/network/title
@@ -0,0 +1 @@
+Network settings
diff --git a/defaultenv/defaultenv-2-menu/menu/20-settings/title b/defaultenv/defaultenv-2-menu/menu/20-settings/title
new file mode 100644
index 0000000000..163d304af4
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/20-settings/title
@@ -0,0 +1 @@
+Settings
diff --git a/defaultenv/defaultenv-2-menu/menu/30-saveenv/action b/defaultenv/defaultenv-2-menu/menu/30-saveenv/action
new file mode 100644
index 0000000000..c6aed70912
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/30-saveenv/action
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+saveenv
+if [ $? != 0 ]; then
+ echo "saving environment failed"
+fi
+
+sleep 2
diff --git a/defaultenv/defaultenv-2-menu/menu/30-saveenv/title b/defaultenv/defaultenv-2-menu/menu/30-saveenv/title
new file mode 100644
index 0000000000..8ae292d6b5
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/30-saveenv/title
@@ -0,0 +1 @@
+Save environment
diff --git a/defaultenv/defaultenv-2-menu/menu/40-shell/action b/defaultenv/defaultenv-2-menu/menu/40-shell/action
new file mode 100644
index 0000000000..fd5bc2b0c4
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/40-shell/action
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+echo "Enter 'exit' to get back to the menu"
+
+sh
diff --git a/defaultenv/defaultenv-2-menu/menu/40-shell/title b/defaultenv/defaultenv-2-menu/menu/40-shell/title
new file mode 100644
index 0000000000..6567bb2d9e
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/40-shell/title
@@ -0,0 +1 @@
+Shell
diff --git a/defaultenv/defaultenv-2-menu/menu/50-reset/action b/defaultenv/defaultenv-2-menu/menu/50-reset/action
new file mode 100644
index 0000000000..61d5c9a965
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/50-reset/action
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+reset
diff --git a/defaultenv/defaultenv-2-menu/menu/50-reset/title b/defaultenv/defaultenv-2-menu/menu/50-reset/title
new file mode 100644
index 0000000000..6d9fd4d6bf
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/50-reset/title
@@ -0,0 +1 @@
+Reset
diff --git a/defaultenv/defaultenv-2-menu/menu/boot-entries-collect b/defaultenv/defaultenv-2-menu/menu/boot-entries-collect
deleted file mode 100644
index c066c930ab..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/boot-entries-collect
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-
-cd /env/boot
-
-./$global.boot.default menu
-
-for i in *; do
- if [ "$i" != "$global.boot.default" ]; then
- ./$i menu
- fi
-done
-
-cd /
diff --git a/defaultenv/defaultenv-2-menu/menu/boot-entries-edit b/defaultenv/defaultenv-2-menu/menu/boot-entries-edit
deleted file mode 100644
index c4e1c3d5fd..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/boot-entries-edit
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-export menu_exit=false
-
-while true; do
- menu -a -m boot_entries_edit -d "\e[1;36mEdit boot entries\e[0m"
-
- boot-entries-collect
-
- menu -e -a -m boot_entries_edit -c "boot-menu-new-boot-entry" -d "Add a new entry"
- menu -e -a -m boot_entries_edit -c "boot-entries-remove" -d "Remove an entry"
- menu -e -a -m boot_entries_edit -c "menu_exit=true" -d "back"
-
- menu -s -m boot_entries_edit
- menu -r -m boot_entries_edit
-
- if [ $menu_exit = true ]; then
- exit
- fi
-done
diff --git a/defaultenv/defaultenv-2-menu/menu/boot-entries-remove b/defaultenv/defaultenv-2-menu/menu/boot-entries-remove
deleted file mode 100644
index 566be9dd6e..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/boot-entries-remove
+++ /dev/null
@@ -1,18 +0,0 @@
-#!/bin/sh
-
-export menu_exit=false
-
-while true; do
- menu -a -m boot_entries_remove -d "\e[1;36mRemove Boot entry\e[0m"
-
- boot-entries-collect
-
- menu -e -a -m boot_entries_remove -c "menu_exit=true" -d "back"
-
- menu -s -m boot_entries_remove
- menu -r -m boot_entries_remove
-
- if [ $menu_exit = true ]; then
- exit
- fi
-done
diff --git a/defaultenv/defaultenv-2-menu/menu/boot-menu-add-entry b/defaultenv/defaultenv-2-menu/menu/boot-menu-add-entry
deleted file mode 100644
index f06c524034..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/boot-menu-add-entry
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-
-menu -e -a -m boot -c "boot -v $1; echo; readline \"press enter to continue\" a " -d "Boot: ${GREEN}$2${NC}"
-menu -e -a -m boot_entries_edit -c "$global.editcmd /env/boot/$1" -d "${GREEN}$2${NC}"
-menu -e -a -m boot_entries_remove -c "rm /env/boot/$1" -d "${GREEN}$2${NC}"
diff --git a/defaultenv/defaultenv-2-menu/menu/boot-menu-new-boot-entry b/defaultenv/defaultenv-2-menu/menu/boot-menu-new-boot-entry
deleted file mode 100644
index c5e982cdb2..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/boot-menu-new-boot-entry
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-name=
-
-readline "Name of the new entry: " name
-
-if [ -z "$name" ]; then
- exit 1
-fi
-
-if [ -e "/env/boot/$name" ]; then
- echo "entry $name already exists"
- readline "<enter>" unused
- exit 1
-fi
-
-cp /env/data/boot-template /env/boot/$name
-
-edit /env/boot/$name
-
-boot-menu-show rebuild
diff --git a/defaultenv/defaultenv-2-menu/menu/init-entries-collect b/defaultenv/defaultenv-2-menu/menu/init-entries-collect
deleted file mode 100644
index dbb775779a..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/init-entries-collect
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-cd /env/init
-
-for i in *; do
- ./$i menu
-done
-
-cd /
diff --git a/defaultenv/defaultenv-2-menu/menu/init-entries-edit b/defaultenv/defaultenv-2-menu/menu/init-entries-edit
deleted file mode 100644
index fc02b327d9..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/init-entries-edit
+++ /dev/null
@@ -1,20 +0,0 @@
-#!/bin/sh
-
-export menu_exit=false
-
-while true; do
- menu -a -m init_entries_edit -d "\e[1;36mEdit init entries\e[0m"
-
- menu -e -a -m init_entries_edit -R -c "true" -d ">> Reset board to let changes here take effect <<"
-
- init-entries-collect
-
- menu -e -a -m init_entries_edit -c "menu_exit=true" -d "back"
-
- menu -s -m init_entries_edit
- menu -r -m init_entries_edit
-
- if [ $menu_exit = true ]; then
- exit
- fi
-done
diff --git a/defaultenv/defaultenv-2-menu/menu/init-menu-add-entry b/defaultenv/defaultenv-2-menu/menu/init-menu-add-entry
deleted file mode 100644
index 7cb5686402..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/init-menu-add-entry
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/bin/sh
-
-menu -e -a -m init_entries_edit -c "$global.editcmd /env/init/$1" -d "\e[1;32m$2\e[0m"
diff --git a/defaultenv/defaultenv-2-menu/menu/mainmenu b/defaultenv/defaultenv-2-menu/menu/mainmenu
index f10f67a62f..98039472bd 100644
--- a/defaultenv/defaultenv-2-menu/menu/mainmenu
+++ b/defaultenv/defaultenv-2-menu/menu/mainmenu
@@ -1,23 +1,5 @@
#!/bin/sh
-savepath=$PATH
-export menupath=$PATH:/env/menu
-
. /env/data/ansi-colors
-while true; do
- export PATH=${menupath}
-
- echo $PATH
-
- menu -a -m boot -d "${CYAN}Welcome to Barebox${NC}"
-
- boot-entries-collect
-
- menu -e -a -m boot -c "settings" -d "Settings"
- menu -e -a -m boot -c 'PATH=$savepath; echo "enter exit to return to menu"; sh' -d "${DARK_YELLOW}Shell${NC}"
- menu -e -a -m boot -c reset -d "${RED}Reset${NC}"
-
- menu -s -m boot
- menu -r -m boot
-done
+menutree
diff --git a/defaultenv/defaultenv-2-menu/menu/settings b/defaultenv/defaultenv-2-menu/menu/settings
deleted file mode 100644
index db619afa6f..0000000000
--- a/defaultenv/defaultenv-2-menu/menu/settings
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/sh
-
-export menu_exit=false
-
-while true; do
- menu -a -m settings -d "${CYAN}Settings${NC}"
-
- menu -e -a -R -m settings -c "$global.editcmd /env/network/eth0" -d "Network settings"
- menu -e -a -R -m settings -c "$global.editcmd /env/config" -d "Config settings"
- menu -e -a -m settings -c "boot-entries-edit" -d "Edit boot entries"
- menu -e -a -m settings -c "init-entries-edit" -d "Edit init entries"
- menu -e -a -R -m settings -c "saveenv || echo \"failed to save environment\" && sleep 2" -d "Save settings"
- menu -e -a -m settings -c "menu_exit=true" -d "back"
-
- menu -s -m settings
- menu -r -m settings
-
- if [ $menu_exit = true ]; then
- exit
- fi
-done
diff --git a/defaultenv/defaultenv-2-menu/menu/title b/defaultenv/defaultenv-2-menu/menu/title
new file mode 100644
index 0000000000..f3c47b5d12
--- /dev/null
+++ b/defaultenv/defaultenv-2-menu/menu/title
@@ -0,0 +1 @@
+${RED}Main menu${NC}
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f5c05920b1..0687b3cddd 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -1,8 +1,9 @@
obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed.o clk-divider.o clk-fixed-factor.o \
- clk-mux.o clk-gate.o clk-divider-table.o
+ clk-mux.o clk-gate.o
obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o
obj-$(CONFIG_ARCH_MVEBU) += mvebu/
obj-$(CONFIG_ARCH_MXS) += mxs/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_CLK_SOCFPGA) += socfpga.o
+obj-$(CONFIG_MACH_MIPS_ATH79) += clk-ar933x.o
diff --git a/drivers/clk/clk-ar933x.c b/drivers/clk/clk-ar933x.c
new file mode 100644
index 0000000000..d983387a93
--- /dev/null
+++ b/drivers/clk/clk-ar933x.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2013 Lucas Stach <l.stach@pengutronix.de>
+ *
+ * Based on the Linux Tegra clock code
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+
+#include <mach/ath79.h>
+#include <dt-bindings/clock/ar933x-clk.h>
+
+static struct clk *clks[AR933X_CLK_END];
+static struct clk_onecell_data clk_data;
+
+struct clk_ar933x {
+ struct clk clk;
+ void __iomem *base;
+ u32 div_shift;
+ u32 div_mask;
+ const char *parent;
+};
+
+static unsigned long clk_ar933x_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+ struct clk_ar933x *f = container_of(clk, struct clk_ar933x, clk);
+ unsigned long rate;
+ unsigned long freq;
+ u32 clock_ctrl;
+ u32 cpu_config;
+ u32 t;
+
+ clock_ctrl = __raw_readl(f->base + AR933X_PLL_CLOCK_CTRL_REG);
+
+ if (clock_ctrl & AR933X_PLL_CLOCK_CTRL_BYPASS) {
+ rate = parent_rate;
+ } else {
+ cpu_config = __raw_readl(f->base + AR933X_PLL_CPU_CONFIG_REG);
+
+ t = (cpu_config >> AR933X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+ AR933X_PLL_CPU_CONFIG_REFDIV_MASK;
+ freq = parent_rate / t;
+
+ t = (cpu_config >> AR933X_PLL_CPU_CONFIG_NINT_SHIFT) &
+ AR933X_PLL_CPU_CONFIG_NINT_MASK;
+ freq *= t;
+
+ t = (cpu_config >> AR933X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+ AR933X_PLL_CPU_CONFIG_OUTDIV_MASK;
+ if (t == 0)
+ t = 1;
+
+ freq >>= t;
+
+ t = ((clock_ctrl >> f->div_shift) & f->div_mask) + 1;
+ rate = freq / t;
+ }
+
+ return rate;
+}
+
+struct clk_ops clk_ar933x_ops = {
+ .recalc_rate = clk_ar933x_recalc_rate,
+};
+
+static struct clk *clk_ar933x(const char *name, const char *parent,
+ void __iomem *base, u32 div_shift, u32 div_mask)
+{
+ struct clk_ar933x *f = xzalloc(sizeof(*f));
+
+ f->parent = parent;
+ f->base = base;
+ f->div_shift = div_shift;
+ f->div_mask = div_mask;
+
+ f->clk.ops = &clk_ar933x_ops;
+ f->clk.name = name;
+ f->clk.parent_names = &f->parent;
+ f->clk.num_parents = 1;
+
+ clk_register(&f->clk);
+
+ return &f->clk;
+}
+
+static void ar933x_ref_clk_init(void __iomem *base)
+{
+ u32 t;
+ unsigned long ref_rate;
+
+ t = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
+ if (t & AR933X_BOOTSTRAP_REF_CLK_40)
+ ref_rate = (40 * 1000 * 1000);
+ else
+ ref_rate = (25 * 1000 * 1000);
+
+ clks[AR933X_CLK_REF] = clk_fixed("ref", ref_rate);
+}
+
+static void ar933x_pll_init(void __iomem *base)
+{
+ clks[AR933X_CLK_UART] = clk_fixed_factor("uart", "ref", 1, 1,
+ CLK_SET_RATE_PARENT);
+
+ clks[AR933X_CLK_CPU] = clk_ar933x("cpu", "ref", base,
+ AR933X_PLL_CLOCK_CTRL_CPU_DIV_SHIFT,
+ AR933X_PLL_CLOCK_CTRL_CPU_DIV_MASK);
+
+ clks[AR933X_CLK_DDR] = clk_ar933x("ddr", "ref", base,
+ AR933X_PLL_CLOCK_CTRL_DDR_DIV_SHIFT,
+ AR933X_PLL_CLOCK_CTRL_DDR_DIV_MASK);
+
+ clks[AR933X_CLK_AHB] = clk_ar933x("ahb", "ref", base,
+ AR933X_PLL_CLOCK_CTRL_AHB_DIV_SHIFT,
+ AR933X_PLL_CLOCK_CTRL_AHB_DIV_MASK);
+
+ clks[AR933X_CLK_WDT] = clk_fixed_factor("wdt", "ahb", 1, 1,
+ CLK_SET_RATE_PARENT);
+}
+
+static int ar933x_clk_probe(struct device_d *dev)
+{
+ void __iomem *base;
+
+ base = dev_request_mem_region(dev, 0);
+ if (!base)
+ return -EBUSY;
+
+ ar933x_ref_clk_init(base);
+ ar933x_pll_init(base);
+
+ clk_data.clks = clks;
+ clk_data.clk_num = ARRAY_SIZE(clks);
+ of_clk_add_provider(dev->device_node, of_clk_src_onecell_get,
+ &clk_data);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id ar933x_clk_dt_ids[] = {
+ {
+ .compatible = "qca,ar933x-clk",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d ar933x_clk_driver = {
+ .probe = ar933x_clk_probe,
+ .name = "ar933x_clk",
+ .of_compatible = DRV_OF_COMPAT(ar933x_clk_dt_ids),
+};
+
+static int ar933x_clk_init(void)
+{
+ return platform_driver_register(&ar933x_clk_driver);
+}
+postcore_initcall(ar933x_clk_init);
diff --git a/drivers/clk/clk-divider-table.c b/drivers/clk/clk-divider-table.c
deleted file mode 100644
index fd2d3fc3c1..0000000000
--- a/drivers/clk/clk-divider-table.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * clk-divider-table.c - generic barebox clock support. Based on Linux clk support
- *
- * Copyright (c) 2012 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-#include <common.h>
-#include <io.h>
-#include <malloc.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-struct clk_divider_table {
- struct clk clk;
- u8 shift;
- u8 width;
- void __iomem *reg;
- const char *parent;
- const struct clk_div_table *table;
- int table_size;
- int max_div_index;
-};
-
-static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
- unsigned long parent_rate)
-{
- struct clk_divider_table *div =
- container_of(clk, struct clk_divider_table, clk);
- unsigned int val;
- int i, div_index = -1;
- unsigned long best = 0;
-
- if (rate > parent_rate)
- rate = parent_rate;
- if (rate < parent_rate / div->table[div->max_div_index].div)
- rate = parent_rate / div->table[div->max_div_index].div;
-
- for (i = 0; i < div->table_size; i++) {
- unsigned long now = parent_rate / div->table[i].div;
-
- if (now <= rate && now >= best) {
- best = now;
- div_index = i;
- }
- }
-
- val = readl(div->reg);
- val &= ~(((1 << div->width) - 1) << div->shift);
- val |= div_index << div->shift;
- writel(val, div->reg);
-
- return 0;
-}
-
-static unsigned long clk_divider_recalc_rate(struct clk *clk,
- unsigned long parent_rate)
-{
- struct clk_divider_table *div =
- container_of(clk, struct clk_divider_table, clk);
- unsigned int val;
-
- val = readl(div->reg) >> div->shift;
- val &= (1 << div->width) - 1;
-
- if (val >= div->table_size)
- return 0;
-
- return parent_rate / div->table[val].div;
-}
-
-static struct clk_ops clk_divider_table_ops = {
- .set_rate = clk_divider_set_rate,
- .recalc_rate = clk_divider_recalc_rate,
-};
-
-struct clk *clk_divider_table(const char *name,
- const char *parent, void __iomem *reg, u8 shift, u8 width,
- const struct clk_div_table *table)
-{
- struct clk_divider_table *div = xzalloc(sizeof(*div));
- const struct clk_div_table *clkt;
- int ret, max_div = 0;
-
- div->shift = shift;
- div->reg = reg;
- div->width = width;
- div->parent = parent;
- div->clk.ops = &clk_divider_table_ops;
- div->clk.name = name;
- div->clk.parent_names = &div->parent;
- div->clk.num_parents = 1;
- div->table = table;
-
- for (clkt = div->table; clkt->div; clkt++) {
- if (clkt->div > max_div) {
- max_div = clkt->div;
- div->max_div_index = div->table_size;
- }
- div->table_size++;
- }
-
- ret = clk_register(&div->clk);
- if (ret) {
- free(div);
- return ERR_PTR(ret);
- }
-
- return &div->clk;
-}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 3bf8105a8b..67783daabb 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -20,65 +20,196 @@
#include <linux/clk.h>
#include <linux/err.h>
-static unsigned int clk_divider_maxdiv(struct clk_divider *div)
+#define div_mask(d) ((1 << ((d)->width)) - 1)
+
+static unsigned int _get_maxdiv(struct clk_divider *divider)
{
- if (div->flags & CLK_DIVIDER_ONE_BASED)
- return (1 << div->width) - 1;
- return 1 << div->width;
+ if (divider->flags & CLK_DIVIDER_ONE_BASED)
+ return div_mask(divider);
+ return div_mask(divider) + 1;
}
-static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
+static unsigned int _get_table_div(const struct clk_div_table *table,
+ unsigned int val)
+{
+ const struct clk_div_table *clkt;
+
+ for (clkt = table; clkt->div; clkt++)
+ if (clkt->val == val)
+ return clkt->div;
+ return 0;
+}
+
+static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+{
+ if (divider->flags & CLK_DIVIDER_ONE_BASED)
+ return val;
+ if (divider->table)
+ return _get_table_div(divider->table, val);
+ return val + 1;
+}
+
+static unsigned int _get_table_val(const struct clk_div_table *table,
+ unsigned int div)
+{
+ const struct clk_div_table *clkt;
+
+ for (clkt = table; clkt->div; clkt++)
+ if (clkt->div == div)
+ return clkt->val;
+ return 0;
+}
+
+static unsigned int _get_val(struct clk_divider *divider, unsigned int div)
+{
+ if (divider->flags & CLK_DIVIDER_ONE_BASED)
+ return div;
+ if (divider->table)
+ return _get_table_val(divider->table, div);
+ return div - 1;
+}
+
+static unsigned long clk_divider_recalc_rate(struct clk *clk,
unsigned long parent_rate)
{
- struct clk_divider *div = container_of(clk, struct clk_divider, clk);
- unsigned int val, divval;
+ struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ unsigned int div, val;
+
+ val = readl(divider->reg) >> divider->shift;
+ val &= div_mask(divider);
+
+ div = _get_div(divider, val);
+
+ return parent_rate / div;
+}
+
+/*
+ * The reverse of DIV_ROUND_UP: The maximum number which
+ * divided by m is r
+ */
+#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
+
+static bool _is_valid_table_div(const struct clk_div_table *table,
+ unsigned int div)
+{
+ const struct clk_div_table *clkt;
+
+ for (clkt = table; clkt->div; clkt++)
+ if (clkt->div == div)
+ return true;
+ return false;
+}
+
+static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
+{
+ if (divider->table)
+ return _is_valid_table_div(divider->table, div);
+ return true;
+}
+
+static int clk_divider_bestdiv(struct clk *clk, unsigned long rate,
+ unsigned long *best_parent_rate)
+{
+ struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ int i, bestdiv = 0;
+ unsigned long parent_rate, best = 0, now, maxdiv;
+ unsigned long parent_rate_saved = *best_parent_rate;
- if (rate > parent_rate)
- rate = parent_rate;
if (!rate)
rate = 1;
- divval = DIV_ROUND_UP(parent_rate, rate);
- if (divval > clk_divider_maxdiv(div))
- divval = clk_divider_maxdiv(div);
+ maxdiv = _get_maxdiv(divider);
- if (!(div->flags & CLK_DIVIDER_ONE_BASED))
- divval--;
+ if (!(clk->flags & CLK_SET_RATE_PARENT)) {
+ parent_rate = *best_parent_rate;
+ bestdiv = DIV_ROUND_UP(parent_rate, rate);
+ bestdiv = bestdiv == 0 ? 1 : bestdiv;
+ bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
+ return bestdiv;
+ }
- val = readl(div->reg);
- val &= ~(((1 << div->width) - 1) << div->shift);
- val |= divval << div->shift;
- writel(val, div->reg);
+ /*
+ * The maximum divider we can use without overflowing
+ * unsigned long in rate * i below
+ */
+ maxdiv = min(ULONG_MAX / rate, maxdiv);
- return 0;
+ for (i = 1; i <= maxdiv; i++) {
+ if (!_is_valid_div(divider, i))
+ continue;
+ if (rate * i == parent_rate_saved) {
+ /*
+ * It's the most ideal case if the requested rate can be
+ * divided from parent clock without needing to change
+ * parent rate, so return the divider immediately.
+ */
+ *best_parent_rate = parent_rate_saved;
+ return i;
+ }
+ parent_rate = clk_round_rate(clk_get_parent(clk),
+ MULT_ROUND_UP(rate, i));
+ now = parent_rate / i;
+ if (now <= rate && now > best) {
+ bestdiv = i;
+ best = now;
+ *best_parent_rate = parent_rate;
+ }
+ }
+
+ if (!bestdiv) {
+ bestdiv = _get_maxdiv(divider);
+ *best_parent_rate = clk_round_rate(clk_get_parent(clk), 1);
+ }
+
+ return bestdiv;
}
-static unsigned long clk_divider_recalc_rate(struct clk *clk,
- unsigned long parent_rate)
+static long clk_divider_round_rate(struct clk *clk, unsigned long rate,
+ unsigned long *parent_rate)
{
- struct clk_divider *div = container_of(clk, struct clk_divider, clk);
- unsigned int val;
+ int div;
- val = readl(div->reg) >> div->shift;
- val &= (1 << div->width) - 1;
+ div = clk_divider_bestdiv(clk, rate, parent_rate);
- if (div->flags & CLK_DIVIDER_ONE_BASED) {
- if (!val)
- val++;
+ return *parent_rate / div;
+}
+
+static int clk_divider_set_rate(struct clk *clk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_divider *divider = container_of(clk, struct clk_divider, clk);
+ unsigned int div, value;
+ u32 val;
+
+ if (clk->flags & CLK_SET_RATE_PARENT) {
+ unsigned long best_parent_rate = parent_rate;
+ div = clk_divider_bestdiv(clk, rate, &best_parent_rate);
+ clk_set_rate(clk_get_parent(clk), best_parent_rate);
} else {
- val++;
+ div = parent_rate / rate;
}
- return parent_rate / val;
+ value = _get_val(divider, div);
+
+ if (value > div_mask(divider))
+ value = div_mask(divider);
+
+ val = readl(divider->reg);
+ val &= ~(div_mask(divider) << divider->shift);
+ val |= value << divider->shift;
+ writel(val, divider->reg);
+
+ return 0;
}
struct clk_ops clk_divider_ops = {
.set_rate = clk_divider_set_rate,
.recalc_rate = clk_divider_recalc_rate,
+ .round_rate = clk_divider_round_rate,
};
struct clk *clk_divider(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width)
+ void __iomem *reg, u8 shift, u8 width, unsigned flags)
{
struct clk_divider *div = xzalloc(sizeof(*div));
int ret;
@@ -89,6 +220,7 @@ struct clk *clk_divider(const char *name, const char *parent,
div->parent = parent;
div->clk.ops = &clk_divider_ops;
div->clk.name = name;
+ div->clk.flags = flags;
div->clk.parent_names = &div->parent;
div->clk.num_parents = 1;
@@ -102,12 +234,12 @@ struct clk *clk_divider(const char *name, const char *parent,
}
struct clk *clk_divider_one_based(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width)
+ void __iomem *reg, u8 shift, u8 width, unsigned flags)
{
struct clk_divider *div;
struct clk *clk;
- clk = clk_divider(name, parent, reg, shift, width);
+ clk = clk_divider(name, parent, reg, shift, width, flags);
if (IS_ERR(clk))
return clk;
@@ -116,3 +248,39 @@ struct clk *clk_divider_one_based(const char *name, const char *parent,
return clk;
}
+
+struct clk *clk_divider_table(const char *name,
+ const char *parent, void __iomem *reg, u8 shift, u8 width,
+ const struct clk_div_table *table, unsigned flags)
+{
+ struct clk_divider *div = xzalloc(sizeof(*div));
+ const struct clk_div_table *clkt;
+ int ret, max_div = 0;
+
+ div->shift = shift;
+ div->reg = reg;
+ div->width = width;
+ div->parent = parent;
+ div->clk.ops = &clk_divider_ops;
+ div->clk.name = name;
+ div->clk.flags = flags;
+ div->clk.parent_names = &div->parent;
+ div->clk.num_parents = 1;
+ div->table = table;
+
+ for (clkt = div->table; clkt->div; clkt++) {
+ if (clkt->div > max_div) {
+ max_div = clkt->div;
+ div->max_div_index = div->table_size;
+ }
+ div->table_size++;
+ }
+
+ ret = clk_register(&div->clk);
+ if (ret) {
+ free(div);
+ return ERR_PTR(ret);
+ }
+
+ return &div->clk;
+}
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index f0ecbd3e59..cb531b146b 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -35,12 +35,42 @@ static unsigned long clk_fixed_factor_recalc_rate(struct clk *clk,
return (parent_rate / f->div) * f->mult;
}
+static long clk_factor_round_rate(struct clk *clk, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk);
+
+ if (clk->flags & CLK_SET_RATE_PARENT) {
+ unsigned long best_parent;
+
+ best_parent = (rate / fix->mult) * fix->div;
+ *prate = clk_round_rate(clk_get_parent(clk), best_parent);
+ }
+
+ return (*prate / fix->div) * fix->mult;
+}
+
+static int clk_factor_set_rate(struct clk *clk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_fixed_factor *fix = container_of(clk, struct clk_fixed_factor, clk);
+
+ if (clk->flags & CLK_SET_RATE_PARENT) {
+ printk("%s: %ld -> parent %ld\n", __func__, rate, rate * fix->div / fix->mult);
+ return clk_set_rate(clk_get_parent(clk), rate * fix->div / fix->mult);
+ }
+
+ return 0;
+}
+
static struct clk_ops clk_fixed_factor_ops = {
+ .set_rate = clk_factor_set_rate,
+ .round_rate = clk_factor_round_rate,
.recalc_rate = clk_fixed_factor_recalc_rate,
};
struct clk *clk_fixed_factor(const char *name,
- const char *parent, unsigned int mult, unsigned int div)
+ const char *parent, unsigned int mult, unsigned int div, unsigned flags)
{
struct clk_fixed_factor *f = xzalloc(sizeof(*f));
int ret;
@@ -50,6 +80,7 @@ struct clk *clk_fixed_factor(const char *name,
f->parent = parent;
f->clk.ops = &clk_fixed_factor_ops;
f->clk.name = name;
+ f->clk.flags = flags;
f->clk.parent_names = &f->parent;
f->clk.num_parents = 1;
diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c
index baec85598d..b298b193dc 100644
--- a/drivers/clk/clk-gate.c
+++ b/drivers/clk/clk-gate.c
@@ -77,13 +77,15 @@ static int clk_gate_is_enabled(struct clk *clk)
}
static struct clk_ops clk_gate_ops = {
+ .set_rate = clk_parent_set_rate,
+ .round_rate = clk_parent_round_rate,
.enable = clk_gate_enable,
.disable = clk_gate_disable,
.is_enabled = clk_gate_is_enabled,
};
struct clk *clk_gate_alloc(const char *name, const char *parent,
- void __iomem *reg, u8 shift)
+ void __iomem *reg, u8 shift, unsigned flags)
{
struct clk_gate *g = xzalloc(sizeof(*g));
@@ -92,6 +94,7 @@ struct clk *clk_gate_alloc(const char *name, const char *parent,
g->shift = shift;
g->clk.ops = &clk_gate_ops;
g->clk.name = name;
+ g->clk.flags = flags;
g->clk.parent_names = &g->parent;
g->clk.num_parents = 1;
@@ -106,12 +109,12 @@ void clk_gate_free(struct clk *clk_gate)
}
struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
- u8 shift)
+ u8 shift, unsigned flags)
{
struct clk *g;
int ret;
- g = clk_gate_alloc(name , parent, reg, shift);
+ g = clk_gate_alloc(name , parent, reg, shift, flags);
ret = clk_register(g);
if (ret) {
@@ -123,12 +126,12 @@ struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
}
struct clk *clk_gate_inverted(const char *name, const char *parent,
- void __iomem *reg, u8 shift)
+ void __iomem *reg, u8 shift, unsigned flags)
{
struct clk *clk;
struct clk_gate *g;
- clk = clk_gate(name, parent, reg, shift);
+ clk = clk_gate(name, parent, reg, shift, flags);
if (IS_ERR(clk))
return clk;
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index b22bdd1ec7..4ce86f43d1 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -51,12 +51,15 @@ static int clk_mux_set_parent(struct clk *clk, u8 idx)
}
static struct clk_ops clk_mux_ops = {
+ .set_rate = clk_parent_set_rate,
+ .round_rate = clk_parent_round_rate,
.get_parent = clk_mux_get_parent,
.set_parent = clk_mux_set_parent,
};
struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents)
+ u8 shift, u8 width, const char **parents, u8 num_parents,
+ unsigned flags)
{
struct clk_mux *m = xzalloc(sizeof(*m));
@@ -65,6 +68,7 @@ struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
m->width = width;
m->clk.ops = &clk_mux_ops;
m->clk.name = name;
+ m->clk.flags = flags;
m->clk.parent_names = parents;
m->clk.num_parents = num_parents;
@@ -79,12 +83,12 @@ void clk_mux_free(struct clk *clk_mux)
}
struct clk *clk_mux(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents)
+ u8 shift, u8 width, const char **parents, u8 num_parents, unsigned flags)
{
struct clk *m;
int ret;
- m = clk_mux_alloc(name, reg, shift, width, parents, num_parents);
+ m = clk_mux_alloc(name, reg, shift, width, parents, num_parents, flags);
ret = clk_register(m);
if (ret) {
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 31d73c028c..0d259413a9 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -104,9 +104,19 @@ unsigned long clk_get_rate(struct clk *clk)
long clk_round_rate(struct clk *clk, unsigned long rate)
{
+ unsigned long parent_rate = 0;
+ struct clk *parent;
+
if (IS_ERR(clk))
return 0;
+ parent = clk_get_parent(clk);
+ if (parent)
+ parent_rate = clk_get_rate(parent);
+
+ if (clk->ops->round_rate)
+ return clk->ops->round_rate(clk, rate, &parent_rate);
+
return clk_get_rate(clk);
}
@@ -249,11 +259,31 @@ int clk_is_enabled(struct clk *clk)
return clk_is_enabled(clk);
}
+/*
+ * Generic struct clk_ops callbacks
+ */
int clk_is_enabled_always(struct clk *clk)
{
return 1;
}
+long clk_parent_round_rate(struct clk *clk, unsigned long rate,
+ unsigned long *prate)
+{
+ if (!(clk->flags & CLK_SET_RATE_PARENT))
+ return *prate;
+
+ return clk_round_rate(clk_get_parent(clk), rate);
+}
+
+int clk_parent_set_rate(struct clk *clk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ if (!(clk->flags & CLK_SET_RATE_PARENT))
+ return 0;
+ return clk_set_rate(clk_get_parent(clk), rate);
+}
+
#if defined(CONFIG_OFTREE) && defined(CONFIG_COMMON_CLK_OF_PROVIDER)
/**
* struct of_clk_provider - Clock provider registration structure
diff --git a/drivers/clk/mvebu/common.c b/drivers/clk/mvebu/common.c
index 37cc1568a3..658ce3e81a 100644
--- a/drivers/clk/mvebu/common.c
+++ b/drivers/clk/mvebu/common.c
@@ -87,7 +87,7 @@ int mvebu_coreclk_probe(struct device_d *dev)
2+n, &rclk_name);
desc->get_clk_ratio(base, desc->ratios[n].id, &mult, &div);
clk_data.clks[2+n] = clk_fixed_factor(rclk_name, cpuclk_name,
- mult, div);
+ mult, div, 0);
WARN_ON(IS_ERR(clk_data.clks[2+n]));
};
@@ -188,7 +188,7 @@ int mvebu_clk_gating_probe(struct device_d *dev)
(desc[n].parent) ? desc[n].parent : default_parent;
gate->bit_idx = desc[n].bit_idx;
gate->clk = clk_gate(desc[n].name, parent,
- base, desc[n].bit_idx);
+ base, desc[n].bit_idx, 0);
WARN_ON(IS_ERR(gate->clk));
}
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 05b3c2a04d..934a1940fb 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -128,7 +128,7 @@ int __init mx28_clocks_init(void __iomem *regs)
clks[fec] = mxs_clk_gate("fec", "fec_sleep", ENET, 30);
clks[usb0_phy] = mxs_clk_gate("usb0_phy", "pll0", PLL0CTRL0, 18);
clks[usb1_phy] = mxs_clk_gate("usb1_phy", "pll1", PLL1CTRL0, 18);
- clks[enet_out] = clk_gate("enet_out", "pll2", ENET, 18);
+ clks[enet_out] = clk_gate("enet_out", "pll2", ENET, 18, 0);
clks[lcdif_comp] = mxs_clk_lcdif("lcdif_comp", clks[ref_pix],
clks[lcdif_div], clks[lcdif]);
diff --git a/drivers/clk/mxs/clk.h b/drivers/clk/mxs/clk.h
index b4fcfa0090..7bab7b5e6e 100644
--- a/drivers/clk/mxs/clk.h
+++ b/drivers/clk/mxs/clk.h
@@ -34,19 +34,19 @@ static inline struct clk *mxs_clk_fixed(const char *name, int rate)
static inline struct clk *mxs_clk_gate(const char *name,
const char *parent_name, void __iomem *reg, u8 shift)
{
- return clk_gate_inverted(name, parent_name, reg, shift);
+ return clk_gate_inverted(name, parent_name, reg, shift, 0);
}
static inline struct clk *mxs_clk_mux(const char *name, void __iomem *reg,
u8 shift, u8 width, const char **parent_names, int num_parents)
{
- return clk_mux(name, reg, shift, width, parent_names, num_parents);
+ return clk_mux(name, reg, shift, width, parent_names, num_parents, 0);
}
static inline struct clk *mxs_clk_fixed_factor(const char *name,
const char *parent_name, unsigned int mult, unsigned int div)
{
- return clk_fixed_factor(name, parent_name, mult, div);
+ return clk_fixed_factor(name, parent_name, mult, div, 0);
}
#endif /* __MXS_CLK_H */
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
index e969495875..c970f63afa 100644
--- a/drivers/clk/tegra/clk-periph.c
+++ b/drivers/clk/tegra/clk-periph.c
@@ -140,12 +140,12 @@ struct clk *_tegra_clk_register_periph(const char *name,
}
periph->mux = clk_mux_alloc(NULL, clk_base + reg_offset, 30, 2,
- parent_names, num_parents);
+ parent_names, num_parents, 0);
if (!periph->mux)
goto out_mux;
periph->gate = clk_gate_alloc(NULL, NULL, clk_base + 0x10 +
- ((id >> 3) & 0xc), id & 0x1f);
+ ((id >> 3) & 0xc), id & 0x1f, 0);
if (!periph->gate)
goto out_gate;
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index f68c811a8d..cfb719f431 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -62,7 +62,7 @@ static void tegra20_osc_clk_init(void)
clks[clk_32k] = clk_fixed("clk_32k", 32768);
clks[pll_ref] = clk_fixed_factor("pll_ref", "clk_m", 1,
- get_pll_ref_div());
+ get_pll_ref_div(), 0);
}
/* PLL frequency tables */
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 4ef25ec45b..43974f03c2 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -14,6 +14,29 @@ config CLOCKSOURCE_CLPS711X
bool
depends on ARCH_CLPS711X
+config CLOCKSOURCE_DUMMY
+ bool "Enable dummy software-only clocksource"
+ help
+ When porting barebox to a new SoC there might be a case
+ of broken or absent clocksource. This causes barebox serial
+ console to be non functional.
+ To solve the problem this software-only clocksource driver is used.
+ WARNING!!! This clocksource doesn't provide correct timing.
+ To adjust this clocksource please use CONFIG_CLOCKSOURCE_DUMMY_RATE.
+ The bigger rate valuest makes clocksource "faster".
+ It's possible to add this clocksource unconditionally.
+ This clocksource starts very early (pure_initcall) so
+ real clocksource will take over.
+ This can help if initialization order is wrong so that
+ the time functions are used before the real clocksource
+ was initialized.
+
+config CLOCKSOURCE_DUMMY_RATE
+ int
+ prompt "dummy clocksource rate"
+ depends on CLOCKSOURCE_DUMMY
+ default 1000
+
config CLOCKSOURCE_MVEBU
bool
depends on ARCH_MVEBU
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 25b7f460da..834a15d1e9 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_AMBA_SP804) += amba-sp804.o
obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o
obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
+obj-$(CONFIG_CLOCKSOURCE_DUMMY) += dummy.o
obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o
obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
obj-$(CONFIG_CLOCKSOURCE_ORION) += orion.o
diff --git a/drivers/clocksource/dummy.c b/drivers/clocksource/dummy.c
new file mode 100644
index 0000000000..154a8cd672
--- /dev/null
+++ b/drivers/clocksource/dummy.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+
+static uint64_t dummy_counter;
+
+static uint64_t dummy_cs_read(void)
+{
+ static int first;
+
+ if (!first) {
+ pr_warn("Warning: Using dummy clocksource\n");
+ first = 1;
+ }
+
+ dummy_counter += CONFIG_CLOCKSOURCE_DUMMY_RATE;
+
+ return dummy_counter;
+}
+
+static struct clocksource dummy_cs = {
+ .read = dummy_cs_read,
+ .mask = CLOCKSOURCE_MASK(32),
+};
+
+static int clocksource_init(void)
+{
+ dummy_counter = 0;
+
+ clocks_calc_mult_shift(&dummy_cs.mult, &dummy_cs.shift,
+ 100000000, NSEC_PER_SEC, 10);
+
+ pr_debug("clocksource_init: mult=%08x, shift=%08x\n",
+ dummy_cs.mult, dummy_cs.shift);
+ init_clock(&dummy_cs);
+
+ return 0;
+}
+pure_initcall(clocksource_init);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 7c426563e7..7302955d87 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -20,6 +20,13 @@ config GPIO_CLPS711X
help
Say yes here to enable the GPIO driver for the CLPS711X CPUs
+config GPIO_DAVINCI
+ bool "TI Davinci/Keystone GPIO support"
+ default y if ARCH_DAVINCI
+ depends on ARM && ARCH_DAVINCI
+ help
+ Say yes here to enable GPIO support for TI Davinci/Keystone SoCs.
+
config GPIO_GENERIC_PLATFORM
bool "Generic memory-mapped GPIO controller support"
select GPIO_GENERIC
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index b7c536d21b..68a76a3745 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -1,6 +1,7 @@
obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIO_BCM2835) += gpio-bcm2835.o
+obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_IMX) += gpio-imx.o
diff --git a/drivers/gpio/gpio-davinci.c b/drivers/gpio/gpio-davinci.c
new file mode 100644
index 0000000000..7d15b855f0
--- /dev/null
+++ b/drivers/gpio/gpio-davinci.c
@@ -0,0 +1,211 @@
+/*
+ * TI DaVinci GPIO Support
+ *
+ * Copyright (c) 2006-2007 David Brownell
+ * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
+ * Copyright (c) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <linux/err.h>
+
+#define readl_relaxed readl
+#define writel_relaxed writel
+
+struct davinci_gpio_regs {
+ u32 dir;
+ u32 out_data;
+ u32 set_data;
+ u32 clr_data;
+ u32 in_data;
+ u32 set_rising;
+ u32 clr_rising;
+ u32 set_falling;
+ u32 clr_falling;
+ u32 intstat;
+};
+
+struct davinci_gpio_controller {
+ struct gpio_chip chip;
+ /* Serialize access to GPIO registers */
+ void __iomem *regs;
+ void __iomem *set_data;
+ void __iomem *clr_data;
+ void __iomem *in_data;
+};
+
+#define chip2controller(chip) \
+ container_of(chip, struct davinci_gpio_controller, chip)
+
+static struct davinci_gpio_regs __iomem *gpio2regs(void __iomem *gpio_base,
+ unsigned gpio)
+{
+ void __iomem *ptr;
+
+ if (gpio < 32 * 1)
+ ptr = gpio_base + 0x10;
+ else if (gpio < 32 * 2)
+ ptr = gpio_base + 0x38;
+ else if (gpio < 32 * 3)
+ ptr = gpio_base + 0x60;
+ else if (gpio < 32 * 4)
+ ptr = gpio_base + 0x88;
+ else if (gpio < 32 * 5)
+ ptr = gpio_base + 0xb0;
+ else
+ ptr = NULL;
+ return ptr;
+}
+
+static int davinci_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+ struct davinci_gpio_controller *d = chip2controller(chip);
+ struct davinci_gpio_regs __iomem *g = d->regs;
+
+ return ((readl_relaxed(&g->dir)) & (1 << offset)) ?
+ GPIOF_DIR_IN : GPIOF_DIR_OUT;
+}
+
+static inline int __davinci_direction(struct gpio_chip *chip,
+ unsigned offset, bool out, int value)
+{
+ struct davinci_gpio_controller *d = chip2controller(chip);
+ struct davinci_gpio_regs __iomem *g = d->regs;
+ u32 temp;
+ u32 mask = 1 << offset;
+
+ temp = readl_relaxed(&g->dir);
+ if (out) {
+ temp &= ~mask;
+ writel_relaxed(mask, value ? &g->set_data : &g->clr_data);
+ } else {
+ temp |= mask;
+ }
+ writel_relaxed(temp, &g->dir);
+
+ return 0;
+}
+
+static int davinci_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ return __davinci_direction(chip, offset, false, 0);
+}
+
+static int
+davinci_direction_out(struct gpio_chip *chip, unsigned offset, int value)
+{
+ return __davinci_direction(chip, offset, true, value);
+}
+
+/*
+ * Read the pin's value (works even if it's set up as output);
+ * returns zero/nonzero.
+ *
+ * Note that changes are synched to the GPIO clock, so reading values back
+ * right after you've set them may give old values.
+ */
+static int davinci_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct davinci_gpio_controller *d = chip2controller(chip);
+ struct davinci_gpio_regs __iomem *g = d->regs;
+
+ return (1 << offset) & readl_relaxed(&g->in_data);
+}
+
+/*
+ * Assuming the pin is muxed as a gpio output, set its output value.
+ */
+static void
+davinci_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct davinci_gpio_controller *d = chip2controller(chip);
+ struct davinci_gpio_regs __iomem *g = d->regs;
+
+ writel_relaxed((1 << offset), value ? &g->set_data : &g->clr_data);
+}
+
+static struct gpio_ops davinci_gpio_ops = {
+ .direction_input = davinci_direction_in,
+ .direction_output = davinci_direction_out,
+ .get_direction = davinci_get_direction,
+ .get = davinci_gpio_get,
+ .set = davinci_gpio_set,
+};
+
+static int davinci_gpio_probe(struct device_d *dev)
+{
+ void __iomem *gpio_base;
+ int ret;
+ u32 val;
+ int i, base;
+ unsigned ngpio;
+ struct davinci_gpio_controller *chips;
+
+ ret = of_property_read_u32(dev->device_node, "ti,ngpio", &val);
+ if (ret) {
+ dev_err(dev, "could not read 'ti,ngpio' property\n");
+ return -EINVAL;
+ }
+
+ ngpio = val;
+
+ if (WARN_ON(ARCH_NR_GPIOS < ngpio))
+ ngpio = ARCH_NR_GPIOS;
+
+ chips = xzalloc((ngpio / 32 + 1) * sizeof(*chips));
+
+ gpio_base = dev_request_mem_region(dev, 0);
+ if (!gpio_base) {
+ dev_err(dev, "could not get memory region\n");
+ return -ENODEV;
+ }
+
+ for (i = 0, base = 0; base < ngpio; i++, base += 32) {
+ struct davinci_gpio_regs __iomem *regs;
+ struct gpio_chip *gc;
+
+ gc = &chips[i].chip;
+ gc->ops = &davinci_gpio_ops;
+
+ gc->dev = dev;
+ gc->base = base;
+ gc->ngpio = ngpio - base;
+ if (gc->ngpio > 32)
+ gc->ngpio = 32;
+
+ regs = gpio2regs(gpio_base, base);
+ chips[i].regs = regs;
+ chips[i].set_data = &regs->set_data;
+ chips[i].clr_data = &regs->clr_data;
+ chips[i].in_data = &regs->in_data;
+
+ gpiochip_add(gc);
+ }
+
+ return 0;
+}
+
+static struct of_device_id davinci_gpio_ids[] = {
+ { .compatible = "ti,dm6441-gpio", },
+ { /* sentinel */ },
+};
+
+static struct driver_d davinci_gpio_driver = {
+ .name = "davinci_gpio",
+ .probe = davinci_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(davinci_gpio_ids),
+};
+
+static int davinci_gpio_drv_reg(void)
+{
+ return platform_driver_register(&davinci_gpio_driver);
+}
+coredevice_initcall(davinci_gpio_drv_reg);
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index f657c287f7..6b390478fa 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -587,4 +587,4 @@ static struct driver_d i2c_fsl_driver = {
.name = DRIVER_NAME,
.of_compatible = DRV_OF_COMPAT(imx_i2c_dt_ids),
};
-device_platform_driver(i2c_fsl_driver);
+coredevice_platform_driver(i2c_fsl_driver);
diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index e289a3569b..9873957015 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -405,6 +405,17 @@ struct i2c_adapter *i2c_get_adapter(int busnum)
return NULL;
}
+struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node)
+{
+ struct i2c_adapter *adap;
+
+ list_for_each_entry(adap, &adapter_list, list)
+ if (adap->dev.device_node == node)
+ return adap;
+
+ return NULL;
+}
+
/**
* i2c_add_numbered_adapter - declare i2c adapter, use static bus number
* @adapter: the adapter to register (with adap->nr initialized)
diff --git a/drivers/input/gpio_keys.c b/drivers/input/gpio_keys.c
index 9486b9a786..d017594662 100644
--- a/drivers/input/gpio_keys.c
+++ b/drivers/input/gpio_keys.c
@@ -121,7 +121,7 @@ static int gpio_keys_probe_dt(struct gpio_keys *gk, struct device_d *dev)
struct device_node *npkey, *np = dev->device_node;
int i = 0, ret;
- if (!IS_ENABLED(CONFIG_OFDEVICE))
+ if (!IS_ENABLED(CONFIG_OFDEVICE) || !IS_ENABLED(CONFIG_OF_GPIO))
return -ENODEV;
gk->nbuttons = of_get_child_count(np);
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 36a363fa37..c97c8c1403 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -401,7 +401,7 @@ int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
mtd->cdev.mtd = mtd;
if (IS_ENABLED(CONFIG_PARAMETER)) {
- dev_add_param_int_ro(&mtd->class_dev, "size", mtd->size, "%u");
+ dev_add_param_int_ro(&mtd->class_dev, "size", mtd->size, "%llu");
dev_add_param_int_ro(&mtd->class_dev, "erasesize", mtd->erasesize, "%u");
dev_add_param_int_ro(&mtd->class_dev, "writesize", mtd->oobsize, "%u");
dev_add_param_int_ro(&mtd->class_dev, "oobsize", mtd->oobsize, "%u");
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 56c69f35c0..50e04548e9 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -268,8 +268,9 @@ static int erase_sector(struct m25p *flash, u32 offset, u32 command)
static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
{
struct m25p *flash = mtd_to_m25p(mtd);
- u32 addr, len;
+ u32 addr;
uint32_t rem;
+ uint64_t len;
dev_dbg(&flash->spi->dev, "%s at 0x%llx, len %lld\n",
__func__, (long long)instr->addr,
@@ -897,7 +898,7 @@ static int m25p_probe(struct device_d *dev)
flash->mtd.type = MTD_NORFLASH;
flash->mtd.writesize = 1;
flash->mtd.flags = MTD_CAP_NORFLASH;
- flash->mtd.size = info->sector_size * info->n_sectors;
+ flash->mtd.size = (uint64_t)info->sector_size * info->n_sectors;
flash->mtd.erase = m25p80_erase;
flash->mtd.read = m25p80_read;
diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index cdc0120c53..fa31b61464 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -625,7 +625,7 @@ add_dataflash_otp(struct spi_device *spi, char *name,
device = &priv->mtd;
device->name = (pdata && pdata->name) ? pdata->name : "dataflash";
- device->size = nr_pages * pagesize;
+ device->size = nr_pages * (uint64_t)pagesize;
device->erasesize = pagesize;
device->writesize = pagesize;
device->type = MTD_DATAFLASH;
diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c
index b9cac2ae69..10d17e90d2 100644
--- a/drivers/mtd/mtdoob.c
+++ b/drivers/mtd/mtdoob.c
@@ -78,7 +78,7 @@ static int add_mtdoob_device(struct mtd_info *mtd, char *devname, void **priv)
mtdoob = xzalloc(sizeof(*mtdoob));
mtdoob->cdev.ops = &mtd_ops_oob;
- mtdoob->cdev.size = (mtd->size / mtd->writesize) * mtd->oobsize;
+ mtdoob->cdev.size = mtd_div_by_wb(mtd->size, mtd) * mtd->oobsize;
mtdoob->cdev.name = asprintf("%s_oob%d", devname, mtd->class_dev.id);
mtdoob->cdev.priv = mtdoob;
mtdoob->cdev.dev = &mtd->class_dev;
diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c
index 006b28f9b2..c25e4062ee 100644
--- a/drivers/mtd/mtdraw.c
+++ b/drivers/mtd/mtdraw.c
@@ -293,7 +293,7 @@ static int add_mtdraw_device(struct mtd_info *mtd, char *devname, void **priv)
mtdraw->mtd = mtd;
mtdraw->cdev.ops = (struct file_operations *)&mtd_raw_fops;
- mtdraw->cdev.size = mtd->size / mtd->writesize *
+ mtdraw->cdev.size = mtd_div_by_wb(mtd->size, mtd) *
(mtd->writesize + mtd->oobsize);
mtdraw->cdev.name = asprintf("%s.raw", mtd->cdev.name);
mtdraw->cdev.priv = mtdraw;
diff --git a/drivers/mtd/nand/nand_mxs.c b/drivers/mtd/nand/nand_mxs.c
index d1e4b5717d..b06b558b08 100644
--- a/drivers/mtd/nand/nand_mxs.c
+++ b/drivers/mtd/nand/nand_mxs.c
@@ -33,6 +33,7 @@
#include <dma/apbh-dma.h>
#include <stmp-device.h>
#include <asm/mmu.h>
+#include <mach/generic.h>
#define MX28_BLOCK_SFTRST (1 << 31)
#define MX28_BLOCK_CLKGATE (1 << 30)
@@ -233,18 +234,31 @@ static uint32_t mxs_nand_aux_status_offset(void)
static inline uint32_t mxs_nand_get_ecc_strength(uint32_t page_data_size,
uint32_t page_oob_size)
{
+ int ecc_chunk_count = mxs_nand_ecc_chunk_cnt(page_data_size);
+ int ecc_strength = 0;
+ int gf_len = 13; /* length of Galois Field for non-DDR nand */
+
+ /*
+ * Possibly this if-else calculation may be removed since
+ * ecc_strength calculated after it is taken from kernel driver
+ * and therefore should work for all cases. But it was tested only
+ * on devices with {data_size = 2046, oob_size = 64} and
+ * {data_size = 4096, oob_size = 224} configuration.
+ */
if (page_data_size == 2048)
return 8;
-
- if (page_data_size == 4096) {
+ else if (page_data_size == 4096) {
if (page_oob_size == 128)
return 8;
-
if (page_oob_size == 218)
return 16;
}
- return 0;
+ ecc_strength = ((page_oob_size - MXS_NAND_METADATA_SIZE) * 8)
+ / (gf_len * ecc_chunk_count);
+
+ /* We need the minor even number. */
+ return rounddown(ecc_strength, 2);
}
static inline uint32_t mxs_nand_get_mark_offset(uint32_t page_data_size,
@@ -427,7 +441,13 @@ static int mxs_nand_device_ready(struct mtd_info *mtd)
if (nand_info->version > GPMI_VERSION_TYPE_MX23) {
tmp = readl(gpmi_regs + GPMI_STAT);
- tmp >>= (GPMI_STAT_READY_BUSY_OFFSET + nand_info->cur_chip);
+ /* i.MX6 has only one R/B actual pin, so if there are several
+ R/B signals they must be all connected to this pin */
+ if (cpu_is_mx6())
+ tmp >>= GPMI_STAT_READY_BUSY_OFFSET;
+ else
+ tmp >>= (GPMI_STAT_READY_BUSY_OFFSET +
+ nand_info->cur_chip);
} else {
tmp = readl(gpmi_regs + GPMI_DEBUG);
tmp >>= (GPMI_DEBUG_READY0_OFFSET + nand_info->cur_chip);
@@ -1304,7 +1324,7 @@ static int mxs_nand_probe(struct device_d *dev)
nand->ecc.strength = 8;
/* first scan to find the device and get the page size */
- err = nand_scan_ident(mtd, 1, NULL);
+ err = nand_scan_ident(mtd, 4, NULL);
if (err)
goto err2;
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index 3053a8e891..59712b8119 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -940,7 +940,7 @@ static int gpmc_nand_probe(struct device_d *pdev)
switch (pdata->device_width) {
case 0:
- printk("probe buswidth\n");
+ dev_dbg(pdev, "probing buswidth\n");
nand->options |= NAND_BUSWIDTH_AUTO;
break;
case 8:
diff --git a/drivers/mtd/partition.c b/drivers/mtd/partition.c
index 351c5831b0..720c2adab3 100644
--- a/drivers/mtd/partition.c
+++ b/drivers/mtd/partition.c
@@ -75,8 +75,8 @@ static int mtd_part_block_markbad(struct mtd_info *mtd, loff_t ofs)
return res;
}
-struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset, size_t size,
- unsigned long flags, const char *name)
+struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset,
+ uint64_t size, unsigned long flags, const char *name)
{
struct mtd_info *part;
int start = 0, end = 0, i;
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index da21f69e7e..b908fcda0b 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -104,6 +104,8 @@ struct ubi_device *ubi_get_device(int ubi_num)
struct ubi_device *ubi;
ubi = ubi_devices[ubi_num];
+ if (!ubi)
+ return NULL;
ubi->ref_count++;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 4b8eb4c5cf..dcd138f553 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -222,7 +222,7 @@ static int ubi_cdev_ioctl(struct cdev *cdev, int cmd, void *buf)
break;
case UBI_IOCMKVOL:
if (!req->bytes)
- req->bytes = ubi->avail_pebs * ubi->leb_size;
+ req->bytes = (__s64)ubi->avail_pebs * ubi->leb_size;
return ubi_create_volume(ubi, req);
};
diff --git a/drivers/net/ar231x.c b/drivers/net/ar231x.c
index 5c091140ac..515de17b10 100644
--- a/drivers/net/ar231x.c
+++ b/drivers/net/ar231x.c
@@ -419,15 +419,9 @@ static int ar231x_eth_probe(struct device_d *dev)
return 0;
}
-static void ar231x_eth_remove(struct device_d *dev)
-{
-
-}
-
static struct driver_d ar231x_eth_driver = {
.name = "ar231x_eth",
.probe = ar231x_eth_probe,
- .remove = ar231x_eth_remove,
};
static int ar231x_eth_driver_init(void)
diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c
index 25924cf7e2..bf2f957a36 100644
--- a/drivers/net/at91_ether.c
+++ b/drivers/net/at91_ether.c
@@ -357,13 +357,8 @@ static int at91_ether_probe(struct device_d *dev)
return 0;
}
-static void at91_ether_remove(struct device_d *dev)
-{
-}
-
static struct driver_d at91_ether_driver = {
.name = "at91_ether",
.probe = at91_ether_probe,
- .remove = at91_ether_remove,
};
device_platform_driver(at91_ether_driver);
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index ecb4656e9d..e706f54b31 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -477,10 +477,6 @@ static int dwc_ether_probe(struct device_d *dev)
return 0;
}
-static void dwc_ether_remove(struct device_d *dev)
-{
-}
-
static __maybe_unused struct of_device_id dwc_ether_compatible[] = {
{
.compatible = "snps,dwmac-3.70a",
@@ -493,7 +489,6 @@ static __maybe_unused struct of_device_id dwc_ether_compatible[] = {
static struct driver_d dwc_ether_driver = {
.name = "designware_eth",
.probe = dwc_ether_probe,
- .remove = dwc_ether_remove,
.of_compatible = DRV_OF_COMPAT(dwc_ether_compatible),
};
device_platform_driver(dwc_ether_driver);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 104b6daeaf..c440a69e6c 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1841,8 +1841,11 @@ int of_device_is_stdout_path(struct device_d *dev)
struct device_node *dn;
const char *name;
- name = of_get_property(of_chosen, "linux,stdout-path", NULL);
- if (name == NULL)
+ name = of_get_property(of_chosen, "stdout-path", NULL);
+ if (!name)
+ name = of_get_property(of_chosen, "linux,stdout-path", NULL);
+
+ if (!name)
return 0;
dn = of_find_node_by_path(name);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 11fc155074..f51c6e6b02 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -14,6 +14,13 @@ config SERIAL_AMBA_PL011
If unsure, say N.
+config DRIVER_SERIAL_AR933X
+ bool "AR933X serial driver"
+ depends on MACH_MIPS_ATH79
+ help
+ If you have an Atheros AR933X SOC based board and want to use the
+ built-in UART of the SoC, say Y to this option.
+
config DRIVER_SERIAL_IMX
depends on ARCH_IMX
default y
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index 93790b5349..e1865f725a 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -1,5 +1,6 @@
obj-$(CONFIG_DRIVER_SERIAL_ARM_DCC) += arm_dcc.o
obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+obj-$(CONFIG_DRIVER_SERIAL_AR933X) += serial_ar933x.o
obj-$(CONFIG_DRIVER_SERIAL_IMX) += serial_imx.o
obj-$(CONFIG_DRIVER_SERIAL_STM378X) += stm-serial.o
obj-$(CONFIG_DRIVER_SERIAL_ATMEL) += atmel.o
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
new file mode 100644
index 0000000000..27cccba119
--- /dev/null
+++ b/drivers/serial/serial_ar933x.c
@@ -0,0 +1,204 @@
+/*
+ * based on linux.git/drivers/tty/serial/serial_ar933x.c
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <io.h>
+#include <asm-generic/div64.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include "serial_ar933x.h"
+
+#define AR933X_UART_MAX_SCALE 0xff
+#define AR933X_UART_MAX_STEP 0xffff
+
+struct ar933x_uart_priv {
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static inline void ar933x_serial_writel(struct console_device *cdev,
+ u32 b, int offset)
+{
+ struct ar933x_uart_priv *priv = cdev->dev->priv;
+
+ cpu_writel(b, priv->base + offset);
+}
+
+static inline u32 ar933x_serial_readl(struct console_device *cdev,
+ int offset)
+{
+ struct ar933x_uart_priv *priv = cdev->dev->priv;
+
+ return cpu_readl(priv->base + offset);
+}
+
+/*
+ * baudrate = (clk / (scale + 1)) * (step * (1 / 2^17))
+ * take from linux.
+ */
+static unsigned long ar933x_uart_get_baud(unsigned int clk,
+ unsigned int scale,
+ unsigned int step)
+{
+ u64 t;
+ u32 div;
+
+ div = (2 << 16) * (scale + 1);
+ t = clk;
+ t *= step;
+ t += (div / 2);
+ do_div(t, div);
+
+ return t;
+}
+
+static void ar933x_uart_get_scale_step(unsigned int clk,
+ unsigned int baud,
+ unsigned int *scale,
+ unsigned int *step)
+{
+ unsigned int tscale;
+ long min_diff;
+
+ *scale = 0;
+ *step = 0;
+
+ min_diff = baud;
+ for (tscale = 0; tscale < AR933X_UART_MAX_SCALE; tscale++) {
+ u64 tstep;
+ int diff;
+
+ tstep = baud * (tscale + 1);
+ tstep *= (2 << 16);
+ do_div(tstep, clk);
+
+ if (tstep > AR933X_UART_MAX_STEP)
+ break;
+
+ diff = abs(ar933x_uart_get_baud(clk, tscale, tstep) - baud);
+ if (diff < min_diff) {
+ min_diff = diff;
+ *scale = tscale;
+ *step = tstep;
+ }
+ }
+}
+
+static int ar933x_serial_setbaudrate(struct console_device *cdev, int baudrate)
+{
+ struct ar933x_uart_priv *priv = cdev->dev->priv;
+ unsigned int scale, step;
+
+ ar933x_uart_get_scale_step(clk_get_rate(priv->clk), baudrate, &scale,
+ &step);
+ ar933x_serial_writel(cdev, (scale << AR933X_UART_CLOCK_SCALE_S) | step,
+ AR933X_UART_CLOCK_REG);
+
+ return 0;
+}
+
+static void ar933x_serial_putc(struct console_device *cdev, char ch)
+{
+ u32 data;
+
+ /* wait transmitter ready */
+ data = ar933x_serial_readl(cdev, AR933X_UART_DATA_REG);
+ while (!(data & AR933X_UART_DATA_TX_CSR))
+ data = ar933x_serial_readl(cdev, AR933X_UART_DATA_REG);
+
+ data = (ch & AR933X_UART_DATA_TX_RX_MASK) | AR933X_UART_DATA_TX_CSR;
+ ar933x_serial_writel(cdev, data, AR933X_UART_DATA_REG);
+}
+
+static int ar933x_serial_tstc(struct console_device *cdev)
+{
+ u32 rdata;
+
+ rdata = ar933x_serial_readl(cdev, AR933X_UART_DATA_REG);
+
+ return rdata & AR933X_UART_DATA_RX_CSR;
+}
+
+static int ar933x_serial_getc(struct console_device *cdev)
+{
+ u32 rdata;
+
+ while (!ar933x_serial_tstc(cdev))
+ ;
+
+ rdata = ar933x_serial_readl(cdev, AR933X_UART_DATA_REG);
+
+ /* remove the character from the FIFO */
+ ar933x_serial_writel(cdev, AR933X_UART_DATA_RX_CSR,
+ AR933X_UART_DATA_REG);
+
+ return rdata & AR933X_UART_DATA_TX_RX_MASK;
+}
+
+static int ar933x_serial_probe(struct device_d *dev)
+{
+ struct console_device *cdev;
+ struct ar933x_uart_priv *priv;
+ u32 uart_cs;
+
+ cdev = xzalloc(sizeof(struct console_device));
+ priv = xzalloc(sizeof(struct ar933x_uart_priv));
+ priv->base = dev_request_mem_region(dev, 0);
+ dev->priv = priv;
+
+ cdev->dev = dev;
+ cdev->tstc = ar933x_serial_tstc;
+ cdev->putc = ar933x_serial_putc;
+ cdev->getc = ar933x_serial_getc;
+ cdev->setbrg = ar933x_serial_setbaudrate;
+
+ priv->clk = clk_get(dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(dev, "unable to get UART clock\n");
+ return PTR_ERR(priv->clk);
+ }
+
+ uart_cs = (AR933X_UART_CS_IF_MODE_DCE << AR933X_UART_CS_IF_MODE_S)
+ | AR933X_UART_CS_TX_READY_ORIDE
+ | AR933X_UART_CS_RX_READY_ORIDE;
+ ar933x_serial_writel(cdev, uart_cs, AR933X_UART_CS_REG);
+ /* FIXME: need ar933x_serial_init_port(cdev); */
+
+ console_register(cdev);
+
+ return 0;
+}
+
+static struct of_device_id ar933x_serial_dt_ids[] = {
+ {
+ .compatible = "qca,ar9330-uart",
+ }, {
+ /* sentinel */
+ },
+};
+
+static struct driver_d ar933x_serial_driver = {
+ .name = "ar933x_serial",
+ .probe = ar933x_serial_probe,
+ .of_compatible = DRV_OF_COMPAT(ar933x_serial_dt_ids),
+};
+console_platform_driver(ar933x_serial_driver);
diff --git a/drivers/serial/serial_ar933x.h b/drivers/serial/serial_ar933x.h
new file mode 100644
index 0000000000..f55f0fa3d7
--- /dev/null
+++ b/drivers/serial/serial_ar933x.h
@@ -0,0 +1,69 @@
+/*
+ * Atheros AR933X UART defines
+ *
+ * Copyright (C) 2011 Gabor Juhos <juhosg@openwrt.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ */
+
+#ifndef __AR933X_UART_H
+#define __AR933X_UART_H
+
+#include <linux/bitops.h>
+
+#define AR933X_UART_REGS_SIZE 20
+#define AR933X_UART_FIFO_SIZE 16
+
+#define AR933X_UART_DATA_REG 0x00
+#define AR933X_UART_CS_REG 0x04
+#define AR933X_UART_CLOCK_REG 0x08
+#define AR933X_UART_INT_REG 0x0c
+#define AR933X_UART_INT_EN_REG 0x10
+
+#define AR933X_UART_DATA_TX_RX_MASK 0xff
+#define AR933X_UART_DATA_RX_CSR BIT(8)
+#define AR933X_UART_DATA_TX_CSR BIT(9)
+
+#define AR933X_UART_CS_PARITY_S 0
+#define AR933X_UART_CS_PARITY_M 0x3
+#define AR933X_UART_CS_PARITY_NONE 0
+#define AR933X_UART_CS_PARITY_ODD 1
+#define AR933X_UART_CS_PARITY_EVEN 2
+#define AR933X_UART_CS_IF_MODE_S 2
+#define AR933X_UART_CS_IF_MODE_M 0x3
+#define AR933X_UART_CS_IF_MODE_NONE 0
+#define AR933X_UART_CS_IF_MODE_DTE 1
+#define AR933X_UART_CS_IF_MODE_DCE 2
+#define AR933X_UART_CS_FLOW_CTRL_S 4
+#define AR933X_UART_CS_FLOW_CTRL_M 0x3
+#define AR933X_UART_CS_DMA_EN BIT(6)
+#define AR933X_UART_CS_TX_READY_ORIDE BIT(7)
+#define AR933X_UART_CS_RX_READY_ORIDE BIT(8)
+#define AR933X_UART_CS_TX_READY BIT(9)
+#define AR933X_UART_CS_RX_BREAK BIT(10)
+#define AR933X_UART_CS_TX_BREAK BIT(11)
+#define AR933X_UART_CS_HOST_INT BIT(12)
+#define AR933X_UART_CS_HOST_INT_EN BIT(13)
+#define AR933X_UART_CS_TX_BUSY BIT(14)
+#define AR933X_UART_CS_RX_BUSY BIT(15)
+
+#define AR933X_UART_CLOCK_STEP_M 0xffff
+#define AR933X_UART_CLOCK_SCALE_M 0xfff
+#define AR933X_UART_CLOCK_SCALE_S 16
+#define AR933X_UART_CLOCK_STEP_M 0xffff
+
+#define AR933X_UART_INT_RX_VALID BIT(0)
+#define AR933X_UART_INT_TX_READY BIT(1)
+#define AR933X_UART_INT_RX_FRAMING_ERR BIT(2)
+#define AR933X_UART_INT_RX_OFLOW_ERR BIT(3)
+#define AR933X_UART_INT_TX_OFLOW_ERR BIT(4)
+#define AR933X_UART_INT_RX_PARITY_ERR BIT(5)
+#define AR933X_UART_INT_RX_BREAK_ON BIT(6)
+#define AR933X_UART_INT_RX_BREAK_OFF BIT(7)
+#define AR933X_UART_INT_RX_FULL BIT(8)
+#define AR933X_UART_INT_TX_EMPTY BIT(9)
+#define AR933X_UART_INT_ALLINTS 0x3ff
+
+#endif /* __AR933X_UART_H */
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index f1da44b7f7..0c00eb182c 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -48,6 +48,7 @@ struct ns16550_priv {
struct NS16550_plat plat;
int access_width;
struct clk *clk;
+ uint32_t fcrval;
};
static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
@@ -157,18 +158,13 @@ static int ns16550_setbaudrate(struct console_device *cdev, int baud_rate)
{
unsigned int baud_divisor = ns16550_calc_divisor(cdev, baud_rate);
struct ns16550_priv *priv = to_ns16550_priv(cdev);
- struct NS16550_plat *plat = &priv->plat;
ns16550_write(cdev, LCR_BKSE, lcr);
ns16550_write(cdev, baud_divisor & 0xff, dll);
ns16550_write(cdev, (baud_divisor >> 8) & 0xff, dlm);
ns16550_write(cdev, LCRVAL, lcr);
ns16550_write(cdev, MCRVAL, mcr);
-
- if (plat->flags & NS16650_FLAG_DISABLE_FIFO)
- ns16550_write(cdev, FCRVAL & ~FCR_FIFO_EN, fcr);
- else
- ns16550_write(cdev, FCRVAL, fcr);
+ ns16550_write(cdev, priv->fcrval, fcr);
return 0;
}
@@ -185,6 +181,15 @@ static void ns16550_serial_init_port(struct console_device *cdev)
ns16550_write(cdev, 0x00, ier);
}
+static void ns16450_serial_init_port(struct console_device *cdev)
+{
+ struct ns16550_priv *priv = to_ns16550_priv(cdev);
+
+ priv->fcrval &= ~FCR_FIFO_EN;
+
+ ns16550_serial_init_port(cdev);
+}
+
#define omap_mdr1 8
static void ns16550_omap_init_port(struct console_device *cdev)
@@ -192,7 +197,17 @@ static void ns16550_omap_init_port(struct console_device *cdev)
ns16550_serial_init_port(cdev);
ns16550_write(cdev, 0x07, omap_mdr1); /* Disable */
- ns16550_write(cdev, 0x00, omap_mdr1);
+ ns16550_write(cdev, 0x00, omap_mdr1);
+}
+
+#define JZ_FCR_UME 0x10 /* Uart Module Enable */
+
+static void ns16550_jz_init_port(struct console_device *cdev)
+{
+ struct ns16550_priv *priv = to_ns16550_priv(cdev);
+
+ priv->fcrval |= JZ_FCR_UME;
+ ns16550_serial_init_port(cdev);
}
/*********** Exposed Functions **********************************/
@@ -246,6 +261,10 @@ static void ns16550_probe_dt(struct device_d *dev, struct ns16550_priv *priv)
of_property_read_u32(np, "reg-shift", &priv->plat.shift);
}
+static struct ns16550_drvdata ns16450_drvdata = {
+ .init_port = ns16450_serial_init_port,
+};
+
static struct ns16550_drvdata ns16550_drvdata = {
.init_port = ns16550_serial_init_port,
};
@@ -255,6 +274,10 @@ static __maybe_unused struct ns16550_drvdata omap_drvdata = {
.linux_console_name = "ttyO",
};
+static __maybe_unused struct ns16550_drvdata jz_drvdata = {
+ .init_port = ns16550_jz_init_port,
+};
+
/**
* @brief Probe entry point -called on the first match for device
*
@@ -316,6 +339,11 @@ static int ns16550_probe(struct device_d *dev)
cdev->setbrg = ns16550_setbaudrate;
cdev->linux_console_name = devtype->linux_console_name;
+ if (plat && (plat->flags & NS16650_FLAG_DISABLE_FIFO))
+ priv->fcrval = FCRVAL & ~FCR_FIFO_EN;
+ else
+ priv->fcrval = FCRVAL;
+
devtype->init_port(cdev);
return console_register(cdev);
@@ -328,6 +356,9 @@ err:
static struct of_device_id ns16550_serial_dt_ids[] = {
{
+ .compatible = "ns16450",
+ .data = (unsigned long)&ns16450_drvdata,
+ }, {
.compatible = "ns16550a",
.data = (unsigned long)&ns16550_drvdata,
}, {
@@ -346,6 +377,12 @@ static struct of_device_id ns16550_serial_dt_ids[] = {
.data = (unsigned long)&omap_drvdata,
},
#endif
+#if IS_ENABLED(CONFIG_MACH_MIPS_XBURST)
+ {
+ .compatible = "ingenic,jz4740-uart",
+ .data = (unsigned long)&jz_drvdata,
+ },
+#endif
{
/* sentinel */
},
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 11b6c186e3..71d0ecf39c 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -994,6 +994,8 @@ static struct usb_gadget_driver composite_driver = {
*/
int usb_composite_register(struct usb_composite_driver *driver)
{
+ int ret;
+
if (!driver || !driver->dev || !driver->bind || composite)
return -EINVAL;
@@ -1002,7 +1004,12 @@ int usb_composite_register(struct usb_composite_driver *driver)
composite_driver.function = (char *) driver->name;
composite = driver;
- return usb_gadget_register_driver(&composite_driver);
+ ret = usb_gadget_register_driver(&composite_driver);
+
+ if (ret)
+ composite = NULL;
+
+ return ret;
}
/**
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index 76b5def33c..d0f2155e49 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -703,7 +703,9 @@ int usb_dfu_register(struct usb_dfu_pdata *pdata)
strings_dev[STRING_MANUFACTURER_IDX].s = pdata->manufacturer;
strings_dev[STRING_PRODUCT_IDX].s = pdata->productname;
- usb_composite_register(&dfu_driver);
+ ret = usb_composite_register(&dfu_driver);
+ if (ret)
+ return ret;
while (1) {
ret = usb_gadget_poll();
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5539266226..34177b3f08 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -77,6 +77,8 @@ config DRIVER_VIDEO_BCM2835
help
Add support for the BCM2835/VideoCore frame buffer device.
+source drivers/video/imx-ipu-v3/Kconfig
+
config DRIVER_VIDEO_SIMPLEFB
bool "Simple framebuffer support"
depends on OFTREE
@@ -84,4 +86,10 @@ config DRIVER_VIDEO_SIMPLEFB
Add support for setting up the kernel's simple framebuffer driver
based on the active barebox framebuffer.
+config DRIVER_VIDEO_EDID
+ bool "Add EDID support"
+ help
+ This enabled support for reading and parsing EDID data from an attached
+ monitor.
+
endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 31edfca2b0..ae9f6e545e 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,4 +1,6 @@
obj-$(CONFIG_VIDEO) += fb.o
+obj-$(CONFIG_DRIVER_VIDEO_EDID) += edid.o
+obj-$(CONFIG_OFDEVICE) += of_display_timing.o
obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
obj-$(CONFIG_DRIVER_VIDEO_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
@@ -11,3 +13,4 @@ obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o
obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o
obj-$(CONFIG_DRIVER_VIDEO_BCM2835) += bcm2835.o
obj-$(CONFIG_DRIVER_VIDEO_SIMPLEFB) += simplefb.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += imx-ipu-v3/
diff --git a/drivers/video/atmel_lcdfb_core.c b/drivers/video/atmel_lcdfb_core.c
index bed540da9f..d03922b2b6 100644
--- a/drivers/video/atmel_lcdfb_core.c
+++ b/drivers/video/atmel_lcdfb_core.c
@@ -269,9 +269,9 @@ int atmel_lcdc_register(struct device_d *dev, struct atmel_lcdfb_devdata *data)
info = &sinfo->info;
info->priv = sinfo;
info->fbops = &atmel_lcdc_ops;
- info->mode_list = pdata->mode_list;
- info->num_modes = pdata->num_modes;
- info->mode = &info->mode_list[0];
+ info->modes.modes = pdata->mode_list;
+ info->modes.num_modes = pdata->num_modes;
+ info->mode = &info->modes.modes[0];
info->xres = info->mode->xres;
info->yres = info->mode->yres;
info->bits_per_pixel = pdata->default_bpp;
diff --git a/drivers/video/edid.c b/drivers/video/edid.c
new file mode 100644
index 0000000000..828c3610ac
--- /dev/null
+++ b/drivers/video/edid.c
@@ -0,0 +1,909 @@
+/*
+ * drivers/video/edid.c
+ *
+ * Copyright (C) 2002 James Simmons <jsimmons@users.sf.net>
+ *
+ * Credits:
+ *
+ * The EDID Parser is a conglomeration from the following sources:
+ *
+ * 1. SciTech SNAP Graphics Architecture
+ * Copyright (C) 1991-2002 SciTech Software, Inc. All rights reserved.
+ *
+ * 2. XFree86 4.3.0, interpret_edid.c
+ * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ * 3. John Fremlin <vii@users.sourceforge.net> and
+ * Ani Joshi <ajoshi@unixbox.com>
+ *
+ * Generalized Timing Formula is derived from:
+ *
+ * GTF Spreadsheet by Andy Morrish (1/5/97)
+ * available at http://www.vesa.org
+ *
+ * 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.
+ *
+ */
+
+#define pr_fmt(fmt) "EDID: " fmt
+
+#include <common.h>
+#include <fb.h>
+#include <malloc.h>
+#include <i2c/i2c.h>
+
+#include "edid.h"
+
+#define FBMON_FIX_HEADER 1
+#define FBMON_FIX_INPUT 2
+#define FBMON_FIX_TIMINGS 3
+
+struct broken_edid {
+ u8 manufacturer[4];
+ u32 model;
+ u32 fix;
+};
+
+static const unsigned char edid_v1_header[] = { 0x00, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x00
+};
+
+static int edid_is_serial_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xff) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_ascii_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfe) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_limits_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfd) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_monitor_block(unsigned char *block)
+{
+ if ((block[0] == 0x00) && (block[1] == 0x00) &&
+ (block[2] == 0x00) && (block[3] == 0xfc) &&
+ (block[4] == 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static int edid_is_timing_block(unsigned char *block)
+{
+ if ((block[0] != 0x00) || (block[1] != 0x00) ||
+ (block[2] != 0x00) || (block[4] != 0x00))
+ return 1;
+ else
+ return 0;
+}
+
+static int check_edid(unsigned char *edid)
+{
+ unsigned char *block = edid + ID_MANUFACTURER_NAME, manufacturer[4];
+ unsigned char *b;
+ u32 model;
+ int i, fix = 0, ret = 0;
+
+ manufacturer[0] = ((block[0] & 0x7c) >> 2) + '@';
+ manufacturer[1] = ((block[0] & 0x03) << 3) +
+ ((block[1] & 0xe0) >> 5) + '@';
+ manufacturer[2] = (block[1] & 0x1f) + '@';
+ manufacturer[3] = 0;
+ model = block[2] + (block[3] << 8);
+
+ switch (fix) {
+ case FBMON_FIX_HEADER:
+ for (i = 0; i < 8; i++) {
+ if (edid[i] != edid_v1_header[i]) {
+ ret = fix;
+ break;
+ }
+ }
+ break;
+ case FBMON_FIX_INPUT:
+ b = edid + EDID_STRUCT_DISPLAY;
+ /* Only if display is GTF capable will
+ the input type be reset to analog */
+ if (b[4] & 0x01 && b[0] & 0x80)
+ ret = fix;
+ break;
+ case FBMON_FIX_TIMINGS:
+ b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ ret = fix;
+
+ for (i = 0; i < 4; i++) {
+ if (edid_is_limits_block(b)) {
+ ret = 0;
+ break;
+ }
+
+ b += DETAILED_TIMING_DESCRIPTION_SIZE;
+ }
+
+ break;
+ }
+
+ if (ret)
+ printk("fbmon: The EDID Block of "
+ "Manufacturer: %s Model: 0x%x is known to "
+ "be broken,\n", manufacturer, model);
+
+ return ret;
+}
+
+static void fix_edid(unsigned char *edid, int fix)
+{
+ int i;
+ unsigned char *b, csum = 0;
+
+ switch (fix) {
+ case FBMON_FIX_HEADER:
+ printk("fbmon: trying a header reconstruct\n");
+ memcpy(edid, edid_v1_header, 8);
+ break;
+ case FBMON_FIX_INPUT:
+ printk("fbmon: trying to fix input type\n");
+ b = edid + EDID_STRUCT_DISPLAY;
+ b[0] &= ~0x80;
+ edid[127] += 0x80;
+ break;
+ case FBMON_FIX_TIMINGS:
+ printk("fbmon: trying to fix monitor timings\n");
+ b = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < 4; i++) {
+ if (!(edid_is_serial_block(b) ||
+ edid_is_ascii_block(b) ||
+ edid_is_monitor_block(b) ||
+ edid_is_timing_block(b))) {
+ b[0] = 0x00;
+ b[1] = 0x00;
+ b[2] = 0x00;
+ b[3] = 0xfd;
+ b[4] = 0x00;
+ b[5] = 60; /* vfmin */
+ b[6] = 60; /* vfmax */
+ b[7] = 30; /* hfmin */
+ b[8] = 75; /* hfmax */
+ b[9] = 17; /* pixclock - 170 MHz*/
+ b[10] = 0; /* GTF */
+ break;
+ }
+
+ b += DETAILED_TIMING_DESCRIPTION_SIZE;
+ }
+
+ for (i = 0; i < EDID_LENGTH - 1; i++)
+ csum += edid[i];
+
+ edid[127] = 256 - csum;
+ break;
+ }
+}
+
+static int edid_checksum(unsigned char *edid)
+{
+ unsigned char csum = 0, all_null = 0;
+ int i, err = 0, fix = check_edid(edid);
+
+ if (fix)
+ fix_edid(edid, fix);
+
+ for (i = 0; i < EDID_LENGTH; i++) {
+ csum += edid[i];
+ all_null |= edid[i];
+ }
+
+ if (csum == 0x00 && all_null) {
+ /* checksum passed, everything's good */
+ err = 1;
+ }
+
+ return err;
+}
+
+static int edid_check_header(unsigned char *edid)
+{
+ int i, err = 1, fix = check_edid(edid);
+
+ if (fix)
+ fix_edid(edid, fix);
+
+ for (i = 0; i < 8; i++) {
+ if (edid[i] != edid_v1_header[i])
+ err = 0;
+ }
+
+ return err;
+}
+
+/*
+ * VESA Generalized Timing Formula (GTF)
+ */
+
+#define FLYBACK 550
+#define V_FRONTPORCH 1
+#define H_OFFSET 40
+#define H_SCALEFACTOR 20
+#define H_BLANKSCALE 128
+#define H_GRADIENT 600
+#define C_VAL 30
+#define M_VAL 300
+
+struct __fb_timings {
+ u32 dclk;
+ u32 hfreq;
+ u32 vfreq;
+ u32 hactive;
+ u32 vactive;
+ u32 hblank;
+ u32 vblank;
+ u32 htotal;
+ u32 vtotal;
+};
+
+/**
+ * fb_get_vblank - get vertical blank time
+ * @hfreq: horizontal freq
+ *
+ * DESCRIPTION:
+ * vblank = right_margin + vsync_len + left_margin
+ *
+ * given: right_margin = 1 (V_FRONTPORCH)
+ * vsync_len = 3
+ * flyback = 550
+ *
+ * flyback * hfreq
+ * left_margin = --------------- - vsync_len
+ * 1000000
+ */
+static u32 fb_get_vblank(u32 hfreq)
+{
+ u32 vblank;
+
+ vblank = (hfreq * FLYBACK)/1000;
+ vblank = (vblank + 500)/1000;
+ return (vblank + V_FRONTPORCH);
+}
+
+/**
+ * fb_get_hblank_by_freq - get horizontal blank time given hfreq
+ * @hfreq: horizontal freq
+ * @xres: horizontal resolution in pixels
+ *
+ * DESCRIPTION:
+ *
+ * xres * duty_cycle
+ * hblank = ------------------
+ * 100 - duty_cycle
+ *
+ * duty cycle = percent of htotal assigned to inactive display
+ * duty cycle = C - (M/Hfreq)
+ *
+ * where: C = ((offset - scale factor) * blank_scale)
+ * -------------------------------------- + scale factor
+ * 256
+ * M = blank_scale * gradient
+ *
+ */
+static u32 fb_get_hblank_by_hfreq(u32 hfreq, u32 xres)
+{
+ u32 c_val, m_val, duty_cycle, hblank;
+
+ c_val = (((H_OFFSET - H_SCALEFACTOR) * H_BLANKSCALE)/256 +
+ H_SCALEFACTOR) * 1000;
+ m_val = (H_BLANKSCALE * H_GRADIENT)/256;
+ m_val = (m_val * 1000000)/hfreq;
+ duty_cycle = c_val - m_val;
+ hblank = (xres * duty_cycle)/(100000 - duty_cycle);
+ return (hblank);
+}
+
+/**
+ * int_sqrt - rough approximation to sqrt
+ * @x: integer of which to calculate the sqrt
+ *
+ * A very rough approximation to the sqrt() function.
+ */
+unsigned long int_sqrt(unsigned long x)
+{
+ unsigned long b, m, y = 0;
+
+ if (x <= 1)
+ return x;
+
+ m = 1UL << (BITS_PER_LONG - 2);
+ while (m != 0) {
+ b = y + m;
+ y >>= 1;
+
+ if (x >= b) {
+ x -= b;
+ y += m;
+ }
+ m >>= 2;
+ }
+
+ return y;
+}
+EXPORT_SYMBOL(int_sqrt);
+
+/**
+ * fb_get_hfreq - estimate hsync
+ * @vfreq: vertical refresh rate
+ * @yres: vertical resolution
+ *
+ * DESCRIPTION:
+ *
+ * (yres + front_port) * vfreq * 1000000
+ * hfreq = -------------------------------------
+ * (1000000 - (vfreq * FLYBACK)
+ *
+ */
+
+static u32 fb_get_hfreq(u32 vfreq, u32 yres)
+{
+ u32 divisor, hfreq;
+
+ divisor = (1000000 - (vfreq * FLYBACK))/1000;
+ hfreq = (yres + V_FRONTPORCH) * vfreq * 1000;
+ return (hfreq/divisor);
+}
+
+static void fb_timings_vfreq(struct __fb_timings *timings)
+{
+ timings->hfreq = fb_get_hfreq(timings->vfreq, timings->vactive);
+ timings->vblank = fb_get_vblank(timings->hfreq);
+ timings->vtotal = timings->vactive + timings->vblank;
+ timings->hblank = fb_get_hblank_by_hfreq(timings->hfreq,
+ timings->hactive);
+ timings->htotal = timings->hactive + timings->hblank;
+ timings->dclk = timings->htotal * timings->hfreq;
+}
+
+/*
+ * fb_get_mode - calculates video mode using VESA GTF
+ * @flags: if: 0 - maximize vertical refresh rate
+ * 1 - vrefresh-driven calculation;
+ * 2 - hscan-driven calculation;
+ * 3 - pixelclock-driven calculation;
+ * @val: depending on @flags, ignored, vrefresh, hsync or pixelclock
+ * @var: pointer to fb_var_screeninfo
+ * @info: pointer to fb_info
+ *
+ * DESCRIPTION:
+ * Calculates video mode based on monitor specs using VESA GTF.
+ * The GTF is best for VESA GTF compliant monitors but is
+ * specifically formulated to work for older monitors as well.
+ *
+ * If @flag==0, the function will attempt to maximize the
+ * refresh rate. Otherwise, it will calculate timings based on
+ * the flag and accompanying value.
+ *
+ * If FB_IGNOREMON bit is set in @flags, monitor specs will be
+ * ignored and @var will be filled with the calculated timings.
+ *
+ * All calculations are based on the VESA GTF Spreadsheet
+ * available at VESA's public ftp (http://www.vesa.org).
+ *
+ * NOTES:
+ * The timings generated by the GTF will be different from VESA
+ * DMT. It might be a good idea to keep a table of standard
+ * VESA modes as well. The GTF may also not work for some displays,
+ * such as, and especially, analog TV.
+ *
+ * REQUIRES:
+ * A valid info->monspecs, otherwise 'safe numbers' will be used.
+ */
+int fb_get_mode(int flags, u32 val, struct fb_videomode *var)
+{
+ struct __fb_timings *timings;
+ u32 interlace = 1, dscan = 1;
+ u32 hfmin, hfmax, vfmin, vfmax, dclkmin, dclkmax, err = 0;
+
+ timings = xzalloc(sizeof(struct __fb_timings));
+
+ /*
+ * If monspecs are invalid, use values that are enough
+ * for 640x480@60
+ */
+ hfmin = 29000; hfmax = 30000;
+ vfmin = 60; vfmax = 60;
+ dclkmin = 0; dclkmax = 25000000;
+
+ timings->hactive = var->xres;
+ timings->vactive = var->yres;
+ if (var->vmode & FB_VMODE_INTERLACED) {
+ timings->vactive /= 2;
+ interlace = 2;
+ }
+ if (var->vmode & FB_VMODE_DOUBLE) {
+ timings->vactive *= 2;
+ dscan = 2;
+ }
+
+ /* vrefresh driven */
+ timings->vfreq = val;
+ fb_timings_vfreq(timings);
+
+ if (timings->dclk)
+ var->pixclock = KHZ2PICOS(timings->dclk / 1000);
+ var->hsync_len = (timings->htotal * 8) / 100;
+ var->right_margin = (timings->hblank / 2) - var->hsync_len;
+ var->left_margin = timings->hblank - var->right_margin -
+ var->hsync_len;
+ var->vsync_len = (3 * interlace) / dscan;
+ var->lower_margin = (1 * interlace) / dscan;
+ var->upper_margin = (timings->vblank * interlace) / dscan -
+ (var->vsync_len + var->lower_margin);
+
+ free(timings);
+ return err;
+}
+
+static void calc_mode_timings(int xres, int yres, int refresh,
+ struct fb_videomode *mode)
+{
+ mode->xres = xres;
+ mode->yres = yres;
+ mode->refresh = refresh;
+ fb_get_mode(0, refresh, mode);
+ mode->name = asprintf("%dx%d@%d-calc", mode->xres, mode->yres, mode->refresh);
+ pr_debug(" %s\n", mode->name);
+}
+
+const struct fb_videomode vesa_modes[] = {
+ /* 0 640x350-85 VESA */
+ { NULL, 85, 640, 350, 31746, 96, 32, 60, 32, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+ /* 1 640x400-85 VESA */
+ { NULL, 85, 640, 400, 31746, 96, 32, 41, 01, 64, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 2 720x400-85 VESA */
+ { NULL, 85, 721, 400, 28169, 108, 36, 42, 01, 72, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 3 640x480-60 VESA */
+ { NULL, 60, 640, 480, 39682, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ /* 4 640x480-72 VESA */
+ { NULL, 72, 640, 480, 31746, 128, 24, 29, 9, 40, 2,
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ /* 5 640x480-75 VESA */
+ { NULL, 75, 640, 480, 31746, 120, 16, 16, 01, 64, 3,
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ /* 6 640x480-85 VESA */
+ { NULL, 85, 640, 480, 27777, 80, 56, 25, 01, 56, 3,
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ /* 7 800x600-56 VESA */
+ { NULL, 56, 800, 600, 27777, 128, 24, 22, 01, 72, 2,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 8 800x600-60 VESA */
+ { NULL, 60, 800, 600, 25000, 88, 40, 23, 01, 128, 4,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 9 800x600-72 VESA */
+ { NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 10 800x600-75 VESA */
+ { NULL, 75, 800, 600, 20202, 160, 16, 21, 01, 80, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 11 800x600-85 VESA */
+ { NULL, 85, 800, 600, 17761, 152, 32, 27, 01, 64, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 12 1024x768i-43 VESA */
+ { NULL, 43, 1024, 768, 22271, 56, 8, 41, 0, 176, 8,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_INTERLACED, 0 },
+ /* 13 1024x768-60 VESA */
+ { NULL, 60, 1024, 768, 15384, 160, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ /* 14 1024x768-70 VESA */
+ { NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6,
+ 0, FB_VMODE_NONINTERLACED, 0 },
+ /* 15 1024x768-75 VESA */
+ { NULL, 75, 1024, 768, 12690, 176, 16, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 16 1024x768-85 VESA */
+ { NULL, 85, 1024, 768, 10582, 208, 48, 36, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 17 1152x864-75 VESA */
+ { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 18 1280x960-60 VESA */
+ { NULL, 60, 1280, 960, 9259, 312, 96, 36, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 19 1280x960-85 VESA */
+ { NULL, 85, 1280, 960, 6734, 224, 64, 47, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 20 1280x1024-60 VESA */
+ { NULL, 60, 1280, 1024, 9259, 248, 48, 38, 1, 112, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 21 1280x1024-75 VESA */
+ { NULL, 75, 1280, 1024, 7407, 248, 16, 38, 1, 144, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 22 1280x1024-85 VESA */
+ { NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 23 1600x1200-60 VESA */
+ { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 24 1600x1200-65 VESA */
+ { NULL, 65, 1600, 1200, 5698, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 25 1600x1200-70 VESA */
+ { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 26 1600x1200-75 VESA */
+ { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 27 1600x1200-85 VESA */
+ { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3,
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+ FB_VMODE_NONINTERLACED, 0 },
+ /* 28 1792x1344-60 VESA */
+ { NULL, 60, 1792, 1344, 4882, 328, 128, 46, 1, 200, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 29 1792x1344-75 VESA */
+ { NULL, 75, 1792, 1344, 3831, 352, 96, 69, 1, 216, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 30 1856x1392-60 VESA */
+ { NULL, 60, 1856, 1392, 4580, 352, 96, 43, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 31 1856x1392-75 VESA */
+ { NULL, 75, 1856, 1392, 3472, 352, 128, 104, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 32 1920x1440-60 VESA */
+ { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 200, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+ /* 33 1920x1440-75 VESA */
+ { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3,
+ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0 },
+};
+
+#define VESA_MODEDB_SIZE ARRAY_SIZE(vesa_modes)
+
+static void add_vesa_mode(struct fb_videomode *mode, int num)
+{
+ *mode = vesa_modes[num];
+ mode->name = asprintf("%dx%d@%d-vesa", mode->xres, mode->yres, mode->refresh);
+ pr_debug(" %s\n", mode->name);
+}
+
+static int get_est_timing(unsigned char *block, struct fb_videomode *mode)
+{
+ int num = 0;
+ unsigned char c;
+
+ c = block[0];
+ if (c & 0x80)
+ calc_mode_timings(720, 400, 70, &mode[num++]);
+ if (c & 0x40)
+ calc_mode_timings(720, 400, 88, &mode[num++]);
+ if (c & 0x20)
+ add_vesa_mode(&mode[num++], 3);
+ if (c & 0x10)
+ calc_mode_timings(640, 480, 67, &mode[num++]);
+ if (c & 0x08)
+ add_vesa_mode(&mode[num++], 4);
+ if (c & 0x04)
+ add_vesa_mode(&mode[num++], 5);
+ if (c & 0x02)
+ add_vesa_mode(&mode[num++], 7);
+ if (c & 0x01)
+ add_vesa_mode(&mode[num++], 8);
+
+ c = block[1];
+ if (c & 0x80)
+ add_vesa_mode(&mode[num++], 9);
+ if (c & 0x40)
+ add_vesa_mode(&mode[num++], 10);
+ if (c & 0x20)
+ calc_mode_timings(832, 624, 75, &mode[num++]);
+ if (c & 0x10)
+ add_vesa_mode(&mode[num++], 12);
+ if (c & 0x08)
+ add_vesa_mode(&mode[num++], 13);
+ if (c & 0x04)
+ add_vesa_mode(&mode[num++], 14);
+ if (c & 0x02)
+ add_vesa_mode(&mode[num++], 15);
+ if (c & 0x01)
+ add_vesa_mode(&mode[num++], 21);
+ c = block[2];
+
+ if (c & 0x80)
+ add_vesa_mode(&mode[num++], 17);
+
+ pr_debug(" Manufacturer's mask: %x\n",c & 0x7F);
+ return num;
+}
+
+static int get_std_timing(unsigned char *block, struct fb_videomode *mode,
+ int ver, int rev)
+{
+ int xres, yres = 0, refresh, ratio, i;
+
+ xres = (block[0] + 31) * 8;
+ if (xres <= 256)
+ return 0;
+
+ ratio = (block[1] & 0xc0) >> 6;
+ switch (ratio) {
+ case 0:
+ /* in EDID 1.3 the meaning of 0 changed to 16:10 (prior 1:1) */
+ if (ver < 1 || (ver == 1 && rev < 3))
+ yres = xres;
+ else
+ yres = (xres * 10) / 16;
+ break;
+ case 1:
+ yres = (xres * 3) / 4;
+ break;
+ case 2:
+ yres = (xres * 4) / 5;
+ break;
+ case 3:
+ yres = (xres * 9) / 16;
+ break;
+ }
+ refresh = (block[1] & 0x3f) + 60;
+
+ for (i = 0; i < VESA_MODEDB_SIZE; i++) {
+ if (vesa_modes[i].xres == xres &&
+ vesa_modes[i].yres == yres &&
+ vesa_modes[i].refresh == refresh) {
+ add_vesa_mode(mode, i);
+ return 1;
+ }
+ }
+
+ calc_mode_timings(xres, yres, refresh, mode);
+
+ return 1;
+}
+
+static int get_dst_timing(unsigned char *block,
+ struct fb_videomode *mode, int ver, int rev)
+{
+ int j, num = 0;
+
+ for (j = 0; j < 6; j++, block += STD_TIMING_DESCRIPTION_SIZE)
+ num += get_std_timing(block, &mode[num], ver, rev);
+
+ return num;
+}
+
+static void get_detailed_timing(unsigned char *block,
+ struct fb_videomode *mode)
+{
+ mode->xres = H_ACTIVE;
+ mode->yres = V_ACTIVE;
+ mode->pixclock = PIXEL_CLOCK;
+ mode->pixclock /= 1000;
+ mode->pixclock = KHZ2PICOS(mode->pixclock);
+ mode->right_margin = H_SYNC_OFFSET;
+ mode->left_margin = (H_ACTIVE + H_BLANKING) -
+ (H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH);
+ mode->upper_margin = V_BLANKING - V_SYNC_OFFSET -
+ V_SYNC_WIDTH;
+ mode->lower_margin = V_SYNC_OFFSET;
+ mode->hsync_len = H_SYNC_WIDTH;
+ mode->vsync_len = V_SYNC_WIDTH;
+ if (HSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_HOR_HIGH_ACT;
+ if (VSYNC_POSITIVE)
+ mode->sync |= FB_SYNC_VERT_HIGH_ACT;
+ mode->refresh = PIXEL_CLOCK/((H_ACTIVE + H_BLANKING) *
+ (V_ACTIVE + V_BLANKING));
+ if (INTERLACED) {
+ mode->yres *= 2;
+ mode->upper_margin *= 2;
+ mode->lower_margin *= 2;
+ mode->vsync_len *= 2;
+ mode->vmode |= FB_VMODE_INTERLACED;
+ }
+
+ pr_debug(" %d MHz ", PIXEL_CLOCK/1000000);
+ pr_debug("%d %d %d %d ", H_ACTIVE, H_ACTIVE + H_SYNC_OFFSET,
+ H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH, H_ACTIVE + H_BLANKING);
+ pr_debug("%d %d %d %d ", V_ACTIVE, V_ACTIVE + V_SYNC_OFFSET,
+ V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH, V_ACTIVE + V_BLANKING);
+ pr_debug("%sHSync %sVSync\n", (HSYNC_POSITIVE) ? "+" : "-",
+ (VSYNC_POSITIVE) ? "+" : "-");
+
+ mode->name = asprintf("%dx%d@%d", mode->xres, mode->yres, mode->refresh);
+}
+
+/**
+ * edid_to_display_timings - create video mode database
+ * @edid: EDID data
+ * @dbsize: database size
+ *
+ * RETURNS: struct fb_videomode, @dbsize contains length of database
+ *
+ * DESCRIPTION:
+ * This function builds a mode database using the contents of the EDID
+ * data
+ */
+int edid_to_display_timings(struct display_timings *timings, unsigned char *edid)
+{
+ struct fb_videomode *mode;
+ unsigned char *block;
+ int num = 0, i, first = 1;
+ int ver, rev, ret;
+
+ ver = edid[EDID_STRUCT_VERSION];
+ rev = edid[EDID_STRUCT_REVISION];
+
+ mode = xzalloc(50 * sizeof(struct fb_videomode));
+
+ if (!edid_checksum(edid) ||
+ !edid_check_header(edid)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ pr_debug(" Detailed Timings\n");
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (!(block[0] == 0x00 && block[1] == 0x00)) {
+ get_detailed_timing(block, &mode[num]);
+ if (first) {
+ first = 0;
+ }
+ num++;
+ }
+ }
+
+ pr_debug(" Supported VESA Modes\n");
+ block = edid + ESTABLISHED_TIMING_1;
+ num += get_est_timing(block, &mode[num]);
+
+ pr_debug(" Standard Timings\n");
+ block = edid + STD_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < STD_TIMING; i++, block += STD_TIMING_DESCRIPTION_SIZE)
+ num += get_std_timing(block, &mode[num], ver, rev);
+
+ block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+ for (i = 0; i < 4; i++, block+= DETAILED_TIMING_DESCRIPTION_SIZE) {
+ if (block[0] == 0x00 && block[1] == 0x00 && block[3] == 0xfa)
+ num += get_dst_timing(block + 5, &mode[num], ver, rev);
+ }
+
+ /* Yikes, EDID data is totally useless */
+ if (!num) {
+ free(mode);
+ return -EINVAL;
+ }
+
+ timings->num_modes = num;
+ timings->modes = mode;
+
+ return 0;
+out:
+ free(timings);
+ free(mode);
+ return ret;
+}
+
+#define DDC_ADDR 0x50
+#define DDC_SEGMENT_ADDR 0x30
+
+/**
+ * Get EDID information via I2C.
+ *
+ * \param adapter : i2c device adaptor
+ * \param buf : EDID data buffer to be filled
+ * \param len : EDID data buffer length
+ * \return 0 on success or -1 on failure.
+ *
+ * Try to fetch EDID information by calling i2c driver function.
+ */
+static int
+edid_do_read_i2c(struct i2c_adapter *adapter, unsigned char *buf,
+ int block, int len)
+{
+ unsigned char start = block * EDID_LENGTH;
+ unsigned char segment = block >> 1;
+ unsigned char xfers = segment ? 3 : 2;
+ int ret, retries = 5;
+
+ /* The core i2c driver will automatically retry the transfer if the
+ * adapter reports EAGAIN. However, we find that bit-banging transfers
+ * are susceptible to errors under a heavily loaded machine and
+ * generate spurious NAKs and timeouts. Retrying the transfer
+ * of the individual block a few times seems to overcome this.
+ */
+ do {
+ struct i2c_msg msgs[] = {
+ {
+ .addr = DDC_SEGMENT_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &segment,
+ }, {
+ .addr = DDC_ADDR,
+ .flags = 0,
+ .len = 1,
+ .buf = &start,
+ }, {
+ .addr = DDC_ADDR,
+ .flags = I2C_M_RD,
+ .len = len,
+ .buf = buf,
+ }
+ };
+
+ /*
+ * Avoid sending the segment addr to not upset non-compliant ddc
+ * monitors.
+ */
+ ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers);
+ } while (ret != xfers && --retries);
+
+ return ret == xfers ? 0 : -1;
+}
+
+void *edid_read_i2c(struct i2c_adapter *adapter)
+{
+ u8 *block;
+
+ block = xmalloc(EDID_LENGTH);
+
+ if (edid_do_read_i2c(adapter, block, 0, EDID_LENGTH))
+ goto out;
+
+ return block;
+out:
+ free(block);
+
+ return NULL;
+}
+
+void fb_edid_add_modes(struct fb_info *info)
+{
+ if (info->edid_i2c_adapter)
+ info->edid_data = edid_read_i2c(info->edid_i2c_adapter);
+
+ if (!info->edid_data)
+ return;
+
+ edid_to_display_timings(&info->edid_modes, info->edid_data);
+}
diff --git a/drivers/video/edid.h b/drivers/video/edid.h
new file mode 100644
index 0000000000..006d9f2834
--- /dev/null
+++ b/drivers/video/edid.h
@@ -0,0 +1,138 @@
+/*
+ * drivers/video/edid.h - EDID/DDC Header
+ *
+ * Based on:
+ * 1. XFree86 4.3.0, edid.h
+ * Copyright 1998 by Egbert Eich <Egbert.Eich@Physik.TU-Darmstadt.DE>
+ *
+ * 2. John Fremlin <vii@users.sourceforge.net> and
+ * Ani Joshi <ajoshi@unixbox.com>
+ *
+ * DDC is a Trademark of VESA (Video Electronics Standard Association).
+ *
+ * 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.
+*/
+
+#ifndef __EDID_H__
+#define __EDID_H__
+
+#define EDID_LENGTH 0x80
+#define EDID_HEADER 0x00
+#define EDID_HEADER_END 0x07
+
+#define ID_MANUFACTURER_NAME 0x08
+#define ID_MANUFACTURER_NAME_END 0x09
+#define ID_MODEL 0x0a
+
+#define ID_SERIAL_NUMBER 0x0c
+
+#define MANUFACTURE_WEEK 0x10
+#define MANUFACTURE_YEAR 0x11
+
+#define EDID_STRUCT_VERSION 0x12
+#define EDID_STRUCT_REVISION 0x13
+
+#define EDID_STRUCT_DISPLAY 0x14
+
+#define DPMS_FLAGS 0x18
+#define ESTABLISHED_TIMING_1 0x23
+#define ESTABLISHED_TIMING_2 0x24
+#define MANUFACTURERS_TIMINGS 0x25
+
+/* standard timings supported */
+#define STD_TIMING 8
+#define STD_TIMING_DESCRIPTION_SIZE 2
+#define STD_TIMING_DESCRIPTIONS_START 0x26
+
+#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE 18
+#define NO_DETAILED_TIMING_DESCRIPTIONS 4
+
+#define DETAILED_TIMING_DESCRIPTION_1 0x36
+#define DETAILED_TIMING_DESCRIPTION_2 0x48
+#define DETAILED_TIMING_DESCRIPTION_3 0x5a
+#define DETAILED_TIMING_DESCRIPTION_4 0x6c
+
+#define DESCRIPTOR_DATA 5
+
+#define UPPER_NIBBLE( x ) \
+ (((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE( x ) \
+ ((1|2|4|8) & (x))
+
+#define COMBINE_HI_8LO( hi, lo ) \
+ ( (((unsigned)hi) << 8) | (unsigned)lo )
+
+#define COMBINE_HI_4LO( hi, lo ) \
+ ( (((unsigned)hi) << 4) | (unsigned)lo )
+
+#define PIXEL_CLOCK_LO (unsigned)block[ 0 ]
+#define PIXEL_CLOCK_HI (unsigned)block[ 1 ]
+#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*10000)
+#define H_ACTIVE_LO (unsigned)block[ 2 ]
+#define H_BLANKING_LO (unsigned)block[ 3 ]
+#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_ACTIVE COMBINE_HI_8LO( H_ACTIVE_HI, H_ACTIVE_LO )
+#define H_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 4 ] )
+#define H_BLANKING COMBINE_HI_8LO( H_BLANKING_HI, H_BLANKING_LO )
+
+#define V_ACTIVE_LO (unsigned)block[ 5 ]
+#define V_BLANKING_LO (unsigned)block[ 6 ]
+#define V_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_ACTIVE COMBINE_HI_8LO( V_ACTIVE_HI, V_ACTIVE_LO )
+#define V_BLANKING_HI LOWER_NIBBLE( (unsigned)block[ 7 ] )
+#define V_BLANKING COMBINE_HI_8LO( V_BLANKING_HI, V_BLANKING_LO )
+
+#define H_SYNC_OFFSET_LO (unsigned)block[ 8 ]
+#define H_SYNC_WIDTH_LO (unsigned)block[ 9 ]
+
+#define V_SYNC_OFFSET_LO UPPER_NIBBLE( (unsigned)block[ 10 ] )
+#define V_SYNC_WIDTH_LO LOWER_NIBBLE( (unsigned)block[ 10 ] )
+
+#define V_SYNC_WIDTH_HI ((unsigned)block[ 11 ] & (1|2))
+#define V_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (4|8)) >> 2)
+
+#define H_SYNC_WIDTH_HI (((unsigned)block[ 11 ] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI (((unsigned)block[ 11 ] & (64|128)) >> 6)
+
+#define V_SYNC_WIDTH COMBINE_HI_4LO( V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO )
+#define V_SYNC_OFFSET COMBINE_HI_4LO( V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO )
+
+#define H_SYNC_WIDTH COMBINE_HI_8LO( H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO )
+#define H_SYNC_OFFSET COMBINE_HI_8LO( H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO )
+
+#define H_SIZE_LO (unsigned)block[ 12 ]
+#define V_SIZE_LO (unsigned)block[ 13 ]
+
+#define H_SIZE_HI UPPER_NIBBLE( (unsigned)block[ 14 ] )
+#define V_SIZE_HI LOWER_NIBBLE( (unsigned)block[ 14 ] )
+
+#define H_SIZE COMBINE_HI_8LO( H_SIZE_HI, H_SIZE_LO )
+#define V_SIZE COMBINE_HI_8LO( V_SIZE_HI, V_SIZE_LO )
+
+#define H_BORDER (unsigned)block[ 15 ]
+#define V_BORDER (unsigned)block[ 16 ]
+
+#define FLAGS (unsigned)block[ 17 ]
+
+#define INTERLACED (FLAGS&128)
+#define SYNC_TYPE (FLAGS&3<<3) /* bits 4,3 */
+#define SYNC_SEPARATE (3<<3)
+#define HSYNC_POSITIVE (FLAGS & 4)
+#define VSYNC_POSITIVE (FLAGS & 2)
+
+#define V_MIN_RATE block[ 5 ]
+#define V_MAX_RATE block[ 6 ]
+#define H_MIN_RATE block[ 7 ]
+#define H_MAX_RATE block[ 8 ]
+#define MAX_PIXEL_CLOCK (((int)block[ 9 ]) * 10)
+#define GTF_SUPPORT block[10]
+
+#define DPMS_ACTIVE_OFF (1 << 5)
+#define DPMS_SUSPEND (1 << 6)
+#define DPMS_STANDBY (1 << 7)
+
+#endif /* __EDID_H__ */
diff --git a/drivers/video/fb.c b/drivers/video/fb.c
index c36b9adcea..2c8b8eb25e 100644
--- a/drivers/video/fb.c
+++ b/drivers/video/fb.c
@@ -49,32 +49,45 @@ static int fb_enable_set(struct param_d *param, void *priv)
return 0;
}
-static int fb_setup_mode(struct device_d *dev, struct param_d *param,
- const char *val)
+static struct fb_videomode *fb_num_to_mode(struct fb_info *info, int num)
{
- struct fb_info *info = dev->priv;
- int mode, ret;
+ int num_modes;
+
+ num_modes = info->modes.num_modes + info->edid_modes.num_modes;
+
+ if (num >= num_modes)
+ return NULL;
+
+ if (num >= info->modes.num_modes)
+ return &info->edid_modes.modes[num - info->modes.num_modes];
+
+ return &info->modes.modes[num];
+}
+
+static int fb_setup_mode(struct fb_info *info)
+{
+ struct device_d *dev = &info->dev;
+ int ret;
+ struct fb_videomode *mode;
if (info->enabled != 0)
return -EPERM;
- if (!val)
- return dev_param_set_generic(dev, param, NULL);
-
- for (mode = 0; mode < info->num_modes; mode++) {
- if (!strcmp(info->mode_list[mode].name, val))
- break;
- }
- if (mode >= info->num_modes)
+ mode = fb_num_to_mode(info, info->current_mode);
+ if (!mode)
return -EINVAL;
- info->mode = &info->mode_list[mode];
+ info->mode = mode;
info->xres = info->mode->xres;
info->yres = info->mode->yres;
info->line_length = 0;
- ret = info->fbops->fb_activate_var(info);
+ if (info->fbops->fb_activate_var) {
+ ret = info->fbops->fb_activate_var(info);
+ if (ret)
+ return ret;
+ }
if (!info->line_length)
info->line_length = info->xres * (info->bits_per_pixel >> 3);
@@ -85,13 +98,24 @@ static int fb_setup_mode(struct device_d *dev, struct param_d *param,
dev->resource[0].start = (resource_size_t)info->screen_base;
info->cdev.size = info->line_length * info->yres;
dev->resource[0].end = dev->resource[0].start + info->cdev.size - 1;
- dev_param_set_generic(dev, param, val);
} else
info->cdev.size = 0;
return ret;
}
+static int fb_set_modename(struct param_d *param, void *priv)
+{
+ struct fb_info *info = priv;
+ int ret;
+
+ ret = fb_setup_mode(info);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static struct file_operations fb_ops = {
.read = mem_read,
.write = mem_write,
@@ -100,22 +124,28 @@ static struct file_operations fb_ops = {
.ioctl = fb_ioctl,
};
-static void fb_info(struct device_d *dev)
+static void fb_print_mode(struct fb_videomode *mode)
+{
+ printf("%-20s %dx%d@%d\n", mode->name,
+ mode->xres, mode->yres, mode->refresh);
+}
+
+static void fb_print_modes(struct display_timings *modes)
{
- struct fb_info *info = dev->priv;
int i;
- if (!info->num_modes)
- return;
+ for (i = 0; i < modes->num_modes; i++)
+ fb_print_mode(&modes->modes[i]);
+}
+
+static void fb_info(struct device_d *dev)
+{
+ struct fb_info *info = dev->priv;
printf("available modes:\n");
- for (i = 0; i < info->num_modes; i++) {
- struct fb_videomode *mode = &info->mode_list[i];
-
- printf("%-10s %dx%d@%d\n", mode->name,
- mode->xres, mode->yres, mode->refresh);
- }
+ fb_print_modes(&info->modes);
+ fb_print_modes(&info->edid_modes);
printf("\n");
}
@@ -124,10 +154,20 @@ int register_framebuffer(struct fb_info *info)
{
int id = get_free_deviceid("fb");
struct device_d *dev;
- int ret;
+ int ret, num_modes, i;
+ const char **names;
dev = &info->dev;
+ /*
+ * If info->mode is set at this point it's the only mode
+ * the fb supports. move it over to the modes list.
+ */
+ if (info->mode) {
+ info->modes.modes = info->mode;
+ info->modes.num_modes = 1;
+ }
+
if (!info->line_length)
info->line_length = info->xres * (info->bits_per_pixel >> 3);
@@ -155,11 +195,22 @@ int register_framebuffer(struct fb_info *info)
dev_add_param_bool(dev, "enable", fb_enable_set, NULL,
&info->p_enable, info);
- if (info->num_modes && (info->mode_list != NULL) &&
- (info->fbops->fb_activate_var != NULL)) {
- dev_add_param(dev, "mode_name", fb_setup_mode, NULL, 0);
- dev_set_param(dev, "mode_name", info->mode_list[0].name);
- }
+ if (IS_ENABLED(CONFIG_DRIVER_VIDEO_EDID))
+ fb_edid_add_modes(info);
+
+ num_modes = info->modes.num_modes + info->edid_modes.num_modes;
+
+ names = xzalloc(sizeof(char *) * num_modes);
+
+ for (i = 0; i < info->modes.num_modes; i++)
+ names[i] = info->modes.modes[i].name;
+ for (i = 0; i < info->edid_modes.num_modes; i++)
+ names[i + info->modes.num_modes] = info->edid_modes.modes[i].name;
+ dev_add_param_enum(dev, "mode_name", fb_set_modename, NULL, &info->current_mode, names, num_modes, info);
+
+ info->mode = fb_num_to_mode(info, 0);
+
+ fb_setup_mode(info);
ret = devfs_create(&info->cdev);
if (ret)
diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c
index 7276647382..abac812cb6 100644
--- a/drivers/video/imx-ipu-fb.c
+++ b/drivers/video/imx-ipu-fb.c
@@ -1007,8 +1007,8 @@ static int imxfb_probe(struct device_d *dev)
fbi->disable_fractional_divider = pdata->disable_fractional_divider;
info->priv = fbi;
info->fbops = &imxfb_ops;
- info->num_modes = pdata->num_modes;
- info->mode_list = pdata->mode;
+ info->modes.modes = pdata->mode;
+ info->modes.num_modes = pdata->num_modes;
imxfb_init_info(info, pdata->mode, pdata->bpp);
@@ -1047,14 +1047,9 @@ static int imxfb_probe(struct device_d *dev)
return ret;
}
-static void imxfb_remove(struct device_d *dev)
-{
-}
-
static struct driver_d imx3fb_driver = {
.name = "imx-ipu-fb",
.probe = imxfb_probe,
- .remove = imxfb_remove,
};
device_platform_driver(imx3fb_driver);
diff --git a/drivers/video/imx-ipu-v3/Kconfig b/drivers/video/imx-ipu-v3/Kconfig
new file mode 100644
index 0000000000..3d656e5193
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/Kconfig
@@ -0,0 +1,14 @@
+config DRIVER_VIDEO_IMX_IPUV3
+ bool "i.MX IPUv3 driver"
+ help
+ Support the IPUv3 found on Freescale i.MX51/53/6 SoCs
+
+if DRIVER_VIDEO_IMX_IPUV3
+
+config DRIVER_VIDEO_IMX_IPUV3_LVDS
+ bool "IPUv3 LVDS support"
+
+config DRIVER_VIDEO_IMX_IPUV3_HDMI
+ bool "IPUv3 HDMI support"
+
+endif
diff --git a/drivers/video/imx-ipu-v3/Makefile b/drivers/video/imx-ipu-v3/Makefile
new file mode 100644
index 0000000000..2bc0aec5ae
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-common.o ipu-dmfc.o ipu-di.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-dp.o ipuv3-plane.o ipufb.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3) += ipu-dc.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3_LVDS) += imx-ldb.o
+obj-$(CONFIG_DRIVER_VIDEO_IMX_IPUV3_HDMI) += imx-hdmi.o
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.c b/drivers/video/imx-ipu-v3/imx-hdmi.c
new file mode 100644
index 0000000000..4f462889a8
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.c
@@ -0,0 +1,1297 @@
+/*
+ * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * SH-Mobile High-Definition Multimedia Interface (HDMI) driver
+ * for SLISHDMI13T and SLIPHDMIT IP cores
+ *
+ * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ */
+#include <common.h>
+#include <fb.h>
+#include <io.h>
+#include <driver.h>
+#include <malloc.h>
+#include <errno.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/div64.h>
+#include <linux/clk.h>
+#include <i2c/i2c.h>
+#include <mach/imx6-regs.h>
+#include <mach/imx53-regs.h>
+
+#include "imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+#include "imx-hdmi.h"
+
+#define HDMI_EDID_LEN 512
+
+#define RGB 0
+#define YCBCR444 1
+#define YCBCR422_16BITS 2
+#define YCBCR422_8BITS 3
+#define XVYCC444 4
+
+enum hdmi_colorimetry {
+ HDMI_COLORIMETRY_NONE,
+ HDMI_COLORIMETRY_ITU_601,
+ HDMI_COLORIMETRY_ITU_709,
+ HDMI_COLORIMETRY_EXTENDED,
+};
+
+enum hdmi_datamap {
+ RGB444_8B = 0x01,
+ RGB444_10B = 0x03,
+ RGB444_12B = 0x05,
+ RGB444_16B = 0x07,
+ YCbCr444_8B = 0x09,
+ YCbCr444_10B = 0x0B,
+ YCbCr444_12B = 0x0D,
+ YCbCr444_16B = 0x0F,
+ YCbCr422_8B = 0x16,
+ YCbCr422_10B = 0x14,
+ YCbCr422_12B = 0x12,
+};
+
+enum imx_hdmi_devtype {
+ IMX6Q_HDMI,
+ IMX6DL_HDMI,
+};
+
+static const u16 csc_coeff_default[3][4] = {
+ { 0x2000, 0x0000, 0x0000, 0x0000 },
+ { 0x0000, 0x2000, 0x0000, 0x0000 },
+ { 0x0000, 0x0000, 0x2000, 0x0000 }
+};
+
+static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
+ { 0x2000, 0x6926, 0x74fd, 0x010e },
+ { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
+ { 0x2000, 0x0000, 0x38b4, 0x7e3b }
+};
+
+static const u16 csc_coeff_rgb_out_eitu709[3][4] = {
+ { 0x2000, 0x7106, 0x7a02, 0x00a7 },
+ { 0x2000, 0x3264, 0x0000, 0x7e6d },
+ { 0x2000, 0x0000, 0x3b61, 0x7e25 }
+};
+
+static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
+ { 0x2591, 0x1322, 0x074b, 0x0000 },
+ { 0x6535, 0x2000, 0x7acc, 0x0200 },
+ { 0x6acd, 0x7534, 0x2000, 0x0200 }
+};
+
+static const u16 csc_coeff_rgb_in_eitu709[3][4] = {
+ { 0x2dc5, 0x0d9b, 0x049e, 0x0000 },
+ { 0x62f0, 0x2000, 0x7d11, 0x0200 },
+ { 0x6756, 0x78ab, 0x2000, 0x0200 }
+};
+
+struct hdmi_vmode {
+ bool mdvi;
+ bool mhsyncpolarity;
+ bool mvsyncpolarity;
+ bool minterlaced;
+ bool mdataenablepolarity;
+
+ unsigned int mpixelclock;
+ unsigned int mpixelrepetitioninput;
+ unsigned int mpixelrepetitionoutput;
+};
+
+struct hdmi_data_info {
+ unsigned int enc_in_format;
+ unsigned int enc_out_format;
+ unsigned int enc_color_depth;
+ unsigned int colorimetry;
+ unsigned int pix_repet_factor;
+ unsigned int hdcp_enable;
+ struct hdmi_vmode video_mode;
+};
+
+struct imx_hdmi {
+ enum imx_hdmi_devtype dev_type;
+ struct device_d *dev;
+ struct clk *isfr_clk;
+ struct clk *iahb_clk;
+
+ bool connected;
+
+ struct hdmi_data_info hdmi_data;
+ int vic;
+
+ u8 edid[HDMI_EDID_LEN];
+ bool cable_plugin;
+
+ bool phy_enabled;
+
+ struct regmap *regmap;
+ struct i2c_adapter *ddc;
+ void __iomem *regs;
+
+ unsigned int sample_rate;
+ int ratio;
+
+ struct ipu_output output;
+};
+
+static void imx_hdmi_set_ipu_di_mux(struct imx_hdmi *hdmi, int ipu_di)
+{
+ void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc;
+ uint32_t val;
+
+ dev_info(hdmi->dev, "setup hdmi mux to %d\n", ipu_di);
+
+ val = readl(gpr3);
+ val &= ~(3 << 2);
+ val |= ipu_di << 2;
+ writel(val, gpr3);
+}
+
+static inline void hdmi_writeb(struct imx_hdmi *hdmi, u8 val, int offset)
+{
+ writeb(val, hdmi->regs + offset);
+}
+
+static inline u8 hdmi_readb(struct imx_hdmi *hdmi, int offset)
+{
+ return readb(hdmi->regs + offset);
+}
+
+static void hdmi_modb(struct imx_hdmi *hdmi, u8 data, u8 mask, unsigned reg)
+{
+ u8 val = hdmi_readb(hdmi, reg) & ~mask;
+ val |= data & mask;
+ hdmi_writeb(hdmi, val, reg);
+}
+
+static void hdmi_mask_writeb(struct imx_hdmi *hdmi, u8 data, unsigned int reg,
+ u8 shift, u8 mask)
+{
+ hdmi_modb(hdmi, data << shift, mask, reg);
+}
+
+static void hdmi_set_clock_regenerator_n(struct imx_hdmi *hdmi,
+ unsigned int value)
+{
+ hdmi_writeb(hdmi, value & 0xff, HDMI_AUD_N1);
+ hdmi_writeb(hdmi, (value >> 8) & 0xff, HDMI_AUD_N2);
+ hdmi_writeb(hdmi, (value >> 16) & 0x0f, HDMI_AUD_N3);
+
+ /* nshift factor = 0 */
+ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3);
+}
+
+static void hdmi_regenerate_cts(struct imx_hdmi *hdmi, unsigned int cts)
+{
+ /* Must be set/cleared first */
+ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+
+ hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1);
+ hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
+ hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) |
+ HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3);
+}
+
+static unsigned int hdmi_compute_n(unsigned int freq, unsigned long pixel_clk,
+ unsigned int ratio)
+{
+ unsigned int n = (128 * freq) / 1000;
+
+ switch (freq) {
+ case 32000:
+ if (pixel_clk == 25170000)
+ n = (ratio == 150) ? 9152 : 4576;
+ else if (pixel_clk == 27020000)
+ n = (ratio == 150) ? 8192 : 4096;
+ else if (pixel_clk == 74170000 || pixel_clk == 148350000)
+ n = 11648;
+ else
+ n = 4096;
+ break;
+
+ case 44100:
+ if (pixel_clk == 25170000)
+ n = 7007;
+ else if (pixel_clk == 74170000)
+ n = 17836;
+ else if (pixel_clk == 148350000)
+ n = (ratio == 150) ? 17836 : 8918;
+ else
+ n = 6272;
+ break;
+
+ case 48000:
+ if (pixel_clk == 25170000)
+ n = (ratio == 150) ? 9152 : 6864;
+ else if (pixel_clk == 27020000)
+ n = (ratio == 150) ? 8192 : 6144;
+ else if (pixel_clk == 74170000)
+ n = 11648;
+ else if (pixel_clk == 148350000)
+ n = (ratio == 150) ? 11648 : 5824;
+ else
+ n = 6144;
+ break;
+
+ case 88200:
+ n = hdmi_compute_n(44100, pixel_clk, ratio) * 2;
+ break;
+
+ case 96000:
+ n = hdmi_compute_n(48000, pixel_clk, ratio) * 2;
+ break;
+
+ case 176400:
+ n = hdmi_compute_n(44100, pixel_clk, ratio) * 4;
+ break;
+
+ case 192000:
+ n = hdmi_compute_n(48000, pixel_clk, ratio) * 4;
+ break;
+
+ default:
+ break;
+ }
+
+ return n;
+}
+
+static unsigned int hdmi_compute_cts(unsigned int freq, unsigned long pixel_clk,
+ unsigned int ratio)
+{
+ unsigned int cts = 0;
+
+ pr_debug("%s: freq: %d pixel_clk: %ld ratio: %d\n", __func__, freq,
+ pixel_clk, ratio);
+
+ switch (freq) {
+ case 32000:
+ if (pixel_clk == 297000000) {
+ cts = 222750;
+ break;
+ }
+ case 48000:
+ case 96000:
+ case 192000:
+ switch (pixel_clk) {
+ case 25200000:
+ case 27000000:
+ case 54000000:
+ case 74250000:
+ case 148500000:
+ cts = pixel_clk / 1000;
+ break;
+ case 297000000:
+ cts = 247500;
+ break;
+ /*
+ * All other TMDS clocks are not supported by
+ * DWC_hdmi_tx. The TMDS clocks divided or
+ * multiplied by 1,001 coefficients are not
+ * supported.
+ */
+ default:
+ break;
+ }
+ break;
+ case 44100:
+ case 88200:
+ case 176400:
+ switch (pixel_clk) {
+ case 25200000:
+ cts = 28000;
+ break;
+ case 27000000:
+ cts = 30000;
+ break;
+ case 54000000:
+ cts = 60000;
+ break;
+ case 74250000:
+ cts = 82500;
+ break;
+ case 148500000:
+ cts = 165000;
+ break;
+ case 297000000:
+ cts = 247500;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ if (ratio == 100)
+ return cts;
+ else
+ return (cts * ratio) / 100;
+}
+
+static void hdmi_set_clk_regenerator(struct imx_hdmi *hdmi,
+ unsigned long pixel_clk)
+{
+ unsigned int clk_n, clk_cts;
+
+ clk_n = hdmi_compute_n(hdmi->sample_rate, pixel_clk,
+ hdmi->ratio);
+ clk_cts = hdmi_compute_cts(hdmi->sample_rate, pixel_clk,
+ hdmi->ratio);
+
+ if (!clk_cts) {
+ dev_dbg(hdmi->dev, "%s: pixel clock not supported: %lu\n",
+ __func__, pixel_clk);
+ return;
+ }
+
+ dev_dbg(hdmi->dev, "%s: samplerate=%d ratio=%d pixelclk=%lu N=%d cts=%d\n",
+ __func__, hdmi->sample_rate, hdmi->ratio,
+ pixel_clk, clk_n, clk_cts);
+
+ hdmi_set_clock_regenerator_n(hdmi, clk_n);
+ hdmi_regenerate_cts(hdmi, clk_cts);
+}
+
+static void hdmi_init_clk_regenerator(struct imx_hdmi *hdmi)
+{
+ hdmi_set_clk_regenerator(hdmi, 74250000);
+}
+
+/*
+ * this submodule is responsible for the video data synchronization.
+ * for example, for RGB 4:4:4 input, the data map is defined as
+ * pin{47~40} <==> R[7:0]
+ * pin{31~24} <==> G[7:0]
+ * pin{15~8} <==> B[7:0]
+ */
+static void hdmi_video_sample(struct imx_hdmi *hdmi)
+{
+ int color_format = 0;
+ u8 val;
+
+ if (hdmi->hdmi_data.enc_in_format == RGB) {
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_format = 0x01;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_format = 0x03;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_format = 0x05;
+ else if (hdmi->hdmi_data.enc_color_depth == 16)
+ color_format = 0x07;
+ else
+ return;
+ } else if (hdmi->hdmi_data.enc_in_format == YCBCR444) {
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_format = 0x09;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_format = 0x0B;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_format = 0x0D;
+ else if (hdmi->hdmi_data.enc_color_depth == 16)
+ color_format = 0x0F;
+ else
+ return;
+ } else if (hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) {
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_format = 0x16;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_format = 0x14;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_format = 0x12;
+ else
+ return;
+ }
+
+ val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
+ ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
+ HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
+ hdmi_writeb(hdmi, val, HDMI_TX_INVID0);
+
+ /* Enable TX stuffing: When DE is inactive, fix the output data to 0 */
+ val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
+ hdmi_writeb(hdmi, val, HDMI_TX_INSTUFFING);
+ hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA0);
+ hdmi_writeb(hdmi, 0x0, HDMI_TX_GYDATA1);
+ hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA0);
+ hdmi_writeb(hdmi, 0x0, HDMI_TX_RCRDATA1);
+ hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA0);
+ hdmi_writeb(hdmi, 0x0, HDMI_TX_BCBDATA1);
+}
+
+static int is_color_space_conversion(struct imx_hdmi *hdmi)
+{
+ return (hdmi->hdmi_data.enc_in_format !=
+ hdmi->hdmi_data.enc_out_format);
+}
+
+static int is_color_space_decimation(struct imx_hdmi *hdmi)
+{
+ return ((hdmi->hdmi_data.enc_out_format == YCBCR422_8BITS) &&
+ (hdmi->hdmi_data.enc_in_format == RGB ||
+ hdmi->hdmi_data.enc_in_format == YCBCR444));
+}
+
+static int is_color_space_interpolation(struct imx_hdmi *hdmi)
+{
+ return ((hdmi->hdmi_data.enc_in_format == YCBCR422_8BITS) &&
+ (hdmi->hdmi_data.enc_out_format == RGB ||
+ hdmi->hdmi_data.enc_out_format == YCBCR444));
+}
+
+static void imx_hdmi_update_csc_coeffs(struct imx_hdmi *hdmi)
+{
+ const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
+ unsigned i;
+ u32 csc_scale = 1;
+
+ if (is_color_space_conversion(hdmi)) {
+ if (hdmi->hdmi_data.enc_out_format == RGB) {
+ if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
+ csc_coeff = &csc_coeff_rgb_out_eitu601;
+ else
+ csc_coeff = &csc_coeff_rgb_out_eitu709;
+ } else if (hdmi->hdmi_data.enc_in_format == RGB) {
+ if (hdmi->hdmi_data.colorimetry == HDMI_COLORIMETRY_ITU_601)
+ csc_coeff = &csc_coeff_rgb_in_eitu601;
+ else
+ csc_coeff = &csc_coeff_rgb_in_eitu709;
+ csc_scale = 0;
+ }
+ }
+
+ /* The CSC registers are sequential, alternating MSB then LSB */
+ for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
+ u16 coeff_a = (*csc_coeff)[0][i];
+ u16 coeff_b = (*csc_coeff)[1][i];
+ u16 coeff_c = (*csc_coeff)[2][i];
+
+ hdmi_writeb(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
+ hdmi_writeb(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
+ hdmi_writeb(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
+ hdmi_writeb(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
+ hdmi_writeb(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
+ hdmi_writeb(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
+ }
+
+ hdmi_modb(hdmi, csc_scale, HDMI_CSC_SCALE_CSCSCALE_MASK,
+ HDMI_CSC_SCALE);
+}
+
+static void hdmi_video_csc(struct imx_hdmi *hdmi)
+{
+ int color_depth = 0;
+ int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
+ int decimation = 0;
+
+ /* YCC422 interpolation to 444 mode */
+ if (is_color_space_interpolation(hdmi))
+ interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
+ else if (is_color_space_decimation(hdmi))
+ decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
+
+ if (hdmi->hdmi_data.enc_color_depth == 8)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
+ else if (hdmi->hdmi_data.enc_color_depth == 10)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
+ else if (hdmi->hdmi_data.enc_color_depth == 12)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
+ else if (hdmi->hdmi_data.enc_color_depth == 16)
+ color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
+ else
+ return;
+
+ /* Configure the CSC registers */
+ hdmi_writeb(hdmi, interpolation | decimation, HDMI_CSC_CFG);
+ hdmi_modb(hdmi, color_depth, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
+ HDMI_CSC_SCALE);
+
+ imx_hdmi_update_csc_coeffs(hdmi);
+}
+
+/*
+ * HDMI video packetizer is used to packetize the data.
+ * for example, if input is YCC422 mode or repeater is used,
+ * data should be repacked this module can be bypassed.
+ */
+static void hdmi_video_packetize(struct imx_hdmi *hdmi)
+{
+ unsigned int color_depth = 0;
+ unsigned int remap_size = HDMI_VP_REMAP_YCC422_16bit;
+ unsigned int output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_PP;
+ struct hdmi_data_info *hdmi_data = &hdmi->hdmi_data;
+ u8 val, vp_conf;
+
+ if (hdmi_data->enc_out_format == RGB
+ || hdmi_data->enc_out_format == YCBCR444) {
+ if (!hdmi_data->enc_color_depth)
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+ else if (hdmi_data->enc_color_depth == 8) {
+ color_depth = 4;
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
+ } else if (hdmi_data->enc_color_depth == 10)
+ color_depth = 5;
+ else if (hdmi_data->enc_color_depth == 12)
+ color_depth = 6;
+ else if (hdmi_data->enc_color_depth == 16)
+ color_depth = 7;
+ else
+ return;
+ } else if (hdmi_data->enc_out_format == YCBCR422_8BITS) {
+ if (!hdmi_data->enc_color_depth ||
+ hdmi_data->enc_color_depth == 8)
+ remap_size = HDMI_VP_REMAP_YCC422_16bit;
+ else if (hdmi_data->enc_color_depth == 10)
+ remap_size = HDMI_VP_REMAP_YCC422_20bit;
+ else if (hdmi_data->enc_color_depth == 12)
+ remap_size = HDMI_VP_REMAP_YCC422_24bit;
+ else
+ return;
+ output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422;
+ } else
+ return;
+
+ /* set the packetizer registers */
+ val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
+ HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
+ ((hdmi_data->pix_repet_factor <<
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
+ hdmi_writeb(hdmi, val, HDMI_VP_PR_CD);
+
+ hdmi_modb(hdmi, HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE,
+ HDMI_VP_STUFF_PR_STUFFING_MASK, HDMI_VP_STUFF);
+
+ /* Data from pixel repeater block */
+ if (hdmi_data->pix_repet_factor > 1) {
+ vp_conf = HDMI_VP_CONF_PR_EN_ENABLE |
+ HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER;
+ } else { /* data from packetizer block */
+ vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
+ HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
+ }
+
+ hdmi_modb(hdmi, vp_conf,
+ HDMI_VP_CONF_PR_EN_MASK |
+ HDMI_VP_CONF_BYPASS_SELECT_MASK, HDMI_VP_CONF);
+
+ hdmi_modb(hdmi, 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET,
+ HDMI_VP_STUFF_IDEFAULT_PHASE_MASK, HDMI_VP_STUFF);
+
+ hdmi_writeb(hdmi, remap_size, HDMI_VP_REMAP);
+
+ if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_PP) {
+ vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+ HDMI_VP_CONF_PP_EN_ENABLE |
+ HDMI_VP_CONF_YCC422_EN_DISABLE;
+ } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422) {
+ vp_conf = HDMI_VP_CONF_BYPASS_EN_DISABLE |
+ HDMI_VP_CONF_PP_EN_DISABLE |
+ HDMI_VP_CONF_YCC422_EN_ENABLE;
+ } else if (output_select == HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS) {
+ vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
+ HDMI_VP_CONF_PP_EN_DISABLE |
+ HDMI_VP_CONF_YCC422_EN_DISABLE;
+ } else {
+ return;
+ }
+
+ hdmi_modb(hdmi, vp_conf,
+ HDMI_VP_CONF_BYPASS_EN_MASK | HDMI_VP_CONF_PP_EN_ENMASK |
+ HDMI_VP_CONF_YCC422_EN_MASK, HDMI_VP_CONF);
+
+ hdmi_modb(hdmi, HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
+ HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE,
+ HDMI_VP_STUFF_PP_STUFFING_MASK |
+ HDMI_VP_STUFF_YCC422_STUFFING_MASK, HDMI_VP_STUFF);
+
+ hdmi_modb(hdmi, output_select, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
+ HDMI_VP_CONF);
+}
+
+static inline void hdmi_phy_test_clear(struct imx_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLR_OFFSET,
+ HDMI_PHY_TST0_TSTCLR_MASK, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_enable(struct imx_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTEN_OFFSET,
+ HDMI_PHY_TST0_TSTEN_MASK, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_clock(struct imx_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_modb(hdmi, bit << HDMI_PHY_TST0_TSTCLK_OFFSET,
+ HDMI_PHY_TST0_TSTCLK_MASK, HDMI_PHY_TST0);
+}
+
+static inline void hdmi_phy_test_din(struct imx_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_writeb(hdmi, bit, HDMI_PHY_TST1);
+}
+
+static inline void hdmi_phy_test_dout(struct imx_hdmi *hdmi,
+ unsigned char bit)
+{
+ hdmi_writeb(hdmi, bit, HDMI_PHY_TST2);
+}
+
+static bool hdmi_phy_wait_i2c_done(struct imx_hdmi *hdmi, int msec)
+{
+ unsigned char val = 0;
+ val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3;
+ while (!val) {
+ udelay(1000);
+ if (msec-- == 0)
+ return false;
+ val = hdmi_readb(hdmi, HDMI_IH_I2CMPHY_STAT0) & 0x3;
+ }
+ return true;
+}
+
+static void __hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
+ unsigned char addr)
+{
+ hdmi_writeb(hdmi, 0xFF, HDMI_IH_I2CMPHY_STAT0);
+ hdmi_writeb(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
+ hdmi_writeb(hdmi, (unsigned char)(data >> 8),
+ HDMI_PHY_I2CM_DATAO_1_ADDR);
+ hdmi_writeb(hdmi, (unsigned char)(data >> 0),
+ HDMI_PHY_I2CM_DATAO_0_ADDR);
+ hdmi_writeb(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
+ HDMI_PHY_I2CM_OPERATION_ADDR);
+ hdmi_phy_wait_i2c_done(hdmi, 1000);
+}
+
+static int hdmi_phy_i2c_write(struct imx_hdmi *hdmi, unsigned short data,
+ unsigned char addr)
+{
+ __hdmi_phy_i2c_write(hdmi, data, addr);
+ return 0;
+}
+
+static void imx_hdmi_phy_enable_power(struct imx_hdmi *hdmi, u8 enable)
+{
+ hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_PDZ_OFFSET,
+ HDMI_PHY_CONF0_PDZ_MASK);
+}
+
+static void imx_hdmi_phy_enable_tmds(struct imx_hdmi *hdmi, u8 enable)
+{
+ hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_ENTMDS_OFFSET,
+ HDMI_PHY_CONF0_ENTMDS_MASK);
+}
+
+static void imx_hdmi_phy_gen2_pddq(struct imx_hdmi *hdmi, u8 enable)
+{
+ hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET,
+ HDMI_PHY_CONF0_GEN2_PDDQ_MASK);
+}
+
+static void imx_hdmi_phy_gen2_txpwron(struct imx_hdmi *hdmi, u8 enable)
+{
+ hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_MASK);
+}
+
+static void imx_hdmi_phy_sel_data_en_pol(struct imx_hdmi *hdmi, u8 enable)
+{
+ hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_SELDATAENPOL_OFFSET,
+ HDMI_PHY_CONF0_SELDATAENPOL_MASK);
+}
+
+static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable)
+{
+ hdmi_mask_writeb(hdmi, enable, HDMI_PHY_CONF0,
+ HDMI_PHY_CONF0_SELDIPIF_OFFSET,
+ HDMI_PHY_CONF0_SELDIPIF_MASK);
+}
+
+enum {
+ RES_8,
+ RES_10,
+ RES_12,
+ RES_MAX,
+};
+
+struct mpll_config {
+ unsigned long mpixelclock;
+ struct {
+ u16 cpce;
+ u16 gmp;
+ } res[RES_MAX];
+};
+
+static const struct mpll_config mpll_config[] = {
+ {
+ 45250000, {
+ { 0x01e0, 0x0000 },
+ { 0x21e1, 0x0000 },
+ { 0x41e2, 0x0000 }
+ },
+ }, {
+ 92500000, {
+ { 0x0140, 0x0005 },
+ { 0x2141, 0x0005 },
+ { 0x4142, 0x0005 },
+ },
+ }, {
+ 148500000, {
+ { 0x00a0, 0x000a },
+ { 0x20a1, 0x000a },
+ { 0x40a2, 0x000a },
+ },
+ }, {
+ ~0UL, {
+ { 0x00a0, 0x000a },
+ { 0x2001, 0x000f },
+ { 0x4002, 0x000f },
+ },
+ }
+};
+
+struct curr_ctrl {
+ unsigned long mpixelclock;
+ u16 curr[RES_MAX];
+};
+
+static const struct curr_ctrl curr_ctrl[] = {
+ /* pixelclk bpp8 bpp10 bpp12 */
+ {
+ 54000000, { 0x091c, 0x091c, 0x06dc },
+ }, {
+ 58400000, { 0x091c, 0x06dc, 0x06dc },
+ }, {
+ 72000000, { 0x06dc, 0x06dc, 0x091c },
+ }, {
+ 74250000, { 0x06dc, 0x0b5c, 0x091c },
+ }, {
+ 118800000, { 0x091c, 0x091c, 0x06dc },
+ }, {
+ 216000000, { 0x06dc, 0x0b5c, 0x091c },
+ }
+};
+
+static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
+ unsigned char res, int cscon)
+{
+ unsigned res_idx, i;
+ u8 val, msec;
+
+ if (prep)
+ return -EINVAL;
+
+ switch (res) {
+ case 0: /* color resolution 0 is 8 bit colour depth */
+ case 8:
+ res_idx = RES_8;
+ break;
+ case 10:
+ res_idx = RES_10;
+ break;
+ case 12:
+ res_idx = RES_12;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Enable csc path */
+ if (cscon)
+ val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
+ else
+ val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS;
+
+ hdmi_writeb(hdmi, val, HDMI_MC_FLOWCTRL);
+
+ /* gen2 tx power off */
+ imx_hdmi_phy_gen2_txpwron(hdmi, 0);
+
+ /* gen2 pddq */
+ imx_hdmi_phy_gen2_pddq(hdmi, 1);
+
+ /* PHY reset */
+ hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
+ hdmi_writeb(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
+
+ hdmi_writeb(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
+
+ hdmi_phy_test_clear(hdmi, 1);
+ hdmi_writeb(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
+ HDMI_PHY_I2CM_SLAVE_ADDR);
+ hdmi_phy_test_clear(hdmi, 0);
+
+ /* PLL/MPLL Cfg - always match on final entry */
+ for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
+ if (hdmi->hdmi_data.video_mode.mpixelclock <=
+ mpll_config[i].mpixelclock)
+ break;
+
+ hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
+ hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
+
+ for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
+ if (hdmi->hdmi_data.video_mode.mpixelclock <=
+ curr_ctrl[i].mpixelclock)
+ break;
+
+ if (i >= ARRAY_SIZE(curr_ctrl)) {
+ dev_err(hdmi->dev,
+ "Pixel clock %d - unsupported by HDMI\n",
+ hdmi->hdmi_data.video_mode.mpixelclock);
+ return -EINVAL;
+ }
+
+ /* CURRCTRL */
+ hdmi_phy_i2c_write(hdmi, curr_ctrl[i].curr[res_idx], 0x10);
+
+ hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
+ hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
+ /* RESISTANCE TERM 133Ohm Cfg */
+ hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */
+ /* PREEMP Cgf 0.00 */
+ hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */
+ /* TX/CK LVL 10 */
+ hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
+ /* REMOVE CLK TERM */
+ hdmi_phy_i2c_write(hdmi, 0x8000, 0x05); /* CKCALCTRL */
+
+ imx_hdmi_phy_enable_power(hdmi, 1);
+
+ /* toggle TMDS enable */
+ imx_hdmi_phy_enable_tmds(hdmi, 0);
+ imx_hdmi_phy_enable_tmds(hdmi, 1);
+
+ /* gen2 tx power on */
+ imx_hdmi_phy_gen2_txpwron(hdmi, 1);
+ imx_hdmi_phy_gen2_pddq(hdmi, 0);
+
+ /*Wait for PHY PLL lock */
+ msec = 5;
+ do {
+ val = hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_TX_PHY_LOCK;
+ if (!val)
+ break;
+
+ if (msec == 0) {
+ dev_err(hdmi->dev, "PHY PLL not locked\n");
+ return -ETIMEDOUT;
+ }
+
+ udelay(1000);
+ msec--;
+ } while (1);
+
+ return 0;
+}
+
+static int imx_hdmi_phy_init(struct imx_hdmi *hdmi)
+{
+ int i, ret;
+ bool cscon = false;
+
+ /*check csc whether needed activated in HDMI mode */
+ cscon = (is_color_space_conversion(hdmi) &&
+ !hdmi->hdmi_data.video_mode.mdvi);
+
+ /* HDMI Phy spec says to do the phy initialization sequence twice */
+ for (i = 0; i < 2; i++) {
+ imx_hdmi_phy_sel_data_en_pol(hdmi, 1);
+ imx_hdmi_phy_sel_interface_control(hdmi, 0);
+ imx_hdmi_phy_enable_tmds(hdmi, 0);
+ imx_hdmi_phy_enable_power(hdmi, 0);
+
+ /* Enable CSC */
+ ret = hdmi_phy_configure(hdmi, 0, 8, cscon);
+ if (ret)
+ return ret;
+ }
+
+ hdmi->phy_enabled = true;
+ return 0;
+}
+
+static void hdmi_tx_hdcp_config(struct imx_hdmi *hdmi)
+{
+ u8 de;
+
+ if (hdmi->hdmi_data.video_mode.mdataenablepolarity)
+ de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH;
+ else
+ de = HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW;
+
+ /* disable rx detect */
+ hdmi_modb(hdmi, HDMI_A_HDCPCFG0_RXDETECT_DISABLE,
+ HDMI_A_HDCPCFG0_RXDETECT_MASK, HDMI_A_HDCPCFG0);
+
+ hdmi_modb(hdmi, de, HDMI_A_VIDPOLCFG_DATAENPOL_MASK, HDMI_A_VIDPOLCFG);
+
+ hdmi_modb(hdmi, HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE,
+ HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK, HDMI_A_HDCPCFG1);
+}
+
+static void imx_hdmi_phy_disable(struct imx_hdmi *hdmi)
+{
+ if (!hdmi->phy_enabled)
+ return;
+
+ imx_hdmi_phy_enable_tmds(hdmi, 0);
+ imx_hdmi_phy_enable_power(hdmi, 0);
+
+ hdmi->phy_enabled = false;
+}
+
+/* HDMI Initialization Step B.4 */
+static void imx_hdmi_enable_video_path(struct imx_hdmi *hdmi)
+{
+ u8 clkdis;
+
+ /* control period minimum duration */
+ hdmi_writeb(hdmi, 12, HDMI_FC_CTRLDUR);
+ hdmi_writeb(hdmi, 32, HDMI_FC_EXCTRLDUR);
+ hdmi_writeb(hdmi, 1, HDMI_FC_EXCTRLSPAC);
+
+ /* Set to fill TMDS data channels */
+ hdmi_writeb(hdmi, 0x0B, HDMI_FC_CH0PREAM);
+ hdmi_writeb(hdmi, 0x16, HDMI_FC_CH1PREAM);
+ hdmi_writeb(hdmi, 0x21, HDMI_FC_CH2PREAM);
+
+ /* Enable pixel clock and tmds data path */
+ clkdis = 0x7F;
+ clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
+ hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+ clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
+ hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+
+ /* Enable csc path */
+ if (is_color_space_conversion(hdmi)) {
+ clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
+ hdmi_writeb(hdmi, clkdis, HDMI_MC_CLKDIS);
+ }
+}
+
+/* Workaround to clear the overflow condition */
+static void imx_hdmi_clear_overflow(struct imx_hdmi *hdmi)
+{
+ int count;
+ u8 val;
+
+ /* TMDS software reset */
+ hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
+
+ val = hdmi_readb(hdmi, HDMI_FC_INVIDCONF);
+ if (hdmi->dev_type == IMX6DL_HDMI) {
+ hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
+ return;
+ }
+
+ for (count = 0; count < 4; count++)
+ hdmi_writeb(hdmi, val, HDMI_FC_INVIDCONF);
+}
+
+static int imx_hdmi_setup(struct imx_hdmi *hdmi, struct fb_videomode *mode)
+{
+ int ret;
+
+ hdmi->vic = 0;
+
+ dev_dbg(hdmi->dev, "Non-CEA mode used in HDMI\n");
+ hdmi->hdmi_data.video_mode.mdvi = true;
+
+ hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
+ hdmi->hdmi_data.video_mode.mpixelrepetitionoutput = 0;
+ hdmi->hdmi_data.video_mode.mpixelrepetitioninput = 0;
+
+ /* TODO: Get input format from IPU (via FB driver interface) */
+ hdmi->hdmi_data.enc_in_format = RGB;
+
+ hdmi->hdmi_data.enc_out_format = RGB;
+
+ hdmi->hdmi_data.enc_color_depth = 8;
+ hdmi->hdmi_data.pix_repet_factor = 0;
+ hdmi->hdmi_data.hdcp_enable = 0;
+ hdmi->hdmi_data.video_mode.mdataenablepolarity = true;
+
+ /* HDMI Initializateion Step B.2 */
+ ret = imx_hdmi_phy_init(hdmi);
+ if (ret)
+ return ret;
+
+ /* HDMI Initialization Step B.3 */
+ imx_hdmi_enable_video_path(hdmi);
+
+ /* not for DVI mode */
+ dev_dbg(hdmi->dev, "%s DVI mode\n", __func__);
+
+ hdmi_video_packetize(hdmi);
+ hdmi_video_csc(hdmi);
+ hdmi_video_sample(hdmi);
+ hdmi_tx_hdcp_config(hdmi);
+
+ imx_hdmi_clear_overflow(hdmi);
+
+ return 0;
+}
+
+static void initialize_hdmi_ih_mutes(struct imx_hdmi *hdmi)
+{
+ u8 ih_mute;
+
+ /*
+ * Boot up defaults are:
+ * HDMI_IH_MUTE = 0x03 (disabled)
+ * HDMI_IH_MUTE_* = 0x00 (enabled)
+ *
+ * Disable top level interrupt bits in HDMI block
+ */
+ ih_mute = hdmi_readb(hdmi, HDMI_IH_MUTE) |
+ HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+ HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
+
+ hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+
+ /* by default mask all interrupts */
+ hdmi_writeb(hdmi, 0xff, HDMI_VP_MASK);
+ hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK0);
+ hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK1);
+ hdmi_writeb(hdmi, 0xff, HDMI_FC_MASK2);
+ hdmi_writeb(hdmi, 0xff, HDMI_PHY_MASK0);
+ hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_INT_ADDR);
+ hdmi_writeb(hdmi, 0xff, HDMI_PHY_I2CM_CTLINT_ADDR);
+ hdmi_writeb(hdmi, 0xff, HDMI_AUD_INT);
+ hdmi_writeb(hdmi, 0xff, HDMI_AUD_SPDIFINT);
+ hdmi_writeb(hdmi, 0xff, HDMI_AUD_HBR_MASK);
+ hdmi_writeb(hdmi, 0xff, HDMI_GP_MASK);
+ hdmi_writeb(hdmi, 0xff, HDMI_A_APIINTMSK);
+ hdmi_writeb(hdmi, 0xff, HDMI_CEC_MASK);
+ hdmi_writeb(hdmi, 0xff, HDMI_I2CM_INT);
+ hdmi_writeb(hdmi, 0xff, HDMI_I2CM_CTLINT);
+
+ /* Disable interrupts in the IH_MUTE_* registers */
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT1);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_FC_STAT2);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AS_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_PHY_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CM_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_CEC_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_VP_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_I2CMPHY_STAT0);
+ hdmi_writeb(hdmi, 0xff, HDMI_IH_MUTE_AHBDMAAUD_STAT0);
+
+ /* Enable top level interrupt bits in HDMI block */
+ ih_mute &= ~(HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
+ HDMI_IH_MUTE_MUTE_ALL_INTERRUPT);
+ hdmi_writeb(hdmi, ih_mute, HDMI_IH_MUTE);
+}
+
+struct imx_hdmi_data {
+ unsigned ipu_mask;
+ enum imx_hdmi_devtype devtype;
+};
+
+static struct imx_hdmi_data imx6q_hdmi_data = {
+ .ipu_mask = 0xf,
+ .devtype = IMX6Q_HDMI,
+};
+
+static struct imx_hdmi_data imx6dl_hdmi_data = {
+ .ipu_mask = 0x3,
+ .devtype = IMX6DL_HDMI,
+};
+
+static struct of_device_id imx_hdmi_dt_ids[] = {
+ {
+ .compatible = "fsl,imx6q-hdmi",
+ .data = (unsigned long)&imx6q_hdmi_data,
+ }, {
+ .compatible = "fsl,imx6dl-hdmi",
+ .data = (unsigned long)&imx6dl_hdmi_data,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int imx_hdmi_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+{
+ struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+
+ imx_hdmi_set_ipu_di_mux(hdmi, di);
+
+ return 0;
+}
+
+static int imx_hdmi_commit(struct ipu_output *output, struct fb_videomode *mode, int di)
+{
+ struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+
+ imx_hdmi_setup(hdmi, mode);
+
+ return 0;
+}
+
+static int imx_hdmi_disable(struct ipu_output *output)
+{
+ struct imx_hdmi *hdmi = container_of(output, struct imx_hdmi, output);
+
+ imx_hdmi_phy_disable(hdmi);
+
+ return 0;
+}
+
+static struct ipu_output_ops imx_hdmi_ops = {
+ .prepare = imx_hdmi_prepare,
+ .enable = imx_hdmi_commit,
+ .disable = imx_hdmi_disable,
+};
+
+static int imx_hdmi_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ struct device_node *ddc_node;
+ struct imx_hdmi *hdmi;
+ int ret;
+ const struct imx_hdmi_data *devtype;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
+ if (ret)
+ return ret;
+
+ hdmi = xzalloc(sizeof(*hdmi));
+
+ hdmi->dev = dev;
+ hdmi->connected = 0;
+ hdmi->sample_rate = 48000;
+ hdmi->ratio = 100;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&hdmi->dev_type);
+ if (ret)
+ return ret;
+
+ ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
+ if (ddc_node) {
+ hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
+ if (!hdmi->ddc)
+ dev_dbg(hdmi->dev, "failed to read ddc node\n");
+ } else {
+ dev_dbg(hdmi->dev, "no ddc property found\n");
+ }
+
+ ddc_node = NULL;
+
+ hdmi->regs = dev_request_mem_region(dev, 0);
+ if (!hdmi->regs)
+ return -EBUSY;
+
+ hdmi->isfr_clk = clk_get(hdmi->dev, "isfr");
+ if (IS_ERR(hdmi->isfr_clk)) {
+ ret = PTR_ERR(hdmi->isfr_clk);
+ dev_err(dev,
+ "Unable to get HDMI isfr clk: %d\n", ret);
+ return ret;
+ }
+
+ ret = clk_enable(hdmi->isfr_clk);
+ if (ret)
+ return ret;
+
+ hdmi->iahb_clk = clk_get(hdmi->dev, "iahb");
+ if (IS_ERR(hdmi->iahb_clk)) {
+ ret = PTR_ERR(hdmi->iahb_clk);
+ dev_err(dev,
+ "Unable to get HDMI iahb clk: %d\n", ret);
+ goto err_isfr;
+ }
+
+ ret = clk_enable(hdmi->iahb_clk);
+ if (ret)
+ goto err_isfr;
+
+ /* Product and revision IDs */
+ dev_info(dev,
+ "Detected HDMI controller 0x%x:0x%x:0x%x:0x%x\n",
+ hdmi_readb(hdmi, HDMI_DESIGN_ID),
+ hdmi_readb(hdmi, HDMI_REVISION_ID),
+ hdmi_readb(hdmi, HDMI_PRODUCT_ID0),
+ hdmi_readb(hdmi, HDMI_PRODUCT_ID1));
+
+ initialize_hdmi_ih_mutes(hdmi);
+
+ /*
+ * To prevent overflows in HDMI_IH_FC_STAT2, set the clk regenerator
+ * N and cts values before enabling phy
+ */
+ hdmi_init_clk_regenerator(hdmi);
+
+ /*
+ * Configure registers related to HDMI interrupt
+ * generation before registering IRQ.
+ */
+ hdmi_writeb(hdmi, HDMI_PHY_HPD, HDMI_PHY_POL0);
+
+ /* Clear Hotplug interrupts */
+ hdmi_writeb(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
+
+ hdmi_writeb(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
+ HDMI_PHY_I2CM_INT_ADDR);
+
+ hdmi_writeb(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
+ HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
+ HDMI_PHY_I2CM_CTLINT_ADDR);
+
+ /* enable cable hot plug irq */
+ hdmi_writeb(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
+
+ /* Unmute interrupts */
+ hdmi_writeb(hdmi, ~HDMI_IH_PHY_STAT0_HPD, HDMI_IH_MUTE_PHY_STAT0);
+
+ hdmi->output.ops = &imx_hdmi_ops;
+ hdmi->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+ hdmi->output.out_pixel_fmt = V4L2_PIX_FMT_RGB24;
+ hdmi->output.name = asprintf("hdmi-0");
+ hdmi->output.ipu_mask = devtype->ipu_mask;
+ hdmi->output.edid_i2c_adapter = hdmi->ddc;
+ hdmi->output.modes = of_get_display_timings(np);
+
+ ipu_register_output(&hdmi->output);
+
+ return 0;
+
+err_isfr:
+ clk_disable(hdmi->isfr_clk);
+
+ return ret;
+}
+
+static struct driver_d imx_hdmi_driver = {
+ .probe = imx_hdmi_probe,
+ .of_compatible = imx_hdmi_dt_ids,
+ .name = "imx-hdmi",
+};
+device_platform_driver(imx_hdmi_driver);
+
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_DESCRIPTION("i.MX6 HDMI transmitter driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/imx-ipu-v3/imx-hdmi.h b/drivers/video/imx-ipu-v3/imx-hdmi.h
new file mode 100644
index 0000000000..39b677689d
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-hdmi.h
@@ -0,0 +1,1032 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __IMX_HDMI_H__
+#define __IMX_HDMI_H__
+
+/* Identification Registers */
+#define HDMI_DESIGN_ID 0x0000
+#define HDMI_REVISION_ID 0x0001
+#define HDMI_PRODUCT_ID0 0x0002
+#define HDMI_PRODUCT_ID1 0x0003
+#define HDMI_CONFIG0_ID 0x0004
+#define HDMI_CONFIG1_ID 0x0005
+#define HDMI_CONFIG2_ID 0x0006
+#define HDMI_CONFIG3_ID 0x0007
+
+/* Interrupt Registers */
+#define HDMI_IH_FC_STAT0 0x0100
+#define HDMI_IH_FC_STAT1 0x0101
+#define HDMI_IH_FC_STAT2 0x0102
+#define HDMI_IH_AS_STAT0 0x0103
+#define HDMI_IH_PHY_STAT0 0x0104
+#define HDMI_IH_I2CM_STAT0 0x0105
+#define HDMI_IH_CEC_STAT0 0x0106
+#define HDMI_IH_VP_STAT0 0x0107
+#define HDMI_IH_I2CMPHY_STAT0 0x0108
+#define HDMI_IH_AHBDMAAUD_STAT0 0x0109
+
+#define HDMI_IH_MUTE_FC_STAT0 0x0180
+#define HDMI_IH_MUTE_FC_STAT1 0x0181
+#define HDMI_IH_MUTE_FC_STAT2 0x0182
+#define HDMI_IH_MUTE_AS_STAT0 0x0183
+#define HDMI_IH_MUTE_PHY_STAT0 0x0184
+#define HDMI_IH_MUTE_I2CM_STAT0 0x0185
+#define HDMI_IH_MUTE_CEC_STAT0 0x0186
+#define HDMI_IH_MUTE_VP_STAT0 0x0187
+#define HDMI_IH_MUTE_I2CMPHY_STAT0 0x0188
+#define HDMI_IH_MUTE_AHBDMAAUD_STAT0 0x0189
+#define HDMI_IH_MUTE 0x01FF
+
+/* Video Sample Registers */
+#define HDMI_TX_INVID0 0x0200
+#define HDMI_TX_INSTUFFING 0x0201
+#define HDMI_TX_GYDATA0 0x0202
+#define HDMI_TX_GYDATA1 0x0203
+#define HDMI_TX_RCRDATA0 0x0204
+#define HDMI_TX_RCRDATA1 0x0205
+#define HDMI_TX_BCBDATA0 0x0206
+#define HDMI_TX_BCBDATA1 0x0207
+
+/* Video Packetizer Registers */
+#define HDMI_VP_STATUS 0x0800
+#define HDMI_VP_PR_CD 0x0801
+#define HDMI_VP_STUFF 0x0802
+#define HDMI_VP_REMAP 0x0803
+#define HDMI_VP_CONF 0x0804
+#define HDMI_VP_STAT 0x0805
+#define HDMI_VP_INT 0x0806
+#define HDMI_VP_MASK 0x0807
+#define HDMI_VP_POL 0x0808
+
+/* Frame Composer Registers */
+#define HDMI_FC_INVIDCONF 0x1000
+#define HDMI_FC_INHACTV0 0x1001
+#define HDMI_FC_INHACTV1 0x1002
+#define HDMI_FC_INHBLANK0 0x1003
+#define HDMI_FC_INHBLANK1 0x1004
+#define HDMI_FC_INVACTV0 0x1005
+#define HDMI_FC_INVACTV1 0x1006
+#define HDMI_FC_INVBLANK 0x1007
+#define HDMI_FC_HSYNCINDELAY0 0x1008
+#define HDMI_FC_HSYNCINDELAY1 0x1009
+#define HDMI_FC_HSYNCINWIDTH0 0x100A
+#define HDMI_FC_HSYNCINWIDTH1 0x100B
+#define HDMI_FC_VSYNCINDELAY 0x100C
+#define HDMI_FC_VSYNCINWIDTH 0x100D
+#define HDMI_FC_INFREQ0 0x100E
+#define HDMI_FC_INFREQ1 0x100F
+#define HDMI_FC_INFREQ2 0x1010
+#define HDMI_FC_CTRLDUR 0x1011
+#define HDMI_FC_EXCTRLDUR 0x1012
+#define HDMI_FC_EXCTRLSPAC 0x1013
+#define HDMI_FC_CH0PREAM 0x1014
+#define HDMI_FC_CH1PREAM 0x1015
+#define HDMI_FC_CH2PREAM 0x1016
+#define HDMI_FC_AVICONF3 0x1017
+#define HDMI_FC_GCP 0x1018
+#define HDMI_FC_AVICONF0 0x1019
+#define HDMI_FC_AVICONF1 0x101A
+#define HDMI_FC_AVICONF2 0x101B
+#define HDMI_FC_AVIVID 0x101C
+#define HDMI_FC_AVIETB0 0x101D
+#define HDMI_FC_AVIETB1 0x101E
+#define HDMI_FC_AVISBB0 0x101F
+#define HDMI_FC_AVISBB1 0x1020
+#define HDMI_FC_AVIELB0 0x1021
+#define HDMI_FC_AVIELB1 0x1022
+#define HDMI_FC_AVISRB0 0x1023
+#define HDMI_FC_AVISRB1 0x1024
+#define HDMI_FC_AUDICONF0 0x1025
+#define HDMI_FC_AUDICONF1 0x1026
+#define HDMI_FC_AUDICONF2 0x1027
+#define HDMI_FC_AUDICONF3 0x1028
+#define HDMI_FC_VSDIEEEID0 0x1029
+#define HDMI_FC_VSDSIZE 0x102A
+#define HDMI_FC_VSDIEEEID1 0x1030
+#define HDMI_FC_VSDIEEEID2 0x1031
+#define HDMI_FC_VSDPAYLOAD0 0x1032
+#define HDMI_FC_VSDPAYLOAD1 0x1033
+#define HDMI_FC_VSDPAYLOAD2 0x1034
+#define HDMI_FC_VSDPAYLOAD3 0x1035
+#define HDMI_FC_VSDPAYLOAD4 0x1036
+#define HDMI_FC_VSDPAYLOAD5 0x1037
+#define HDMI_FC_VSDPAYLOAD6 0x1038
+#define HDMI_FC_VSDPAYLOAD7 0x1039
+#define HDMI_FC_VSDPAYLOAD8 0x103A
+#define HDMI_FC_VSDPAYLOAD9 0x103B
+#define HDMI_FC_VSDPAYLOAD10 0x103C
+#define HDMI_FC_VSDPAYLOAD11 0x103D
+#define HDMI_FC_VSDPAYLOAD12 0x103E
+#define HDMI_FC_VSDPAYLOAD13 0x103F
+#define HDMI_FC_VSDPAYLOAD14 0x1040
+#define HDMI_FC_VSDPAYLOAD15 0x1041
+#define HDMI_FC_VSDPAYLOAD16 0x1042
+#define HDMI_FC_VSDPAYLOAD17 0x1043
+#define HDMI_FC_VSDPAYLOAD18 0x1044
+#define HDMI_FC_VSDPAYLOAD19 0x1045
+#define HDMI_FC_VSDPAYLOAD20 0x1046
+#define HDMI_FC_VSDPAYLOAD21 0x1047
+#define HDMI_FC_VSDPAYLOAD22 0x1048
+#define HDMI_FC_VSDPAYLOAD23 0x1049
+#define HDMI_FC_SPDVENDORNAME0 0x104A
+#define HDMI_FC_SPDVENDORNAME1 0x104B
+#define HDMI_FC_SPDVENDORNAME2 0x104C
+#define HDMI_FC_SPDVENDORNAME3 0x104D
+#define HDMI_FC_SPDVENDORNAME4 0x104E
+#define HDMI_FC_SPDVENDORNAME5 0x104F
+#define HDMI_FC_SPDVENDORNAME6 0x1050
+#define HDMI_FC_SPDVENDORNAME7 0x1051
+#define HDMI_FC_SDPPRODUCTNAME0 0x1052
+#define HDMI_FC_SDPPRODUCTNAME1 0x1053
+#define HDMI_FC_SDPPRODUCTNAME2 0x1054
+#define HDMI_FC_SDPPRODUCTNAME3 0x1055
+#define HDMI_FC_SDPPRODUCTNAME4 0x1056
+#define HDMI_FC_SDPPRODUCTNAME5 0x1057
+#define HDMI_FC_SDPPRODUCTNAME6 0x1058
+#define HDMI_FC_SDPPRODUCTNAME7 0x1059
+#define HDMI_FC_SDPPRODUCTNAME8 0x105A
+#define HDMI_FC_SDPPRODUCTNAME9 0x105B
+#define HDMI_FC_SDPPRODUCTNAME10 0x105C
+#define HDMI_FC_SDPPRODUCTNAME11 0x105D
+#define HDMI_FC_SDPPRODUCTNAME12 0x105E
+#define HDMI_FC_SDPPRODUCTNAME13 0x105F
+#define HDMI_FC_SDPPRODUCTNAME14 0x1060
+#define HDMI_FC_SPDPRODUCTNAME15 0x1061
+#define HDMI_FC_SPDDEVICEINF 0x1062
+#define HDMI_FC_AUDSCONF 0x1063
+#define HDMI_FC_AUDSSTAT 0x1064
+#define HDMI_FC_DATACH0FILL 0x1070
+#define HDMI_FC_DATACH1FILL 0x1071
+#define HDMI_FC_DATACH2FILL 0x1072
+#define HDMI_FC_CTRLQHIGH 0x1073
+#define HDMI_FC_CTRLQLOW 0x1074
+#define HDMI_FC_ACP0 0x1075
+#define HDMI_FC_ACP28 0x1076
+#define HDMI_FC_ACP27 0x1077
+#define HDMI_FC_ACP26 0x1078
+#define HDMI_FC_ACP25 0x1079
+#define HDMI_FC_ACP24 0x107A
+#define HDMI_FC_ACP23 0x107B
+#define HDMI_FC_ACP22 0x107C
+#define HDMI_FC_ACP21 0x107D
+#define HDMI_FC_ACP20 0x107E
+#define HDMI_FC_ACP19 0x107F
+#define HDMI_FC_ACP18 0x1080
+#define HDMI_FC_ACP17 0x1081
+#define HDMI_FC_ACP16 0x1082
+#define HDMI_FC_ACP15 0x1083
+#define HDMI_FC_ACP14 0x1084
+#define HDMI_FC_ACP13 0x1085
+#define HDMI_FC_ACP12 0x1086
+#define HDMI_FC_ACP11 0x1087
+#define HDMI_FC_ACP10 0x1088
+#define HDMI_FC_ACP9 0x1089
+#define HDMI_FC_ACP8 0x108A
+#define HDMI_FC_ACP7 0x108B
+#define HDMI_FC_ACP6 0x108C
+#define HDMI_FC_ACP5 0x108D
+#define HDMI_FC_ACP4 0x108E
+#define HDMI_FC_ACP3 0x108F
+#define HDMI_FC_ACP2 0x1090
+#define HDMI_FC_ACP1 0x1091
+#define HDMI_FC_ISCR1_0 0x1092
+#define HDMI_FC_ISCR1_16 0x1093
+#define HDMI_FC_ISCR1_15 0x1094
+#define HDMI_FC_ISCR1_14 0x1095
+#define HDMI_FC_ISCR1_13 0x1096
+#define HDMI_FC_ISCR1_12 0x1097
+#define HDMI_FC_ISCR1_11 0x1098
+#define HDMI_FC_ISCR1_10 0x1099
+#define HDMI_FC_ISCR1_9 0x109A
+#define HDMI_FC_ISCR1_8 0x109B
+#define HDMI_FC_ISCR1_7 0x109C
+#define HDMI_FC_ISCR1_6 0x109D
+#define HDMI_FC_ISCR1_5 0x109E
+#define HDMI_FC_ISCR1_4 0x109F
+#define HDMI_FC_ISCR1_3 0x10A0
+#define HDMI_FC_ISCR1_2 0x10A1
+#define HDMI_FC_ISCR1_1 0x10A2
+#define HDMI_FC_ISCR2_15 0x10A3
+#define HDMI_FC_ISCR2_14 0x10A4
+#define HDMI_FC_ISCR2_13 0x10A5
+#define HDMI_FC_ISCR2_12 0x10A6
+#define HDMI_FC_ISCR2_11 0x10A7
+#define HDMI_FC_ISCR2_10 0x10A8
+#define HDMI_FC_ISCR2_9 0x10A9
+#define HDMI_FC_ISCR2_8 0x10AA
+#define HDMI_FC_ISCR2_7 0x10AB
+#define HDMI_FC_ISCR2_6 0x10AC
+#define HDMI_FC_ISCR2_5 0x10AD
+#define HDMI_FC_ISCR2_4 0x10AE
+#define HDMI_FC_ISCR2_3 0x10AF
+#define HDMI_FC_ISCR2_2 0x10B0
+#define HDMI_FC_ISCR2_1 0x10B1
+#define HDMI_FC_ISCR2_0 0x10B2
+#define HDMI_FC_DATAUTO0 0x10B3
+#define HDMI_FC_DATAUTO1 0x10B4
+#define HDMI_FC_DATAUTO2 0x10B5
+#define HDMI_FC_DATMAN 0x10B6
+#define HDMI_FC_DATAUTO3 0x10B7
+#define HDMI_FC_RDRB0 0x10B8
+#define HDMI_FC_RDRB1 0x10B9
+#define HDMI_FC_RDRB2 0x10BA
+#define HDMI_FC_RDRB3 0x10BB
+#define HDMI_FC_RDRB4 0x10BC
+#define HDMI_FC_RDRB5 0x10BD
+#define HDMI_FC_RDRB6 0x10BE
+#define HDMI_FC_RDRB7 0x10BF
+#define HDMI_FC_STAT0 0x10D0
+#define HDMI_FC_INT0 0x10D1
+#define HDMI_FC_MASK0 0x10D2
+#define HDMI_FC_POL0 0x10D3
+#define HDMI_FC_STAT1 0x10D4
+#define HDMI_FC_INT1 0x10D5
+#define HDMI_FC_MASK1 0x10D6
+#define HDMI_FC_POL1 0x10D7
+#define HDMI_FC_STAT2 0x10D8
+#define HDMI_FC_INT2 0x10D9
+#define HDMI_FC_MASK2 0x10DA
+#define HDMI_FC_POL2 0x10DB
+#define HDMI_FC_PRCONF 0x10E0
+
+#define HDMI_FC_GMD_STAT 0x1100
+#define HDMI_FC_GMD_EN 0x1101
+#define HDMI_FC_GMD_UP 0x1102
+#define HDMI_FC_GMD_CONF 0x1103
+#define HDMI_FC_GMD_HB 0x1104
+#define HDMI_FC_GMD_PB0 0x1105
+#define HDMI_FC_GMD_PB1 0x1106
+#define HDMI_FC_GMD_PB2 0x1107
+#define HDMI_FC_GMD_PB3 0x1108
+#define HDMI_FC_GMD_PB4 0x1109
+#define HDMI_FC_GMD_PB5 0x110A
+#define HDMI_FC_GMD_PB6 0x110B
+#define HDMI_FC_GMD_PB7 0x110C
+#define HDMI_FC_GMD_PB8 0x110D
+#define HDMI_FC_GMD_PB9 0x110E
+#define HDMI_FC_GMD_PB10 0x110F
+#define HDMI_FC_GMD_PB11 0x1110
+#define HDMI_FC_GMD_PB12 0x1111
+#define HDMI_FC_GMD_PB13 0x1112
+#define HDMI_FC_GMD_PB14 0x1113
+#define HDMI_FC_GMD_PB15 0x1114
+#define HDMI_FC_GMD_PB16 0x1115
+#define HDMI_FC_GMD_PB17 0x1116
+#define HDMI_FC_GMD_PB18 0x1117
+#define HDMI_FC_GMD_PB19 0x1118
+#define HDMI_FC_GMD_PB20 0x1119
+#define HDMI_FC_GMD_PB21 0x111A
+#define HDMI_FC_GMD_PB22 0x111B
+#define HDMI_FC_GMD_PB23 0x111C
+#define HDMI_FC_GMD_PB24 0x111D
+#define HDMI_FC_GMD_PB25 0x111E
+#define HDMI_FC_GMD_PB26 0x111F
+#define HDMI_FC_GMD_PB27 0x1120
+
+#define HDMI_FC_DBGFORCE 0x1200
+#define HDMI_FC_DBGAUD0CH0 0x1201
+#define HDMI_FC_DBGAUD1CH0 0x1202
+#define HDMI_FC_DBGAUD2CH0 0x1203
+#define HDMI_FC_DBGAUD0CH1 0x1204
+#define HDMI_FC_DBGAUD1CH1 0x1205
+#define HDMI_FC_DBGAUD2CH1 0x1206
+#define HDMI_FC_DBGAUD0CH2 0x1207
+#define HDMI_FC_DBGAUD1CH2 0x1208
+#define HDMI_FC_DBGAUD2CH2 0x1209
+#define HDMI_FC_DBGAUD0CH3 0x120A
+#define HDMI_FC_DBGAUD1CH3 0x120B
+#define HDMI_FC_DBGAUD2CH3 0x120C
+#define HDMI_FC_DBGAUD0CH4 0x120D
+#define HDMI_FC_DBGAUD1CH4 0x120E
+#define HDMI_FC_DBGAUD2CH4 0x120F
+#define HDMI_FC_DBGAUD0CH5 0x1210
+#define HDMI_FC_DBGAUD1CH5 0x1211
+#define HDMI_FC_DBGAUD2CH5 0x1212
+#define HDMI_FC_DBGAUD0CH6 0x1213
+#define HDMI_FC_DBGAUD1CH6 0x1214
+#define HDMI_FC_DBGAUD2CH6 0x1215
+#define HDMI_FC_DBGAUD0CH7 0x1216
+#define HDMI_FC_DBGAUD1CH7 0x1217
+#define HDMI_FC_DBGAUD2CH7 0x1218
+#define HDMI_FC_DBGTMDS0 0x1219
+#define HDMI_FC_DBGTMDS1 0x121A
+#define HDMI_FC_DBGTMDS2 0x121B
+
+/* HDMI Source PHY Registers */
+#define HDMI_PHY_CONF0 0x3000
+#define HDMI_PHY_TST0 0x3001
+#define HDMI_PHY_TST1 0x3002
+#define HDMI_PHY_TST2 0x3003
+#define HDMI_PHY_STAT0 0x3004
+#define HDMI_PHY_INT0 0x3005
+#define HDMI_PHY_MASK0 0x3006
+#define HDMI_PHY_POL0 0x3007
+
+/* HDMI Master PHY Registers */
+#define HDMI_PHY_I2CM_SLAVE_ADDR 0x3020
+#define HDMI_PHY_I2CM_ADDRESS_ADDR 0x3021
+#define HDMI_PHY_I2CM_DATAO_1_ADDR 0x3022
+#define HDMI_PHY_I2CM_DATAO_0_ADDR 0x3023
+#define HDMI_PHY_I2CM_DATAI_1_ADDR 0x3024
+#define HDMI_PHY_I2CM_DATAI_0_ADDR 0x3025
+#define HDMI_PHY_I2CM_OPERATION_ADDR 0x3026
+#define HDMI_PHY_I2CM_INT_ADDR 0x3027
+#define HDMI_PHY_I2CM_CTLINT_ADDR 0x3028
+#define HDMI_PHY_I2CM_DIV_ADDR 0x3029
+#define HDMI_PHY_I2CM_SOFTRSTZ_ADDR 0x302a
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_1_ADDR 0x302b
+#define HDMI_PHY_I2CM_SS_SCL_HCNT_0_ADDR 0x302c
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_1_ADDR 0x302d
+#define HDMI_PHY_I2CM_SS_SCL_LCNT_0_ADDR 0x302e
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_1_ADDR 0x302f
+#define HDMI_PHY_I2CM_FS_SCL_HCNT_0_ADDR 0x3030
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_1_ADDR 0x3031
+#define HDMI_PHY_I2CM_FS_SCL_LCNT_0_ADDR 0x3032
+
+/* Audio Sampler Registers */
+#define HDMI_AUD_CONF0 0x3100
+#define HDMI_AUD_CONF1 0x3101
+#define HDMI_AUD_INT 0x3102
+#define HDMI_AUD_CONF2 0x3103
+#define HDMI_AUD_N1 0x3200
+#define HDMI_AUD_N2 0x3201
+#define HDMI_AUD_N3 0x3202
+#define HDMI_AUD_CTS1 0x3203
+#define HDMI_AUD_CTS2 0x3204
+#define HDMI_AUD_CTS3 0x3205
+#define HDMI_AUD_INPUTCLKFS 0x3206
+#define HDMI_AUD_SPDIFINT 0x3302
+#define HDMI_AUD_CONF0_HBR 0x3400
+#define HDMI_AUD_HBR_STATUS 0x3401
+#define HDMI_AUD_HBR_INT 0x3402
+#define HDMI_AUD_HBR_POL 0x3403
+#define HDMI_AUD_HBR_MASK 0x3404
+
+/*
+ * Generic Parallel Audio Interface Registers
+ * Not used as GPAUD interface is not enabled in hw
+ */
+#define HDMI_GP_CONF0 0x3500
+#define HDMI_GP_CONF1 0x3501
+#define HDMI_GP_CONF2 0x3502
+#define HDMI_GP_STAT 0x3503
+#define HDMI_GP_INT 0x3504
+#define HDMI_GP_MASK 0x3505
+#define HDMI_GP_POL 0x3506
+
+/* Audio DMA Registers */
+#define HDMI_AHB_DMA_CONF0 0x3600
+#define HDMI_AHB_DMA_START 0x3601
+#define HDMI_AHB_DMA_STOP 0x3602
+#define HDMI_AHB_DMA_THRSLD 0x3603
+#define HDMI_AHB_DMA_STRADDR0 0x3604
+#define HDMI_AHB_DMA_STRADDR1 0x3605
+#define HDMI_AHB_DMA_STRADDR2 0x3606
+#define HDMI_AHB_DMA_STRADDR3 0x3607
+#define HDMI_AHB_DMA_STPADDR0 0x3608
+#define HDMI_AHB_DMA_STPADDR1 0x3609
+#define HDMI_AHB_DMA_STPADDR2 0x360a
+#define HDMI_AHB_DMA_STPADDR3 0x360b
+#define HDMI_AHB_DMA_BSTADDR0 0x360c
+#define HDMI_AHB_DMA_BSTADDR1 0x360d
+#define HDMI_AHB_DMA_BSTADDR2 0x360e
+#define HDMI_AHB_DMA_BSTADDR3 0x360f
+#define HDMI_AHB_DMA_MBLENGTH0 0x3610
+#define HDMI_AHB_DMA_MBLENGTH1 0x3611
+#define HDMI_AHB_DMA_STAT 0x3612
+#define HDMI_AHB_DMA_INT 0x3613
+#define HDMI_AHB_DMA_MASK 0x3614
+#define HDMI_AHB_DMA_POL 0x3615
+#define HDMI_AHB_DMA_CONF1 0x3616
+#define HDMI_AHB_DMA_BUFFSTAT 0x3617
+#define HDMI_AHB_DMA_BUFFINT 0x3618
+#define HDMI_AHB_DMA_BUFFMASK 0x3619
+#define HDMI_AHB_DMA_BUFFPOL 0x361a
+
+/* Main Controller Registers */
+#define HDMI_MC_SFRDIV 0x4000
+#define HDMI_MC_CLKDIS 0x4001
+#define HDMI_MC_SWRSTZ 0x4002
+#define HDMI_MC_OPCTRL 0x4003
+#define HDMI_MC_FLOWCTRL 0x4004
+#define HDMI_MC_PHYRSTZ 0x4005
+#define HDMI_MC_LOCKONCLOCK 0x4006
+#define HDMI_MC_HEACPHY_RST 0x4007
+
+/* Color Space Converter Registers */
+#define HDMI_CSC_CFG 0x4100
+#define HDMI_CSC_SCALE 0x4101
+#define HDMI_CSC_COEF_A1_MSB 0x4102
+#define HDMI_CSC_COEF_A1_LSB 0x4103
+#define HDMI_CSC_COEF_A2_MSB 0x4104
+#define HDMI_CSC_COEF_A2_LSB 0x4105
+#define HDMI_CSC_COEF_A3_MSB 0x4106
+#define HDMI_CSC_COEF_A3_LSB 0x4107
+#define HDMI_CSC_COEF_A4_MSB 0x4108
+#define HDMI_CSC_COEF_A4_LSB 0x4109
+#define HDMI_CSC_COEF_B1_MSB 0x410A
+#define HDMI_CSC_COEF_B1_LSB 0x410B
+#define HDMI_CSC_COEF_B2_MSB 0x410C
+#define HDMI_CSC_COEF_B2_LSB 0x410D
+#define HDMI_CSC_COEF_B3_MSB 0x410E
+#define HDMI_CSC_COEF_B3_LSB 0x410F
+#define HDMI_CSC_COEF_B4_MSB 0x4110
+#define HDMI_CSC_COEF_B4_LSB 0x4111
+#define HDMI_CSC_COEF_C1_MSB 0x4112
+#define HDMI_CSC_COEF_C1_LSB 0x4113
+#define HDMI_CSC_COEF_C2_MSB 0x4114
+#define HDMI_CSC_COEF_C2_LSB 0x4115
+#define HDMI_CSC_COEF_C3_MSB 0x4116
+#define HDMI_CSC_COEF_C3_LSB 0x4117
+#define HDMI_CSC_COEF_C4_MSB 0x4118
+#define HDMI_CSC_COEF_C4_LSB 0x4119
+
+/* HDCP Encryption Engine Registers */
+#define HDMI_A_HDCPCFG0 0x5000
+#define HDMI_A_HDCPCFG1 0x5001
+#define HDMI_A_HDCPOBS0 0x5002
+#define HDMI_A_HDCPOBS1 0x5003
+#define HDMI_A_HDCPOBS2 0x5004
+#define HDMI_A_HDCPOBS3 0x5005
+#define HDMI_A_APIINTCLR 0x5006
+#define HDMI_A_APIINTSTAT 0x5007
+#define HDMI_A_APIINTMSK 0x5008
+#define HDMI_A_VIDPOLCFG 0x5009
+#define HDMI_A_OESSWCFG 0x500A
+#define HDMI_A_TIMER1SETUP0 0x500B
+#define HDMI_A_TIMER1SETUP1 0x500C
+#define HDMI_A_TIMER2SETUP0 0x500D
+#define HDMI_A_TIMER2SETUP1 0x500E
+#define HDMI_A_100MSCFG 0x500F
+#define HDMI_A_2SCFG0 0x5010
+#define HDMI_A_2SCFG1 0x5011
+#define HDMI_A_5SCFG0 0x5012
+#define HDMI_A_5SCFG1 0x5013
+#define HDMI_A_SRMVERLSB 0x5014
+#define HDMI_A_SRMVERMSB 0x5015
+#define HDMI_A_SRMCTRL 0x5016
+#define HDMI_A_SFRSETUP 0x5017
+#define HDMI_A_I2CHSETUP 0x5018
+#define HDMI_A_INTSETUP 0x5019
+#define HDMI_A_PRESETUP 0x501A
+#define HDMI_A_SRM_BASE 0x5020
+
+/* CEC Engine Registers */
+#define HDMI_CEC_CTRL 0x7D00
+#define HDMI_CEC_STAT 0x7D01
+#define HDMI_CEC_MASK 0x7D02
+#define HDMI_CEC_POLARITY 0x7D03
+#define HDMI_CEC_INT 0x7D04
+#define HDMI_CEC_ADDR_L 0x7D05
+#define HDMI_CEC_ADDR_H 0x7D06
+#define HDMI_CEC_TX_CNT 0x7D07
+#define HDMI_CEC_RX_CNT 0x7D08
+#define HDMI_CEC_TX_DATA0 0x7D10
+#define HDMI_CEC_TX_DATA1 0x7D11
+#define HDMI_CEC_TX_DATA2 0x7D12
+#define HDMI_CEC_TX_DATA3 0x7D13
+#define HDMI_CEC_TX_DATA4 0x7D14
+#define HDMI_CEC_TX_DATA5 0x7D15
+#define HDMI_CEC_TX_DATA6 0x7D16
+#define HDMI_CEC_TX_DATA7 0x7D17
+#define HDMI_CEC_TX_DATA8 0x7D18
+#define HDMI_CEC_TX_DATA9 0x7D19
+#define HDMI_CEC_TX_DATA10 0x7D1a
+#define HDMI_CEC_TX_DATA11 0x7D1b
+#define HDMI_CEC_TX_DATA12 0x7D1c
+#define HDMI_CEC_TX_DATA13 0x7D1d
+#define HDMI_CEC_TX_DATA14 0x7D1e
+#define HDMI_CEC_TX_DATA15 0x7D1f
+#define HDMI_CEC_RX_DATA0 0x7D20
+#define HDMI_CEC_RX_DATA1 0x7D21
+#define HDMI_CEC_RX_DATA2 0x7D22
+#define HDMI_CEC_RX_DATA3 0x7D23
+#define HDMI_CEC_RX_DATA4 0x7D24
+#define HDMI_CEC_RX_DATA5 0x7D25
+#define HDMI_CEC_RX_DATA6 0x7D26
+#define HDMI_CEC_RX_DATA7 0x7D27
+#define HDMI_CEC_RX_DATA8 0x7D28
+#define HDMI_CEC_RX_DATA9 0x7D29
+#define HDMI_CEC_RX_DATA10 0x7D2a
+#define HDMI_CEC_RX_DATA11 0x7D2b
+#define HDMI_CEC_RX_DATA12 0x7D2c
+#define HDMI_CEC_RX_DATA13 0x7D2d
+#define HDMI_CEC_RX_DATA14 0x7D2e
+#define HDMI_CEC_RX_DATA15 0x7D2f
+#define HDMI_CEC_LOCK 0x7D30
+#define HDMI_CEC_WKUPCTRL 0x7D31
+
+/* I2C Master Registers (E-DDC) */
+#define HDMI_I2CM_SLAVE 0x7E00
+#define HDMI_I2CMESS 0x7E01
+#define HDMI_I2CM_DATAO 0x7E02
+#define HDMI_I2CM_DATAI 0x7E03
+#define HDMI_I2CM_OPERATION 0x7E04
+#define HDMI_I2CM_INT 0x7E05
+#define HDMI_I2CM_CTLINT 0x7E06
+#define HDMI_I2CM_DIV 0x7E07
+#define HDMI_I2CM_SEGADDR 0x7E08
+#define HDMI_I2CM_SOFTRSTZ 0x7E09
+#define HDMI_I2CM_SEGPTR 0x7E0A
+#define HDMI_I2CM_SS_SCL_HCNT_1_ADDR 0x7E0B
+#define HDMI_I2CM_SS_SCL_HCNT_0_ADDR 0x7E0C
+#define HDMI_I2CM_SS_SCL_LCNT_1_ADDR 0x7E0D
+#define HDMI_I2CM_SS_SCL_LCNT_0_ADDR 0x7E0E
+#define HDMI_I2CM_FS_SCL_HCNT_1_ADDR 0x7E0F
+#define HDMI_I2CM_FS_SCL_HCNT_0_ADDR 0x7E10
+#define HDMI_I2CM_FS_SCL_LCNT_1_ADDR 0x7E11
+#define HDMI_I2CM_FS_SCL_LCNT_0_ADDR 0x7E12
+
+enum {
+/* IH_FC_INT2 field values */
+ HDMI_IH_FC_INT2_OVERFLOW_MASK = 0x03,
+ HDMI_IH_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_IH_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_FC_STAT2 field values */
+ HDMI_IH_FC_STAT2_OVERFLOW_MASK = 0x03,
+ HDMI_IH_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_IH_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_PHY_STAT0 field values */
+ HDMI_IH_PHY_STAT0_RX_SENSE3 = 0x20,
+ HDMI_IH_PHY_STAT0_RX_SENSE2 = 0x10,
+ HDMI_IH_PHY_STAT0_RX_SENSE1 = 0x8,
+ HDMI_IH_PHY_STAT0_RX_SENSE0 = 0x4,
+ HDMI_IH_PHY_STAT0_TX_PHY_LOCK = 0x2,
+ HDMI_IH_PHY_STAT0_HPD = 0x1,
+
+/* IH_MUTE_I2CMPHY_STAT0 field values */
+ HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYDONE = 0x2,
+ HDMI_IH_MUTE_I2CMPHY_STAT0_I2CMPHYERROR = 0x1,
+
+/* IH_AHBDMAAUD_STAT0 field values */
+ HDMI_IH_AHBDMAAUD_STAT0_ERROR = 0x20,
+ HDMI_IH_AHBDMAAUD_STAT0_LOST = 0x10,
+ HDMI_IH_AHBDMAAUD_STAT0_RETRY = 0x08,
+ HDMI_IH_AHBDMAAUD_STAT0_DONE = 0x04,
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+ HDMI_IH_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE_FC_STAT2 field values */
+ HDMI_IH_MUTE_FC_STAT2_OVERFLOW_MASK = 0x03,
+ HDMI_IH_MUTE_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_IH_MUTE_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* IH_MUTE_AHBDMAAUD_STAT0 field values */
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_ERROR = 0x20,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_LOST = 0x10,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_RETRY = 0x08,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_DONE = 0x04,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFFULL = 0x02,
+ HDMI_IH_MUTE_AHBDMAAUD_STAT0_BUFFEMPTY = 0x01,
+
+/* IH_MUTE field values */
+ HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT = 0x2,
+ HDMI_IH_MUTE_MUTE_ALL_INTERRUPT = 0x1,
+
+/* TX_INVID0 field values */
+ HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_MASK = 0x80,
+ HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_ENABLE = 0x80,
+ HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE = 0x00,
+ HDMI_TX_INVID0_VIDEO_MAPPING_MASK = 0x1F,
+ HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET = 0,
+
+/* TX_INSTUFFING field values */
+ HDMI_TX_INSTUFFING_BDBDATA_STUFFING_MASK = 0x4,
+ HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE = 0x4,
+ HDMI_TX_INSTUFFING_BDBDATA_STUFFING_DISABLE = 0x0,
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_MASK = 0x2,
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE = 0x2,
+ HDMI_TX_INSTUFFING_RCRDATA_STUFFING_DISABLE = 0x0,
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_MASK = 0x1,
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE = 0x1,
+ HDMI_TX_INSTUFFING_GYDATA_STUFFING_DISABLE = 0x0,
+
+/* VP_PR_CD field values */
+ HDMI_VP_PR_CD_COLOR_DEPTH_MASK = 0xF0,
+ HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET = 4,
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK = 0x0F,
+ HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET = 0,
+
+/* VP_STUFF field values */
+ HDMI_VP_STUFF_IDEFAULT_PHASE_MASK = 0x20,
+ HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET = 5,
+ HDMI_VP_STUFF_IFIX_PP_TO_LAST_MASK = 0x10,
+ HDMI_VP_STUFF_IFIX_PP_TO_LAST_OFFSET = 4,
+ HDMI_VP_STUFF_ICX_GOTO_P0_ST_MASK = 0x8,
+ HDMI_VP_STUFF_ICX_GOTO_P0_ST_OFFSET = 3,
+ HDMI_VP_STUFF_YCC422_STUFFING_MASK = 0x4,
+ HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE = 0x4,
+ HDMI_VP_STUFF_YCC422_STUFFING_DIRECT_MODE = 0x0,
+ HDMI_VP_STUFF_PP_STUFFING_MASK = 0x2,
+ HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE = 0x2,
+ HDMI_VP_STUFF_PP_STUFFING_DIRECT_MODE = 0x0,
+ HDMI_VP_STUFF_PR_STUFFING_MASK = 0x1,
+ HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE = 0x1,
+ HDMI_VP_STUFF_PR_STUFFING_DIRECT_MODE = 0x0,
+
+/* VP_CONF field values */
+ HDMI_VP_CONF_BYPASS_EN_MASK = 0x40,
+ HDMI_VP_CONF_BYPASS_EN_ENABLE = 0x40,
+ HDMI_VP_CONF_BYPASS_EN_DISABLE = 0x00,
+ HDMI_VP_CONF_PP_EN_ENMASK = 0x20,
+ HDMI_VP_CONF_PP_EN_ENABLE = 0x20,
+ HDMI_VP_CONF_PP_EN_DISABLE = 0x00,
+ HDMI_VP_CONF_PR_EN_MASK = 0x10,
+ HDMI_VP_CONF_PR_EN_ENABLE = 0x10,
+ HDMI_VP_CONF_PR_EN_DISABLE = 0x00,
+ HDMI_VP_CONF_YCC422_EN_MASK = 0x8,
+ HDMI_VP_CONF_YCC422_EN_ENABLE = 0x8,
+ HDMI_VP_CONF_YCC422_EN_DISABLE = 0x0,
+ HDMI_VP_CONF_BYPASS_SELECT_MASK = 0x4,
+ HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER = 0x4,
+ HDMI_VP_CONF_BYPASS_SELECT_PIX_REPEATER = 0x0,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_MASK = 0x3,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS = 0x3,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_YCC422 = 0x1,
+ HDMI_VP_CONF_OUTPUT_SELECTOR_PP = 0x0,
+
+/* VP_REMAP field values */
+ HDMI_VP_REMAP_MASK = 0x3,
+ HDMI_VP_REMAP_YCC422_24bit = 0x2,
+ HDMI_VP_REMAP_YCC422_20bit = 0x1,
+ HDMI_VP_REMAP_YCC422_16bit = 0x0,
+
+/* FC_INVIDCONF field values */
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_MASK = 0x80,
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_ACTIVE = 0x80,
+ HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE = 0x00,
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_MASK = 0x40,
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH = 0x40,
+ HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_MASK = 0x20,
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH = 0x20,
+ HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW = 0x00,
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_MASK = 0x10,
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH = 0x10,
+ HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW = 0x00,
+ HDMI_FC_INVIDCONF_DVI_MODEZ_MASK = 0x8,
+ HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE = 0x8,
+ HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE = 0x0,
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_MASK = 0x2,
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_HIGH = 0x2,
+ HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW = 0x0,
+ HDMI_FC_INVIDCONF_IN_I_P_MASK = 0x1,
+ HDMI_FC_INVIDCONF_IN_I_P_INTERLACED = 0x1,
+ HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE = 0x0,
+
+/* FC_AUDICONF0 field values */
+ HDMI_FC_AUDICONF0_CC_OFFSET = 4,
+ HDMI_FC_AUDICONF0_CC_MASK = 0x70,
+ HDMI_FC_AUDICONF0_CT_OFFSET = 0,
+ HDMI_FC_AUDICONF0_CT_MASK = 0xF,
+
+/* FC_AUDICONF1 field values */
+ HDMI_FC_AUDICONF1_SS_OFFSET = 3,
+ HDMI_FC_AUDICONF1_SS_MASK = 0x18,
+ HDMI_FC_AUDICONF1_SF_OFFSET = 0,
+ HDMI_FC_AUDICONF1_SF_MASK = 0x7,
+
+/* FC_AUDICONF3 field values */
+ HDMI_FC_AUDICONF3_LFEPBL_OFFSET = 5,
+ HDMI_FC_AUDICONF3_LFEPBL_MASK = 0x60,
+ HDMI_FC_AUDICONF3_DM_INH_OFFSET = 4,
+ HDMI_FC_AUDICONF3_DM_INH_MASK = 0x10,
+ HDMI_FC_AUDICONF3_LSV_OFFSET = 0,
+ HDMI_FC_AUDICONF3_LSV_MASK = 0xF,
+
+/* FC_AUDSCHNLS0 field values */
+ HDMI_FC_AUDSCHNLS0_CGMSA_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS0_CGMSA_MASK = 0x30,
+ HDMI_FC_AUDSCHNLS0_COPYRIGHT_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS0_COPYRIGHT_MASK = 0x01,
+
+/* FC_AUDSCHNLS3-6 field values */
+ HDMI_FC_AUDSCHNLS3_OIEC_CH0_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS3_OIEC_CH0_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS3_OIEC_CH1_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS3_OIEC_CH1_MASK = 0xf0,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH2_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH2_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH3_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS4_OIEC_CH3_MASK = 0xf0,
+
+ HDMI_FC_AUDSCHNLS5_OIEC_CH0_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS5_OIEC_CH0_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS5_OIEC_CH1_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS5_OIEC_CH1_MASK = 0xf0,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH2_OFFSET = 0,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH2_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH3_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS6_OIEC_CH3_MASK = 0xf0,
+
+/* HDMI_FC_AUDSCHNLS7 field values */
+ HDMI_FC_AUDSCHNLS7_ACCURACY_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS7_ACCURACY_MASK = 0x30,
+
+/* HDMI_FC_AUDSCHNLS8 field values */
+ HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_MASK = 0xf0,
+ HDMI_FC_AUDSCHNLS8_ORIGSAMPFREQ_OFFSET = 4,
+ HDMI_FC_AUDSCHNLS8_WORDLEGNTH_MASK = 0x0f,
+ HDMI_FC_AUDSCHNLS8_WORDLEGNTH_OFFSET = 0,
+
+/* FC_AUDSCONF field values */
+ HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_MASK = 0xF0,
+ HDMI_FC_AUDSCONF_AUD_PACKET_SAMPFIT_OFFSET = 4,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_MASK = 0x1,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_OFFSET = 0,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT1 = 0x1,
+ HDMI_FC_AUDSCONF_AUD_PACKET_LAYOUT_LAYOUT0 = 0x0,
+
+/* FC_STAT2 field values */
+ HDMI_FC_STAT2_OVERFLOW_MASK = 0x03,
+ HDMI_FC_STAT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_FC_STAT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_INT2 field values */
+ HDMI_FC_INT2_OVERFLOW_MASK = 0x03,
+ HDMI_FC_INT2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_FC_INT2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_MASK2 field values */
+ HDMI_FC_MASK2_OVERFLOW_MASK = 0x03,
+ HDMI_FC_MASK2_LOW_PRIORITY_OVERFLOW = 0x02,
+ HDMI_FC_MASK2_HIGH_PRIORITY_OVERFLOW = 0x01,
+
+/* FC_PRCONF field values */
+ HDMI_FC_PRCONF_INCOMING_PR_FACTOR_MASK = 0xF0,
+ HDMI_FC_PRCONF_INCOMING_PR_FACTOR_OFFSET = 4,
+ HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_MASK = 0x0F,
+ HDMI_FC_PRCONF_OUTPUT_PR_FACTOR_OFFSET = 0,
+
+/* FC_AVICONF0-FC_AVICONF3 field values */
+ HDMI_FC_AVICONF0_PIX_FMT_MASK = 0x03,
+ HDMI_FC_AVICONF0_PIX_FMT_RGB = 0x00,
+ HDMI_FC_AVICONF0_PIX_FMT_YCBCR422 = 0x01,
+ HDMI_FC_AVICONF0_PIX_FMT_YCBCR444 = 0x02,
+ HDMI_FC_AVICONF0_ACTIVE_FMT_MASK = 0x40,
+ HDMI_FC_AVICONF0_ACTIVE_FMT_INFO_PRESENT = 0x40,
+ HDMI_FC_AVICONF0_ACTIVE_FMT_NO_INFO = 0x00,
+ HDMI_FC_AVICONF0_BAR_DATA_MASK = 0x0C,
+ HDMI_FC_AVICONF0_BAR_DATA_NO_DATA = 0x00,
+ HDMI_FC_AVICONF0_BAR_DATA_VERT_BAR = 0x04,
+ HDMI_FC_AVICONF0_BAR_DATA_HORIZ_BAR = 0x08,
+ HDMI_FC_AVICONF0_BAR_DATA_VERT_HORIZ_BAR = 0x0C,
+ HDMI_FC_AVICONF0_SCAN_INFO_MASK = 0x30,
+ HDMI_FC_AVICONF0_SCAN_INFO_OVERSCAN = 0x10,
+ HDMI_FC_AVICONF0_SCAN_INFO_UNDERSCAN = 0x20,
+ HDMI_FC_AVICONF0_SCAN_INFO_NODATA = 0x00,
+
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_MASK = 0x0F,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_USE_CODED = 0x08,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_4_3 = 0x09,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_16_9 = 0x0A,
+ HDMI_FC_AVICONF1_ACTIVE_ASPECT_RATIO_14_9 = 0x0B,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_MASK = 0x30,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_NO_DATA = 0x00,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_4_3 = 0x10,
+ HDMI_FC_AVICONF1_CODED_ASPECT_RATIO_16_9 = 0x20,
+ HDMI_FC_AVICONF1_COLORIMETRY_MASK = 0xC0,
+ HDMI_FC_AVICONF1_COLORIMETRY_NO_DATA = 0x00,
+ HDMI_FC_AVICONF1_COLORIMETRY_SMPTE = 0x40,
+ HDMI_FC_AVICONF1_COLORIMETRY_ITUR = 0x80,
+ HDMI_FC_AVICONF1_COLORIMETRY_EXTENDED_INFO = 0xC0,
+
+ HDMI_FC_AVICONF2_SCALING_MASK = 0x03,
+ HDMI_FC_AVICONF2_SCALING_NONE = 0x00,
+ HDMI_FC_AVICONF2_SCALING_HORIZ = 0x01,
+ HDMI_FC_AVICONF2_SCALING_VERT = 0x02,
+ HDMI_FC_AVICONF2_SCALING_HORIZ_VERT = 0x03,
+ HDMI_FC_AVICONF2_RGB_QUANT_MASK = 0x0C,
+ HDMI_FC_AVICONF2_RGB_QUANT_DEFAULT = 0x00,
+ HDMI_FC_AVICONF2_RGB_QUANT_LIMITED_RANGE = 0x04,
+ HDMI_FC_AVICONF2_RGB_QUANT_FULL_RANGE = 0x08,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_MASK = 0x70,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC601 = 0x00,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_XVYCC709 = 0x10,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_SYCC601 = 0x20,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_YCC601 = 0x30,
+ HDMI_FC_AVICONF2_EXT_COLORIMETRY_ADOBE_RGB = 0x40,
+ HDMI_FC_AVICONF2_IT_CONTENT_MASK = 0x80,
+ HDMI_FC_AVICONF2_IT_CONTENT_NO_DATA = 0x00,
+ HDMI_FC_AVICONF2_IT_CONTENT_VALID = 0x80,
+
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_MASK = 0x03,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GRAPHICS = 0x00,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_PHOTO = 0x01,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_CINEMA = 0x02,
+ HDMI_FC_AVICONF3_IT_CONTENT_TYPE_GAME = 0x03,
+ HDMI_FC_AVICONF3_QUANT_RANGE_MASK = 0x0C,
+ HDMI_FC_AVICONF3_QUANT_RANGE_LIMITED = 0x00,
+ HDMI_FC_AVICONF3_QUANT_RANGE_FULL = 0x04,
+
+/* FC_DBGFORCE field values */
+ HDMI_FC_DBGFORCE_FORCEAUDIO = 0x10,
+ HDMI_FC_DBGFORCE_FORCEVIDEO = 0x1,
+
+/* PHY_CONF0 field values */
+ HDMI_PHY_CONF0_PDZ_MASK = 0x80,
+ HDMI_PHY_CONF0_PDZ_OFFSET = 7,
+ HDMI_PHY_CONF0_ENTMDS_MASK = 0x40,
+ HDMI_PHY_CONF0_ENTMDS_OFFSET = 6,
+ HDMI_PHY_CONF0_SPARECTRL = 0x20,
+ HDMI_PHY_CONF0_GEN2_PDDQ_MASK = 0x10,
+ HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET = 4,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_MASK = 0x8,
+ HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET = 3,
+ HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_MASK = 0x4,
+ HDMI_PHY_CONF0_GEN2_ENHPDRXSENSE_OFFSET = 2,
+ HDMI_PHY_CONF0_SELDATAENPOL_MASK = 0x2,
+ HDMI_PHY_CONF0_SELDATAENPOL_OFFSET = 1,
+ HDMI_PHY_CONF0_SELDIPIF_MASK = 0x1,
+ HDMI_PHY_CONF0_SELDIPIF_OFFSET = 0,
+
+/* PHY_TST0 field values */
+ HDMI_PHY_TST0_TSTCLR_MASK = 0x20,
+ HDMI_PHY_TST0_TSTCLR_OFFSET = 5,
+ HDMI_PHY_TST0_TSTEN_MASK = 0x10,
+ HDMI_PHY_TST0_TSTEN_OFFSET = 4,
+ HDMI_PHY_TST0_TSTCLK_MASK = 0x1,
+ HDMI_PHY_TST0_TSTCLK_OFFSET = 0,
+
+/* PHY_STAT0 field values */
+ HDMI_PHY_RX_SENSE3 = 0x80,
+ HDMI_PHY_RX_SENSE2 = 0x40,
+ HDMI_PHY_RX_SENSE1 = 0x20,
+ HDMI_PHY_RX_SENSE0 = 0x10,
+ HDMI_PHY_HPD = 0x02,
+ HDMI_PHY_TX_PHY_LOCK = 0x01,
+
+/* PHY_I2CM_SLAVE_ADDR field values */
+ HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2 = 0x69,
+ HDMI_PHY_I2CM_SLAVE_ADDR_HEAC_PHY = 0x49,
+
+/* PHY_I2CM_OPERATION_ADDR field values */
+ HDMI_PHY_I2CM_OPERATION_ADDR_WRITE = 0x10,
+ HDMI_PHY_I2CM_OPERATION_ADDR_READ = 0x1,
+
+/* HDMI_PHY_I2CM_INT_ADDR */
+ HDMI_PHY_I2CM_INT_ADDR_DONE_POL = 0x08,
+ HDMI_PHY_I2CM_INT_ADDR_DONE_MASK = 0x04,
+
+/* HDMI_PHY_I2CM_CTLINT_ADDR */
+ HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL = 0x80,
+ HDMI_PHY_I2CM_CTLINT_ADDR_NAC_MASK = 0x40,
+ HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL = 0x08,
+ HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_MASK = 0x04,
+
+/* AUD_CTS3 field values */
+ HDMI_AUD_CTS3_N_SHIFT_OFFSET = 5,
+ HDMI_AUD_CTS3_N_SHIFT_MASK = 0xe0,
+ HDMI_AUD_CTS3_N_SHIFT_1 = 0,
+ HDMI_AUD_CTS3_N_SHIFT_16 = 0x20,
+ HDMI_AUD_CTS3_N_SHIFT_32 = 0x40,
+ HDMI_AUD_CTS3_N_SHIFT_64 = 0x60,
+ HDMI_AUD_CTS3_N_SHIFT_128 = 0x80,
+ HDMI_AUD_CTS3_N_SHIFT_256 = 0xa0,
+ /* note that the CTS3 MANUAL bit has been removed
+ from our part. Can't set it, will read as 0. */
+ HDMI_AUD_CTS3_CTS_MANUAL = 0x10,
+ HDMI_AUD_CTS3_AUDCTS19_16_MASK = 0x0f,
+
+/* AHB_DMA_CONF0 field values */
+ HDMI_AHB_DMA_CONF0_SW_FIFO_RST_OFFSET = 7,
+ HDMI_AHB_DMA_CONF0_SW_FIFO_RST_MASK = 0x80,
+ HDMI_AHB_DMA_CONF0_HBR = 0x10,
+ HDMI_AHB_DMA_CONF0_EN_HLOCK_OFFSET = 3,
+ HDMI_AHB_DMA_CONF0_EN_HLOCK_MASK = 0x08,
+ HDMI_AHB_DMA_CONF0_INCR_TYPE_OFFSET = 1,
+ HDMI_AHB_DMA_CONF0_INCR_TYPE_MASK = 0x06,
+ HDMI_AHB_DMA_CONF0_INCR4 = 0x0,
+ HDMI_AHB_DMA_CONF0_INCR8 = 0x2,
+ HDMI_AHB_DMA_CONF0_INCR16 = 0x4,
+ HDMI_AHB_DMA_CONF0_BURST_MODE = 0x1,
+
+/* HDMI_AHB_DMA_START field values */
+ HDMI_AHB_DMA_START_START_OFFSET = 0,
+ HDMI_AHB_DMA_START_START_MASK = 0x01,
+
+/* HDMI_AHB_DMA_STOP field values */
+ HDMI_AHB_DMA_STOP_STOP_OFFSET = 0,
+ HDMI_AHB_DMA_STOP_STOP_MASK = 0x01,
+
+/* AHB_DMA_STAT, AHB_DMA_INT, AHB_DMA_MASK, AHB_DMA_POL field values */
+ HDMI_AHB_DMA_DONE = 0x80,
+ HDMI_AHB_DMA_RETRY_SPLIT = 0x40,
+ HDMI_AHB_DMA_LOSTOWNERSHIP = 0x20,
+ HDMI_AHB_DMA_ERROR = 0x10,
+ HDMI_AHB_DMA_FIFO_THREMPTY = 0x04,
+ HDMI_AHB_DMA_FIFO_FULL = 0x02,
+ HDMI_AHB_DMA_FIFO_EMPTY = 0x01,
+
+/* AHB_DMA_BUFFSTAT, AHB_DMA_BUFFINT,AHB_DMA_BUFFMASK,AHB_DMA_BUFFPOL values */
+ HDMI_AHB_DMA_BUFFSTAT_FULL = 0x02,
+ HDMI_AHB_DMA_BUFFSTAT_EMPTY = 0x01,
+
+/* MC_CLKDIS field values */
+ HDMI_MC_CLKDIS_HDCPCLK_DISABLE = 0x40,
+ HDMI_MC_CLKDIS_CECCLK_DISABLE = 0x20,
+ HDMI_MC_CLKDIS_CSCCLK_DISABLE = 0x10,
+ HDMI_MC_CLKDIS_AUDCLK_DISABLE = 0x8,
+ HDMI_MC_CLKDIS_PREPCLK_DISABLE = 0x4,
+ HDMI_MC_CLKDIS_TMDSCLK_DISABLE = 0x2,
+ HDMI_MC_CLKDIS_PIXELCLK_DISABLE = 0x1,
+
+/* MC_SWRSTZ field values */
+ HDMI_MC_SWRSTZ_TMDSSWRST_REQ = 0x02,
+
+/* MC_FLOWCTRL field values */
+ HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_MASK = 0x1,
+ HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH = 0x1,
+ HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS = 0x0,
+
+/* MC_PHYRSTZ field values */
+ HDMI_MC_PHYRSTZ_ASSERT = 0x0,
+ HDMI_MC_PHYRSTZ_DEASSERT = 0x1,
+
+/* MC_HEACPHY_RST field values */
+ HDMI_MC_HEACPHY_RST_ASSERT = 0x1,
+ HDMI_MC_HEACPHY_RST_DEASSERT = 0x0,
+
+/* CSC_CFG field values */
+ HDMI_CSC_CFG_INTMODE_MASK = 0x30,
+ HDMI_CSC_CFG_INTMODE_OFFSET = 4,
+ HDMI_CSC_CFG_INTMODE_DISABLE = 0x00,
+ HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1 = 0x10,
+ HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA2 = 0x20,
+ HDMI_CSC_CFG_DECMODE_MASK = 0x3,
+ HDMI_CSC_CFG_DECMODE_OFFSET = 0,
+ HDMI_CSC_CFG_DECMODE_DISABLE = 0x0,
+ HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA1 = 0x1,
+ HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA2 = 0x2,
+ HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3 = 0x3,
+
+/* CSC_SCALE field values */
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK = 0xF0,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP = 0x00,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP = 0x50,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP = 0x60,
+ HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP = 0x70,
+ HDMI_CSC_SCALE_CSCSCALE_MASK = 0x03,
+
+/* A_HDCPCFG0 field values */
+ HDMI_A_HDCPCFG0_ELVENA_MASK = 0x80,
+ HDMI_A_HDCPCFG0_ELVENA_ENABLE = 0x80,
+ HDMI_A_HDCPCFG0_ELVENA_DISABLE = 0x00,
+ HDMI_A_HDCPCFG0_I2CFASTMODE_MASK = 0x40,
+ HDMI_A_HDCPCFG0_I2CFASTMODE_ENABLE = 0x40,
+ HDMI_A_HDCPCFG0_I2CFASTMODE_DISABLE = 0x00,
+ HDMI_A_HDCPCFG0_BYPENCRYPTION_MASK = 0x20,
+ HDMI_A_HDCPCFG0_BYPENCRYPTION_ENABLE = 0x20,
+ HDMI_A_HDCPCFG0_BYPENCRYPTION_DISABLE = 0x00,
+ HDMI_A_HDCPCFG0_SYNCRICHECK_MASK = 0x10,
+ HDMI_A_HDCPCFG0_SYNCRICHECK_ENABLE = 0x10,
+ HDMI_A_HDCPCFG0_SYNCRICHECK_DISABLE = 0x00,
+ HDMI_A_HDCPCFG0_AVMUTE_MASK = 0x8,
+ HDMI_A_HDCPCFG0_AVMUTE_ENABLE = 0x8,
+ HDMI_A_HDCPCFG0_AVMUTE_DISABLE = 0x0,
+ HDMI_A_HDCPCFG0_RXDETECT_MASK = 0x4,
+ HDMI_A_HDCPCFG0_RXDETECT_ENABLE = 0x4,
+ HDMI_A_HDCPCFG0_RXDETECT_DISABLE = 0x0,
+ HDMI_A_HDCPCFG0_EN11FEATURE_MASK = 0x2,
+ HDMI_A_HDCPCFG0_EN11FEATURE_ENABLE = 0x2,
+ HDMI_A_HDCPCFG0_EN11FEATURE_DISABLE = 0x0,
+ HDMI_A_HDCPCFG0_HDMIDVI_MASK = 0x1,
+ HDMI_A_HDCPCFG0_HDMIDVI_HDMI = 0x1,
+ HDMI_A_HDCPCFG0_HDMIDVI_DVI = 0x0,
+
+/* A_HDCPCFG1 field values */
+ HDMI_A_HDCPCFG1_DISSHA1CHECK_MASK = 0x8,
+ HDMI_A_HDCPCFG1_DISSHA1CHECK_DISABLE = 0x8,
+ HDMI_A_HDCPCFG1_DISSHA1CHECK_ENABLE = 0x0,
+ HDMI_A_HDCPCFG1_PH2UPSHFTENC_MASK = 0x4,
+ HDMI_A_HDCPCFG1_PH2UPSHFTENC_ENABLE = 0x4,
+ HDMI_A_HDCPCFG1_PH2UPSHFTENC_DISABLE = 0x0,
+ HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_MASK = 0x2,
+ HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_DISABLE = 0x2,
+ HDMI_A_HDCPCFG1_ENCRYPTIONDISABLE_ENABLE = 0x0,
+ HDMI_A_HDCPCFG1_SWRESET_MASK = 0x1,
+ HDMI_A_HDCPCFG1_SWRESET_ASSERT = 0x0,
+
+/* A_VIDPOLCFG field values */
+ HDMI_A_VIDPOLCFG_UNENCRYPTCONF_MASK = 0x60,
+ HDMI_A_VIDPOLCFG_UNENCRYPTCONF_OFFSET = 5,
+ HDMI_A_VIDPOLCFG_DATAENPOL_MASK = 0x10,
+ HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_HIGH = 0x10,
+ HDMI_A_VIDPOLCFG_DATAENPOL_ACTIVE_LOW = 0x0,
+ HDMI_A_VIDPOLCFG_VSYNCPOL_MASK = 0x8,
+ HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_HIGH = 0x8,
+ HDMI_A_VIDPOLCFG_VSYNCPOL_ACTIVE_LOW = 0x0,
+ HDMI_A_VIDPOLCFG_HSYNCPOL_MASK = 0x2,
+ HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_HIGH = 0x2,
+ HDMI_A_VIDPOLCFG_HSYNCPOL_ACTIVE_LOW = 0x0,
+};
+#endif /* __IMX_HDMI_H__ */
diff --git a/drivers/video/imx-ipu-v3/imx-ipu-v3.h b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
new file mode 100644
index 0000000000..7c48a7ce38
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-ipu-v3.h
@@ -0,0 +1,344 @@
+/*
+ * Copyright 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU Lesser General
+ * Public License. You may obtain a copy of the GNU Lesser General
+ * Public License Version 2.1 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/lgpl-license.html
+ * http://www.gnu.org/copyleft/lgpl.html
+ */
+
+#ifndef __DRM_IPU_H__
+#define __DRM_IPU_H__
+
+#include <io.h>
+#include <fb.h>
+#include <video/fourcc.h>
+
+struct ipu_soc;
+
+enum ipuv3_type {
+ IPUV3EX,
+ IPUV3M,
+ IPUV3H,
+};
+
+void ipuwritel(const char *unit, uint32_t value, void __iomem *reg);
+uint32_t ipureadl(void __iomem *reg);
+
+/*
+ * Bitfield of Display Interface signal polarities.
+ */
+struct ipu_di_signal_cfg {
+ unsigned datamask_en:1;
+ unsigned interlaced:1;
+ unsigned odd_field_first:1;
+ unsigned clksel_en:1;
+ unsigned clkidle_en:1;
+ unsigned data_pol:1; /* true = inverted */
+ unsigned clk_pol:1; /* true = rising edge */
+ unsigned enable_pol:1;
+ unsigned Hsync_pol:1; /* true = active high */
+ unsigned Vsync_pol:1;
+
+ u16 width;
+ u16 height;
+ u32 pixel_fmt;
+ u16 h_start_width;
+ u16 h_sync_width;
+ u16 h_end_width;
+ u16 v_start_width;
+ u16 v_sync_width;
+ u16 v_end_width;
+ u32 v_to_h_sync;
+ unsigned long pixelclock;
+#define IPU_DI_CLKMODE_SYNC (1 << 0)
+#define IPU_DI_CLKMODE_EXT (1 << 1)
+#define IPU_DI_CLKMODE_NON_FRACTIONAL (1 << 2)
+ unsigned long clkflags;
+
+ u8 hsync_pin;
+ u8 vsync_pin;
+};
+
+enum ipu_color_space {
+ IPUV3_COLORSPACE_RGB,
+ IPUV3_COLORSPACE_YUV,
+ IPUV3_COLORSPACE_UNKNOWN,
+};
+
+struct ipuv3_channel;
+
+enum ipu_channel_irq {
+ IPU_IRQ_EOF = 0,
+ IPU_IRQ_NFACK = 64,
+ IPU_IRQ_NFB4EOF = 128,
+ IPU_IRQ_EOS = 192,
+};
+
+int ipu_idmac_channel_irq(struct ipu_soc *ipu, struct ipuv3_channel *channel,
+ enum ipu_channel_irq irq);
+
+#define IPU_IRQ_DP_SF_START (448 + 2)
+#define IPU_IRQ_DP_SF_END (448 + 3)
+#define IPU_IRQ_BG_SF_END IPU_IRQ_DP_SF_END,
+#define IPU_IRQ_DC_FC_0 (448 + 8)
+#define IPU_IRQ_DC_FC_1 (448 + 9)
+#define IPU_IRQ_DC_FC_2 (448 + 10)
+#define IPU_IRQ_DC_FC_3 (448 + 11)
+#define IPU_IRQ_DC_FC_4 (448 + 12)
+#define IPU_IRQ_DC_FC_6 (448 + 13)
+#define IPU_IRQ_VSYNC_PRE_0 (448 + 14)
+#define IPU_IRQ_VSYNC_PRE_1 (448 + 15)
+
+/*
+ * IPU Image DMA Controller (idmac) functions
+ */
+struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned channel);
+void ipu_idmac_put(struct ipuv3_channel *);
+
+int ipu_idmac_enable_channel(struct ipuv3_channel *channel);
+int ipu_idmac_disable_channel(struct ipuv3_channel *channel);
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms);
+
+void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
+ bool doublebuffer);
+void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num);
+
+/*
+ * IPU Display Controller (dc) functions
+ */
+struct ipu_dc;
+struct ipu_di;
+struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel);
+void ipu_dc_put(struct ipu_dc *dc);
+int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
+ u32 pixel_fmt, u32 width);
+void ipu_dc_enable_channel(struct ipu_dc *dc);
+void ipu_dc_disable_channel(struct ipu_dc *dc);
+
+/*
+ * IPU Display Interface (di) functions
+ */
+struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp);
+void ipu_di_put(struct ipu_di *);
+int ipu_di_disable(struct ipu_di *);
+int ipu_di_enable(struct ipu_di *);
+int ipu_di_get_num(struct ipu_di *);
+int ipu_di_init_sync_panel(struct ipu_di *, struct ipu_di_signal_cfg *sig);
+
+/*
+ * IPU Display Multi FIFO Controller (dmfc) functions
+ */
+struct dmfc_channel;
+int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc);
+void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc);
+int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
+ unsigned long bandwidth_mbs, int burstsize);
+void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc);
+int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width);
+struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipuv3_channel);
+void ipu_dmfc_put(struct dmfc_channel *dmfc);
+
+/*
+ * IPU Display Processor (dp) functions
+ */
+#define IPU_DP_FLOW_SYNC_BG 0
+#define IPU_DP_FLOW_SYNC_FG 1
+#define IPU_DP_FLOW_ASYNC0_BG 2
+#define IPU_DP_FLOW_ASYNC0_FG 3
+#define IPU_DP_FLOW_ASYNC1_BG 4
+#define IPU_DP_FLOW_ASYNC1_FG 5
+
+struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow);
+void ipu_dp_put(struct ipu_dp *);
+int ipu_dp_enable_channel(struct ipu_dp *dp);
+void ipu_dp_disable_channel(struct ipu_dp *dp);
+int ipu_dp_setup_channel(struct ipu_dp *dp,
+ enum ipu_color_space in, enum ipu_color_space out);
+int ipu_dp_set_window_pos(struct ipu_dp *, u16 x_pos, u16 y_pos);
+int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable, u8 alpha,
+ bool bg_chan);
+
+#define IPU_CPMEM_WORD(word, ofs, size) ((((word) * 160 + (ofs)) << 8) | (size))
+
+#define IPU_FIELD_UBO IPU_CPMEM_WORD(0, 46, 22)
+#define IPU_FIELD_VBO IPU_CPMEM_WORD(0, 68, 22)
+#define IPU_FIELD_IOX IPU_CPMEM_WORD(0, 90, 4)
+#define IPU_FIELD_RDRW IPU_CPMEM_WORD(0, 94, 1)
+#define IPU_FIELD_SO IPU_CPMEM_WORD(0, 113, 1)
+#define IPU_FIELD_SLY IPU_CPMEM_WORD(1, 102, 14)
+#define IPU_FIELD_SLUV IPU_CPMEM_WORD(1, 128, 14)
+
+#define IPU_FIELD_XV IPU_CPMEM_WORD(0, 0, 10)
+#define IPU_FIELD_YV IPU_CPMEM_WORD(0, 10, 9)
+#define IPU_FIELD_XB IPU_CPMEM_WORD(0, 19, 13)
+#define IPU_FIELD_YB IPU_CPMEM_WORD(0, 32, 12)
+#define IPU_FIELD_NSB_B IPU_CPMEM_WORD(0, 44, 1)
+#define IPU_FIELD_CF IPU_CPMEM_WORD(0, 45, 1)
+#define IPU_FIELD_SX IPU_CPMEM_WORD(0, 46, 12)
+#define IPU_FIELD_SY IPU_CPMEM_WORD(0, 58, 11)
+#define IPU_FIELD_NS IPU_CPMEM_WORD(0, 69, 10)
+#define IPU_FIELD_SDX IPU_CPMEM_WORD(0, 79, 7)
+#define IPU_FIELD_SM IPU_CPMEM_WORD(0, 86, 10)
+#define IPU_FIELD_SCC IPU_CPMEM_WORD(0, 96, 1)
+#define IPU_FIELD_SCE IPU_CPMEM_WORD(0, 97, 1)
+#define IPU_FIELD_SDY IPU_CPMEM_WORD(0, 98, 7)
+#define IPU_FIELD_SDRX IPU_CPMEM_WORD(0, 105, 1)
+#define IPU_FIELD_SDRY IPU_CPMEM_WORD(0, 106, 1)
+#define IPU_FIELD_BPP IPU_CPMEM_WORD(0, 107, 3)
+#define IPU_FIELD_DEC_SEL IPU_CPMEM_WORD(0, 110, 2)
+#define IPU_FIELD_DIM IPU_CPMEM_WORD(0, 112, 1)
+#define IPU_FIELD_BNDM IPU_CPMEM_WORD(0, 114, 3)
+#define IPU_FIELD_BM IPU_CPMEM_WORD(0, 117, 2)
+#define IPU_FIELD_ROT IPU_CPMEM_WORD(0, 119, 1)
+#define IPU_FIELD_HF IPU_CPMEM_WORD(0, 120, 1)
+#define IPU_FIELD_VF IPU_CPMEM_WORD(0, 121, 1)
+#define IPU_FIELD_THE IPU_CPMEM_WORD(0, 122, 1)
+#define IPU_FIELD_CAP IPU_CPMEM_WORD(0, 123, 1)
+#define IPU_FIELD_CAE IPU_CPMEM_WORD(0, 124, 1)
+#define IPU_FIELD_FW IPU_CPMEM_WORD(0, 125, 13)
+#define IPU_FIELD_FH IPU_CPMEM_WORD(0, 138, 12)
+#define IPU_FIELD_EBA0 IPU_CPMEM_WORD(1, 0, 29)
+#define IPU_FIELD_EBA1 IPU_CPMEM_WORD(1, 29, 29)
+#define IPU_FIELD_ILO IPU_CPMEM_WORD(1, 58, 20)
+#define IPU_FIELD_NPB IPU_CPMEM_WORD(1, 78, 7)
+#define IPU_FIELD_PFS IPU_CPMEM_WORD(1, 85, 4)
+#define IPU_FIELD_ALU IPU_CPMEM_WORD(1, 89, 1)
+#define IPU_FIELD_ALBM IPU_CPMEM_WORD(1, 90, 3)
+#define IPU_FIELD_ID IPU_CPMEM_WORD(1, 93, 2)
+#define IPU_FIELD_TH IPU_CPMEM_WORD(1, 95, 7)
+#define IPU_FIELD_SL IPU_CPMEM_WORD(1, 102, 14)
+#define IPU_FIELD_WID0 IPU_CPMEM_WORD(1, 116, 3)
+#define IPU_FIELD_WID1 IPU_CPMEM_WORD(1, 119, 3)
+#define IPU_FIELD_WID2 IPU_CPMEM_WORD(1, 122, 3)
+#define IPU_FIELD_WID3 IPU_CPMEM_WORD(1, 125, 3)
+#define IPU_FIELD_OFS0 IPU_CPMEM_WORD(1, 128, 5)
+#define IPU_FIELD_OFS1 IPU_CPMEM_WORD(1, 133, 5)
+#define IPU_FIELD_OFS2 IPU_CPMEM_WORD(1, 138, 5)
+#define IPU_FIELD_OFS3 IPU_CPMEM_WORD(1, 143, 5)
+#define IPU_FIELD_SXYS IPU_CPMEM_WORD(1, 148, 1)
+#define IPU_FIELD_CRE IPU_CPMEM_WORD(1, 149, 1)
+#define IPU_FIELD_DEC_SEL2 IPU_CPMEM_WORD(1, 150, 1)
+
+struct ipu_cpmem_word {
+ u32 data[5];
+ u32 res[3];
+};
+
+struct ipu_ch_param {
+ struct ipu_cpmem_word word[2];
+};
+
+void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v);
+u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs);
+struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel);
+void ipu_ch_param_dump(struct ipu_ch_param __iomem *p);
+
+static inline void ipu_ch_param_zero(struct ipu_ch_param __iomem *p)
+{
+ int i;
+ void __iomem *base = p;
+
+ for (i = 0; i < sizeof(*p) / sizeof(u32); i++)
+ ipuwritel("chp", 0, base + i * sizeof(u32));
+}
+
+static inline void ipu_cpmem_set_buffer(struct ipu_ch_param __iomem *p,
+ int bufnum, dma_addr_t buf)
+{
+ if (bufnum)
+ ipu_ch_param_write_field(p, IPU_FIELD_EBA1, buf >> 3);
+ else
+ ipu_ch_param_write_field(p, IPU_FIELD_EBA0, buf >> 3);
+}
+
+static inline void ipu_cpmem_set_resolution(struct ipu_ch_param __iomem *p,
+ int xres, int yres)
+{
+ ipu_ch_param_write_field(p, IPU_FIELD_FW, xres - 1);
+ ipu_ch_param_write_field(p, IPU_FIELD_FH, yres - 1);
+}
+
+static inline void ipu_cpmem_set_stride(struct ipu_ch_param __iomem *p,
+ int stride)
+{
+ ipu_ch_param_write_field(p, IPU_FIELD_SLY, stride - 1);
+}
+
+void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel);
+
+struct ipu_rgb {
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+ int bits_per_pixel;
+};
+
+struct ipu_rgb *drm_fourcc_to_rgb(u32 drm_fourcc);
+
+int ipu_cpmem_set_format_passthrough(struct ipu_ch_param __iomem *p,
+ int width);
+
+int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *,
+ const struct ipu_rgb *rgb);
+
+static inline void ipu_cpmem_interlaced_scan(struct ipu_ch_param *p,
+ int stride)
+{
+ ipu_ch_param_write_field(p, IPU_FIELD_SO, 1);
+ ipu_ch_param_write_field(p, IPU_FIELD_ILO, stride / 8);
+ ipu_ch_param_write_field(p, IPU_FIELD_SLY, (stride * 2) - 1);
+};
+
+void ipu_cpmem_set_yuv_planar(struct ipu_ch_param __iomem *p, u32 pixel_format,
+ int stride, int height);
+void ipu_cpmem_set_yuv_interleaved(struct ipu_ch_param __iomem *p,
+ u32 pixel_format);
+void ipu_cpmem_set_yuv_planar_full(struct ipu_ch_param __iomem *p,
+ u32 pixel_format, int stride, int u_offset, int v_offset);
+int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 pixelformat);
+
+enum ipu_color_space ipu_drm_fourcc_to_colorspace(u32 drm_fourcc);
+enum ipu_color_space ipu_pixelformat_to_colorspace(u32 pixelformat);
+
+static inline void ipu_cpmem_set_burstsize(struct ipu_ch_param __iomem *p,
+ int burstsize)
+{
+ ipu_ch_param_write_field(p, IPU_FIELD_NPB, burstsize - 1);
+};
+
+struct ipu_client_platformdata {
+ int di;
+ int dc;
+ int dp;
+ int dmfc;
+ int dma[2];
+ struct device_node *device_node;
+};
+
+struct ipu_output;
+
+struct ipu_output_ops {
+ int (*prepare)(struct ipu_output *ipu_video_output, struct fb_videomode *mode, int di);
+ int (*enable)(struct ipu_output *ipu_video_output, struct fb_videomode *mode, int di);
+ int (*disable)(struct ipu_output *ipu_video_output);
+ int (*unprepare)(struct ipu_output *ipu_video_output);
+};
+
+struct ipu_output {
+ struct ipu_output_ops *ops;
+ struct list_head list;
+ unsigned int di_clkflags;
+ uint32_t out_pixel_fmt;
+ struct i2c_adapter *edid_i2c_adapter;
+ struct display_timings *modes;
+ char *name;
+ int ipu_mask;
+};
+
+int ipu_register_output(struct ipu_output *ouput);
+
+#endif /* __DRM_IPU_H__ */
diff --git a/drivers/video/imx-ipu-v3/imx-ldb.c b/drivers/video/imx-ipu-v3/imx-ldb.c
new file mode 100644
index 0000000000..7367fbea71
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/imx-ldb.c
@@ -0,0 +1,310 @@
+/*
+ * i.MX drm driver - parallel display implementation
+ *
+ * Copyright (C) 2012 Sascha Hauer, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#include <common.h>
+#include <fb.h>
+#include <io.h>
+#include <driver.h>
+#include <malloc.h>
+#include <errno.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/div64.h>
+#include <linux/clk.h>
+#include <mach/imx6-regs.h>
+#include <mach/imx53-regs.h>
+
+#include "imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+
+#define LDB_CH0_MODE_EN_TO_DI0 (1 << 0)
+#define LDB_CH0_MODE_EN_TO_DI1 (3 << 0)
+#define LDB_CH0_MODE_EN_MASK (3 << 0)
+#define LDB_CH1_MODE_EN_TO_DI0 (1 << 2)
+#define LDB_CH1_MODE_EN_TO_DI1 (3 << 2)
+#define LDB_CH1_MODE_EN_MASK (3 << 2)
+#define LDB_SPLIT_MODE_EN (1 << 4)
+#define LDB_DATA_WIDTH_CH0_24 (1 << 5)
+#define LDB_BIT_MAP_CH0_JEIDA (1 << 6)
+#define LDB_DATA_WIDTH_CH1_24 (1 << 7)
+#define LDB_BIT_MAP_CH1_JEIDA (1 << 8)
+#define LDB_DI0_VS_POL_ACT_LOW (1 << 9)
+#define LDB_DI1_VS_POL_ACT_LOW (1 << 10)
+#define LDB_BGREF_RMODE_INT (1 << 15)
+
+struct imx_ldb;
+
+struct imx_ldb_channel {
+ struct imx_ldb *ldb;
+ int chno;
+ int mode_valid;
+ struct display_timings *modes;
+ struct ipu_output output;
+};
+
+struct imx_ldb_data {
+ void __iomem *base;
+ int (*prepare)(struct imx_ldb_channel *imx_ldb_ch, int di);
+ unsigned ipu_mask;
+};
+
+struct imx_ldb {
+ struct device_d *dev;
+ u32 interface_pix_fmt;
+ int mode_valid;
+ struct imx_ldb_channel channel[2];
+ u32 ldb_ctrl;
+ void __iomem *base;
+ const struct imx_ldb_data *soc_data;
+};
+
+enum {
+ LVDS_BIT_MAP_SPWG,
+ LVDS_BIT_MAP_JEIDA
+};
+
+static const char * const imx_ldb_bit_mappings[] = {
+ [LVDS_BIT_MAP_SPWG] = "spwg",
+ [LVDS_BIT_MAP_JEIDA] = "jeida",
+};
+
+static const int of_get_data_mapping(struct device_node *np)
+{
+ const char *bm;
+ int ret, i;
+
+ ret = of_property_read_string(np, "fsl,data-mapping", &bm);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(imx_ldb_bit_mappings); i++)
+ if (!strcasecmp(bm, imx_ldb_bit_mappings[i]))
+ return i;
+
+ return -EINVAL;
+}
+
+static int imx_ldb_prepare(struct ipu_output *output, struct fb_videomode *mode, int di)
+{
+ struct imx_ldb_channel *imx_ldb_ch = container_of(output, struct imx_ldb_channel, output);
+ struct imx_ldb *ldb = imx_ldb_ch->ldb;
+
+ if (PICOS2KHZ(mode->pixclock) > 85000) {
+ dev_warn(ldb->dev,
+ "%s: mode exceeds 85 MHz pixel clock\n", __func__);
+ }
+
+ ldb->soc_data->prepare(imx_ldb_ch, di);
+
+ /* FIXME - assumes straight connections DI0 --> CH0, DI1 --> CH1 */
+ if (imx_ldb_ch == &ldb->channel[0]) {
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ ldb->ldb_ctrl |= LDB_DI0_VS_POL_ACT_LOW;
+ else
+ ldb->ldb_ctrl &= ~LDB_DI0_VS_POL_ACT_LOW;
+ }
+
+ if (imx_ldb_ch == &ldb->channel[1]) {
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ ldb->ldb_ctrl |= LDB_DI1_VS_POL_ACT_LOW;
+ else
+ ldb->ldb_ctrl &= ~LDB_DI1_VS_POL_ACT_LOW;
+ }
+
+ if (imx_ldb_ch == &ldb->channel[0]) {
+ ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK;
+ ldb->ldb_ctrl |= LDB_CH0_MODE_EN_TO_DI0;
+ }
+
+ if (imx_ldb_ch == &ldb->channel[1]) {
+ ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK;
+ ldb->ldb_ctrl |= LDB_CH1_MODE_EN_TO_DI1;
+ }
+
+ writel(ldb->ldb_ctrl, ldb->base);
+
+ return 0;
+}
+
+static int imx6q_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+ struct clk *diclk, *ldbclk;
+ struct imx_ldb *ldb = imx_ldb_ch->ldb;
+ int ret, ipuno, dino;
+ char *clkname;
+ void __iomem *gpr3 = (void *)MX6_IOMUXC_BASE_ADDR + 0xc;
+ uint32_t val;
+ int shift;
+
+ ipuno = ((di >> 1) & 1) + 1;
+ dino = di & 0x1;
+
+ clkname = asprintf("ipu%d_di%d_sel", ipuno, dino);
+ diclk = clk_lookup(clkname);
+ free(clkname);
+ if (IS_ERR(diclk)) {
+ dev_err(ldb->dev, "failed to get di clk: %s\n", strerror(PTR_ERR(diclk)));
+ return PTR_ERR(diclk);
+ }
+
+ clkname = asprintf("ldb_di%d_podf", imx_ldb_ch->chno);
+ ldbclk = clk_lookup(clkname);
+ free(clkname);
+ if (IS_ERR(ldbclk)) {
+ dev_err(ldb->dev, "failed to get ldb clk: %s\n", strerror(PTR_ERR(ldbclk)));
+ return PTR_ERR(ldbclk);
+ }
+
+ ret = clk_set_parent(diclk, ldbclk);
+ if (ret) {
+ dev_err(ldb->dev, "failed to set display clock parent: %s\n", strerror(-ret));
+ return ret;
+ }
+printk("%s: %d\n", __func__, di);
+ val = readl(gpr3);
+ shift = (imx_ldb_ch->chno == 0) ? 6 : 8;
+ val &= ~(3 << shift);
+ val |= di << shift;
+ writel(val, gpr3);
+
+ return 0;
+}
+
+static int imx53_ldb_prepare(struct imx_ldb_channel *imx_ldb_ch, int di)
+{
+ return -ENOSYS;
+}
+
+static struct imx_ldb_data imx_ldb_data_imx6q = {
+ .base = (void *)MX6_IOMUXC_BASE_ADDR + 0x8,
+ .prepare = imx6q_ldb_prepare,
+ .ipu_mask = 0xf,
+};
+
+static struct imx_ldb_data imx_ldb_data_imx53 = {
+ .base = (void *)MX53_IOMUXC_BASE_ADDR + 0x8,
+ .prepare = imx53_ldb_prepare,
+ .ipu_mask = 0x3,
+};
+
+static struct ipu_output_ops imx_ldb_ops = {
+ .prepare = imx_ldb_prepare,
+};
+
+static int imx_ldb_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ struct device_node *child;
+ struct imx_ldb *imx_ldb;
+ int ret, i;
+ int dual = 0;
+ int datawidth;
+ int mapping;
+ const struct imx_ldb_data *devtype;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
+ if (ret)
+ return ret;
+
+ imx_ldb = xzalloc(sizeof(*imx_ldb));
+ imx_ldb->base = devtype->base;
+ imx_ldb->soc_data = devtype;
+
+ for_each_child_of_node(np, child) {
+ struct imx_ldb_channel *channel;
+
+ ret = of_property_read_u32(child, "reg", &i);
+ if (ret || i < 0 || i > 1)
+ return -EINVAL;
+
+ if (dual && i > 0) {
+ dev_warn(dev, "dual-channel mode, ignoring second output\n");
+ continue;
+ }
+
+ if (!of_device_is_available(child))
+ continue;
+
+ channel = &imx_ldb->channel[i];
+ channel->ldb = imx_ldb;
+ channel->chno = i;
+
+ ret = of_property_read_u32(child, "fsl,data-width", &datawidth);
+ if (ret)
+ datawidth = 0;
+ else if (datawidth != 18 && datawidth != 24)
+ return -EINVAL;
+
+ mapping = of_get_data_mapping(child);
+ switch (mapping) {
+ case LVDS_BIT_MAP_SPWG:
+ if (datawidth == 24) {
+ if (i == 0 || dual)
+ imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24;
+ if (i == 1 || dual)
+ imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24;
+ }
+ break;
+ case LVDS_BIT_MAP_JEIDA:
+ if (datawidth == 18) {
+ dev_err(dev, "JEIDA standard only supported in 24 bit\n");
+ return -EINVAL;
+ }
+ if (i == 0 || dual)
+ imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH0_24 | LDB_BIT_MAP_CH0_JEIDA;
+ if (i == 1 || dual)
+ imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA;
+ break;
+ default:
+ dev_err(dev, "data mapping not specified or invalid\n");
+ return -EINVAL;
+ }
+
+ channel->output.ops = &imx_ldb_ops;
+ channel->output.di_clkflags = IPU_DI_CLKMODE_EXT | IPU_DI_CLKMODE_SYNC;
+ channel->output.out_pixel_fmt = (datawidth == 24) ?
+ V4L2_PIX_FMT_RGB24 : V4L2_PIX_FMT_BGR666;
+ channel->output.modes = of_get_display_timings(child);
+ channel->output.name = asprintf("ldb-%d", i);
+ channel->output.ipu_mask = devtype->ipu_mask;
+
+ ipu_register_output(&channel->output);
+ }
+
+ return 0;
+}
+
+static struct of_device_id imx_ldb_dt_ids[] = {
+ { .compatible = "fsl,imx6q-ldb", (unsigned long)&imx_ldb_data_imx6q},
+ { .compatible = "fsl,imx53-ldb", (unsigned long)&imx_ldb_data_imx53},
+ { /* sentinel */ }
+};
+
+static struct driver_d imx_ldb_driver = {
+ .probe = imx_ldb_probe,
+ .of_compatible = imx_ldb_dt_ids,
+ .name = "imx-ldb",
+};
+device_platform_driver(imx_ldb_driver);
+
+MODULE_DESCRIPTION("i.MX LVDS display driver");
+MODULE_AUTHOR("Sascha Hauer, Pengutronix");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/imx-ipu-v3/ipu-common.c b/drivers/video/imx-ipu-v3/ipu-common.c
new file mode 100644
index 0000000000..ffd6ec18a9
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipu-common.c
@@ -0,0 +1,836 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <common.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <clock.h>
+#include <driver.h>
+#include <init.h>
+#include <asm/mmu.h>
+#include <mach/generic.h>
+#include <mach/imx6-regs.h>
+
+#include "imx-ipu-v3.h"
+#include "ipu-prv.h"
+
+void ipuwritel(const char *unit, uint32_t value, void __iomem *reg)
+{
+ pr_debug("w: %s 0x%08lx -> 0x%08x\n", unit, (unsigned long)reg & 0xfff, value);
+
+ writel(value, reg);
+}
+
+uint32_t ipureadl(void __iomem *reg)
+{
+ uint32_t val;
+
+ val = readl(reg);
+
+ pr_debug("r: 0x%p -> 0x%08x\n", reg - 0x02600000, val);
+
+ return val;
+}
+
+static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return ipureadl(ipu->cm_reg + offset);
+}
+
+static inline void ipu_cm_write(struct ipu_soc *ipu, u32 value, unsigned offset)
+{
+ ipuwritel("cm", value, ipu->cm_reg + offset);
+}
+
+static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
+{
+ return ipureadl(ipu->idmac_reg + offset);
+}
+
+static inline void ipu_idmac_write(struct ipu_soc *ipu, u32 value,
+ unsigned offset)
+{
+ ipuwritel("idmac", value, ipu->idmac_reg + offset);
+}
+
+void ipu_srm_dp_sync_update(struct ipu_soc *ipu)
+{
+ u32 val;
+
+ val = ipu_cm_read(ipu, IPU_SRM_PRI2);
+ val |= 0x8;
+ ipu_cm_write(ipu, val, IPU_SRM_PRI2);
+}
+EXPORT_SYMBOL_GPL(ipu_srm_dp_sync_update);
+
+struct ipu_ch_param __iomem *ipu_get_cpmem(struct ipuv3_channel *channel)
+{
+ struct ipu_soc *ipu = channel->ipu;
+
+ return ipu->cpmem_base + channel->num;
+}
+EXPORT_SYMBOL_GPL(ipu_get_cpmem);
+
+void ipu_cpmem_set_high_priority(struct ipuv3_channel *channel)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ struct ipu_ch_param __iomem *p = ipu_get_cpmem(channel);
+ u32 val;
+
+ if (ipu->ipu_type == IPUV3EX)
+ ipu_ch_param_write_field(p, IPU_FIELD_ID, 1);
+
+ val = ipu_idmac_read(ipu, IDMAC_CHA_PRI(channel->num));
+ val |= 1 << (channel->num % 32);
+ ipu_idmac_write(ipu, val, IDMAC_CHA_PRI(channel->num));
+};
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_high_priority);
+
+void ipu_ch_param_write_field(struct ipu_ch_param __iomem *base, u32 wbs, u32 v)
+{
+ u32 bit = (wbs >> 8) % 160;
+ u32 size = wbs & 0xff;
+ u32 word = (wbs >> 8) / 160;
+ u32 i = bit / 32;
+ u32 ofs = bit % 32;
+ u32 mask = (1 << size) - 1;
+ u32 val;
+
+ pr_debug("%s %d %d %d 0x%08x\n", __func__, word, bit , size, v);
+
+ val = ipureadl(&base->word[word].data[i]);
+ val &= ~(mask << ofs);
+ val |= v << ofs;
+ ipuwritel("chp", val, &base->word[word].data[i]);
+
+ if ((bit + size - 1) / 32 > i) {
+ val = ipureadl(&base->word[word].data[i + 1]);
+ val &= ~(mask >> (ofs ? (32 - ofs) : 0));
+ val |= v >> (ofs ? (32 - ofs) : 0);
+ ipuwritel("chp", val, &base->word[word].data[i + 1]);
+ }
+}
+EXPORT_SYMBOL_GPL(ipu_ch_param_write_field);
+
+u32 ipu_ch_param_read_field(struct ipu_ch_param __iomem *base, u32 wbs)
+{
+ u32 bit = (wbs >> 8) % 160;
+ u32 size = wbs & 0xff;
+ u32 word = (wbs >> 8) / 160;
+ u32 i = bit / 32;
+ u32 ofs = bit % 32;
+ u32 mask = (1 << size) - 1;
+ u32 val = 0;
+
+ pr_debug("%s %d %d %d\n", __func__, word, bit , size);
+
+ val = (ipureadl(&base->word[word].data[i]) >> ofs) & mask;
+
+ if ((bit + size - 1) / 32 > i) {
+ u32 tmp;
+ tmp = ipureadl(&base->word[word].data[i + 1]);
+ tmp &= mask >> (ofs ? (32 - ofs) : 0);
+ val |= tmp << (ofs ? (32 - ofs) : 0);
+ }
+
+ return val;
+}
+EXPORT_SYMBOL_GPL(ipu_ch_param_read_field);
+
+int ipu_cpmem_set_format_rgb(struct ipu_ch_param __iomem *p,
+ const struct ipu_rgb *rgb)
+{
+ int bpp = 0, npb = 0, ro, go, bo, to;
+
+ ro = rgb->bits_per_pixel - rgb->red.length - rgb->red.offset;
+ go = rgb->bits_per_pixel - rgb->green.length - rgb->green.offset;
+ bo = rgb->bits_per_pixel - rgb->blue.length - rgb->blue.offset;
+ to = rgb->bits_per_pixel - rgb->transp.length - rgb->transp.offset;
+
+ ipu_ch_param_write_field(p, IPU_FIELD_WID0, rgb->red.length - 1);
+ ipu_ch_param_write_field(p, IPU_FIELD_OFS0, ro);
+ ipu_ch_param_write_field(p, IPU_FIELD_WID1, rgb->green.length - 1);
+ ipu_ch_param_write_field(p, IPU_FIELD_OFS1, go);
+ ipu_ch_param_write_field(p, IPU_FIELD_WID2, rgb->blue.length - 1);
+ ipu_ch_param_write_field(p, IPU_FIELD_OFS2, bo);
+
+ if (rgb->transp.length) {
+ ipu_ch_param_write_field(p, IPU_FIELD_WID3,
+ rgb->transp.length - 1);
+ ipu_ch_param_write_field(p, IPU_FIELD_OFS3, to);
+ } else {
+ ipu_ch_param_write_field(p, IPU_FIELD_WID3, 7);
+ ipu_ch_param_write_field(p, IPU_FIELD_OFS3,
+ rgb->bits_per_pixel);
+ }
+
+ switch (rgb->bits_per_pixel) {
+ case 32:
+ bpp = 0;
+ npb = 15;
+ break;
+ case 24:
+ bpp = 1;
+ npb = 19;
+ break;
+ case 16:
+ bpp = 3;
+ npb = 31;
+ break;
+ case 8:
+ bpp = 5;
+ npb = 63;
+ break;
+ default:
+ return -EINVAL;
+ }
+ ipu_ch_param_write_field(p, IPU_FIELD_BPP, bpp);
+ ipu_ch_param_write_field(p, IPU_FIELD_NPB, npb);
+ ipu_ch_param_write_field(p, IPU_FIELD_PFS, 7); /* rgb mode */
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_format_rgb);
+
+static struct ipu_rgb def_rgb_32 = {
+ .red = { .offset = 16, .length = 8, },
+ .green = { .offset = 8, .length = 8, },
+ .blue = { .offset = 0, .length = 8, },
+ .transp = { .offset = 24, .length = 8, },
+ .bits_per_pixel = 32,
+};
+
+static struct ipu_rgb def_bgr_32 = {
+ .red = { .offset = 0, .length = 8, },
+ .green = { .offset = 8, .length = 8, },
+ .blue = { .offset = 16, .length = 8, },
+ .transp = { .offset = 24, .length = 8, },
+ .bits_per_pixel = 32,
+};
+
+static struct ipu_rgb def_rgb_24 = {
+ .red = { .offset = 16, .length = 8, },
+ .green = { .offset = 8, .length = 8, },
+ .blue = { .offset = 0, .length = 8, },
+ .transp = { .offset = 0, .length = 0, },
+ .bits_per_pixel = 24,
+};
+
+static struct ipu_rgb def_bgr_24 = {
+ .red = { .offset = 0, .length = 8, },
+ .green = { .offset = 8, .length = 8, },
+ .blue = { .offset = 16, .length = 8, },
+ .transp = { .offset = 0, .length = 0, },
+ .bits_per_pixel = 24,
+};
+
+static struct ipu_rgb def_rgb_16 = {
+ .red = { .offset = 11, .length = 5, },
+ .green = { .offset = 5, .length = 6, },
+ .blue = { .offset = 0, .length = 5, },
+ .transp = { .offset = 0, .length = 0, },
+ .bits_per_pixel = 16,
+};
+
+static struct ipu_rgb def_bgr_16 = {
+ .red = { .offset = 0, .length = 5, },
+ .green = { .offset = 5, .length = 6, },
+ .blue = { .offset = 11, .length = 5, },
+ .transp = { .offset = 0, .length = 0, },
+ .bits_per_pixel = 16,
+};
+
+struct ipu_rgb *drm_fourcc_to_rgb(u32 drm_fourcc)
+{
+ switch (drm_fourcc) {
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ return &def_bgr_32;
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ return &def_rgb_32;
+ case DRM_FORMAT_BGR888:
+ return &def_bgr_24;
+ case DRM_FORMAT_RGB888:
+ return &def_rgb_24;
+ case DRM_FORMAT_RGB565:
+ return &def_rgb_16;
+ case DRM_FORMAT_BGR565:
+ return &def_bgr_16;
+ default:
+ return NULL;
+ }
+}
+
+#define Y_OFFSET(pix, x, y) ((x) + pix->width * (y))
+#define U_OFFSET(pix, x, y) ((pix->width * pix->height) + \
+ (pix->width * (y) / 4) + (x) / 2)
+#define V_OFFSET(pix, x, y) ((pix->width * pix->height) + \
+ (pix->width * pix->height / 4) + \
+ (pix->width * (y) / 4) + (x) / 2)
+
+int ipu_cpmem_set_fmt(struct ipu_ch_param __iomem *cpmem, u32 drm_fourcc)
+{
+ switch (drm_fourcc) {
+ case DRM_FORMAT_ABGR8888:
+ case DRM_FORMAT_XBGR8888:
+ ipu_cpmem_set_format_rgb(cpmem, &def_bgr_32);
+ break;
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_XRGB8888:
+ ipu_cpmem_set_format_rgb(cpmem, &def_rgb_32);
+ break;
+ case DRM_FORMAT_BGR888:
+ ipu_cpmem_set_format_rgb(cpmem, &def_bgr_24);
+ break;
+ case DRM_FORMAT_RGB888:
+ ipu_cpmem_set_format_rgb(cpmem, &def_rgb_24);
+ break;
+ case DRM_FORMAT_RGB565:
+ ipu_cpmem_set_format_rgb(cpmem, &def_rgb_16);
+ break;
+ case DRM_FORMAT_BGR565:
+ ipu_cpmem_set_format_rgb(cpmem, &def_bgr_16);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_cpmem_set_fmt);
+
+struct ipuv3_channel *ipu_idmac_get(struct ipu_soc *ipu, unsigned num)
+{
+ struct ipuv3_channel *channel;
+
+ dev_dbg(ipu->dev, "%s %d\n", __func__, num);
+
+ if (num > 63)
+ return ERR_PTR(-ENODEV);
+
+ mutex_lock(&ipu->channel_lock);
+
+ channel = &ipu->channel[num];
+
+ if (channel->busy) {
+ channel = ERR_PTR(-EBUSY);
+ goto out;
+ }
+
+ channel->busy = true;
+ channel->num = num;
+
+out:
+ mutex_unlock(&ipu->channel_lock);
+
+ return channel;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_get);
+
+void ipu_idmac_put(struct ipuv3_channel *channel)
+{
+ struct ipu_soc *ipu = channel->ipu;
+
+ dev_dbg(ipu->dev, "%s %d\n", __func__, channel->num);
+
+ mutex_lock(&ipu->channel_lock);
+
+ channel->busy = false;
+
+ mutex_unlock(&ipu->channel_lock);
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_put);
+
+#define idma_mask(ch) (1 << (ch & 0x1f))
+
+void ipu_idmac_set_double_buffer(struct ipuv3_channel *channel,
+ bool doublebuffer)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ u32 reg;
+
+ reg = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
+ if (doublebuffer)
+ reg |= idma_mask(channel->num);
+ else
+ reg &= ~idma_mask(channel->num);
+ ipu_cm_write(ipu, reg, IPU_CHA_DB_MODE_SEL(channel->num));
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_set_double_buffer);
+
+int ipu_module_enable(struct ipu_soc *ipu, u32 mask)
+{
+ u32 val;
+
+ val = ipu_cm_read(ipu, IPU_DISP_GEN);
+
+ if (mask & IPU_CONF_DI0_EN)
+ val |= IPU_DI0_COUNTER_RELEASE;
+ if (mask & IPU_CONF_DI1_EN)
+ val |= IPU_DI1_COUNTER_RELEASE;
+
+ ipu_cm_write(ipu, val, IPU_DISP_GEN);
+
+ val = ipu_cm_read(ipu, IPU_CONF);
+ val |= mask;
+ ipu_cm_write(ipu, val, IPU_CONF);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_module_enable);
+
+int ipu_module_disable(struct ipu_soc *ipu, u32 mask)
+{
+ u32 val;
+
+ val = ipu_cm_read(ipu, IPU_CONF);
+ val &= ~mask;
+ ipu_cm_write(ipu, val, IPU_CONF);
+
+ val = ipu_cm_read(ipu, IPU_DISP_GEN);
+
+ if (mask & IPU_CONF_DI0_EN)
+ val &= ~IPU_DI0_COUNTER_RELEASE;
+ if (mask & IPU_CONF_DI1_EN)
+ val &= ~IPU_DI1_COUNTER_RELEASE;
+
+ ipu_cm_write(ipu, val, IPU_DISP_GEN);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_module_disable);
+
+void ipu_idmac_select_buffer(struct ipuv3_channel *channel, u32 buf_num)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ unsigned int chno = channel->num;
+
+ /* Mark buffer as ready. */
+ if (buf_num == 0)
+ ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF0_RDY(chno));
+ else
+ ipu_cm_write(ipu, idma_mask(chno), IPU_CHA_BUF1_RDY(chno));
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_select_buffer);
+
+int ipu_idmac_enable_channel(struct ipuv3_channel *channel)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ u32 val;
+
+ val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
+ val |= idma_mask(channel->num);
+ ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_enable_channel);
+
+int ipu_idmac_wait_busy(struct ipuv3_channel *channel, int ms)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ uint64_t start;
+
+ start = get_time_ns();
+
+ while (ipu_idmac_read(ipu, IDMAC_CHA_BUSY(channel->num)) &
+ idma_mask(channel->num)) {
+ if (is_timeout(start, ms * MSECOND))
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_wait_busy);
+
+int ipu_idmac_disable_channel(struct ipuv3_channel *channel)
+{
+ struct ipu_soc *ipu = channel->ipu;
+ u32 val;
+
+ /* Disable DMA channel(s) */
+ val = ipu_idmac_read(ipu, IDMAC_CHA_EN(channel->num));
+ val &= ~idma_mask(channel->num);
+ ipu_idmac_write(ipu, val, IDMAC_CHA_EN(channel->num));
+
+ /* Set channel buffers NOT to be ready */
+ ipu_cm_write(ipu, 0xf0000000, IPU_GPR); /* write one to clear */
+
+ if (ipu_cm_read(ipu, IPU_CHA_BUF0_RDY(channel->num)) &
+ idma_mask(channel->num)) {
+ ipu_cm_write(ipu, idma_mask(channel->num),
+ IPU_CHA_BUF0_RDY(channel->num));
+ }
+
+ if (ipu_cm_read(ipu, IPU_CHA_BUF1_RDY(channel->num)) &
+ idma_mask(channel->num)) {
+ ipu_cm_write(ipu, idma_mask(channel->num),
+ IPU_CHA_BUF1_RDY(channel->num));
+ }
+
+ ipu_cm_write(ipu, 0x0, IPU_GPR); /* write one to set */
+
+ /* Reset the double buffer */
+ val = ipu_cm_read(ipu, IPU_CHA_DB_MODE_SEL(channel->num));
+ val &= ~idma_mask(channel->num);
+ ipu_cm_write(ipu, val, IPU_CHA_DB_MODE_SEL(channel->num));
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_idmac_disable_channel);
+
+static int ipu_memory_reset(struct ipu_soc *ipu)
+{
+ uint64_t start;
+
+ ipu_cm_write(ipu, 0x807FFFFF, IPU_MEM_RST);
+
+ start = get_time_ns();
+
+ while (ipu_cm_read(ipu, IPU_MEM_RST) & 0x80000000) {
+ if (is_timeout(start, SECOND))
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int imx6_ipu_reset(struct ipu_soc *ipu)
+{
+ uint32_t val;
+ int ret;
+ void __iomem *reg;
+
+ reg = (void *)MX6_SRC_BASE_ADDR;
+ val = ipureadl(reg);
+ if (ipu->base == (void *)MX6_IPU1_BASE_ADDR)
+ val |= (1 << 3);
+ else
+ val |= (1 << 12);
+
+ ipuwritel("reset", val, reg);
+
+ ret = wait_on_timeout(100 * MSECOND, !(readl(reg) & (1 << 3)));
+
+ return ret;
+
+}
+
+struct ipu_devtype {
+ const char *name;
+ unsigned long cm_ofs;
+ unsigned long cpmem_ofs;
+ unsigned long srm_ofs;
+ unsigned long tpm_ofs;
+ unsigned long disp0_ofs;
+ unsigned long disp1_ofs;
+ unsigned long dc_tmpl_ofs;
+ unsigned long vdi_ofs;
+ enum ipuv3_type type;
+ int (*reset)(struct ipu_soc *ipu);
+};
+
+static struct ipu_devtype ipu_type_imx51 = {
+ .name = "IPUv3EX",
+ .cm_ofs = 0x1e000000,
+ .cpmem_ofs = 0x1f000000,
+ .srm_ofs = 0x1f040000,
+ .tpm_ofs = 0x1f060000,
+ .disp0_ofs = 0x1e040000,
+ .disp1_ofs = 0x1e048000,
+ .dc_tmpl_ofs = 0x1f080000,
+ .vdi_ofs = 0x1e068000,
+ .type = IPUV3EX,
+};
+
+static struct ipu_devtype ipu_type_imx53 = {
+ .name = "IPUv3M",
+ .cm_ofs = 0x06000000,
+ .cpmem_ofs = 0x07000000,
+ .srm_ofs = 0x07040000,
+ .tpm_ofs = 0x07060000,
+ .disp0_ofs = 0x06040000,
+ .disp1_ofs = 0x06048000,
+ .dc_tmpl_ofs = 0x07080000,
+ .vdi_ofs = 0x06068000,
+ .type = IPUV3M,
+};
+
+static struct ipu_devtype ipu_type_imx6q = {
+ .name = "IPUv3H",
+ .cm_ofs = 0x00200000,
+ .cpmem_ofs = 0x00300000,
+ .srm_ofs = 0x00340000,
+ .tpm_ofs = 0x00360000,
+ .disp0_ofs = 0x00240000,
+ .disp1_ofs = 0x00248000,
+ .dc_tmpl_ofs = 0x00380000,
+ .vdi_ofs = 0x00268000,
+ .type = IPUV3H,
+ .reset = imx6_ipu_reset,
+};
+
+static struct of_device_id imx_ipu_dt_ids[] = {
+ { .compatible = "fsl,imx51-ipu", .data = (unsigned long)&ipu_type_imx51, },
+ { .compatible = "fsl,imx53-ipu", .data = (unsigned long)&ipu_type_imx53, },
+ { .compatible = "fsl,imx6q-ipu", .data = (unsigned long)&ipu_type_imx6q, },
+ { /* sentinel */ }
+};
+
+static int ipu_submodules_init(struct ipu_soc *ipu,
+ struct device_d *dev, void __iomem *ipu_base,
+ struct clk *ipu_clk)
+{
+ char *unit;
+ int ret;
+ const struct ipu_devtype *devtype = ipu->devtype;
+
+ ret = ipu_di_init(ipu, dev, 0, ipu_base + devtype->disp0_ofs,
+ IPU_CONF_DI0_EN, ipu_clk);
+ if (ret) {
+ unit = "di0";
+ goto err_di_0;
+ }
+
+ ret = ipu_di_init(ipu, dev, 1, ipu_base + devtype->disp1_ofs,
+ IPU_CONF_DI1_EN, ipu_clk);
+ if (ret) {
+ unit = "di1";
+ goto err_di_1;
+ }
+
+ ret = ipu_dc_init(ipu, dev, ipu_base + devtype->cm_ofs +
+ IPU_CM_DC_REG_OFS, ipu_base + devtype->dc_tmpl_ofs);
+ if (ret) {
+ unit = "dc_template";
+ goto err_dc;
+ }
+
+ ret = ipu_dmfc_init(ipu, dev, ipu_base +
+ devtype->cm_ofs + IPU_CM_DMFC_REG_OFS, ipu_clk);
+ if (ret) {
+ unit = "dmfc";
+ goto err_dmfc;
+ }
+
+ ret = ipu_dp_init(ipu, dev, ipu_base + devtype->srm_ofs);
+ if (ret) {
+ unit = "dp";
+ goto err_dp;
+ }
+
+ return 0;
+
+err_dp:
+ ipu_dmfc_exit(ipu);
+err_dmfc:
+ ipu_dc_exit(ipu);
+err_dc:
+ ipu_di_exit(ipu, 1);
+err_di_1:
+ ipu_di_exit(ipu, 0);
+err_di_0:
+ dev_err(dev, "init %s failed with %d\n", unit, ret);
+ return ret;
+}
+
+static void ipu_submodules_exit(struct ipu_soc *ipu)
+{
+ ipu_dp_exit(ipu);
+ ipu_dmfc_exit(ipu);
+ ipu_dc_exit(ipu);
+ ipu_di_exit(ipu, 1);
+ ipu_di_exit(ipu, 0);
+}
+
+struct ipu_platform_reg {
+ struct ipu_client_platformdata pdata;
+ const char *name;
+};
+
+static struct ipu_platform_reg client_reg[] = {
+ {
+ .pdata = {
+ .di = 0,
+ .dc = 5,
+ .dp = IPU_DP_FLOW_SYNC_BG,
+ .dma[0] = IPUV3_CHANNEL_MEM_BG_SYNC,
+ .dma[1] = IPUV3_CHANNEL_MEM_FG_SYNC,
+ },
+ .name = "imx-ipuv3-crtc",
+ }, {
+ .pdata = {
+ .di = 1,
+ .dc = 1,
+ .dp = -EINVAL,
+ .dma[0] = IPUV3_CHANNEL_MEM_DC_SYNC,
+ .dma[1] = -EINVAL,
+ },
+ .name = "imx-ipuv3-crtc",
+ },
+};
+
+static int ipu_client_id;
+
+static int ipu_add_subdevice_pdata(struct device_d *ipu_dev,
+ struct ipu_platform_reg *reg)
+{
+ struct device_d *dev;
+ int ret;
+
+ dev = device_alloc(reg->name, ipu_client_id++);
+ dev->parent = ipu_dev;
+ device_add_data(dev, &reg->pdata, sizeof(reg->pdata));
+ ((struct ipu_client_platformdata *)dev->platform_data)->device_node = ipu_dev->device_node;
+
+ ret = platform_device_register(dev);
+
+ return ret;
+}
+
+static int ipu_add_client_devices(struct ipu_soc *ipu)
+{
+ int ret;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(client_reg); i++) {
+ struct ipu_platform_reg *reg = &client_reg[i];
+ ret = ipu_add_subdevice_pdata(ipu->dev, reg);
+ if (ret)
+ goto err_register;
+ }
+
+ return 0;
+
+err_register:
+
+ return ret;
+}
+
+static int ipu_probe(struct device_d *dev)
+{
+ struct ipu_soc *ipu;
+ void __iomem *ipu_base;
+ int i, ret;
+ const struct ipu_devtype *devtype;
+
+ ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
+ if (ret)
+ return ret;
+
+ ipu_base = dev_request_mem_region(dev, 0);
+ if (!ipu_base)
+ return -EBUSY;
+
+ ipu = xzalloc(sizeof(*ipu));
+
+ ipu->base = ipu_base;
+
+ for (i = 0; i < 64; i++)
+ ipu->channel[i].ipu = ipu;
+ ipu->devtype = devtype;
+ ipu->ipu_type = devtype->type;
+
+ dev_dbg(dev, "cm_reg: 0x%p\n",
+ ipu_base + devtype->cm_ofs);
+ dev_dbg(dev, "idmac: 0x%p\n",
+ ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS);
+ dev_dbg(dev, "cpmem: 0x%p\n",
+ ipu_base + devtype->cpmem_ofs);
+ dev_dbg(dev, "disp0: 0x%p\n",
+ ipu_base + devtype->disp0_ofs);
+ dev_dbg(dev, "disp1: 0x%p\n",
+ ipu_base + devtype->disp1_ofs);
+ dev_dbg(dev, "srm: 0x%p\n",
+ ipu_base + devtype->srm_ofs);
+ dev_dbg(dev, "tpm: 0x%p\n",
+ ipu_base + devtype->tpm_ofs);
+ dev_dbg(dev, "dc: 0x%p\n",
+ ipu_base + devtype->cm_ofs + IPU_CM_DC_REG_OFS);
+ dev_dbg(dev, "ic: 0x%p\n",
+ ipu_base + devtype->cm_ofs + IPU_CM_IC_REG_OFS);
+ dev_dbg(dev, "dmfc: 0x%p\n",
+ ipu_base + devtype->cm_ofs + IPU_CM_DMFC_REG_OFS);
+ dev_dbg(dev, "vdi: 0x%p\n",
+ ipu_base + devtype->vdi_ofs);
+
+ ipu->cm_reg = ipu_base + devtype->cm_ofs, PAGE_SIZE;
+ ipu->idmac_reg = ipu_base + devtype->cm_ofs + IPU_CM_IDMAC_REG_OFS;
+ ipu->cpmem_base = ipu_base + devtype->cpmem_ofs;
+
+ ipu->clk = clk_get(dev, "bus");
+ if (IS_ERR(ipu->clk)) {
+ ret = PTR_ERR(ipu->clk);
+ dev_err(dev, "clk_get failed with %d", ret);
+ return ret;
+ }
+
+ dev->priv = ipu;
+
+ ret = clk_enable(ipu->clk);
+ if (ret)
+ return ret;
+
+ ipu->dev = dev;
+
+ ret = devtype->reset(ipu);
+ if (ret) {
+ dev_err(dev, "failed to reset: %d\n", ret);
+ goto out_failed_reset;
+ }
+
+ ret = ipu_memory_reset(ipu);
+ if (ret)
+ goto out_failed_reset;
+
+ /* Set MCU_T to divide MCU access window into 2 */
+ ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
+ IPU_DISP_GEN);
+
+ ret = ipu_submodules_init(ipu, dev, ipu_base, ipu->clk);
+ if (ret)
+ goto failed_submodules_init;
+
+ ret = ipu_add_client_devices(ipu);
+ if (ret) {
+ dev_err(dev, "adding client devices failed with %d\n",
+ ret);
+ goto failed_add_clients;
+ }
+
+ dev_info(dev, "%s probed\n", devtype->name);
+
+ return 0;
+
+failed_add_clients:
+ ipu_submodules_exit(ipu);
+failed_submodules_init:
+out_failed_reset:
+ clk_disable(ipu->clk);
+ return ret;
+}
+
+static struct driver_d imx_ipu_driver = {
+ .name = "imx-ipuv3",
+ .of_compatible = imx_ipu_dt_ids,
+ .probe = ipu_probe,
+};
+
+device_platform_driver(imx_ipu_driver);
+
+MODULE_DESCRIPTION("i.MX IPU v3 driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/imx-ipu-v3/ipu-dc.c b/drivers/video/imx-ipu-v3/ipu-dc.c
new file mode 100644
index 0000000000..2deb2ae048
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipu-dc.c
@@ -0,0 +1,392 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <common.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <malloc.h>
+
+#include "imx-ipu-v3.h"
+#include "ipu-prv.h"
+
+#define DC_MAP_CONF_PTR(n) (0x108 + ((n) & ~0x1) * 2)
+#define DC_MAP_CONF_VAL(n) (0x144 + ((n) & ~0x1) * 2)
+
+#define DC_EVT_NF 0
+#define DC_EVT_NL 1
+#define DC_EVT_EOF 2
+#define DC_EVT_NFIELD 3
+#define DC_EVT_EOL 4
+#define DC_EVT_EOFIELD 5
+#define DC_EVT_NEW_ADDR 6
+#define DC_EVT_NEW_CHAN 7
+#define DC_EVT_NEW_DATA 8
+
+#define DC_EVT_NEW_ADDR_W_0 0
+#define DC_EVT_NEW_ADDR_W_1 1
+#define DC_EVT_NEW_CHAN_W_0 2
+#define DC_EVT_NEW_CHAN_W_1 3
+#define DC_EVT_NEW_DATA_W_0 4
+#define DC_EVT_NEW_DATA_W_1 5
+#define DC_EVT_NEW_ADDR_R_0 6
+#define DC_EVT_NEW_ADDR_R_1 7
+#define DC_EVT_NEW_CHAN_R_0 8
+#define DC_EVT_NEW_CHAN_R_1 9
+#define DC_EVT_NEW_DATA_R_0 10
+#define DC_EVT_NEW_DATA_R_1 11
+
+#define DC_WR_CH_CONF 0x0
+#define DC_WR_CH_ADDR 0x4
+#define DC_RL_CH(evt) (8 + ((evt) & ~0x1) * 2)
+
+#define DC_GEN 0xd4
+#define DC_DISP_CONF1(disp) (0xd8 + (disp) * 4)
+#define DC_DISP_CONF2(disp) (0xe8 + (disp) * 4)
+#define DC_STAT 0x1c8
+
+#define WROD(lf) (0x18 | ((lf) << 1))
+#define WRG 0x01
+#define WCLK 0xc9
+
+#define SYNC_WAVE 0
+#define NULL_WAVE (-1)
+
+#define DC_GEN_SYNC_1_6_SYNC (2 << 1)
+#define DC_GEN_SYNC_PRIORITY_1 (1 << 7)
+
+#define DC_WR_CH_CONF_WORD_SIZE_8 (0 << 0)
+#define DC_WR_CH_CONF_WORD_SIZE_16 (1 << 0)
+#define DC_WR_CH_CONF_WORD_SIZE_24 (2 << 0)
+#define DC_WR_CH_CONF_WORD_SIZE_32 (3 << 0)
+#define DC_WR_CH_CONF_DISP_ID_PARALLEL(i) (((i) & 0x1) << 3)
+#define DC_WR_CH_CONF_DISP_ID_SERIAL (2 << 3)
+#define DC_WR_CH_CONF_DISP_ID_ASYNC (3 << 4)
+#define DC_WR_CH_CONF_FIELD_MODE (1 << 9)
+#define DC_WR_CH_CONF_PROG_TYPE_NORMAL (4 << 5)
+#define DC_WR_CH_CONF_PROG_TYPE_MASK (7 << 5)
+#define DC_WR_CH_CONF_PROG_DI_ID (1 << 2)
+#define DC_WR_CH_CONF_PROG_DISP_ID(i) (((i) & 0x1) << 3)
+
+#define IPU_DC_NUM_CHANNELS 10
+
+struct ipu_dc_priv;
+
+enum ipu_dc_map {
+ IPU_DC_MAP_RGB24,
+ IPU_DC_MAP_RGB565,
+ IPU_DC_MAP_GBR24, /* TVEv2 */
+ IPU_DC_MAP_BGR666,
+ IPU_DC_MAP_BGR24,
+};
+
+struct ipu_dc {
+ /* The display interface number assigned to this dc channel */
+ unsigned int di;
+ void __iomem *base;
+ struct ipu_dc_priv *priv;
+ int chno;
+ bool in_use;
+};
+
+struct ipu_dc_priv {
+ void __iomem *dc_reg;
+ void __iomem *dc_tmpl_reg;
+ struct ipu_soc *ipu;
+ struct device_d *dev;
+ struct ipu_dc channels[IPU_DC_NUM_CHANNELS];
+};
+
+static void dc_link_event(struct ipu_dc *dc, int event, int addr, int priority)
+{
+ u32 reg;
+
+ reg = ipureadl(dc->base + DC_RL_CH(event));
+ reg &= ~(0xffff << (16 * (event & 0x1)));
+ reg |= ((addr << 8) | priority) << (16 * (event & 0x1));
+ ipuwritel("dc", reg, dc->base + DC_RL_CH(event));
+}
+
+static void dc_write_tmpl(struct ipu_dc *dc, int word, u32 opcode, u32 operand,
+ int map, int wave, int glue, int sync, int stop)
+{
+ struct ipu_dc_priv *priv = dc->priv;
+ u32 reg1, reg2;
+
+ if (opcode == WCLK) {
+ reg1 = (operand << 20) & 0xfff00000;
+ reg2 = operand >> 12 | opcode << 1 | stop << 9;
+ } else if (opcode == WRG) {
+ reg1 = sync | glue << 4 | ++wave << 11 | ((operand << 15) & 0xffff8000);
+ reg2 = operand >> 17 | opcode << 7 | stop << 9;
+ } else {
+ reg1 = sync | glue << 4 | ++wave << 11 | ++map << 15 | ((operand << 20) & 0xfff00000);
+ reg2 = operand >> 12 | opcode << 4 | stop << 9;
+ }
+ ipuwritel("dc", reg1, priv->dc_tmpl_reg + word * 8);
+ ipuwritel("dc", reg2, priv->dc_tmpl_reg + word * 8 + 4);
+}
+
+static int ipu_pixfmt_to_map(u32 fmt)
+{
+ switch (fmt) {
+ case V4L2_PIX_FMT_RGB24:
+ return IPU_DC_MAP_RGB24;
+ case V4L2_PIX_FMT_RGB565:
+ return IPU_DC_MAP_RGB565;
+ case IPU_PIX_FMT_GBR24:
+ return IPU_DC_MAP_GBR24;
+ case V4L2_PIX_FMT_BGR666:
+ return IPU_DC_MAP_BGR666;
+ case V4L2_PIX_FMT_BGR24:
+ return IPU_DC_MAP_BGR24;
+ default:
+ return -EINVAL;
+ }
+}
+
+int ipu_dc_init_sync(struct ipu_dc *dc, struct ipu_di *di, bool interlaced,
+ u32 pixel_fmt, u32 width)
+{
+ struct ipu_dc_priv *priv = dc->priv;
+ u32 reg = 0;
+ int map;
+
+ dc->di = ipu_di_get_num(di);
+
+ map = ipu_pixfmt_to_map(pixel_fmt);
+ if (map < 0) {
+ dev_dbg(priv->dev, "IPU_DISP: No MAP\n");
+ return map;
+ }
+
+ if (interlaced) {
+ dc_link_event(dc, DC_EVT_NL, 0, 3);
+ dc_link_event(dc, DC_EVT_EOL, 0, 2);
+ dc_link_event(dc, DC_EVT_NEW_DATA, 0, 1);
+
+ /* Init template microcode */
+ dc_write_tmpl(dc, 0, WROD(0), 0, map, SYNC_WAVE, 0, 8, 1);
+ } else {
+ if (dc->di) {
+ dc_link_event(dc, DC_EVT_NL, 2, 3);
+ dc_link_event(dc, DC_EVT_EOL, 3, 2);
+ dc_link_event(dc, DC_EVT_NEW_DATA, 1, 1);
+ /* Init template microcode */
+ dc_write_tmpl(dc, 2, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
+ dc_write_tmpl(dc, 3, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
+ dc_write_tmpl(dc, 4, WRG, 0, map, NULL_WAVE, 0, 0, 1);
+ dc_write_tmpl(dc, 1, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ } else {
+ dc_link_event(dc, DC_EVT_NL, 5, 3);
+ dc_link_event(dc, DC_EVT_EOL, 6, 2);
+ dc_link_event(dc, DC_EVT_NEW_DATA, 8, 1);
+ /* Init template microcode */
+ dc_write_tmpl(dc, 5, WROD(0), 0, map, SYNC_WAVE, 8, 5, 1);
+ dc_write_tmpl(dc, 6, WROD(0), 0, map, SYNC_WAVE, 4, 5, 0);
+ dc_write_tmpl(dc, 7, WRG, 0, map, NULL_WAVE, 0, 0, 1);
+ dc_write_tmpl(dc, 8, WROD(0), 0, map, SYNC_WAVE, 0, 5, 1);
+ }
+ }
+ dc_link_event(dc, DC_EVT_NF, 0, 0);
+ dc_link_event(dc, DC_EVT_NFIELD, 0, 0);
+ dc_link_event(dc, DC_EVT_EOF, 0, 0);
+ dc_link_event(dc, DC_EVT_EOFIELD, 0, 0);
+ dc_link_event(dc, DC_EVT_NEW_CHAN, 0, 0);
+ dc_link_event(dc, DC_EVT_NEW_ADDR, 0, 0);
+
+ reg = ipureadl(dc->base + DC_WR_CH_CONF);
+ if (interlaced)
+ reg |= DC_WR_CH_CONF_FIELD_MODE;
+ else
+ reg &= ~DC_WR_CH_CONF_FIELD_MODE;
+ ipuwritel("dc", reg, dc->base + DC_WR_CH_CONF);
+
+ ipuwritel("dc", 0x0, dc->base + DC_WR_CH_ADDR);
+ ipuwritel("dc", width, priv->dc_reg + DC_DISP_CONF2(dc->di));
+
+ ipu_module_enable(priv->ipu, IPU_CONF_DC_EN);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dc_init_sync);
+
+void ipu_dc_enable_channel(struct ipu_dc *dc)
+{
+ int di;
+ u32 reg;
+
+ di = dc->di;
+
+ reg = ipureadl(dc->base + DC_WR_CH_CONF);
+ reg |= DC_WR_CH_CONF_PROG_TYPE_NORMAL;
+ ipuwritel("dc", reg, dc->base + DC_WR_CH_CONF);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_enable_channel);
+
+void ipu_dc_disable_channel(struct ipu_dc *dc)
+{
+ struct ipu_dc_priv *priv = dc->priv;
+ u32 val;
+ int irq = 0, timeout = 50;
+
+ if (dc->chno == 1)
+ irq = IPU_IRQ_DC_FC_1;
+ else if (dc->chno == 5)
+ irq = IPU_IRQ_DP_SF_END;
+ else
+ return;
+
+ /* should wait for the interrupt here */
+ mdelay(50);
+
+ if (dc->di == 0)
+ val = 0x00000002;
+ else
+ val = 0x00000020;
+
+ /* Wait for DC triple buffer to empty */
+ while ((ipureadl(priv->dc_reg + DC_STAT) & val) != val) {
+ mdelay(2);
+ timeout -= 2;
+ if (timeout <= 0)
+ break;
+ }
+
+ val = ipureadl(dc->base + DC_WR_CH_CONF);
+ val &= ~DC_WR_CH_CONF_PROG_TYPE_MASK;
+ ipuwritel("dc", val, dc->base + DC_WR_CH_CONF);
+}
+EXPORT_SYMBOL_GPL(ipu_dc_disable_channel);
+
+static void ipu_dc_map_config(struct ipu_dc_priv *priv, enum ipu_dc_map map,
+ int byte_num, int offset, int mask)
+{
+ int ptr = map * 3 + byte_num;
+ u32 reg;
+
+ reg = ipureadl(priv->dc_reg + DC_MAP_CONF_VAL(ptr));
+ reg &= ~(0xffff << (16 * (ptr & 0x1)));
+ reg |= ((offset << 8) | mask) << (16 * (ptr & 0x1));
+ ipuwritel("dc", reg, priv->dc_reg + DC_MAP_CONF_VAL(ptr));
+
+ reg = ipureadl(priv->dc_reg + DC_MAP_CONF_PTR(map));
+ reg &= ~(0x1f << ((16 * (map & 0x1)) + (5 * byte_num)));
+ reg |= ptr << ((16 * (map & 0x1)) + (5 * byte_num));
+ ipuwritel("dc", reg, priv->dc_reg + DC_MAP_CONF_PTR(map));
+}
+
+static void ipu_dc_map_clear(struct ipu_dc_priv *priv, int map)
+{
+ u32 reg = ipureadl(priv->dc_reg + DC_MAP_CONF_PTR(map));
+
+ ipuwritel("dc", reg & ~(0xffff << (16 * (map & 0x1))),
+ priv->dc_reg + DC_MAP_CONF_PTR(map));
+}
+
+struct ipu_dc *ipu_dc_get(struct ipu_soc *ipu, int channel)
+{
+ struct ipu_dc_priv *priv = ipu->dc_priv;
+ struct ipu_dc *dc;
+
+ if (channel >= IPU_DC_NUM_CHANNELS)
+ return ERR_PTR(-ENODEV);
+
+ dc = &priv->channels[channel];
+
+ if (dc->in_use)
+ return ERR_PTR(-EBUSY);
+
+ dc->in_use = true;
+
+ return dc;
+}
+EXPORT_SYMBOL_GPL(ipu_dc_get);
+
+void ipu_dc_put(struct ipu_dc *dc)
+{
+ dc->in_use = false;
+}
+EXPORT_SYMBOL_GPL(ipu_dc_put);
+
+int ipu_dc_init(struct ipu_soc *ipu, struct device_d *dev,
+ void __iomem *base, void __iomem *template_base)
+{
+ struct ipu_dc_priv *priv;
+ static int channel_offsets[] = { 0, 0x1c, 0x38, 0x54, 0x58, 0x5c,
+ 0x78, 0, 0x94, 0xb4};
+ int i;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->dev = dev;
+ priv->ipu = ipu;
+ priv->dc_reg = base;
+ priv->dc_tmpl_reg = template_base;
+
+ for (i = 0; i < IPU_DC_NUM_CHANNELS; i++) {
+ priv->channels[i].chno = i;
+ priv->channels[i].priv = priv;
+ priv->channels[i].base = priv->dc_reg + channel_offsets[i];
+ }
+
+ ipuwritel("dc", DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(1) |
+ DC_WR_CH_CONF_PROG_DI_ID,
+ priv->channels[1].base + DC_WR_CH_CONF);
+ ipuwritel("dc", DC_WR_CH_CONF_WORD_SIZE_24 | DC_WR_CH_CONF_DISP_ID_PARALLEL(0),
+ priv->channels[5].base + DC_WR_CH_CONF);
+
+ ipuwritel("dc", DC_GEN_SYNC_1_6_SYNC | DC_GEN_SYNC_PRIORITY_1, priv->dc_reg + DC_GEN);
+
+ ipu->dc_priv = priv;
+
+ dev_dbg(dev, "DC base: 0x%p template base: 0x%p\n",
+ base, template_base);
+
+ /* rgb24 */
+ ipu_dc_map_clear(priv, IPU_DC_MAP_RGB24);
+ ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 0, 7, 0xff); /* blue */
+ ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 1, 15, 0xff); /* green */
+ ipu_dc_map_config(priv, IPU_DC_MAP_RGB24, 2, 23, 0xff); /* red */
+
+ /* rgb565 */
+ ipu_dc_map_clear(priv, IPU_DC_MAP_RGB565);
+ ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 0, 4, 0xf8); /* blue */
+ ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 1, 10, 0xfc); /* green */
+ ipu_dc_map_config(priv, IPU_DC_MAP_RGB565, 2, 15, 0xf8); /* red */
+
+ /* gbr24 */
+ ipu_dc_map_clear(priv, IPU_DC_MAP_GBR24);
+ ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 2, 15, 0xff); /* green */
+ ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 1, 7, 0xff); /* blue */
+ ipu_dc_map_config(priv, IPU_DC_MAP_GBR24, 0, 23, 0xff); /* red */
+
+ /* bgr666 */
+ ipu_dc_map_clear(priv, IPU_DC_MAP_BGR666);
+ ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 0, 5, 0xfc); /* blue */
+ ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 1, 11, 0xfc); /* green */
+ ipu_dc_map_config(priv, IPU_DC_MAP_BGR666, 2, 17, 0xfc); /* red */
+
+ /* bgr24 */
+ ipu_dc_map_clear(priv, IPU_DC_MAP_BGR24);
+ ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 2, 7, 0xff); /* red */
+ ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 1, 15, 0xff); /* green */
+ ipu_dc_map_config(priv, IPU_DC_MAP_BGR24, 0, 23, 0xff); /* blue */
+
+ return 0;
+}
+
+void ipu_dc_exit(struct ipu_soc *ipu)
+{
+}
diff --git a/drivers/video/imx-ipu-v3/ipu-di.c b/drivers/video/imx-ipu-v3/ipu-di.c
new file mode 100644
index 0000000000..e3338d09ba
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipu-di.c
@@ -0,0 +1,762 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <common.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <asm-generic/div64.h>
+#include <malloc.h>
+
+#include "imx-ipu-v3.h"
+#include "ipu-prv.h"
+
+struct ipu_di {
+ void __iomem *base;
+ int id;
+ u32 module;
+ struct clk *clk_di; /* display input clock */
+ struct clk *clk_ipu; /* IPU bus clock */
+ struct clk clk_di_pixel; /* resulting pixel clock */
+ char *clk_name;
+ const char *di_parent_names[2];
+ bool inuse;
+ unsigned long clkflags;
+ struct ipu_soc *ipu;
+};
+
+struct di_sync_config {
+ int run_count;
+ int run_src;
+ int offset_count;
+ int offset_src;
+ int repeat_count;
+ int cnt_clr_src;
+ int cnt_polarity_gen_en;
+ int cnt_polarity_clr_src;
+ int cnt_polarity_trigger_src;
+ int cnt_up;
+ int cnt_down;
+};
+
+enum di_pins {
+ DI_PIN11 = 0,
+ DI_PIN12 = 1,
+ DI_PIN13 = 2,
+ DI_PIN14 = 3,
+ DI_PIN15 = 4,
+ DI_PIN16 = 5,
+ DI_PIN17 = 6,
+ DI_PIN_CS = 7,
+
+ DI_PIN_SER_CLK = 0,
+ DI_PIN_SER_RS = 1,
+};
+
+enum di_sync_wave {
+ DI_SYNC_NONE = 0,
+ DI_SYNC_CLK = 1,
+ DI_SYNC_INT_HSYNC = 2,
+ DI_SYNC_HSYNC = 3,
+ DI_SYNC_VSYNC = 4,
+ DI_SYNC_DE = 6,
+};
+
+#define SYNC_WAVE 0
+
+#define DI_GENERAL 0x0000
+#define DI_BS_CLKGEN0 0x0004
+#define DI_BS_CLKGEN1 0x0008
+#define DI_SW_GEN0(gen) (0x000c + 4 * ((gen) - 1))
+#define DI_SW_GEN1(gen) (0x0030 + 4 * ((gen) - 1))
+#define DI_STP_REP(gen) (0x0148 + 4 * (((gen) - 1)/2))
+#define DI_SYNC_AS_GEN 0x0054
+#define DI_DW_GEN(gen) (0x0058 + 4 * (gen))
+#define DI_DW_SET(gen, set) (0x0088 + 4 * ((gen) + 0xc * (set)))
+#define DI_SER_CONF 0x015c
+#define DI_SSC 0x0160
+#define DI_POL 0x0164
+#define DI_AW0 0x0168
+#define DI_AW1 0x016c
+#define DI_SCR_CONF 0x0170
+#define DI_STAT 0x0174
+
+#define DI_SW_GEN0_RUN_COUNT(x) ((x) << 19)
+#define DI_SW_GEN0_RUN_SRC(x) ((x) << 16)
+#define DI_SW_GEN0_OFFSET_COUNT(x) ((x) << 3)
+#define DI_SW_GEN0_OFFSET_SRC(x) ((x) << 0)
+
+#define DI_SW_GEN1_CNT_POL_GEN_EN(x) ((x) << 29)
+#define DI_SW_GEN1_CNT_CLR_SRC(x) ((x) << 25)
+#define DI_SW_GEN1_CNT_POL_TRIGGER_SRC(x) ((x) << 12)
+#define DI_SW_GEN1_CNT_POL_CLR_SRC(x) ((x) << 9)
+#define DI_SW_GEN1_CNT_DOWN(x) ((x) << 16)
+#define DI_SW_GEN1_CNT_UP(x) (x)
+#define DI_SW_GEN1_AUTO_RELOAD (0x10000000)
+
+#define DI_DW_GEN_ACCESS_SIZE_OFFSET 24
+#define DI_DW_GEN_COMPONENT_SIZE_OFFSET 16
+
+#define DI_GEN_POLARITY_1 (1 << 0)
+#define DI_GEN_POLARITY_2 (1 << 1)
+#define DI_GEN_POLARITY_3 (1 << 2)
+#define DI_GEN_POLARITY_4 (1 << 3)
+#define DI_GEN_POLARITY_5 (1 << 4)
+#define DI_GEN_POLARITY_6 (1 << 5)
+#define DI_GEN_POLARITY_7 (1 << 6)
+#define DI_GEN_POLARITY_8 (1 << 7)
+#define DI_GEN_POLARITY_DISP_CLK (1 << 17)
+#define DI_GEN_DI_CLK_EXT (1 << 20)
+#define DI_GEN_DI_VSYNC_EXT (1 << 21)
+
+#define DI_POL_DRDY_DATA_POLARITY (1 << 7)
+#define DI_POL_DRDY_POLARITY_15 (1 << 4)
+
+#define DI_VSYNC_SEL_OFFSET 13
+
+static inline u32 ipu_di_read(struct ipu_di *di, unsigned offset)
+{
+ return readl(di->base + offset);
+}
+
+static inline void ipu_di_write(struct ipu_di *di, u32 value, unsigned offset)
+{
+ ipuwritel("di", value, di->base + offset);
+}
+
+static int ipu_di_clk_calc_div(unsigned long inrate, unsigned long outrate)
+{
+ u64 tmp = inrate;
+ int div;
+
+ tmp *= 16;
+
+ do_div(tmp, outrate);
+
+ div = tmp;
+
+ if (div < 0x10)
+ div = 0x10;
+
+#ifdef WTF_IS_THIS
+ /*
+ * Freescale has this in their Kernel. It is neither clear what
+ * it does nor why it does it
+ */
+ if (div & 0x10)
+ div &= ~0x7;
+ else {
+ /* Round up divider if it gets us closer to desired pix clk */
+ if ((div & 0xC) == 0xC) {
+ div += 0x10;
+ div &= ~0xF;
+ }
+ }
+#endif
+ return div;
+}
+
+static unsigned long clk_di_recalc_rate(struct clk *clk,
+ unsigned long parent_rate)
+{
+ struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
+ unsigned long outrate;
+ u32 div = ipu_di_read(di, DI_BS_CLKGEN0);
+
+ if (div < 0x10)
+ div = 0x10;
+
+ outrate = (parent_rate / div) * 16;
+
+ return outrate;
+}
+
+static long clk_di_round_rate(struct clk *clk, unsigned long rate,
+ unsigned long *prate)
+{
+ struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
+ unsigned long outrate;
+ int div;
+ u32 val;
+
+ div = ipu_di_clk_calc_div(*prate, rate);
+
+ outrate = (*prate / div) * 16;
+
+ val = ipu_di_read(di, DI_GENERAL);
+
+ if (!(val & DI_GEN_DI_CLK_EXT) && outrate > *prate / 2)
+ outrate = *prate / 2;
+
+ dev_dbg(di->ipu->dev,
+ "%s: inrate: %ld div: 0x%08x outrate: %ld wanted: %ld\n",
+ __func__, *prate, div, outrate, rate);
+
+ return outrate;
+}
+
+static int clk_di_set_rate(struct clk *clk, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
+ int div;
+ u32 clkgen0;
+
+ clkgen0 = ipu_di_read(di, DI_BS_CLKGEN0) & ~0xfff;
+
+ div = ipu_di_clk_calc_div(parent_rate, rate);
+
+ ipu_di_write(di, clkgen0 | div, DI_BS_CLKGEN0);
+
+ dev_dbg(di->ipu->dev, "%s: inrate: %ld desired: %ld div: 0x%08x\n",
+ __func__, parent_rate, rate, div);
+ return 0;
+}
+
+static int clk_di_get_parent(struct clk *clk)
+{
+ struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
+ u32 val;
+
+ val = ipu_di_read(di, DI_GENERAL);
+
+ return val & DI_GEN_DI_CLK_EXT ? 1 : 0;
+}
+
+static int clk_di_set_parent(struct clk *clk, u8 index)
+{
+ struct ipu_di *di = container_of(clk, struct ipu_di, clk_di_pixel);
+ u32 val;
+
+ val = ipu_di_read(di, DI_GENERAL);
+
+ if (index)
+ val |= DI_GEN_DI_CLK_EXT;
+ else
+ val &= ~DI_GEN_DI_CLK_EXT;
+
+ ipu_di_write(di, val, DI_GENERAL);
+
+ return 0;
+}
+
+static struct clk_ops clk_di_ops = {
+ .round_rate = clk_di_round_rate,
+ .set_rate = clk_di_set_rate,
+ .recalc_rate = clk_di_recalc_rate,
+ .set_parent = clk_di_set_parent,
+ .get_parent = clk_di_get_parent,
+};
+
+static void ipu_di_data_wave_config(struct ipu_di *di,
+ int wave_gen,
+ int access_size, int component_size)
+{
+ u32 reg;
+ reg = (access_size << DI_DW_GEN_ACCESS_SIZE_OFFSET) |
+ (component_size << DI_DW_GEN_COMPONENT_SIZE_OFFSET);
+ ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
+}
+
+static void ipu_di_data_pin_config(struct ipu_di *di, int wave_gen, int di_pin,
+ int set, int up, int down)
+{
+ u32 reg;
+
+ reg = ipu_di_read(di, DI_DW_GEN(wave_gen));
+ reg &= ~(0x3 << (di_pin * 2));
+ reg |= set << (di_pin * 2);
+ ipu_di_write(di, reg, DI_DW_GEN(wave_gen));
+
+ ipu_di_write(di, (down << 16) | up, DI_DW_SET(wave_gen, set));
+}
+
+static void ipu_di_sync_config(struct ipu_di *di, struct di_sync_config *config,
+ int start, int count)
+{
+ u32 reg;
+ int i;
+
+ for (i = 0; i < count; i++) {
+ struct di_sync_config *c = &config[i];
+ int wave_gen = start + i + 1;
+
+ if ((c->run_count >= 0x1000) || (c->offset_count >= 0x1000) ||
+ (c->repeat_count >= 0x1000) ||
+ (c->cnt_up >= 0x400) ||
+ (c->cnt_down >= 0x400)) {
+ dev_err(di->ipu->dev, "DI%d counters out of range.\n",
+ di->id);
+ return;
+ }
+
+ reg = DI_SW_GEN0_RUN_COUNT(c->run_count) |
+ DI_SW_GEN0_RUN_SRC(c->run_src) |
+ DI_SW_GEN0_OFFSET_COUNT(c->offset_count) |
+ DI_SW_GEN0_OFFSET_SRC(c->offset_src);
+ ipu_di_write(di, reg, DI_SW_GEN0(wave_gen));
+
+ reg = DI_SW_GEN1_CNT_POL_GEN_EN(c->cnt_polarity_gen_en) |
+ DI_SW_GEN1_CNT_CLR_SRC(c->cnt_clr_src) |
+ DI_SW_GEN1_CNT_POL_TRIGGER_SRC(
+ c->cnt_polarity_trigger_src) |
+ DI_SW_GEN1_CNT_POL_CLR_SRC(c->cnt_polarity_clr_src) |
+ DI_SW_GEN1_CNT_DOWN(c->cnt_down) |
+ DI_SW_GEN1_CNT_UP(c->cnt_up);
+
+ /* Enable auto reload */
+ if (c->repeat_count == 0)
+ reg |= DI_SW_GEN1_AUTO_RELOAD;
+
+ ipu_di_write(di, reg, DI_SW_GEN1(wave_gen));
+
+ reg = ipu_di_read(di, DI_STP_REP(wave_gen));
+ reg &= ~(0xffff << (16 * ((wave_gen - 1) & 0x1)));
+ reg |= c->repeat_count << (16 * ((wave_gen - 1) & 0x1));
+ ipu_di_write(di, reg, DI_STP_REP(wave_gen));
+ }
+}
+
+static void ipu_di_sync_config_interlaced(struct ipu_di *di,
+ struct ipu_di_signal_cfg *sig)
+{
+ u32 h_total = sig->width + sig->h_sync_width +
+ sig->h_start_width + sig->h_end_width;
+ u32 v_total = sig->height + sig->v_sync_width +
+ sig->v_start_width + sig->v_end_width;
+ u32 reg;
+ struct di_sync_config cfg[] = {
+ {
+ .run_count = h_total / 2 - 1,
+ .run_src = DI_SYNC_CLK,
+ }, {
+ .run_count = h_total - 11,
+ .run_src = DI_SYNC_CLK,
+ .cnt_down = 4,
+ }, {
+ .run_count = v_total * 2 - 1,
+ .run_src = DI_SYNC_INT_HSYNC,
+ .offset_count = 1,
+ .offset_src = DI_SYNC_INT_HSYNC,
+ .cnt_down = 4,
+ }, {
+ .run_count = v_total / 2 - 1,
+ .run_src = DI_SYNC_HSYNC,
+ .offset_count = sig->v_start_width,
+ .offset_src = DI_SYNC_HSYNC,
+ .repeat_count = 2,
+ .cnt_clr_src = DI_SYNC_VSYNC,
+ }, {
+ .run_src = DI_SYNC_HSYNC,
+ .repeat_count = sig->height / 2,
+ .cnt_clr_src = 4,
+ }, {
+ .run_count = v_total - 1,
+ .run_src = DI_SYNC_HSYNC,
+ }, {
+ .run_count = v_total / 2 - 1,
+ .run_src = DI_SYNC_HSYNC,
+ .offset_count = 9,
+ .offset_src = DI_SYNC_HSYNC,
+ .repeat_count = 2,
+ .cnt_clr_src = DI_SYNC_VSYNC,
+ }, {
+ .run_src = DI_SYNC_CLK,
+ .offset_count = sig->h_start_width,
+ .offset_src = DI_SYNC_CLK,
+ .repeat_count = sig->width,
+ .cnt_clr_src = 5,
+ }, {
+ .run_count = v_total - 1,
+ .run_src = DI_SYNC_INT_HSYNC,
+ .offset_count = v_total / 2,
+ .offset_src = DI_SYNC_INT_HSYNC,
+ .cnt_clr_src = DI_SYNC_HSYNC,
+ .cnt_down = 4,
+ }
+ };
+
+ ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
+
+ /* set gentime select and tag sel */
+ reg = ipu_di_read(di, DI_SW_GEN1(9));
+ reg &= 0x1FFFFFFF;
+ reg |= (3 - 1) << 29 | 0x00008000;
+ ipu_di_write(di, reg, DI_SW_GEN1(9));
+
+ ipu_di_write(di, v_total / 2 - 1, DI_SCR_CONF);
+}
+
+static void ipu_di_sync_config_noninterlaced(struct ipu_di *di,
+ struct ipu_di_signal_cfg *sig, int div)
+{
+ u32 h_total = sig->width + sig->h_sync_width + sig->h_start_width +
+ sig->h_end_width;
+ u32 v_total = sig->height + sig->v_sync_width + sig->v_start_width +
+ sig->v_end_width;
+ struct di_sync_config cfg[] = {
+ {
+ /* 1: INT_HSYNC */
+ .run_count = h_total - 1,
+ .run_src = DI_SYNC_CLK,
+ } , {
+ /* PIN2: HSYNC */
+ .run_count = h_total - 1,
+ .run_src = DI_SYNC_CLK,
+ .offset_count = div * sig->v_to_h_sync,
+ .offset_src = DI_SYNC_CLK,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_CLK,
+ .cnt_down = sig->h_sync_width * 2,
+ } , {
+ /* PIN3: VSYNC */
+ .run_count = v_total - 1,
+ .run_src = DI_SYNC_INT_HSYNC,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
+ .cnt_down = sig->v_sync_width * 2,
+ } , {
+ /* 4: Line Active */
+ .run_src = DI_SYNC_HSYNC,
+ .offset_count = sig->v_sync_width + sig->v_start_width,
+ .offset_src = DI_SYNC_HSYNC,
+ .repeat_count = sig->height,
+ .cnt_clr_src = DI_SYNC_VSYNC,
+ } , {
+ /* 5: Pixel Active, referenced by DC */
+ .run_src = DI_SYNC_CLK,
+ .offset_count = sig->h_sync_width + sig->h_start_width,
+ .offset_src = DI_SYNC_CLK,
+ .repeat_count = sig->width,
+ .cnt_clr_src = 5, /* Line Active */
+ } , {
+ /* unused */
+ } , {
+ /* unused */
+ } , {
+ /* unused */
+ } , {
+ /* unused */
+ },
+ };
+ /* can't use #7 and #8 for line active and pixel active counters */
+ struct di_sync_config cfg_vga[] = {
+ {
+ /* 1: INT_HSYNC */
+ .run_count = h_total - 1,
+ .run_src = DI_SYNC_CLK,
+ } , {
+ /* 2: VSYNC */
+ .run_count = v_total - 1,
+ .run_src = DI_SYNC_INT_HSYNC,
+ } , {
+ /* 3: Line Active */
+ .run_src = DI_SYNC_INT_HSYNC,
+ .offset_count = sig->v_sync_width + sig->v_start_width,
+ .offset_src = DI_SYNC_INT_HSYNC,
+ .repeat_count = sig->height,
+ .cnt_clr_src = 3 /* VSYNC */,
+ } , {
+ /* PIN4: HSYNC for VGA via TVEv2 on TQ MBa53 */
+ .run_count = h_total - 1,
+ .run_src = DI_SYNC_CLK,
+ .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
+ .offset_src = DI_SYNC_CLK,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_CLK,
+ .cnt_down = sig->h_sync_width * 2,
+ } , {
+ /* 5: Pixel Active signal to DC */
+ .run_src = DI_SYNC_CLK,
+ .offset_count = sig->h_sync_width + sig->h_start_width,
+ .offset_src = DI_SYNC_CLK,
+ .repeat_count = sig->width,
+ .cnt_clr_src = 4, /* Line Active */
+ } , {
+ /* PIN6: VSYNC for VGA via TVEv2 on TQ MBa53 */
+ .run_count = v_total - 1,
+ .run_src = DI_SYNC_INT_HSYNC,
+ .offset_count = 1, /* magic value from Freescale TVE driver */
+ .offset_src = DI_SYNC_INT_HSYNC,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
+ .cnt_down = sig->v_sync_width * 2,
+ } , {
+ /* PIN4: HSYNC for VGA via TVEv2 on i.MX53-QSB */
+ .run_count = h_total - 1,
+ .run_src = DI_SYNC_CLK,
+ .offset_count = div * sig->v_to_h_sync + 18, /* magic value from Freescale TVE driver */
+ .offset_src = DI_SYNC_CLK,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_CLK,
+ .cnt_down = sig->h_sync_width * 2,
+ } , {
+ /* PIN6: VSYNC for VGA via TVEv2 on i.MX53-QSB */
+ .run_count = v_total - 1,
+ .run_src = DI_SYNC_INT_HSYNC,
+ .offset_count = 1, /* magic value from Freescale TVE driver */
+ .offset_src = DI_SYNC_INT_HSYNC,
+ .cnt_polarity_gen_en = 1,
+ .cnt_polarity_trigger_src = DI_SYNC_INT_HSYNC,
+ .cnt_down = sig->v_sync_width * 2,
+ } , {
+ /* unused */
+ },
+ };
+
+ ipu_di_write(di, v_total - 1, DI_SCR_CONF);
+ if (sig->hsync_pin == 2 && sig->vsync_pin == 3)
+ ipu_di_sync_config(di, cfg, 0, ARRAY_SIZE(cfg));
+ else
+ ipu_di_sync_config(di, cfg_vga, 0, ARRAY_SIZE(cfg_vga));
+}
+
+int ipu_di_init_sync_panel(struct ipu_di *di, struct ipu_di_signal_cfg *sig)
+{
+ u32 reg;
+ u32 di_gen, vsync_cnt;
+ u32 div;
+ u32 h_total, v_total;
+ int ret;
+ unsigned long round;
+ struct clk *parent;
+
+ dev_dbg(di->ipu->dev, "disp %d: panel size = %d x %d, pixelclock = %ld\n",
+ di->id, sig->width, sig->height, sig->pixelclock);
+
+ if ((sig->v_sync_width == 0) || (sig->h_sync_width == 0))
+ return -EINVAL;
+
+ if (sig->clkflags & IPU_DI_CLKMODE_EXT)
+ parent = di->clk_di;
+ else
+ parent = di->clk_ipu;
+
+ ret = clk_set_parent(&di->clk_di_pixel, parent);
+ if (ret) {
+ dev_err(di->ipu->dev,
+ "setting pixel clock to parent %s failed with %d\n",
+ parent->name, ret);
+ return ret;
+ }
+
+ if (sig->clkflags & IPU_DI_CLKMODE_SYNC) {
+ ret = clk_set_rate(clk_get_parent(parent), sig->pixelclock);
+ round = sig->pixelclock;
+ } else if (sig->clkflags & IPU_DI_CLKMODE_NON_FRACTIONAL) {
+ unsigned div;
+
+ round = clk_get_rate(parent);
+ div = DIV_ROUND_CLOSEST(round, sig->pixelclock);
+ round = round / div;
+ } else {
+ round = sig->pixelclock;
+ }
+
+ ret = clk_set_rate(&di->clk_di_pixel, round);
+
+ h_total = sig->width + sig->h_sync_width + sig->h_start_width +
+ sig->h_end_width;
+ v_total = sig->height + sig->v_sync_width + sig->v_start_width +
+ sig->v_end_width;
+
+ div = ipu_di_read(di, DI_BS_CLKGEN0) & 0xfff;
+ div = div / 16; /* Now divider is integer portion */
+
+ /* Setup pixel clock timing */
+ /* Down time is half of period */
+ ipu_di_write(di, (div << 16), DI_BS_CLKGEN1);
+
+ ipu_di_data_wave_config(di, SYNC_WAVE, div - 1, div - 1);
+ ipu_di_data_pin_config(di, SYNC_WAVE, DI_PIN15, 3, 0, div * 2);
+
+ di_gen = ipu_di_read(di, DI_GENERAL) & DI_GEN_DI_CLK_EXT;
+ di_gen |= DI_GEN_DI_VSYNC_EXT;
+
+ if (sig->interlaced) {
+ ipu_di_sync_config_interlaced(di, sig);
+
+ /* set y_sel = 1 */
+ di_gen |= 0x10000000;
+ di_gen |= DI_GEN_POLARITY_5;
+ di_gen |= DI_GEN_POLARITY_8;
+
+ vsync_cnt = 7;
+
+ if (sig->Hsync_pol)
+ di_gen |= DI_GEN_POLARITY_3;
+ if (sig->Vsync_pol)
+ di_gen |= DI_GEN_POLARITY_2;
+ } else {
+ ipu_di_sync_config_noninterlaced(di, sig, div);
+
+ vsync_cnt = 3;
+ if (di->id == 1)
+ /*
+ * TODO: change only for TVEv2, parallel display
+ * uses pin 2 / 3
+ */
+ if (!(sig->hsync_pin == 2 && sig->vsync_pin == 3))
+ vsync_cnt = 6;
+
+ if (sig->Hsync_pol) {
+ if (sig->hsync_pin == 2)
+ di_gen |= DI_GEN_POLARITY_2;
+ else if (sig->hsync_pin == 4)
+ di_gen |= DI_GEN_POLARITY_4;
+ else if (sig->hsync_pin == 7)
+ di_gen |= DI_GEN_POLARITY_7;
+ }
+ if (sig->Vsync_pol) {
+ if (sig->vsync_pin == 3)
+ di_gen |= DI_GEN_POLARITY_3;
+ else if (sig->vsync_pin == 6)
+ di_gen |= DI_GEN_POLARITY_6;
+ else if (sig->vsync_pin == 8)
+ di_gen |= DI_GEN_POLARITY_8;
+ }
+ }
+
+ if (!sig->clk_pol)
+ di_gen |= DI_GEN_POLARITY_DISP_CLK;
+
+ ipu_di_write(di, di_gen, DI_GENERAL);
+
+ ipu_di_write(di, (--vsync_cnt << DI_VSYNC_SEL_OFFSET) | 0x00000002,
+ DI_SYNC_AS_GEN);
+
+ reg = ipu_di_read(di, DI_POL);
+ reg &= ~(DI_POL_DRDY_DATA_POLARITY | DI_POL_DRDY_POLARITY_15);
+
+ if (sig->enable_pol)
+ reg |= DI_POL_DRDY_POLARITY_15;
+ if (sig->data_pol)
+ reg |= DI_POL_DRDY_DATA_POLARITY;
+
+ ipu_di_write(di, reg, DI_POL);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_init_sync_panel);
+
+int ipu_di_enable(struct ipu_di *di)
+{
+ int ret = clk_enable(&di->clk_di_pixel);
+ if (ret)
+ return ret;
+
+ ipu_module_enable(di->ipu, di->module);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_enable);
+
+int ipu_di_disable(struct ipu_di *di)
+{
+ ipu_module_disable(di->ipu, di->module);
+
+ clk_disable(&di->clk_di_pixel);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_di_disable);
+
+int ipu_di_get_num(struct ipu_di *di)
+{
+ return di->id;
+}
+EXPORT_SYMBOL_GPL(ipu_di_get_num);
+
+struct ipu_di *ipu_di_get(struct ipu_soc *ipu, int disp)
+{
+ struct ipu_di *di;
+
+ if (disp > 1)
+ return ERR_PTR(-EINVAL);
+
+ di = ipu->di_priv[disp];
+
+ if (di->inuse) {
+ di = ERR_PTR(-EBUSY);
+ goto out;
+ }
+
+ di->inuse = true;
+out:
+ return di;
+}
+EXPORT_SYMBOL_GPL(ipu_di_get);
+
+void ipu_di_put(struct ipu_di *di)
+{
+ di->inuse = false;
+}
+EXPORT_SYMBOL_GPL(ipu_di_put);
+
+int ipu_di_init(struct ipu_soc *ipu, struct device_d *dev, int id,
+ void __iomem *base,
+ u32 module, struct clk *clk_ipu)
+{
+ struct ipu_di *di;
+ int ret;
+
+ if (id > 1)
+ return -ENODEV;
+
+ di = xzalloc(sizeof(*di));
+
+ ipu->di_priv[id] = di;
+
+ di->clk_di = clk_get(dev, id ? "di1" : "di0");
+ if (IS_ERR(di->clk_di))
+ return PTR_ERR(di->clk_di);
+
+ di->module = module;
+ di->id = id;
+ di->clk_ipu = clk_ipu;
+ di->base = base;
+
+ di->di_parent_names[0] = di->clk_ipu->name;
+ di->di_parent_names[1] = di->clk_di->name;
+
+ ipu_di_write(di, 0x10, DI_BS_CLKGEN0);
+
+ di->clk_di_pixel.parent_names = di->di_parent_names;
+ di->clk_name = asprintf("%s_di%d_pixel",
+ dev_name(dev), id);
+ if (!di->clk_name)
+ return -ENOMEM;
+
+ di->clk_di_pixel.ops = &clk_di_ops;
+ di->clk_di_pixel.num_parents = 2;
+ di->clk_di_pixel.name = di->clk_name;
+ ret = clk_register(&di->clk_di_pixel);
+ if (ret)
+ goto failed_clk_register;
+
+ dev_dbg(dev, "DI%d base: 0x%p\n", id, base);
+ di->inuse = false;
+ di->ipu = ipu;
+
+ return 0;
+
+failed_clk_register:
+
+ free(di->clk_name);
+
+ return ret;
+}
+
+void ipu_di_exit(struct ipu_soc *ipu, int id)
+{
+}
diff --git a/drivers/video/imx-ipu-v3/ipu-dmfc.c b/drivers/video/imx-ipu-v3/ipu-dmfc.c
new file mode 100644
index 0000000000..7b54e25001
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipu-dmfc.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <common.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include "imx-ipu-v3.h"
+#include "ipu-prv.h"
+
+#define DMFC_RD_CHAN 0x0000
+#define DMFC_WR_CHAN 0x0004
+#define DMFC_WR_CHAN_DEF 0x0008
+#define DMFC_DP_CHAN 0x000c
+#define DMFC_DP_CHAN_DEF 0x0010
+#define DMFC_GENERAL1 0x0014
+#define DMFC_GENERAL2 0x0018
+#define DMFC_IC_CTRL 0x001c
+#define DMFC_STAT 0x0020
+
+#define DMFC_WR_CHAN_1_28 0
+#define DMFC_WR_CHAN_2_41 8
+#define DMFC_WR_CHAN_1C_42 16
+#define DMFC_WR_CHAN_2C_43 24
+
+#define DMFC_DP_CHAN_5B_23 0
+#define DMFC_DP_CHAN_5F_27 8
+#define DMFC_DP_CHAN_6B_24 16
+#define DMFC_DP_CHAN_6F_29 24
+
+#define DMFC_FIFO_SIZE_64 (3 << 3)
+#define DMFC_FIFO_SIZE_128 (2 << 3)
+#define DMFC_FIFO_SIZE_256 (1 << 3)
+#define DMFC_FIFO_SIZE_512 (0 << 3)
+
+#define DMFC_SEGMENT(x) ((x & 0x7) << 0)
+#define DMFC_BURSTSIZE_128 (0 << 6)
+#define DMFC_BURSTSIZE_64 (1 << 6)
+#define DMFC_BURSTSIZE_32 (2 << 6)
+#define DMFC_BURSTSIZE_16 (3 << 6)
+
+struct dmfc_channel_data {
+ int ipu_channel;
+ unsigned long channel_reg;
+ unsigned long shift;
+ unsigned eot_shift;
+ unsigned max_fifo_lines;
+};
+
+static const struct dmfc_channel_data dmfcdata[] = {
+ {
+ .ipu_channel = IPUV3_CHANNEL_MEM_BG_SYNC,
+ .channel_reg = DMFC_DP_CHAN,
+ .shift = DMFC_DP_CHAN_5B_23,
+ .eot_shift = 20,
+ .max_fifo_lines = 3,
+ }, {
+ .ipu_channel = 24,
+ .channel_reg = DMFC_DP_CHAN,
+ .shift = DMFC_DP_CHAN_6B_24,
+ .eot_shift = 22,
+ .max_fifo_lines = 1,
+ }, {
+ .ipu_channel = IPUV3_CHANNEL_MEM_FG_SYNC,
+ .channel_reg = DMFC_DP_CHAN,
+ .shift = DMFC_DP_CHAN_5F_27,
+ .eot_shift = 21,
+ .max_fifo_lines = 2,
+ }, {
+ .ipu_channel = IPUV3_CHANNEL_MEM_DC_SYNC,
+ .channel_reg = DMFC_WR_CHAN,
+ .shift = DMFC_WR_CHAN_1_28,
+ .eot_shift = 16,
+ .max_fifo_lines = 2,
+ }, {
+ .ipu_channel = 29,
+ .channel_reg = DMFC_DP_CHAN,
+ .shift = DMFC_DP_CHAN_6F_29,
+ .eot_shift = 23,
+ .max_fifo_lines = 1,
+ },
+};
+
+#define DMFC_NUM_CHANNELS ARRAY_SIZE(dmfcdata)
+
+struct ipu_dmfc_priv;
+
+struct dmfc_channel {
+ unsigned slots;
+ unsigned slotmask;
+ unsigned segment;
+ int burstsize;
+ struct ipu_soc *ipu;
+ struct ipu_dmfc_priv *priv;
+ const struct dmfc_channel_data *data;
+};
+
+struct ipu_dmfc_priv {
+ struct ipu_soc *ipu;
+ struct device_d *dev;
+ struct dmfc_channel channels[DMFC_NUM_CHANNELS];
+ unsigned long bandwidth_per_slot;
+ void __iomem *base;
+ int use_count;
+};
+
+int ipu_dmfc_enable_channel(struct dmfc_channel *dmfc)
+{
+ struct ipu_dmfc_priv *priv = dmfc->priv;
+
+ if (!priv->use_count)
+ ipu_module_enable(priv->ipu, IPU_CONF_DMFC_EN);
+
+ priv->use_count++;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_enable_channel);
+
+void ipu_dmfc_disable_channel(struct dmfc_channel *dmfc)
+{
+ struct ipu_dmfc_priv *priv = dmfc->priv;
+
+ priv->use_count--;
+
+ if (!priv->use_count)
+ ipu_module_disable(priv->ipu, IPU_CONF_DMFC_EN);
+
+ if (priv->use_count < 0)
+ priv->use_count = 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_disable_channel);
+
+static int ipu_dmfc_setup_channel(struct dmfc_channel *dmfc, int slots,
+ int segment, int burstsize)
+{
+ struct ipu_dmfc_priv *priv = dmfc->priv;
+ u32 val, field;
+
+ dev_dbg(priv->dev,
+ "dmfc: using %d slots starting from segment %d for IPU channel %d\n",
+ slots, segment, dmfc->data->ipu_channel);
+
+ if (!dmfc)
+ return -EINVAL;
+
+ switch (slots) {
+ case 1:
+ field = DMFC_FIFO_SIZE_64;
+ break;
+ case 2:
+ field = DMFC_FIFO_SIZE_128;
+ break;
+ case 4:
+ field = DMFC_FIFO_SIZE_256;
+ break;
+ case 8:
+ field = DMFC_FIFO_SIZE_512;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (burstsize) {
+ case 16:
+ field |= DMFC_BURSTSIZE_16;
+ break;
+ case 32:
+ field |= DMFC_BURSTSIZE_32;
+ break;
+ case 64:
+ field |= DMFC_BURSTSIZE_64;
+ break;
+ case 128:
+ field |= DMFC_BURSTSIZE_128;
+ break;
+ }
+
+ field |= DMFC_SEGMENT(segment);
+
+ val = ipureadl(priv->base + dmfc->data->channel_reg);
+
+ val &= ~(0xff << dmfc->data->shift);
+ val |= field << dmfc->data->shift;
+
+ ipuwritel("dmfc", val, priv->base + dmfc->data->channel_reg);
+
+ dmfc->slots = slots;
+ dmfc->segment = segment;
+ dmfc->burstsize = burstsize;
+ dmfc->slotmask = ((1 << slots) - 1) << segment;
+
+ return 0;
+}
+
+static int dmfc_bandwidth_to_slots(struct ipu_dmfc_priv *priv,
+ unsigned long bandwidth)
+{
+ int slots = 1;
+
+ while (slots * priv->bandwidth_per_slot < bandwidth)
+ slots *= 2;
+
+ return slots;
+}
+
+static int dmfc_find_slots(struct ipu_dmfc_priv *priv, int slots)
+{
+ unsigned slotmask_need, slotmask_used = 0;
+ int i, segment = 0;
+
+ slotmask_need = (1 << slots) - 1;
+
+ for (i = 0; i < DMFC_NUM_CHANNELS; i++)
+ slotmask_used |= priv->channels[i].slotmask;
+
+ while (slotmask_need <= 0xff) {
+ if (!(slotmask_used & slotmask_need))
+ return segment;
+
+ slotmask_need <<= 1;
+ segment++;
+ }
+
+ return -EBUSY;
+}
+
+void ipu_dmfc_free_bandwidth(struct dmfc_channel *dmfc)
+{
+ struct ipu_dmfc_priv *priv = dmfc->priv;
+ int i;
+
+ dev_dbg(priv->dev, "dmfc: freeing %d slots starting from segment %d\n",
+ dmfc->slots, dmfc->segment);
+
+ if (!dmfc->slots)
+ return;
+
+ dmfc->slotmask = 0;
+ dmfc->slots = 0;
+ dmfc->segment = 0;
+
+ for (i = 0; i < DMFC_NUM_CHANNELS; i++)
+ priv->channels[i].slotmask = 0;
+
+ for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
+ if (priv->channels[i].slots > 0) {
+ priv->channels[i].segment =
+ dmfc_find_slots(priv, priv->channels[i].slots);
+ priv->channels[i].slotmask =
+ ((1 << priv->channels[i].slots) - 1) <<
+ priv->channels[i].segment;
+ }
+ }
+
+ for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
+ if (priv->channels[i].slots > 0)
+ ipu_dmfc_setup_channel(&priv->channels[i],
+ priv->channels[i].slots,
+ priv->channels[i].segment,
+ priv->channels[i].burstsize);
+ }
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_free_bandwidth);
+
+int ipu_dmfc_alloc_bandwidth(struct dmfc_channel *dmfc,
+ unsigned long bandwidth_pixel_per_second, int burstsize)
+{
+ struct ipu_dmfc_priv *priv = dmfc->priv;
+ int slots = dmfc_bandwidth_to_slots(priv, bandwidth_pixel_per_second);
+ int segment = -1, ret = 0;
+
+ dev_dbg(priv->dev, "dmfc: trying to allocate %ldMpixel/s for IPU channel %d\n",
+ bandwidth_pixel_per_second / 1000000,
+ dmfc->data->ipu_channel);
+
+ ipu_dmfc_free_bandwidth(dmfc);
+
+ if (slots > 8) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* For the MEM_BG channel, first try to allocate twice the slots */
+ if (dmfc->data->ipu_channel == IPUV3_CHANNEL_MEM_BG_SYNC)
+ segment = dmfc_find_slots(priv, slots * 2);
+ else if (slots < 2)
+ /* Always allocate at least 128*4 bytes (2 slots) */
+ slots = 2;
+
+ if (segment >= 0)
+ slots *= 2;
+ else
+ segment = dmfc_find_slots(priv, slots);
+ if (segment < 0) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ipu_dmfc_setup_channel(dmfc, slots, segment, burstsize);
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_alloc_bandwidth);
+
+int ipu_dmfc_init_channel(struct dmfc_channel *dmfc, int width)
+{
+ struct ipu_dmfc_priv *priv = dmfc->priv;
+ u32 dmfc_gen1;
+
+ dmfc_gen1 = ipureadl(priv->base + DMFC_GENERAL1);
+
+ if ((dmfc->slots * 64 * 4) / width > dmfc->data->max_fifo_lines)
+ dmfc_gen1 |= 1 << dmfc->data->eot_shift;
+ else
+ dmfc_gen1 &= ~(1 << dmfc->data->eot_shift);
+
+ ipuwritel("dmfc", dmfc_gen1, priv->base + DMFC_GENERAL1);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_init_channel);
+
+struct dmfc_channel *ipu_dmfc_get(struct ipu_soc *ipu, int ipu_channel)
+{
+ struct ipu_dmfc_priv *priv = ipu->dmfc_priv;
+ int i;
+
+ for (i = 0; i < DMFC_NUM_CHANNELS; i++)
+ if (dmfcdata[i].ipu_channel == ipu_channel)
+ return &priv->channels[i];
+ return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_get);
+
+void ipu_dmfc_put(struct dmfc_channel *dmfc)
+{
+ ipu_dmfc_free_bandwidth(dmfc);
+}
+EXPORT_SYMBOL_GPL(ipu_dmfc_put);
+
+int ipu_dmfc_init(struct ipu_soc *ipu, struct device_d *dev, void __iomem *base,
+ struct clk *ipu_clk)
+{
+ struct ipu_dmfc_priv *priv;
+ int i;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->base = base;
+
+ priv->dev = dev;
+ priv->ipu = ipu;
+
+ ipu->dmfc_priv = priv;
+
+ for (i = 0; i < DMFC_NUM_CHANNELS; i++) {
+ priv->channels[i].priv = priv;
+ priv->channels[i].ipu = ipu;
+ priv->channels[i].data = &dmfcdata[i];
+ }
+
+ ipuwritel("dmfc", 0x0, priv->base + DMFC_WR_CHAN);
+ ipuwritel("dmfc", 0x0, priv->base + DMFC_DP_CHAN);
+
+ /*
+ * We have a total bandwidth of clkrate * 4pixel divided
+ * into 8 slots.
+ */
+ priv->bandwidth_per_slot = clk_get_rate(ipu_clk) * 4 / 8;
+
+ dev_dbg(dev, "dmfc: 8 slots with %ldMpixel/s bandwidth each\n",
+ priv->bandwidth_per_slot / 1000000);
+
+ ipuwritel("dmfc", 0x202020f6, priv->base + DMFC_WR_CHAN_DEF);
+ ipuwritel("dmfc", 0x2020f6f6, priv->base + DMFC_DP_CHAN_DEF);
+ ipuwritel("dmfc", 0x00000003, priv->base + DMFC_GENERAL1);
+
+ return 0;
+}
+
+void ipu_dmfc_exit(struct ipu_soc *ipu)
+{
+}
diff --git a/drivers/video/imx-ipu-v3/ipu-dp.c b/drivers/video/imx-ipu-v3/ipu-dp.c
new file mode 100644
index 0000000000..8829954db0
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipu-dp.c
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#include <common.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <malloc.h>
+
+#include "imx-ipu-v3.h"
+#include "ipu-prv.h"
+
+#define DP_SYNC 0
+#define DP_ASYNC0 0x60
+#define DP_ASYNC1 0xBC
+
+#define DP_COM_CONF 0x0
+#define DP_GRAPH_WIND_CTRL 0x0004
+#define DP_FG_POS 0x0008
+#define DP_CSC_A_0 0x0044
+#define DP_CSC_A_1 0x0048
+#define DP_CSC_A_2 0x004C
+#define DP_CSC_A_3 0x0050
+#define DP_CSC_0 0x0054
+#define DP_CSC_1 0x0058
+
+#define DP_COM_CONF_FG_EN (1 << 0)
+#define DP_COM_CONF_GWSEL (1 << 1)
+#define DP_COM_CONF_GWAM (1 << 2)
+#define DP_COM_CONF_GWCKE (1 << 3)
+#define DP_COM_CONF_CSC_DEF_MASK (3 << 8)
+#define DP_COM_CONF_CSC_DEF_OFFSET 8
+#define DP_COM_CONF_CSC_DEF_FG (3 << 8)
+#define DP_COM_CONF_CSC_DEF_BG (2 << 8)
+#define DP_COM_CONF_CSC_DEF_BOTH (1 << 8)
+
+#define IPUV3_NUM_FLOWS 3
+
+struct ipu_dp_priv;
+
+struct ipu_dp {
+ u32 flow;
+ bool in_use;
+ bool foreground;
+ enum ipu_color_space in_cs;
+};
+
+struct ipu_flow {
+ struct ipu_dp foreground;
+ struct ipu_dp background;
+ enum ipu_color_space out_cs;
+ void __iomem *base;
+ struct ipu_dp_priv *priv;
+};
+
+struct ipu_dp_priv {
+ struct ipu_soc *ipu;
+ struct device_d *dev;
+ void __iomem *base;
+ struct ipu_flow flow[IPUV3_NUM_FLOWS];
+ int use_count;
+};
+
+static u32 ipu_dp_flow_base[] = {DP_SYNC, DP_ASYNC0, DP_ASYNC1};
+
+static inline struct ipu_flow *to_flow(struct ipu_dp *dp)
+{
+ if (dp->foreground)
+ return container_of(dp, struct ipu_flow, foreground);
+ else
+ return container_of(dp, struct ipu_flow, background);
+}
+
+int ipu_dp_set_global_alpha(struct ipu_dp *dp, bool enable,
+ u8 alpha, bool bg_chan)
+{
+ struct ipu_flow *flow = to_flow(dp);
+ struct ipu_dp_priv *priv = flow->priv;
+ u32 reg;
+
+ reg = ipureadl(flow->base + DP_COM_CONF);
+ if (bg_chan)
+ reg &= ~DP_COM_CONF_GWSEL;
+ else
+ reg |= DP_COM_CONF_GWSEL;
+ ipuwritel("dp", reg, flow->base + DP_COM_CONF);
+
+ if (enable) {
+ reg = ipureadl(flow->base + DP_GRAPH_WIND_CTRL) & 0x00FFFFFFL;
+ ipuwritel("dp", reg | ((u32) alpha << 24),
+ flow->base + DP_GRAPH_WIND_CTRL);
+
+ reg = ipureadl(flow->base + DP_COM_CONF);
+ ipuwritel("dp", reg | DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
+ } else {
+ reg = ipureadl(flow->base + DP_COM_CONF);
+ ipuwritel("dp", reg & ~DP_COM_CONF_GWAM, flow->base + DP_COM_CONF);
+ }
+
+ ipu_srm_dp_sync_update(priv->ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_set_global_alpha);
+
+int ipu_dp_set_window_pos(struct ipu_dp *dp, u16 x_pos, u16 y_pos)
+{
+ struct ipu_flow *flow = to_flow(dp);
+ struct ipu_dp_priv *priv = flow->priv;
+
+ ipuwritel("dp", (x_pos << 16) | y_pos, flow->base + DP_FG_POS);
+
+ ipu_srm_dp_sync_update(priv->ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_set_window_pos);
+
+static void ipu_dp_csc_init(struct ipu_flow *flow,
+ enum ipu_color_space in,
+ enum ipu_color_space out,
+ u32 place)
+{
+ u32 reg;
+
+ reg = ipureadl(flow->base + DP_COM_CONF);
+ reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+
+ if (in == out) {
+ ipuwritel("dp", reg, flow->base + DP_COM_CONF);
+ return;
+ }
+
+ if (in == IPUV3_COLORSPACE_RGB && out == IPUV3_COLORSPACE_YUV) {
+ ipuwritel("dp", 0x099 | (0x12d << 16), flow->base + DP_CSC_A_0);
+ ipuwritel("dp", 0x03a | (0x3a9 << 16), flow->base + DP_CSC_A_1);
+ ipuwritel("dp", 0x356 | (0x100 << 16), flow->base + DP_CSC_A_2);
+ ipuwritel("dp", 0x100 | (0x329 << 16), flow->base + DP_CSC_A_3);
+ ipuwritel("dp", 0x3d6 | (0x0000 << 16) | (2 << 30),
+ flow->base + DP_CSC_0);
+ ipuwritel("dp", 0x200 | (2 << 14) | (0x200 << 16) | (2 << 30),
+ flow->base + DP_CSC_1);
+ } else {
+ ipuwritel("dp", 0x095 | (0x000 << 16), flow->base + DP_CSC_A_0);
+ ipuwritel("dp", 0x0cc | (0x095 << 16), flow->base + DP_CSC_A_1);
+ ipuwritel("dp", 0x3ce | (0x398 << 16), flow->base + DP_CSC_A_2);
+ ipuwritel("dp", 0x095 | (0x0ff << 16), flow->base + DP_CSC_A_3);
+ ipuwritel("dp", 0x000 | (0x3e42 << 16) | (1 << 30),
+ flow->base + DP_CSC_0);
+ ipuwritel("dp", 0x10a | (1 << 14) | (0x3dd6 << 16) | (1 << 30),
+ flow->base + DP_CSC_1);
+ }
+
+ reg |= place;
+
+ ipuwritel("dp", reg, flow->base + DP_COM_CONF);
+}
+
+int ipu_dp_setup_channel(struct ipu_dp *dp,
+ enum ipu_color_space in,
+ enum ipu_color_space out)
+{
+ struct ipu_flow *flow = to_flow(dp);
+ struct ipu_dp_priv *priv = flow->priv;
+
+ dp->in_cs = in;
+
+ if (!dp->foreground)
+ flow->out_cs = out;
+
+ if (flow->foreground.in_cs == flow->background.in_cs) {
+ /*
+ * foreground and background are of same colorspace, put
+ * colorspace converter after combining unit.
+ */
+ ipu_dp_csc_init(flow, flow->foreground.in_cs, flow->out_cs,
+ DP_COM_CONF_CSC_DEF_BOTH);
+ } else {
+ if (flow->foreground.in_cs == flow->out_cs)
+ /*
+ * foreground identical to output, apply color
+ * conversion on background
+ */
+ ipu_dp_csc_init(flow, flow->background.in_cs,
+ flow->out_cs, DP_COM_CONF_CSC_DEF_BG);
+ else
+ ipu_dp_csc_init(flow, flow->foreground.in_cs,
+ flow->out_cs, DP_COM_CONF_CSC_DEF_FG);
+ }
+
+ ipu_srm_dp_sync_update(priv->ipu);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_setup_channel);
+
+int ipu_dp_enable_channel(struct ipu_dp *dp)
+{
+ struct ipu_flow *flow = to_flow(dp);
+ struct ipu_dp_priv *priv = flow->priv;
+
+ if (!priv->use_count)
+ ipu_module_enable(priv->ipu, IPU_CONF_DP_EN);
+
+ priv->use_count++;
+
+ if (dp->foreground) {
+ u32 reg;
+
+ reg = ipureadl(flow->base + DP_COM_CONF);
+ reg |= DP_COM_CONF_FG_EN;
+ ipuwritel("dp", reg, flow->base + DP_COM_CONF);
+
+ ipu_srm_dp_sync_update(priv->ipu);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_enable_channel);
+
+void ipu_dp_disable_channel(struct ipu_dp *dp)
+{
+ struct ipu_flow *flow = to_flow(dp);
+ struct ipu_dp_priv *priv = flow->priv;
+
+ priv->use_count--;
+
+ if (dp->foreground) {
+ u32 reg, csc;
+
+ reg = ipureadl(flow->base + DP_COM_CONF);
+ csc = reg & DP_COM_CONF_CSC_DEF_MASK;
+ if (csc == DP_COM_CONF_CSC_DEF_FG)
+ reg &= ~DP_COM_CONF_CSC_DEF_MASK;
+
+ reg &= ~DP_COM_CONF_FG_EN;
+ ipuwritel("dp", reg, flow->base + DP_COM_CONF);
+
+ ipuwritel("dp", 0, flow->base + DP_FG_POS);
+ ipu_srm_dp_sync_update(priv->ipu);
+ }
+
+ if (!priv->use_count)
+ ipu_module_disable(priv->ipu, IPU_CONF_DP_EN);
+
+ if (priv->use_count < 0)
+ priv->use_count = 0;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_disable_channel);
+
+struct ipu_dp *ipu_dp_get(struct ipu_soc *ipu, unsigned int flow)
+{
+ struct ipu_dp_priv *priv = ipu->dp_priv;
+ struct ipu_dp *dp;
+
+ if ((flow >> 1) >= IPUV3_NUM_FLOWS)
+ return ERR_PTR(-EINVAL);
+
+ if (flow & 1)
+ dp = &priv->flow[flow >> 1].foreground;
+ else
+ dp = &priv->flow[flow >> 1].background;
+
+ if (dp->in_use)
+ return ERR_PTR(-EBUSY);
+
+ dp->in_use = true;
+
+ return dp;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_get);
+
+void ipu_dp_put(struct ipu_dp *dp)
+{
+ dp->in_use = false;
+}
+EXPORT_SYMBOL_GPL(ipu_dp_put);
+
+int ipu_dp_init(struct ipu_soc *ipu, struct device_d *dev, void __iomem *base)
+{
+ struct ipu_dp_priv *priv;
+ int i;
+
+ priv = xzalloc(sizeof(*priv));
+ priv->dev = dev;
+ priv->ipu = ipu;
+
+ ipu->dp_priv = priv;
+
+ priv->base = base;
+
+ for (i = 0; i < IPUV3_NUM_FLOWS; i++) {
+ priv->flow[i].foreground.foreground = true;
+ priv->flow[i].base = priv->base + ipu_dp_flow_base[i];
+ priv->flow[i].priv = priv;
+ }
+
+ return 0;
+}
+
+void ipu_dp_exit(struct ipu_soc *ipu)
+{
+}
diff --git a/drivers/video/imx-ipu-v3/ipu-prv.h b/drivers/video/imx-ipu-v3/ipu-prv.h
new file mode 100644
index 0000000000..44d7802521
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipu-prv.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
+ * Copyright (C) 2005-2009 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+#ifndef __IPU_PRV_H__
+#define __IPU_PRV_H__
+
+struct ipu_soc;
+
+#include "imx-ipu-v3.h"
+
+#define IPU_PIX_FMT_GBR24 v4l2_fourcc('G', 'B', 'R', '3')
+
+#define IPUV3_CHANNEL_CSI0 0
+#define IPUV3_CHANNEL_CSI1 1
+#define IPUV3_CHANNEL_CSI2 2
+#define IPUV3_CHANNEL_CSI3 3
+#define IPUV3_CHANNEL_MEM_BG_SYNC 23
+#define IPUV3_CHANNEL_MEM_FG_SYNC 27
+#define IPUV3_CHANNEL_MEM_DC_SYNC 28
+#define IPUV3_CHANNEL_MEM_FG_SYNC_ALPHA 31
+#define IPUV3_CHANNEL_MEM_DC_ASYNC 41
+#define IPUV3_CHANNEL_ROT_ENC_MEM 45
+#define IPUV3_CHANNEL_ROT_VF_MEM 46
+#define IPUV3_CHANNEL_ROT_PP_MEM 47
+#define IPUV3_CHANNEL_ROT_ENC_MEM_OUT 48
+#define IPUV3_CHANNEL_ROT_VF_MEM_OUT 49
+#define IPUV3_CHANNEL_ROT_PP_MEM_OUT 50
+#define IPUV3_CHANNEL_MEM_BG_SYNC_ALPHA 51
+
+#define IPU_MCU_T_DEFAULT 8
+#define IPU_CM_IDMAC_REG_OFS 0x00008000
+#define IPU_CM_IC_REG_OFS 0x00020000
+#define IPU_CM_IRT_REG_OFS 0x00028000
+#define IPU_CM_CSI0_REG_OFS 0x00030000
+#define IPU_CM_CSI1_REG_OFS 0x00038000
+#define IPU_CM_SMFC_REG_OFS 0x00050000
+#define IPU_CM_DC_REG_OFS 0x00058000
+#define IPU_CM_DMFC_REG_OFS 0x00060000
+
+/* Register addresses */
+/* IPU Common registers */
+#define IPU_CM_REG(offset) (offset)
+
+#define IPU_CONF IPU_CM_REG(0)
+
+#define IPU_SRM_PRI1 IPU_CM_REG(0x00a0)
+#define IPU_SRM_PRI2 IPU_CM_REG(0x00a4)
+#define IPU_FS_PROC_FLOW1 IPU_CM_REG(0x00a8)
+#define IPU_FS_PROC_FLOW2 IPU_CM_REG(0x00ac)
+#define IPU_FS_PROC_FLOW3 IPU_CM_REG(0x00b0)
+#define IPU_FS_DISP_FLOW1 IPU_CM_REG(0x00b4)
+#define IPU_FS_DISP_FLOW2 IPU_CM_REG(0x00b8)
+#define IPU_SKIP IPU_CM_REG(0x00bc)
+#define IPU_DISP_ALT_CONF IPU_CM_REG(0x00c0)
+#define IPU_DISP_GEN IPU_CM_REG(0x00c4)
+#define IPU_DISP_ALT1 IPU_CM_REG(0x00c8)
+#define IPU_DISP_ALT2 IPU_CM_REG(0x00cc)
+#define IPU_DISP_ALT3 IPU_CM_REG(0x00d0)
+#define IPU_DISP_ALT4 IPU_CM_REG(0x00d4)
+#define IPU_SNOOP IPU_CM_REG(0x00d8)
+#define IPU_MEM_RST IPU_CM_REG(0x00dc)
+#define IPU_PM IPU_CM_REG(0x00e0)
+#define IPU_GPR IPU_CM_REG(0x00e4)
+#define IPU_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
+#define IPU_CHA_CUR_BUF(ch) IPU_CM_REG(0x023C + 4 * ((ch) / 32))
+#define IPU_ALT_CUR_BUF0 IPU_CM_REG(0x0244)
+#define IPU_ALT_CUR_BUF1 IPU_CM_REG(0x0248)
+#define IPU_SRM_STAT IPU_CM_REG(0x024C)
+#define IPU_PROC_TASK_STAT IPU_CM_REG(0x0250)
+#define IPU_DISP_TASK_STAT IPU_CM_REG(0x0254)
+#define IPU_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0268 + 4 * ((ch) / 32))
+#define IPU_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0270 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_BUF0_RDY(ch) IPU_CM_REG(0x0278 + 4 * ((ch) / 32))
+#define IPU_ALT_CHA_BUF1_RDY(ch) IPU_CM_REG(0x0280 + 4 * ((ch) / 32))
+
+#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * (n))
+#define IPU_INT_STAT(n) IPU_CM_REG(0x0200 + 4 * (n))
+
+#define IPU_DI0_COUNTER_RELEASE (1 << 24)
+#define IPU_DI1_COUNTER_RELEASE (1 << 25)
+
+#define IPU_IDMAC_REG(offset) (offset)
+
+#define IDMAC_CONF IPU_IDMAC_REG(0x0000)
+#define IDMAC_CHA_EN(ch) IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
+#define IDMAC_SEP_ALPHA IPU_IDMAC_REG(0x000c)
+#define IDMAC_ALT_SEP_ALPHA IPU_IDMAC_REG(0x0010)
+#define IDMAC_CHA_PRI(ch) IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
+#define IDMAC_WM_EN(ch) IPU_IDMAC_REG(0x001c + 4 * ((ch) / 32))
+#define IDMAC_CH_LOCK_EN_1 IPU_IDMAC_REG(0x0024)
+#define IDMAC_CH_LOCK_EN_2 IPU_IDMAC_REG(0x0028)
+#define IDMAC_SUB_ADDR_0 IPU_IDMAC_REG(0x002c)
+#define IDMAC_SUB_ADDR_1 IPU_IDMAC_REG(0x0030)
+#define IDMAC_SUB_ADDR_2 IPU_IDMAC_REG(0x0034)
+#define IDMAC_BAND_EN(ch) IPU_IDMAC_REG(0x0040 + 4 * ((ch) / 32))
+#define IDMAC_CHA_BUSY(ch) IPU_IDMAC_REG(0x0100 + 4 * ((ch) / 32))
+
+#define IPU_NUM_IRQS (32 * 15)
+
+enum ipu_modules {
+ IPU_CONF_CSI0_EN = (1 << 0),
+ IPU_CONF_CSI1_EN = (1 << 1),
+ IPU_CONF_IC_EN = (1 << 2),
+ IPU_CONF_ROT_EN = (1 << 3),
+ IPU_CONF_ISP_EN = (1 << 4),
+ IPU_CONF_DP_EN = (1 << 5),
+ IPU_CONF_DI0_EN = (1 << 6),
+ IPU_CONF_DI1_EN = (1 << 7),
+ IPU_CONF_SMFC_EN = (1 << 8),
+ IPU_CONF_DC_EN = (1 << 9),
+ IPU_CONF_DMFC_EN = (1 << 10),
+
+ IPU_CONF_VDI_EN = (1 << 12),
+
+ IPU_CONF_IDMAC_DIS = (1 << 22),
+
+ IPU_CONF_IC_DMFC_SEL = (1 << 25),
+ IPU_CONF_IC_DMFC_SYNC = (1 << 26),
+ IPU_CONF_VDI_DMFC_SYNC = (1 << 27),
+
+ IPU_CONF_CSI0_DATA_SOURCE = (1 << 28),
+ IPU_CONF_CSI1_DATA_SOURCE = (1 << 29),
+ IPU_CONF_IC_INPUT = (1 << 30),
+ IPU_CONF_CSI_SEL = (1 << 31),
+};
+
+struct ipuv3_channel {
+ unsigned int num;
+
+ bool enabled;
+ bool busy;
+
+ struct ipu_soc *ipu;
+};
+
+struct ipu_dc_priv;
+struct ipu_dmfc_priv;
+struct ipu_di;
+struct ipu_devtype;
+
+struct ipu_soc {
+ struct device_d *dev;
+ const struct ipu_devtype *devtype;
+ enum ipuv3_type ipu_type;
+ spinlock_t lock;
+ struct mutex channel_lock;
+
+ void __iomem *base;
+ void __iomem *cm_reg;
+ void __iomem *idmac_reg;
+ struct ipu_ch_param __iomem *cpmem_base;
+
+ int usecount;
+
+ struct clk *clk;
+
+ struct ipuv3_channel channel[64];
+
+ int irq_sync;
+ int irq_err;
+ struct irq_domain *domain;
+
+ struct ipu_dc_priv *dc_priv;
+ struct ipu_dp_priv *dp_priv;
+ struct ipu_dmfc_priv *dmfc_priv;
+ struct ipu_di *di_priv[2];
+};
+
+void ipu_srm_dp_sync_update(struct ipu_soc *ipu);
+
+int ipu_module_enable(struct ipu_soc *ipu, u32 mask);
+int ipu_module_disable(struct ipu_soc *ipu, u32 mask);
+
+int ipu_di_init(struct ipu_soc *ipu, struct device_d *dev, int id,
+ void __iomem *base, u32 module, struct clk *ipu_clk);
+void ipu_di_exit(struct ipu_soc *ipu, int id);
+
+int ipu_dmfc_init(struct ipu_soc *ipu, struct device_d *dev, void __iomem *base,
+ struct clk *ipu_clk);
+void ipu_dmfc_exit(struct ipu_soc *ipu);
+
+int ipu_dp_init(struct ipu_soc *ipu, struct device_d *dev, void __iomem *base);
+void ipu_dp_exit(struct ipu_soc *ipu);
+
+int ipu_dc_init(struct ipu_soc *ipu, struct device_d *dev, void __iomem *base,
+ void __iomem *template_base);
+void ipu_dc_exit(struct ipu_soc *ipu);
+
+int ipu_cpmem_init(struct ipu_soc *ipu, struct device_d *dev, void __iomem *base);
+void ipu_cpmem_exit(struct ipu_soc *ipu);
+
+#endif /* __IPU_PRV_H__ */
diff --git a/drivers/video/imx-ipu-v3/ipufb.c b/drivers/video/imx-ipu-v3/ipufb.c
new file mode 100644
index 0000000000..14a099e14a
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipufb.c
@@ -0,0 +1,353 @@
+/*
+ * Freescale i.MX Frame Buffer device driver
+ *
+ * Copyright (C) 2004 Sascha Hauer, Pengutronix
+ * Based on acornfb.c Copyright (C) Russell King.
+ *
+ * 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.
+ *
+ */
+#define pr_fmt(fmt) "IPU: " fmt
+
+#include <common.h>
+#include <fb.h>
+#include <io.h>
+#include <driver.h>
+#include <malloc.h>
+#include <errno.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/div64.h>
+#include <asm/mmu.h>
+
+#include "imx-ipu-v3.h"
+#include "ipuv3-plane.h"
+
+/*
+ * These are the bitfields for each
+ * display depth that we support.
+ */
+struct ipufb_rgb {
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+};
+
+struct ipufb_info {
+ void __iomem *regs;
+
+ struct clk *ahb_clk;
+ struct clk *ipg_clk;
+ struct clk *per_clk;
+
+ struct fb_videomode *mode;
+
+ struct fb_info info;
+ struct device_d *dev;
+
+ /* plane[0] is the full plane, plane[1] is the partial plane */
+ struct ipu_plane *plane[2];
+
+ void (*enable)(int enable);
+
+ unsigned int di_clkflags;
+ u32 interface_pix_fmt;
+ struct ipu_dc *dc;
+ struct ipu_di *di;
+
+ struct list_head list;
+ char *name;
+ int id;
+
+ struct ipu_output *output;
+};
+
+static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf)
+{
+ chan &= 0xffff;
+ chan >>= 16 - bf->length;
+ return chan << bf->offset;
+}
+
+static LIST_HEAD(ipu_outputs);
+static LIST_HEAD(ipu_fbs);
+
+int ipu_register_output(struct ipu_output *ouput)
+{
+ list_add_tail(&ouput->list, &ipu_outputs);
+
+ return 0;
+}
+
+static int ipu_register_fb(struct ipufb_info *ipufb)
+{
+ list_add_tail(&ipufb->list, &ipu_fbs);
+
+ return 0;
+}
+
+int ipu_crtc_mode_set(struct ipufb_info *fbi,
+ struct fb_videomode *mode,
+ int x, int y)
+{
+ struct fb_info *info = &fbi->info;
+ int ret;
+ struct ipu_di_signal_cfg sig_cfg = {};
+ u32 out_pixel_fmt;
+
+ dev_info(fbi->dev, "%s: mode->xres: %d\n", __func__,
+ mode->xres);
+ dev_info(fbi->dev, "%s: mode->yres: %d\n", __func__,
+ mode->yres);
+
+ out_pixel_fmt = fbi->output->out_pixel_fmt;
+
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
+ sig_cfg.Hsync_pol = 1;
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
+ sig_cfg.Vsync_pol = 1;
+
+ sig_cfg.enable_pol = 1;
+ sig_cfg.clk_pol = 1;
+ sig_cfg.width = mode->xres;
+ sig_cfg.height = mode->yres;
+ sig_cfg.pixel_fmt = out_pixel_fmt;
+ sig_cfg.h_start_width = mode->left_margin;
+ sig_cfg.h_sync_width = mode->hsync_len;
+ sig_cfg.h_end_width = mode->right_margin;
+
+ sig_cfg.v_start_width = mode->upper_margin;
+ sig_cfg.v_sync_width = mode->vsync_len;
+ sig_cfg.v_end_width = mode->lower_margin;
+ sig_cfg.pixelclock = PICOS2KHZ(mode->pixclock) * 1000UL;
+ sig_cfg.clkflags = fbi->output->di_clkflags;
+
+ sig_cfg.v_to_h_sync = 0;
+
+ sig_cfg.hsync_pin = 2;
+ sig_cfg.vsync_pin = 3;
+
+ ret = ipu_dc_init_sync(fbi->dc, fbi->di, sig_cfg.interlaced,
+ out_pixel_fmt, mode->xres);
+ if (ret) {
+ dev_err(fbi->dev,
+ "initializing display controller failed with %d\n",
+ ret);
+ return ret;
+ }
+
+ ret = ipu_di_init_sync_panel(fbi->di, &sig_cfg);
+ if (ret) {
+ dev_err(fbi->dev,
+ "initializing panel failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = ipu_plane_mode_set(fbi->plane[0], mode, info, DRM_FORMAT_XRGB8888,
+ 0, 0, mode->xres, mode->yres,
+ x, y, mode->xres, mode->yres);
+ if (ret) {
+ dev_err(fbi->dev, "initialising plane failed with %s\n", strerror(-ret));
+ return ret;
+ }
+
+ ret = ipu_di_enable(fbi->di);
+ if (ret) {
+ dev_err(fbi->dev, "enabling di failed with %s\n", strerror(-ret));
+ return ret;
+ }
+
+ ipu_dc_enable_channel(fbi->dc);
+
+ ipu_plane_enable(fbi->plane[0]);
+
+ return 0;
+}
+
+static void ipufb_enable_controller(struct fb_info *info)
+{
+ struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
+ struct ipu_output *output = fbi->output;
+
+ if (output->ops->prepare)
+ output->ops->prepare(output, info->mode, fbi->id);
+
+ ipu_crtc_mode_set(fbi, info->mode, 0, 0);
+
+ if (output->ops->enable)
+ output->ops->enable(output, info->mode, fbi->id);
+}
+
+static void ipufb_disable_controller(struct fb_info *info)
+{
+ struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
+ struct ipu_output *output = fbi->output;
+
+ if (output->ops->disable)
+ output->ops->disable(output);
+
+ ipu_plane_disable(fbi->plane[0]);
+ ipu_dc_disable_channel(fbi->dc);
+ ipu_di_disable(fbi->di);
+
+ if (output->ops->unprepare)
+ output->ops->unprepare(output);
+}
+
+static int ipufb_activate_var(struct fb_info *info)
+{
+ struct ipufb_info *fbi = container_of(info, struct ipufb_info, info);
+
+ info->line_length = info->xres * (info->bits_per_pixel >> 3);
+ fbi->info.screen_base = dma_alloc_coherent(info->line_length * info->yres);
+ if (!fbi->info.screen_base)
+ return -ENOMEM;
+
+ memset(fbi->info.screen_base, 0, info->line_length * info->yres);
+
+ return 0;
+}
+
+static struct fb_ops ipufb_ops = {
+ .fb_enable = ipufb_enable_controller,
+ .fb_disable = ipufb_disable_controller,
+ .fb_activate_var = ipufb_activate_var,
+};
+
+static struct ipufb_info *ipu_output_find_di(struct ipu_output *output)
+{
+ struct ipufb_info *ipufb;
+
+ list_for_each_entry(ipufb, &ipu_fbs, list) {
+ if (!(output->ipu_mask & (1 << ipufb->id)))
+ continue;
+ if (ipufb->output)
+ continue;
+
+ return ipufb;
+ }
+
+ return NULL;
+}
+
+static int ipu_init(void)
+{
+ struct ipu_output *output;
+ struct ipufb_info *ipufb;
+ int ret;
+
+ list_for_each_entry(output, &ipu_outputs, list) {
+ pr_info("found output: %s\n", output->name);
+ ipufb = ipu_output_find_di(output);
+ if (!ipufb) {
+ pr_info("no di found for output %s\n", output->name);
+ continue;
+ }
+ pr_info("using di %s for output %s\n", ipufb->name, output->name);
+
+ ipufb->output = output;
+
+ ipufb->info.edid_i2c_adapter = output->edid_i2c_adapter;
+ if (output->modes) {
+ ipufb->info.modes.modes = output->modes->modes;
+ ipufb->info.modes.num_modes = output->modes->num_modes;
+ }
+
+ ret = register_framebuffer(&ipufb->info);
+ if (ret < 0) {
+ dev_err(ipufb->dev, "failed to register framebuffer\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+late_initcall(ipu_init);
+
+static int ipu_get_resources(struct ipufb_info *fbi,
+ struct ipu_client_platformdata *pdata)
+{
+ struct ipu_soc *ipu = fbi->dev->parent->priv;
+ int ret;
+ int dp = -EINVAL;
+
+ fbi->dc = ipu_dc_get(ipu, pdata->dc);
+ if (IS_ERR(fbi->dc)) {
+ ret = PTR_ERR(fbi->dc);
+ goto err_out;
+ }
+
+ fbi->di = ipu_di_get(ipu, pdata->di);
+ if (IS_ERR(fbi->di)) {
+ ret = PTR_ERR(fbi->di);
+ goto err_out;
+ }
+
+ if (pdata->dp >= 0)
+ dp = IPU_DP_FLOW_SYNC_BG;
+
+ fbi->plane[0] = ipu_plane_init(ipu, pdata->dma[0], dp);
+ ret = ipu_plane_get_resources(fbi->plane[0]);
+ if (ret) {
+ dev_err(fbi->dev, "getting plane 0 resources failed with %d.\n",
+ ret);
+ goto err_out;
+ }
+
+ return 0;
+err_out:
+ return ret;
+}
+
+static int ipufb_probe(struct device_d *dev)
+{
+ struct ipufb_info *fbi;
+ struct fb_info *info;
+ int ret, ipuid;
+ struct ipu_client_platformdata *pdata = dev->platform_data;
+ struct ipu_rgb *ipu_rgb;
+
+ fbi = xzalloc(sizeof(*fbi));
+ info = &fbi->info;
+
+ ipuid = of_alias_get_id(dev->parent->device_node, "ipu");
+ fbi->name = asprintf("ipu%d-di%d", ipuid + 1, pdata->di);
+ fbi->id = ipuid * 2 + pdata->di;
+
+ fbi->dev = dev;
+ info->priv = fbi;
+ info->fbops = &ipufb_ops;
+
+ ipu_rgb = drm_fourcc_to_rgb(DRM_FORMAT_RGB888);
+
+ info->bits_per_pixel = 32;
+ info->red = ipu_rgb->red;
+ info->green = ipu_rgb->green;
+ info->blue = ipu_rgb->blue;
+ info->transp = ipu_rgb->transp;
+
+ dev_dbg(dev, "i.MX Framebuffer driver\n");
+
+ ret = ipu_get_resources(fbi, pdata);
+ if (ret)
+ return ret;
+
+ ret = ipu_register_fb(fbi);
+
+ return ret;
+}
+
+static void ipufb_remove(struct device_d *dev)
+{
+}
+
+static struct driver_d ipufb_driver = {
+ .name = "imx-ipuv3-crtc",
+ .probe = ipufb_probe,
+ .remove = ipufb_remove,
+};
+device_platform_driver(ipufb_driver);
diff --git a/drivers/video/imx-ipu-v3/ipuv3-plane.c b/drivers/video/imx-ipu-v3/ipuv3-plane.c
new file mode 100644
index 0000000000..9dffcfc670
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipuv3-plane.c
@@ -0,0 +1,239 @@
+/*
+ * i.MX IPUv3 DP Overlay Planes
+ *
+ * Copyright (C) 2013 Philipp Zabel, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+#include <common.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <malloc.h>
+#include <fb.h>
+
+#include "ipuv3-plane.h"
+#include "imx-ipu-v3.h"
+
+static int calc_vref(struct fb_videomode *mode)
+{
+ unsigned long htotal, vtotal;
+
+ htotal = mode->left_margin + mode->right_margin + mode->xres + mode->hsync_len;
+ vtotal = mode->upper_margin + mode->lower_margin + mode->yres + mode->vsync_len;
+
+ return DIV_ROUND_UP(PICOS2KHZ(mode->pixclock) * 1000, vtotal * htotal);
+}
+
+static inline int calc_bandwidth(int width, int height, unsigned int vref)
+{
+ return width * height * vref;
+}
+
+int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct fb_info *info,
+ int x, int y)
+{
+ struct ipu_ch_param __iomem *cpmem;
+
+ pr_debug("phys = 0x%p, x = %d, y = %d, line_length = %d\n",
+ info->screen_base, x, y, info->line_length);
+
+ cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
+ ipu_cpmem_set_stride(cpmem, info->line_length);
+ ipu_cpmem_set_buffer(cpmem, 0, (unsigned long)info->screen_base +
+ info->line_length * y + x);
+ ipu_cpmem_set_buffer(cpmem, 1, (unsigned long)info->screen_base +
+ info->line_length * y + x);
+
+ return 0;
+}
+
+int ipu_plane_mode_set(struct ipu_plane *ipu_plane,
+ struct fb_videomode *mode,
+ struct fb_info *info, u32 pixel_format,
+ int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h)
+{
+ struct ipu_ch_param __iomem *cpmem;
+ struct device_d *dev = &info->dev;
+ int ret;
+
+ /* no scaling */
+ if (src_w != crtc_w || src_h != crtc_h)
+ return -EINVAL;
+
+ /* clip to crtc bounds */
+ if (crtc_x < 0) {
+ if (-crtc_x > crtc_w)
+ return -EINVAL;
+ src_x += -crtc_x;
+ src_w -= -crtc_x;
+ crtc_w -= -crtc_x;
+ crtc_x = 0;
+ }
+ if (crtc_y < 0) {
+ if (-crtc_y > crtc_h)
+ return -EINVAL;
+ src_y += -crtc_y;
+ src_h -= -crtc_y;
+ crtc_h -= -crtc_y;
+ crtc_y = 0;
+ }
+ if (crtc_x + crtc_w > mode->xres) {
+ if (crtc_x > mode->xres)
+ return -EINVAL;
+ crtc_w = mode->xres - crtc_x;
+ src_w = crtc_w;
+ }
+ if (crtc_y + crtc_h > mode->yres) {
+ if (crtc_y > mode->yres)
+ return -EINVAL;
+ crtc_h = mode->yres - crtc_y;
+ src_h = crtc_h;
+ }
+ /* full plane minimum width is 13 pixels */
+ if (crtc_w < 13 && (ipu_plane->dp_flow != IPU_DP_FLOW_SYNC_FG))
+ return -EINVAL;
+ if (crtc_h < 2)
+ return -EINVAL;
+
+ switch (ipu_plane->dp_flow) {
+ case IPU_DP_FLOW_SYNC_BG:
+ ret = ipu_dp_setup_channel(ipu_plane->dp,
+ IPUV3_COLORSPACE_RGB,
+ IPUV3_COLORSPACE_RGB);
+ if (ret) {
+ dev_err(dev,
+ "initializing display processor failed with %d\n",
+ ret);
+ return ret;
+ }
+ ipu_dp_set_global_alpha(ipu_plane->dp, 1, 0, 1);
+ break;
+ case IPU_DP_FLOW_SYNC_FG:
+ ipu_dp_setup_channel(ipu_plane->dp,
+ IPUV3_COLORSPACE_RGB,
+ IPUV3_COLORSPACE_UNKNOWN);
+ ipu_dp_set_window_pos(ipu_plane->dp, crtc_x, crtc_y);
+ break;
+ }
+
+ ret = ipu_dmfc_init_channel(ipu_plane->dmfc, crtc_w);
+ if (ret) {
+ dev_err(dev, "initializing dmfc channel failed with %d\n", ret);
+ return ret;
+ }
+
+ ret = ipu_dmfc_alloc_bandwidth(ipu_plane->dmfc,
+ calc_bandwidth(crtc_w, crtc_h,
+ calc_vref(mode)), 64);
+ if (ret) {
+ dev_err(dev, "allocating dmfc bandwidth failed with %d\n", ret);
+ return ret;
+ }
+
+ cpmem = ipu_get_cpmem(ipu_plane->ipu_ch);
+ ipu_ch_param_zero(cpmem);
+ ipu_cpmem_set_resolution(cpmem, src_w, src_h);
+ ret = ipu_cpmem_set_fmt(cpmem, pixel_format);
+ if (ret < 0) {
+ dev_err(dev, "unsupported pixel format 0x%08x\n",
+ pixel_format);
+ return ret;
+ }
+ ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);
+
+ ret = ipu_plane_set_base(ipu_plane, info, src_x, src_y);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+void ipu_plane_put_resources(struct ipu_plane *ipu_plane)
+{
+ if (!IS_ERR_OR_NULL(ipu_plane->dp))
+ ipu_dp_put(ipu_plane->dp);
+ if (!IS_ERR_OR_NULL(ipu_plane->dmfc))
+ ipu_dmfc_put(ipu_plane->dmfc);
+ if (!IS_ERR_OR_NULL(ipu_plane->ipu_ch))
+ ipu_idmac_put(ipu_plane->ipu_ch);
+}
+
+int ipu_plane_get_resources(struct ipu_plane *ipu_plane)
+{
+ int ret;
+
+ ipu_plane->ipu_ch = ipu_idmac_get(ipu_plane->ipu, ipu_plane->dma);
+ if (IS_ERR(ipu_plane->ipu_ch)) {
+ ret = PTR_ERR(ipu_plane->ipu_ch);
+ pr_err("failed to get idmac channel: %d\n", ret);
+ return ret;
+ }
+
+ ipu_plane->dmfc = ipu_dmfc_get(ipu_plane->ipu, ipu_plane->dma);
+ if (IS_ERR(ipu_plane->dmfc)) {
+ ret = PTR_ERR(ipu_plane->dmfc);
+ pr_err("failed to get dmfc: ret %d\n", ret);
+ goto err_out;
+ }
+
+ if (ipu_plane->dp_flow >= 0) {
+ ipu_plane->dp = ipu_dp_get(ipu_plane->ipu, ipu_plane->dp_flow);
+ if (IS_ERR(ipu_plane->dp)) {
+ ret = PTR_ERR(ipu_plane->dp);
+ pr_err("failed to get dp flow: %d\n", ret);
+ goto err_out;
+ }
+ }
+
+ return 0;
+err_out:
+ ipu_plane_put_resources(ipu_plane);
+
+ return ret;
+}
+
+void ipu_plane_enable(struct ipu_plane *ipu_plane)
+{
+ ipu_dmfc_enable_channel(ipu_plane->dmfc);
+ ipu_idmac_enable_channel(ipu_plane->ipu_ch);
+ if (ipu_plane->dp)
+ ipu_dp_enable_channel(ipu_plane->dp);
+
+ ipu_plane->enabled = true;
+}
+
+void ipu_plane_disable(struct ipu_plane *ipu_plane)
+{
+ ipu_plane->enabled = false;
+
+ ipu_idmac_wait_busy(ipu_plane->ipu_ch, 50);
+
+ if (ipu_plane->dp)
+ ipu_dp_disable_channel(ipu_plane->dp);
+ ipu_idmac_disable_channel(ipu_plane->ipu_ch);
+ ipu_dmfc_disable_channel(ipu_plane->dmfc);
+}
+
+struct ipu_plane *ipu_plane_init(struct ipu_soc *ipu,
+ int dma, int dp)
+{
+ struct ipu_plane *ipu_plane;
+
+ ipu_plane = xzalloc(sizeof(*ipu_plane));
+
+ ipu_plane->ipu = ipu;
+ ipu_plane->dma = dma;
+ ipu_plane->dp_flow = dp;
+
+ return ipu_plane;
+}
diff --git a/drivers/video/imx-ipu-v3/ipuv3-plane.h b/drivers/video/imx-ipu-v3/ipuv3-plane.h
new file mode 100644
index 0000000000..3d52f807fe
--- /dev/null
+++ b/drivers/video/imx-ipu-v3/ipuv3-plane.h
@@ -0,0 +1,51 @@
+#ifndef __IPUV3_PLANE_H__
+#define __IPUV3_PLANE_H__
+
+struct drm_plane;
+struct drm_device;
+struct ipu_soc;
+struct drm_crtc;
+struct drm_framebuffer;
+
+struct ipuv3_channel;
+struct dmfc_channel;
+struct ipu_dp;
+
+struct ipu_plane {
+ struct ipu_soc *ipu;
+ struct ipuv3_channel *ipu_ch;
+ struct dmfc_channel *dmfc;
+ struct ipu_dp *dp;
+
+ int dma;
+ int dp_flow;
+
+ int x;
+ int y;
+
+ bool enabled;
+};
+
+struct ipu_plane *ipu_plane_init(struct ipu_soc *ipu,
+ int dma, int dp);
+
+/* Init IDMAC, DMFC, DP */
+int ipu_plane_mode_set(struct ipu_plane *ipu_plane,
+ struct fb_videomode *mode,
+ struct fb_info *info, u32 pixel_format,
+ int crtc_x, int crtc_y,
+ unsigned int crtc_w, unsigned int crtc_h,
+ uint32_t src_x, uint32_t src_y,
+ uint32_t src_w, uint32_t src_h);
+
+void ipu_plane_enable(struct ipu_plane *plane);
+void ipu_plane_disable(struct ipu_plane *plane);
+int ipu_plane_set_base(struct ipu_plane *ipu_plane, struct fb_info *info,
+ int x, int y);
+
+int ipu_plane_get_resources(struct ipu_plane *plane);
+void ipu_plane_put_resources(struct ipu_plane *plane);
+
+int ipu_plane_irq(struct ipu_plane *plane);
+
+#endif
diff --git a/drivers/video/imx.c b/drivers/video/imx.c
index 05c6105c7a..b12c09c8cf 100644
--- a/drivers/video/imx.c
+++ b/drivers/video/imx.c
@@ -294,7 +294,7 @@ static int imxfb_activate_var(struct fb_info *info)
u32 pcr;
int i;
- for (i = 0; i < info->num_modes; i++) {
+ for (i = 0; i < info->modes.num_modes; i++) {
if (!strcmp(fbi->mode[i].mode.name, mode->name)) {
fbi->pcr = fbi->mode[i].pcr;
break;
@@ -551,8 +551,8 @@ static int imxfb_probe(struct device_d *dev)
fbi->enable = pdata->enable;
fbi->dev = dev;
info->priv = fbi;
- info->mode_list = mode_list;
- info->num_modes = pdata->num_modes;
+ info->modes.modes = mode_list;
+ info->modes.num_modes = pdata->num_modes;
info->mode = &pdata->mode->mode;
info->xres = pdata->mode->mode.xres;
info->yres = pdata->mode->mode.yres;
@@ -580,13 +580,8 @@ static int imxfb_probe(struct device_d *dev)
return 0;
}
-static void imxfb_remove(struct device_d *dev)
-{
-}
-
static struct driver_d imxfb_driver = {
.name = "imxfb",
.probe = imxfb_probe,
- .remove = imxfb_remove,
};
device_platform_driver(imxfb_driver);
diff --git a/drivers/video/of_display_timing.c b/drivers/video/of_display_timing.c
new file mode 100644
index 0000000000..5dfd5b3f1c
--- /dev/null
+++ b/drivers/video/of_display_timing.c
@@ -0,0 +1,238 @@
+/*
+ * OF helpers for parsing display timings
+ *
+ * Copyright (c) 2012 Steffen Trumtrar <s.trumtrar@pengutronix.de>, Pengutronix
+ *
+ * based on of_videomode.c by Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ */
+#include <common.h>
+#include <of.h>
+#include <fb.h>
+#include <malloc.h>
+
+void display_timings_release(struct display_timings *disp)
+{
+ free(disp->modes);
+ free(disp);
+}
+EXPORT_SYMBOL_GPL(display_timings_release);
+
+/**
+ * parse_timing_property - parse timing_entry from device_node
+ * @np: device_node with the property
+ * @name: name of the property
+ * @result: will be set to the return value
+ *
+ * DESCRIPTION:
+ * Every display_timing can be specified with either just the typical value or
+ * a range consisting of min/typ/max. This function helps handling this
+ **/
+static int parse_timing_property(const struct device_node *np, const char *name,
+ u32 *res)
+{
+ struct property *prop;
+ int length, cells, ret;
+
+ prop = of_find_property(np, name, &length);
+ if (!prop) {
+ pr_err("%s: could not find property %s\n",
+ np->full_name, name);
+ return -EINVAL;
+ }
+
+ cells = length / sizeof(u32);
+ if (cells == 1) {
+ ret = of_property_read_u32(np, name, res);
+ } else {
+ pr_err("%s: illegal timing specification in %s\n",
+ np->full_name, name);
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+/**
+ * of_parse_display_timing - parse display_timing entry from device_node
+ * @np: device_node with the properties
+ **/
+static int of_parse_display_timing(const struct device_node *np,
+ struct fb_videomode *mode)
+{
+ u32 val = 0, pixelclock = 0;
+ int ret = 0;
+
+ memset(mode, 0, sizeof(*mode));
+
+ ret |= parse_timing_property(np, "hback-porch", &mode->left_margin);
+ ret |= parse_timing_property(np, "hfront-porch", &mode->right_margin);
+ ret |= parse_timing_property(np, "hactive", &mode->xres);
+ ret |= parse_timing_property(np, "hsync-len", &mode->hsync_len);
+ ret |= parse_timing_property(np, "vback-porch", &mode->upper_margin);
+ ret |= parse_timing_property(np, "vfront-porch", &mode->lower_margin);
+ ret |= parse_timing_property(np, "vactive", &mode->yres);
+ ret |= parse_timing_property(np, "vsync-len", &mode->vsync_len);
+ ret |= parse_timing_property(np, "clock-frequency", &pixelclock);
+
+ mode->pixclock = pixelclock ? KHZ2PICOS(pixelclock / 1000) : 0;
+
+ if (!of_property_read_u32(np, "vsync-active", &val))
+ mode->sync |= val ? FB_SYNC_VERT_HIGH_ACT : 0;
+ if (!of_property_read_u32(np, "hsync-active", &val))
+ mode->sync |= val ? FB_SYNC_HOR_HIGH_ACT : 0;
+ if (!of_property_read_u32(np, "de-active", &val))
+ mode->display_flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+ DISPLAY_FLAGS_DE_LOW;
+ if (!of_property_read_u32(np, "pixelclk-active", &val))
+ mode->display_flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+
+ if (ret) {
+ pr_err("%s: error reading timing properties\n",
+ np->full_name);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/**
+ * of_get_display_timing - parse a display_timing entry
+ * @np: device_node with the timing subnode
+ * @name: name of the timing node
+ * @dt: display_timing struct to fill
+ **/
+int of_get_display_timing(struct device_node *np, const char *name,
+ struct fb_videomode *mode)
+{
+ struct device_node *timing_np;
+
+ if (!np) {
+ pr_err("%s: no devicenode given\n", np->full_name);
+ return -EINVAL;
+ }
+
+ timing_np = of_get_child_by_name(np, name);
+ if (!timing_np) {
+ pr_err("%s: could not find node '%s'\n",
+ np->full_name, name);
+ return -ENOENT;
+ }
+
+ return of_parse_display_timing(timing_np, mode);
+}
+EXPORT_SYMBOL_GPL(of_get_display_timing);
+
+/**
+ * of_get_display_timings - parse all display_timing entries from a device_node
+ * @np: device_node with the subnodes
+ **/
+struct display_timings *of_get_display_timings(struct device_node *np)
+{
+ struct device_node *timings_np;
+ struct device_node *entry;
+ struct device_node *native_mode;
+ struct display_timings *disp;
+
+ if (!np) {
+ pr_err("%s: no device node given\n", np->full_name);
+ return NULL;
+ }
+
+ timings_np = of_get_child_by_name(np, "display-timings");
+ if (!timings_np) {
+ pr_debug("%s: could not find display-timings node\n",
+ np->full_name);
+ return NULL;
+ }
+
+ disp = xzalloc(sizeof(*disp));
+
+ entry = of_parse_phandle(timings_np, "native-mode", 0);
+ /* assume first child as native mode if none provided */
+ if (!entry)
+ entry = of_get_next_available_child(np, NULL);
+ /* if there is no child, it is useless to go on */
+ if (!entry) {
+ pr_err("%s: no timing specifications given\n",
+ np->full_name);
+ goto entryfail;
+ }
+
+ pr_debug("%s: using %s as default timing\n",
+ np->full_name, entry->name);
+
+ native_mode = entry;
+
+ disp->num_modes = of_get_child_count(timings_np);
+ if (disp->num_modes == 0) {
+ /* should never happen, as entry was already found above */
+ pr_err("%s: no timings specified\n", np->full_name);
+ goto entryfail;
+ }
+
+ disp->modes = xzalloc(sizeof(struct fb_videomode) * disp->num_modes);
+
+ disp->num_modes = 0;
+ disp->native_mode = 0;
+
+ for_each_child_of_node(timings_np, entry) {
+ struct fb_videomode *mode;
+ int r;
+
+ mode = &disp->modes[disp->num_modes];
+
+ r = of_parse_display_timing(entry, mode);
+ if (r) {
+ /*
+ * to not encourage wrong devicetrees, fail in case of
+ * an error
+ */
+ pr_err("%s: error in timing %d\n",
+ np->full_name, disp->num_modes + 1);
+ goto timingfail;
+ }
+
+ mode->name = xstrdup(entry->name);
+
+ if (native_mode == entry)
+ disp->native_mode = disp->num_modes;
+
+ disp->num_modes++;
+ }
+
+ pr_debug("%s: got %d timings. Using timing #%d as default\n",
+ np->full_name, disp->num_modes,
+ disp->native_mode + 1);
+
+ return disp;
+
+timingfail:
+ display_timings_release(disp);
+entryfail:
+ free(disp);
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(of_get_display_timings);
+
+/**
+ * of_display_timings_exist - check if a display-timings node is provided
+ * @np: device_node with the timing
+ **/
+int of_display_timings_exist(struct device_node *np)
+{
+ struct device_node *timings_np;
+
+ if (!np)
+ return -EINVAL;
+
+ timings_np = of_parse_phandle(np, "display-timings", 0);
+ if (!timings_np)
+ return -EINVAL;
+
+ return 1;
+}
+EXPORT_SYMBOL_GPL(of_display_timings_exist);
diff --git a/drivers/video/omap.c b/drivers/video/omap.c
index 487aca6f26..485cc7538b 100644
--- a/drivers/video/omap.c
+++ b/drivers/video/omap.c
@@ -467,8 +467,8 @@ static int omapfb_probe(struct device_d *dev)
for (i = 0; i < pdata->num_displays; ++i)
fbi->video_modes[i] = pdata->displays[i].mode;
- info->mode_list = fbi->video_modes;
- info->num_modes = pdata->num_displays;
+ info->modes.modes = fbi->video_modes;
+ info->modes.num_modes = pdata->num_displays;
info->priv = fbi;
info->fbops = &omapfb_ops;
diff --git a/drivers/video/pxa.c b/drivers/video/pxa.c
index 529190baec..b4ce3a1bf8 100644
--- a/drivers/video/pxa.c
+++ b/drivers/video/pxa.c
@@ -536,13 +536,8 @@ static int pxafb_probe(struct device_d *dev)
return 0;
}
-static void pxafb_remove(struct device_d *dev)
-{
-}
-
static struct driver_d pxafb_driver = {
.name = "pxafb",
.probe = pxafb_probe,
- .remove = pxafb_remove,
};
device_platform_driver(pxafb_driver);
diff --git a/drivers/video/s3c24xx.c b/drivers/video/s3c24xx.c
index c3e05c6cd7..b1883e232c 100644
--- a/drivers/video/s3c24xx.c
+++ b/drivers/video/s3c24xx.c
@@ -376,9 +376,9 @@ static int s3cfb_probe(struct device_d *hw_dev)
hw_dev->priv = &fbi;
/* add runtime video info */
- fbi.info.mode_list = pdata->mode_list;
- fbi.info.num_modes = pdata->mode_cnt;
- fbi.info.mode = &fbi.info.mode_list[1];
+ fbi.info.modes.modes = pdata->mode_list;
+ fbi.info.modes.num_modes = pdata->mode_cnt;
+ fbi.info.mode = &fbi.info.modes.modes[0];
fbi.info.xres = fbi.info.mode->xres;
fbi.info.yres = fbi.info.mode->yres;
if (pdata->bits_per_pixel)
diff --git a/drivers/video/sdl.c b/drivers/video/sdl.c
index 8dec5e5778..a56834004c 100644
--- a/drivers/video/sdl.c
+++ b/drivers/video/sdl.c
@@ -37,8 +37,8 @@ static int sdlfb_probe(struct device_d *dev)
return -EIO;
fb = xzalloc(sizeof(*fb));
- fb->mode_list = fb->mode = dev->platform_data;
- fb->num_modes = 1;
+ fb->modes.modes = fb->mode = dev->platform_data;
+ fb->modes.num_modes = 1;
fb->bits_per_pixel = 4 << 3;
fb->xres = fb->mode->xres;
fb->yres = fb->mode->yres;
diff --git a/drivers/video/stm.c b/drivers/video/stm.c
index fdeaf9c645..175e4b611d 100644
--- a/drivers/video/stm.c
+++ b/drivers/video/stm.c
@@ -499,9 +499,9 @@ static int stmfb_probe(struct device_d *hw_dev)
clk_enable(fbi.clk);
/* add runtime video info */
- fbi.info.mode_list = pdata->mode_list;
- fbi.info.num_modes = pdata->mode_cnt;
- fbi.info.mode = &fbi.info.mode_list[0];
+ fbi.info.modes.modes = pdata->mode_list;
+ fbi.info.modes.num_modes = pdata->mode_cnt;
+ fbi.info.mode = &fbi.info.modes.modes[0];
fbi.info.xres = fbi.info.mode->xres;
fbi.info.yres = fbi.info.mode->yres;
if (pdata->bits_per_pixel)
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 5b650de69b..06794fd379 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -82,6 +82,12 @@ CFG_start_imx6q_mba6x.pblx.imximg = $(board)/tqma6x/flash-header-tqma6q.imxcfg
FILE_barebox-tq-tqma6q-mba6x.img = start_imx6q_mba6x.pblx.imximg
image-$(CONFIG_MACH_TQMA6X) += barebox-tq-tqma6q-mba6x.img
+pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_4gib
+CFG_start_phytec_pbab01_4gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
+imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_4gib.pblx.imximg
+FILE_barebox-phytec-pbab01-4gib.img = start_phytec_pbab01_4gib.pblx.imximg
+image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01-4gib.img
+
pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_2gib
CFG_start_phytec_pbab01_2gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02-2gib.imxcfg
FILE_barebox-phytec-pbab01-2gib.img = start_phytec_pbab01_2gib.pblx.imximg
@@ -92,6 +98,18 @@ CFG_start_phytec_pbab01_1gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-he
FILE_barebox-phytec-pbab01-1gib.img = start_phytec_pbab01_1gib.pblx.imximg
image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01-1gib.img
+pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01dl_1gib
+CFG_start_phytec_pbab01dl_1gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
+imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01dl_1gib.pblx.imximg
+FILE_barebox-phytec-pbab01dl-1gib.img = start_phytec_pbab01dl_1gib.pblx.imximg
+image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01dl-1gib.img
+
+pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01s_512mb
+CFG_start_phytec_pbab01s_512mb.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
+imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01s_512mb.pblx.imximg
+FILE_barebox-phytec-pbab01s-512mb.img = start_phytec_pbab01s_512mb.pblx.imximg
+image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01s-512mb.img
+
pblx-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6dl_dfi_fs700_m60_6s
CFG_start_imx6dl_dfi_fs700_m60_6s.pblx.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6s.imxcfg
FILE_barebox-dfi-fs700-m60-6s.img = start_imx6dl_dfi_fs700_m60_6s.pblx.imximg
@@ -143,3 +161,8 @@ pblx-$(CONFIG_MACH_UDOO) += start_imx6_udoo
CFG_start_imx6_udoo.pblx.imximg = $(board)/udoo/flash-header-mx6-udoo.imxcfg
FILE_barebox-udoo-imx6q.img = start_imx6_udoo.pblx.imximg
image-$(CONFIG_MACH_UDOO) += barebox-udoo-imx6q.img
+
+pblx-$(CONFIG_MACH_VARISCITE_MX6) += start_variscite_custom
+CFG_start_variscite_custom.pblx.imximg = $(board)/variscite-mx6/flash-header-variscite.imxcfg
+FILE_barebox-variscite-custom.img = start_variscite_custom.pblx.imximg
+image-$(CONFIG_MACH_VARISCITE_MX6) += barebox-variscite-custom.img
diff --git a/include/blspec.h b/include/blspec.h
index 66d2e8485d..afac5ed7ba 100644
--- a/include/blspec.h
+++ b/include/blspec.h
@@ -35,7 +35,6 @@ int blspec_boot_devicename(const char *devname, int verbose, int dryrun);
int blspec_scan_devices(struct blspec *blspec);
-struct blspec_entry *blspec_entry_default(struct blspec *l);
int blspec_scan_devicename(struct blspec *blspec, const char *devname);
int blspec_scan_directory(struct blspec *blspec, const char *root);
@@ -91,4 +90,13 @@ static inline void blspec_free(struct blspec *blspec)
free(blspec);
}
+#ifdef CONFIG_BLSPEC
+struct blspec_entry *blspec_entry_default(struct blspec *l);
+#else
+static inline struct blspec_entry *blspec_entry_default(struct blspec *l)
+{
+ return NULL;
+}
+#endif
+
#endif /* __LOADER_H__ */
diff --git a/include/common.h b/include/common.h
index 6987b4f16d..bfd3ce8b7b 100644
--- a/include/common.h
+++ b/include/common.h
@@ -165,6 +165,15 @@ void arch_shutdown(void);
int run_shell(void);
+#ifdef CONFIG_SHELL_HUSH
+char *shell_expand(char *str);
+#else
+static inline char *shell_expand(char *str)
+{
+ return strdup(str);
+}
+#endif
+
/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
diff --git a/include/dt-bindings/clock/ar933x-clk.h b/include/dt-bindings/clock/ar933x-clk.h
new file mode 100644
index 0000000000..f048930726
--- /dev/null
+++ b/include/dt-bindings/clock/ar933x-clk.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __DT_BINDINGS_AR933X_CLK_H
+#define __DT_BINDINGS_AR933X_CLK_H
+
+#define AR933X_CLK_REF 0
+#define AR933X_CLK_UART 1
+#define AR933X_CLK_CPU 2
+#define AR933X_CLK_DDR 3
+#define AR933X_CLK_AHB 4
+#define AR933X_CLK_WDT 5
+
+#define AR933X_CLK_END 6
+
+#endif /* __DT_BINDINGS_AR933X_CLK_H */
diff --git a/include/fb.h b/include/fb.h
index 22fa9b130b..2db6ad6f37 100644
--- a/include/fb.h
+++ b/include/fb.h
@@ -4,6 +4,7 @@
#include <ioctl.h>
#include <param.h>
#include <driver.h>
+#include <linux/bitops.h>
#define FB_VISUAL_TRUECOLOR 2 /* True color */
#define FB_VISUAL_PSEUDOCOLOR 3 /* Pseudo color (like atari) */
@@ -32,6 +33,16 @@
#define PICOS2KHZ(a) (1000000000UL/(a))
#define KHZ2PICOS(a) (1000000000UL/(a))
+enum display_flags {
+ /* data enable flag */
+ DISPLAY_FLAGS_DE_LOW = BIT(4),
+ DISPLAY_FLAGS_DE_HIGH = BIT(5),
+ /* drive data on pos. edge */
+ DISPLAY_FLAGS_PIXDATA_POSEDGE = BIT(6),
+ /* drive data on neg. edge */
+ DISPLAY_FLAGS_PIXDATA_NEGEDGE = BIT(7),
+};
+
struct fb_videomode {
const char *name; /* optional */
u32 refresh; /* optional */
@@ -46,7 +57,7 @@ struct fb_videomode {
u32 vsync_len;
u32 sync;
u32 vmode;
- u32 flag;
+ u32 display_flags;
};
/* Interpretation of offset for color fields: All offsets are from the right,
@@ -77,10 +88,30 @@ struct fb_ops {
int (*fb_activate_var)(struct fb_info *info);
};
+/*
+ * This describes all timing settings a display provides.
+ * The native_mode is the default setting for this display.
+ * Drivers that can handle multiple videomodes should work with this struct and
+ * convert each entry to the desired end result.
+ */
+struct display_timings {
+ unsigned int native_mode;
+
+ unsigned int num_modes;
+ struct fb_videomode *modes;
+};
+
+struct i2c_adapter;
+
struct fb_info {
struct fb_videomode *mode;
- struct fb_videomode *mode_list;
- unsigned num_modes;
+ struct display_timings modes;
+
+ int current_mode;
+
+ void *edid_data;
+ struct i2c_adapter *edid_i2c_adapter;
+ struct display_timings edid_modes;
struct fb_ops *fbops;
struct device_d dev; /* This is this fb device */
@@ -111,6 +142,8 @@ struct fb_info {
*/
};
+struct display_timings *of_get_display_timings(struct device_node *np);
+
int register_framebuffer(struct fb_info *info);
#define FBIOGET_SCREENINFO _IOR('F', 1, loff_t)
@@ -123,5 +156,8 @@ extern struct bus_type fb_bus;
int fb_register_simplefb(struct fb_info *info);
-#endif /* __FB_H */
+int edid_to_display_timings(struct display_timings *, unsigned char *edid);
+void *edid_read_i2c(struct i2c_adapter *adapter);
+void fb_edid_add_modes(struct fb_info *info);
+#endif /* __FB_H */
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index 81e5daa200..f89fefbb27 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -133,6 +133,7 @@ static inline int i2c_register_board_info(int busnum,
#endif
extern int i2c_add_numbered_adapter(struct i2c_adapter *adapter);
struct i2c_adapter *i2c_get_adapter(int busnum);
+struct i2c_adapter *of_find_i2c_adapter_by_node(struct device_node *node);
/* For devices that use several addresses, use i2c_new_dummy() to make
* client handles for the extra addresses.
diff --git a/include/linux/clk.h b/include/linux/clk.h
index af38c720e8..07b27cf148 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -196,6 +196,9 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
#endif
#ifdef CONFIG_COMMON_CLK
+
+#define CLK_SET_RATE_PARENT (1 << 0) /* propagate rate change up one level */
+
struct clk_ops {
int (*enable)(struct clk *clk);
void (*disable)(struct clk *clk);
@@ -237,36 +240,46 @@ struct clk_divider {
const char *parent;
#define CLK_DIVIDER_ONE_BASED (1 << 0)
unsigned flags;
+ const struct clk_div_table *table;
+ int max_div_index;
+ int table_size;
};
extern struct clk_ops clk_divider_ops;
struct clk *clk_divider(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width);
+ void __iomem *reg, u8 shift, u8 width, unsigned flags);
struct clk *clk_divider_one_based(const char *name, const char *parent,
- void __iomem *reg, u8 shift, u8 width);
+ void __iomem *reg, u8 shift, u8 width, unsigned flags);
struct clk *clk_divider_table(const char *name,
const char *parent, void __iomem *reg, u8 shift, u8 width,
- const struct clk_div_table *table);
+ const struct clk_div_table *table, unsigned flags);
struct clk *clk_fixed_factor(const char *name,
- const char *parent, unsigned int mult, unsigned int div);
+ const char *parent, unsigned int mult, unsigned int div,
+ unsigned flags);
struct clk *clk_mux_alloc(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents);
+ u8 shift, u8 width, const char **parents, u8 num_parents,
+ unsigned flags);
void clk_mux_free(struct clk *clk_mux);
struct clk *clk_mux(const char *name, void __iomem *reg,
- u8 shift, u8 width, const char **parents, u8 num_parents);
+ u8 shift, u8 width, const char **parents, u8 num_parents,
+ unsigned flags);
struct clk *clk_gate_alloc(const char *name, const char *parent,
- void __iomem *reg, u8 shift);
+ void __iomem *reg, u8 shift, unsigned flags);
void clk_gate_free(struct clk *clk_gate);
struct clk *clk_gate(const char *name, const char *parent, void __iomem *reg,
- u8 shift);
+ u8 shift, unsigned flags);
struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem *reg,
- u8 shift);
+ u8 shift, unsigned flags);
int clk_is_enabled(struct clk *clk);
int clk_is_enabled_always(struct clk *clk);
+long clk_parent_round_rate(struct clk *clk, unsigned long rate,
+ unsigned long *prate);
+int clk_parent_set_rate(struct clk *clk, unsigned long rate,
+ unsigned long parent_rate);
int clk_register(struct clk *clk);
diff --git a/include/linux/const.h b/include/linux/const.h
new file mode 100644
index 0000000000..c872bfd25e
--- /dev/null
+++ b/include/linux/const.h
@@ -0,0 +1,27 @@
+/* const.h: Macros for dealing with constants. */
+
+#ifndef _LINUX_CONST_H
+#define _LINUX_CONST_H
+
+/* Some constant macros are used in both assembler and
+ * C code. Therefore we cannot annotate them always with
+ * 'UL' and other type specifiers unilaterally. We
+ * use the following macros to deal with this.
+ *
+ * Similarly, _AT() will cast an expression with a type in C, but
+ * leave it unchanged in asm.
+ */
+
+#ifdef __ASSEMBLY__
+#define _AC(X,Y) X
+#define _AT(T,X) X
+#else
+#define __AC(X,Y) (X##Y)
+#define _AC(X,Y) __AC(X,Y)
+#define _AT(T,X) ((T)(X))
+#endif
+
+#define _BITUL(x) (_AC(1,UL) << (x))
+#define _BITULL(x) (_AC(1,ULL) << (x))
+
+#endif /* !(_LINUX_CONST_H) */
diff --git a/include/linux/err.h b/include/linux/err.h
index 19fb70dc08..ed563f2c4a 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -52,6 +52,14 @@ static inline void *ERR_CAST(const void *ptr)
return (void *) ptr;
}
+static inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr)
+{
+ if (IS_ERR(ptr))
+ return PTR_ERR(ptr);
+ else
+ return 0;
+}
+
#endif
#endif /* _LINUX_ERR_H */
diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h
index 11d51e2744..c1ba55bd2d 100644
--- a/include/linux/mtd/mtd-abi.h
+++ b/include/linux/mtd/mtd-abi.h
@@ -9,6 +9,8 @@
#ifndef DOXYGEN_SHOULD_SKIP_THIS
+#include <asm-generic/div64.h>
+
struct erase_info_user {
uint32_t start;
uint32_t length;
@@ -73,7 +75,7 @@ enum {
struct mtd_info_user {
uint8_t type;
uint32_t flags;
- uint32_t size; // Total size of the MTD
+ uint64_t size; /* Total size of the MTD */
uint32_t erasesize;
uint32_t writesize;
uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
@@ -173,6 +175,14 @@ enum mtd_file_modes {
MTD_MODE_RAW,
};
+
+static inline uint32_t mtd_user_div_by_eb(uint64_t sz,
+ struct mtd_info_user *mtd_user)
+{
+ do_div(sz, mtd_user->erasesize);
+ return sz;
+}
+
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
#endif /* __MTD_ABI_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index e02204a503..c63b514f44 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -86,7 +86,7 @@ struct mtd_oob_ops {
struct mtd_info {
u_char type;
u_int32_t flags;
- u_int32_t size; // Total size of the MTD
+ u_int64_t size; /* Total size of the MTD */
/* "Major" erase size for the device. Naïve users may take this
* to be the only erase size available, or may use the more detailed
@@ -219,7 +219,7 @@ struct mtd_info {
int p_allow_erasebad;
struct mtd_info *master;
- uint32_t master_offset;
+ loff_t master_offset;
};
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
@@ -256,6 +256,13 @@ static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
{
return do_div(sz, mtd->erasesize);
}
+
+static inline uint32_t mtd_div_by_wb(uint64_t sz, struct mtd_info *mtd)
+{
+ do_div(sz, mtd->writesize);
+ return sz;
+}
+
/* Kernel-side ioctl definitions */
extern int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id);
@@ -273,8 +280,8 @@ struct mtd_notifier {
struct list_head list;
};
-struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset, size_t size,
- unsigned long flags, const char *name);
+struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset,
+ uint64_t size, unsigned long flags, const char *name);
int mtd_del_partition(struct mtd_info *mtd);
extern void register_mtd_user (struct mtd_notifier *new);
diff --git a/include/menu.h b/include/menu.h
index f63a405121..8b0ffb1f83 100644
--- a/include/menu.h
+++ b/include/menu.h
@@ -106,4 +106,6 @@ struct menu_entry* menu_entry_get_by_num(struct menu* m, int num);
*/
void menu_action_exit(struct menu *m, struct menu_entry *me);
+int menutree(const char *path, int toplevel);
+
#endif /* __MENU_H__ */
diff --git a/include/mfd/imx6q-iomuxc-gpr.h b/include/mfd/imx6q-iomuxc-gpr.h
index db43d5905c..24993ffe7e 100644
--- a/include/mfd/imx6q-iomuxc-gpr.h
+++ b/include/mfd/imx6q-iomuxc-gpr.h
@@ -103,15 +103,15 @@
#define IMX6Q_GPR1_EXC_MON_MASK BIT(22)
#define IMX6Q_GPR1_EXC_MON_OKAY 0x0
#define IMX6Q_GPR1_EXC_MON_SLVE BIT(22)
-#define IMX6Q_GPR1_MIPI_IPU2_SEL_MASK BIT(21)
-#define IMX6Q_GPR1_MIPI_IPU2_SEL_GASKET 0x0
-#define IMX6Q_GPR1_MIPI_IPU2_SEL_IOMUX BIT(21)
-#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK BIT(20)
-#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET 0x0
-#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX BIT(20)
-#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK BIT(19)
+#define IMX6Q_GPR1_ENET_CLK_SEL_MASK BIT(21)
+#define IMX6Q_GPR1_ENET_CLK_SEL_PAD 0
+#define IMX6Q_GPR1_ENET_CLK_SEL_ANATOP BIT(21)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_MASK BIT(20)
#define IMX6Q_GPR1_MIPI_IPU2_MUX_GASKET 0x0
-#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX BIT(19)
+#define IMX6Q_GPR1_MIPI_IPU2_MUX_IOMUX BIT(20)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_MASK BIT(19)
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_GASKET 0x0
+#define IMX6Q_GPR1_MIPI_IPU1_MUX_IOMUX BIT(19)
#define IMX6Q_GPR1_PCIE_TEST_PD BIT(18)
#define IMX6Q_GPR1_IPU_VPU_MUX_MASK BIT(17)
#define IMX6Q_GPR1_IPU_VPU_MUX_IPU1 0x0
@@ -241,6 +241,24 @@
#define IMX6Q_GPR5_L2_CLK_STOP BIT(8)
+#define IMX6Q_GPR6_IPU1_ID00_WR_QOS_MASK (0xf << 0)
+#define IMX6Q_GPR6_IPU1_ID01_WR_QOS_MASK (0xf << 4)
+#define IMX6Q_GPR6_IPU1_ID10_WR_QOS_MASK (0xf << 8)
+#define IMX6Q_GPR6_IPU1_ID11_WR_QOS_MASK (0xf << 12)
+#define IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK (0xf << 16)
+#define IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK (0xf << 20)
+#define IMX6Q_GPR6_IPU1_ID10_RD_QOS_MASK (0xf << 24)
+#define IMX6Q_GPR6_IPU1_ID11_RD_QOS_MASK (0xf << 28)
+
+#define IMX6Q_GPR7_IPU2_ID00_WR_QOS_MASK (0xf << 0)
+#define IMX6Q_GPR7_IPU2_ID01_WR_QOS_MASK (0xf << 4)
+#define IMX6Q_GPR7_IPU2_ID10_WR_QOS_MASK (0xf << 8)
+#define IMX6Q_GPR7_IPU2_ID11_WR_QOS_MASK (0xf << 12)
+#define IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK (0xf << 16)
+#define IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK (0xf << 20)
+#define IMX6Q_GPR7_IPU2_ID10_RD_QOS_MASK (0xf << 24)
+#define IMX6Q_GPR7_IPU2_ID11_RD_QOS_MASK (0xf << 28)
+
#define IMX6Q_GPR9_TZASC2_BYP BIT(1)
#define IMX6Q_GPR9_TZASC1_BYP BIT(0)
diff --git a/include/param.h b/include/param.h
index e8458b5b2d..eac3372f34 100644
--- a/include/param.h
+++ b/include/param.h
@@ -54,6 +54,11 @@ struct param_d *dev_add_param_ip(struct device_d *dev, const char *name,
int (*get)(struct param_d *p, void *priv),
IPaddr_t *ip, void *priv);
+struct param_d *dev_add_param_mac(struct device_d *dev, const char *name,
+ int (*set)(struct param_d *p, void *priv),
+ int (*get)(struct param_d *p, void *priv),
+ u8 *mac, void *priv);
+
int dev_add_param_fixed(struct device_d *dev, char *name, const char *value);
void dev_remove_param(struct param_d *p);
@@ -126,6 +131,14 @@ static inline struct param_d *dev_add_param_ip(struct device_d *dev, const char
return NULL;
}
+static inline struct param_d *dev_add_param_mac(struct device_d *dev, const char *name,
+ int (*set)(struct param_d *p, void *priv),
+ int (*get)(struct param_d *p, void *priv),
+ u8 *mac, void *priv)
+{
+ return NULL;
+}
+
static inline int dev_add_param_fixed(struct device_d *dev, char *name, char *value)
{
return 0;
diff --git a/include/video/fourcc.h b/include/video/fourcc.h
new file mode 100644
index 0000000000..322142c1ba
--- /dev/null
+++ b/include/video/fourcc.h
@@ -0,0 +1,261 @@
+#ifndef __VIDEO_FOURCC_H
+#define __VIDEO_FOURCC_H
+
+/* Four-character-code (FOURCC) */
+#define v4l2_fourcc(a, b, c, d)\
+ ((__u32)(a) | ((__u32)(b) << 8) | ((__u32)(c) << 16) | ((__u32)(d) << 24))
+
+/* Pixel format FOURCC depth Description */
+
+/* RGB formats */
+#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */
+#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */
+#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */
+#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */
+#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */
+#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */
+#define V4L2_PIX_FMT_BGR666 v4l2_fourcc('B', 'G', 'R', 'H') /* 18 BGR-6-6-6 */
+#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */
+#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */
+#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */
+#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */
+
+/* Grey formats */
+#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */
+#define V4L2_PIX_FMT_Y4 v4l2_fourcc('Y', '0', '4', ' ') /* 4 Greyscale */
+#define V4L2_PIX_FMT_Y6 v4l2_fourcc('Y', '0', '6', ' ') /* 6 Greyscale */
+#define V4L2_PIX_FMT_Y10 v4l2_fourcc('Y', '1', '0', ' ') /* 10 Greyscale */
+#define V4L2_PIX_FMT_Y12 v4l2_fourcc('Y', '1', '2', ' ') /* 12 Greyscale */
+#define V4L2_PIX_FMT_Y16 v4l2_fourcc('Y', '1', '6', ' ') /* 16 Greyscale */
+
+/* Grey bit-packed formats */
+#define V4L2_PIX_FMT_Y10BPACK v4l2_fourcc('Y', '1', '0', 'B') /* 10 Greyscale bit-packed */
+
+/* Palette formats */
+#define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P', 'A', 'L', '8') /* 8 8-bit palette */
+
+/* Chrominance formats */
+#define V4L2_PIX_FMT_UV8 v4l2_fourcc('U', 'V', '8', ' ') /* 8 UV 4:4 */
+
+/* Luminance+Chrominance formats */
+#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y', 'V', 'U', '9') /* 9 YVU 4:1:0 */
+#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y', 'V', '1', '2') /* 12 YVU 4:2:0 */
+#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y', 'U', 'Y', 'V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y', 'Y', 'U', 'V') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') /* 16 YVU 4:2:2 */
+#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U', 'Y', 'V', 'Y') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_VYUY v4l2_fourcc('V', 'Y', 'U', 'Y') /* 16 YUV 4:2:2 */
+#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4', '2', '2', 'P') /* 16 YVU422 planar */
+#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4', '1', '1', 'P') /* 16 YVU411 planar */
+#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y', '4', '1', 'P') /* 12 YUV 4:1:1 */
+#define V4L2_PIX_FMT_YUV444 v4l2_fourcc('Y', '4', '4', '4') /* 16 xxxxyyyy uuuuvvvv */
+#define V4L2_PIX_FMT_YUV555 v4l2_fourcc('Y', 'U', 'V', 'O') /* 16 YUV-5-5-5 */
+#define V4L2_PIX_FMT_YUV565 v4l2_fourcc('Y', 'U', 'V', 'P') /* 16 YUV-5-6-5 */
+#define V4L2_PIX_FMT_YUV32 v4l2_fourcc('Y', 'U', 'V', '4') /* 32 YUV-8-8-8-8 */
+#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y', 'U', 'V', '9') /* 9 YUV 4:1:0 */
+#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y', 'U', '1', '2') /* 12 YUV 4:2:0 */
+#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H', 'I', '2', '4') /* 8 8-bit color */
+#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H', 'M', '1', '2') /* 8 YUV 4:2:0 16x16 macroblocks */
+#define V4L2_PIX_FMT_M420 v4l2_fourcc('M', '4', '2', '0') /* 12 YUV 4:2:0 2 lines y, 1 line uv interleaved */
+
+/* two planes -- one Y, one Cr + Cb interleaved */
+#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N', 'V', '1', '2') /* 12 Y/CbCr 4:2:0 */
+#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N', 'V', '2', '1') /* 12 Y/CrCb 4:2:0 */
+#define V4L2_PIX_FMT_NV16 v4l2_fourcc('N', 'V', '1', '6') /* 16 Y/CbCr 4:2:2 */
+#define V4L2_PIX_FMT_NV61 v4l2_fourcc('N', 'V', '6', '1') /* 16 Y/CrCb 4:2:2 */
+#define V4L2_PIX_FMT_NV24 v4l2_fourcc('N', 'V', '2', '4') /* 24 Y/CbCr 4:4:4 */
+#define V4L2_PIX_FMT_NV42 v4l2_fourcc('N', 'V', '4', '2') /* 24 Y/CrCb 4:4:4 */
+
+/* two non contiguous planes - one Y, one Cr + Cb interleaved */
+#define V4L2_PIX_FMT_NV12M v4l2_fourcc('N', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 */
+#define V4L2_PIX_FMT_NV21M v4l2_fourcc('N', 'M', '2', '1') /* 21 Y/CrCb 4:2:0 */
+#define V4L2_PIX_FMT_NV16M v4l2_fourcc('N', 'M', '1', '6') /* 16 Y/CbCr 4:2:2 */
+#define V4L2_PIX_FMT_NV61M v4l2_fourcc('N', 'M', '6', '1') /* 16 Y/CrCb 4:2:2 */
+#define V4L2_PIX_FMT_NV12MT v4l2_fourcc('T', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 64x32 macroblocks */
+#define V4L2_PIX_FMT_NV12MT_16X16 v4l2_fourcc('V', 'M', '1', '2') /* 12 Y/CbCr 4:2:0 16x16 macroblocks */
+
+/* three non contiguous planes - Y, Cb, Cr */
+#define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12 YUV420 planar */
+#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12 YVU420 planar */
+
+/* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
+#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B', 'A', '8', '1') /* 8 BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G', 'B', 'R', 'G') /* 8 GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G', 'R', 'B', 'G') /* 8 GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R', 'G', 'G', 'B') /* 8 RGRG.. GBGB.. */
+#define V4L2_PIX_FMT_SBGGR10 v4l2_fourcc('B', 'G', '1', '0') /* 10 BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG10 v4l2_fourcc('G', 'B', '1', '0') /* 10 GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG10 v4l2_fourcc('B', 'A', '1', '0') /* 10 GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB10 v4l2_fourcc('R', 'G', '1', '0') /* 10 RGRG.. GBGB.. */
+#define V4L2_PIX_FMT_SBGGR12 v4l2_fourcc('B', 'G', '1', '2') /* 12 BGBG.. GRGR.. */
+#define V4L2_PIX_FMT_SGBRG12 v4l2_fourcc('G', 'B', '1', '2') /* 12 GBGB.. RGRG.. */
+#define V4L2_PIX_FMT_SGRBG12 v4l2_fourcc('B', 'A', '1', '2') /* 12 GRGR.. BGBG.. */
+#define V4L2_PIX_FMT_SRGGB12 v4l2_fourcc('R', 'G', '1', '2') /* 12 RGRG.. GBGB.. */
+ /* 10bit raw bayer a-law compressed to 8 bits */
+#define V4L2_PIX_FMT_SBGGR10ALAW8 v4l2_fourcc('a', 'B', 'A', '8')
+#define V4L2_PIX_FMT_SGBRG10ALAW8 v4l2_fourcc('a', 'G', 'A', '8')
+#define V4L2_PIX_FMT_SGRBG10ALAW8 v4l2_fourcc('a', 'g', 'A', '8')
+#define V4L2_PIX_FMT_SRGGB10ALAW8 v4l2_fourcc('a', 'R', 'A', '8')
+ /* 10bit raw bayer DPCM compressed to 8 bits */
+#define V4L2_PIX_FMT_SBGGR10DPCM8 v4l2_fourcc('b', 'B', 'A', '8')
+#define V4L2_PIX_FMT_SGBRG10DPCM8 v4l2_fourcc('b', 'G', 'A', '8')
+#define V4L2_PIX_FMT_SGRBG10DPCM8 v4l2_fourcc('B', 'D', '1', '0')
+#define V4L2_PIX_FMT_SRGGB10DPCM8 v4l2_fourcc('b', 'R', 'A', '8')
+ /*
+ * 10bit raw bayer, expanded to 16 bits
+ * xxxxrrrrrrrrrrxxxxgggggggggg xxxxggggggggggxxxxbbbbbbbbbb...
+ */
+#define V4L2_PIX_FMT_SBGGR16 v4l2_fourcc('B', 'Y', 'R', '2') /* 16 BGBG.. GRGR.. */
+
+/* compressed formats */
+#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M', 'J', 'P', 'G') /* Motion-JPEG */
+#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J', 'P', 'E', 'G') /* JFIF JPEG */
+#define V4L2_PIX_FMT_DV v4l2_fourcc('d', 'v', 's', 'd') /* 1394 */
+#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M', 'P', 'E', 'G') /* MPEG-1/2/4 Multiplexed */
+#define V4L2_PIX_FMT_H264 v4l2_fourcc('H', '2', '6', '4') /* H264 with start codes */
+#define V4L2_PIX_FMT_H264_NO_SC v4l2_fourcc('A', 'V', 'C', '1') /* H264 without start codes */
+#define V4L2_PIX_FMT_H264_MVC v4l2_fourcc('M', '2', '6', '4') /* H264 MVC */
+#define V4L2_PIX_FMT_H263 v4l2_fourcc('H', '2', '6', '3') /* H263 */
+#define V4L2_PIX_FMT_MPEG1 v4l2_fourcc('M', 'P', 'G', '1') /* MPEG-1 ES */
+#define V4L2_PIX_FMT_MPEG2 v4l2_fourcc('M', 'P', 'G', '2') /* MPEG-2 ES */
+#define V4L2_PIX_FMT_MPEG4 v4l2_fourcc('M', 'P', 'G', '4') /* MPEG-4 part 2 ES */
+#define V4L2_PIX_FMT_XVID v4l2_fourcc('X', 'V', 'I', 'D') /* Xvid */
+#define V4L2_PIX_FMT_VC1_ANNEX_G v4l2_fourcc('V', 'C', '1', 'G') /* SMPTE 421M Annex G compliant stream */
+#define V4L2_PIX_FMT_VC1_ANNEX_L v4l2_fourcc('V', 'C', '1', 'L') /* SMPTE 421M Annex L compliant stream */
+#define V4L2_PIX_FMT_VP8 v4l2_fourcc('V', 'P', '8', '0') /* VP8 */
+
+/* Vendor-specific formats */
+#define V4L2_PIX_FMT_CPIA1 v4l2_fourcc('C', 'P', 'I', 'A') /* cpia1 YUV */
+#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W', 'N', 'V', 'A') /* Winnov hw compress */
+#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S', '9', '1', '0') /* SN9C10x compression */
+#define V4L2_PIX_FMT_SN9C20X_I420 v4l2_fourcc('S', '9', '2', '0') /* SN9C20x YUV 4:2:0 */
+#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P', 'W', 'C', '1') /* pwc older webcam */
+#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P', 'W', 'C', '2') /* pwc newer webcam */
+#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E', '6', '2', '5') /* ET61X251 compression */
+#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S', '5', '0', '1') /* YUYV per line */
+#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S', '5', '0', '5') /* YYUV per line */
+#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S', '5', '0', '8') /* YUVY per line */
+#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S', '5', '6', '1') /* compressed GBRG bayer */
+#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P', '2', '0', '7') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_MR97310A v4l2_fourcc('M', '3', '1', '0') /* compressed BGGR bayer */
+#define V4L2_PIX_FMT_JL2005BCD v4l2_fourcc('J', 'L', '2', '0') /* compressed RGGB bayer */
+#define V4L2_PIX_FMT_SN9C2028 v4l2_fourcc('S', 'O', 'N', 'X') /* compressed GBRG bayer */
+#define V4L2_PIX_FMT_SQ905C v4l2_fourcc('9', '0', '5', 'C') /* compressed RGGB bayer */
+#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') /* Pixart 73xx JPEG */
+#define V4L2_PIX_FMT_OV511 v4l2_fourcc('O', '5', '1', '1') /* ov511 JPEG */
+#define V4L2_PIX_FMT_OV518 v4l2_fourcc('O', '5', '1', '8') /* ov518 JPEG */
+#define V4L2_PIX_FMT_STV0680 v4l2_fourcc('S', '6', '8', '0') /* stv0680 bayer */
+#define V4L2_PIX_FMT_TM6000 v4l2_fourcc('T', 'M', '6', '0') /* tm5600/tm60x0 */
+#define V4L2_PIX_FMT_CIT_YYVYUY v4l2_fourcc('C', 'I', 'T', 'V') /* one line of Y then 1 line of VYUY */
+#define V4L2_PIX_FMT_KONICA420 v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
+#define V4L2_PIX_FMT_JPGL v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
+#define V4L2_PIX_FMT_SE401 v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
+
+#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
+ ((__u32)(c) << 16) | ((__u32)(d) << 24))
+
+#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
+
+/* color index */
+#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
+
+/* 8 bpp RGB */
+#define DRM_FORMAT_RGB332 fourcc_code('R', 'G', 'B', '8') /* [7:0] R:G:B 3:3:2 */
+#define DRM_FORMAT_BGR233 fourcc_code('B', 'G', 'R', '8') /* [7:0] B:G:R 2:3:3 */
+
+/* 16 bpp RGB */
+#define DRM_FORMAT_XRGB4444 fourcc_code('X', 'R', '1', '2') /* [15:0] x:R:G:B 4:4:4:4 little endian */
+#define DRM_FORMAT_XBGR4444 fourcc_code('X', 'B', '1', '2') /* [15:0] x:B:G:R 4:4:4:4 little endian */
+#define DRM_FORMAT_RGBX4444 fourcc_code('R', 'X', '1', '2') /* [15:0] R:G:B:x 4:4:4:4 little endian */
+#define DRM_FORMAT_BGRX4444 fourcc_code('B', 'X', '1', '2') /* [15:0] B:G:R:x 4:4:4:4 little endian */
+
+#define DRM_FORMAT_ARGB4444 fourcc_code('A', 'R', '1', '2') /* [15:0] A:R:G:B 4:4:4:4 little endian */
+#define DRM_FORMAT_ABGR4444 fourcc_code('A', 'B', '1', '2') /* [15:0] A:B:G:R 4:4:4:4 little endian */
+#define DRM_FORMAT_RGBA4444 fourcc_code('R', 'A', '1', '2') /* [15:0] R:G:B:A 4:4:4:4 little endian */
+#define DRM_FORMAT_BGRA4444 fourcc_code('B', 'A', '1', '2') /* [15:0] B:G:R:A 4:4:4:4 little endian */
+
+#define DRM_FORMAT_XRGB1555 fourcc_code('X', 'R', '1', '5') /* [15:0] x:R:G:B 1:5:5:5 little endian */
+#define DRM_FORMAT_XBGR1555 fourcc_code('X', 'B', '1', '5') /* [15:0] x:B:G:R 1:5:5:5 little endian */
+#define DRM_FORMAT_RGBX5551 fourcc_code('R', 'X', '1', '5') /* [15:0] R:G:B:x 5:5:5:1 little endian */
+#define DRM_FORMAT_BGRX5551 fourcc_code('B', 'X', '1', '5') /* [15:0] B:G:R:x 5:5:5:1 little endian */
+
+#define DRM_FORMAT_ARGB1555 fourcc_code('A', 'R', '1', '5') /* [15:0] A:R:G:B 1:5:5:5 little endian */
+#define DRM_FORMAT_ABGR1555 fourcc_code('A', 'B', '1', '5') /* [15:0] A:B:G:R 1:5:5:5 little endian */
+#define DRM_FORMAT_RGBA5551 fourcc_code('R', 'A', '1', '5') /* [15:0] R:G:B:A 5:5:5:1 little endian */
+#define DRM_FORMAT_BGRA5551 fourcc_code('B', 'A', '1', '5') /* [15:0] B:G:R:A 5:5:5:1 little endian */
+
+#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */
+#define DRM_FORMAT_BGR565 fourcc_code('B', 'G', '1', '6') /* [15:0] B:G:R 5:6:5 little endian */
+
+/* 24 bpp RGB */
+#define DRM_FORMAT_RGB888 fourcc_code('R', 'G', '2', '4') /* [23:0] R:G:B little endian */
+#define DRM_FORMAT_BGR888 fourcc_code('B', 'G', '2', '4') /* [23:0] B:G:R little endian */
+
+/* 32 bpp RGB */
+#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */
+#define DRM_FORMAT_XBGR8888 fourcc_code('X', 'B', '2', '4') /* [31:0] x:B:G:R 8:8:8:8 little endian */
+#define DRM_FORMAT_RGBX8888 fourcc_code('R', 'X', '2', '4') /* [31:0] R:G:B:x 8:8:8:8 little endian */
+#define DRM_FORMAT_BGRX8888 fourcc_code('B', 'X', '2', '4') /* [31:0] B:G:R:x 8:8:8:8 little endian */
+
+#define DRM_FORMAT_ARGB8888 fourcc_code('A', 'R', '2', '4') /* [31:0] A:R:G:B 8:8:8:8 little endian */
+#define DRM_FORMAT_ABGR8888 fourcc_code('A', 'B', '2', '4') /* [31:0] A:B:G:R 8:8:8:8 little endian */
+#define DRM_FORMAT_RGBA8888 fourcc_code('R', 'A', '2', '4') /* [31:0] R:G:B:A 8:8:8:8 little endian */
+#define DRM_FORMAT_BGRA8888 fourcc_code('B', 'A', '2', '4') /* [31:0] B:G:R:A 8:8:8:8 little endian */
+
+#define DRM_FORMAT_XRGB2101010 fourcc_code('X', 'R', '3', '0') /* [31:0] x:R:G:B 2:10:10:10 little endian */
+#define DRM_FORMAT_XBGR2101010 fourcc_code('X', 'B', '3', '0') /* [31:0] x:B:G:R 2:10:10:10 little endian */
+#define DRM_FORMAT_RGBX1010102 fourcc_code('R', 'X', '3', '0') /* [31:0] R:G:B:x 10:10:10:2 little endian */
+#define DRM_FORMAT_BGRX1010102 fourcc_code('B', 'X', '3', '0') /* [31:0] B:G:R:x 10:10:10:2 little endian */
+
+#define DRM_FORMAT_ARGB2101010 fourcc_code('A', 'R', '3', '0') /* [31:0] A:R:G:B 2:10:10:10 little endian */
+#define DRM_FORMAT_ABGR2101010 fourcc_code('A', 'B', '3', '0') /* [31:0] A:B:G:R 2:10:10:10 little endian */
+#define DRM_FORMAT_RGBA1010102 fourcc_code('R', 'A', '3', '0') /* [31:0] R:G:B:A 10:10:10:2 little endian */
+#define DRM_FORMAT_BGRA1010102 fourcc_code('B', 'A', '3', '0') /* [31:0] B:G:R:A 10:10:10:2 little endian */
+
+/* packed YCbCr */
+#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */
+#define DRM_FORMAT_YVYU fourcc_code('Y', 'V', 'Y', 'U') /* [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian */
+#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */
+#define DRM_FORMAT_VYUY fourcc_code('V', 'Y', 'U', 'Y') /* [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian */
+
+#define DRM_FORMAT_AYUV fourcc_code('A', 'Y', 'U', 'V') /* [31:0] A:Y:Cb:Cr 8:8:8:8 little endian */
+
+/*
+ * 2 plane YCbCr
+ * index 0 = Y plane, [7:0] Y
+ * index 1 = Cr:Cb plane, [15:0] Cr:Cb little endian
+ * or
+ * index 1 = Cb:Cr plane, [15:0] Cb:Cr little endian
+ */
+#define DRM_FORMAT_NV12 fourcc_code('N', 'V', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV21 fourcc_code('N', 'V', '2', '1') /* 2x2 subsampled Cb:Cr plane */
+#define DRM_FORMAT_NV16 fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV61 fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
+#define DRM_FORMAT_NV24 fourcc_code('N', 'V', '2', '4') /* non-subsampled Cr:Cb plane */
+#define DRM_FORMAT_NV42 fourcc_code('N', 'V', '4', '2') /* non-subsampled Cb:Cr plane */
+
+/* special NV12 tiled format */
+#define DRM_FORMAT_NV12MT fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */
+
+/*
+ * 3 plane YCbCr
+ * index 0: Y plane, [7:0] Y
+ * index 1: Cb plane, [7:0] Cb
+ * index 2: Cr plane, [7:0] Cr
+ * or
+ * index 1: Cr plane, [7:0] Cr
+ * index 2: Cb plane, [7:0] Cb
+ */
+#define DRM_FORMAT_YUV410 fourcc_code('Y', 'U', 'V', '9') /* 4x4 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU410 fourcc_code('Y', 'V', 'U', '9') /* 4x4 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV411 fourcc_code('Y', 'U', '1', '1') /* 4x1 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU411 fourcc_code('Y', 'V', '1', '1') /* 4x1 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV420 fourcc_code('Y', 'U', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU420 fourcc_code('Y', 'V', '1', '2') /* 2x2 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV422 fourcc_code('Y', 'U', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU422 fourcc_code('Y', 'V', '1', '6') /* 2x1 subsampled Cr (1) and Cb (2) planes */
+#define DRM_FORMAT_YUV444 fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
+#define DRM_FORMAT_YVU444 fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
+
+#endif /* __VIDEO_FOURCC_H */
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 1606b872fd..56672bd951 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -195,7 +195,7 @@ int libmtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
void *buf, int len)
{
int ret, rd = 0;
- off_t seek;
+ loff_t seek;
ret = mtd_valid_erase_block(mtd, eb);
if (ret)
@@ -209,7 +209,7 @@ int libmtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
}
/* Seek to the beginning of the eraseblock */
- seek = (off_t)eb * mtd->eb_size + offs;
+ seek = (loff_t)eb * mtd->eb_size + offs;
if (lseek(fd, seek, SEEK_SET) != seek)
return sys_errmsg("cannot seek %s to offset %llu",
mtd->node, (unsigned long long)seek);
@@ -229,7 +229,7 @@ int libmtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
void *buf, int len)
{
int ret;
- off_t seek;
+ loff_t seek;
ret = mtd_valid_erase_block(mtd, eb);
if (ret)
@@ -255,7 +255,7 @@ int libmtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
}
/* Seek to the beginning of the eraseblock */
- seek = (off_t)eb * mtd->eb_size + offs;
+ seek = (loff_t)eb * mtd->eb_size + offs;
if (lseek(fd, seek, SEEK_SET) != seek)
return sys_errmsg("cannot seek %s to offset %llu",
mtd->node, (unsigned long long)seek);
@@ -326,7 +326,7 @@ int mtd_get_dev_info(const char *node, struct mtd_dev_info *mtd)
goto out_close;
}
- mtd->eb_cnt = ui.size / ui.erasesize;
+ mtd->eb_cnt = mtd_user_div_by_eb(ui.size, &ui);
switch(mtd->type) {
case MTD_ABSENT:
diff --git a/lib/parameter.c b/lib/parameter.c
index 9dfde3f698..baa2b156c0 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -542,6 +542,93 @@ struct param_d *dev_add_param_ip(struct device_d *dev, const char *name,
return &pi->param;
}
+
+struct param_mac {
+ struct param_d param;
+ char *mac;
+ u8 mac_str[sizeof("xx:xx:xx:xx:xx:xx")];
+ const char *format;
+ int (*set)(struct param_d *p, void *priv);
+ int (*get)(struct param_d *p, void *priv);
+};
+
+int string_to_ethaddr(const char *str, u8 enetaddr[6]);
+void ethaddr_to_string(const u8 enetaddr[6], char *str);
+
+static inline struct param_mac *to_param_mac(struct param_d *p)
+{
+ return container_of(p, struct param_mac, param);
+}
+
+static int param_mac_set(struct device_d *dev, struct param_d *p, const char *val)
+{
+ struct param_mac *pm = to_param_mac(p);
+ char mac_save[6];
+ int ret;
+
+ if (!val)
+ return -EINVAL;
+
+ memcpy(mac_save, pm->mac, 6);
+
+ ret = string_to_ethaddr(val, pm->mac);
+ if (ret)
+ goto out;
+
+ if (!pm->set)
+ return 0;
+
+ ret = pm->set(p, p->driver_priv);
+ if (ret)
+ goto out;
+
+ return 0;
+out:
+ memcpy(pm->mac, mac_save, 6);
+
+ return ret;
+}
+
+static const char *param_mac_get(struct device_d *dev, struct param_d *p)
+{
+ struct param_mac *pm = to_param_mac(p);
+ int ret;
+
+ if (pm->get) {
+ ret = pm->get(p, p->driver_priv);
+ if (ret)
+ return NULL;
+ }
+
+ ethaddr_to_string(pm->mac, p->value);
+
+ return p->value;
+}
+
+struct param_d *dev_add_param_mac(struct device_d *dev, const char *name,
+ int (*set)(struct param_d *p, void *priv),
+ int (*get)(struct param_d *p, void *priv),
+ u8 *mac, void *priv)
+{
+ struct param_mac *pm;
+ int ret;
+
+ pm = xzalloc(sizeof(*pm));
+ pm->mac = mac;
+ pm->set = set;
+ pm->get = get;
+ pm->param.driver_priv = priv;
+ pm->param.value = pm->mac_str;
+
+ ret = __dev_add_param(&pm->param, dev, name,
+ param_mac_set, param_mac_get, 0);
+ if (ret) {
+ free(pm);
+ return ERR_PTR(ret);
+ }
+
+ return &pm->param;
+}
#endif
/**
diff --git a/lib/string.c b/lib/string.c
index ceced7f48e..6a39eb5ced 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -16,7 +16,7 @@
*/
#include <linux/types.h>
-#include <linux/string.h>
+#include <string.h>
#include <linux/ctype.h>
#include <malloc.h>
diff --git a/net/eth.c b/net/eth.c
index 1f48f2df8a..3ced3cddbe 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -257,17 +257,9 @@ int eth_rx(void)
return eth_current->recv(eth_current);
}
-static int eth_set_ethaddr(struct device_d *dev, struct param_d *param, const char *val)
+static int eth_set_ethaddr(struct param_d *param, void *priv)
{
- struct eth_device *edev = dev_to_edev(dev);
-
- if (!val)
- return dev_param_set_generic(dev, param, NULL);
-
- if (string_to_ethaddr(val, edev->ethaddr) < 0)
- return -EINVAL;
-
- dev_param_set_generic(dev, param, val);
+ struct eth_device *edev = priv;
edev->set_ethaddr(edev, edev->ethaddr);
@@ -345,7 +337,7 @@ int eth_register(struct eth_device *edev)
dev_add_param_ip(dev, "serverip", NULL, NULL, &edev->serverip, edev);
dev_add_param_ip(dev, "gateway", NULL, NULL, &edev->gateway, edev);
dev_add_param_ip(dev, "netmask", NULL, NULL, &edev->netmask, edev);
- dev_add_param(dev, "ethaddr", eth_set_ethaddr, NULL, 0);
+ dev_add_param_mac(dev, "ethaddr", eth_set_ethaddr, NULL, edev->ethaddr, edev);
if (edev->init)
edev->init(edev);
diff --git a/net/netconsole.c b/net/netconsole.c
index 2ab19de4d5..86a68e19d9 100644
--- a/net/netconsole.c
+++ b/net/netconsole.c
@@ -81,6 +81,9 @@ static int nc_getc(struct console_device *cdev)
struct nc_priv, cdev);
unsigned char c;
+ if (!priv->con)
+ return 0;
+
while (!kfifo_len(priv->fifo))
net_poll();
@@ -94,6 +97,9 @@ static int nc_tstc(struct console_device *cdev)
struct nc_priv *priv = container_of(cdev,
struct nc_priv, cdev);
+ if (!priv->con)
+ return 0;
+
if (priv->busy)
return kfifo_len(priv->fifo) ? 1 : 0;
diff --git a/scripts/omap4_usbboot/omap4_usbboot.c b/scripts/omap4_usbboot/omap4_usbboot.c
index e52108614b..0e5abcb159 100644
--- a/scripts/omap4_usbboot/omap4_usbboot.c
+++ b/scripts/omap4_usbboot/omap4_usbboot.c
@@ -35,16 +35,17 @@
#define WHITE 8
#define RED 1
#define BLACK 0
-#define FORMAT "%c[%d;%d;%dm"
-#define TARGET_FORMAT 0x1B, BRIGHT, RED+30, BLACK+40
-#define HOST_FORMAT 0x1B, RESET, WHITE+30, BLACK+40
-#define host_print(fmt, arg...) printf(FORMAT fmt FORMAT, \
+#define TFORMAT "%c[%d;%dm"
+#define HFORMAT "%c[%dm"
+#define TARGET_FORMAT 0x1B, BRIGHT, RED+30
+#define HOST_FORMAT 0x1B, RESET
+#define host_print(fmt, arg...) printf(HFORMAT fmt TFORMAT, \
HOST_FORMAT, ##arg, TARGET_FORMAT)
void panic(struct termios *t_restore)
{
tcsetattr(STDIN_FILENO, TCSANOW, t_restore);
- printf(FORMAT, HOST_FORMAT);
+ printf(HFORMAT, HOST_FORMAT);
exit(1);
}
@@ -354,7 +355,7 @@ int usb_boot(
tcgetattr(STDIN_FILENO, &vars.t_restore);
tn = vars.t_restore;
tn.c_lflag &= ~(ICANON | ECHO);
- printf(FORMAT, TARGET_FORMAT);
+ printf(TFORMAT, TARGET_FORMAT);
tcsetattr(STDIN_FILENO, TCSANOW, &tn);
if (pthread_create(&thread, NULL, listenerTask, &vars))
host_print("listenerTask failed\n");
@@ -375,7 +376,7 @@ int usb_boot(
usb_close(usb);
pthread_mutex_destroy(&vars.usb_mutex);
tcsetattr(STDIN_FILENO, TCSANOW, &vars.t_restore);
- printf(FORMAT, HOST_FORMAT);
+ printf(HFORMAT, HOST_FORMAT);
return 0;
}
@@ -415,7 +416,7 @@ int main(int argc, char **argv)
sz = s.st_size;
close(fd);
argv++;
- printf(FORMAT, HOST_FORMAT);
+ printf(HFORMAT, HOST_FORMAT);
for (once = 1;;) {
usb = usb_open(match_omap4_bootloader);
if (usb)