diff --git a/arch/arm/boards/archosg9/lowlevel.c b/arch/arm/boards/archosg9/lowlevel.c index 0334693..49c1541 100644 --- a/arch/arm/boards/archosg9/lowlevel.c +++ b/arch/arm/boards/archosg9/lowlevel.c @@ -48,8 +48,7 @@ set_muxconf_regs(); - /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(TPS62361_VSEL0_GPIO); + omap4460_scale_vcores(TPS62361_VSEL0_GPIO, 1380); /* Enable all clocks */ omap4_enable_all_clocks(); diff --git a/arch/arm/boards/panda/lowlevel.c b/arch/arm/boards/panda/lowlevel.c index ed1dc6f..5d3490f 100644 --- a/arch/arm/boards/panda/lowlevel.c +++ b/arch/arm/boards/panda/lowlevel.c @@ -52,6 +52,7 @@ struct dpll_param per = OMAP4_PER_DPLL_PARAM_38M4; struct dpll_param abe = OMAP4_ABE_DPLL_PARAM_38M4; struct dpll_param usb = OMAP4_USB_DPLL_PARAM_38M4; + unsigned int rev = omap4_revision(); writel(CM_SYS_CLKSEL_38M4, CM_SYS_CLKSEL); @@ -69,8 +70,10 @@ omap4_ddr_init(&ddr_regs_400_mhz_2cs, &core); - /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(TPS62361_VSEL0_GPIO); + if (rev < OMAP4460_ES1_0) + omap4430_scale_vcores(); + else + omap4460_scale_vcores(TPS62361_VSEL0_GPIO, 1210); } void barebox_arm_reset_vector(void) diff --git a/arch/arm/boards/pcm049/lowlevel.c b/arch/arm/boards/pcm049/lowlevel.c index 8bcecb1..6b12fa4 100644 --- a/arch/arm/boards/pcm049/lowlevel.c +++ b/arch/arm/boards/pcm049/lowlevel.c @@ -67,6 +67,7 @@ struct dpll_param per = OMAP4_PER_DPLL_PARAM_19M2; struct dpll_param abe = OMAP4_ABE_DPLL_PARAM_19M2; struct dpll_param usb = OMAP4_USB_DPLL_PARAM_19M2; + unsigned int rev = omap4_revision(); set_muxconf_regs(); @@ -77,12 +78,15 @@ #endif /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(TPS62361_VSEL0_GPIO); + if (rev < OMAP4460_ES1_0) + omap4430_scale_vcores(); + else + omap4460_scale_vcores(TPS62361_VSEL0_GPIO, 1320); writel(CM_SYS_CLKSEL_19M2, CM_SYS_CLKSEL); /* Configure all DPLL's at 100% OPP */ - if (omap4_revision() < OMAP4460_ES1_0) + if (rev < OMAP4460_ES1_0) omap4_configure_mpu_dpll(&mpu44xx); else omap4_configure_mpu_dpll(&mpu4460); diff --git a/arch/arm/boards/pcm051/board.c b/arch/arm/boards/pcm051/board.c index 8754ba5..eea5ebb 100644 --- a/arch/arm/boards/pcm051/board.c +++ b/arch/arm/boards/pcm051/board.c @@ -19,13 +19,21 @@ #include #include +#include #include #include #include #include +#include #include +#include #include #include +#include +#include +#include +#include +#include #include "mux.h" @@ -52,12 +60,91 @@ } mem_initcall(pcm051_mem_init); +static struct flash_platform_data pcm051_spi_flash = { + .name = "nor", + .type = "w25q64", +}; + +/* +* SPI Flash works at 80Mhz however the SPI controller runs with 48MHz. +* So setup Max speed to be less than the controller speed. +*/ +static struct spi_board_info pcm051_spi_board_info[] = { + { + .name = "m25p80", + .platform_data = &pcm051_spi_flash, + .max_speed_hz = 24000000, + .bus_num = 0, + .chip_select = 0, + }, +}; + +static struct cpsw_slave_data cpsw_slaves[] = { + { + .phy_id = 0, + .phy_if = PHY_INTERFACE_MODE_RMII, + }, +}; + +static struct cpsw_platform_data cpsw_data = { + .slave_data = cpsw_slaves, + .num_slaves = ARRAY_SIZE(cpsw_slaves), +}; + +static struct i2c_board_info i2c0_devices[] = { + { + I2C_BOARD_INFO("24c32", 0x52), + }, +}; + +static void pcm051_spi_init(void) +{ + int ret; + + am33xx_enable_spi0_pin_mux(); + + ret = spi_register_board_info(pcm051_spi_board_info, + ARRAY_SIZE(pcm051_spi_board_info)); + am33xx_add_spi0(); +} + +static void pcm051_eth_init(void) +{ + am33xx_register_ethaddr(0, 0); + + writel(0x49, AM33XX_MAC_MII_SEL); + + am33xx_enable_rmii1_pin_mux(); + + am33xx_add_cpsw(&cpsw_data); +} + +static void pcm051_i2c_init(void) +{ + am33xx_enable_i2c0_pin_mux(); + + i2c_register_board_info(0, i2c0_devices, ARRAY_SIZE(i2c0_devices)); + + am33xx_add_i2c0(NULL); +} + static int pcm051_devices_init(void) { pcm051_enable_mmc0_pin_mux(); am33xx_add_mmc0(NULL); + pcm051_spi_init(); + pcm051_eth_init(); + pcm051_i2c_init(); + + devfs_add_partition("nor0", 0x00000, SZ_128K, + DEVFS_PARTITION_FIXED, "xload"); + devfs_add_partition("nor0", SZ_128K, SZ_512K, + DEVFS_PARTITION_FIXED, "self0"); + devfs_add_partition("nor0", SZ_128K + SZ_512K, SZ_128K, + DEVFS_PARTITION_FIXED, "env0"); + armlinux_set_bootparams((void *)(AM33XX_DRAM_ADDR_SPACE_START + 0x100)); armlinux_set_architecture(MACH_TYPE_PCM051); diff --git a/arch/arm/boards/pcm051/env/boot/spi-nor b/arch/arm/boards/pcm051/env/boot/spi-nor new file mode 100644 index 0000000..d5f77c8 --- /dev/null +++ b/arch/arm/boards/pcm051/env/boot/spi-nor @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + boot-menu-add-entry "$0" "SPI NOR Flash" + exit +fi + +global.bootm.image="/dev/nor0.kernel" + +# Use rootfs form SD-Card for now as rootfs partition < 4MB +global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootfstype=ext3 rootwait" + diff --git a/arch/arm/boards/pcm051/env/init/mtdparts-nor b/arch/arm/boards/pcm051/env/init/mtdparts-nor new file mode 100644 index 0000000..91aa847 --- /dev/null +++ b/arch/arm/boards/pcm051/env/init/mtdparts-nor @@ -0,0 +1,12 @@ +#!/bin/sh + +if [ "$1" = menu ]; then + init-menu-add-entry "$0" "NOR partitions" + exit +fi + +mtdparts="128k(nor0.xload),512k(nor0.barebox),128k(nor0.bareboxenv),4M(nor0.kernel),-(nor0.root)" +kernelname="spi_flash" + +mtdparts-add -d nor0 -k ${kernelname} -p ${mtdparts} + diff --git a/arch/arm/boards/phycard-a-xl2/lowlevel.c b/arch/arm/boards/phycard-a-xl2/lowlevel.c index 07505ff..010171a 100644 --- a/arch/arm/boards/phycard-a-xl2/lowlevel.c +++ b/arch/arm/boards/phycard-a-xl2/lowlevel.c @@ -52,18 +52,21 @@ struct dpll_param per = OMAP4_PER_DPLL_PARAM_19M2; struct dpll_param abe = OMAP4_ABE_DPLL_PARAM_19M2; struct dpll_param usb = OMAP4_USB_DPLL_PARAM_19M2; + unsigned int rev = omap4_revision(); set_muxconf_regs(); omap4_ddr_init(&ddr_regs_mt42L64M64_25_400_mhz, &core); - /* Set VCORE1 = 1.3 V, VCORE2 = VCORE3 = 1.21V */ - omap4_scale_vcores(TPS62361_VSEL0_GPIO); + if (rev < OMAP4460_ES1_0) + omap4430_scale_vcores(); + else + omap4460_scale_vcores(TPS62361_VSEL0_GPIO, 1320); writel(CM_SYS_CLKSEL_19M2, CM_SYS_CLKSEL); /* Configure all DPLL's at 100% OPP */ - if (omap4_revision() < OMAP4460_ES1_0) + if (rev < OMAP4460_ES1_0) omap4_configure_mpu_dpll(&mpu44xx); else omap4_configure_mpu_dpll(&mpu4460); diff --git a/arch/arm/configs/pcm051_defconfig b/arch/arm/configs/pcm051_defconfig index 4da0ed4..8de3714 100644 --- a/arch/arm/configs/pcm051_defconfig +++ b/arch/arm/configs/pcm051_defconfig @@ -42,15 +42,25 @@ CONFIG_CMD_PARTITION=y CONFIG_CMD_GPIO=y CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_I2C=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y CONFIG_DRIVER_SERIAL_NS16550=y CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y -# CONFIG_SPI is not set +CONFIG_DRIVER_NET_CPSW=y +CONFIG_DRIVER_SPI_OMAP3=y +CONFIG_I2C=y +CONFIG_I2C_OMAP=y CONFIG_MTD=y +CONFIG_MTD_M25P80=y CONFIG_NAND=y CONFIG_USB=y CONFIG_MCI=y CONFIG_MCI_STARTUP=y CONFIG_MCI_OMAP_HSMMC=y +CONFIG_EEPROM_AT24=y CONFIG_FS_FAT=y CONFIG_FS_FAT_WRITE=y CONFIG_FS_FAT_LFN=y diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index 973068d..e5759f5 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -15,7 +15,7 @@ # GNU General Public License for more details. # # -obj-$(CONFIG_ARCH_OMAP) += syslib.o omap_devices.o omap_generic.o +obj-$(CONFIG_ARCH_OMAP) += syslib.o omap_devices.o omap_generic.o omap_fb.o pbl-$(CONFIG_ARCH_OMAP) += syslib.o obj-$(CONFIG_OMAP_CLOCK_SOURCE_S32K) += s32k_clksource.o obj-$(CONFIG_OMAP_CLOCK_SOURCE_DMTIMER0) += dmtimer0.o diff --git a/arch/arm/mach-omap/am33xx_mux.c b/arch/arm/mach-omap/am33xx_mux.c index 424d120..abc8586 100644 --- a/arch/arm/mach-omap/am33xx_mux.c +++ b/arch/arm/mach-omap/am33xx_mux.c @@ -314,3 +314,8 @@ { configure_module_pin_mux(mmc0_pin_mux); } + +void am33xx_enable_spi0_pin_mux(void) +{ + configure_module_pin_mux(spi0_pin_mux); +} diff --git a/arch/arm/mach-omap/include/mach/am33xx-devices.h b/arch/arm/mach-omap/include/mach/am33xx-devices.h index fe9fba9..6a4d901 100644 --- a/arch/arm/mach-omap/include/mach/am33xx-devices.h +++ b/arch/arm/mach-omap/include/mach/am33xx-devices.h @@ -37,4 +37,38 @@ AM335X_CPSW_BASE, SZ_32K, IORESOURCE_MEM, cpsw_data); } +static inline struct device_d *am33xx_add_spi(int id, resource_size_t start) +{ + return add_generic_device("omap3_spi", id, NULL, start + 0x100, SZ_4K - 0x100, + IORESOURCE_MEM, NULL); +} + +static inline struct device_d *am33xx_add_spi0(void) +{ + return am33xx_add_spi(0, AM33XX_MCSPI0_BASE); +} + +static inline struct device_d *am33xx_add_spi1(void) +{ + return am33xx_add_spi(1, AM33XX_MCSPI1_BASE); +} + +static inline struct device_d *am33xx_add_i2c0(void *pdata) +{ + return add_generic_device("i2c-am33xx", 0, NULL, AM33XX_I2C0_BASE, + SZ_4K, IORESOURCE_MEM, pdata); +} + +static inline struct device_d *am33xx_add_i2c1(void *pdata) +{ + return add_generic_device("i2c-am33xx", 1, NULL, AM33XX_I2C1_BASE, + SZ_4K, IORESOURCE_MEM, pdata); +} + +static inline struct device_d *am33xx_add_i2c2(void *pdata) +{ + return add_generic_device("i2c-am33xx", 2, NULL, AM33XX_I2C2_BASE, + SZ_4K, IORESOURCE_MEM, pdata); +} + #endif /* __MACH_OMAP3_DEVICES_H */ diff --git a/arch/arm/mach-omap/include/mach/am33xx-mux.h b/arch/arm/mach-omap/include/mach/am33xx-mux.h index 44b93bd..d6b19dd 100644 --- a/arch/arm/mach-omap/include/mach/am33xx-mux.h +++ b/arch/arm/mach-omap/include/mach/am33xx-mux.h @@ -256,5 +256,6 @@ extern void am33xx_enable_uart0_pin_mux(void); extern void am33xx_enable_uart2_pin_mux(void); extern void am33xx_enable_mmc0_pin_mux(void); +extern void am33xx_enable_spi0_pin_mux(void); #endif /*__AM33XX_MUX_H__ */ diff --git a/arch/arm/mach-omap/include/mach/am33xx-silicon.h b/arch/arm/mach-omap/include/mach/am33xx-silicon.h index 9edf4ca..8a7bd16 100644 --- a/arch/arm/mach-omap/include/mach/am33xx-silicon.h +++ b/arch/arm/mach-omap/include/mach/am33xx-silicon.h @@ -41,6 +41,11 @@ #define AM33XX_DRAM_ADDR_SPACE_START 0x80000000 #define AM33XX_DRAM_ADDR_SPACE_END 0xC0000000 +/* I2C */ +#define AM33XX_I2C0_BASE (AM33XX_L4_WKUP_BASE + 0x20B000) +#define AM33XX_I2C1_BASE (AM33XX_L4_PER_BASE + 0x02A000) +#define AM33XX_I2C2_BASE (AM33XX_L4_PER_BASE + 0x19C000) + /* GPMC */ #define AM33XX_GPMC_BASE 0x50000000 @@ -49,6 +54,10 @@ #define AM33XX_MMC1_BASE (AM33XX_L4_PER_BASE + 0x1D8000) #define AM33XX_MMCHS2_BASE 0x47810000 +/* SPI */ +#define AM33XX_MCSPI0_BASE (AM33XX_L4_PER_BASE + 0x30000) +#define AM33XX_MCSPI1_BASE (AM33XX_L4_PER_BASE + 0x1A0000) + /* DTMTimer0 */ #define AM33XX_DMTIMER0_BASE (AM33XX_L4_WKUP_BASE + 0x205000) diff --git a/arch/arm/mach-omap/include/mach/devices.h b/arch/arm/mach-omap/include/mach/devices.h index adae01b..537213f 100644 --- a/arch/arm/mach-omap/include/mach/devices.h +++ b/arch/arm/mach-omap/include/mach/devices.h @@ -9,6 +9,4 @@ struct device_d *omap_add_uart(int id, unsigned long base); -struct device_d *omap_add_i2c(int id, unsigned long base, void *pdata); - #endif /* __MACH_OMAP_DEVICES_H */ diff --git a/arch/arm/mach-omap/include/mach/generic.h b/arch/arm/mach-omap/include/mach/generic.h index 5a10a54..178c21f 100644 --- a/arch/arm/mach-omap/include/mach/generic.h +++ b/arch/arm/mach-omap/include/mach/generic.h @@ -27,4 +27,10 @@ #define cpu_is_omap4xxx() (0) #endif +#ifdef CONFIG_ARCH_AM33XX +#define cpu_is_am33xx() (1) +#else +#define cpu_is_am33xx() (0) +#endif + #endif diff --git a/arch/arm/mach-omap/include/mach/omap-fb.h b/arch/arm/mach-omap/include/mach/omap-fb.h new file mode 100644 index 0000000..f68dc1a --- /dev/null +++ b/arch/arm/mach-omap/include/mach/omap-fb.h @@ -0,0 +1,47 @@ +#ifndef H_BAREBOX_ARCH_ARM_MACH_OMAP_MACH_FB4_H +#define H_BAREBOX_ARCH_ARM_MACH_OMAP_MACH_FB4_H + +#include + +#define OMAP_DSS_LCD_TFT (1u << 0) +#define OMAP_DSS_LCD_IVS (1u << 1) +#define OMAP_DSS_LCD_IHS (1u << 2) +#define OMAP_DSS_LCD_IPC (1u << 3) +#define OMAP_DSS_LCD_IEO (1u << 4) +#define OMAP_DSS_LCD_RF (1u << 5) +#define OMAP_DSS_LCD_ONOFF (1u << 6) + +#define OMAP_DSS_LCD_DATALINES(_l) ((_l) << 10) +#define OMAP_DSS_LCD_DATALINES_msk OMAP_DSS_LCD_DATALINES(3u) +#define OMAP_DSS_LCD_DATALINES_12 OMAP_DSS_LCD_DATALINES(0u) +#define OMAP_DSS_LCD_DATALINES_16 OMAP_DSS_LCD_DATALINES(1u) +#define OMAP_DSS_LCD_DATALINES_18 OMAP_DSS_LCD_DATALINES(2u) +#define OMAP_DSS_LCD_DATALINES_24 OMAP_DSS_LCD_DATALINES(3u) + +struct omapfb_display { + struct fb_videomode mode; + + unsigned long config; + + unsigned int power_on_delay; + unsigned int power_off_delay; +}; + +struct omapfb_platform_data { + struct omapfb_display const *displays; + size_t num_displays; + + unsigned int dss_clk_hz; + + unsigned int bpp; + + struct resource const *screen; + + void (*enable)(int p); +}; + +struct device_d; +struct device_d *omap_add_display(struct omapfb_platform_data *o_pdata); + + +#endif /* H_BAREBOX_ARCH_ARM_MACH_OMAP_MACH_FB4_H */ diff --git a/arch/arm/mach-omap/include/mach/omap3-devices.h b/arch/arm/mach-omap/include/mach/omap3-devices.h index de67ea0..0809e95 100644 --- a/arch/arm/mach-omap/include/mach/omap3-devices.h +++ b/arch/arm/mach-omap/include/mach/omap3-devices.h @@ -77,17 +77,20 @@ static inline struct device_d *omap3_add_i2c1(void *pdata) { - return omap_add_i2c(0, OMAP3_I2C1_BASE, pdata); + return add_generic_device("i2c-omap3", 0, NULL, OMAP3_I2C1_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap3_add_i2c2(void *pdata) { - return omap_add_i2c(1, OMAP3_I2C2_BASE, pdata); + return add_generic_device("i2c-omap3", 1, NULL, OMAP3_I2C2_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap3_add_i2c3(void *pdata) { - return omap_add_i2c(2, OMAP3_I2C3_BASE, pdata); + return add_generic_device("i2c-omap3", 2, NULL, OMAP3_I2C3_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap3_add_ehci(void *pdata) diff --git a/arch/arm/mach-omap/include/mach/omap4-devices.h b/arch/arm/mach-omap/include/mach/omap4-devices.h index 561d9ce..76c9789 100644 --- a/arch/arm/mach-omap/include/mach/omap4-devices.h +++ b/arch/arm/mach-omap/include/mach/omap4-devices.h @@ -60,22 +60,26 @@ static inline struct device_d *omap44xx_add_i2c1(void *pdata) { - return omap_add_i2c(0, OMAP44XX_I2C1_BASE, pdata); + return add_generic_device("i2c-omap4", 0, NULL, OMAP44XX_I2C1_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap44xx_add_i2c2(void *pdata) { - return omap_add_i2c(1, OMAP44XX_I2C2_BASE, pdata); + return add_generic_device("i2c-omap4", 1, NULL, OMAP44XX_I2C2_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap44xx_add_i2c3(void *pdata) { - return omap_add_i2c(2, OMAP44XX_I2C3_BASE, pdata); + return add_generic_device("i2c-omap4", 2, NULL, OMAP44XX_I2C3_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap44xx_add_i2c4(void *pdata) { - return omap_add_i2c(3, OMAP44XX_I2C4_BASE, pdata); + return add_generic_device("i2c-omap4", 3, NULL, OMAP44XX_I2C4_BASE, + SZ_4K, IORESOURCE_MEM, pdata); } static inline struct device_d *omap44xx_add_ehci(void *pdata) diff --git a/arch/arm/mach-omap/include/mach/omap4-silicon.h b/arch/arm/mach-omap/include/mach/omap4-silicon.h index 666e721..336415c 100644 --- a/arch/arm/mach-omap/include/mach/omap4-silicon.h +++ b/arch/arm/mach-omap/include/mach/omap4-silicon.h @@ -230,7 +230,8 @@ void omap4_ddr_init(const struct ddr_regs *, const struct dpll_param *); void omap4_power_i2c_send(u32); unsigned int omap4_revision(void); -noinline int omap4_scale_vcores(unsigned vsel0_pin); +int omap4430_scale_vcores(void); +int omap4460_scale_vcores(unsigned vsel0_pin, unsigned volt_mv); void omap4_set_warmboot_order(u32 *device_list); #endif diff --git a/arch/arm/mach-omap/omap4_generic.c b/arch/arm/mach-omap/omap4_generic.c index 7d71fdc..a082b71 100644 --- a/arch/arm/mach-omap/omap4_generic.c +++ b/arch/arm/mach-omap/omap4_generic.c @@ -537,11 +537,9 @@ #define I2C_SLAVE 0x12 -noinline int omap4_scale_vcores(unsigned vsel0_pin) +noinline int omap4430_scale_vcores(void) { - void __iomem *base; unsigned int rev = omap4_revision(); - u32 val = 0; /* For VC bypass only VCOREx_CGF_FORCE is necessary and * VCOREx_CFG_VOLTAGE changes can be discarded @@ -549,50 +547,16 @@ writel(0, OMAP44XX_PRM_VC_CFG_I2C_MODE); writel(0x6026, OMAP44XX_PRM_VC_CFG_I2C_CLK); - /* TPS - supplies vdd_mpu on 4460 */ - if (rev >= OMAP4460_ES1_0) { - /* - * Setup SET1 and SET0 with right values so that kernel - * can use either of them based on its needs. - */ - omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET0, 1430); - omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET1, 1430); - - /* - * Select SET1 in TPS62361: - * VSEL1 is grounded on board. So the following selects - * VSEL1 = 0 and VSEL0 = 1 - */ - base = omap4_get_gpio_base(vsel0_pin); - - val = 1 << (vsel0_pin & GPIO_MASK); - writel(val, base + 0x190); - - val = readl(base + 0x134); - val &= ~(1 << (vsel0_pin & GPIO_MASK)); - writel(val, base + 0x134); - - val = 1 << (vsel0_pin & GPIO_MASK); - writel(val, base + 0x194); - } - - /* set VCORE1 force VSEL */ - /* + /* set VCORE1 force VSEL * 4430 : supplies vdd_mpu * Setting a high voltage for Nitro mode as smart reflex is not enabled. * We use the maximum possible value in the AVS range because the next * higher voltage in the discrete range (code >= 0b111010) is way too * high - * - * 4460 : supplies vdd_core - * */ - if (rev < OMAP4460_ES1_0) - /* 0x55: i2c addr, 3A: ~ 1430 mvolts*/ - omap4_power_i2c_send((0x3A55 << 8) | I2C_SLAVE); - else - /* 0x55: i2c addr, 28: ~ 1200 mvolts*/ - omap4_power_i2c_send((0x2855 << 8) | I2C_SLAVE); + + /* 0x55: i2c addr, 3A: ~ 1430 mvolts*/ + omap4_power_i2c_send((0x3A55 << 8) | I2C_SLAVE); /* FIXME: set VCORE2 force VSEL, Check the reset value */ omap4_power_i2c_send((0x295B << 8) | I2C_SLAVE); @@ -605,12 +569,59 @@ case OMAP4430_ES2_1: omap4_power_i2c_send((0x2A61 << 8) | I2C_SLAVE); break; - /* > OMAP4460_ES1_0 : VCORE3 not connected */ } return 0; } +noinline int omap4460_scale_vcores(unsigned vsel0_pin, unsigned volt_mv) +{ + void __iomem *base; + u32 val = 0; + + /* For VC bypass only VCOREx_CGF_FORCE is necessary and + * VCOREx_CFG_VOLTAGE changes can be discarded + */ + writel(0, OMAP44XX_PRM_VC_CFG_I2C_MODE); + writel(0x6026, OMAP44XX_PRM_VC_CFG_I2C_CLK); + + /* TPS - supplies vdd_mpu on 4460 + * Setup SET1 and don't touch SET0 it acts as boot voltage + * source after reset. + */ + + omap4_do_scale_tps62361(TPS62361_REG_ADDR_SET1, volt_mv); + + /* + * Select SET1 in TPS62361: + * VSEL1 is grounded on board. So the following selects + * VSEL1 = 0 and VSEL0 = 1 + */ + base = omap4_get_gpio_base(vsel0_pin); + + val = 1 << (vsel0_pin & GPIO_MASK); + writel(val, base + 0x190); + + val = readl(base + 0x134); + val &= ~(1 << (vsel0_pin & GPIO_MASK)); + writel(val, base + 0x134); + + val = 1 << (vsel0_pin & GPIO_MASK); + writel(val, base + 0x194); + + /* set VCORE1 force VSEL + * 4460 : supplies vdd_core + */ + + /* 0x55: i2c addr, 28: ~ 1200 mvolts*/ + omap4_power_i2c_send((0x2855 << 8) | I2C_SLAVE); + + /* FIXME: set VCORE2 force VSEL, Check the reset value */ + omap4_power_i2c_send((0x295B << 8) | I2C_SLAVE); + + return 0; +} + void omap4_do_set_mux(u32 base, struct pad_conf_entry const *array, int size) { int i; diff --git a/arch/arm/mach-omap/omap_devices.c b/arch/arm/mach-omap/omap_devices.c index 056cba5..30cfdd0 100644 --- a/arch/arm/mach-omap/omap_devices.c +++ b/arch/arm/mach-omap/omap_devices.c @@ -24,9 +24,3 @@ return add_ns16550_device(id, base, 1024, IORESOURCE_MEM_8BIT, &serial_plat); } - -struct device_d *omap_add_i2c(int id, unsigned long base, void *pdata) -{ - return add_generic_device("i2c-omap", id, NULL, base, SZ_4K, - IORESOURCE_MEM, pdata); -} diff --git a/arch/arm/mach-omap/omap_fb.c b/arch/arm/mach-omap/omap_fb.c new file mode 100644 index 0000000..ae318d8 --- /dev/null +++ b/arch/arm/mach-omap/omap_fb.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +#if defined(CONFIG_DRIVER_VIDEO_OMAP) +static struct resource omapfb_resources[] = { + { + .name = "omap4_dss", + .start = 0x48040000, + .end = 0x48040000 + 512 - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, + }, { + .name = "omap4_dispc", + .start = 0x48041000, + .end = 0x48041000 + 3072 - 1, + .flags = IORESOURCE_MEM | IORESOURCE_MEM_32BIT, + }, +}; + +struct device_d *omap_add_display(struct omapfb_platform_data *o_pdata) +{ + return add_generic_device_res("omap_fb", -1, + omapfb_resources, + ARRAY_SIZE(omapfb_resources), + o_pdata); +} +#else +struct device_d *omap_add_display(struct omapfb_platform_data *o_pdata) +{ + return NULL; +} +#endif +EXPORT_SYMBOL(omap_add_display); diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 503443f..b2a74c0 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -24,10 +24,6 @@ * GNU General Public License for more details. */ - -/* #include */ - - #include #include #include @@ -44,12 +40,6 @@ #include #include -#define OMAP_I2C_SIZE 0x3f -#define OMAP1_I2C_BASE 0xfffb3800 -#define OMAP2_I2C_BASE1 0x48070000 -#define OMAP2_I2C_BASE2 0x48072000 -#define OMAP2_I2C_BASE3 0x48060000 - /* This will be the driver name */ #define DRIVER_NAME "i2c-omap" @@ -141,11 +131,17 @@ #define SYSC_IDLEMODE_SMART 0x2 #define SYSC_CLOCKACTIVITY_FCLK 0x2 +/* i2c driver flags from kernel */ +#define OMAP_I2C_FLAG_RESET_REGS_POSTIDLE BIT(3) +#define OMAP_I2C_FLAG_BUS_SHIFT_NONE 0 +#define OMAP_I2C_FLAG_BUS_SHIFT_1 BIT(7) +#define OMAP_I2C_FLAG_BUS_SHIFT_2 BIT(8) +#define OMAP_I2C_FLAG_BUS_SHIFT__SHIFT 7 struct omap_i2c_struct { void *base; - u8 *regs; u8 reg_shift; + struct omap_i2c_driver_data *data; struct resource *ioarea; u32 speed; /* Speed of bus in Khz */ u16 cmd_err; @@ -241,22 +237,50 @@ [OMAP_I2C_IRQENABLE_CLR] = 0x30, }; +struct omap_i2c_driver_data { + u32 flags; + u32 fclk_rate; + u8 *regs; +}; + +static struct omap_i2c_driver_data omap3_data = { + .flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE | + OMAP_I2C_FLAG_BUS_SHIFT_2, + .fclk_rate = 48000, + .regs = (u8 *) reg_map, +}; + +static struct omap_i2c_driver_data omap4_data = { + .flags = OMAP_I2C_FLAG_BUS_SHIFT_NONE, + .fclk_rate = 96000, + .regs = (u8 *) omap4_reg_map, +}; + +static struct omap_i2c_driver_data am33xx_data = { + .flags = OMAP_I2C_FLAG_RESET_REGS_POSTIDLE | + OMAP_I2C_FLAG_BUS_SHIFT_NONE, + .fclk_rate = 96000, + .regs = (u8 *) omap4_reg_map, +}; + static inline void omap_i2c_write_reg(struct omap_i2c_struct *i2c_omap, int reg, u16 val) { __raw_writew(val, i2c_omap->base + - (i2c_omap->regs[reg] << i2c_omap->reg_shift)); + (i2c_omap->data->regs[reg] << i2c_omap->reg_shift)); } static inline u16 omap_i2c_read_reg(struct omap_i2c_struct *i2c_omap, int reg) { return __raw_readw(i2c_omap->base + - (i2c_omap->regs[reg] << i2c_omap->reg_shift)); + (i2c_omap->data->regs[reg] << i2c_omap->reg_shift)); } static void omap_i2c_unidle(struct omap_i2c_struct *i2c_omap) { - if (cpu_is_omap34xx()) { + struct omap_i2c_driver_data *i2c_data = i2c_omap->data; + + if (i2c_data->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, 0); omap_i2c_write_reg(i2c_omap, OMAP_I2C_PSC_REG, i2c_omap->pscstate); omap_i2c_write_reg(i2c_omap, OMAP_I2C_SCLL_REG, i2c_omap->scllstate); @@ -299,9 +323,8 @@ u16 psc = 0, scll = 0, sclh = 0, buf = 0; u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; uint64_t start; - - unsigned long fclk_rate = 12000000; unsigned long internal_clk = 0; + struct omap_i2c_driver_data *i2c_data = i2c_omap->data; if (i2c_omap->rev >= OMAP_I2C_REV_2) { /* Disable I2C controller before soft reset */ @@ -352,63 +375,50 @@ } omap_i2c_write_reg(i2c_omap, OMAP_I2C_CON_REG, 0); - /* omap1 handling is missing here */ + /* + * HSI2C controller internal clk rate should be 19.2 Mhz for + * HS and for all modes on 2430. On 34xx we can use lower rate + * to get longer filter period for better noise suppression. + * The filter is iclk (fclk for HS) period. + */ + if (i2c_omap->speed > 400) + internal_clk = 19200; + else if (i2c_omap->speed > 100) + internal_clk = 9600; + else + internal_clk = 4000; - if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap4xxx()) { + /* Compute prescaler divisor */ + psc = i2c_data->fclk_rate / internal_clk; + psc = psc - 1; - /* - * HSI2C controller internal clk rate should be 19.2 Mhz for - * HS and for all modes on 2430. On 34xx we can use lower rate - * to get longer filter period for better noise suppression. - * The filter is iclk (fclk for HS) period. - */ - if (i2c_omap->speed > 400 || cpu_is_omap2430()) - internal_clk = 19200; - else if (i2c_omap->speed > 100) - internal_clk = 9600; - else - internal_clk = 4000; - fclk_rate = 96000000 / 1000; + /* If configured for High Speed */ + if (i2c_omap->speed > 400) { + unsigned long scl; - /* Compute prescaler divisor */ - psc = fclk_rate / internal_clk; - psc = psc - 1; + /* For first phase of HS mode */ + scl = internal_clk / 400; + fsscll = scl - (scl / 3) - 7; + fssclh = (scl / 3) - 5; - /* If configured for High Speed */ - if (i2c_omap->speed > 400) { - unsigned long scl; + /* For second phase of HS mode */ + scl = i2c_data->fclk_rate / i2c_omap->speed; + hsscll = scl - (scl / 3) - 7; + hssclh = (scl / 3) - 5; + } else if (i2c_omap->speed > 100) { + unsigned long scl; - /* For first phase of HS mode */ - scl = internal_clk / 400; - fsscll = scl - (scl / 3) - 7; - fssclh = (scl / 3) - 5; - - /* For second phase of HS mode */ - scl = fclk_rate / i2c_omap->speed; - hsscll = scl - (scl / 3) - 7; - hssclh = (scl / 3) - 5; - } else if (i2c_omap->speed > 100) { - unsigned long scl; - - /* Fast mode */ - scl = internal_clk / i2c_omap->speed; - fsscll = scl - (scl / 3) - 7; - fssclh = (scl / 3) - 5; - } else { - /* Standard mode */ - fsscll = internal_clk / (i2c_omap->speed * 2) - 7; - fssclh = internal_clk / (i2c_omap->speed * 2) - 5; - } - scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; - sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; + /* Fast mode */ + scl = internal_clk / i2c_omap->speed; + fsscll = scl - (scl / 3) - 7; + fssclh = (scl / 3) - 5; } else { - /* Program desired operating rate */ - fclk_rate /= (psc + 1) * 1000; - if (psc > 2) - psc = 2; - scll = fclk_rate / (i2c_omap->speed * 2) - 7 + psc; - sclh = fclk_rate / (i2c_omap->speed * 2) - 7 + psc; + /* Standard mode */ + fsscll = internal_clk / (i2c_omap->speed * 2) - 7; + fssclh = internal_clk / (i2c_omap->speed * 2) - 5; } + scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; + sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ omap_i2c_write_reg(i2c_omap, OMAP_I2C_PSC_REG, psc); @@ -433,7 +443,7 @@ OMAP_I2C_IE_AL) | ((i2c_omap->fifo_size) ? (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0); omap_i2c_write_reg(i2c_omap, OMAP_I2C_IE_REG, i2c_omap->iestate); - if (cpu_is_omap34xx()) { + if (i2c_data->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { i2c_omap->pscstate = psc; i2c_omap->scllstate = scll; i2c_omap->sclhstate = sclh; @@ -525,15 +535,6 @@ if (dev->buf_len) { *dev->buf++ = w; dev->buf_len--; - /* Data reg from 2430 is 8 bit wide */ - if (!cpu_is_omap2430() && - !cpu_is_omap34xx() && - !cpu_is_omap4xxx()) { - if (dev->buf_len) { - *dev->buf++ = w >> 8; - dev->buf_len--; - } - } } else { if (stat & OMAP_I2C_STAT_RRDY) dev_err(&dev->adapter.dev, @@ -566,15 +567,6 @@ if (dev->buf_len) { w = *dev->buf++; dev->buf_len--; - /* Data reg from 2430 is 8 bit wide */ - if (!cpu_is_omap2430() && - !cpu_is_omap34xx() && - !cpu_is_omap4xxx()) { - if (dev->buf_len) { - w |= *dev->buf++ << 8; - dev->buf_len--; - } - } } else { if (stat & OMAP_I2C_STAT_XRDY) dev_err(&dev->adapter.dev, @@ -706,7 +698,7 @@ ret = omap_i2c_isr(i2c_omap); while (ret){ ret = omap_i2c_isr(i2c_omap); - if (is_timeout(start, MSECOND)) { + if (is_timeout(start, 50 * MSECOND)) { dev_err(&adapter->dev, "timed out on polling for " "open i2c message handling\n"); @@ -773,9 +765,10 @@ i2c_omap_probe(struct device_d *pdev) { struct omap_i2c_struct *i2c_omap; - /* struct i2c_platform_data *pdata; */ + struct omap_i2c_driver_data *i2c_data; int r; u32 speed = 0; + u16 s; i2c_omap = kzalloc(sizeof(struct omap_i2c_struct), GFP_KERNEL); if (!i2c_omap) { @@ -783,13 +776,13 @@ goto err_free_mem; } - if (cpu_is_omap4xxx()) { - i2c_omap->regs = (u8 *)omap4_reg_map; - i2c_omap->reg_shift = 0; - } else { - i2c_omap->regs = (u8 *)reg_map; - i2c_omap->reg_shift = 2; - } + r = dev_get_drvdata(pdev, (unsigned long *)&i2c_data); + if (r) + return r; + + i2c_omap->data = i2c_data; + i2c_omap->reg_shift = (i2c_data->flags >> + OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; if (pdev->platform_data != NULL) speed = *(u32 *)pdev->platform_data; @@ -802,28 +795,23 @@ omap_i2c_unidle(i2c_omap); i2c_omap->rev = omap_i2c_read_reg(i2c_omap, OMAP_I2C_REV_REG) & 0xff; - /* i2c_omap->base = OMAP2_I2C_BASE3; */ - if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap4xxx()) { - u16 s; + /* Set up the fifo size - Get total size */ + s = (omap_i2c_read_reg(i2c_omap, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3; + i2c_omap->fifo_size = 0x8 << s; - /* Set up the fifo size - Get total size */ - s = (omap_i2c_read_reg(i2c_omap, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3; - i2c_omap->fifo_size = 0x8 << s; + /* + * Set up notification threshold as half the total available + * size. This is to ensure that we can handle the status on int + * call back latencies. + */ - /* - * Set up notification threshold as half the total available - * size. This is to ensure that we can handle the status on int - * call back latencies. - */ + i2c_omap->fifo_size = (i2c_omap->fifo_size / 2); - i2c_omap->fifo_size = (i2c_omap->fifo_size / 2); - - if (i2c_omap->rev >= OMAP_I2C_REV_ON_4430) - i2c_omap->b_hw = 0; /* Disable hardware fixes */ - else - i2c_omap->b_hw = 1; /* Enable hardware fixes */ - } + if (i2c_omap->rev >= OMAP_I2C_REV_ON_4430) + i2c_omap->b_hw = 0; /* Disable hardware fixes */ + else + i2c_omap->b_hw = 1; /* Enable hardware fixes */ /* reset ASAP, clearing any IRQs */ omap_i2c_init(i2c_omap); @@ -856,9 +844,25 @@ return r; } +static struct platform_device_id omap_i2c_ids[] = { + { + .name = "i2c-omap3", + .driver_data = (unsigned long)&omap3_data, + }, { + .name = "i2c-omap4", + .driver_data = (unsigned long)&omap4_data, + }, { + .name = "i2c-am33xx", + .driver_data = (unsigned long)&am33xx_data, + }, { + /* sentinel */ + }, +}; + static struct driver_d omap_i2c_driver = { .probe = i2c_omap_probe, .name = DRIVER_NAME, + .id_table = omap_i2c_ids, }; device_platform_driver(omap_i2c_driver); diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index f14e28f..c279c21 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -40,7 +40,7 @@ config DRIVER_SPI_OMAP3 bool "OMAP3 McSPI Master driver" - depends on ARCH_OMAP3 + depends on ARCH_OMAP3 || ARCH_AM33XX endif diff --git a/drivers/spi/omap3_spi.c b/drivers/spi/omap3_spi.c index e6581df..5c8cc88 100644 --- a/drivers/spi/omap3_spi.c +++ b/drivers/spi/omap3_spi.c @@ -325,17 +325,6 @@ static int omap3_spi_setup(struct spi_device *spi) { - struct spi_master *master = spi->master; - - if (((master->bus_num == 1) && (spi->chip_select > 3)) || - ((master->bus_num == 2) && (spi->chip_select > 1)) || - ((master->bus_num == 3) && (spi->chip_select > 1)) || - ((master->bus_num == 4) && (spi->chip_select > 0))) { - printf("SPI error: unsupported chip select %i \ - on bus %i\n", spi->chip_select, master->bus_num); - return -EINVAL; - } - if (spi->max_speed_hz > OMAP3_MCSPI_MAX_FREQ) { printf("SPI error: unsupported frequency %i Hz. \ Max frequency is 48 Mhz\n", spi->max_speed_hz); @@ -368,16 +357,24 @@ * McSPI3 has 2 CS (bus 3, cs 0 - 1) * McSPI4 has 1 CS (bus 4, cs 0) * + * AM335x McSPI has 2 busses with 2 chip selects: + * McSPI0 has 2 CS (bus 0, cs 0 - 1) + * McSPI1 has 2 CS (bus 1, cs 0 - 1) + * * The board code has to make sure that it does not use * invalid buses or chip selects. */ master->bus_num = dev->id; - master->num_chipselect = 4; + + if (IS_ENABLED(CONFIG_ARCH_OMAP3)) + master->num_chipselect = 4; + else + master->num_chipselect = 2; master->setup = omap3_spi_setup; master->transfer = omap3_spi_transfer; - omap3_master->regs = dev_request_mem_region(dev, 0);; + omap3_master->regs = dev_request_mem_region(dev, 0); spi_reset(master); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6d6b08f..0639d9c 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -45,6 +45,14 @@ help Add support for the S3C244x LCD controller. +config DRIVER_VIDEO_OMAP + bool "OMAP framebuffer driver" + depends on ARCH_OMAP4 + help + Add support for OMAP Display Controller. Currently this + driver only supports OMAP4 SoCs in DISPC parallel mode on + LCD2 (MIPI DPI). + if DRIVER_VIDEO_S3C24XX config DRIVER_VIDEO_S3C_VERBOSE diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 7429141..67169d1 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -8,3 +8,4 @@ obj-$(CONFIG_DRIVER_VIDEO_S3C24XX) += s3c24xx.o obj-$(CONFIG_DRIVER_VIDEO_PXA) += pxa.o obj-$(CONFIG_DRIVER_VIDEO_SDL) += sdl.o +obj-$(CONFIG_DRIVER_VIDEO_OMAP) += omap.o diff --git a/drivers/video/omap.c b/drivers/video/omap.c new file mode 100644 index 0000000..487aca6 --- /dev/null +++ b/drivers/video/omap.c @@ -0,0 +1,524 @@ +/* + * TI Omap Frame Buffer device driver + * + * Copyright (C) 2013 Christoph Fritz + * Based on work by Enrico Scholz, sponsored by Phytec + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "omap.h" + +struct omapfb_device { + struct fb_info info; + struct device_d *dev; + + struct omapfb_display const *cur_display; + + struct omapfb_display const *displays; + size_t num_displays; + + void __iomem *dss; + void __iomem *dispc; + + struct { + void __iomem *addr; + size_t size; + } prealloc_screen; + + struct { + uint32_t dispc_control; + uint32_t dispc_pol_freq; + } shadow; + + struct { + unsigned int dss_clk_hz; + unsigned int lckd; + unsigned int pckd; + } divisor; + size_t dma_size; + void (*enable_fn)(int); + + struct fb_videomode video_modes[]; +}; + +static inline struct omapfb_device *to_omapfb(const struct fb_info *info) +{ + return container_of(info, struct omapfb_device, info); +} + +static void omapfb_enable(struct fb_info *info) +{ + struct omapfb_device *fbi = to_omapfb(info); + + dev_dbg(fbi->dev, "%s\n", __func__); + + if (!fbi->cur_display) { + dev_err(fbi->dev, "no valid mode set\n"); + return; + } + + if (fbi->enable_fn) + fbi->enable_fn(1); + + udelay(fbi->cur_display->power_on_delay * 1000u); + + o4_dispc_write(o4_dispc_read(O4_DISPC_CONTROL2) | + DSS_DISPC_CONTROL_LCDENABLE | + DSS_DISPC_CONTROL_LCDENABLESIGNAL, O4_DISPC_CONTROL2); + + o4_dispc_write(o4_dispc_read(O4_DISPC_VID1_ATTRIBUTES) | + DSS_DISPC_VIDn_ATTRIBUTES_VIDENABLE, O4_DISPC_VID1_ATTRIBUTES); + + o4_dispc_write(o4_dispc_read(O4_DISPC_CONTROL2) | + DSS_DISPC_CONTROL_GOLCD, O4_DISPC_CONTROL2); +} + +static void omapfb_disable(struct fb_info *info) +{ + struct omapfb_device *fbi = to_omapfb(info); + + dev_dbg(fbi->dev, "%s\n", __func__); + + if (!fbi->cur_display) { + dev_err(fbi->dev, "no valid mode set\n"); + return; + } + + o4_dispc_write(o4_dispc_read(O4_DISPC_CONTROL2) & + ~(DSS_DISPC_CONTROL_LCDENABLE | + DSS_DISPC_CONTROL_LCDENABLESIGNAL), O4_DISPC_CONTROL2); + + o4_dispc_write(o4_dispc_read(O4_DISPC_VID1_ATTRIBUTES) & + ~(DSS_DISPC_VIDn_ATTRIBUTES_VIDENABLE), + O4_DISPC_VID1_ATTRIBUTES); + + if (fbi->prealloc_screen.addr == NULL) { + /* free frame buffer; but only when screen is not + * preallocated */ + if (info->screen_base) + dma_free_coherent(info->screen_base, fbi->dma_size); + } + + info->screen_base = NULL; + + udelay(fbi->cur_display->power_off_delay * 1000u); + + if (fbi->enable_fn) + fbi->enable_fn(0); +} + +static void omapfb_calc_divisor(struct omapfb_device *fbi, + struct fb_videomode const *mode) +{ + unsigned int l, k, t, b; + + b = UINT_MAX; + for (l = 1; l < 256; l++) { + for (k = 1; k < 256; k++) { + t = abs(mode->pixclock * 100 - + (fbi->divisor.dss_clk_hz / l / k)); + if (t <= b) { + b = t; + fbi->divisor.lckd = l; + fbi->divisor.pckd = k; + } + } + } +} + +static unsigned int omapfb_calc_format(struct fb_info const *info) +{ + struct omapfb_device *fbi = to_omapfb(info); + + switch (info->bits_per_pixel) { + case 24: + return 9; + case 32: + return 0x8; /* xRGB24-8888 (32-bit container) */ + default: + dev_err(fbi->dev, "%s: unsupported bpp %d\n", __func__, + info->bits_per_pixel); + return 0; + } +} + +struct omapfb_colors { + struct fb_bitfield red; + struct fb_bitfield green; + struct fb_bitfield blue; + struct fb_bitfield transp; +}; + +static struct omapfb_colors const omapfb_col[] = { + [0] = { + .red = { .length = 0, .offset = 0 }, + }, + [1] = { + .blue = { .length = 8, .offset = 0 }, + .green = { .length = 8, .offset = 8 }, + .red = { .length = 8, .offset = 16 }, + }, + [2] = { + .blue = { .length = 8, .offset = 0 }, + .green = { .length = 8, .offset = 8 }, + .red = { .length = 8, .offset = 16 }, + .transp = { .length = 8, .offset = 24 }, + }, +}; + +static void omapfb_fill_shadow(struct omapfb_device *fbi, + struct omapfb_display const *display) +{ + fbi->shadow.dispc_control = 0; + fbi->shadow.dispc_pol_freq = 0; + + fbi->shadow.dispc_control |= DSS_DISPC_CONTROL_STNTFT; + + switch (display->config & OMAP_DSS_LCD_DATALINES_msk) { + case OMAP_DSS_LCD_DATALINES_12: + fbi->shadow.dispc_control |= DSS_DISPC_CONTROL_TFTDATALINES_12; + break; + case OMAP_DSS_LCD_DATALINES_16: + fbi->shadow.dispc_control |= DSS_DISPC_CONTROL_TFTDATALINES_16; + break; + case OMAP_DSS_LCD_DATALINES_18: + fbi->shadow.dispc_control |= DSS_DISPC_CONTROL_TFTDATALINES_18; + break; + case OMAP_DSS_LCD_DATALINES_24: + fbi->shadow.dispc_control |= DSS_DISPC_CONTROL_TFTDATALINES_24; + break; + } + + if (display->config & OMAP_DSS_LCD_IPC) + fbi->shadow.dispc_pol_freq |= DSS_DISPC_POL_FREQ_IPC; + + if (display->config & OMAP_DSS_LCD_IVS) + fbi->shadow.dispc_pol_freq |= DSS_DISPC_POL_FREQ_IVS; + + if (display->config & OMAP_DSS_LCD_IHS) + fbi->shadow.dispc_pol_freq |= DSS_DISPC_POL_FREQ_IHS; + + if (display->config & OMAP_DSS_LCD_IEO) + fbi->shadow.dispc_pol_freq |= DSS_DISPC_POL_FREQ_IEO; + + if (display->config & OMAP_DSS_LCD_RF) + fbi->shadow.dispc_pol_freq |= DSS_DISPC_POL_FREQ_RF; + + if (display->config & OMAP_DSS_LCD_ONOFF) + fbi->shadow.dispc_pol_freq |= DSS_DISPC_POL_FREQ_ONOFF; +} + +static int omapfb_find_display_by_name(struct omapfb_device *fbi, + const char *name) +{ + int i; + + for (i = 0; i < fbi->num_displays; ++i) { + if (strcmp(name, fbi->displays[i].mode.name) == 0) + return i; + } + return -ENXIO; +} + +static int omapfb_activate_var(struct fb_info *info) +{ + struct omapfb_device *fbi = to_omapfb(info); + struct fb_videomode const *mode = info->mode; + size_t size = mode->xres * mode->yres * (info->bits_per_pixel / 8); + int rc; + unsigned int fmt = omapfb_calc_format(info); + struct omapfb_colors const *cols; + struct omapfb_display const *new_display = NULL; + + rc = omapfb_find_display_by_name(fbi, mode->name); + if (rc < 0) { + dev_err(fbi->dev, "no display found for this mode '%s'\n", + mode->name); + goto out; + } + new_display = &fbi->displays[rc]; + + /*Free old screen buf*/ + if (!fbi->prealloc_screen.addr && info->screen_base) + dma_free_coherent(info->screen_base, fbi->dma_size); + + fbi->dma_size = PAGE_ALIGN(size); + + if (!fbi->prealloc_screen.addr) { + /* case 1: no preallocated screen */ + info->screen_base = dma_alloc_coherent(size); + } else if (fbi->prealloc_screen.size < fbi->dma_size) { + /* case 2: preallocated screen, but too small */ + dev_err(fbi->dev, + "allocated framebuffer too small (%zu < %zu)\n", + fbi->prealloc_screen.size, fbi->dma_size); + rc = -ENOMEM; + goto out; + } else { + /* case 3: preallocated screen */ + info->screen_base = fbi->prealloc_screen.addr; + } + + omapfb_fill_shadow(fbi, new_display); + + omapfb_calc_divisor(fbi, mode); + + switch (info->bits_per_pixel) { + case 24: + cols = &omapfb_col[1]; + break; + case 32: + cols = &omapfb_col[2]; + break; + default: + cols = &omapfb_col[0]; + } + + info->red = cols->red; + info->green = cols->green; + info->blue = cols->blue; + info->transp = cols->transp; + + o4_dispc_write(fbi->shadow.dispc_control, O4_DISPC_CONTROL2); + + o4_dispc_write(fbi->shadow.dispc_pol_freq, O4_DISPC_POL_FREQ2); + + o4_dispc_write(DSS_DISPC_TIMING_H_HSW(mode->hsync_len - 1) | + DSS_DISPC_TIMING_H_HFP(mode->right_margin - 1) | + DSS_DISPC_TIMING_H_HBP(mode->left_margin - 1), + O4_DISPC_TIMING_H2); + + o4_dispc_write(DSS_DISPC_TIMING_V_VSW(mode->vsync_len - 1) | + DSS_DISPC_TIMING_V_VFP(mode->lower_margin) | + DSS_DISPC_TIMING_V_VBP(mode->upper_margin), O4_DISPC_TIMING_V2); + + o4_dispc_write(DSS_DISPC_DIVISOR_ENABLE | DSS_DISPC_DIVISOR_LCD(1), + O4_DISPC_DIVISOR); + + o4_dispc_write(DSS_DISPC_DIVISOR2_LCD(fbi->divisor.lckd) | + DSS_DISPC_DIVISOR2_PCD(fbi->divisor.pckd), O4_DISPC_DIVISOR2); + + o4_dispc_write(DSS_DISPC_SIZE_LCD_PPL(mode->xres - 1) | + DSS_DISPC_SIZE_LCD_LPP(mode->yres - 1), O4_DISPC_SIZE_LCD2); + + o4_dispc_write(0x0000ff00, O4_DISPC_DEFAULT_COLOR2); + + /* we use VID1 */ + o4_dispc_write((uintptr_t)info->screen_base, O4_DISPC_VID1_BA0); + o4_dispc_write((uintptr_t)info->screen_base, O4_DISPC_VID1_BA1); + + o4_dispc_write(DSS_DISPC_VIDn_POSITION_VIDPOSX(0) | + DSS_DISPC_VIDn_POSITION_VIDPOSY(0), O4_DISPC_VID1_POSITION); + o4_dispc_write(DSS_DISPC_VIDn_SIZE_VIDSIZEX(mode->xres - 1) | + DSS_DISPC_VIDn_SIZE_VIDSIZEY(mode->yres - 1), + O4_DISPC_VID1_SIZE); + o4_dispc_write(DSS_DISPC_VIDn_PICTURE_SIZE_VIDORGSIZEX(mode->xres - 1) | + DSS_DISPC_VIDn_PICTURE_SIZE_VIDORGSIZEY(mode->yres - 1), + O4_DISPC_VID1_PICTURE_SIZE); + o4_dispc_write(1, O4_DISPC_VID1_ROW_INC); + o4_dispc_write(1, O4_DISPC_VID1_PIXEL_INC); + + o4_dispc_write(0xfff, O4_DISPC_VID1_PRELOAD); + + o4_dispc_write(DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(fmt) | + DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE_8x128 | + DSS_DISPC_VIDn_ATTRIBUTES_ZORDERENABLE | + DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2_SECONDARY_LCD, + O4_DISPC_VID1_ATTRIBUTES); + + rc = wait_on_timeout(OFB_TIMEOUT, + !(o4_dispc_read(O4_DISPC_CONTROL2) & + DSS_DISPC_CONTROL_GOLCD)); + + if (rc) { + dev_err(fbi->dev, "timeout: dispc golcd\n"); + goto out; + } + + o4_dispc_write(o4_dispc_read(O4_DISPC_CONTROL2) | + DSS_DISPC_CONTROL_GOLCD, O4_DISPC_CONTROL2); + + fbi->cur_display = new_display; + info->xres = mode->xres; + info->yres = mode->yres; + + rc = 0; + +out: + return rc; +} + +static int omapfb_reset(struct omapfb_device const *fbi) +{ + uint32_t v = o4_dispc_read(O4_DISPC_CONTROL2); + int rc; + + /* step 1: stop the LCD controller */ + if (v & DSS_DISPC_CONTROL_LCDENABLE) { + o4_dispc_write(v & ~DSS_DISPC_CONTROL_LCDENABLE, + O4_DISPC_CONTROL2); + + o4_dispc_write(DSS_DISPC_IRQSTATUS_FRAMEDONE2, + O4_DISPC_IRQSTATUS); + + rc = wait_on_timeout(OFB_TIMEOUT, + ((o4_dispc_read(O4_DISPC_IRQSTATUS) & + DSS_DISPC_IRQSTATUS_FRAMEDONE) != 0)); + + if (rc) { + dev_err(fbi->dev, "timeout: irqstatus framedone\n"); + return -ETIMEDOUT; + } + } + + /* step 2: wait for reset done status */ + rc = wait_on_timeout(OFB_TIMEOUT, + (o4_dss_read(O4_DSS_SYSSTATUS) & + DSS_DSS_SYSSTATUS_RESETDONE)); + + if (rc) { + dev_err(fbi->dev, "timeout: sysstatus resetdone\n"); + return -ETIMEDOUT; + } + + /* DSS_CTL: set to reset value */ + o4_dss_write(0, O4_DSS_CTRL); + + return 0; +} + +static struct fb_ops omapfb_ops = { + .fb_enable = omapfb_enable, + .fb_disable = omapfb_disable, + .fb_activate_var = omapfb_activate_var, +}; + +static int omapfb_probe(struct device_d *dev) +{ + struct omapfb_platform_data const *pdata = dev->platform_data; + struct omapfb_device *fbi; + struct fb_info *info; + int rc; + size_t i; + + fbi = xzalloc(sizeof *fbi + + pdata->num_displays * sizeof fbi->video_modes[0]); + info = &fbi->info; + + fbi->dev = dev; + + /* CM_DSS_CLKSTCTRL (TRM: 935) trigger SW_WKUP */ + __raw_writel(0x2, 0x4a009100); /* TODO: move this to clockmanagement */ + + fbi->dss = dev_request_mem_region_by_name(dev, "omap4_dss"); + fbi->dispc = dev_request_mem_region_by_name(dev, "omap4_dispc"); + + if (!fbi->dss || !fbi->dispc) { + dev_err(dev, "Insufficient register description\n"); + rc = -EINVAL; + goto out; + } + + dev_info(dev, "HW-Revision 0x%04x 0x%04x\n", + o4_dss_read(O4_DISPC_REVISION), + o4_dss_read(O4_DSS_REVISION)); + + if (!pdata->dss_clk_hz | !pdata->displays | !pdata->num_displays | + !pdata->bpp) { + dev_err(dev, "Insufficient omapfb_platform_data\n"); + rc = -EINVAL; + goto out; + } + + fbi->enable_fn = pdata->enable; + fbi->displays = pdata->displays; + fbi->num_displays = pdata->num_displays; + fbi->divisor.dss_clk_hz = pdata->dss_clk_hz; + + 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->priv = fbi; + info->fbops = &omapfb_ops; + info->bits_per_pixel = pdata->bpp; + + if (pdata->screen) { + if (!IS_ALIGNED(pdata->screen->start, PAGE_SIZE) || + !IS_ALIGNED(resource_size(pdata->screen), PAGE_SIZE)) { + dev_err(dev, "screen resource not aligned\n"); + rc = -EINVAL; + goto out; + } + fbi->prealloc_screen.addr = + (void __iomem *)pdata->screen->start; + fbi->prealloc_screen.size = resource_size(pdata->screen); + remap_range(fbi->prealloc_screen.addr, + fbi->prealloc_screen.size, + mmu_get_pte_uncached_flags()); + } + + rc = omapfb_reset(fbi); + if (rc < 0) { + dev_err(dev, "failed to reset: %d\n", rc); + goto out; + } + + rc = register_framebuffer(info); + if (rc < 0) { + dev_err(dev, "failed to register framebuffer: %d\n", rc); + goto out; + } + + rc = 0; + dev_info(dev, "registered\n"); + +out: + if (rc < 0) + free(fbi); + + return rc; +} + +static struct driver_d omapfb_driver = { + .name = "omap_fb", + .probe = omapfb_probe, +}; + +static int omapfb_init(void) +{ + return platform_driver_register(&omapfb_driver); +} + +device_initcall(omapfb_init); diff --git a/drivers/video/omap.h b/drivers/video/omap.h new file mode 100644 index 0000000..ac9e1ce --- /dev/null +++ b/drivers/video/omap.h @@ -0,0 +1,187 @@ +/* + * TI Omap4 Frame Buffer device driver + * + * Copyright (C) 2013 Christoph Fritz + * + * 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. + */ + +#ifndef H_BAREBOX_DRIVER_VIDEO_OMAP4_REGS_H +#define H_BAREBOX_DRIVER_VIDEO_OMAP4_REGS_H + +#include +#include + +#define OFB_TIMEOUT (128 * USECOND) + +#define _ofb_read(io, reg) __raw_readl((io)+(reg)) +#define _ofb_write(val, io, reg) __raw_writel((val), (io)+(reg)) + +/* TRM: 10.1.3.2 DSS Registers */ +#define O4_DSS_REVISION 0x0 +#define O4_DSS_SYSSTATUS 0x14 +#define O4_DSS_CTRL 0x40 +#define O4_DSS_STATUS 0x5c + +#define o4_dss_read(reg) _ofb_read(fbi->dss, reg) +#define o4_dss_write(val, reg) _ofb_write(val, fbi->dss, reg) + +/* TRM: 10.2.7.3 Display Controller Registers */ +#define O4_DISPC_REVISION 0x0 +#define O4_DISPC_IRQSTATUS 0x18 +#define O4_DISPC_VID1_BA0 0xbc +#define O4_DISPC_VID1_BA1 0xc0 +#define O4_DISPC_VID1_POSITION 0xc4 +#define O4_DISPC_VID1_SIZE 0xc8 +#define O4_DISPC_VID1_ATTRIBUTES 0xcc +#define O4_DISPC_VID1_ROW_INC 0xd8 +#define O4_DISPC_VID1_PIXEL_INC 0xdc +#define O4_DISPC_VID1_PICTURE_SIZE 0xe4 +#define O4_DISPC_VID1_PRELOAD 0x230 +#define O4_DISPC_CONTROL2 0x238 +#define O4_DISPC_DEFAULT_COLOR2 0x3ac +#define O4_DISPC_SIZE_LCD2 0x3cc +#define O4_DISPC_TIMING_H2 0x400 +#define O4_DISPC_TIMING_V2 0x404 +#define O4_DISPC_POL_FREQ2 0x408 +#define O4_DISPC_DIVISOR2 0x40c +#define O4_DISPC_DIVISOR 0x804 + +#define o4_dispc_read(reg) _ofb_read(fbi->dispc, reg) +#define o4_dispc_write(val, reg) _ofb_write(val, fbi->dispc, reg) + +#define DSS_DISPC_VIDn_POSITION_VIDPOSX(_x) ((_x) << 0) +#define DSS_DISPC_VIDn_POSITION_VIDPOSY(_y) ((_y) << 16) + +#define DSS_DISPC_VIDn_PICTURE_SIZE_VIDORGSIZEX(_x) ((_x) << 0) +#define DSS_DISPC_VIDn_PICTURE_SIZE_VIDORGSIZEY(_y) ((_y) << 16) + +#define DSS_DISPC_VIDn_SIZE_VIDSIZEX(_x) ((_x) << 0) +#define DSS_DISPC_VIDn_SIZE_VIDSIZEY(_y) ((_y) << 16) + +#define DSS_DISPC_SIZE_LCD_PPL(_x) ((_x) << 0) +#define DSS_DISPC_SIZE_LCD_LPP(_y) ((_y) << 16) + +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDENABLE (1u << 0) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(_fmt) ((_fmt) << 1) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_RGB12 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(4u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_ARGB16 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(5u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_RGB16 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(6u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_ARGB16o \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(7u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_xRGB24u \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(8u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_RGB24p \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(9u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_YUV2 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(10u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_UYVY \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(11u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_ARGB32 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(12u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_RGBA32 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(13u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT_xRGB32 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDFORMAT(14u) + +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE(_b) ((_b) << 14) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE_2x128 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE(0u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE_4x128 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE(1u) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE_8x128 \ + DSS_DISPC_VIDn_ATTRIBUTES_VIDBURSTSIZE(2u) + +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDCHANNELOUT (1u << 16) +#define DSS_DISPC_VIDn_ATTRIBUTES_SELFREFRESHAUTO (1u << 17) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDFIFOPRELOAD (1u << 19) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDVERTICALTAPS (1u << 21) +#define DSS_DISPC_VIDn_ATTRIBUTES_DOUBLESTRIDE (1u << 22) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDARBITRATION (1u << 23) +#define DSS_DISPC_VIDn_ATTRIBUTES_VIDSELFREFRESH (1u << 24) +#define DSS_DISPC_VIDn_ATTRIBUTES_ZORDERENABLE (1u << 25) + +#define DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2(_b) ((_b) << 30) +#define DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2_PRIMARY_LCD \ + DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2(0u) +#define DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2_SECONDARY_LCD \ + DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2(1u) +#define DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2_WRITEBACK_MEM \ + DSS_DISPC_VIDn_ATTRIBUTES_CHANNELOUT2(3u) + +#define DSS_DISPC_CONTROL_LCDENABLE (1u << 0) +#define DSS_DISPC_CONTROL_TVENABLE (1u << 1) +#define DSS_DISPC_CONTROL_MONOCOLOR (1u << 2) +#define DSS_DISPC_CONTROL_STNTFT (1u << 3) +#define DSS_DISPC_CONTROL_M8B (1u << 4) +#define DSS_DISPC_CONTROL_GOLCD (1u << 5) +#define DSS_DISPC_CONTROL_GOTV (1u << 6) +#define DSS_DISPC_CONTROL_STDITHERENABLE (1u << 7) + +#define DSS_DISPC_CONTROL_TFTDATALINES(_l) ((_l) << 8) +#define DSS_DISPC_CONTROL_TFTDATALINES_12 \ + DSS_DISPC_CONTROL_TFTDATALINES(0u) +#define DSS_DISPC_CONTROL_TFTDATALINES_16 \ + DSS_DISPC_CONTROL_TFTDATALINES(1u) +#define DSS_DISPC_CONTROL_TFTDATALINES_18 \ + DSS_DISPC_CONTROL_TFTDATALINES(2u) +#define DSS_DISPC_CONTROL_TFTDATALINES_24 \ + DSS_DISPC_CONTROL_TFTDATALINES(3u) + +#define DSS_DISPC_CONTROL_STALLMODE (1u << 11) +#define DSS_DISPC_CONTROL_OVERLAYOPTIMIZATION (1u << 12) +#define DSS_DISPC_CONTROL_GPIN0 (1u << 13) /* ro */ +#define DSS_DISPC_CONTROL_GPIN1 (1u << 14) /* ro */ +#define DSS_DISPC_CONTROL_GPOUT0 (1u << 15) +#define DSS_DISPC_CONTROL_GPOUT1 (1u << 16) +#define DSS_DISPC_CONTROL_HT(_ht) ((_ht) << 17) +#define DSS_DISPC_CONTROL_TDMENABLE (1u << 20) +#define DSS_DISPC_CONTROL_TDMPARALLELMODE(_pm) ((_pm) << 21) +#define DSS_DISPC_CONTROL_TDMCYCLEFORMAT(_cf) ((_cf) << 23) +#define DSS_DISPC_CONTROL_TDMUNUSEDBITS(_ub) ((_ub) << 25) +#define DSS_DISPC_CONTROL_PCKFREEENABLE (1u << 27) +#define DSS_DISPC_CONTROL_LCDENABLESIGNAL (1u << 28) +#define DSS_DISPC_CONTROL_LCDENABLEPOL (1u << 29) +#define DSS_DISPC_CONTROL_SPATIALTEMPD(_df) ((_df) << 30) + +#define DSS_DISPC_POL_FREQ_IVS (1u << 12) +#define DSS_DISPC_POL_FREQ_IHS (1u << 13) +#define DSS_DISPC_POL_FREQ_IPC (1u << 14) +#define DSS_DISPC_POL_FREQ_IEO (1u << 15) +#define DSS_DISPC_POL_FREQ_RF (1u << 16) +#define DSS_DISPC_POL_FREQ_ONOFF (1u << 17) + +#define DSS_DISPC_TIMING_H_HSW(_hsw) ((_hsw) << 0) +#define DSS_DISPC_TIMING_H_HFP(_hfp) ((_hfp) << 8) +#define DSS_DISPC_TIMING_H_HBP(_hbp) ((_hbp) << 20) + +#define DSS_DISPC_TIMING_V_VSW(_vsw) ((_vsw) << 0) +#define DSS_DISPC_TIMING_V_VFP(_vfp) ((_vfp) << 8) +#define DSS_DISPC_TIMING_V_VBP(_vbp) ((_vbp) << 20) + +#define DSS_DISPC_DIVISOR_ENABLE (1u << 0) +#define DSS_DISPC_DIVISOR_LCD(_lcd) ((_lcd) << 16) + +#define DSS_DISPC_DIVISOR2_PCD(_pcd) ((_pcd) << 0) +#define DSS_DISPC_DIVISOR2_LCD(_lcd) ((_lcd) << 16) + +#define DSS_DISPC_IRQSTATUS_FRAMEDONE (1u << 0) +#define DSS_DISPC_IRQSTATUS_FRAMEDONE2 (1u << 22) + +#define DSS_DSS_SYSSTATUS_RESETDONE (1u << 0) + +#endif /* H_BAREBOX_DRIVER_VIDEO_O4_REGS_H */