From 40df631f29896e4e13a2d078ac50bab62fd09c6c Mon Sep 17 00:00:00 2001 From: Li Jun Date: Tue, 25 Jul 2017 00:05:20 +0800 Subject: [PATCH 01/62] MLK-16066-1 usb: host: add imx8m xhci host driver imx8mq usb xhci is a dwc3 based controller, its synopsys PHY can be controlled by usbmix glue layer. imx8mq has 2 USB3 instance, this patch only enables USB2(2nd instance). Reviewed-by : Peng Fan Signed-off-by: Li Jun --- drivers/usb/host/Kconfig | 8 ++ drivers/usb/host/Makefile | 1 + drivers/usb/host/xhci-imx8m.c | 140 ++++++++++++++++++++++++++++++++++ include/linux/usb/dwc3.h | 1 + 4 files changed, 150 insertions(+) create mode 100644 drivers/usb/host/xhci-imx8m.c diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index a213c918bcf8..20ebef673db2 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -94,6 +94,14 @@ config USB_XHCI_FSL depends on !SPL_NO_USB help Enables support for the on-chip xHCI controller on NXP Layerscape SoCs. + +config USB_XHCI_IMX8M + bool "XHCI support for imx8M(mscale)" + depends on ARCH_MX8M + default y + help + Enables support for the on-chip xHCI controller on imx8m(mscale) SoC. + endif # USB_XHCI_HCD config USB_EHCI_HCD diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index cb8c315a1510..1f3b7c9a645c 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_USB_XHCI_OMAP) += xhci-omap.o obj-$(CONFIG_USB_XHCI_PCI) += xhci-pci.o obj-$(CONFIG_USB_XHCI_RCAR) += xhci-rcar.o obj-$(CONFIG_USB_XHCI_STI) += dwc3-sti-glue.o +obj-$(CONFIG_USB_XHCI_IMX8M) += xhci-imx8m.o # designware obj-$(CONFIG_USB_DWC2) += dwc2.o diff --git a/drivers/usb/host/xhci-imx8m.c b/drivers/usb/host/xhci-imx8m.c new file mode 100644 index 000000000000..1c63550a8f6c --- /dev/null +++ b/drivers/usb/host/xhci-imx8m.c @@ -0,0 +1,140 @@ +/* + * Copyright 2017 NXP + * + * FSL i.MX8M USB HOST xHCI Controller + * + * Author: Jun Li + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include "xhci.h" + +/* Declare global data pointer */ +DECLARE_GLOBAL_DATA_PTR; + +#define USBMIX_PHY_OFFSET 0xF0040 + +#define PHY_CTRL0_REF_SSP_EN BIT(2) + +#define PHY_CTRL1_RESET BIT(0) +#define PHY_CTRL1_ATERESET BIT(3) +#define PHY_CTRL1_VDATSRCENB0 BIT(19) +#define PHY_CTRL1_VDATDETENB0 BIT(20) + +#define PHY_CTRL2_TXENABLEN0 BIT(8) + +struct imx8m_usbmix { + u32 phy_ctrl0; + u32 phy_ctrl1; + u32 phy_ctrl2; + u32 phy_ctrl3; +}; + +struct imx8m_xhci { + struct xhci_hccr *hcd; + struct dwc3 *dwc3_reg; + struct imx8m_usbmix *usbmix_reg; +}; + +static struct imx8m_xhci imx8m_xhci; +unsigned long ctr_addr[] = {USB2_BASE_ADDR}; + +static void imx8m_usb_phy_init(struct imx8m_usbmix *usbmix_reg) +{ + u32 reg; + + reg = readl(&usbmix_reg->phy_ctrl1); + reg &= ~(PHY_CTRL1_VDATSRCENB0 | PHY_CTRL1_VDATDETENB0); + reg |= PHY_CTRL1_RESET | PHY_CTRL1_ATERESET; + writel(reg, &usbmix_reg->phy_ctrl1); + + reg = readl(&usbmix_reg->phy_ctrl0); + reg |= PHY_CTRL0_REF_SSP_EN; + writel(reg, &usbmix_reg->phy_ctrl0); + + reg = readl(&usbmix_reg->phy_ctrl2); + reg |= PHY_CTRL2_TXENABLEN0; + writel(reg, &usbmix_reg->phy_ctrl2); + + reg = readl(&usbmix_reg->phy_ctrl1); + reg &= ~(PHY_CTRL1_RESET | PHY_CTRL1_ATERESET); + writel(reg, &usbmix_reg->phy_ctrl1); +} + +static void imx8m_xhci_set_suspend_clk(struct dwc3 *dwc3_reg) +{ + u32 reg; + + /* Set suspend_clk to be 32KHz */ + reg = readl(&dwc3_reg->g_ctl); + reg &= ~(DWC3_GCTL_PWRDNSCALE_MASK); + reg |= DWC3_GCTL_PWRDNSCALE(2); + + writel(reg, &dwc3_reg->g_ctl); +} + +static int imx8m_xhci_core_init(struct imx8m_xhci *imx8m_xhci) +{ + int ret = 0; + + imx8m_usb_phy_init(imx8m_xhci->usbmix_reg); + + ret = dwc3_core_init(imx8m_xhci->dwc3_reg); + if (ret) { + debug("%s:failed to initialize core\n", __func__); + return ret; + } + + imx8m_xhci_set_suspend_clk(imx8m_xhci->dwc3_reg); + + /* We are hard-coding DWC3 core to Host Mode */ + dwc3_set_mode(imx8m_xhci->dwc3_reg, DWC3_GCTL_PRTCAP_HOST); + + /* Set GFLADJ_30MHZ as 20h as per XHCI spec default value */ + dwc3_set_fladj(imx8m_xhci->dwc3_reg, GFLADJ_30MHZ_DEFAULT); + + return ret; +} + +int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) +{ + struct imx8m_xhci *ctx = &imx8m_xhci; + int ret = 0; + + ctx->hcd = (struct xhci_hccr *)ctr_addr[index]; + ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); + ctx->usbmix_reg = (struct imx8m_usbmix *)((char *)(ctx->hcd) + + USBMIX_PHY_OFFSET); + + ret = board_usb_init(index, USB_INIT_HOST); + if (ret != 0) { + puts("Failed to initialize board for imx8m USB\n"); + return ret; + } + + ret = imx8m_xhci_core_init(ctx); + if (ret < 0) { + puts("Failed to initialize imx8m xhci\n"); + return ret; + } + + *hccr = (struct xhci_hccr *)ctx->hcd; + *hcor = (struct xhci_hcor *)((uintptr_t) *hccr + + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); + + debug("imx8m-xhci: init hccr %lx and hcor %lx hc_length %lx\n", + (uintptr_t)*hccr, (uintptr_t)*hcor, + (uintptr_t)HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); + + return ret; +} + +void xhci_hcd_stop(int index) +{ +} diff --git a/include/linux/usb/dwc3.h b/include/linux/usb/dwc3.h index 9ceee0a1c9f6..c63a5f34c0ce 100644 --- a/include/linux/usb/dwc3.h +++ b/include/linux/usb/dwc3.h @@ -154,6 +154,7 @@ struct dwc3 { /* offset: 0xC100 */ /* Global Configuration Register */ #define DWC3_GCTL_PWRDNSCALE(n) ((n) << 19) +#define DWC3_GCTL_PWRDNSCALE_MASK DWC3_GCTL_PWRDNSCALE(0x1fff) #define DWC3_GCTL_U2RSTECN (1 << 16) #define DWC3_GCTL_RAMCLKSEL(x) \ (((x) & DWC3_GCTL_CLK_MASK) << 6) From a7215d5184da753e82467a3f52ac300b52a6eb51 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Thu, 14 Dec 2017 19:56:40 -0600 Subject: [PATCH 02/62] MLK-17210 usb: imx8m: Add PU power on/off to USB ATF will power off all PUs at default, so for USB, we enable its PU power for both host and device modes in board_usb_init and disable the power when usb is stop in board_usb_cleanup. Signed-off-by: Ye Li Reviewed-by: Li Jun --- arch/arm/mach-imx/imx8m/soc.c | 19 +++++++++++++++++++ drivers/usb/host/xhci-imx8m.c | 14 +++++++++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 46873aa8ddf3..593a7dfb111b 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -224,3 +224,22 @@ void reset_cpu(ulong addr) */ } } + +#ifdef CONFIG_USB_XHCI_IMX8M +#define FSL_SIP_GPC 0xC2000000 +#define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03 +int imx8m_usb_power(int usb_id, bool on) +{ + unsigned long ret; + + if (usb_id > 1) + return -EINVAL; + + ret = call_imx_sip(FSL_SIP_GPC, + FSL_SIP_CONFIG_GPC_PM_DOMAIN, 2 + usb_id, on, 0); + if (ret) + return -EPERM; + + return 0; +} +#endif diff --git a/drivers/usb/host/xhci-imx8m.c b/drivers/usb/host/xhci-imx8m.c index 1c63550a8f6c..40f0518bc5bb 100644 --- a/drivers/usb/host/xhci-imx8m.c +++ b/drivers/usb/host/xhci-imx8m.c @@ -42,8 +42,14 @@ struct imx8m_xhci { struct imx8m_usbmix *usbmix_reg; }; +struct imx8m_usbctrl_data { + u32 usb_id; + unsigned long ctr_addr; +}; static struct imx8m_xhci imx8m_xhci; -unsigned long ctr_addr[] = {USB2_BASE_ADDR}; +static struct imx8m_usbctrl_data ctr_data[] = { + {1, USB2_BASE_ADDR}, +}; static void imx8m_usb_phy_init(struct imx8m_usbmix *usbmix_reg) { @@ -107,13 +113,14 @@ int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) struct imx8m_xhci *ctx = &imx8m_xhci; int ret = 0; - ctx->hcd = (struct xhci_hccr *)ctr_addr[index]; + ctx->hcd = (struct xhci_hccr *)(ctr_data[index].ctr_addr); ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); ctx->usbmix_reg = (struct imx8m_usbmix *)((char *)(ctx->hcd) + USBMIX_PHY_OFFSET); - ret = board_usb_init(index, USB_INIT_HOST); + ret = board_usb_init(ctr_data[index].usb_id, USB_INIT_HOST); if (ret != 0) { + imx8m_usb_power(ctr_data[index].usb_id, false); puts("Failed to initialize board for imx8m USB\n"); return ret; } @@ -137,4 +144,5 @@ int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) void xhci_hcd_stop(int index) { + board_usb_cleanup(ctr_data[index].usb_id, USB_INIT_HOST); } From 204b2a568d36e0e508471f31f5d80b0e9a2bf94e Mon Sep 17 00:00:00 2001 From: Ye Li Date: Wed, 20 Dec 2017 04:28:32 -0600 Subject: [PATCH 03/62] MLK-17272 imx8mq_evk: Fix build warnings with usb power MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix build warnings below, because the imx8m_usb_power is not declared board/freescale/imx8mq_evk/imx8m_evk.c: In function ‘board_usb_init’: board/freescale/imx8mq_evk/imx8m_evk.c:205:2: warning: implicit declaration of function ‘imx8m_usb_power’ [-Wimplicit-function-declaration] imx8m_usb_power(index, true); ^~~~~~~~~~~~~~~ drivers/usb/host/xhci-imx8m.c: In function ‘xhci_hcd_init’: drivers/usb/host/xhci-imx8m.c:123:3: warning: implicit declaration of function ‘imx8m_usb_power’ [-Wimplicit-function-declaration] imx8m_usb_power(ctr_data[index].usb_id, false); ^~~~~~~~~~~~~~~ Signed-off-by: Ye Li Acked-by: Peng Fan --- arch/arm/include/asm/arch-imx8m/sys_proto.h | 1 + drivers/usb/host/xhci-imx8m.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/arm/include/asm/arch-imx8m/sys_proto.h b/arch/arm/include/asm/arch-imx8m/sys_proto.h index d328542ece21..3e54f9b6764a 100644 --- a/arch/arm/include/asm/arch-imx8m/sys_proto.h +++ b/arch/arm/include/asm/arch-imx8m/sys_proto.h @@ -11,6 +11,7 @@ void set_wdog_reset(struct wdog_regs *wdog); void enable_tzc380(void); void restore_boot_params(void); +int imx8m_usb_power(int usb_id, bool on); extern unsigned long rom_pointer[]; enum boot_device get_boot_device(void); bool is_usb_boot(void); diff --git a/drivers/usb/host/xhci-imx8m.c b/drivers/usb/host/xhci-imx8m.c index 40f0518bc5bb..b4ed87df46c5 100644 --- a/drivers/usb/host/xhci-imx8m.c +++ b/drivers/usb/host/xhci-imx8m.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "xhci.h" /* Declare global data pointer */ From 0492488647d3e2338ef0a6227aad38e910238709 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Sun, 11 Feb 2018 02:45:07 -0800 Subject: [PATCH 04/62] MLK-17573-2 xhci-imx8m: add USB3 controller 1 address i.MX8MQ has two USB3 controllers. Previously we only added the #2 controller support in driver. This patch adds the address for #1 controller. Signed-off-by: Ye Li Acked-by: Jun Li (cherry picked from commit 3172dab3f9b25ccf8f66b122a69cda1da65d808f) --- drivers/usb/host/xhci-imx8m.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/host/xhci-imx8m.c b/drivers/usb/host/xhci-imx8m.c index b4ed87df46c5..32ae1f927e59 100644 --- a/drivers/usb/host/xhci-imx8m.c +++ b/drivers/usb/host/xhci-imx8m.c @@ -49,6 +49,7 @@ struct imx8m_usbctrl_data { }; static struct imx8m_xhci imx8m_xhci; static struct imx8m_usbctrl_data ctr_data[] = { + {0, USB1_BASE_ADDR}, {1, USB2_BASE_ADDR}, }; From 9a84860c17e1d053df808903531a6533f46b0e82 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Mon, 29 Aug 2016 13:51:01 +0800 Subject: [PATCH 05/62] MLK-15324-1 video: cfb_console: Fix 64 bits support problem There are some integer to pointer convert. To support 64 bits system, change the unsigned int to unsigned long. Signed-off-by: Ye Li --- drivers/video/cfb_console.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 636c3e8c184d..4ffb92a21796 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -1176,7 +1176,7 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff, y = __le32_to_cpu(img->header.height) - 1; ncolors = __le32_to_cpu(img->header.colors_used); bpp = VIDEO_PIXEL_SIZE; - fbp = (unsigned char *) ((unsigned int) video_fb_address + + fbp = (unsigned char *) ((unsigned long) video_fb_address + (y + yoff) * VIDEO_LINE_LEN + xoff * bpp); @@ -1231,7 +1231,7 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff, x = 0; y--; fbp = (unsigned char *) - ((unsigned int) video_fb_address + + ((unsigned long) video_fb_address + (y + yoff) * VIDEO_LINE_LEN + xoff * bpp); continue; @@ -1244,7 +1244,7 @@ static int display_rle8_bitmap(struct bmp_image *img, int xoff, int yoff, x += bm[2]; y -= bm[3]; fbp = (unsigned char *) - ((unsigned int) video_fb_address + + ((unsigned long) video_fb_address + (y + yoff) * VIDEO_LINE_LEN + xoff * bpp); bm += 4; @@ -2023,7 +2023,7 @@ static int cfg_video_init(void) if (pGD == NULL) return -1; - video_fb_address = (void *) VIDEO_FB_ADRS; + video_fb_address = (void *)(unsigned long) VIDEO_FB_ADRS; cfb_do_flush_cache = cfb_fb_is_in_dram() && dcache_status(); From 866ee40b742a7b5aaf87b5e25b72b614ff2fd809 Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Mon, 29 Jan 2018 14:11:06 -0600 Subject: [PATCH 06/62] MLK-17404-3 arch: arm: Adding support for i.MX8 HDMI Adding basic HDMI support for i.MX8 for splash screen. Signed-off-by: Oliver Brown --- arch/arm/include/asm/arch-mx8m/video_common.h | 40 + arch/arm/mach-imx/imx8m/Makefile | 1 + arch/arm/mach-imx/mx8m/video_common.c | 736 ++++++++++++++++++ 3 files changed, 777 insertions(+) create mode 100644 arch/arm/include/asm/arch-mx8m/video_common.h create mode 100644 arch/arm/mach-imx/mx8m/video_common.c diff --git a/arch/arm/include/asm/arch-mx8m/video_common.h b/arch/arm/include/asm/arch-mx8m/video_common.h new file mode 100644 index 000000000000..cdeec6999ce1 --- /dev/null +++ b/arch/arm/include/asm/arch-mx8m/video_common.h @@ -0,0 +1,40 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + * + */ + +#ifndef __ASM_ARCH_VIDEO_COMMON_H__ +#define __ASM_ARCH_VIDEO_COMMON_H__ +#include +#include + +struct video_mode_settings { + uint32_t pixelclock; /* horizontal resolution */ + uint16_t xres; /* horizontal resolution */ + uint16_t yres; /* vertical resolution */ + uint16_t hfp; /* horizontal front porch */ + uint16_t hbp; /* horizontal back porch */ + uint16_t vfp; /* vertical front porch */ + uint16_t vbp; /* vertical back porch */ + uint16_t hsync; /* horizontal sync pulse width */ + uint16_t vsync; /* vertical sync pulse width */ + bool hpol; /* horizontal pulse polarity */ + bool vpol; /* vertical pulse polarity */ +}; + +#define PS2KHZ(ps) (1000000000UL / (ps)) +struct video_mode_settings *imx8m_get_gmode(void); +GraphicDevice *imx8m_get_gd(void); +void imx8m_show_gmode(void); +void imx8m_create_color_bar( + void *start_address, + struct video_mode_settings *vms); +int imx8m_fb_init( + struct fb_videomode const *mode, + uint8_t disp, + uint32_t pixfmt); +void imx8m_fb_disable(void); + +#endif /* __ASM_ARCH_VIDEO_COMMON_H__ */ diff --git a/arch/arm/mach-imx/imx8m/Makefile b/arch/arm/mach-imx/imx8m/Makefile index feff4941c1ac..ec6ef3865fd1 100644 --- a/arch/arm/mach-imx/imx8m/Makefile +++ b/arch/arm/mach-imx/imx8m/Makefile @@ -4,3 +4,4 @@ obj-y += lowlevel_init.o obj-y += clock.o clock_slice.o soc.o +obj-$(CONFIG_VIDEO_IMXDCSS) += video_common.o diff --git a/arch/arm/mach-imx/mx8m/video_common.c b/arch/arm/mach-imx/mx8m/video_common.c new file mode 100644 index 000000000000..ee7c844049e8 --- /dev/null +++ b/arch/arm/mach-imx/mx8m/video_common.c @@ -0,0 +1,736 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* test congiurations */ +#undef IMXDCSS_LOAD_HDMI_FIRMWARE +#undef IMXDCSS_SET_PIXEL_CLOCK + +static struct video_mode_settings gmode; +static uint32_t gpixfmt; +GraphicDevice panel; +struct video_mode_settings *imx8m_get_gmode(void) +{ + return &gmode; +} + +void imx8m_show_gmode(void) +{ + printf("gmode =\n" + "pixelclock = %u\n" + "xres = %u\n" + "yres = %u\n" + "hfp = %u\n" + "hbp = %u\n" + "vfp = %u\n" + "vbp = %u\n" + "hsync = %u\n" + "vsync = %u\n" + "hpol = %u\n" + "vpol = %u\n", + gmode.pixelclock, + gmode.xres, + gmode.yres, + gmode.hfp, + gmode.hbp, + gmode.vfp, + gmode.vbp, gmode.hsync, gmode.vsync, gmode.hpol, gmode.vpol); +} + +GraphicDevice *imx8m_get_gd(void) +{ + return &panel; +} + +#define REG_BASE_ADDR 0x32e00000UL + +/*#define DEBUGREG*/ +#ifdef DEBUGREG +#define reg32_write(addr, val) \ +do { \ + debug("%s():%d 0x%08x -> 0x%08x\n", __func__, __LINE__, \ + (unsigned int)addr, (unsigned int)val); \ + __raw_writel(val, addr); \ +} while (0) +#else +#define reg32_write(addr, val) __raw_writel(val, addr) +#endif + +#define reg32_read(addr) __raw_readl(addr) + +#define reg32setbit(addr, bitpos) \ + reg32_write((addr), (reg32_read((addr)) | (1<<(bitpos)))) +#define reg32clearbit(addr, bitpos) \ + reg32_write((addr), (reg32_read((addr)) & ~(1<<(bitpos)))) + +#define reg32_read_tst(addr, val, mask) \ +do { \ + u32 temp = reg32_read((addr)); \ + if ((temp & (mask)) == ((val) & (mask))) \ + debug("%s():%d 0x%08x -> 0x%08x\n", \ + __func__, __LINE__, addr, val); \ + else \ + debug("%s():%d 0x%08x -> 0x%08x instead of 0x%08x\n", \ + __func__, __LINE__, addr, temp, val); \ +} while (0) + +#define COLOR_LIST_SIZE 8 +static u32 color_list_argb32[COLOR_LIST_SIZE] = { + 0xFFFFFFFF, /* white */ + 0xFFFF0000, /* red */ + 0xFF00FF00, /* green */ + 0xFF0000FF, /* blue */ + 0xFFFFFF00, /* yellow */ + 0xFF00FFFF, /* cyan */ + 0xFFFF00FF, /* magenta */ + 0xFFC1C2C3, /* silver */ +}; /*AARRGGBB */ + +static unsigned int get_color_index(unsigned short px, unsigned short py, + unsigned short width, unsigned short height, + unsigned short bar_size) +{ + const int mw = 5; /* margin width */ + if ((py >= 0 && py < mw) || (py >= height - mw && py < height) || + (px >= 0 && px < mw) || (px >= width - mw && px < width)) { + return 1; + } + + return py / bar_size; +} + +void imx8m_create_color_bar(void *start_address, + struct video_mode_settings *vms) +{ + /*struct video_mode_settings *vms = &vm_settings[g_vm]; */ + uint32_t color_bar_size = vms->yres / COLOR_LIST_SIZE; + int i, j; + u32 *pointer; + int color_index = 0; + pointer = (u32 *)start_address; + uint32_t *color_map = &color_list_argb32[0]; + debug("%s(), %d: start_address %p\n", + __func__, __LINE__, start_address); + debug("%s(), %d: pointer %p\n", __func__, __LINE__, pointer); + debug("%s(), %d x %d\n", __func__, vms->xres, vms->yres); + for (i = 0; i < vms->yres; i++) { + for (j = 0; j < vms->xres; j++) { + color_index = get_color_index(j, i, vms->xres, + vms->yres, + color_bar_size); + *pointer = color_map[color_index]; + pointer++; + } + } + invalidate_dcache_all(); +} + +static void imx8m_set_clocks(int apb_clk, int b_clk, int hdmi_core_clk, + int p_clk, int rtr_clk) +{ + if (b_clk == 800) { + /* b_clk: bus_clk_root(4) sel 2nd input source and + pre_div to 0; output should be 800M */ + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_CLR(4), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_SET(4), (0x2 << 24)); + } else { + printf("b_clk does not match a supported frequency"); + } + if (rtr_clk == 400) { + /* rtr_clk: bus_clk_root(6) sel 1st input source + and pre_div to 1; output should be 400M */ + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_CLR(6), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_SET(6), + (0x1 << 24) | (0x1 << 16)); + } else { + debug("rtr_clk does not match a supported frequency"); + } + +#ifdef IMXDCSS_LOAD_HDMI_FIRMWARE + /* If ROM is loading HDMI firmware then this clock should not be set */ + if (hdmi_core_clk == 200) { + /* hdmi_core_clk: ip_clk_root(69) sel 1st input source and + pre_div to 0 */ + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(69), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(69), (0x1 << 24)); + g_hdmi_core_clock = 200000000; + } else { + debug("hdmi_core_clk does not match a supported frequency"); + } +#endif + +#ifdef IMXDCSS_SET_PIXEL_CLOCK + /* This would be needed for MIPI-DSI DCSS display */ + if (p_clk == 27) { + /* p_clk: ip_clk_root(9) sel 1st input source and + pre_div to 1; post_div to 5, output 100M */ + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + (0x1 << 24) | (29 << 16)); + } else if (p_clk == 100) { + /* p_clk: ip_clk_root(9) sel 1st input source and + pre_div to 1; post_div to 5, output 100M */ + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + (0x1 << 24) | (0x5 << 16)); + } else if (p_clk == 120) { + /* p_clk: ip_clk_root(9) sel 1st input source and + pre_div to 1; post_div to 4, output 120M */ + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + (0x1 << 24) | (0x4 << 16)); + } else if (p_clk == 200) { + /* I added this to speed up the pixel clock and + get frames out faster. may need to adjust this. + */ + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + (0x4 << 24) | (0x3 << 16)); /*for emu use 800 / 4 */ + } else if (p_clk == 400) { + /* I added this to speed up the pixel clock and + get frames out faster. may need to adjust this. + */ + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + (0x7 << 24) | (0x7 << 16)); + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + (0x4 << 24) | (0x1 << 16)); /*for emu use 800 / 2 */ + } else if (p_clk == 40) { /* Do not reprogram, will get 40MHz */ + } else { + debug("p_clk does not match a supported frequency"); + } +#endif +} + +static int imx8m_power_init(uint32_t clock_control) +{ + u32 temp; + /*struct video_mode_settings *vms = &vm_settings[g_vm]; */ + + debug("\nenabling display clock...\n"); + clock_enable(CCGR_DISPLAY, 1); + + reg32_write(0x303A00EC, 0x0000ffff); /*PGC_CPU_MAPPING */ + reg32setbit(0x303A00F8, 10); /*PU_PGC_SW_PUP_REQ : disp was 10 */ +#ifdef LOAD_HDMI_FIRMWARE + reg32setbit(0x303A00F8, 9); /*PU_PGC_SW_PUP_REQ : hdmi was 9 */ +#endif + imx8m_set_clocks(133, 800, 200, 27, 400); + + /* DCSS reset */ + reg32_write(0x32e2f000, 0xffffffff); + + /* DCSS clock selection */ + reg32_write(0x32e2f010, clock_control); + temp = reg32_read(0x32e2f010); + debug("%s(): DCSS clock control 0x%08x\n", __func__, temp); + + /* take DCSS out of reset - not needed OFB */ + /*__raw_writel(0xffffffff, 0x32e2f004); */ + + return 0; +} + +static void imx8m_display_init(u64 buffer, int encoding, + struct video_mode_settings *vms) +{ + /*struct video_mode_settings *vms = &vm_settings[g_vm]; */ + + debug("entering %s() ...\n", __func__); + debug("%s() buffer ...\n", __func__); + + /* DTRC-CHAN2/3 */ + reg32_write(REG_BASE_ADDR + 0x160c8, 0x00000002); + reg32_write(REG_BASE_ADDR + 0x170c8, 0x00000002); + + /* CHAN1_DPR */ + reg32_write(REG_BASE_ADDR + 0x180c0, (unsigned int)buffer); + reg32_write(REG_BASE_ADDR + 0x18090, 0x00000002); + reg32_write(REG_BASE_ADDR + 0x180a0, vms->xres); + reg32_write(REG_BASE_ADDR + 0x180b0, vms->yres); + reg32_write(REG_BASE_ADDR + 0x18110, + (unsigned int)buffer + vms->xres * vms->yres); + reg32_write(REG_BASE_ADDR + 0x180f0, 0x00000280); + reg32_write(REG_BASE_ADDR + 0x18100, 0x000000f0); + reg32_write(REG_BASE_ADDR + 0x18070, ((vms->xres * 4) << 16)); + reg32_write(REG_BASE_ADDR + 0x18050, 0x000e4203); + reg32_write(REG_BASE_ADDR + 0x18050, 0x000e4203); + reg32_write(REG_BASE_ADDR + 0x18200, 0x00000038); + reg32_write(REG_BASE_ADDR + 0x18000, 0x00000004); + reg32_write(REG_BASE_ADDR + 0x18000, 0x00000005); + + /* SCALER */ + reg32_write(REG_BASE_ADDR + 0x1c008, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c00c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c010, 0x00000002); + reg32_write(REG_BASE_ADDR + 0x1c014, 0x00000002); + reg32_write(REG_BASE_ADDR + 0x1c018, + ((vms->yres - 1) << 16 | (vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x1c01c, + ((vms->yres - 1) << 16 | (vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x1c020, + ((vms->yres - 1) << 16 | (vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x1c024, + ((vms->yres - 1) << 16 | (vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x1c028, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c02c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c030, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c034, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c038, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c03c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c040, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c044, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c048, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c04c, 0x00002000); + reg32_write(REG_BASE_ADDR + 0x1c050, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c054, 0x00002000); + reg32_write(REG_BASE_ADDR + 0x1c058, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c05c, 0x00002000); + reg32_write(REG_BASE_ADDR + 0x1c060, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c064, 0x00002000); + reg32_write(REG_BASE_ADDR + 0x1c080, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0c0, 0x00040000); + reg32_write(REG_BASE_ADDR + 0x1c100, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c084, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0c4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c104, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c088, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0c8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c108, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c08c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0cc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c10c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c090, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0d0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c110, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c094, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0d4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c114, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c098, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0d8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c118, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c09c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0dc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c11c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0a0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0e0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c120, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0a4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0e4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c124, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0a8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0e8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c128, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0ac, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0ec, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c12c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0b0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0f0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c130, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0b4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0f4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c134, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0b8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0f8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c138, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0bc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c0fc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c13c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c140, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c180, 0x00040000); + reg32_write(REG_BASE_ADDR + 0x1c1c0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c144, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c184, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1c4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c148, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c188, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1c8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c14c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c18c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1cc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c150, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c190, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1d0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c154, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c194, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1d4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c158, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c198, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1d8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c15c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c19c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1dc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c160, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1a0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1e0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c164, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1a4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1e4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c168, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1a8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1e8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c16c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1ac, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1ec, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c170, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1b0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1f0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c174, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1b4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1f4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c178, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1b8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1f8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c17c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1bc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c1fc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c300, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c340, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c380, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c304, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c344, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c384, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c308, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c348, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c388, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c30c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c34c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c38c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c310, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c350, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c390, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c314, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c354, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c394, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c318, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c358, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c398, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c31c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c35c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c39c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c320, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c360, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3a0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c324, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c364, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3a4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c328, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c368, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3a8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c32c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c36c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3ac, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c330, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c370, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3b0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c334, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c374, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3b4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c338, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c378, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3b8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c33c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c37c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c3bc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c200, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c240, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c280, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c204, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c244, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c284, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c208, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c248, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c288, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c20c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c24c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c28c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c210, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c250, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c290, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c214, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c254, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c294, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c218, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c258, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c298, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c21c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c25c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c29c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c220, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c260, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2a0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c224, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c264, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2a4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c228, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c268, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2a8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c22c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c26c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2ac, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c230, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c270, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2b0, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c234, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c274, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2b4, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c238, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c278, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2b8, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c23c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c27c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2bc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c2bc, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x1c000, 0x00000011); + + /* SUBSAM */ + reg32_write(REG_BASE_ADDR + 0x1b070, 0x21612161); + reg32_write(REG_BASE_ADDR + 0x1b080, 0x03ff0000); + reg32_write(REG_BASE_ADDR + 0x1b090, 0x03ff0000); + + reg32_write(REG_BASE_ADDR + 0x1b010, + (((vms->vfp + vms->vbp + vms->vsync + vms->yres - + 1) << 16) | (vms->hfp + vms->hbp + vms->hsync + + vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x1b020, + (((vms->hsync - 1) << 16) | vms->hpol << 31 | (vms->hfp + + vms->hbp + + vms->hsync + + vms->xres - + 1))); + reg32_write(REG_BASE_ADDR + 0x1b030, + (((vms->vfp + vms->vsync - + 1) << 16) | vms->vpol << 31 | (vms->vfp - 1))); + + reg32_write(REG_BASE_ADDR + 0x1b040, + ((1 << 31) | ((vms->vsync + vms->vfp + vms->vbp) << 16) | + (vms->hsync + vms->hbp - 1))); + reg32_write(REG_BASE_ADDR + 0x1b050, + (((vms->vsync + vms->vfp + vms->vbp + vms->yres - + 1) << 16) | (vms->hsync + vms->hbp + vms->xres - 1))); + + /* subsample mode 0 none, 1 422, 2 420 */ + switch (encoding) { + case 4: + reg32_write(REG_BASE_ADDR + 0x1b060, 0x00000001); + break; + + case 8: + reg32_write(REG_BASE_ADDR + 0x1b060, 0x00000002); + break; + + case 2: + case 1: + default: + reg32_write(REG_BASE_ADDR + 0x1b060, 0x0000000); + } + + reg32_write(REG_BASE_ADDR + 0x1b000, 0x00000001); +#if 0 + /* not needed for splash setup */ + /* HDR10 Chan3 LUT */ + reg32_write(REG_BASE_ADDR + 0x03874, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x03080, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x03000, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x03800, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x07874, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x07080, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x07000, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x07800, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0b874, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0b080, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0b000, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0b800, 0x00000000); + + /* HDR10 Tables and Registers */ + /*reg32_write(REG_BASE_ADDR+0x0f074, 0x00000003); */ + /*reg32_write(REG_BASE_ADDR+0x0f000, 0x00000004); */ + + reg32_write(REG_BASE_ADDR + 0x0f004, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f008, 0x00000001); + reg32_write(REG_BASE_ADDR + 0x0f00c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f010, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f014, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f018, 0x00000001); + reg32_write(REG_BASE_ADDR + 0x0f01c, 0x00000001); + reg32_write(REG_BASE_ADDR + 0x0f020, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f024, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f028, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f02c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f030, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f034, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f038, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f03c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f040, 0xffffffff); + reg32_write(REG_BASE_ADDR + 0x0f044, 0xffffffff); + reg32_write(REG_BASE_ADDR + 0x0f048, 0xffffffff); + reg32_write(REG_BASE_ADDR + 0x0f04c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f050, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f054, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f058, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f05c, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f060, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f064, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f068, 0xffffffff); + reg32_write(REG_BASE_ADDR + 0x0f06c, 0xffffffff); + reg32_write(REG_BASE_ADDR + 0x0f070, 0xffffffff); + reg32_write(REG_BASE_ADDR + 0x0f074, 0x00000000); + reg32_write(REG_BASE_ADDR + 0x0f000, 0x00000003); +#endif + /* DTG */ + /*reg32_write(REG_BASE_ADDR + 0x20000, 0xff000484); */ + /* disable local alpha */ + reg32_write(REG_BASE_ADDR + 0x20000, 0xff005084); + reg32_write(REG_BASE_ADDR + 0x20004, + (((vms->vfp + vms->vbp + vms->vsync + vms->yres - + 1) << 16) | (vms->hfp + vms->hbp + vms->hsync + + vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x20008, + (((vms->vsync + vms->vfp + vms->vbp - + 1) << 16) | (vms->hsync + vms->hbp - 1))); + reg32_write(REG_BASE_ADDR + 0x2000c, + (((vms->vsync + vms->vfp + vms->vbp + vms->yres - + 1) << 16) | (vms->hsync + vms->hbp + vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x20010, + (((vms->vsync + vms->vfp + vms->vbp - + 1) << 16) | (vms->hsync + vms->hbp - 1))); + reg32_write(REG_BASE_ADDR + 0x20014, + (((vms->vsync + vms->vfp + vms->vbp + vms->yres - + 1) << 16) | (vms->hsync + vms->hbp + vms->xres - 1))); + reg32_write(REG_BASE_ADDR + 0x20028, 0x000b000a); + + /* disable local alpha */ + reg32_write(REG_BASE_ADDR + 0x20000, 0xff005184); + + debug("leaving %s() ...\n", __func__); +} + +void imx8m_display_shutdown(void) +{ + /* stop the DCSS modules in use */ + /* dtg */ + reg32_write(REG_BASE_ADDR + 0x20000, 0); + /* scaler */ + reg32_write(REG_BASE_ADDR + 0x1c000, 0); + reg32_write(REG_BASE_ADDR + 0x1c400, 0); + reg32_write(REG_BASE_ADDR + 0x1c800, 0); + /* dpr */ + reg32_write(REG_BASE_ADDR + 0x18000, 0); + reg32_write(REG_BASE_ADDR + 0x19000, 0); + reg32_write(REG_BASE_ADDR + 0x1a000, 0); + /* sub-sampler*/ + reg32_write(REG_BASE_ADDR + 0x1b000, 0); +#if 0 + /* reset the DCSS */ + reg32_write(0x32e2f000, 0xffffe8); + udelay(100); + reg32_write(0x32e2f000, 0xffffff); +#endif + +} +void *video_hw_init(void) +{ + void *fb; + int encoding = 1; + + debug("%s()\n", __func__); + + imx8m_power_init(0x1); + + panel.winSizeX = gmode.xres; + panel.winSizeY = gmode.yres; + panel.plnSizeX = gmode.xres; + panel.plnSizeY = gmode.yres; + panel.gdfBytesPP = 4; + panel.gdfIndex = GDF_32BIT_X888RGB; + panel.memSize = gmode.xres * gmode.yres * panel.gdfBytesPP; + + /* Allocate framebuffer */ + fb = memalign(0x1000, roundup(panel.memSize, 0x1000)); + debug("%s(): fb %p\n", __func__, fb); + if (!fb) { + printf("%s, %s(): Error allocating framebuffer!\n", + __FILE__, __func__); + return NULL; + } + + imx8m_create_color_bar((void *)((uint64_t) fb), &gmode); + + imx8_hdmi_enable(encoding, &gmode); /* may change gmode */ + + /* start dccs */ + imx8m_display_init((uint64_t) fb, encoding, &gmode); + + panel.frameAdrs = (ulong) fb; + debug("IMXDCSS display started ...\n"); + + return &panel; +} + +void imx8m_fb_disable(void) +{ + debug("%s()\n", __func__); + if (panel.frameAdrs) { +#ifdef CONFIG_VIDEO_IMX8_HDMI + imx8_hdmi_disable(); +#endif + imx8m_display_shutdown(); + } + +} + +int imx8m_fb_init(struct fb_videomode const *mode, + uint8_t disp, uint32_t pixfmt) +{ + debug("entering %s()\n", __func__); + + if (disp > 1) { + debug("Invalid disp parameter %d for imxdcss_fb_init()\n", + disp); + return -EINVAL; + } + + memset(&gmode, 0, sizeof(struct video_mode_settings)); + gmode.pixelclock = PS2KHZ(mode->pixclock) * 1000; + gmode.xres = mode->xres; + gmode.hbp = mode->left_margin; + gmode.hfp = mode->right_margin; + + gmode.yres = mode->yres; + gmode.vbp = mode->upper_margin; + gmode.vfp = mode->lower_margin; + + gmode.hsync = mode->hsync_len; + gmode.vsync = mode->vsync_len; + gmode.hpol = (mode->flag & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0; + gmode.vpol = (mode->flag & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0; + gpixfmt = pixfmt; + + debug("leaving %s()\n", __func__); + + return 0; +} From 2a964ceb68a1e98c4856b48522d8fc43a4f61d04 Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Wed, 13 Dec 2017 17:09:14 -0600 Subject: [PATCH 07/62] MLK-17205-1 video: imx: hdp: Adding support for HDP firmware loading This adds a command to load the HDP firmware and supporting libraries. Signed-off-by: Oliver Brown --- drivers/video/imx/Makefile | 7 + drivers/video/imx/hdp/API_General.c | 477 ++++++++++++++++++++++++ drivers/video/imx/hdp/API_General.h | 302 +++++++++++++++ drivers/video/imx/hdp/Makefile | 1 + drivers/video/imx/hdp/address.h | 108 ++++++ drivers/video/imx/hdp/apb_cfg.h | 185 +++++++++ drivers/video/imx/hdp/externs.h | 80 ++++ drivers/video/imx/hdp/general_handler.h | 162 ++++++++ drivers/video/imx/hdp/opcodes.h | 115 ++++++ drivers/video/imx/hdp/test_base_sw.c | 180 +++++++++ drivers/video/imx/hdp/util.c | 329 ++++++++++++++++ drivers/video/imx/hdp/util.h | 278 ++++++++++++++ drivers/video/imx/hdpload.c | 107 ++++++ drivers/video/imx/scfw_utils.h | 90 +++++ 14 files changed, 2421 insertions(+) create mode 100644 drivers/video/imx/Makefile create mode 100644 drivers/video/imx/hdp/API_General.c create mode 100644 drivers/video/imx/hdp/API_General.h create mode 100644 drivers/video/imx/hdp/Makefile create mode 100644 drivers/video/imx/hdp/address.h create mode 100644 drivers/video/imx/hdp/apb_cfg.h create mode 100644 drivers/video/imx/hdp/externs.h create mode 100644 drivers/video/imx/hdp/general_handler.h create mode 100644 drivers/video/imx/hdp/opcodes.h create mode 100644 drivers/video/imx/hdp/test_base_sw.c create mode 100644 drivers/video/imx/hdp/util.c create mode 100644 drivers/video/imx/hdp/util.h create mode 100644 drivers/video/imx/hdpload.c create mode 100644 drivers/video/imx/scfw_utils.h diff --git a/drivers/video/imx/Makefile b/drivers/video/imx/Makefile new file mode 100644 index 000000000000..1d688c701f47 --- /dev/null +++ b/drivers/video/imx/Makefile @@ -0,0 +1,7 @@ +ifdef CONFIG_VIDEO_IMX_HDP_LOAD + +UBOOTINCLUDE += -I$(srctree)/drivers/video/imx/hdp +obj-y += hdpload.o +obj-y += hdp/ + +endif diff --git a/drivers/video/imx/hdp/API_General.c b/drivers/video/imx/hdp/API_General.c new file mode 100644 index 000000000000..83458d7fae30 --- /dev/null +++ b/drivers/video/imx/hdp/API_General.c @@ -0,0 +1,477 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * API_General.c + * + ****************************************************************************** + */ + +#include "API_General.h" +#include "util.h" +#ifndef __UBOOT__ +#include +#endif +#include "address.h" +#include "apb_cfg.h" +#include "opcodes.h" +#include "general_handler.h" +#include "externs.h" +#ifndef __UBOOT__ +#include +#endif + +extern state_struct state; + +void cdn_api_init(void) +{ + memset(&state, 0, sizeof(state_struct)); +} + +CDN_API_STATUS cdn_api_loadfirmware(unsigned char *imem, int imemsize, + unsigned char *dmem, int dmemsize) +{ + int i; + for (i = 0; i < imemsize; i += 4) + if (cdn_apb_write(ADDR_IMEM + i, + (unsigned int)imem[i] << 0 | + (unsigned int)imem[i + 1] << 8 | + (unsigned int)imem[i + 2] << 16 | + (unsigned int)imem[i + 3] << 24)) + return CDN_ERR; + for (i = 0; i < dmemsize; i += 4) + if (cdn_apb_write(ADDR_DMEM + i, + (unsigned int)dmem[i] << 0 | + (unsigned int)dmem[i + 1] << 8 | + (unsigned int)dmem[i + 2] << 16 | + (unsigned int)dmem[i + 3] << 24)) + return CDN_ERR; + return CDN_OK; +} + +CDN_API_STATUS cdn_api_general_test_echo(unsigned int val, + CDN_BUS_TYPE bus_type) +{ + CDN_API_STATUS ret; + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + state.bus_type = bus_type; + state.rxenable = 1; + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, GENERAL_TEST_ECHO, + 1, 4, val); + return CDN_STARTED; + } + if (state.txenable && !internal_mbox_tx_process().txend) + return CDN_BSY; + if (state.rxenable && !internal_mbox_rx_process().rxend) + return CDN_BSY; + ret = internal_test_rx_head(MB_MODULE_ID_GENERAL, GENERAL_TEST_ECHO); + if (ret != CDN_OK) { + state.running = 0; + return ret; + } + state.running = 0; + if (val != internal_betoi(state.rxbuffer + INTERNAL_CMD_HEAD_SIZE, 4)) + return CDN_ERR; + return CDN_OK; +} + +CDN_API_STATUS cdn_api_general_test_echo_blocking(unsigned int val, + CDN_BUS_TYPE bus_type) +{ + internal_block_function(cdn_api_general_test_echo(val, bus_type)); +} + +CDN_API_STATUS cdn_api_general_test_echo_ext(uint8_t const *msg, uint8_t *resp, + uint16_t num_bytes, + CDN_BUS_TYPE bus_type) +{ + CDN_API_STATUS ret; + + if (!msg || !resp) + return CDN_ERR; + + if ((num_bytes > GENERAL_TEST_ECHO_MAX_PAYLOAD) || + (num_bytes < GENERAL_TEST_ECHO_MIN_PAYLOAD)) + return CDN_ERR; + + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + + state.bus_type = bus_type; + state.rxenable = 1; + + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, GENERAL_TEST_ECHO, + 1, -num_bytes, msg); + + return CDN_STARTED; + } + + if (state.txenable && !internal_mbox_tx_process().txend) + return CDN_BSY; + + if (state.rxenable && !internal_mbox_rx_process().rxend) + return CDN_BSY; + + ret = internal_test_rx_head(MB_MODULE_ID_GENERAL, GENERAL_TEST_ECHO); + + if (ret != CDN_OK) { + state.running = 0; + return ret; + } + + state.running = 0; + + memcpy(resp, state.rxbuffer + INTERNAL_CMD_HEAD_SIZE, num_bytes); + + if (memcmp(msg, resp, num_bytes) != 0) + return CDN_ERR; + + return CDN_OK; +} + +CDN_API_STATUS cdn_api_general_test_echo_ext_blocking(uint8_t const *msg, + uint8_t *resp, + uint16_t num_bytes, + CDN_BUS_TYPE bus_type) +{ + internal_block_function(cdn_api_general_test_echo_ext + (msg, resp, num_bytes, bus_type) + ); +} + +CDN_API_STATUS cdn_api_general_getcurversion(unsigned short *ver, + unsigned short *verlib) +{ + unsigned int vh, vl, vlh, vll; + if (cdn_apb_read(VER_L << 2, &vl)) + return CDN_ERR; + if (cdn_apb_read(VER_H << 2, &vh)) + return CDN_ERR; + if (cdn_apb_read(VER_LIB_L_ADDR << 2, &vll)) + return CDN_ERR; + if (cdn_apb_read(VER_LIB_H_ADDR << 2, &vlh)) + return CDN_ERR; + *ver = F_VER_MSB_RD(vh) << 8 | F_VER_LSB_RD(vl); + *verlib = F_SW_LIB_VER_H_RD(vlh) << 8 | F_SW_LIB_VER_L_RD(vll); + return CDN_OK; +} + +CDN_API_STATUS cdn_api_get_event(uint32_t *events) +{ + uint32_t evt[4] = { 0 }; + + if (!events) { + printf("events pointer is NULL!\n"); + return CDN_ERR; + } + + if (cdn_apb_read(SW_EVENTS0 << 2, &evt[0]) || + cdn_apb_read(SW_EVENTS1 << 2, &evt[1]) || + cdn_apb_read(SW_EVENTS2 << 2, &evt[2]) || + cdn_apb_read(SW_EVENTS3 << 2, &evt[3])) { + printf("Failed to read events registers.\n"); + return CDN_ERR; + } + + *events = (evt[0] & 0xFF) + | ((evt[1] & 0xFF) << 8) + | ((evt[2] & 0xFF) << 16) + | ((evt[3] & 0xFF) << 24); + + return CDN_OK; +} + +CDN_API_STATUS cdn_api_get_debug_reg_val(uint16_t *val) +{ + uint32_t dbg[2] = { 0 }; + + if (!val) { + printf("val pointer is NULL!\n"); + return CDN_ERR; + } + + if (cdn_apb_read(SW_DEBUG_L << 2, &dbg[0]) || + cdn_apb_read(SW_DEBUG_H << 2, &dbg[1])) { + printf("Failed to read debug registers.\n"); + return CDN_ERR; + } + + *val = (uint16_t) ((dbg[0] & 0xFF) | ((dbg[1] & 0xFF) << 8)); + + return CDN_OK; +} + +CDN_API_STATUS cdn_api_checkalive(void) +{ + static unsigned int alive; + unsigned int newalive; + if (cdn_apb_read(KEEP_ALIVE << 2, &newalive)) + return CDN_ERR; + if (alive == newalive) + return CDN_BSY; + alive = newalive; + return CDN_OK; +} + +CDN_API_STATUS cdn_api_checkalive_blocking(void) +{ + internal_block_function(cdn_api_checkalive()); +} + +CDN_API_STATUS cdn_api_maincontrol(unsigned char mode, unsigned char *resp) +{ + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + state.bus_type = CDN_BUS_TYPE_APB; + state.rxenable = 1; + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, + GENERAL_MAIN_CONTROL, 1, 1, mode); + return CDN_STARTED; + } + INTERNAL_PROCESS_MESSAGES; + internal_opcode_ok_or_return(MB_MODULE_ID_GENERAL, + GENERAL_MAIN_CONTROL_RESP); + internal_readmsg(1, 1, resp); + return CDN_OK; +} + +CDN_API_STATUS cdn_api_maincontrol_blocking(unsigned char mode, + unsigned char *resp) +{ + internal_block_function(cdn_api_maincontrol(mode, resp)); +} + +CDN_API_STATUS cdn_api_apbconf(uint8_t dpcd_bus_sel, uint8_t dpcd_bus_lock, + uint8_t hdcp_bus_sel, uint8_t hdcp_bus_lock, + uint8_t capb_bus_sel, uint8_t capb_bus_lock, + uint8_t *dpcd_resp, uint8_t *hdcp_resp, + uint8_t *capb_resp) +{ + uint8_t resp; + uint8_t set = 0; + + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + + state.bus_type = CDN_BUS_TYPE_APB; + state.rxenable = 1; + + set |= (dpcd_bus_sel) + ? (1 << GENERAL_BUS_SETTINGS_DPCD_BUS_BIT) + : 0; + set |= (dpcd_bus_lock) + ? (1 << GENERAL_BUS_SETTINGS_DPCD_BUS_LOCK_BIT) + : 0; + set |= (hdcp_bus_sel) + ? (1 << GENERAL_BUS_SETTINGS_HDCP_BUS_BIT) + : 0; + set |= (hdcp_bus_lock) + ? (1 << GENERAL_BUS_SETTINGS_HDCP_BUS_LOCK_BIT) + : 0; + set |= (capb_bus_sel) + ? (1 << GENERAL_BUS_SETTINGS_CAPB_OWNER_BIT) + : 0; + set |= (capb_bus_lock) + ? (1 << GENERAL_BUS_SETTINGS_CAPB_OWNER_LOCK_BIT) + : 0; + + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, + GENERAL_BUS_SETTINGS, 1, 1, set); + + return CDN_STARTED; + } + + INTERNAL_PROCESS_MESSAGES; + internal_opcode_ok_or_return(MB_MODULE_ID_GENERAL, + GENERAL_BUS_SETTINGS_RESP); + + /* Read one one-byte response */ + internal_readmsg(1, 1, &resp); + + *dpcd_resp = + (resp & (1 << GENERAL_BUS_SETTINGS_RESP_DPCD_BUS_BIT)) ? 1 : 0; + *hdcp_resp = + (resp & (1 << GENERAL_BUS_SETTINGS_RESP_HDCP_BUS_BIT)) ? 1 : 0; + *capb_resp = + (resp & (1 << GENERAL_BUS_SETTINGS_RESP_CAPB_OWNER_BIT)) ? 1 : 0; + + return CDN_OK; +} + +CDN_API_STATUS cdn_api_apbconf_blocking(uint8_t dpcd_bus_sel, + uint8_t dpcd_bus_lock, + uint8_t hdcp_bus_sel, + uint8_t hdcp_bus_lock, + uint8_t capb_bus_sel, + uint8_t capb_bus_lock, + uint8_t *dpcd_resp, + uint8_t *hdcp_resp, + uint8_t *capb_resp) +{ + internal_block_function(cdn_api_apbconf(dpcd_bus_sel, dpcd_bus_lock, + hdcp_bus_sel, hdcp_bus_lock, + capb_bus_sel, capb_bus_lock, + dpcd_resp, hdcp_resp, + capb_resp)); +} + +CDN_API_STATUS cdn_api_setclock(unsigned char mhz) +{ + return cdn_apb_write(SW_CLK_H << 2, mhz); +} + +CDN_API_STATUS cdn_api_general_read_register(unsigned int addr, + GENERAL_READ_REGISTER_RESPONSE + *resp) +{ + CDN_API_STATUS ret; + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, + GENERAL_READ_REGISTER, 1, 4, addr); + state.bus_type = CDN_BUS_TYPE_APB; + state.rxenable = 1; + return CDN_STARTED; + } + INTERNAL_PROCESS_MESSAGES; + ret = internal_test_rx_head(MB_MODULE_ID_GENERAL, + GENERAL_READ_REGISTER_RESP); + if (ret != CDN_OK) + return ret; + internal_readmsg(2, 4, &resp->addr, 4, &resp->val); + return CDN_OK; +} + +CDN_API_STATUS +cdn_api_general_read_register_blocking(unsigned int addr, + GENERAL_READ_REGISTER_RESPONSE *resp) +{ + internal_block_function(cdn_api_general_read_register(addr, resp)); +} + +CDN_API_STATUS cdn_api_general_write_register(unsigned int addr, + unsigned int val) +{ + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, + GENERAL_WRITE_REGISTER, 2, 4, addr, 4, + val); + state.bus_type = CDN_BUS_TYPE_APB; + return CDN_STARTED; + } + INTERNAL_PROCESS_MESSAGES; + return CDN_OK; +} + +CDN_API_STATUS cdn_api_general_write_register_blocking(unsigned int addr, + unsigned int val) +{ + internal_block_function(cdn_api_general_write_register(addr, val)); +} + +CDN_API_STATUS cdn_api_general_write_field(unsigned int addr, + unsigned char startbit, + unsigned char bitsno, + unsigned int val) +{ + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, GENERAL_WRITE_FIELD, + 4, 4, addr, 1, startbit, 1, bitsno, 4, + val); + state.bus_type = CDN_BUS_TYPE_APB; + return CDN_STARTED; + } + INTERNAL_PROCESS_MESSAGES; + return CDN_OK; +} + +CDN_API_STATUS cdn_api_general_write_field_blocking(unsigned int addr, + unsigned char startbit, + unsigned char bitsno, + unsigned int val) +{ + internal_block_function(cdn_api_general_write_field + (addr, startbit, bitsno, val)); +} + +CDN_API_STATUS cdn_api_general_phy_test_access(uint8_t *resp) +{ + CDN_API_STATUS ret; + + *resp = 0; + + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, GENERAL_TEST_ACCESS, + 0); + state.bus_type = CDN_BUS_TYPE_APB; + state.rxenable = 1; + + return CDN_STARTED; + } + + INTERNAL_PROCESS_MESSAGES; + + ret = internal_test_rx_head(MB_MODULE_ID_GENERAL, GENERAL_TEST_ACCESS); + + if (ret != CDN_OK) + return ret; + + internal_readmsg(1, 1, resp); + + return CDN_OK; +} + +CDN_API_STATUS cdn_api_general_phy_test_access_blocking(uint8_t *resp) +{ + internal_block_function(cdn_api_general_phy_test_access(resp)); +} diff --git a/drivers/video/imx/hdp/API_General.h b/drivers/video/imx/hdp/API_General.h new file mode 100644 index 000000000000..44e16e8ad7f5 --- /dev/null +++ b/drivers/video/imx/hdp/API_General.h @@ -0,0 +1,302 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * API_General.h + * + ****************************************************************************** + */ + +#ifndef API_GENERAL_H_ +#define API_GENERAL_H_ + +#ifndef __UBOOT__ +#include +#else +#include +#endif + +#define GENERAL_TEST_ECHO_MAX_PAYLOAD 100 +#define GENERAL_TEST_ECHO_MIN_PAYLOAD 1 + +/** + * \addtogroup GENERAL_API + * \{ + */ +/** status code returned by API calls */ +typedef enum { + /** operation succedded */ + CDN_OK = 0, + /** CEC operation succedded */ + CDN_CEC_ERR_NONE = 0, + /** mailbox is currently sending or receiving data */ + CDN_BSY, + /** message set up and ready to be sent, no data sent yet */ + CDN_STARTED, + /** error encountered while reading/writing APB */ + CDN_ERR, + /** reply returned with bad opcode */ + CDN_BAD_OPCODE, + /** reply returned with bad module */ + CDN_BAD_MODULE, + /** reply not supported mode */ + CDN_ERROR_NOT_SUPPORTED, + /** Invalid argument passed to CEC API function */ + CDN_CEC_ERR_INVALID_ARG, + /** + * TX Buffer for CEC Messages is full. This is applicable only + * when TX Buffers for CEC Messages are implemented in the HW. + */ + CDN_CEC_ERR_TX_BUFF_FULL, + /** No Messages in the RX Buffers are present. */ + CDN_CEC_ERR_RX_BUFF_EMPTY, + /** Timeout during TX operation */ + CDN_CEC_ERR_TX_TIMEOUT, + /** Timeout during RX operation */ + CDN_CEC_ERR_RX_TIMEOUT, + /** Data transmision fail. */ + CDN_CEC_ERR_TX_FAILED, + /** Data reception fail. */ + CDN_CEC_ERR_RX_FAILED, + /** Operation aborted. */ + CDN_CEC_ERR_ABORT, + /** All Logical Addresses are in use. */ + CDN_CEC_ERR_ALL_LA_IN_USE, +} CDN_API_STATUS; + +typedef enum { + CDN_BUS_TYPE_APB = 0, + CDN_BUS_TYPE_SAPB = 1 +} CDN_BUS_TYPE; + +/** + * GENERAL_Read_Register response struct + */ +typedef struct { + unsigned int addr; + unsigned int val; +} GENERAL_READ_REGISTER_RESPONSE; + +/** + * \brief set up API, must be called before any other API call + */ +void cdn_api_init(void); + +/** + * \brief Loads firmware + * + * \param iMem - pointer to instruction memory + * \param imemSize - size of instruction memory buffer + * \param dMem - pointer to data memory + * \param dmemSize - size of data memory buffer + * \return 0 if success, 1 if apb error encountered, 2 if CPU + * isn't alive after loading firmware + * + * This function does not require initialisation by #CDN_API_Init + */ + +CDN_API_STATUS cdn_api_loadfirmware(unsigned char *imem, + int imemsize, + unsigned char *dmem, int dmemsize); +/** + * \brief debug echo command for APB + * \param val - value to echo + * \return status + * + * will return #CDN_ERROR if reply message doesn't match request + */ +CDN_API_STATUS cdn_api_general_test_echo(unsigned int val, + CDN_BUS_TYPE bus_type); + +/** + * \brief blocking version of #CDN_API_General_Test_Echo + */ +CDN_API_STATUS cdn_api_general_test_echo_blocking(unsigned int val, + CDN_BUS_TYPE bus_type); + +/** + * \brief Extended Echo test for mailbox. + * + * This test will send msg buffer to firmware's mailbox and + * receive it back to the resp buffer. Received data will be + * check against data sent and status will be returned as well + * as received data. + * + * \param msg - Pointer to a buffer to send. + * \param resp - Pointer to buffer for receiving msg payload back. + * \param num_bytes - Number of bytes to send and receive. + * \param bus_type Bus type. + * \return status + * + * will return #CDN_ERROR if reply message doesn't match request or if + * arguments are invalid. + */ +CDN_API_STATUS cdn_api_general_test_echo_ext(uint8_t const *msg, uint8_t *resp, + uint16_t num_bytes, + CDN_BUS_TYPE bus_type); + +/** + * \brief blocking version of #CDN_API_General_Test_Echo_Ext + */ +CDN_API_STATUS cdn_api_general_test_echo_ext_blocking(uint8_t const *msg, + uint8_t *resp, + uint16_t num_bytes, + CDN_BUS_TYPE bus_type); + +/** + * \brief get current version + * \param [out] ver - fw version + * \param [out] libver - lib version + * \return status + * + * this fucntion does not require #CDN_API_Init + */ +CDN_API_STATUS cdn_api_general_getcurversion(unsigned short *ver, + unsigned short *verlib); + +/** + * \brief read event value + * \param [out] event - pointer to store 32-bit events value + * \return status + * + * this function does not require #CDN_API_Init + */ +CDN_API_STATUS cdn_api_get_event(uint32_t *events); + +/** + * \brief read debug register value + * \param [out] val - pointer to store 16-bit debug reg value + * \return status + * + * this function does not require #CDN_API_Init + */ +CDN_API_STATUS cdn_api_get_debug_reg_val(uint16_t *val); + +/** + * \brief check if KEEP_ALIVE register changed + * \return #CDN_BSY if KEEP_ALIVE not changed, #CDN_OK if changed and #CDN_ERR + * if error occured while reading + */ +CDN_API_STATUS cdn_api_checkalive(void); + +/** + * \breif blocking version of #CDN_API_CheckAlive + * blocks untill KEEP_ALIVE register changes or error occurs while reading + */ +CDN_API_STATUS cdn_api_checkalive_blocking(void); + +/** + * \brief set cpu to standby or active + * \param [in] state - 1 for active, 0 for standby + * \return status + */ +CDN_API_STATUS cdn_api_maincontrol(unsigned char mode, unsigned char *resp); + +/** + * \breif blocking version of #CDN_API_MainControl + */ +CDN_API_STATUS cdn_api_maincontrol_blocking(unsigned char mode, + unsigned char *resp); + +/** + * \brief settings for APB + * + * Sends GENERAL_APB_CONF Command via regular Mailbox. + * @param dpcd_bus_sel Set DPCD to use selected bus (0 for APB or 1 for SAPB) + * @param dpcd_bus_lock Lock bus type. Aftern that bus type cannot be changed + * by using this function. + * @param hdcp_bus_sel Same meaning as for DPCD but for HDCP. + * @param hdcp_bus_lock Same meaning as for DPCD but for HDCP. + * @param capb_bus_sel Same meaning as for DPCD but for Cipher APB. + * @param capb_bus_lock Same meaning as for DPCD but for Cipher APB. + * @param dpcd_resp [out] Status of the operation. + * If set to zero then DPCD bus type was successfuly changed. + * If not then error occurred, most likely due to locked DPCD bus. + * @param hdcp_resp [out] Same as for DPCD but for HDCP. + * @param capb_resp [out] Same as for DPCD but for Cipher APB. + * + * \return status + */ +CDN_API_STATUS cdn_api_apbconf(uint8_t dpcd_bus_sel, uint8_t dpcd_bus_lock, + uint8_t hdcp_bus_sel, uint8_t hdcp_bus_lock, + uint8_t capb_bus_sel, uint8_t capb_bus_lock, + uint8_t *dpcd_resp, uint8_t *hdcp_resp, + uint8_t *capb_resp); + +/** + * blocking version of #CDN_API_MainControl + */ +CDN_API_STATUS cdn_api_apbconf_blocking(uint8_t dpcd_bus_sel, + uint8_t dpcd_bus_lock, + uint8_t hdcp_bus_sel, + uint8_t hdcp_bus_lock, + uint8_t capb_bus_sel, + uint8_t capb_bus_lock, + uint8_t *dpcd_resp, + uint8_t *hdcp_resp, + uint8_t *capb_resp); + +/** + * \brief set the xtensa clk, write this api before turn on the cpu + */ +CDN_API_STATUS cdn_api_setclock(unsigned char mhz); + +CDN_API_STATUS cdn_api_general_read_register(unsigned int addr, + GENERAL_READ_REGISTER_RESPONSE + *resp); +CDN_API_STATUS +cdn_api_general_read_register_blocking(unsigned int addr, + GENERAL_READ_REGISTER_RESPONSE *resp); +CDN_API_STATUS cdn_api_general_write_register(unsigned int addr, + unsigned int val); +CDN_API_STATUS cdn_api_general_write_register_blocking(unsigned int addr, + unsigned int val); +CDN_API_STATUS cdn_api_general_write_field(unsigned int addr, + unsigned char startbit, + unsigned char bitsno, + unsigned int val); +CDN_API_STATUS cdn_api_general_write_field_blocking(unsigned int addr, + unsigned char startbit, + unsigned char bitsno, + unsigned int val); +CDN_API_STATUS cdn_api_general_phy_test_access(uint8_t *resp); +CDN_API_STATUS cdn_api_general_phy_test_access_blocking(uint8_t *resp); + +#endif diff --git a/drivers/video/imx/hdp/Makefile b/drivers/video/imx/hdp/Makefile new file mode 100644 index 000000000000..13dcefdee5f6 --- /dev/null +++ b/drivers/video/imx/hdp/Makefile @@ -0,0 +1 @@ +obj-y += API_General.o util.o test_base_sw.o diff --git a/drivers/video/imx/hdp/address.h b/drivers/video/imx/hdp/address.h new file mode 100644 index 000000000000..fd8936246bd9 --- /dev/null +++ b/drivers/video/imx/hdp/address.h @@ -0,0 +1,108 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * address.h + * + ****************************************************************************** + */ + +#ifndef ADDRESS_H_ +# define ADDRESS_H_ + +# define ADDR_IMEM 0x10000 +# define ADDR_DMEM 0x20000 +# define ADDR_CIPHER 0x60000 +# define BASE_CIPHER 0x600 +# define ADDR_APB_CFG 0x00000 +# define BASE_APB_CFG 0x000 +# define ADDR_SOURCE_AIF_DECODER 0x30000 +# define BASE_SOURCE_AIF_DECODER 0x300 +# define ADDR_SOURCE_AIF_SMPL2PCKT 0x30080 +# define BASE_SOURCE_AIF_SMPL2PCKT 0x300 +# define ADDR_AIF_ENCODER 0x30000 +# define BASE_AIF_ENCODER 0x300 +# define ADDR_SOURCE_PIF 0x30800 +# define BASE_SOURCE_PIF 0x308 +# define ADDR_SINK_PIF 0x30800 +# define BASE_SINK_PIF 0x308 +# define ADDR_APB_CFG 0x00000 +# define BASE_APB_CFG 0x000 +# define ADDR_SOURCE_CSC 0x40000 +# define BASE_SOURCE_CSC 0x400 +# define ADDR_UCPU_CFG 0x00000 +# define BASE_UCPU_CFG 0x000 +# define ADDR_SOURCE_CAR 0x00900 +# define BASE_SOURCE_CAR 0x009 +# define ADDR_SINK_CAR 0x00900 +# define BASE_SINK_CAR 0x009 +# define ADDR_CLOCK_METERS 0x00A00 +# define BASE_CLOCK_METERS 0x00A +# define ADDR_SOURCE_VIF 0x00b00 +# define BASE_SOURCE_VIF 0x00b +# define ADDR_SINK_MHL_HD 0x01000 +# define ADDR_SINK_VIDEO_HD 0x01800 +# define BASE_SINK_MHL_HD 0x010 +# define ADDR_SINK_CORE 0x07800 +# define BASE_SINK_CORE 0x078 +# define ADDR_DPTX_PHY 0x02000 +# define BASE_DPTX_PHY 0x020 +# define ADDR_DPTX_HPD 0x02100 +# define BASE_DPTX_HPD 0x021 +# define ADDR_DPTX_FRAMER 0x02200 +# define BASE_DPTX_FRAMER 0x022 +# define ADDR_DPTX_STREAM 0x02200 +# define BASE_DPTX_STREAM 0x022 +# define ADDR_DPTX_GLBL 0x02300 +# define BASE_DPTX_GLBL 0x023 +# define ADDR_DPTX_HDCP 0x02400 +# define BASE_DPTX_HDCP 0x024 +# define ADDR_DP_AUX 0x02800 +# define BASE_DP_AUX 0x028 +# define ADDR_CRYPTO 0x05800 +# define BASE_CRYPTO 0x058 +# define ADDR_CIPHER 0x60000 +# define BASE_CIPHER 0x600 +# define ADDR_SOURCE_MHL_HD 0x01000 + +# define ADDR_AFE (0x20000 * 4) +# define ADDR_SOURCD_PHY (0x800) + +#endif diff --git a/drivers/video/imx/hdp/apb_cfg.h b/drivers/video/imx/hdp/apb_cfg.h new file mode 100644 index 000000000000..cdcbd76c016c --- /dev/null +++ b/drivers/video/imx/hdp/apb_cfg.h @@ -0,0 +1,185 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * apb_cfg.h + * + ****************************************************************************** + */ + +#ifndef APB_CFG_H_ +#define APB_CFG_H_ + +/* register APB_CTRL */ +#define APB_CTRL 0 +#define F_APB_XT_RESET(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_APB_XT_RESET_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_APB_DRAM_PATH(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_APB_DRAM_PATH_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_APB_IRAM_PATH(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_APB_IRAM_PATH_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) + +/* register XT_INT_CTRL */ +#define XT_INT_CTRL 1 +#define F_XT_INT_POLARITY(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_XT_INT_POLARITY_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) + +/* register MAILBOX_FULL_ADDR */ +#define MAILBOX_FULL_ADDR 2 +#define F_MAILBOX_FULL(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_MAILBOX_FULL_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register MAILBOX_EMPTY_ADDR */ +#define MAILBOX_EMPTY_ADDR 3 +#define F_MAILBOX_EMPTY(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_MAILBOX_EMPTY_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register MAILBOX0_WR_DATA */ +#define MAILBOX0_WR_DATA 4 +#define F_MAILBOX0_WR_DATA(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_MAILBOX0_WR_DATA_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register MAILBOX0_RD_DATA */ +#define MAILBOX0_RD_DATA 5 +#define F_MAILBOX0_RD_DATA(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_MAILBOX0_RD_DATA_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register KEEP_ALIVE */ +#define KEEP_ALIVE 6 +#define F_KEEP_ALIVE_CNT(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_KEEP_ALIVE_CNT_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register VER_L */ +#define VER_L 7 +#define F_VER_LSB(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_VER_LSB_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register VER_H */ +#define VER_H 8 +#define F_VER_MSB(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_VER_MSB_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register VER_LIB_L_ADDR */ +#define VER_LIB_L_ADDR 9 +#define F_SW_LIB_VER_L(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_LIB_VER_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register VER_LIB_H_ADDR */ +#define VER_LIB_H_ADDR 10 +#define F_SW_LIB_VER_H(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_LIB_VER_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_DEBUG_L */ +#define SW_DEBUG_L 11 +#define F_SW_DEBUG_7_0(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_DEBUG_7_0_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_DEBUG_H */ +#define SW_DEBUG_H 12 +#define F_SW_DEBUG_15_8(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_DEBUG_15_8_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register MAILBOX_INT_MASK */ +#define MAILBOX_INT_MASK 13 +#define F_MAILBOX_INT_MASK(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_MAILBOX_INT_MASK_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) + +/* register MAILBOX_INT_STATUS */ +#define MAILBOX_INT_STATUS 14 +#define F_MAILBOX_INT_STATUS(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_MAILBOX_INT_STATUS_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) + +/* register SW_CLK_L */ +#define SW_CLK_L 15 +#define F_SW_CLOCK_VAL_L(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_CLOCK_VAL_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_CLK_H */ +#define SW_CLK_H 16 +#define F_SW_CLOCK_VAL_H(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_CLOCK_VAL_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_EVENTS0 */ +#define SW_EVENTS0 17 +#define F_SW_EVENTS7_0(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_EVENTS7_0_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_EVENTS1 */ +#define SW_EVENTS1 18 +#define F_SW_EVENTS15_8(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_EVENTS15_8_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_EVENTS2 */ +#define SW_EVENTS2 19 +#define F_SW_EVENTS23_16(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_EVENTS23_16_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register SW_EVENTS3 */ +#define SW_EVENTS3 20 +#define F_SW_EVENTS31_24(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SW_EVENTS31_24_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register XT_OCD_CTRL */ +#define XT_OCD_CTRL 24 +#define F_XT_DRESET(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_XT_DRESET_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_XT_OCDHALTONRESET(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_XT_OCDHALTONRESET_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) + +/* register XT_OCD_CTRL_RO */ +#define XT_OCD_CTRL_RO 25 +#define F_XT_XOCDMODE(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_XT_XOCDMODE_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register APB_INT_MASK */ +#define APB_INT_MASK 27 +#define F_APB_INTR_MASK(x) (((x) & ((1 << 3) - 1)) << 0) +#define F_APB_INTR_MASK_RD(x) (((x) & (((1 << 3) - 1) << 0)) >> 0) + +/* register APB_STATUS_MASK */ +#define APB_STATUS_MASK 28 +#define F_APB_INTR_STATUS(x) (((x) & ((1 << 3) - 1)) << 0) +#define F_APB_INTR_STATUS_RD(x) (((x) & (((1 << 3) - 1) << 0)) >> 0) + +#endif /*APB_CFG*/ diff --git a/drivers/video/imx/hdp/externs.h b/drivers/video/imx/hdp/externs.h new file mode 100644 index 000000000000..a222d2658edc --- /dev/null +++ b/drivers/video/imx/hdp/externs.h @@ -0,0 +1,80 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * externs.h + * + ****************************************************************************** + */ + +#ifndef EXTERNS_H_ +#define EXTERNS_H_ + +#ifndef __UBOOT__ +#include + +#else +#include +#endif +/** + * \addtogroup UTILS + * \{ + */ +/** + * \brief read from apb + * \param addr - address to read + * \param value - pointer to store value + * \return non-zero value if error + */ +/*extern int cdn_bus_read(unsigned int addr, unsigned int* value);*/ + +/** + * \brief write to apb + * \param addr - address to write + * \param value - value to write + * \return non-zero if error + */ +/*extern int cdn_bus_write(unsigned int addr, unsigned int value);*/ + +uint32_t cdn_apb_read(uint32_t addr, uint32_t *value); +uint32_t cdn_sapb_read(uint32_t addr, uint32_t *value); +uint32_t cdn_apb_write(uint32_t addr, uint32_t value); +uint32_t cdn_sapb_write(uint32_t addr, uint32_t value); +#endif diff --git a/drivers/video/imx/hdp/general_handler.h b/drivers/video/imx/hdp/general_handler.h new file mode 100644 index 000000000000..3656ef8848e8 --- /dev/null +++ b/drivers/video/imx/hdp/general_handler.h @@ -0,0 +1,162 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * general_handler.h + * + ****************************************************************************** + */ + +#ifndef GENERAL_HANDLER_H +#define GENERAL_HANDLER_H + +/** + * \file + * \brief general handler, checks available messages, receives + * it from mailbox, handles requests and sends response + * to the host + */ +#define DP_TX_MAIL_HANDLER_REQUEST_BUFFER_LEN 256 + +/** + * \brief opcode defines host->controller + */ +#define GENERAL_MAIN_CONTROL 0x01 +#define GENERAL_TEST_ECHO 0x02 +#define GENERAL_BUS_SETTINGS 0x03 +#define GENERAL_TEST_ACCESS 0x04 + +#define GENERAL_WRITE_REGISTER 0x05 +#define GENERAL_WRITE_FIELD 0x06 +#define GENERAL_READ_REGISTER 0x07 + +#define GENERAL_TEST_TRNG_SIMPLE 0xF0 + +#define GENERAL_MAIN_CONTROL_SET_ACTIVE_BIT 0 +#define GENERAL_MAIN_CONTROL_SET_ALT_CIPHER_ADDR 1 +#define GENERAL_MAIN_CONTROL_SET_FAST_HDCP_DELAYS 2 + +#define GENERAL_BUS_SETTINGS_DPCD_BUS_BIT 0 +#define GENERAL_BUS_SETTINGS_DPCD_BUS_LOCK_BIT 1 +#define GENERAL_BUS_SETTINGS_HDCP_BUS_BIT 2 +#define GENERAL_BUS_SETTINGS_HDCP_BUS_LOCK_BIT 3 +#define GENERAL_BUS_SETTINGS_CAPB_OWNER_BIT 4 +#define GENERAL_BUS_SETTINGS_CAPB_OWNER_LOCK_BIT 5 + +/** + * \brief opcode defines controller->host + */ + +#define GENERAL_MAIN_CONTROL_RESP 0x01 +#define GENERAL_TEST_ECHO_RESP 0x02 +#define GENERAL_BUS_SETTINGS_RESP 0x03 + +#define GENERAL_READ_REGISTER_RESP 0x07 + +#define GENERAL_BUS_SETTINGS_RESP_DPCD_BUS_BIT 0 +#define GENERAL_BUS_SETTINGS_RESP_HDCP_BUS_BIT 1 +#define GENERAL_BUS_SETTINGS_RESP_CAPB_OWNER_BIT 2 + +#define GENERAL_BUS_SETTINGS_RESP_SUCCESS 0 +#define GENERAL_BUS_SETTINGS_RESP_LOCK_ERROR 1 + +typedef struct { + unsigned char dpcd_locked; + unsigned char hdcp_locked; + unsigned char capb_locked; + unsigned char active_mode; +} S_GENERAL_HANDLER_DATA; + +/** + * \brief event id sent to the host + */ +typedef enum { + EVENT_ID_DPTX_HPD = 0, + EVENT_ID_HDMI_TX_HPD = 0, + EVENT_ID_HDMI_RX_5V = 0, + + EVENT_ID_DPTX_TRAINING = 1, + EVENT_ID_HDMI_RX_SCDC_CHANGE = 1, + + EVENT_ID_RESERVE0 = 2, + EVENT_ID_RESERVE1 = 3, + + EVENT_ID_HDCPTX_STATUS = 4, + EVENT_ID_HDCPRX_STATUS = 4, + + EVENT_ID_HDCPTX_IS_KM_STORED = 5, + EVENT_ID_HDCPTX_STORE_KM = 6, + EVENT_ID_HDCPTX_IS_RECEIVER_ID_VALID = 7, + EVENT_ID_HDMITX_READ_REQUEST = 8, +} EVENT_ID; + +/** + * \brief convert bank id and register number to address and write to ptr + */ + +#define select_reg_old(bank, reg_no, ptr) \ +do { \ + ptr = 0; \ + if ((bank == 0x22) || (bank == 0x20) || (bank == 0x0b) || \ + (bank == 0x09) || (bank == 0x0A)) \ + ptr = (unsigned int *)(bank << 8 | reg_no); \ +} while (0) + +#define select_reg(bank, reg_no, ptr) \ + ptr = (unsigned int *)(bank << 8 | reg_no) + +#define select_reg4(pmsb, p2, p3, plsb, ptr) \ + ptr = (unsigned int *)((pmsb << 24) | (p2 << 16) | \ + (p3 << 8) | (plsb << 0)) + + +#define EVENTS_DPTX_CNT 2 +#define EVENTS_HDCPTX_CNT 4 + +void general_handler_set_active_mode(void); +void general_handler_set_standby_mode(void); + +/** + * \brief request sending en event to the host + * \param [in] eventId + * \param [in] eventCode + */ + +#endif /* GENERAL_HANDLER_H */ diff --git a/drivers/video/imx/hdp/opcodes.h b/drivers/video/imx/hdp/opcodes.h new file mode 100644 index 000000000000..e0e7d93412b1 --- /dev/null +++ b/drivers/video/imx/hdp/opcodes.h @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * opcodes.h + * + ****************************************************************************** + */ + +#ifndef OPCODES_H_ +# define OPCODES_H_ + +# define DP_TX_MAIL_HANDLER_H +# define DP_TX_MAIL_HANDLER_REQUEST_BUFFER_LEN 256 +# define DPTX_SET_POWER_MNG 0x00 +# define DPTX_SET_HOST_CAPABILITIES 0x01 +# define DPTX_GET_EDID 0x02 +# define DPTX_READ_DPCD 0x03 +# define DPTX_WRITE_DPCD 0x04 +# define DPTX_ENABLE_EVENT 0x05 +# define DPTX_WRITE_REGISTER 0x06 +# define DPTX_READ_REGISTER 0x07 +# define DPTX_WRITE_FIELD 0x08 +# define DPTX_TRAINING_CONTROL 0x09 +# define DPTX_READ_EVENT 0x0A +# define DPTX_READ_LINK_STAT 0x0B +# define DPTX_SET_VIDEO 0x0C +# define DPTX_SET_AUDIO 0x0D +# define DPTX_GET_LAST_AUX_STAUS 0x0E +# define DPTX_SET_LINK_BREAK_POINT 0x0F +# define DPTX_FORCE_LANES 0x10 +# define DPTX_HPD_STATE 0x11 +# define DPTX_DBG_SET 0xF0 +# define DP_TX_OPCODE_READ_I2C_REQUEST 0xA5 +# define DP_TX_OPCODE_WRITE_I2C_REQUEST 0xA6 +# define DP_TX_OPCODE_MESSAGE_FILTER 0xA7 +# define DPTX_EDID_RESP 0x02 +# define DPTX_DPCD_READ_RESP 0x03 +# define DPTX_DPCD_WRITE_RESP 0x04 +# define DPTX_READ_EVENT_RESP 0x0A +# define DPTX_READ_REGISTER_RESP 0x07 +# define DP_TX_OPCODE_MESSAGE 0x10 +# define DP_TX_OPCODE_READ_I2C_RESPONSE 0x50 +# define DP_TX_OPCODE_WRITE_I2C_RESPONSE 0x60 +# define DP_TX_OPCODE_LOOPBACK_TEST 0xFE +# define DP_TX_OPCODE_BIT_TEST 0xFF +# define DP_TX_EVENT_ENABLE_HPD_BIT 0x00 +# define DP_TX_EVENT_ENABLE_TRAINING_BIT 0x01 +# define DP_TX_EVENT_CODE_HPD_HIGH 0x01 +# define DP_TX_EVENT_CODE_HPD_LOW 0x02 +# define DP_TX_EVENT_CODE_HPD_PULSE 0x04 +# define DP_TX_EVENT_CODE_HPD_STATE_HIGH 0x08 +# define DP_TX_EVENT_CODE_HPD_STATE_LOW 0x00 +# define DP_TX_EVENT_CODE_TRAINING_FULL_STARTED 0x01 +# define DP_TX_EVENT_CODE_TRAINING_FAST_STARTED 0x02 +# define DP_TX_EVENT_CODE_TRAINING_FINISHED_CR 0x04 +# define DP_TX_EVENT_CODE_TRAINING_FINISHED_EQ 0x08 +# define DP_TX_EVENT_CODE_TRAINING_FINISHED_FAST 0x10 +# define DP_TX_EVENT_CODE_TRAINING_FAILED_CR 0x20 +# define DP_TX_EVENT_CODE_TRAINING_FAILED_EQ 0x40 +# define DP_TX_EVENT_CODE_TRAINING_FAILED_FAST 0x80 +# define MB_MODULE_ID_DP_TX 0x01 +# define MB_MODULE_ID_DP_RX 0x02 +# define MB_MODULE_ID_HDMI_TX 0x03 +# define MB_MODULE_ID_HDMI_RX 0x04 +# define MB_MODULE_ID_MHL_TX 0x05 +# define MB_MODULE_ID_MHL_RX 0x06 +# define MB_MODULE_ID_HDCP_TX 0x07 +# define MB_MODULE_ID_HDCP_RX 0x08 +# define MB_MODULE_ID_HDCP_GENERAL 0x09 +# define MB_MODULE_ID_GENERAL 0x0A +# define MB_MODULE_ID 1 + +#endif diff --git a/drivers/video/imx/hdp/test_base_sw.c b/drivers/video/imx/hdp/test_base_sw.c new file mode 100644 index 000000000000..46a8ffa650ac --- /dev/null +++ b/drivers/video/imx/hdp/test_base_sw.c @@ -0,0 +1,180 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * test_base_sw.c + * + ****************************************************************************** + */ + +#ifndef __UBOOT__ +#include +#include +#include +#else +#include +#include + +#ifdef CONFIG_ARCH_MX8M +/* mscale */ +#define HDMI_BASE 0x32c00000 +#define HDMI_PHY_BASE 0x32c80000 +#define HDMI_SEC_BASE 0x32e40000 +#endif +#ifdef CONFIG_ARCH_MX8 +/* QM */ +#define HDMI_BASE 0x56268000 +#define HDMI_SEC_BASE 0x56269000 +#define HDMI_OFFSET_ADDR 0x56261008 +#define HDMI_SEC_OFFSET_ADDR 0x5626100c +#endif + +#endif + +#ifdef CONFIG_ARCH_MX8M +int cdn_apb_read(unsigned int addr, unsigned int *value) +{ + unsigned int temp; + uint64_t tmp_addr = addr + HDMI_BASE; + temp = __raw_readl(tmp_addr); + *value = temp; + return 0; +} + +int cdn_apb_write(unsigned int addr, unsigned int value) +{ + uint64_t tmp_addr = addr + HDMI_BASE; + + __raw_writel(value, tmp_addr); + return 0; +} + +int cdn_sapb_read(unsigned int addr, unsigned int *value) +{ + unsigned int temp; + uint64_t tmp_addr = addr + HDMI_SEC_BASE; + temp = __raw_readl(tmp_addr); + *value = temp; + return 0; +} + +int cdn_sapb_write(unsigned int addr, unsigned int value) +{ + uint64_t tmp_addr = addr + HDMI_SEC_BASE; + __raw_writel(value, tmp_addr); + return 0; +} + +void cdn_sleep(uint32_t ms) +{ + mdelay(ms); +} + +void cdn_usleep(uint32_t us) +{ + udelay(us); +} +#endif +#ifdef CONFIG_ARCH_MX8 +int cdn_apb_read(unsigned int addr, unsigned int *value) +{ + unsigned int temp; + uint64_t tmp_addr = (addr & 0xfff) + HDMI_BASE; + + /* printf("%s():%d addr = 0x%08x, tmp_addr = 0x%08x, offset = 0x%08x\n", + __func__, __LINE__, addr, (unsigned int)tmp_addr, addr>>12); */ + + __raw_writel(addr >> 12, HDMI_OFFSET_ADDR); + + temp = __raw_readl(tmp_addr); + /* printf("%s():%d temp = 0x%08x\n", __func__, __LINE__, temp ); */ + + *value = temp; + return 0; +} + +int cdn_apb_write(unsigned int addr, unsigned int value) +{ + uint64_t tmp_addr = (addr & 0xfff) + HDMI_BASE; + + /*printf("%s():%d addr=0x%08x, taddr=0x%08x, off=0x%08x, val=0x%08x\n", + __func__, __LINE__, addr, (unsigned int)tmp_addr, + addr>>12, value);*/ + + __raw_writel(addr >> 12, HDMI_OFFSET_ADDR); + + /* printf("%s():%d\n", __func__, __LINE__); */ + __raw_writel(value, tmp_addr); + + return 0; +} + +int cdn_sapb_read(unsigned int addr, unsigned int *value) +{ + unsigned int temp; + uint64_t tmp_addr = (addr & 0xfff) + HDMI_SEC_BASE; + + __raw_writel(addr >> 12, HDMI_SEC_OFFSET_ADDR); + + temp = __raw_readl(tmp_addr); + *value = temp; + return 0; +} + +int cdn_sapb_write(unsigned int addr, unsigned int value) +{ + uint64_t tmp_addr = (addr & 0xfff) + HDMI_SEC_BASE; + + __raw_writel(addr >> 12, HDMI_SEC_OFFSET_ADDR); + __raw_writel(value, tmp_addr); + + return 0; +} + +void cdn_sleep(uint32_t ms) +{ + mdelay(ms); +} + +void cdn_usleep(uint32_t us) +{ + udelay(us); +} +#endif diff --git a/drivers/video/imx/hdp/util.c b/drivers/video/imx/hdp/util.c new file mode 100644 index 000000000000..727946a79636 --- /dev/null +++ b/drivers/video/imx/hdp/util.c @@ -0,0 +1,329 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * util.c + * + ****************************************************************************** + */ + +#include "util.h" +#include "API_General.h" +#include "externs.h" +#ifndef __UBOOT__ +#include +#endif +#include "apb_cfg.h" +#include "opcodes.h" +#ifndef __UBOOT__ +#include + +#endif +state_struct state; + +int cdn_bus_read(unsigned int addr, unsigned int *value) +{ + return state.bus_type ? + cdn_sapb_read(addr, value) : cdn_apb_read(addr, value); +} + +int cdn_bus_write(unsigned int addr, unsigned int value) +{ + return state.bus_type ? + cdn_sapb_write(addr, value) : cdn_apb_write(addr, value); +} + +void internal_itobe(int val, volatile unsigned char *dest, int bytes) +{ + int i; + for (i = bytes - 1; i >= 0; --i) { + dest[i] = (unsigned char)val; + val >>= 8; + } +} + +uint32_t internal_betoi(volatile uint8_t const *src, uint8_t bytes) +{ + uint32_t ret = 0; + int i; + + if (bytes > sizeof(ret)) { + printf("Warning. Read request for payload larger then supported.\n"); + bytes = sizeof(ret); + } + + for (i = 0; i < bytes; ++i) { + ret <<= 8; + ret |= (unsigned int)src[i]; + } + + return ret; +} + +unsigned int internal_mkmsg(volatile unsigned char *dest, int valno, ...) +{ + va_list vl; + unsigned int len = 0; + va_start(vl, valno); + len = internal_vmkmsg(dest, valno, vl); + va_end(vl); + return len; +} + +unsigned int internal_vmkmsg(volatile unsigned char *dest, int valno, + va_list vl) +{ + unsigned int len = 0; + int i; + for (i = 0; i < valno; ++i) { + int size = va_arg(vl, int); + if (size > 0) { + internal_itobe(va_arg(vl, int), dest, size); + dest += size; + len += size; + } else { + memcpy((void *)dest, va_arg(vl, void *), -size); + dest -= size; + len -= size; + } + } + return len; +} + +void internal_tx_mkfullmsg(unsigned char module, unsigned char opcode, + int valno, ...) +{ + va_list vl; + va_start(vl, valno); + internal_vtx_mkfullmsg(module, opcode, valno, vl); + va_end(vl); +} + +void internal_vtx_mkfullmsg(unsigned char module, unsigned char opcode, + int valno, va_list vl) +{ + unsigned int len = + internal_vmkmsg(state.txbuffer + INTERNAL_CMD_HEAD_SIZE, valno, vl); + internal_mbox_tx_enable(module, opcode, len); + state.txenable = 1; + state.running = 1; +} + +void internal_readmsg(int valno, ...) +{ + va_list vl; + va_start(vl, valno); + internal_vreadmsg(valno, vl); + va_end(vl); +} + +void internal_vreadmsg(int valno, va_list vl) +{ + uint8_t *src = state.rxbuffer + INTERNAL_CMD_HEAD_SIZE; + size_t i; + + for (i = 0; i < (size_t) valno; ++i) { + int size = va_arg(vl, int); + void *ptr = va_arg(vl, void *); + + if (!ptr) { + src += size; + } else if (!size) { + *((unsigned char **)ptr) = src; + } else if (size > 0) { + switch ((size_t) size) { + case sizeof(uint8_t): + *((uint8_t *)ptr) = internal_betoi(src, size); + break; + case sizeof(uint16_t): + *((uint16_t *)ptr) = internal_betoi(src, size); + break; + case 3: /* 3-byte value (e.g. DPCD address) + can be safely converted from BE.*/ + case sizeof(uint32_t): + *((uint32_t *)ptr) = internal_betoi(src, size); + break; + default: + printf("Warning. Unsupported variable size.\n"); + memcpy(ptr, src, size); + }; + + src += size; + } else { + memcpy(ptr, src, -size); + src -= size; + } + } +} + +INTERNAL_MBOX_STATUS mailbox_write(unsigned char val) +{ + INTERNAL_MBOX_STATUS ret; + unsigned int full; + if (cdn_bus_read(MAILBOX_FULL_ADDR << 2, &full)) { + ret.tx_status = CDN_TX_APB_ERROR; + return ret; + } + if (full) { + ret.tx_status = CDN_TX_FULL; + return ret; + } + if (cdn_bus_write(MAILBOX0_WR_DATA << 2, val)) { + ret.tx_status = CDN_TX_APB_ERROR; + return ret; + } + ret.tx_status = CDN_TX_WRITE; + return ret; +} + +INTERNAL_MBOX_STATUS mailbox_read(volatile unsigned char *val) +{ + INTERNAL_MBOX_STATUS ret; + unsigned int empty; + unsigned int rd; + if (cdn_bus_read(MAILBOX_EMPTY_ADDR << 2, &empty)) { + ret.rx_status = CDN_RX_APB_ERROR; + return ret; + } + if (empty) { + ret.rx_status = CDN_RX_EMPTY; + return ret; + } + if (cdn_bus_read(MAILBOX0_RD_DATA << 2, &rd)) { + ret.rx_status = CDN_RX_APB_ERROR; + return ret; + } + *val = (unsigned char)rd; + ret.rx_status = CDN_RX_READ; + return ret; +} + +INTERNAL_MBOX_STATUS internal_mbox_tx_process(void) +{ + unsigned int txcount = 0; + unsigned int length = + (unsigned int)state.txbuffer[2] << 8 | (unsigned int)state. + txbuffer[3]; + INTERNAL_MBOX_STATUS ret = {.txend = 0 }; + ret.tx_status = CDN_TX_NOTHING; + INTERNAL_MBOX_STATUS tx_ret; + if (!state.txenable) + return ret; + while ((tx_ret.tx_status = + mailbox_write(state.txbuffer[state.txi]).tx_status) == + CDN_TX_WRITE) { + txcount++; + if (++state.txi >= length + 4) { + state.txenable = 0; + state.txi = 0; + ret.txend = 1; + break; + } + } + if (txcount && tx_ret.tx_status == CDN_TX_FULL) + ret.tx_status = CDN_TX_WRITE; + else + ret.tx_status = tx_ret.tx_status; + return ret; +} + +INTERNAL_MBOX_STATUS internal_mbox_rx_process(void) +{ + unsigned int rxcount = 0; + INTERNAL_MBOX_STATUS ret = { 0, 0, 0, 0 }; + INTERNAL_MBOX_STATUS rx_ret; + while ((rx_ret.rx_status = + mailbox_read(state.rxbuffer + state.rxi).rx_status) == + CDN_RX_READ) { + rxcount++; + if (++state.rxi >= 4 + + ((unsigned int)state.rxbuffer[2] << 8 | + (unsigned int)state.rxbuffer[3])) { /* end of message */ + state.rxi = 0; + ret.rxend = 1; + state.rxenable = 0; + break; + } + } + ret.rx_status = rxcount ? CDN_RX_READ : CDN_RX_EMPTY; + return ret; +} + +unsigned int internal_apb_available(void) +{ + return !(state.rxenable || state.txenable); +} + +void internal_mbox_tx_enable(unsigned char module, unsigned char opcode, + unsigned short length) +{ + state.txbuffer[0] = opcode; + state.txbuffer[1] = module; + state.txbuffer[2] = (unsigned char)(length >> 8); + state.txbuffer[3] = (unsigned char)length; + state.txenable = 1; +} + +CDN_API_STATUS internal_test_rx_head(unsigned char module, unsigned char opcode) +{ + if (opcode != state.rxbuffer[0]) + return CDN_BAD_OPCODE; + if (module != state.rxbuffer[1]) + return CDN_BAD_MODULE; + return CDN_OK; +} + +CDN_API_STATUS internal_test_rx_head_match(void) +{ + return internal_test_rx_head(state.txbuffer[1], state.txbuffer[0]); +} + +void print_fw_ver(void) +{ + unsigned short ver, verlib; + cdn_api_general_getcurversion(&ver, &verlib); + printf("FIRMWARE VERSION: %d, LIB VERSION: %d\n", ver, verlib); +} + +unsigned short internal_get_msg_len(void) +{ + return ((unsigned short)state.rxbuffer[2] << 8) | (unsigned short)state. + rxbuffer[3]; +} diff --git a/drivers/video/imx/hdp/util.h b/drivers/video/imx/hdp/util.h new file mode 100644 index 000000000000..605f0f933baf --- /dev/null +++ b/drivers/video/imx/hdp/util.h @@ -0,0 +1,278 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Copyright 2017 NXP + * + ****************************************************************************** + * + * util.h + * + ****************************************************************************** + */ + +#ifndef UTIL_H_ +#define UTIL_H_ + +#include "API_General.h" +#ifndef __UBOOT__ +#include +#include +#else +#include +#endif +/** + * \addtogroup UTILS + * \{ + */ +#define INTERNAL_CMD_HEAD_SIZE 4 + +/** + * \brief expands to blocking function body + * \param x - function call + */ +#define internal_block_function(x) \ +do { \ + CDN_API_STATUS ret; \ + do { \ + ret = x; \ + } while (ret == CDN_BSY || ret == CDN_STARTED); \ + return ret; \ +} while (0) + +/** + * \brief write message and write response (if any), non-blocking way. Also sets state.running = 0 + */ +#define INTERNAL_PROCESS_MESSAGES \ +do { \ + if (state.txenable && !internal_mbox_tx_process().txend) \ + return CDN_BSY; \ + if (state.rxenable && !internal_mbox_rx_process().rxend) \ + return CDN_BSY; \ + state.running = 0; \ +} while (0) + +#define internal_opcode_ok_or_return(module, opcode) \ +do { \ + CDN_API_STATUS ret = internal_test_rx_head(module, opcode); \ + if (ret != CDN_OK) \ + return ret; \ +} while (0) + +#define internal_opcode_match_or_return() \ +do { \ + CDN_API_STATUS ret = internal_test_rx_head_match(); \ + if (ret != CDN_OK) \ + return ret; \ +} while (0) + +/* macro for simple tx only command, command format as in mkfullmsg + (with count) */ +#define internal_macro_command_tx(module, opcode, bustype, command...) \ +do { \ + if (!state.running) { \ + internal_tx_mkfullmsg(module, opcode, command); \ + state.bus_type = bustype; \ + return CDN_STARTED; \ + } \ + INTERNAL_PROCESS_MESSAGES; \ +} while (0) + +/* macro for command with response with matching opcode, command format as in + mkfullmsg (with count) */ +#define internal_macro_command_txrx(module, opcode, bustype, command...) \ +do { \ + if (!state.running) { \ + internal_tx_mkfullmsg(module, opcode, command); \ + state.bus_type = bustype; \ + state.rxenable = 1; \ + return CDN_STARTED; \ + } \ + INTERNAL_PROCESS_MESSAGES; \ + internal_opcode_match_or_return(); \ +} while (0) + +typedef struct { + /** apb write status */ + enum tx_status_enum { + /** one or more bytes written */ + CDN_TX_WRITE = 0, + /** nothing to write */ + CDN_TX_NOTHING = 1, + /** mailbox full, 0 bytes written */ + CDN_TX_FULL = 2, + /** APB error while writing */ + CDN_TX_APB_ERROR = 3 + } tx_status:3; + /** apb read status */ + enum rx_status_enum { + /** 1 or more bytes read */ + CDN_RX_READ = 0, + /** mailbox empty, 0 bytes read */ + CDN_RX_EMPTY = 1, + /** apb error while reading */ + CDN_RX_APB_ERROR = 2 + } rx_status:2; + /** indicates end of currenly recived message */ + unsigned char rxend:1; + /** end of tx message reached */ + unsigned char txend:1; +} INTERNAL_MBOX_STATUS; + +/** + * \brief put val into dest in big endian format + * \param val - value to put + * \param dest - place to put value + * \param bytes - true size of val in bytes. for example if + * bytes = 2 val is treated as short int + */ +void internal_itobe(int val, volatile unsigned char *dest, int bytes); + +/** + * \brief read big endian value from src and return it + * \param src - source to read from + * \param bytes - size of read value + * \return result + */ +uint32_t internal_betoi(volatile uint8_t const *src, uint8_t bytes); + +/** + * \brief create message from size and value pairs; also sets + * state.running and state.txEnable + * \param dest - pointer to write message to + * \param valNo - number of values to write + * \param ... - pairs of size and value, each value is written + * after another. if size is positive value, value is + * written with #internal_itobe, if size is negative, + * value is treated as src pointer for memcpy + * + * example: + * + * unsigned short x = 0xAABB; + * + * internal_mkmsg(dest, 3, 1, 1, 2, 3, -2, &x); + * + * will write 01 00 03 AA BB to dest + */ +unsigned int internal_mkmsg(volatile unsigned char *dest, int valno, ...); +unsigned int internal_vmkmsg(volatile unsigned char *dest, int valno, + va_list vl); + +/** + * \brief setup message header in txBuffer, set txEnable = 1 + */ +void internal_mbox_tx_enable(unsigned char module, unsigned char opcode, + unsigned short length); + +/** + * \brief write from txBuffer to mailbox untill full or end of message. + * + * when txEnable == 0 writes nothing + * when write reaches end of message set txEnable = 0 + */ + +/** + * \brief combination of #internal_mkmsg and #internal_mbox_tx_enable + * + * #internal_mkmsg dest and #internal_mbox_tx_enable length are determined + * automaticly this function also sets state.txEnable = 1 and + * state.running + */ +void internal_tx_mkfullmsg(unsigned char module, unsigned char opcode, + int valno, ...); +void internal_vtx_mkfullmsg(unsigned char module, unsigned char opcode, + int valno, va_list vl); + +/** + * \brief read from state.txBuffer and store results in specified pointers + * \param valNo - numbero of values to read + * \param ... - pairs of size and ptr + * + * this function is similar to #internal_mkmsg - + * + * when size is positive read value using #internal_betoi + * when size is negative mempcy from txBuffer to ptr -size bytes + * when size is 0 write to ptr addres of current position in rxbuffer + * when ptr is NULL ignore size bytes (if size is negative this + * will rewind buffer) + */ +void internal_readmsg(int valno, ...); +void internal_vreadmsg(int valno, va_list vl); + +INTERNAL_MBOX_STATUS internal_mbox_tx_process(void); +/** + * \brief read to rxBuffer from mailbox untill empty or end of message + * + * when rxEnable == 0 reads nothing + * when end of message reached sets rxEnable = 0 + */ +INTERNAL_MBOX_STATUS internal_mbox_rx_process(void); + +/** + * \brief check if apb is available + * \return !(rxEnable && txEable) + */ +unsigned int internal_apb_available(void); + +/** + * \brief test if parameters match module and opcode in rxBuffer + * \return CDN_OK or CDN_BAD_OPCODE or CDN_BAD_MODULE + */ +CDN_API_STATUS internal_test_rx_head(unsigned char module, + unsigned char opcode); + +CDN_API_STATUS internal_test_rx_head_match(void); + +/** + * \brief print current fw and lib version + */ +void print_fw_ver(void); + +typedef struct { + unsigned char txbuffer[1024]; + unsigned char rxbuffer[1024]; + unsigned int txi; /* iterators */ + unsigned int rxi; + unsigned char txenable; /*data readt to send*/ + unsigned char rxenable; + unsigned char running; + CDN_BUS_TYPE bus_type; + unsigned int tmp; +} state_struct; + +unsigned short internal_get_msg_len(void); + +#endif diff --git a/drivers/video/imx/hdpload.c b/drivers/video/imx/hdpload.c new file mode 100644 index 000000000000..0ffc960a6daf --- /dev/null +++ b/drivers/video/imx/hdpload.c @@ -0,0 +1,107 @@ +/* + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include + +#include "API_General.h" +#include "scfw_utils.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define ON 1 +#define OFF 0 + +static void display_set_power(int onoff) +{ + sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle; + + SC_PM_SET_RESOURCE_POWER_MODE(ipcHndl, SC_R_DC_0, onoff); + SC_PM_SET_RESOURCE_POWER_MODE(ipcHndl, SC_R_HDMI, onoff); +} + +static void display_set_clocks(void) +{ + sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle; + const sc_pm_clock_rate_t pll = 1188000000; + const sc_pm_clock_rate_t hdmi_core_clock = pll / 10; + const sc_pm_clock_rate_t hdmi_bus_clock = pll / 14; + + SC_PM_SET_RESOURCE_POWER_MODE(ipcHndl, + SC_R_HDMI_PLL_0, SC_PM_PW_MODE_OFF); + SC_PM_SET_CLOCK_RATE(ipcHndl, + SC_R_HDMI_PLL_0, SC_PM_CLK_PLL, pll); + SC_PM_SET_RESOURCE_POWER_MODE(ipcHndl, + SC_R_HDMI_PLL_0, SC_PM_PW_MODE_ON); + + /* HDMI DI Bus Clock */ + SC_PM_SET_CLOCK_RATE(ipcHndl, + SC_R_HDMI, SC_PM_CLK_MISC4, hdmi_bus_clock); + /* HDMI DI Core Clock */ + SC_PM_SET_CLOCK_RATE(ipcHndl, + SC_R_HDMI, SC_PM_CLK_MISC2, hdmi_core_clock); +} + +static void display_enable_clocks(int enable) +{ + sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle; + + SC_PM_CLOCK_ENABLE(ipcHndl, SC_R_HDMI_PLL_0, SC_PM_CLK_PLL, enable); + SC_PM_CLOCK_ENABLE(ipcHndl, SC_R_HDMI, SC_PM_CLK_MISC2, enable); + SC_PM_CLOCK_ENABLE(ipcHndl, SC_R_HDMI, SC_PM_CLK_MISC4, enable); +} + +int do_hdp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + if (argc < 2) + return 0; + + if (strncmp(argv[1], "tracescfw", 9) == 0) { + g_debug_scfw = 1; + printf("Enabled SCFW API tracing\n"); + } else if (strncmp(argv[1], "load", 7) == 0) { + unsigned long address = 0; + unsigned long offset = 0x2000; + const int iram_size = 0x10000; + const int dram_size = 0x8000; + + if (argc > 2) { + address = simple_strtoul(argv[2], NULL, 0); + if (argc > 3) + offset = simple_strtoul(argv[3], NULL, 0); + } else + printf("Missing address\n"); + + printf("Loading hdp firmware from 0x%016lx offset 0x%016lx\n", + address, offset); + display_set_power(SC_PM_PW_MODE_ON); + display_set_clocks(); + display_enable_clocks(ON); + cdn_api_loadfirmware((unsigned char *)(address + offset), + iram_size, + (unsigned char *)(address + offset + + iram_size), + dram_size); + display_enable_clocks(OFF); + printf("Loading hdp firmware Complete\n"); + /* do not turn off hdmi power or firmware load will be lost */ + } else { + printf("test error argc %d\n", argc); + } + + return 0; +} +/***************************************************/ + +U_BOOT_CMD( + hdp, CONFIG_SYS_MAXARGS, 1, do_hdp, + "load hdmi firmware ", + "[] ...\n" + "hdpload [address] []\n" + " address - address where the binary image starts\n" + " - IRAM offset in the binary image (8192 default)\n" + "tracescfw - Trace SCFW API calls for video commands\n" + ); diff --git a/drivers/video/imx/scfw_utils.h b/drivers/video/imx/scfw_utils.h new file mode 100644 index 000000000000..6f6143db450a --- /dev/null +++ b/drivers/video/imx/scfw_utils.h @@ -0,0 +1,90 @@ +/* + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#ifndef _SCFW_UTILS_H_ +#define _SCFW_UTILS_H_ + +#include +#include + +static int g_debug_scfw; /* set to one to turn on SCFW API tracing */ + +#define SC_PM_SET_CLOCK_PARENT(__ipcHndl__, __res__, __clk__, __parent__) \ +do { \ + char _res_str[] = #__res__;\ + char _clk_str[] = #__clk__;\ + sc_err_t _ret;\ + if (g_debug_scfw) \ + printf("(%4d) sc_pm_set_clock_parent %s:%s -> %d\n",\ + __LINE__, _res_str, _clk_str, __parent__);\ + _ret = sc_pm_set_clock_parent(__ipcHndl__,\ + __res__, __clk__, __parent__);\ + if (_ret != SC_ERR_NONE) \ + printf("(%d)>> sc_pm_set_clock_parent failed! %s:%s -> %d (error = %d)\n",\ + __LINE__, _res_str, _clk_str, __parent__, _ret);\ +} while (0) + +#define SC_PM_SET_CLOCK_RATE(__ipcHndl__, __res__, __clk__, __rate__) \ +do { \ + char _res_str[] = #__res__;\ + char _clk_str[] = #__clk__;\ + sc_err_t _ret;\ + sc_pm_clock_rate_t _actual = __rate__;\ + if (g_debug_scfw) \ + printf("(%4d) sc_pm_set_clock_rate %s:%s -> %d\n",\ + __LINE__, _res_str, _clk_str, __rate__);\ + _ret = sc_pm_set_clock_rate(__ipcHndl__, __res__, __clk__, &_actual);\ + if (_ret != SC_ERR_NONE)\ + printf("(%4d)>> sc_pm_set_clock_rate failed! %s:%s -> %d (error = %d)\n",\ + __LINE__, _res_str, _clk_str, __rate__, _ret);\ + if (_actual != __rate__)\ + printf("(%4d)>> Actual rate for %s:%s is %d instead of %d\n", \ + __LINE__, _res_str, _clk_str, _actual, __rate__); \ +} while (0) + +#define SC_PM_CLOCK_ENABLE(__ipcHndl__, __res__, __clk__, __enable__) \ +do { \ + char _res_str[] = #__res__;\ + char _clk_str[] = #__clk__;\ + sc_err_t _ret;\ + if (g_debug_scfw) \ + printf("(%4d) sc_pm_clock_enable %s:%s -> %d\n",\ + __LINE__, _res_str, _clk_str, __enable__);\ + _ret = sc_pm_clock_enable(ipcHndl,\ + __res__, __clk__, __enable__, false);\ + if (_ret != SC_ERR_NONE)\ + printf("(%4d)>> sc_pm_clock_enable failed! %s:%s -> %d (error = %d)\n",\ + __LINE__, _res_str, _clk_str, __enable__, _ret);\ +} while (0) \ + +#define SC_MISC_SET_CONTROL(__ipcHndl__, __res__, __clk__, __value__) \ +do { \ + char _res_str[] = #__res__; \ + char _clk_str[] = #__clk__; \ + sc_err_t _ret; \ + if (g_debug_scfw) \ + printf("(%4d) sc_misc_set_control %s:%s -> %d\n",\ + __LINE__, _res_str, _clk_str, __value__);\ + _ret = sc_misc_set_control(ipcHndl, \ + __res__, __clk__, __value__); \ + if (_ret != SC_ERR_NONE) \ + printf("(%4d)>> sc_misc_set_control failed! %s:%s -> %d (error = %d)\n", \ + __LINE__, _res_str, _clk_str, __value__, _ret); \ +} while (0) + +#define SC_PM_SET_RESOURCE_POWER_MODE(__ipcHndl__, __res__, __enable__) \ +do { \ + char _res_str[] = #__res__; \ + sc_err_t _ret; \ + if (g_debug_scfw) \ + printf("(%4d) sc_pm_set_resource_power_mode %s -> %d\n",\ + __LINE__, _res_str, __enable__);\ + _ret = sc_pm_set_resource_power_mode(ipcHndl, __res__, __enable__);\ + if (_ret != SC_ERR_NONE) \ + printf("(%4d)>> sc_pm_set_resource_power_mode failed! %s -> %d (error = %d)\n", \ + __LINE__, _res_str, __enable__, _ret);\ +} while (0) + +#endif /*_SCFW_UTILS_H_ */ From 770c6784a4995a9637adce6f700d783acad25ec0 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Wed, 20 Dec 2017 03:42:55 -0600 Subject: [PATCH 08/62] MLK-17262 video: Fix build break when CONFIG_VIDEO_IMX_HDP_LOAD is not selected Met build errors below when CONFIG_VIDEO_IMX_HDP_LOAD is not selected. Because the u-boot make script checks the "$(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)" for built-in target. aarch64-poky-linux-ld.bfd: cannot find drivers/video/imx/built-in.o: No such file or directory scripts/Makefile.build:359: recipe for target 'drivers/video/built-in.o' failed Signed-off-by: Ye Li Reviewed-by: Peng Fan --- drivers/video/imx/Makefile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/video/imx/Makefile b/drivers/video/imx/Makefile index 1d688c701f47..0ec6e0ea680b 100644 --- a/drivers/video/imx/Makefile +++ b/drivers/video/imx/Makefile @@ -1,7 +1,8 @@ -ifdef CONFIG_VIDEO_IMX_HDP_LOAD +# +# Copyright 2017 NXP +# +# SPDX-License-Identifier: GPL-2.0+ +# UBOOTINCLUDE += -I$(srctree)/drivers/video/imx/hdp -obj-y += hdpload.o -obj-y += hdp/ - -endif +obj-$(CONFIG_VIDEO_IMX_HDP_LOAD) += hdpload.o hdp/ From 8c32dd4b851b7c7239ee3cc6d6c10ccf04caa504 Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Mon, 15 Jan 2018 15:25:55 -0600 Subject: [PATCH 09/62] MLK-17375 video: imx: hdp: fix "n" arg for strncmp call Renaming hdpload to hdp_load for consistancy. Correcting the strncmp to use only 4 characters to match "load" argument Signed-off-by: Oliver Brown --- drivers/video/imx/Makefile | 2 +- drivers/video/imx/{hdpload.c => hdp_load.c} | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) rename drivers/video/imx/{hdpload.c => hdp_load.c} (97%) diff --git a/drivers/video/imx/Makefile b/drivers/video/imx/Makefile index 0ec6e0ea680b..93d6deba1a40 100644 --- a/drivers/video/imx/Makefile +++ b/drivers/video/imx/Makefile @@ -5,4 +5,4 @@ # UBOOTINCLUDE += -I$(srctree)/drivers/video/imx/hdp -obj-$(CONFIG_VIDEO_IMX_HDP_LOAD) += hdpload.o hdp/ +obj-$(CONFIG_VIDEO_IMX_HDP_LOAD) += hdp_load.o hdp/ diff --git a/drivers/video/imx/hdpload.c b/drivers/video/imx/hdp_load.c similarity index 97% rename from drivers/video/imx/hdpload.c rename to drivers/video/imx/hdp_load.c index 0ffc960a6daf..66eb3e93856f 100644 --- a/drivers/video/imx/hdpload.c +++ b/drivers/video/imx/hdp_load.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -62,7 +62,7 @@ int do_hdp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) if (strncmp(argv[1], "tracescfw", 9) == 0) { g_debug_scfw = 1; printf("Enabled SCFW API tracing\n"); - } else if (strncmp(argv[1], "load", 7) == 0) { + } else if (strncmp(argv[1], "load", 4) == 0) { unsigned long address = 0; unsigned long offset = 0x2000; const int iram_size = 0x10000; From 0ad26a6f9d37fb2523d5908550d445c021bd424c Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Mon, 29 Jan 2018 14:05:05 -0600 Subject: [PATCH 10/62] MLK-17404-1 video: imx: hdp: Adding support for HDMI splash screen Adding HDMI support for splash screen. Signed-off-by: Oliver Brown --- drivers/video/imx/Makefile | 3 +- drivers/video/imx/hdp.c | 46 + drivers/video/imx/hdp/API_AFE.c | 115 + drivers/video/imx/hdp/API_AFE.h | 98 + drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.c | 1863 +++++++++++++++++ drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.h | 64 + drivers/video/imx/hdp/API_AVI.c | 191 ++ drivers/video/imx/hdp/API_AVI.h | 58 + drivers/video/imx/hdp/API_General.c | 2 +- drivers/video/imx/hdp/API_General.h | 2 +- drivers/video/imx/hdp/API_HDMITX.c | 485 +++++ drivers/video/imx/hdp/API_HDMITX.h | 181 ++ drivers/video/imx/hdp/API_Infoframe.c | 156 ++ drivers/video/imx/hdp/API_Infoframe.h | 67 + drivers/video/imx/hdp/Makefile | 50 +- drivers/video/imx/hdp/apb_cfg.h | 2 +- drivers/video/imx/hdp/avgen.h | 252 +++ drivers/video/imx/hdp/avgen_drv.c | 305 +++ drivers/video/imx/hdp/avgen_drv.h | 68 + drivers/video/imx/hdp/defs.h | 56 + drivers/video/imx/hdp/edid_parser.c | 617 ++++++ drivers/video/imx/hdp/edid_parser.h | 297 +++ drivers/video/imx/hdp/externs.h | 2 +- drivers/video/imx/hdp/general_handler.h | 3 +- drivers/video/imx/hdp/hdmi.h | 124 ++ drivers/video/imx/hdp/mhl_hdtx_top.h | 220 ++ drivers/video/imx/hdp/opcodes.h | 2 +- drivers/video/imx/hdp/source_car.h | 179 ++ drivers/video/imx/hdp/source_phy.h | 181 ++ drivers/video/imx/hdp/source_pif.h | 174 ++ drivers/video/imx/hdp/source_vif.h | 93 + drivers/video/imx/hdp/test_base_sw.c | 2 +- drivers/video/imx/hdp/util.c | 2 +- drivers/video/imx/hdp/util.h | 3 + drivers/video/imx/hdp/vic_table.c | 68 + drivers/video/imx/hdp/vic_table.h | 140 ++ drivers/video/imx/imx8_hdmi.c | 293 +++ 37 files changed, 6454 insertions(+), 10 deletions(-) create mode 100644 drivers/video/imx/hdp.c create mode 100644 drivers/video/imx/hdp/API_AFE.c create mode 100644 drivers/video/imx/hdp/API_AFE.h create mode 100644 drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.c create mode 100644 drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.h create mode 100644 drivers/video/imx/hdp/API_AVI.c create mode 100644 drivers/video/imx/hdp/API_AVI.h create mode 100644 drivers/video/imx/hdp/API_HDMITX.c create mode 100644 drivers/video/imx/hdp/API_HDMITX.h create mode 100644 drivers/video/imx/hdp/API_Infoframe.c create mode 100644 drivers/video/imx/hdp/API_Infoframe.h create mode 100644 drivers/video/imx/hdp/avgen.h create mode 100644 drivers/video/imx/hdp/avgen_drv.c create mode 100644 drivers/video/imx/hdp/avgen_drv.h create mode 100644 drivers/video/imx/hdp/defs.h create mode 100644 drivers/video/imx/hdp/edid_parser.c create mode 100644 drivers/video/imx/hdp/edid_parser.h create mode 100644 drivers/video/imx/hdp/hdmi.h create mode 100644 drivers/video/imx/hdp/mhl_hdtx_top.h create mode 100644 drivers/video/imx/hdp/source_car.h create mode 100644 drivers/video/imx/hdp/source_phy.h create mode 100644 drivers/video/imx/hdp/source_pif.h create mode 100644 drivers/video/imx/hdp/source_vif.h create mode 100644 drivers/video/imx/hdp/vic_table.c create mode 100644 drivers/video/imx/hdp/vic_table.h create mode 100644 drivers/video/imx/imx8_hdmi.c diff --git a/drivers/video/imx/Makefile b/drivers/video/imx/Makefile index 93d6deba1a40..5c243af8fde6 100644 --- a/drivers/video/imx/Makefile +++ b/drivers/video/imx/Makefile @@ -1,8 +1,9 @@ # -# Copyright 2017 NXP +# Copyright 2017-2018 NXP # # SPDX-License-Identifier: GPL-2.0+ # UBOOTINCLUDE += -I$(srctree)/drivers/video/imx/hdp obj-$(CONFIG_VIDEO_IMX_HDP_LOAD) += hdp_load.o hdp/ +obj-$(CONFIG_VIDEO_IMX8_HDMI) += hdp.o imx8_hdmi.o hdp/ diff --git a/drivers/video/imx/hdp.c b/drivers/video/imx/hdp.c new file mode 100644 index 000000000000..2f946ed2872b --- /dev/null +++ b/drivers/video/imx/hdp.c @@ -0,0 +1,46 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +int do_hdp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + if (argc < 2) + return 0; + + if (strncmp(argv[1], "colorbar", 8) == 0) { + GraphicDevice *gdev; + struct video_mode_settings *vm; + + gdev = imx8m_get_gd(); + vm = imx8m_get_gmode(); + imx8m_show_gmode(); + + imx8m_create_color_bar( + (void *)((uint64_t)gdev->frameAdrs), + vm); + printf("colorbar test\n"); + } else if (strncmp(argv[1], "stop", 4) == 0) { + imx8_hdmi_disable(); + printf("stopping hdmi\n"); + } else { + printf("test error argc %d\n", argc); + } + + return 0; +} +/***************************************************/ + +U_BOOT_CMD( + hdp, CONFIG_SYS_MAXARGS, 1, do_hdp, + "hdmi/dp display test commands", + "[] ...\n" + "colorbar - display a colorbar pattern\n" + ); diff --git a/drivers/video/imx/hdp/API_AFE.c b/drivers/video/imx/hdp/API_AFE.c new file mode 100644 index 000000000000..7b778cd3d586 --- /dev/null +++ b/drivers/video/imx/hdp/API_AFE.c @@ -0,0 +1,115 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_AFE.c + * + ****************************************************************************** + */ + +#include "address.h" +#include "API_AFE.h" +#include "util.h" +#ifndef __UBOOT__ +#include +#endif + +void afe_write(unsigned int offset, unsigned short val) +{ +#ifdef EXTERNAL_AFE + cdn_phapb_write(offset << 2, val); +#else + CDN_API_STATUS sts; + + sts = cdn_api_general_write_register_blocking( + ADDR_AFE + (offset << 2), val); + + if (sts != CDN_OK) { + printf("CDN_API_General_Write_Register_blocking(0x%.8X, 0x%.8X) returned %d\n", + offset, + val, + (int)sts); + } +#endif +} + +unsigned short afe_read(unsigned int offset) +{ + GENERAL_READ_REGISTER_RESPONSE resp; + +#ifdef EXTERNAL_AFE + cdn_phapb_read(offset << 2, &resp.val); +#else + CDN_API_STATUS sts; + + sts = cdn_api_general_read_register_blocking( + ADDR_AFE + (offset << 2), &resp); + + if (sts != CDN_OK) { + printf("CDN_API_General_Read_Register_blocking(0x%.8X) returned %d\n", + offset, + (int)sts); + } +#endif + return resp.val; +} + +void set_field_value(reg_field_t *reg_field, u32 value) +{ + u8 length; + u32 max_value; + u32 trunc_val; + length = (reg_field->msb - reg_field->lsb + 1); + + max_value = (1 << length) - 1; + if (value > max_value) { + trunc_val = value; + trunc_val &= (1 << length) - 1; + printf("set_field_value() Error! Specified value (0x%0X) exceeds field capacity - it will by truncated to 0x%0X (%0d-bit field - max value: %0d dec)\n", + value, trunc_val, length, max_value); + } else { + reg_field->value = value; + } +} + +int set_reg_value(reg_field_t reg_field) +{ + return reg_field.value << reg_field.lsb; +} diff --git a/drivers/video/imx/hdp/API_AFE.h b/drivers/video/imx/hdp/API_AFE.h new file mode 100644 index 000000000000..f3db97368380 --- /dev/null +++ b/drivers/video/imx/hdp/API_AFE.h @@ -0,0 +1,98 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_AFE.h + * + ****************************************************************************** + */ + +#ifndef API_AFE_H_ +#define API_AFE_H_ +#include "util.h" + +typedef enum { + AFE_LINK_RATE_1_6 = 0x6, /* 1.62 Gb/s */ + AFE_LINK_RATE_2_1 = 0x8, /* 2.16 Gb/s */ + AFE_LINK_RATE_2_4 = 0x9, /* 2.43 Gb/s */ + AFE_LINK_RATE_2_7 = 0xA, /* 2.70 Gb/s */ + AFE_LINK_RATE_3_2 = 0xC, /* 3.24 Gb/s */ + AFE_LINK_RATE_4_3 = 0x10, /* 4.32 Gb/s */ + AFE_LINK_RATE_5_4 = 0x14, /* 5.40 Gb/s */ + AFE_LINK_RATE_8_1 = 0x1E, /* 8.10 Gb/s */ +} ENUM_AFE_LINK_RATE; + +/* Some of the PHY programming sequences */ +/* depend on the reference clock frequency. */ +/* Variable of this type is used to control */ +/* the programming flow. */ +typedef enum { + REFCLK_24MHZ, + REFCLK_27MHZ +} REFCLK_FREQ; + +typedef enum { + CLK_RATIO_1_1, + CLK_RATIO_5_4, + CLK_RATIO_3_2, + CLK_RATIO_2_1, + CLK_RATIO_1_2, + CLK_RATIO_5_8, + CLK_RATIO_3_4 +} clk_ratio_t; + +typedef struct { + u32 value; + u8 lsb; + u8 msb; +} reg_field_t; + +unsigned char AFE_check_rate_supported(ENUM_AFE_LINK_RATE rate); +void afe_write(unsigned int offset, unsigned short val); +unsigned short afe_read(unsigned int offset); +void AFE_init(int num_lanes, ENUM_AFE_LINK_RATE link_rate); +void AFE_power(int num_lanes, ENUM_AFE_LINK_RATE link_rate); + +/*extern int cdn_phapb_read(unsigned int addr, unsigned int *value);*/ +/*extern int cdn_phapb_write(unsigned int addr, unsigned int value);*/ +void set_field_value(reg_field_t *reg_field, u32 value); +int set_reg_value(reg_field_t reg_field); + +#endif diff --git a/drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.c b/drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.c new file mode 100644 index 000000000000..933ecfa8d438 --- /dev/null +++ b/drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.c @@ -0,0 +1,1863 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_AFE_t28hpc_hdmitx.c + * + ****************************************************************************** + */ + +#include "API_AFE_t28hpc_hdmitx.h" +#include "API_AFE.h" +#include "externs.h" + +#ifndef DEBUG +static inline void write16(uint32_t addr, uint16_t val) +{ + afe_write(addr, val); +} + +static inline uint16_t read16(uint32_t addr) +{ + return afe_read(addr); +} +#else +#define write16(addr, val) __write16(addr, val, __LINE__) +static inline void __write16(uint32_t addr, uint16_t val, int line) +{ + afe_write(addr, val); + debug("write16():%4d Writting value 0x%04X at address 0x%05X (0x%04X)\n", + line, val, (0x20000 * 4) + (addr << 2), addr); +} +#define read16(addr) __read16(addr, __LINE__) +static inline uint16_t __read16(uint32_t addr, int line) +{ + debug("read16():%5d Reading from address 0x%05X (0x%04X)\n", + line, (0x20000 * 4) + (addr << 2), addr); + return afe_read(addr); +} + +#endif + +static char inside(u32 value, u32 left_sharp_corner, + u32 right_sharp_corner) +{ + if (value < left_sharp_corner) + return false; + if (value > right_sharp_corner) + return false; + return true; +} + +void aux_cfg_t28hpc(void) +{ + write16(0x5025, 0x0001); + + write16(0x5024, 36); + + write16(0x5021, 0x0100); + write16(0x5021, 0x0300); + write16(0x5026, 0x0000); + write16(0x5020, 0x2008); + write16(0x5020, 0x2018); + write16(0x5020, 0xA018); + write16(0x5021, 0x030C); + write16(0x5029, 0x0000); + write16(0x5027, 0x4001); + write16(0x5020, 0xA098); + write16(0x5020, 0xA198); + write16(0x5021, 0x030D); + write16(0x5021, 0x030F); +} + +int phy_cfg_t28hpc(int num_lanes, VIC_MODES vic_mode, int bpp, + VIC_PXL_ENCODING_FORMAT format, bool pixel_clk_from_phy) +{ + const int phy_reset_workaround = 1; + unsigned int vco_freq; + unsigned char k; + uint32_t reg_val; + uint32_t pixel_freq_khz = vic_table[vic_mode][PIXEL_FREQ_KHZ]; + uint32_t character_clock_ratio_num = 1; + uint32_t character_clock_ratio_den = 1; + uint32_t character_freq_khz; + const unsigned int refclk_freq_khz = 27000; + unsigned int ftemp, ftemp2; + + clk_ratio_t clk_ratio = 0; + reg_field_t cmnda_pll0_hs_sym_div_sel; + reg_field_t cmnda_pll0_ip_div; + reg_field_t cmnda_pll0_fb_div_low; + reg_field_t cmnda_pll0_fb_div_high; + reg_field_t cmn_ref_clk_dig_div; + reg_field_t divider_scaler; + reg_field_t cmnda_hs_clk_0_sel; + reg_field_t cmnda_hs_clk_1_sel; + reg_field_t tx_subrate; + reg_field_t voltage_to_current_coarse; + reg_field_t voltage_to_current; + reg_field_t ndac_ctrl; + reg_field_t pmos_ctrl; + reg_field_t ptat_ndac_ctrl; + reg_field_t charge_pump_gain; + reg_field_t vco_ring_select; + reg_field_t pll_feedback_divider_total; + reg_field_t cmnda_pll0_pxdiv_high; + reg_field_t cmnda_pll0_pxdiv_low; + reg_field_t coarse_code; + reg_field_t v2i_code; + reg_field_t vco_cal_code; + + cmnda_pll0_fb_div_high.value = 0x00A; + ftemp = pixel_freq_khz; + + debug(" VIC %d, pixel clock %u kHz\n", vic_mode, ftemp); + + /* Set field position */ + cmnda_pll0_hs_sym_div_sel.msb = 9; + cmnda_pll0_hs_sym_div_sel.lsb = 8; + cmnda_pll0_ip_div.msb = 7; + cmnda_pll0_ip_div.lsb = 0; + cmnda_pll0_fb_div_low.msb = 9; + cmnda_pll0_fb_div_low.lsb = 0; + cmnda_pll0_fb_div_high.msb = 9; + cmnda_pll0_fb_div_high.lsb = 0; + cmn_ref_clk_dig_div.msb = 13; + cmn_ref_clk_dig_div.lsb = 12; + divider_scaler.msb = 14; + divider_scaler.lsb = 12; + cmnda_hs_clk_0_sel.msb = 1; + cmnda_hs_clk_0_sel.lsb = 0; + cmnda_hs_clk_1_sel.msb = 1; + cmnda_hs_clk_1_sel.lsb = 0; + tx_subrate.msb = 2; + tx_subrate.lsb = 0; + voltage_to_current_coarse.msb = 2; + voltage_to_current_coarse.lsb = 0; + voltage_to_current.msb = 5; + voltage_to_current.lsb = 4; + ndac_ctrl.msb = 11; + ndac_ctrl.lsb = 8; + pmos_ctrl.msb = 7; + pmos_ctrl.lsb = 0; + ptat_ndac_ctrl.msb = 5; + ptat_ndac_ctrl.lsb = 0; + charge_pump_gain.msb = 8; + charge_pump_gain.lsb = 0; + vco_ring_select.msb = 12; + vco_ring_select.lsb = 12; + pll_feedback_divider_total.msb = 9; + pll_feedback_divider_total.lsb = 0; + cmnda_pll0_pxdiv_high.msb = 9; + cmnda_pll0_pxdiv_high.lsb = 0; + cmnda_pll0_pxdiv_low.msb = 9; + cmnda_pll0_pxdiv_low.lsb = 0; + coarse_code.msb = 7; + coarse_code.lsb = 0; + v2i_code.msb = 3; + v2i_code.lsb = 0; + vco_cal_code.msb = 8; + vco_cal_code.lsb = 0; + + if (phy_reset_workaround) { + /* register PHY_PMA_ISOLATION_CTRL */ + write16(0xC81F, 0xD000); /* enable PHY iso mode only for CMN */ + /* register PHY_PMA_ISO_PLL_CTRL1 */ + reg_val = read16(0xC812); + reg_val &= 0xFF00; + reg_val |= 0x0012; + /* set pll0_clk_datart1_div/pll0_clk_datart0_div dividers */ + write16(0xC812, reg_val); + /* register PHY_ISO_CMN_CTRL */ + /* assert PHY reset from isolation register */ + write16(0xC010, 0x0000); + /* register PHY_PMA_ISO_CMN_CTRL */ + write16(0xC810, 0x0000); /* assert PMA CMN reset */ + /* register XCVR_DIAG_BIDI_CTRL */ + for (k = 0; k < num_lanes; k++) + write16(0x40E8 | (k << 9), 0x00FF); + } + /*--------------------------------------------------------------- + * Describing Task phy_cfg_hdp + * --------------------------------------------------------------*/ + /* register PHY_PMA_CMN_CTRL1 */ + reg_val = read16(0xC800); + reg_val &= 0xFFF7; + reg_val |= 0x0008; + write16(0xC800, reg_val); + + /* register CMN_DIAG_PLL0_TEST_MODE */ + write16(0x01C4, 0x0020); + /* register CMN_PSM_CLK_CTRL */ + write16(0x0061, 0x0016); + + switch (format) { + case YCBCR_4_2_2: + clk_ratio = CLK_RATIO_1_1; + character_clock_ratio_num = 1; + character_clock_ratio_den = 1; + break; + case YCBCR_4_2_0: + switch (bpp) { + case 8: + clk_ratio = CLK_RATIO_1_2; + character_clock_ratio_num = 1; + character_clock_ratio_den = 2; + break; + case 10: + clk_ratio = CLK_RATIO_5_8; + character_clock_ratio_num = 5; + character_clock_ratio_den = 8; + break; + case 12: + clk_ratio = CLK_RATIO_3_4; + character_clock_ratio_num = 3; + character_clock_ratio_den = 4; + break; + case 16: + clk_ratio = CLK_RATIO_1_1; + character_clock_ratio_num = 1; + character_clock_ratio_den = 1; + break; + default: + debug("Invalid ColorDepth\n"); + } + break; + + default: + switch (bpp) { + /* Assume RGB */ + case 10: + clk_ratio = CLK_RATIO_5_4; + character_clock_ratio_num = 5; + character_clock_ratio_den = 4; + break; + case 12: + clk_ratio = CLK_RATIO_3_2; + character_clock_ratio_num = 3; + character_clock_ratio_den = 2; + break; + case 16: + clk_ratio = CLK_RATIO_2_1; + character_clock_ratio_num = 2; + character_clock_ratio_den = 1; + break; + default: + clk_ratio = CLK_RATIO_1_1; + character_clock_ratio_num = 1; + character_clock_ratio_den = 1; + } + } + + character_freq_khz = pixel_freq_khz * + character_clock_ratio_num / character_clock_ratio_den; + ftemp = pixel_freq_khz; + ftemp2 = character_freq_khz; + debug("Pixel clock frequency: %u kHz, character clock frequency: %u, color depth is %0d-bit.\n", + ftemp, ftemp2, bpp); + if (pixel_clk_from_phy == 0) { + /* ----------------------------------------------------------- + * Describing Task phy_cfg_hdmi_pll0_0pt5736 (Clock is input) + * -----------------------------------------------------------*/ + + /* register CMN_PLL0_VCOCAL_INIT_TMR */ + write16(0x0084, 0x0064); + /* register CMN_PLL0_VCOCAL_ITER_TMR */ + write16(0x0085, 0x000A); + /* register PHY_HDP_CLK_CTL */ + reg_val = read16(0xC009); + reg_val &= 0x00FF; + reg_val |= 0x1200; + write16(0xC009, reg_val); + + switch (clk_ratio) { + case CLK_RATIO_1_1: + if (inside(pixel_freq_khz, 340000, 600000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x3C); + set_field_value(&cmnda_pll0_fb_div_low, 0x24A); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x06); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 600); + } else if (inside(pixel_freq_khz, 170000, 340000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x22); + set_field_value(&cmnda_pll0_fb_div_low, 0x146); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x07); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 340); + } else if (inside(pixel_freq_khz, 85000, 170000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + set_field_value(&cmnda_pll0_ip_div, 0x11); + set_field_value(&cmnda_pll0_fb_div_low, 0x146); + set_field_value(&cmn_ref_clk_dig_div, 0x00); + set_field_value(÷r_scaler, 0x07); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 340); + } else if (inside(pixel_freq_khz, 42500, 85000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + set_field_value(&cmnda_pll0_ip_div, 0x08); + set_field_value(&cmnda_pll0_fb_div_low, 0x132); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 320); + } else if (inside(pixel_freq_khz, 25000, 42500)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + set_field_value(&cmnda_pll0_ip_div, 0x05); + set_field_value(&cmnda_pll0_fb_div_low, 0x182); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 400); + } else { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } + break; + + case CLK_RATIO_5_4: + if (inside(pixel_freq_khz, 272000, 480000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x30); + set_field_value(&cmnda_pll0_fb_div_low, 0x24A); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x05); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 600); + } else if (inside(pixel_freq_khz, 136000, 272000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x1A); + set_field_value(&cmnda_pll0_fb_div_low, 0x137); + set_field_value(&cmn_ref_clk_dig_div, 0x02); + set_field_value(÷r_scaler, 0x04); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 325); + } else if (inside(pixel_freq_khz, 68000, 136000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + set_field_value(&cmnda_pll0_ip_div, 0x0D); + set_field_value(&cmnda_pll0_fb_div_low, 0x137); + set_field_value(&cmn_ref_clk_dig_div, 0x02); + set_field_value(÷r_scaler, 0x02); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 325); + } else if (inside(pixel_freq_khz, 34000, 68000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + set_field_value(&cmnda_pll0_ip_div, 0x06); + set_field_value(&cmnda_pll0_fb_div_low, 0x11E); + set_field_value(&cmn_ref_clk_dig_div, 0x02); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 300); + } else if (inside(pixel_freq_khz, 25000, 34000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmnda_pll0_fb_div_low, 0x182); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 400); + } else { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } + break; + case CLK_RATIO_3_2: + if (inside(pixel_freq_khz, 226000, 400000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x28); + set_field_value(&cmnda_pll0_fb_div_low, 0x24A); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x04); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 600); + } else if (inside(pixel_freq_khz, 113000, 226000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x16); + set_field_value(&cmnda_pll0_fb_div_low, 0x13C); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x05); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 330); + } else if (inside(pixel_freq_khz, 56000, 113000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + set_field_value(&cmnda_pll0_ip_div, 0x0B); + set_field_value(&cmnda_pll0_fb_div_low, 0x13C); + set_field_value(&cmn_ref_clk_dig_div, 0x00); + set_field_value(÷r_scaler, 0x05); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 330); + } else if (inside(pixel_freq_khz, 28000, 56000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + set_field_value(&cmnda_pll0_ip_div, 0x06); + set_field_value(&cmnda_pll0_fb_div_low, 0x15A); + set_field_value(&cmn_ref_clk_dig_div, 0x02); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 360); + } else if (inside(pixel_freq_khz, 25000, 28000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmnda_pll0_fb_div_low, 0x15A); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 360); + } else { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } + break; + case CLK_RATIO_2_1: + if (inside(pixel_freq_khz, 170000, 300000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x22); + set_field_value(&cmnda_pll0_fb_div_low, 0x29A); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x06); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 680); + } else if (inside(pixel_freq_khz, 85000, 170000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x11); + set_field_value(&cmnda_pll0_fb_div_low, 0x146); + set_field_value(&cmn_ref_clk_dig_div, 0x00); + set_field_value(÷r_scaler, 0x07); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 340); + } else if (inside(pixel_freq_khz, 42500, 85000)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + set_field_value(&cmnda_pll0_ip_div, 0x08); + set_field_value(&cmnda_pll0_fb_div_low, 0x132); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 320); + } else if (inside(pixel_freq_khz, 25000, 42500)) { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + set_field_value(&cmnda_pll0_ip_div, 0x05); + set_field_value(&cmnda_pll0_fb_div_low, 0x182); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x04); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&pll_feedback_divider_total, + 400); + } else { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } + break; + case CLK_RATIO_1_2: + if (!(inside(pixel_freq_khz, 594000, 594000))) { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } else { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + set_field_value(&cmnda_pll0_ip_div, 0x3C); + set_field_value(&cmnda_pll0_fb_div_low, 0x24A); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x06); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 600); + } + break; + case CLK_RATIO_5_8: + if (!(inside(pixel_freq_khz, 594000, 594000))) { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } else { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x3C); + set_field_value(&cmnda_pll0_fb_div_low, 0x169); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x06); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 375); + } + break; + case CLK_RATIO_3_4: + if (!(inside(pixel_freq_khz, 594000, 594000))) { + ftemp = pixel_freq_khz; + debug("Pixel clock frequency (%u) is outside of the supported range\n", + ftemp); + } else { + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + set_field_value(&cmnda_pll0_ip_div, 0x3C); + set_field_value(&cmnda_pll0_fb_div_low, 0x1B4); + set_field_value(&cmn_ref_clk_dig_div, 0x03); + set_field_value(÷r_scaler, 0x06); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&pll_feedback_divider_total, + 450); + } + break; + } + vco_freq = + pixel_freq_khz * pll_feedback_divider_total.value / + cmnda_pll0_ip_div.value; + ftemp = vco_freq; + debug("VCO frequency is %u kHz\n", ftemp); + + if (inside(vco_freq, 1700000, 2000000)) { + set_field_value(&voltage_to_current_coarse, 0x04); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x09); + set_field_value(&ptat_ndac_ctrl, 0x09); + switch (pll_feedback_divider_total.value) { + case 300: + set_field_value(&charge_pump_gain, 0x82); + break; + case 320: + set_field_value(&charge_pump_gain, 0x83); + break; + case 325: + set_field_value(&charge_pump_gain, 0x83); + break; + case 330: + set_field_value(&charge_pump_gain, 0x84); + break; + case 340: + set_field_value(&charge_pump_gain, 0x84); + break; + case 360: + set_field_value(&charge_pump_gain, 0x86); + break; + case 400: + set_field_value(&charge_pump_gain, 0xA2); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 2000000, 2400000)) { + set_field_value(&voltage_to_current_coarse, 0x04); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x09); + set_field_value(&ptat_ndac_ctrl, 0x09); + switch (pll_feedback_divider_total.value) { + case 300: + set_field_value(&charge_pump_gain, 0x47); + break; + case 320: + set_field_value(&charge_pump_gain, 0x4B); + break; + case 325: + set_field_value(&charge_pump_gain, 0x4C); + break; + case 330: + set_field_value(&charge_pump_gain, 0x80); + break; + case 340: + set_field_value(&charge_pump_gain, 0x81); + break; + case 360: + set_field_value(&charge_pump_gain, 0x82); + break; + case 400: + set_field_value(&charge_pump_gain, 0x84); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 2400000, 2800000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + switch (pll_feedback_divider_total.value) { + case 300: + set_field_value(&charge_pump_gain, 0x43); + break; + case 320: + set_field_value(&charge_pump_gain, 0x45); + break; + case 325: + set_field_value(&charge_pump_gain, 0x45); + break; + case 330: + set_field_value(&charge_pump_gain, 0x45); + break; + case 340: + set_field_value(&charge_pump_gain, 0x86); + break; + case 360: + set_field_value(&charge_pump_gain, 0x4A); + break; + case 400: + set_field_value(&charge_pump_gain, 0x81); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 2800000, 3400000)) { + set_field_value(&voltage_to_current_coarse, 0x06); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + switch (pll_feedback_divider_total.value) { + case 300: + set_field_value(&charge_pump_gain, 0x3D); + break; + case 320: + set_field_value(&charge_pump_gain, 0x41); + break; + case 325: + set_field_value(&charge_pump_gain, 0x41); + break; + case 330: + set_field_value(&charge_pump_gain, 0x41); + break; + case 340: + set_field_value(&charge_pump_gain, 0x42); + break; + case 360: + set_field_value(&charge_pump_gain, 0x43); + break; + case 400: + set_field_value(&charge_pump_gain, 0x46); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 3400000, 3900000)) { + set_field_value(&voltage_to_current_coarse, 0x04); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x07); + set_field_value(&ptat_ndac_ctrl, 0x0F); + switch (pll_feedback_divider_total.value) { + case 375: + set_field_value(&charge_pump_gain, 0x41); + break; + case 600: + set_field_value(&charge_pump_gain, 0x82); + break; + case 680: + set_field_value(&charge_pump_gain, 0x85); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 3900000, 4500000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x07); + set_field_value(&ptat_ndac_ctrl, 0x0F); + switch (pll_feedback_divider_total.value) { + case 450: + set_field_value(&charge_pump_gain, 0x41); + break; + case 600: + set_field_value(&charge_pump_gain, 0x4B); + break; + case 680: + set_field_value(&charge_pump_gain, 0x82); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 4500000, 5200000)) { + set_field_value(&voltage_to_current_coarse, 0x06); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + switch (pll_feedback_divider_total.value) { + case 600: + set_field_value(&charge_pump_gain, 0x45); + break; + case 680: + set_field_value(&charge_pump_gain, 0x4A); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else if (inside(vco_freq, 5200000, 6000000)) { + set_field_value(&voltage_to_current_coarse, 0x07); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + switch (pll_feedback_divider_total.value) { + case 600: + set_field_value(&charge_pump_gain, 0x42); + break; + case 680: + set_field_value(&charge_pump_gain, 0x45); + break; + default: + debug("pll_feedback_divider_total (%0d) is outside of the supported range for vco_freq equal %u\n", + pll_feedback_divider_total.value, ftemp); + } + } else + debug("VCO frequency %u kHz is outside of the supported range\n", + ftemp); + + /* register CMN_DIAG_PLL0_INCLK_CTRL */ + reg_val = set_reg_value(cmnda_pll0_hs_sym_div_sel); + reg_val |= set_reg_value(cmnda_pll0_ip_div); + write16(0x01CA, reg_val); + /* register CMN_DIAG_PLL0_FBL_OVRD */ + reg_val = set_reg_value(cmnda_pll0_fb_div_low); + reg_val |= (1 << 15); + write16(0x01C1, reg_val); + /* register PHY_PMA_CMN_CTRL1 */ + reg_val = read16(0xC800); + reg_val &= 0xCFFF; + reg_val |= set_reg_value(cmn_ref_clk_dig_div); + write16(0xC800, reg_val); + /* register CMN_CDIAG_REFCLK_CTRL */ + reg_val = read16(0x0062); + reg_val &= 0x8FFF; + reg_val |= set_reg_value(divider_scaler); + reg_val |= 0x00C0; + write16(0x0062, reg_val); + /* register CMN_DIAG_HSCLK_SEL */ + reg_val = read16(0x01E0); + reg_val &= 0xFF00; + reg_val |= (cmnda_hs_clk_0_sel.value >> 1) << 0; + reg_val |= (cmnda_hs_clk_1_sel.value >> 1) << 4; + write16(0x01E0, reg_val); + + /* register XCVR_DIAG_HSCLK_SEL */ + for (k = 0; k < num_lanes; k++) { + reg_val = read16(0x40E1 | (k << 9)); + reg_val &= 0xCFFF; + reg_val |= (cmnda_hs_clk_0_sel.value >> 1) << 12; + write16(0x40E1 | (k << 9), reg_val); + } + + /* register TX_DIAG_TX_CTRL */ + for (k = 0; k < num_lanes; k++) { + reg_val = read16(0x41E0 | (k << 9)); + reg_val &= 0xFF3F; + reg_val |= (tx_subrate.value >> 1) << 6; + write16(0x41E0 | (k << 9), reg_val); + } + + /* register CMN_PLLSM0_USER_DEF_CTRL */ + reg_val = set_reg_value(vco_ring_select); + write16(0x002F, reg_val); + /* register CMN_DIAG_PLL0_OVRD */ + write16(0x01C2, 0x0000); + /* register CMN_DIAG_PLL0_FBH_OVRD */ + reg_val = set_reg_value(cmnda_pll0_fb_div_high); + reg_val |= (1 << 15); + write16(0x01C0, reg_val); + /* register CMN_DIAG_PLL0_V2I_TUNE */ + reg_val = set_reg_value(voltage_to_current_coarse); + reg_val |= set_reg_value(voltage_to_current); + write16(0x01C5, reg_val); + /* register CMN_DIAG_PLL0_PTATIS_TUNE1 */ + reg_val = set_reg_value(pmos_ctrl); + reg_val |= set_reg_value(ndac_ctrl); + write16(0x01C8, reg_val); + /* register CMN_DIAG_PLL0_PTATIS_TUNE2 */ + reg_val = set_reg_value(ptat_ndac_ctrl); + write16(0x01C9, reg_val); + /* register CMN_DIAG_PLL0_CP_TUNE */ + reg_val = set_reg_value(charge_pump_gain); + write16(0x01C6, reg_val); + /* register CMN_DIAG_PLL0_LF_PROG */ + write16(0x01C7, 0x0008); + + /* register XCVR_DIAG_PLLDRC_CTRL */ + for (k = 0; k < num_lanes; k++) { + reg_val = read16(0x40E0 | (k << 9)); + reg_val &= 0xBFFF; + write16(0x40E0 | (k << 9), reg_val); + } + + } else { + /* Describing task phy_cfg_hdmi_pll0_0pt099_ver2 + (Clock is OUTPUT) */ + if (inside(pixel_freq_khz, 27000, 27000)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 240); + set_field_value(&cmnda_pll0_fb_div_low, 0xBC); + set_field_value(&cmnda_pll0_fb_div_high, 0x30); + set_field_value(&cmnda_pll0_pxdiv_low, 0x26); + set_field_value(&cmnda_pll0_pxdiv_high, 0x26); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + break; + case CLK_RATIO_5_4: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 300); + set_field_value(&cmnda_pll0_fb_div_low, 0x0EC); + set_field_value(&cmnda_pll0_fb_div_high, 0x03C); + set_field_value(&cmnda_pll0_pxdiv_low, 0x030); + set_field_value(&cmnda_pll0_pxdiv_high, 0x030); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 360); + set_field_value(&cmnda_pll0_fb_div_low, 0x11C); + set_field_value(&cmnda_pll0_fb_div_high, 0x048); + set_field_value(&cmnda_pll0_pxdiv_low, 0x03A); + set_field_value(&cmnda_pll0_pxdiv_high, 0x03A); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 240); + set_field_value(&cmnda_pll0_fb_div_low, 0x0BC); + set_field_value(&cmnda_pll0_fb_div_high, 0x030); + set_field_value(&cmnda_pll0_pxdiv_low, 0x026); + set_field_value(&cmnda_pll0_pxdiv_high, 0x026); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + default: + break; + } + } else if (inside(pixel_freq_khz, 54000, 54000)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 480); + set_field_value(&cmnda_pll0_fb_div_low, 0x17C); + set_field_value(&cmnda_pll0_fb_div_high, 0x060); + set_field_value(&cmnda_pll0_pxdiv_low, 0x026); + set_field_value(&cmnda_pll0_pxdiv_high, 0x026); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + break; + case CLK_RATIO_5_4: + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 400); + set_field_value(&cmnda_pll0_fb_div_low, 0x13C); + set_field_value(&cmnda_pll0_fb_div_high, 0x050); + set_field_value(&cmnda_pll0_pxdiv_low, 0x017); + set_field_value(&cmnda_pll0_pxdiv_high, 0x017); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 480); + set_field_value(&cmnda_pll0_fb_div_low, 0x17C); + set_field_value(&cmnda_pll0_fb_div_high, 0x060); + set_field_value(&cmnda_pll0_pxdiv_low, 0x01C); + set_field_value(&cmnda_pll0_pxdiv_high, 0x01C); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 240); + set_field_value(&cmnda_pll0_fb_div_low, 0x0bc); + set_field_value(&cmnda_pll0_fb_div_high, 0x030); + set_field_value(&cmnda_pll0_pxdiv_low, 0x012); + set_field_value(&cmnda_pll0_pxdiv_high, 0x012); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + default: + break; + } + } else if (inside(pixel_freq_khz, 74250, 74250)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x026); + set_field_value(&cmnda_pll0_pxdiv_high, 0x026); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x03); + break; + case CLK_RATIO_5_4: + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 550); + set_field_value(&cmnda_pll0_fb_div_low, 0x1b4); + set_field_value(&cmnda_pll0_fb_div_high, 0x06e); + set_field_value(&cmnda_pll0_pxdiv_low, 0x017); + set_field_value(&cmnda_pll0_pxdiv_high, 0x017); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x04); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x01c); + set_field_value(&cmnda_pll0_pxdiv_high, 0x01c); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 330); + set_field_value(&cmnda_pll0_fb_div_low, 0x104); + set_field_value(&cmnda_pll0_fb_div_high, 0x042); + set_field_value(&cmnda_pll0_pxdiv_low, 0x012); + set_field_value(&cmnda_pll0_pxdiv_high, 0x012); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + default: + break; + } + } else if (inside(pixel_freq_khz, 99000, 99000)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 440); + set_field_value(&cmnda_pll0_fb_div_low, 0x15c); + set_field_value(&cmnda_pll0_fb_div_high, 0x058); + set_field_value(&cmnda_pll0_pxdiv_low, 0x012); + set_field_value(&cmnda_pll0_pxdiv_high, 0x012); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + case CLK_RATIO_5_4: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 275); + set_field_value(&cmnda_pll0_fb_div_low, 0x0d8); + set_field_value(&cmnda_pll0_fb_div_high, 0x037); + set_field_value(&cmnda_pll0_pxdiv_low, 0x00b); + set_field_value(&cmnda_pll0_pxdiv_high, 0x00a); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 330); + set_field_value(&cmnda_pll0_fb_div_low, 0x104); + set_field_value(&cmnda_pll0_fb_div_high, 0x042); + set_field_value(&cmnda_pll0_pxdiv_low, 0x00d); + set_field_value(&cmnda_pll0_pxdiv_high, 0x00d); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 440); + set_field_value(&cmnda_pll0_fb_div_low, 0x15c); + set_field_value(&cmnda_pll0_fb_div_high, 0x058); + set_field_value(&cmnda_pll0_pxdiv_low, 0x012); + set_field_value(&cmnda_pll0_pxdiv_high, 0x012); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + default: + break; + } + } else if (inside(pixel_freq_khz, 148500, 148500)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x012); + set_field_value(&cmnda_pll0_pxdiv_high, 0x012); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x02); + break; + case CLK_RATIO_5_4: + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 550); + set_field_value(&cmnda_pll0_fb_div_low, 0x1b4); + set_field_value(&cmnda_pll0_fb_div_high, 0x06e); + set_field_value(&cmnda_pll0_pxdiv_low, 0x00b); + set_field_value(&cmnda_pll0_pxdiv_high, 0x00a); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 495); + set_field_value(&cmnda_pll0_fb_div_low, 0x188); + set_field_value(&cmnda_pll0_fb_div_high, 0x063); + set_field_value(&cmnda_pll0_pxdiv_low, 0x00d); + set_field_value(&cmnda_pll0_pxdiv_high, 0x00d); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x012); + set_field_value(&cmnda_pll0_pxdiv_high, 0x012); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x02); + set_field_value(&cmnda_hs_clk_1_sel, 0x02); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + default: + break; + } + } else if (inside(pixel_freq_khz, 198000, 198000)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 220); + set_field_value(&cmnda_pll0_fb_div_low, 0x0ac); + set_field_value(&cmnda_pll0_fb_div_high, 0x02c); + set_field_value(&cmnda_pll0_pxdiv_low, 0x003); + set_field_value(&cmnda_pll0_pxdiv_high, 0x003); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + case CLK_RATIO_5_4: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 550); + set_field_value(&cmnda_pll0_fb_div_low, 0x1b4); + set_field_value(&cmnda_pll0_fb_div_high, 0x06e); + set_field_value(&cmnda_pll0_pxdiv_low, 0x00b); + set_field_value(&cmnda_pll0_pxdiv_high, 0x00a); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 330); + set_field_value(&cmnda_pll0_fb_div_low, 0x104); + set_field_value(&cmnda_pll0_fb_div_high, 0x042); + set_field_value(&cmnda_pll0_pxdiv_low, 0x006); + set_field_value(&cmnda_pll0_pxdiv_high, 0x005); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 440); + set_field_value(&cmnda_pll0_fb_div_low, 0x15c); + set_field_value(&cmnda_pll0_fb_div_high, 0x058); + set_field_value(&cmnda_pll0_pxdiv_low, 0x008); + set_field_value(&cmnda_pll0_pxdiv_high, 0x008); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + default: + break; + } + } else if (inside(pixel_freq_khz, 297000, 297000)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 330); + set_field_value(&cmnda_pll0_fb_div_low, 0x104); + set_field_value(&cmnda_pll0_fb_div_high, 0x042); + set_field_value(&cmnda_pll0_pxdiv_low, 0x003); + set_field_value(&cmnda_pll0_pxdiv_high, 0x003); + set_field_value(&vco_ring_select, 0x00); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + case CLK_RATIO_3_2: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 495); + set_field_value(&cmnda_pll0_fb_div_low, 0x188); + set_field_value(&cmnda_pll0_fb_div_high, 0x063); + set_field_value(&cmnda_pll0_pxdiv_low, 0x006); + set_field_value(&cmnda_pll0_pxdiv_high, 0x005); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + case CLK_RATIO_2_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x008); + set_field_value(&cmnda_pll0_pxdiv_high, 0x008); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + default: + ftemp = pixel_freq_khz; + debug("This pixel clock frequency (%u kHz) is not supported with this (%0d-bit) color depth.\n", + ftemp, bpp); + } + } else if (inside(pixel_freq_khz, 594000, 594000)) { + switch (clk_ratio) { + case CLK_RATIO_1_1: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x003); + set_field_value(&cmnda_pll0_pxdiv_high, 0x003); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + case CLK_RATIO_1_2: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 660); + set_field_value(&cmnda_pll0_fb_div_low, 0x20c); + set_field_value(&cmnda_pll0_fb_div_high, 0x084); + set_field_value(&cmnda_pll0_pxdiv_low, 0x003); + set_field_value(&cmnda_pll0_pxdiv_high, 0x003); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x02); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x01); + break; + case CLK_RATIO_5_8: + set_field_value(&cmnda_pll0_ip_div, 0x04); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 550); + set_field_value(&cmnda_pll0_fb_div_low, 0x1b4); + set_field_value(&cmnda_pll0_fb_div_high, 0x06e); + /* does not matter - pixel clock delivered to + controller from SoC */ + set_field_value(&cmnda_pll0_pxdiv_low, 0x003); + /* does not matter - pixel clock delivered to + controller from SoC */ + set_field_value(&cmnda_pll0_pxdiv_high, 0x003); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + case CLK_RATIO_3_4: + set_field_value(&cmnda_pll0_ip_div, 0x03); + set_field_value(&cmn_ref_clk_dig_div, 0x01); + set_field_value(÷r_scaler, 0x01); + set_field_value(&pll_feedback_divider_total, + 495); + set_field_value(&cmnda_pll0_fb_div_low, 0x188); + set_field_value(&cmnda_pll0_fb_div_high, 0x063); + /* does not matter - pixel clock delivered to + controller from SoC */ + set_field_value(&cmnda_pll0_pxdiv_low, 0x003); + /* does not matter - pixel clock delivered to + controller from SoC */ + set_field_value(&cmnda_pll0_pxdiv_high, 0x003); + set_field_value(&vco_ring_select, 0x01); + set_field_value(&cmnda_hs_clk_0_sel, 0x01); + set_field_value(&cmnda_hs_clk_1_sel, 0x01); + set_field_value(&tx_subrate, 0x01); + set_field_value(&cmnda_pll0_hs_sym_div_sel, + 0x00); + break; + default: + debug("This pixel clock frequency (%d KHz) is not supported with this (%0d-bit) color depth.\n", + pixel_freq_khz, bpp); + } + } else { + ftemp = pixel_freq_khz; + debug("This pixel clock frequency (%u kHz) is not supported.\n", + ftemp); + } + + vco_freq = + refclk_freq_khz * pll_feedback_divider_total.value / + cmnda_pll0_ip_div.value; + ftemp = vco_freq; + debug("VCO frequency is %u kHz\n", ftemp); + + if (inside(vco_freq, 1980000, 1980000)) { + set_field_value(&voltage_to_current_coarse, 0x04); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x09); + set_field_value(&ptat_ndac_ctrl, 0x09); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 160); + set_field_value(&v2i_code, 5); + set_field_value(&vco_cal_code, 183); + } else if (inside(vco_freq, 2160000, 2160000)) { + set_field_value(&voltage_to_current_coarse, 0x04); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x09); + set_field_value(&ptat_ndac_ctrl, 0x09); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 166); + set_field_value(&v2i_code, 6); + set_field_value(&vco_cal_code, 208); + } else if (inside(vco_freq, 2475000, 2475000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 167); + set_field_value(&v2i_code, 6); + set_field_value(&vco_cal_code, 209); + } else if (inside(vco_freq, 2700000, 2700000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + switch (pll_feedback_divider_total.value) { + case 300: + set_field_value(&charge_pump_gain, 0x042); + break; + case 400: + set_field_value(&charge_pump_gain, 0x04c); + break; + } + set_field_value(&coarse_code, 188); + set_field_value(&v2i_code, 6); + set_field_value(&vco_cal_code, 225); + } else if (inside(vco_freq, 2970000, 2970000)) { + set_field_value(&voltage_to_current_coarse, 0x06); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 183); + set_field_value(&v2i_code, 6); + set_field_value(&vco_cal_code, 225); + } else if (inside(vco_freq, 3240000, 3240000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + switch (pll_feedback_divider_total.value) { + case 360: + set_field_value(&charge_pump_gain, 0x042); + break; + case 480: + set_field_value(&charge_pump_gain, 0x04c); + break; + } + set_field_value(&coarse_code, 203); + set_field_value(&v2i_code, 7); + set_field_value(&vco_cal_code, 256); + } else if (inside(vco_freq, 3712500, 3712500)) { + set_field_value(&voltage_to_current_coarse, 0x04); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x07); + set_field_value(&ptat_ndac_ctrl, 0x0F); + set_field_value(&charge_pump_gain, 0x04c); + set_field_value(&coarse_code, 212); + set_field_value(&v2i_code, 7); + set_field_value(&vco_cal_code, 257); + } else if (inside(vco_freq, 3960000, 3960000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x07); + set_field_value(&ptat_ndac_ctrl, 0x0F); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 184); + set_field_value(&v2i_code, 6); + set_field_value(&vco_cal_code, 226); + } else if (inside(vco_freq, 4320000, 4320000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x07); + set_field_value(&ptat_ndac_ctrl, 0x0F); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 205); + set_field_value(&v2i_code, 7); + set_field_value(&vco_cal_code, 258); + } else if (inside(vco_freq, 4455000, 4455000)) { + set_field_value(&voltage_to_current_coarse, 0x05); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x00); + set_field_value(&pmos_ctrl, 0x07); + set_field_value(&ptat_ndac_ctrl, 0x0F); + switch (pll_feedback_divider_total.value) { + case 495: + set_field_value(&charge_pump_gain, 0x042); + break; + case 660: + set_field_value(&charge_pump_gain, 0x04c); + break; + } + set_field_value(&coarse_code, 219); + set_field_value(&v2i_code, 7); + set_field_value(&vco_cal_code, 272); + } else if (inside(vco_freq, 4950000, 4950000)) { + set_field_value(&voltage_to_current_coarse, 0x06); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 213); + set_field_value(&v2i_code, 7); + set_field_value(&vco_cal_code, 258); + } else if (inside(vco_freq, 5940000, 5940000)) { + set_field_value(&voltage_to_current_coarse, 0x07); + set_field_value(&voltage_to_current, 0x03); + set_field_value(&ndac_ctrl, 0x01); + set_field_value(&pmos_ctrl, 0x00); + set_field_value(&ptat_ndac_ctrl, 0x07); + set_field_value(&charge_pump_gain, 0x042); + set_field_value(&coarse_code, 244); + set_field_value(&v2i_code, 8); + set_field_value(&vco_cal_code, 292); + } else { + ftemp = vco_freq; + debug("Current vco_freq (%u kHz) is not supported.\n", + ftemp); + } + + /* register CMN_PLL0_VCOCAL_INIT_TMR */ + write16(0x0084, 0x0064); + /* register CMN_PLL0_VCOCAL_ITER_TMR */ + write16(0x0085, 0x000A); + /* register PHY_HDP_CLK_CTL */ + reg_val = read16(0xC009); + reg_val &= 0x00FF; + reg_val |= 0x2 << 8; + reg_val |= 0x1 << 12; + write16(0xC009, reg_val); + /* register CMN_DIAG_PLL0_INCLK_CTRL */ + reg_val = set_reg_value(cmnda_pll0_ip_div); + reg_val |= set_reg_value(cmnda_pll0_hs_sym_div_sel); + write16(0x01CA, reg_val); + /* register CMN_DIAG_PLL0_FBH_OVRD */ + reg_val = set_reg_value(cmnda_pll0_fb_div_high); + reg_val |= (1 << 15); + write16(0x01C0, reg_val); + /* register CMN_DIAG_PLL0_FBL_OVRD */ + reg_val = set_reg_value(cmnda_pll0_fb_div_low); + reg_val |= (1 << 15); + write16(0x01C1, reg_val); + /* register CMN_DIAG_PLL0_PXL_DIVL */ + reg_val = set_reg_value(cmnda_pll0_pxdiv_low); + write16(0x01CC, reg_val); + /* register CMN_DIAG_PLL0_PXL_DIVH */ + reg_val = set_reg_value(cmnda_pll0_pxdiv_high); + reg_val |= (1 << 15); + write16(0x01CB, reg_val); + + /* register TX_DIAG_TX_CTRL */ + for (k = 0; k < num_lanes; k++) { + reg_val = read16(0x41E0 | (k << 9)); + reg_val &= 0xFF3F; + reg_val |= (tx_subrate.value >> 1) << 6; + write16(0x41E0 | (k << 9), reg_val); + } + + /* register PHY_PMA_CMN_CTRL1 */ + reg_val = read16(0xC800); + reg_val &= 0xCFFF; + reg_val |= set_reg_value(cmn_ref_clk_dig_div); + write16(0xC800, reg_val); + /* register CMN_CDIAG_REFCLK_CTRL */ + reg_val = read16(0x0062); + reg_val &= 0x8FFF; + reg_val |= set_reg_value(divider_scaler); + reg_val |= 0x00C0; + write16(0x0062, reg_val); + /* register CMN_DIAG_HSCLK_SEL */ + reg_val = read16(0x01E0); + reg_val &= 0xFF00; + reg_val |= (cmnda_hs_clk_0_sel.value >> 1) << 0; + reg_val |= (cmnda_hs_clk_1_sel.value >> 1) << 4; + write16(0x01E0, reg_val); + /* register CMN_PLLSM0_USER_DEF_CTRL */ + reg_val = set_reg_value(vco_ring_select); + write16(0x002F, reg_val); + + /* register XCVR_DIAG_HSCLK_SEL */ + for (k = 0; k < num_lanes; k++) { + reg_val = read16(0x40E1 | (k << 9)); + reg_val &= 0xCFFF; + reg_val |= (cmnda_hs_clk_0_sel.value >> 1) << 12; + write16(0x40E1 | (k << 9), reg_val); + } + + /* register CMN_DIAG_PLL0_OVRD */ + write16(0x01C2, 0x0000); + /* register CMN_DIAG_PLL0_V2I_TUNE */ + reg_val = set_reg_value(voltage_to_current_coarse); + reg_val |= set_reg_value(voltage_to_current); + write16(0x01C5, reg_val); + /* register CMN_DIAG_PLL0_PTATIS_TUNE1 */ + reg_val = set_reg_value(pmos_ctrl); + reg_val |= set_reg_value(ndac_ctrl); + write16(0x01C8, reg_val); + /* register CMN_DIAG_PLL0_PTATIS_TUNE2 */ + reg_val = set_reg_value(ptat_ndac_ctrl); + write16(0x01C9, reg_val); + /* register CMN_PLL0_VCOCAL_START */ + reg_val = read16(0x0081); + reg_val &= 0xFE00; + reg_val |= set_reg_value(vco_cal_code); + write16(0x0081, reg_val); + /* register CMN_DIAG_PLL0_CP_TUNE */ + reg_val = set_reg_value(charge_pump_gain); + write16(0x01C6, reg_val); + /* register CMN_DIAG_PLL0_LF_PROG */ + write16(0x01C7, 0x0008); + + /* register XCVR_DIAG_PLLDRC_CTRL */ + for (k = 0; k < num_lanes; k++) { + reg_val = read16(0x40E0 | (k << 9)); + reg_val &= 0xBFFF; + write16(0x40E0 | (k << 9), reg_val); + } + } + + /* Back to task phy_cfg_hdp */ + + /* register PHY_PMA_CMN_CTRL1 */ + reg_val = read16(0xC800); + reg_val &= 0xFF8F; + /* for differential clock on the refclk_p and refclk_m + * off chip pins: PHY_PMA_CMN_CTRL1[6:4]=3'b000 */ + reg_val |= 0x0000; + write16(0xC800, reg_val); + + /* register CMN_DIAG_ACYA */ + write16(0x01FF, 0x0100); + + if (phy_reset_workaround) { + /* register PHY_ISO_CMN_CTRL */ + write16(0xC010, 0x0001); /* Deassert PHY reset */ + /* register PHY_PMA_ISO_CMN_CTRL */ + write16(0xC810, 0x0003); + for (k = 0; k < num_lanes; k++) { + /* register XCVR_PSM_RCTRL */ + write16(0x4001 | (k << 9), 0xFEFC); + } + /* register PHY_PMA_ISO_CMN_CTRL + * Assert cmn_macro_pwr_en*/ + write16(0xC810, 0x0013); + + /* PHY_PMA_ISO_CMN_CTRL + * wait for cmn_macro_pwr_en_ack*/ + while (!(read16(0xC810) & (1 << 5))) + ; + + /* PHY_PMA_CMN_CTRL1 wait for cmn_ready */ + while (!(read16(0xC800) & (1 << 0))) + ; + } else { + for (k = 0; k < num_lanes; k++) { + /* register XCVR_PSM_RCTRL */ + write16(0x4001 | (k << 9), 0xBEFC); + } + } + for (k = 0; k < num_lanes; k++) { + /* register TX_PSC_A0 */ + write16(0x4100 | (k << 9), 0x6791); + /* register TX_PSC_A1 */ + write16(0x4101 | (k << 9), 0x6790); + /* register TX_PSC_A2 */ + write16(0x4102 | (k << 9), 0x0090); + /* register TX_PSC_A3 */ + write16(0x4103 | (k << 9), 0x0090); + /* register RX_PSC_CAL */ + reg_val = read16(0x8006 | (k << 9)); + reg_val &= 0xFFBB; + write16(0x8006 | (k << 9), reg_val); + reg_val = read16(0x8000 | (k << 9)); + reg_val &= 0xFFBB; + write16(0x8000 | (k << 9), reg_val); + } + + /* End of task phy_cfg_hdp */ + /* register PHY_HDP_MODE_CTL */ + write16(0xC008, 0x0004); + + aux_cfg_t28hpc(); + return character_freq_khz; +} + +int hdmi_tx_t28hpc_power_config_seq(int num_lanes) +{ + unsigned char k; + + /* Configure the power state. + * register TX_DIAG_ACYA */ + for (k = 0; k < num_lanes; k++) { + /* register XCVR_PSM_CAL_TMR */ + write16(0x41FF | (k << 9), 0x0001); + } + + /* register PHY_DP_MODE_CTL */ + while (!(read16(0xC008) & (1 << 6))) + ; + + /* PHY_DP_MODE_CTL */ + write16(0xC008, (((0x0F << num_lanes) & 0x0F) << 12) | 0x0101); + + /* PHY_DP_MODE_CTL */ + while (!(read16(0xC008) & (1 << 4))) + ; + + return 0; +} diff --git a/drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.h b/drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.h new file mode 100644 index 000000000000..756c1d577e1d --- /dev/null +++ b/drivers/video/imx/hdp/API_AFE_t28hpc_hdmitx.h @@ -0,0 +1,64 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_AFE_t28hpc_hdmitx.h + * + ****************************************************************************** + */ + +#ifndef API_AFE_T28HPC_HDMITX_H_ +#define API_AFE_T28HPC_HDMITX_H_ + +#ifndef __UBOOT__ +#include +#include +#else +#include +#endif +#include "vic_table.h" +#include "API_AFE.h" +#include "externs.h" + +int phy_cfg_t28hpc(int num_lanes, VIC_MODES vic_mode, int bpp, + VIC_PXL_ENCODING_FORMAT format, bool pixel_clk_from_phy); +int hdmi_tx_t28hpc_power_config_seq(int num_lanes); + +#endif diff --git a/drivers/video/imx/hdp/API_AVI.c b/drivers/video/imx/hdp/API_AVI.c new file mode 100644 index 000000000000..d9346f237585 --- /dev/null +++ b/drivers/video/imx/hdp/API_AVI.c @@ -0,0 +1,191 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_AVI.c + * + ****************************************************************************** + */ + +#include "API_AVI.h" +#include "API_Infoframe.h" + +CDN_API_STATUS cdn_api_set_avi(VIC_MODES vic_mode, + VIC_PXL_ENCODING_FORMAT color_mode, + BT_TYPE itu_ver) +{ + unsigned int active_slot = vic_table[vic_mode][H_BLANK]; + unsigned int line_width = vic_table[vic_mode][H_TOTAL]; + unsigned int hactive = line_width - active_slot + 1; + unsigned int vactive = vic_table[vic_mode][V_ACTIVE] + 1; + + unsigned int hactive_l = hactive - 256 * ((unsigned int)hactive / 256); + unsigned int hactive_h = hactive / 256; + unsigned int vactive_l = vactive - 256 * ((unsigned int)vactive / 256); + unsigned int vactive_h = vactive / 256; + + /* unsigned int packet; */ + + unsigned int packet_type = 0x82; + unsigned int packet_version = 0x2; + unsigned int packet_len = 0xd; + unsigned int packet_y = 0; + unsigned int packet_c = 0; + unsigned int packet_r = 0; + unsigned int packet_vic = 0; + unsigned int packet_pr = 0; + unsigned int packet_buf[18 / sizeof(unsigned int)]; + unsigned char *packet = (unsigned char *)&packet_buf[0]; + unsigned int packet_hb0 = 0; + unsigned int packet_hb1 = 0; + unsigned int packet_hb2 = 0; + unsigned int packet_pb0 = 0; + unsigned int packet_pb1 = 0; + unsigned int packet_pb2 = 0; + unsigned int packet_pb3 = 0; + unsigned int packet_pb4 = 0; + unsigned int packet_pb5 = 0; + unsigned int packet_pb6 = 0; + unsigned int packet_pb7 = 0; + unsigned int packet_pb8 = 0; + unsigned int packet_pb9 = 0; + unsigned int packet_pb10 = 0; + unsigned int packet_pb11 = 0; + unsigned int packet_pb12 = 0; + unsigned int packet_pb13 = 0; + unsigned int pb1_13_chksum = 0; + unsigned int packet_chksum = 0; + + if (color_mode == PXL_RGB) + packet_y = 0; + else if (color_mode == YCBCR_4_4_4) + packet_y = 2; + else if (color_mode == YCBCR_4_2_2) + packet_y = 1; + else if (color_mode == YCBCR_4_2_0) + packet_y = 3; + + /* Colorimetry: Nodata=0 IT601=1 ITU709=2 */ + if (itu_ver == BT_601) + packet_c = 1; + else if (itu_ver == BT_709) + packet_c = 2; + else + packet_c = 0; + + unsigned int packet_a0 = 1; + unsigned int packet_b = 0; + unsigned int packet_s = 0; + unsigned int packet_sc = 0; /* Picture Scaling */ + + /* Active Format Aspec Ratio: Same As Picture = 0x8 4:3(Center)=0x9 + 16:9=0xA 14:9=0xB */ + packet_r = vic_table[vic_mode][VIC_R3_0]; + /* Aspect Ratio: Nodata=0 4:3=1 16:9=2 */ + unsigned int packet_m = 0; + /* Quantization Range Default=0 Limited Range=0x1 FullRange=0x2 + Reserved 0x3 */ + unsigned int packet_q = 0; + /* Quantization Range 0=Limited Range FullRange=0x1 Reserved 0x3/2 */ + unsigned int packet_yq = 0; + /* Extended Colorimetry xvYCC601=0x0 xvYCC709=1 All other Reserved */ + unsigned int packet_ec = 0; + /*IT content nodata=0 ITcontent=1 */ + unsigned int packet_it = 0; + /* Video Code (CEA) */ + packet_vic = vic_table[vic_mode][VIC]; + /* Pixel Repetition 0 ... 9 (1-10) */ + packet_pr = vic_table[vic_mode][VIC_PR]; + /* Content Type */ + unsigned int packet_cn = 0; + + packet_hb0 = packet_type; + packet_hb1 = packet_version; + packet_hb2 = packet_len; + + packet_pb1 = 32 * packet_y + 16 * packet_a0 + 4 * packet_b + packet_s; + packet_pb2 = 64 * packet_c + 16 * packet_m + packet_r; + packet_pb3 = + 128 * packet_it + 16 * packet_ec + 4 * packet_q + packet_sc; + packet_pb4 = packet_vic; + packet_pb5 = 64 * packet_yq + 16 * packet_cn + packet_pr; + packet_pb6 = 0; + packet_pb7 = 0; + packet_pb8 = vactive_l; + packet_pb9 = vactive_h; + packet_pb10 = 0; + packet_pb11 = 0; + packet_pb12 = hactive_l; + packet_pb13 = hactive_h; + + pb1_13_chksum = + (packet_hb0 + packet_hb1 + packet_hb2 + packet_pb1 + + packet_pb2 + packet_pb3 + packet_pb4 + packet_pb5 + + packet_pb6 + packet_pb7 + packet_pb8 + packet_pb9 + + packet_pb10 + packet_pb11 + packet_pb12 + packet_pb13); + packet_chksum = + 256 - (pb1_13_chksum - + 256 * ((unsigned int)pb1_13_chksum / 256)); + packet_pb0 = packet_chksum; + + packet[0] = 0; + packet[1] = packet_hb0; + packet[2] = packet_hb1; + packet[3] = packet_hb2; + packet[4] = packet_pb0; + packet[5] = packet_pb1; + packet[6] = packet_pb2; + packet[7] = packet_pb3; + packet[8] = packet_pb4; + packet[9] = packet_pb5; + packet[10] = packet_pb6; + packet[11] = packet_pb7; + packet[12] = packet_pb8; + packet[13] = packet_pb9; + packet[14] = packet_pb10; + packet[15] = packet_pb11; + packet[16] = packet_pb12; + packet[17] = packet_pb13; + + cdn_api_infoframeset(0, packet_len, + (unsigned int *)&packet[0], packet_type); + + return CDN_OK; +} /* End API */ diff --git a/drivers/video/imx/hdp/API_AVI.h b/drivers/video/imx/hdp/API_AVI.h new file mode 100644 index 000000000000..08c35fa39762 --- /dev/null +++ b/drivers/video/imx/hdp/API_AVI.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_AVI.h + * + ****************************************************************************** + */ + +#ifndef API_AVI_H_ +#define API_AVI_H_ + +#include "vic_table.h" +#include "API_General.h" + +CDN_API_STATUS cdn_api_set_avi( + VIC_MODES vic_mode, + VIC_PXL_ENCODING_FORMAT color_mode, + BT_TYPE itu_ver); + +#endif /*API_AVI_H_ */ diff --git a/drivers/video/imx/hdp/API_General.c b/drivers/video/imx/hdp/API_General.c index 83458d7fae30..fb606558c2dc 100644 --- a/drivers/video/imx/hdp/API_General.c +++ b/drivers/video/imx/hdp/API_General.c @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/API_General.h b/drivers/video/imx/hdp/API_General.h index 44e16e8ad7f5..e631919f5715 100644 --- a/drivers/video/imx/hdp/API_General.h +++ b/drivers/video/imx/hdp/API_General.h @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/API_HDMITX.c b/drivers/video/imx/hdp/API_HDMITX.c new file mode 100644 index 000000000000..e3e4eb0e3055 --- /dev/null +++ b/drivers/video/imx/hdp/API_HDMITX.c @@ -0,0 +1,485 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_HDMITX.c + * + ****************************************************************************** + */ + +#include "API_HDMITX.h" +#include "util.h" +#include "opcodes.h" +#ifndef __UBOOT__ +#include "string.h" +#include "stdio.h" +#endif +#include "mhl_hdtx_top.h" +#include "source_phy.h" +#include "address.h" +#include "source_car.h" +#include "source_vif.h" +#include "general_handler.h" + +CDN_API_STATUS CDN_API_HDMITX_DDC_READ(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out) +{ + internal_macro_command_txrx(MB_MODULE_ID_HDMI_TX, HDMI_TX_READ, + CDN_BUS_TYPE_APB, 3, + 1, data_in->slave, + 1, data_in->offset, + 2, data_in->len + ); + internal_readmsg(5, + 1, &data_out->status, + 1, &data_out->slave, + 1, &data_out->offset, + 2, &data_out->len, + 0, &data_out->buff + ); + return CDN_OK; +} + +CDN_API_STATUS CDN_API_HDMITX_DDC_READ_blocking(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out) +{ + internal_block_function(CDN_API_HDMITX_DDC_READ(data_in, data_out)); +} + +CDN_API_STATUS CDN_API_HDMITX_DDC_WRITE(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out) +{ + printf("foo: %x\n", data_in->buff[0]); + internal_macro_command_txrx(MB_MODULE_ID_HDMI_TX, HDMI_TX_WRITE, + CDN_BUS_TYPE_APB, 4, + 1, data_in->slave, + 1, data_in->offset, + 2, data_in->len, + -data_in->len, data_in->buff + ); + internal_readmsg(4, + 1, &data_out->status, + 1, &data_out->slave, + 1, &data_out->offset, + 2, &data_out->len + ); + return CDN_OK; +} + +CDN_API_STATUS CDN_API_HDMITX_DDC_WRITE_blocking(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out) +{ + internal_block_function(CDN_API_HDMITX_DDC_WRITE(data_in, data_out)); +} + +CDN_API_STATUS CDN_API_HDMITX_DDC_UPDATE_READ(HDMITX_TRANS_DATA *data_out) +{ + internal_macro_command_txrx(MB_MODULE_ID_HDMI_TX, HDMI_TX_UPDATE_READ, + CDN_BUS_TYPE_APB, 0); + internal_readmsg(2, + 1, &data_out->status, + 0, &data_out->buff + ); + return CDN_OK; +} + +CDN_API_STATUS CDN_API_HDMITX_DDC_UPDATE_READ_blocking(HDMITX_TRANS_DATA + *data_out) +{ + internal_block_function(CDN_API_HDMITX_DDC_UPDATE_READ(data_out)); +} + +CDN_API_STATUS CDN_API_HDMITX_READ_EDID(unsigned char block, + unsigned char segment, + HDMITX_TRANS_DATA *data_out) +{ + internal_macro_command_txrx(MB_MODULE_ID_HDMI_TX, HDMI_TX_EDID, + CDN_BUS_TYPE_APB, 2, + 1, block, + 1, segment + ); + internal_readmsg(5, + 1, &data_out->status, + 1, &data_out->slave, + 1, &data_out->offset, + 2, &data_out->len, + 0, &data_out->buff + ); + return CDN_OK; +} + +CDN_API_STATUS CDN_API_HDMITX_READ_EDID_blocking(unsigned char block, + unsigned char segment, + HDMITX_TRANS_DATA *data_out) +{ + internal_block_function(CDN_API_HDMITX_READ_EDID(block, segment, + data_out)); +} + +CDN_API_STATUS +CDN_API_HDMITX_Set_Mode_blocking(HDMI_TX_MAIL_HANDLER_PROTOCOL_TYPE protocol, + unsigned int character_rate) +{ + CDN_API_STATUS ret; + GENERAL_READ_REGISTER_RESPONSE resp; + HDMITX_TRANS_DATA data_in; + HDMITX_TRANS_DATA data_out; + unsigned char buff = 1; + + /*enable/disable scrambler; */ + if (protocol == HDMI_TX_MODE_HDMI_2_0) { + if (character_rate > 340000) + buff = 3; /*enable scrambling + TMDS_Bit_Clock_Ratio */ + else + buff = 1; /*enable scrambling */ + } else { + buff = 0; /*disable scrambling */ + } + + data_in.buff = &buff; + data_in.len = 1; + data_in.slave = 0x54; + data_in.offset = 0x20; /*TMDS config */ +#if 1 + if (protocol == HDMI_TX_MODE_HDMI_2_0) + ret = CDN_API_HDMITX_DDC_WRITE_blocking(&data_in, &data_out); + +#endif + ret = cdn_api_general_read_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + &resp); + + /*remove data enable */ + resp.val = resp.val & (~(F_DATA_EN(1))); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + + if (protocol == HDMI_TX_MODE_HDMI_2_0) { + if (character_rate > 3400000) { + /* Set TMDS clock ratio */ + ret = cdn_api_general_write_register_blocking + (ADDR_SOURCE_MHL_HD + + (HDTX_CLOCK_REG_0 << 2), + F_DATA_REGISTER_VAL_0(0x00000)); + ret = cdn_api_general_write_register_blocking + (ADDR_SOURCE_MHL_HD + + (HDTX_CLOCK_REG_1 << 2), + F_DATA_REGISTER_VAL_1(0xFFFFF)); + } + } + + /*set hdmi mode and preemble mode */ + resp.val = resp.val & (~(F_HDMI_MODE(3))); + resp.val = resp.val & (~(F_HDMI2_PREAMBLE_EN(1))); + + resp.val = (resp.val) | (F_HDMI_MODE(protocol)) | + (F_HDMI2_PREAMBLE_EN(1)); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + + /*data enable */ + resp.val |= F_DATA_EN(1); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + + return ret; +} + +CDN_API_STATUS CDN_API_HDMITX_Init_blocking(void) +{ + CDN_API_STATUS ret; + + /*init phy and CAR and HDMI TX */ +/* ret = cdn_api_general_write_register_blocking + (ADDR_SOURCD_PHY + (LANES_CONFIG<<2), + F_SOURCE_PHY_LANE0_SWAP(0) | + F_SOURCE_PHY_LANE1_SWAP(1) | + F_SOURCE_PHY_LANE2_SWAP(2) | + F_SOURCE_PHY_LANE3_SWAP(3) | + F_SOURCE_PHY_COMB_BYPASS(0) | + F_SOURCE_PHY_20_10(1)); */ + + ret = cdn_api_general_write_register_blocking(ADDR_SOURCD_PHY + + (PHY_DATA_SEL << 2), + F_SOURCE_PHY_MHDP_SEL(1)); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_HPD << 2), + F_HPD_VALID_WIDTH(4) | + F_HPD_GLITCH_WIDTH(0)); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + F_HDMI_MODE(1) | + F_AUTO_MODE(0) | + F_GCP_EN(1) | + F_DATA_EN(1) | + F_CLEAR_AVMUTE(1) | + F_HDMI2_PREAMBLE_EN(1) | + F_HDMI2_CTRL_IL_MODE(1) | + F_PIC_3D(0XF) | + F_BCH_EN(1)); + /* open CARS */ + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_PHY_CAR << 2), + 0xF); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_HDTX_CAR << 2), + 0xFF); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_PKT_CAR << 2), + 0xF); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_AIF_CAR << 2), + 0xF); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_CIPHER_CAR << 2), + 0xF); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_CRYPTO_CAR << 2), + 0xF); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_CAR + + (SOURCE_CEC_CAR << 2), 3); + + /*init vif */ + /*ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_VIF + +(HSYNC2VSYNC_POL_CTRL<<2), F_HPOL(0) | F_VPOL(0)); */ + + return ret; +} + + +CDN_API_STATUS CDN_API_HDMITX_SetVic_blocking(VIC_MODES vicMode, int bpp, + VIC_PXL_ENCODING_FORMAT format) +{ + CDN_API_STATUS ret; + GENERAL_READ_REGISTER_RESPONSE resp; + unsigned int vsync_lines = vic_table[vicMode][VSYNC]; + unsigned int eof_lines = vic_table[vicMode][TYPE_EOF]; + unsigned int sof_lines = vic_table[vicMode][SOF]; + unsigned int hblank = vic_table[vicMode][H_BLANK]; + unsigned int hactive = vic_table[vicMode][H_TOTAL] - hblank; + unsigned int vblank = vsync_lines + eof_lines + sof_lines; + unsigned int vactive = vic_table[vicMode][V_TOTAL] - vblank; + unsigned int hfront = vic_table[vicMode][FRONT_PORCH]; + unsigned int hback = vic_table[vicMode][BACK_PORCH]; + unsigned int vfront = eof_lines; + unsigned int hsync = hblank - hfront - hback; + unsigned int vsync = vsync_lines; + unsigned int vback = sof_lines; + unsigned int v_h_polarity = ((vic_table[vicMode][HSYNC_POL] == + ACTIVE_LOW) ? 0 : 1) + + ((vic_table[vicMode][VSYNC_POL] == ACTIVE_LOW) ? 0 : 2); + + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (SCHEDULER_H_SIZE << 2), + (hactive << 16) + hblank); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (SCHEDULER_V_SIZE << 2), + (vactive << 16) + vblank); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_SIGNAL_FRONT_WIDTH + << 2), + (vfront << 16) + hfront); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_SIGNAL_SYNC_WIDTH + << 2), + (vsync << 16) + hsync); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_SIGNAL_BACK_WIDTH + << 2), + (vback << 16) + hback); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_VIF + + (HSYNC2VSYNC_POL_CTRL + << 2), + v_h_polarity); + + /* Data Enable is 1 */ + + /*Reset Data Enable */ + cdn_api_general_read_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), &resp); + + /*reset data enable */ + resp.val = resp.val & (~(F_DATA_EN(1))); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + + /*set bpp */ + resp.val = resp.val & (~(F_VIF_DATA_WIDTH(3))); + switch (bpp) { + case 8: + resp.val = resp.val | (F_VIF_DATA_WIDTH(0)); + break; + + case 10: + resp.val = resp.val | (F_VIF_DATA_WIDTH(1)); + break; + + case 12: + resp.val = resp.val | (F_VIF_DATA_WIDTH(2)); + break; + + case 16: + resp.val = resp.val | (F_VIF_DATA_WIDTH(3)); + break; + } + + /*select color encoding */ + resp.val = resp.val & (~(F_HDMI_ENCODING(3))); + switch (format) { + case PXL_RGB: + + resp.val = resp.val | (F_HDMI_ENCODING(0)); + break; + + case YCBCR_4_4_4: + resp.val = resp.val | (F_HDMI_ENCODING(2)); + break; + + case YCBCR_4_2_2: + resp.val = resp.val | (F_HDMI_ENCODING(1)); + break; + + case YCBCR_4_2_0: + resp.val = resp.val | (F_HDMI_ENCODING(3)); + break; + case Y_ONLY: + /*not exist in hdmi */ + break; + } + + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + + /*set data enable */ + resp.val = resp.val | (F_DATA_EN(1)); + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + + return ret; +} + +CDN_API_STATUS CDN_API_HDMITX_ForceColorDepth_blocking(unsigned char force, + unsigned char val) +{ + unsigned int valToWrite = F_COLOR_DEPTH_VAL(val) | + F_COLOR_DEPTH_FORCE(force); + + return cdn_api_general_write_register_blocking + (ADDR_SOURCE_MHL_HD + + (GCP_FORCE_COLOR_DEPTH_CODING << 2), + valToWrite); +} + +CDN_API_STATUS CDN_API_HDMITX_ReadEvents(uint32_t *events) +{ + CDN_API_STATUS ret; + + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + + internal_tx_mkfullmsg(MB_MODULE_ID_HDMI_TX, HDMI_TX_EVENTS, 0); + state.rxenable = 1; + state.bus_type = CDN_BUS_TYPE_APB; + + return CDN_STARTED; + } + + INTERNAL_PROCESS_MESSAGES; + + ret = internal_test_rx_head(MB_MODULE_ID_HDMI_TX, HDMI_TX_EVENTS); + + if (ret != CDN_OK) + return ret; + + internal_readmsg(1, 4, events); + + return CDN_OK; +} + +CDN_API_STATUS CDN_API_HDMITX_ReadEvents_blocking(uint32_t *events) +{ + internal_block_function(CDN_API_HDMITX_ReadEvents(events)); +} + +CDN_API_STATUS CDN_API_HDMITX_GetHpdStatus(uint8_t *hpd_sts) +{ + CDN_API_STATUS ret; + + if (!state.running) { + if (!internal_apb_available()) + return CDN_BSY; + + /* + * General Module is used here for obtaining HPD State because + * HDMI TX Module is inactive in stand-by mode, thus cannot + * return it. + */ + internal_tx_mkfullmsg(MB_MODULE_ID_GENERAL, + GENERAL_GET_HPD_STATE, 0); + state.rxenable = 1; + state.bus_type = CDN_BUS_TYPE_APB; + + return CDN_STARTED; + } + + INTERNAL_PROCESS_MESSAGES; + + ret = internal_test_rx_head(MB_MODULE_ID_GENERAL, + GENERAL_GET_HPD_STATE); + + if (ret != CDN_OK) + return ret; + + internal_readmsg(1, 1, hpd_sts); + + return CDN_OK; +} + +CDN_API_STATUS CDN_API_HDMITX_GetHpdStatus_blocking(uint8_t *hpd_sts) +{ + internal_block_function(CDN_API_HDMITX_GetHpdStatus(hpd_sts)); +} diff --git a/drivers/video/imx/hdp/API_HDMITX.h b/drivers/video/imx/hdp/API_HDMITX.h new file mode 100644 index 000000000000..7e910de934cb --- /dev/null +++ b/drivers/video/imx/hdp/API_HDMITX.h @@ -0,0 +1,181 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_HDMITX.h + * + ****************************************************************************** + */ + +#ifndef _API_HDMITX_H_ +# define _API_HDMITX_H_ + +# include "API_General.h" +# include "hdmi.h" +# include "vic_table.h" + +/** + * \addtogroup HDMI_TX_API + * \{ + */ + +# define HDMI_TX_EVENT_CODE_HPD_HIGH 0x01 +# define HDMI_TX_EVENT_CODE_HPD_LOW 0x02 +# define HDMI_TX_EVENT_CODE_HPD_STATE_LOW 0x00 +# define HDMI_TX_EVENT_CODE_HPD_STATE_HIGH 0x08 + +typedef struct { + /** if used to return data, this pointer is set (instead of being a + * destination to copy data to + */ + unsigned char *buff; + HDMI_I2C_STATUS status; + unsigned short len; + unsigned char slave; + unsigned char offset; +} HDMITX_TRANS_DATA; + + +typedef enum { + HDMI_TX_MODE_DVI, + HDMI_TX_MODE_HDMI_1_4, + HDMI_TX_MODE_HDMI_2_0, +} HDMI_TX_MAIL_HANDLER_PROTOCOL_TYPE; + +/** + * \brief I2C read transaction + * \param [in] data_in - fields used: len, slave, offset + * \param [out] data_out - fields used: all + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_DDC_READ(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out); +CDN_API_STATUS CDN_API_HDMITX_DDC_READ_blocking(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out); + +/** + * \brief I2C write transaction + * \param [in] data_in - fields used: len, slave, offset, buff + * \param [out] data_out - fields used: status, len, slave, offset + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_DDC_WRITE(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out); +CDN_API_STATUS CDN_API_HDMITX_DDC_WRITE_blocking(HDMITX_TRANS_DATA *data_in, + HDMITX_TRANS_DATA *data_out); + +/** + * \brief I2C update read + * \param [out] data_out - fields used: status, buff + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_DDC_UPDATE_READ(HDMITX_TRANS_DATA *data_out); +CDN_API_STATUS +CDN_API_HDMITX_DDC_UPDATE_READ_blocking(HDMITX_TRANS_DATA *data_out); + +/** + * \brief I2C read edid + * \param [in] block - EDID block + * \pram [in] segment - EDID segment + * \param [out] data_out - fields used: status, buff, slave (as block), + * offset (as segment), len + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_READ_EDID(unsigned char block, + unsigned char segment, + HDMITX_TRANS_DATA *data_out); +CDN_API_STATUS CDN_API_HDMITX_READ_EDID_blocking(unsigned char block, + unsigned char segment, + HDMITX_TRANS_DATA *data_out); + +/** + * \brief set hdmi protocol type (DVI,1.x,2.x) (send scrambler command over + * scdc and set bits in controller) + * \param [in] protocol - type + * \returns status + */ +/*CDN_API_STATUS +CDN_API_HDMITX_Set_Mode_blocking(HDMI_TX_MAIL_HANDLER_PROTOCOL_TYPE protocol, + float character_rate);*/ +CDN_API_STATUS +CDN_API_HDMITX_Set_Mode_blocking(HDMI_TX_MAIL_HANDLER_PROTOCOL_TYPE protocol, + unsigned int character_rate); +/** + * \brief init hdmi registers + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_Init_blocking(void); + +/** + * \brief change to vid id vicMode + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_SetVic_blocking(VIC_MODES vicMode, + int bpp, + VIC_PXL_ENCODING_FORMAT format); + +/** + * \brief option to force color depth in the gcp or not force (HW mode) + * \returns status + */ +CDN_API_STATUS CDN_API_HDMITX_ForceColorDepth_blocking(unsigned char force, + unsigned char val); + +/** + * \brief send HDMI_TX_TX_READ_EVENTS command + */ +CDN_API_STATUS CDN_API_HDMITX_ReadEvents(uint32_t *events); + +/** + * blocking version of #CDN_API_HDMITX_ReadEvents + */ +CDN_API_STATUS CDN_API_HDMITX_ReadEvents_blocking(uint32_t *events); + +/** + * \brief get current HPD status + */ +CDN_API_STATUS CDN_API_HDMITX_GetHpdStatus(uint8_t *hpd_sts); + +/** + * \brief blocking version of #CDN_API_HDMITX_GetHpdStatus + */ +CDN_API_STATUS CDN_API_HDMITX_GetHpdStatus_blocking(uint8_t *hpd_sts); + +#endif diff --git a/drivers/video/imx/hdp/API_Infoframe.c b/drivers/video/imx/hdp/API_Infoframe.c new file mode 100644 index 000000000000..9fe05aabb5a3 --- /dev/null +++ b/drivers/video/imx/hdp/API_Infoframe.c @@ -0,0 +1,156 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_Infoframe.c + * + ****************************************************************************** + */ + +#include "API_Infoframe.h" +#include "address.h" +#include "source_pif.h" +#include "externs.h" +#ifndef __UBOOT__ +#include +#include +#include +#else +#include +#include +#endif +#include "util.h" + +#define BANK_OFFSET 0x0 + +/* Redefined because of compiler warnings about 32 bit shift left */ +#ifdef F_DATA_WR +#undef F_DATA_WR +#define F_DATA_WR(a_) ((uint32_t)(a_)) +#endif + +static CDN_API_STATUS infoframeSet(unsigned char entry_id, + unsigned char packet_len, + unsigned int *packet, + unsigned char packet_type, + unsigned char active_idle) +{ + unsigned int idx; + unsigned int activeIdleBit = (0 == active_idle) ? 0 : 0x20000; + /*invalidate entry */ + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_PKT_ALLOC_REG << 2), + activeIdleBit | F_PKT_ALLOC_ADDRESS(entry_id))) + return CDN_ERR; + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_PKT_ALLOC_WR_EN << 2), + F_PKT_ALLOC_WR_EN(1))) + return CDN_ERR; + + /*flush fifo 1 */ + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_FIFO1_FLUSH << 2), + F_FIFO1_FLUSH(1))) + return CDN_ERR; + + /*write packet into memory */ + for (idx = 0; idx < packet_len; idx++) + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_DATA_WR << 2), + F_DATA_WR(packet[idx]))) + return CDN_ERR; + + /*write entry id */ + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_WR_ADDR << 2), + F_WR_ADDR(entry_id))) + return CDN_ERR; + + /*write request */ + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_WR_REQ << 2), + F_HOST_WR(1))) + return CDN_ERR; + + /*update entry */ + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_PKT_ALLOC_REG << 2), + activeIdleBit | F_TYPE_VALID(1) | + F_PACKET_TYPE(packet_type) | + F_PKT_ALLOC_ADDRESS(entry_id))) + return CDN_ERR; + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_PKT_ALLOC_WR_EN << 2), + F_PKT_ALLOC_WR_EN(1))) + return CDN_ERR; + + return CDN_OK; +} + +CDN_API_STATUS cdn_api_infoframeset(unsigned char entry_id, + unsigned char packet_len, + unsigned int *packet, + unsigned char packet_type) +{ + return infoframeSet(entry_id, packet_len, packet, packet_type, 1); +} + +CDN_API_STATUS cdn_api_infoframesetnoactiveidle(unsigned char entry_id, + unsigned char packet_len, + unsigned int *packet, + unsigned char packet_type) +{ + return infoframeSet(entry_id, packet_len, packet, packet_type, 0); +} + +CDN_API_STATUS cdn_api_infoframeremove(unsigned char entry_id) +{ + /*invalidate entry */ + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_PKT_ALLOC_REG << 2), + 0x20000 | F_PKT_ALLOC_ADDRESS(entry_id))) + return CDN_ERR; + if (cdn_apb_write(BANK_OFFSET | ADDR_SOURCE_PIF | + (SOURCE_PIF_PKT_ALLOC_WR_EN << 2), + F_PKT_ALLOC_WR_EN(1))) + return CDN_ERR; + + return CDN_OK; +} diff --git a/drivers/video/imx/hdp/API_Infoframe.h b/drivers/video/imx/hdp/API_Infoframe.h new file mode 100644 index 000000000000..6cfde69535f9 --- /dev/null +++ b/drivers/video/imx/hdp/API_Infoframe.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * API_Infoframe.h + * + ****************************************************************************** + */ + +#ifndef API_INFOFRAME_H +# define API_INFOFRAME_H + +/** + * \addtogroup INFO_FRAME_API + * \{ + */ + +# include "API_General.h" + +CDN_API_STATUS cdn_api_infoframeset(unsigned char entry_id, + unsigned char packet_len, + unsigned int *packet, + unsigned char packet_type); +CDN_API_STATUS cdn_api_infoframesetnoactiveidle(unsigned char entry_id, + unsigned char packet_len, + unsigned int *packet, + unsigned char packet_type); +CDN_API_STATUS cdn_api_infoframeremove(unsigned char entry_id); + +#endif diff --git a/drivers/video/imx/hdp/Makefile b/drivers/video/imx/hdp/Makefile index 13dcefdee5f6..d704b73201c6 100644 --- a/drivers/video/imx/hdp/Makefile +++ b/drivers/video/imx/hdp/Makefile @@ -1 +1,49 @@ -obj-y += API_General.o util.o test_base_sw.o +# +# Copyright 2018 NXP +# +# SPDX-License-Identifier: GPL-2.0+ +# +obj-$(CONFIG_VIDEO_IMX_HDP_LOAD) += API_General.o util.o test_base_sw.o + +obj-$(CONFIG_VIDEO_IMX8_HDMI) += \ + API_General.o \ + test_base_sw.o \ + API_AVI.o \ + API_Infoframe.o \ + util.o \ + vic_table.o \ + edid_parser.o \ + API_AFE.o \ + API_HDMITX.o \ + API_AFE_t28hpc_hdmitx.o + +# common objects +#obj-y += \ +# API_General.o API_AVI.o API_Infoframe.o \ +# util.o vic_table.o test_base_sw.o \ +# avgen_drv.o edid_parser.o \ +# API_AFE.o + +#DP objects +# API_DPTX.o \ +# API_AFE_mcu2_dp.o\ +# mhdp_firmware.o + +#hdmi objects +#obj-y += \ +# API_HDMITX.o \ +# API_HDCP.o \ +# API_AFE_t28hpc_hdmitx.o +# + +# USE for QM +# blob/API_AFE_mcu1_dp.o +# blob/API_AFE_ss28fdsoi_kiran_hdmitx.o +# blob/ss28fdsoi_hdmitx_table.o +# blob/hdmitx_firmware.o +# blob/mhdp_firmware.o + +# Use for mscale +# API_AFE_mcu2_dp.o () +# API_AFE_t28hpc_hdmitx.c +# diff --git a/drivers/video/imx/hdp/apb_cfg.h b/drivers/video/imx/hdp/apb_cfg.h index cdcbd76c016c..572ab07b94d9 100644 --- a/drivers/video/imx/hdp/apb_cfg.h +++ b/drivers/video/imx/hdp/apb_cfg.h @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/avgen.h b/drivers/video/imx/hdp/avgen.h new file mode 100644 index 000000000000..507d851d1e75 --- /dev/null +++ b/drivers/video/imx/hdp/avgen.h @@ -0,0 +1,252 @@ +/****************************************************************************** + * + * Copyright (C) 2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * avgen.h + * + ****************************************************************************** + */ + +#ifndef AVGEN_H_ +# define AVGEN_H_ + + +/* register HDMIPOL */ +# define HDMIPOL 0 +# define F_HDMI_V_H_POLARITY(x) (((x) & ((1 << 2) - 1)) << 0) +# define F_HDMI_V_H_POLARITY_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) +# define F_HDMI_BITWIDTH(x) (((x) & ((1 << 2) - 1)) << 2) +# define F_HDMI_BITWIDTH_RD(x) (((x) & (((1 << 2) - 1) << 2)) >> 2) + +/* register HDMI_FRONT_PORCHE_L */ +# define HDMI_FRONT_PORCHE_L 1 +# define F_HDMI_FRONT_PORCHE_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_FRONT_PORCHE_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDFP */ +# define HDFP 2 +# define F_HDMI_FRONT_PORCHE_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_FRONT_PORCHE_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDBP */ +# define HDBP 3 +# define F_HDMI_BACK_PORCHE_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_BACK_PORCHE_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDMI_BACK_PORCHE_H */ +# define HDMI_BACK_PORCHE_H 4 +# define F_HDMI_BACK_PORCHE_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_BACK_PORCHE_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDAS */ +# define HDAS 5 +# define F_HDMI_ACTIVE_SLOT_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_ACTIVE_SLOT_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDMI_ACTIVE_SLOT_H */ +# define HDMI_ACTIVE_SLOT_H 6 +# define F_HDMI_ACTIVE_SLOT_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_ACTIVE_SLOT_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDFL */ +# define HDFL 7 +# define F_HDMI_FRAME_LINES_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_FRAME_LINES_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDMI_FRAME_LINES_H */ +# define HDMI_FRAME_LINES_H 8 +# define F_HDMI_FRAME_LINES_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_FRAME_LINES_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDLW */ +# define HDLW 9 +# define F_HDMI_LINE_WIDTH_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_LINE_WIDTH_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDMI_LINE_WIDTH_H */ +# define HDMI_LINE_WIDTH_H 10 +# define F_HDMI_LINE_WIDTH_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDMI_LINE_WIDTH_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDVL */ +# define HDVL 11 +# define F_HDMI_VSYNC_LINES(x) (((x) & ((1 << 7) - 1)) << 0) +# define F_HDMI_VSYNC_LINES_RD(x) (((x) & (((1 << 7) - 1) << 0)) >> 0) + +/* register HDEL */ +# define HDEL 12 +# define F_HDMI_EOF_LINES(x) (((x) & ((1 << 7) - 1)) << 0) +# define F_HDMI_EOF_LINES_RD(x) (((x) & (((1 << 7) - 1) << 0)) >> 0) + +/* register HDSL */ +# define HDSL 13 +# define F_HDMI_SOF_LINES(x) (((x) & ((1 << 7) - 1)) << 0) +# define F_HDMI_SOF_LINES_RD(x) (((x) & (((1 << 7) - 1) << 0)) >> 0) + +/* register HDCFUPDT */ +# define HDCFUPDT 14 +# define F_HDMI_CODE_FORMAT_UPDT(x) (((x) & ((1 << 6) - 1)) << 0) +# define F_HDMI_CODE_FORMAT_UPDT_RD(x) (((x) & (((1 << 6) - 1) << 0)) >> 0) + +/* register HDCF */ +# define HDCF 15 +# define F_HDMI_CODE_FORMAT(x) (((x) & ((1 << 6) - 1)) << 0) +# define F_HDMI_CODE_FORMAT_RD(x) (((x) & (((1 << 6) - 1) << 0)) >> 0) + +/* register HDASPACE */ +# define HDASPACE 16 +# define F_HDASPACE(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_HDASPACE_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register HDMI_3D_MODE */ +# define HDMI_3D_MODE 17 +# define F_HDMI_3D_MODE(x) (((x) & ((1 << 3) - 1)) << 0) +# define F_HDMI_3D_MODE_RD(x) (((x) & (((1 << 3) - 1) << 0)) >> 0) + +/* register PTRNGENR */ +# define PTRNGENR 18 +# define F_PTRNGENR_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_PTRNGENR_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register PTRNGENR_H */ +# define PTRNGENR_H 19 +# define F_PTRNGENR_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_PTRNGENR_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register PTRNGENG */ +# define PTRNGENG 20 +# define F_PTRNGENG_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_PTRNGENG_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register PTRNEGENG_H */ +# define PTRNEGENG_H 21 +# define F_PTRNGENG_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_PTRNGENG_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register PTRNGENB */ +# define PTRNGENB 22 +# define F_PTRNGENB_L(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_PTRNGENB_L_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register PTRGENB */ +# define PTRGENB 23 +# define F_PTRNGENB_H(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_PTRNGENB_H_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register PTRNGENFF */ +# define PTRNGENFF 30 +# define F_PTRNGENIP(x) (((x) & ((1 << 1) - 1)) << 1) +# define F_PTRNGENIP_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) + +/* register PGENCTRL */ +# define PGENCTRL 32 +# define F_PGENCF(x) (((x) & ((1 << 6) - 1)) << 1) +# define F_PGENCF_RD(x) (((x) & (((1 << 6) - 1) << 1)) >> 1) +# define F_PTRNGENSTRT(x) (((x) & ((1 << 1) - 1)) << 7) +# define F_PTRNGENSTRT_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) + +/* register PGENCTRL_H */ +# define PGENCTRL_H 33 +# define F_PTRNGENRST(x) (((x) & ((1 << 1) - 1)) << 0) +# define F_PTRNGENRST_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +# define F_PIC_SEL(x) (((x) & ((1 << 3) - 1)) << 1) +# define F_PIC_SEL_RD(x) (((x) & (((1 << 3) - 1) << 1)) >> 1) +# define F_PIC_YCBCR_SEL(x) (((x) & ((1 << 2) - 1)) << 4) +# define F_PIC_YCBCR_SEL_RD(x) (((x) & (((1 << 2) - 1) << 4)) >> 4) + +/* register PGEN_COLOR_BAR_CTRL */ +# define PGEN_COLOR_BAR_CTRL 34 +# define F_PGEN_NUM_BAR(x) (((x) & ((1 << 3) - 1)) << 0) +# define F_PGEN_NUM_BAR_RD(x) (((x) & (((1 << 3) - 1) << 0)) >> 0) + +/* register PGEN_COLOR_BAR_CONTROL_H */ +# define PGEN_COLOR_BAR_CONTROL_H 35 +# define F_PGEN_COLOR_UPDT(x) (((x) & ((1 << 6) - 1)) << 0) +# define F_PGEN_COLOR_UPDT_RD(x) (((x) & (((1 << 6) - 1) << 0)) >> 0) + +/* register GEN_AUDIO_CONTROL */ +# define GEN_AUDIO_CONTROL 36 +# define F_AUDIO_START(x) (((x) & ((1 << 1) - 1)) << 1) +# define F_AUDIO_START_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +# define F_AUDIO_RESET(x) (((x) & ((1 << 1) - 1)) << 2) +# define F_AUDIO_RESET_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) + +/* register SPDIF_CTRL_A */ +# define SPDIF_CTRL_A 37 +# define F_SPDIF_SOURCE_NUM(x) (((x) & ((1 << 4) - 1)) << 0) +# define F_SPDIF_SOURCE_NUM_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +# define F_SPDIF_CH_NUM(x) (((x) & ((1 << 4) - 1)) << 4) +# define F_SPDIF_CH_NUM_RD(x) (((x) & (((1 << 4) - 1) << 4)) >> 4) + +/* register SPDIF_CTRL_A_H */ +# define SPDIF_CTRL_A_H 38 +# define F_SPDIF_SMP_FREQ(x) (((x) & ((1 << 4) - 1)) << 0) +# define F_SPDIF_SMP_FREQ_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +# define F_SPDIF_CLK_ACCUR(x) (((x) & ((1 << 2) - 1)) << 4) +# define F_SPDIF_CLK_ACCUR_RD(x) (((x) & (((1 << 2) - 1) << 4)) >> 4) +# define F_SPDIF_VALID(x) (((x) & ((1 << 1) - 1)) << 6) +# define F_SPDIF_VALID_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) + +/* register SPDIF_CTRL_B */ +# define SPDIF_CTRL_B 39 +# define F_SPDIF_WORD_LENGTH(x) (((x) & ((1 << 4) - 1)) << 0) +# define F_SPDIF_WORD_LENGTH_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +# define F_SPDIF_ORG_SMP_FREQ(x) (((x) & ((1 << 4) - 1)) << 4) +# define F_SPDIF_ORG_SMP_FREQ_RD(x) (((x) & (((1 << 4) - 1) << 4)) >> 4) + +/* register SPDIF_CTRL_B_H */ +# define SPDIF_CTRL_B_H 40 +# define F_CATEGORY_MODE(x) (((x) & ((1 << 8) - 1)) << 0) +# define F_CATEGORY_MODE_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) + +/* register AUDIO_DIV_EN */ +# define AUDIO_DIV_EN 45 +# define F_AGEN_60958_I2S(x) (((x) & ((1 << 1) - 1)) << 1) +# define F_AGEN_60958_I2S_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +# define F_AGEN_PRL_SUBFRAME(x) (((x) & ((1 << 1) - 1)) << 2) +# define F_AGEN_PRL_SUBFRAME_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +# define F_AGEN_SAMPLES_DATA(x) (((x) & ((1 << 1) - 1)) << 3) +# define F_AGEN_SAMPLES_DATA_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) + +#endif /*AVGEN */ diff --git a/drivers/video/imx/hdp/avgen_drv.c b/drivers/video/imx/hdp/avgen_drv.c new file mode 100644 index 000000000000..171c5f94653d --- /dev/null +++ b/drivers/video/imx/hdp/avgen_drv.c @@ -0,0 +1,305 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * avgen_drv.c + * + ****************************************************************************** + */ + +#include "mhl_hdtx_top.h" +#include "address.h" +#include "avgen.h" +#include "avgen_drv.h" +#include "util.h" +#include "externs.h" + +#define ADDR_AVGEN 0x80000 + +CDN_API_STATUS CDN_API_AVGEN_Set(VIC_MODES vicMode, CDN_PROTOCOL_TYPE protocol, + VIC_PXL_ENCODING_FORMAT format) +{ + /*CDN_API_STATUS ret; */ + /*GENERAL_Read_Register_response resp; */ + unsigned int pixelClockFreq = CDN_API_Get_PIXEL_FREQ_KHZ_ClosetVal + (vic_table[vicMode][PIXEL_FREQ_KHZ], protocol); + unsigned int v_h_polarity = + ((vic_table[vicMode][HSYNC_POL] == ACTIVE_LOW) ? 0 : 1) + + ((vic_table[vicMode][VSYNC_POL] == ACTIVE_LOW) ? 0 : 2); + unsigned int front_porche_l = vic_table[vicMode][FRONT_PORCH] - 256 * + ((unsigned int)vic_table[vicMode][FRONT_PORCH] / 256); + unsigned int front_porche_h = vic_table[vicMode][FRONT_PORCH] / 256; + unsigned int back_porche_l = vic_table[vicMode][BACK_PORCH] - 256 * + ((unsigned int)vic_table[vicMode][BACK_PORCH] / 256); + unsigned int back_porche_h = vic_table[vicMode][BACK_PORCH] / 256; + unsigned int active_slot_l = vic_table[vicMode][H_BLANK] - 256 * + ((unsigned int)vic_table[vicMode][H_BLANK] / 256); + unsigned int active_slot_h = vic_table[vicMode][H_BLANK] / 256; + unsigned int frame_lines_l = vic_table[vicMode][V_TOTAL] - 256 * + ((unsigned int)vic_table[vicMode][V_TOTAL] / 256); + unsigned int frame_lines_h = vic_table[vicMode][V_TOTAL] / 256; + unsigned int line_width_l = vic_table[vicMode][H_TOTAL] - 256 * + ((unsigned int)vic_table[vicMode][H_TOTAL] / 256); + unsigned int line_width_h = vic_table[vicMode][H_TOTAL] / 256; + unsigned int vsync_lines = vic_table[vicMode][VSYNC]; + unsigned int eof_lines = vic_table[vicMode][TYPE_EOF]; + unsigned int sof_lines = vic_table[vicMode][SOF]; + unsigned int interlace_progressive = + (vic_table[vicMode][I_P] == INTERLACED) ? 2 : 0; + unsigned int set_vif_clock = 0; + + /*needed for HDMI /////////////////////////////// */ + /*unsigned int hblank = vic_table[vicMode][H_BLANK]; */ + /*unsigned int hactive = vic_table[vicMode][H_TOTAL]-hblank; */ + /*unsigned int vblank = vsync_lines+eof_lines+sof_lines; */ + /*unsigned int vactive = vic_table[vicMode][V_TOTAL]-vblank; */ + /*unsigned int hfront = vic_table[vicMode][FRONT_PORCH]; */ + /*unsigned int hback = vic_table[vicMode][BACK_PORCH]; */ + /*unsigned int vfront = eof_lines; */ + /*unsigned int hsync = hblank-hfront-hback; */ + /*unsigned int vsync = vsync_lines; */ + /*unsigned int vback = sof_lines; */ + unsigned int set_CLK_SEL = 0; + unsigned int set_REF_CLK_SEL = 0; + unsigned int set_pll_CLK_IN = 0; + unsigned int set_pll_clkfbout_l = 0; + unsigned int set_pll_clkfbout_h = 0; + unsigned int set_pll_CLKOUT5_L = 0; + unsigned int set_pll_CLKOUT5_H = 0; + unsigned int set_pll2_CLKIN = 0; + unsigned int set_pll2_CLKFBOUT_L = 0; + unsigned int set_pll2_CLKFBOUT_H = 0; + unsigned int set_pll2_CLKOUT5_L = 0; + unsigned int set_pll2_CLKOUT5_H = 0; + /*///////////////////////////////////////////////// */ + + cdn_apb_write(0x1c00C6 << 2, + (int)(vic_table[vicMode][PIXEL_FREQ_KHZ] * 1000)); + cdn_apb_write(0x1c00C6 << 2, (int)(pixelClockFreq)); + + if ((int)(pixelClockFreq) == 25) { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 4; + set_REF_CLK_SEL = 0; + set_pll_CLK_IN = 65; + set_pll_clkfbout_l = 4292; + set_pll_clkfbout_h = 128; + set_pll_CLKOUT5_L = 4422; + set_pll_CLKOUT5_H = 128; + set_pll2_CLKIN = 12289; + set_pll2_CLKFBOUT_L = 4356; + set_pll2_CLKFBOUT_H = 0; + set_pll2_CLKOUT5_L = 4552; + set_pll2_CLKOUT5_H = 128; + } else { + set_vif_clock = 0x300; + } + } else if ((int)pixelClockFreq == 27000) { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 5; + set_REF_CLK_SEL = 0; + set_pll_CLK_IN = 49217; + set_pll_clkfbout_l = 4226; + set_pll_clkfbout_h = 0; + set_pll_CLKOUT5_L = 4422; + set_pll_CLKOUT5_H = 128; + } else { + set_vif_clock = 0x301; + } + } else if ((int)pixelClockFreq == 54000) { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 5; + set_REF_CLK_SEL = 0; + set_pll_CLK_IN = 4096; + set_pll_clkfbout_l = 4226; + set_pll_clkfbout_h = 0; + set_pll_CLKOUT5_L = 4422; + set_pll_CLKOUT5_H = 128; + } else { + set_vif_clock = 0x302; + } + } else if (pixelClockFreq == 74250) { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 1; + set_pll_CLK_IN = 74; + } else { + set_vif_clock = 0x303; + } + } else if (pixelClockFreq == 148500) { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 0; + set_pll_CLK_IN = 148; + } else { + set_vif_clock = 0x304; + } + } else if ((int)pixelClockFreq == 108000) { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 5; + set_REF_CLK_SEL = 2; + set_pll_CLK_IN = 8258; + set_pll_clkfbout_l = 4616; + set_pll_clkfbout_h = 0; + set_pll_CLKOUT5_L = 4422; + set_pll_CLKOUT5_H = 128; + } else { + set_vif_clock = 0x305; + } + } else { + if (protocol == CDN_HDMITX_TYPHOON) { + set_CLK_SEL = 1; + set_pll_CLK_IN = pixelClockFreq; + } else { + set_vif_clock = 0; + } + } + unsigned int start_pgen = 128; + /*unsigned int temp; */ + if (protocol == CDN_HDMITX_TYPHOON) { + if (cdn_apb_write(0x0c0001 << 2, + ((0) + (2 * set_CLK_SEL) + (16 * 0) + + (32 * 0) + (64 * 3) + (65536 * 3) + + (1048576 * set_REF_CLK_SEL)))) + return CDN_ERR; + if (cdn_apb_write(0x1c00C6 << 2, set_pll_CLK_IN)) + return CDN_ERR; + if (cdn_apb_write(0x1c00CC << 2, set_pll_clkfbout_l)) + return CDN_ERR; + if (cdn_apb_write(0x1c00CD << 2, set_pll_clkfbout_h)) + return CDN_ERR; + if (cdn_apb_write(0x1c00CE << 2, set_pll_CLKOUT5_L)) + return CDN_ERR; + if (cdn_apb_write(0x1c00CF << 2, set_pll_CLKOUT5_H)) + return CDN_ERR; + if (cdn_apb_write(0x1c0086 << 2, set_pll2_CLKIN)) + return CDN_ERR; + if (cdn_apb_write(0x1c008C << 2, set_pll2_CLKFBOUT_L)) + return CDN_ERR; + if (cdn_apb_write(0x1c008D << 2, set_pll2_CLKFBOUT_H)) + return CDN_ERR; + if (cdn_apb_write(0x1c008E << 2, set_pll2_CLKOUT5_L)) + return CDN_ERR; + if (cdn_apb_write(0x1c008F << 2, set_pll2_CLKOUT5_H)) + return CDN_ERR; + if (cdn_apb_write(0x0c0001 << 2, + ((1) + (2 * set_CLK_SEL) + (16 * 0) + + (32 * 0) + (64 * 3) + (65536 * 3) + + (1048576 * set_REF_CLK_SEL)))) + return CDN_ERR; + } + + if (cdn_apb_write((ADDR_AVGEN + HDMIPOL) << 2, v_h_polarity)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDMI_FRONT_PORCHE_L) << 2, + front_porche_l)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDFP) << 2, front_porche_h)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDBP) << 2, back_porche_l)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDMI_BACK_PORCHE_H) << 2, + back_porche_h)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDAS) << 2, active_slot_l)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDMI_ACTIVE_SLOT_H) << 2, + active_slot_h)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDFL) << 2, frame_lines_l)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDMI_FRAME_LINES_H) << 2, + frame_lines_h)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDLW) << 2, line_width_l)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDMI_LINE_WIDTH_H) << 2, line_width_h)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDVL) << 2, vsync_lines)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDEL) << 2, eof_lines)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + HDSL) << 2, sof_lines)) + return CDN_ERR; + if (cdn_apb_write((ADDR_AVGEN + PTRNGENFF) << 2, interlace_progressive)) + return CDN_ERR; + + if (protocol == CDN_HDMITX_TYPHOON) { + switch (format) { + case PXL_RGB: + + if (cdn_apb_write((ADDR_AVGEN + PGENCTRL_H) << 2, + F_PIC_SEL(1) | F_PIC_YCBCR_SEL(0))) + return CDN_ERR; + break; + + case YCBCR_4_4_4: + if (cdn_apb_write((ADDR_AVGEN + PGENCTRL_H) << 2, + F_PIC_SEL(2) | F_PIC_YCBCR_SEL(0))) + return CDN_ERR; + + break; + + case YCBCR_4_2_2: + if (cdn_apb_write((ADDR_AVGEN + PGENCTRL_H) << 2, + F_PIC_SEL(2) | F_PIC_YCBCR_SEL(1))) + return CDN_ERR; + + break; + + case YCBCR_4_2_0: + if (cdn_apb_write((ADDR_AVGEN + PGENCTRL_H) << 2, + F_PIC_SEL(2) | F_PIC_YCBCR_SEL(2))) + return CDN_ERR; + + break; + case Y_ONLY: + /*not exist in hdmi */ + break; + } + } else { + if (set_vif_clock != 0) + if (cdn_apb_write(0xC0006 << 2, set_vif_clock)) + return CDN_ERR; + } + + if (cdn_apb_write((ADDR_AVGEN + PGENCTRL) << 2, start_pgen)) + return CDN_ERR; + + return CDN_OK; +} diff --git a/drivers/video/imx/hdp/avgen_drv.h b/drivers/video/imx/hdp/avgen_drv.h new file mode 100644 index 000000000000..56473d738d0d --- /dev/null +++ b/drivers/video/imx/hdp/avgen_drv.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * avgen_drv.h + * + ****************************************************************************** + */ + +#ifndef AVGEN_DRV_H_ +# define AVGEN_DRV_H_ + +#ifndef __UBOOT__ +# include +#else +#include +#endif + +# include "vic_table.h" +# include "API_General.h" +# include "defs.h" + +/** + * \brief set avgen according to mode and vic table, user that doesnt have + * cadence AVGEN, need to implement this function on user + * platform + */ +CDN_API_STATUS CDN_API_AVGEN_Set(VIC_MODES vicMode, CDN_PROTOCOL_TYPE protocol, + VIC_PXL_ENCODING_FORMAT format); + +#endif diff --git a/drivers/video/imx/hdp/defs.h b/drivers/video/imx/hdp/defs.h new file mode 100644 index 000000000000..12ad806aab29 --- /dev/null +++ b/drivers/video/imx/hdp/defs.h @@ -0,0 +1,56 @@ +/****************************************************************************** + * + * Copyright (C) 2015-2016 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * defs.h + * + ****************************************************************************** + */ + +#ifndef _DEFS_H_ +#define _DEFS_H_ + +typedef enum { + CDN_DPTX , + CDN_HDMITX_TYPHOON, + CDN_HDMITX_KIRAN, +} CDN_PROTOCOL_TYPE; + +#endif /*_DEFS_H_ */ diff --git a/drivers/video/imx/hdp/edid_parser.c b/drivers/video/imx/hdp/edid_parser.c new file mode 100644 index 000000000000..24aa7397910e --- /dev/null +++ b/drivers/video/imx/hdp/edid_parser.c @@ -0,0 +1,617 @@ +/****************************************************************************** + * + * Copyright (C) 2015-2016 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * edid_parser.c + * + ****************************************************************************** + */ + +#include "edid_parser.h" + +static EDID_PARSER_RESULT edid_parse_dtd(S_DTD_DATA *descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_DTD; + descriptor->header.tag = 0; + + descriptor->pixel_clock = raw_data[raw_data_index]; + descriptor->pixel_clock += + (unsigned short)raw_data[raw_data_index + 1] << 8; + + descriptor->horizontal_addressable_video = raw_data[raw_data_index + 2]; + descriptor->horizontal_addressable_video += + ((unsigned short)raw_data[raw_data_index + 4] & 0xF0) << 4; + descriptor->horizontal_blanking = raw_data[raw_data_index + 3]; + descriptor->horizontal_blanking += + ((unsigned short)raw_data[raw_data_index + 4] & 0x0F) << 8; + + descriptor->vertical_addressable_video = raw_data[raw_data_index + 5]; + descriptor->vertical_addressable_video += + ((unsigned short)raw_data[raw_data_index + 7] & 0xF0) << 4; + descriptor->vertical_blanking = raw_data[raw_data_index + 6]; + descriptor->vertical_blanking += + ((unsigned short)raw_data[raw_data_index + 7] & 0x0F) << 8; + + descriptor->horizontal_front_porch = raw_data[raw_data_index + 8]; + descriptor->horizontal_front_porch += + ((unsigned short)raw_data[raw_data_index + 11] & 0xC0) << 2; + descriptor->horizontal_sync_pulse_width = raw_data[raw_data_index + 9]; + descriptor->horizontal_sync_pulse_width += + ((unsigned short)raw_data[raw_data_index + 11] & 0x30) << 4; + + descriptor->vertical_front_porch = + (raw_data[raw_data_index + 10] & 0xF0) >> 4; + descriptor->vertical_front_porch += + (raw_data[raw_data_index + 11] & 0x0C) << 2; + descriptor->vertical_sync_pulse_width = + raw_data[raw_data_index + 10] & 0x0F; + descriptor->vertical_sync_pulse_width += + (raw_data[raw_data_index + 11] & 0x03) << 4; + + descriptor->horizontal_addressable_video_image_size = + raw_data[raw_data_index + 12]; + descriptor->horizontal_addressable_video_image_size += + ((unsigned short)raw_data[raw_data_index + 14] & 0xF0) << 4; + descriptor->vertical_addressable_video_image_size = + raw_data[raw_data_index + 13]; + descriptor->vertical_addressable_video_image_size += + ((unsigned short)raw_data[raw_data_index + 14] & 0x0F) << 8; + + descriptor->horizontal_border = raw_data[raw_data_index + 15]; + descriptor->vertical_border = raw_data[raw_data_index + 16]; + + descriptor->signal_features = raw_data[raw_data_index + 17]; + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_serial_number(S_SERIAL_NUMBER_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + descriptor->header.type = DESCRIPTOR_TYPE_SERIAL_NUMBER; + descriptor->header.tag = 0xFF; + + int idx; + for (idx = 0; idx < 13; idx++) + descriptor->serial_number[idx] = + raw_data[raw_data_index + 5 + idx]; + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_data_string(S_DATA_STRING_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + descriptor->header.type = DESCRIPTOR_TYPE_DATA_STRING; + descriptor->header.tag = 0xFE; + int idx; + for (idx = 0; idx < 13; idx++) + descriptor->data_string[idx] = + raw_data[raw_data_index + 5 + idx]; + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_range_limits(S_RANGE_LIMITS_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_RANGE_LIMITS; + descriptor->header.tag = 0xFD; + + descriptor->offset_flags = raw_data[raw_data_index + 4]; + descriptor->min_vertical_rate = raw_data[raw_data_index + 5]; + descriptor->max_vertical_rate = raw_data[raw_data_index + 6]; + descriptor->min_horizontal_rate = raw_data[raw_data_index + 7]; + descriptor->max_horizontal_rate = raw_data[raw_data_index + 8]; + descriptor->max_pixel_clock = raw_data[raw_data_index + 9]; + + switch (raw_data[raw_data_index + 10]) { + case 0x00: + descriptor->type = VIDEO_TIMING_DEFAULT_GTF; + break; + case 0x01: + descriptor->type = VIDEO_TIMING_RANGE_LIMITS_ONLY; + break; + case 0x02: + descriptor->type = VIDEO_TIMING_SECONDARY_GTF; + S_RANGE_LIMITS_VIDEO_TIMING_SECONDARY_GTF *timing_type_gtf = + (S_RANGE_LIMITS_VIDEO_TIMING_SECONDARY_GTF *) + descriptor->suport_flags; + timing_type_gtf->start_break_frequency = + raw_data[raw_data_index + 12]; + timing_type_gtf->c = raw_data[raw_data_index + 13]; + timing_type_gtf->m = raw_data[raw_data_index + 14]; + timing_type_gtf->m += + (unsigned short)raw_data[raw_data_index + 15] << 8; + timing_type_gtf->k = raw_data[raw_data_index + 16]; + timing_type_gtf->j = raw_data[raw_data_index + 17]; + break; + case 0x04: + descriptor->type = VIDEO_TIMING_CVT; + S_RANGE_LIMITS_VIDEO_TIMING_CVT *timing_type_cvt = + (S_RANGE_LIMITS_VIDEO_TIMING_CVT *)descriptor-> + suport_flags; + timing_type_cvt->cvt_version = raw_data[raw_data_index + 11]; + timing_type_cvt->additional_pixel_clock_precision = + raw_data[raw_data_index + 12] >> 2; + timing_type_cvt->max_active_pixels = + raw_data[raw_data_index + 13]; + timing_type_cvt->max_active_pixels += + (unsigned short)(raw_data[raw_data_index + 12] & 0x03) + << 8; + timing_type_cvt->supported_ar = + raw_data[raw_data_index + 14] >> 3; + timing_type_cvt->preferred_ar = + raw_data[raw_data_index + 15] >> 5; + timing_type_cvt->blanking_support = + (raw_data[raw_data_index + 15] & 0x18) >> 3; + timing_type_cvt->supported_scalling = + raw_data[raw_data_index + 16] >> 4; + timing_type_cvt->preferred_vertical_refresh_rate = + raw_data[raw_data_index + 17]; + break; + } + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_product_name(S_PRODUCT_NAME_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_PRODUCT_NAME; + descriptor->header.tag = 0xFC; + int idx; + for (idx = 0; idx < 13; idx++) + descriptor->product_name[idx] = + raw_data[raw_data_index + 5 + idx]; + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_color_point(S_COLOR_POINT_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_COLOR_POINT; + descriptor->header.tag = 0xFB; + descriptor->white_point_index_1 = raw_data[raw_data_index + 5]; + descriptor->white_x_1 = (raw_data[raw_data_index + 6] & 0x0C) >> 2; + descriptor->white_x_1 += + (unsigned short)raw_data[raw_data_index + 7] << 2; + descriptor->white_y_1 = raw_data[raw_data_index + 6] & 0x03; + descriptor->white_y_1 += + (unsigned short)raw_data[raw_data_index + 8] << 2; + descriptor->gamma_1 = raw_data[raw_data_index + 9]; + + descriptor->white_point_index_2 = raw_data[raw_data_index + 10]; + descriptor->white_x_2 = (raw_data[raw_data_index + 11] & 0x0C) >> 2; + descriptor->white_x_2 += + (unsigned short)raw_data[raw_data_index + 12] << 2; + descriptor->white_y_2 = raw_data[raw_data_index + 11] & 0x03; + descriptor->white_y_2 += + (unsigned short)raw_data[raw_data_index + 13] << 2; + descriptor->gamma_2 = raw_data[raw_data_index + 14]; + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_standard_timing(S_STANDARD_TIMING_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_STANDARD_TIMING; + descriptor->header.tag = 0xFA; + int idx; + for (idx = 0; idx < 6; idx++) { + descriptor->standard_timings[idx] = + raw_data[raw_data_index + 5 + 2 * idx]; + descriptor->standard_timings[idx] += + (unsigned short)raw_data[raw_data_index + 5 + 2 * idx + + 1]; + } + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_color_management(S_COLOR_MANAGEMENT_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_COLOR_MANAGEMENT; + descriptor->header.tag = 0xF9; + + descriptor->version = raw_data[raw_data_index + 5]; + + descriptor->red_a3 = raw_data[raw_data_index + 6]; + descriptor->red_a3 += (unsigned short)raw_data[raw_data_index + 7] << 8; + descriptor->red_a2 = raw_data[raw_data_index + 8]; + descriptor->red_a2 += (unsigned short)raw_data[raw_data_index + 9] << 8; + + descriptor->green_a3 = raw_data[raw_data_index + 10]; + descriptor->green_a3 += + (unsigned short)raw_data[raw_data_index + 11] << 8; + descriptor->green_a2 = raw_data[raw_data_index + 12]; + descriptor->green_a2 += + (unsigned short)raw_data[raw_data_index + 13] << 8; + + descriptor->blue_a3 = raw_data[raw_data_index + 14]; + descriptor->blue_a3 += + (unsigned short)raw_data[raw_data_index + 15] << 8; + descriptor->blue_a2 = raw_data[raw_data_index + 16]; + descriptor->blue_a2 += + (unsigned short)raw_data[raw_data_index + 17] << 8; + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_cvt_timing_codes(S_CVT_TIMING_CODES_DATA * + descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_CVT_TIMING_CODES; + descriptor->header.tag = 0xF8; + descriptor->version = raw_data[raw_data_index + 5]; + + int idx; + for (idx = 0; idx < 4; idx++) { + descriptor->addressable_lines[idx] = + raw_data[raw_data_index + 6 + idx * 3]; + descriptor->addressable_lines[idx] += + (unsigned short)(raw_data[raw_data_index + 7 + idx * 3] + & 0xF0) << 4; + descriptor->aspect_ratio[idx] = + (raw_data[raw_data_index + 7 + idx * 3] & 0x0C) >> 2; + descriptor->preferred_vertical_rate[idx] = + (raw_data[raw_data_index + 8 + idx * 3] & 0x60) >> 5; + descriptor->supported_vertical_rate_and_blanking[idx] = + raw_data[raw_data_index + 8 + idx * 3] & 0x1F; + } + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT +edid_parse_established_timings_3(S_ESTABLISHED_TIMINGS_3_DATA *descriptor, + unsigned char *raw_data) +{ + unsigned int raw_data_index = 0; + + descriptor->header.type = DESCRIPTOR_TYPE_ESTABLISHED_TIMINGS_3; + descriptor->header.tag = 0xF7; + descriptor->version = raw_data[raw_data_index + 5]; + int idx; + for (idx = 0; idx < 6; idx++) { + descriptor->established_timings[idx] = + raw_data[raw_data_index + 6 + idx]; + } + + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT edid_parse_dummy(S_DUMMY_DATA *descriptor, + unsigned char *raw_data) +{ + descriptor->header.type = DESCRIPTOR_TYPE_DUMMY; + descriptor->header.tag = 0x10; + return EDID_PARSER_SUCCESS; +} + +static EDID_PARSER_RESULT +edid_parse_manufacturer_specific(S_MANUFACTURER_SPECIFIC_DATA *descriptor, + unsigned char *raw_data, unsigned char tag) +{ + descriptor->header.type = DESCRIPTOR_TYPE_MANUFACTURER_SPECIFIC; + descriptor->header.tag = tag; + + return EDID_PARSER_SUCCESS; +} + +EDID_PARSER_RESULT edid_parse(S_EDID_DATA *edid, unsigned char *raw_data, + unsigned int len) +{ + unsigned int raw_data_index = 0; + unsigned char sum = 0; + /*CHECK SUM OF BYTES IN BLOCK0 */ + for (raw_data_index = 0; raw_data_index < EDID_LENGTH; raw_data_index++) + sum += raw_data[raw_data_index]; + + if (sum != 0) + return EDID_PARSER_ERROR; + + /*READ HEADER */ + for (raw_data_index = 0; raw_data_index < EDID_HEADER_LENGTH; + raw_data_index++) + edid->header[raw_data_index] = raw_data[raw_data_index]; + + /*READ VENDOR & PRODUCT IDENTIFICATION */ + /*manufacturer name */ + edid->manufacturer_name[0] = ((raw_data[8] & 0x7C) >> 2) + 0x40; + edid->manufacturer_name[1] = + ((raw_data[8] & 0x03) << 3) + ((raw_data[9] & 0xE0) >> 5) + + 0x40; + edid->manufacturer_name[2] = ((raw_data[9] & 0x1F)) + 0x40; + edid->manufacturer_name[3] = 0; + + /*product code */ + edid->product_code = (raw_data[10]); + edid->product_code += ((unsigned short)raw_data[11]) << 8; + + /*serial number */ + edid->serial_number = raw_data[12]; + edid->serial_number += (unsigned int)raw_data[13] << 8; + edid->serial_number += (unsigned int)raw_data[14] << 16; + edid->serial_number += (unsigned int)raw_data[15] << 24; + + /*week of manufacture */ + edid->week = raw_data[16]; + + /*year of manufacture */ + edid->year = raw_data[17]; + + /*EDID STRUCTURE VERSION & REVISION */ + edid->edid_version = ((unsigned short)raw_data[18] << 8) + raw_data[19]; + + /*BASIC DISPLAY PARAMETERS AND FEATURES */ + /*video input definition */ + edid->video_input_definition = raw_data[20]; + + /*horizontal screen size */ + edid->horizontal_size = raw_data[21]; + + /*vertical screen size */ + edid->vertical_size = raw_data[22]; + + /*display transfer characteristic */ + edid->gamma = raw_data[23]; + + /*feature support */ + edid->feature_support = raw_data[24]; + + /*COLOR CHARACTERISTIC */ + /*red */ + edid->chromacity_coorditates_red_x = (raw_data[25] & 0xC0) >> 6; + edid->chromacity_coorditates_red_x += (unsigned short)raw_data[27] << 2; + edid->chromacity_coorditates_red_y = (raw_data[25] & 0x30) >> 4; + edid->chromacity_coorditates_red_y += (unsigned short)raw_data[28] << 2; + + /*green */ + edid->chromacity_coorditates_green_x = (raw_data[25] & 0x0C) >> 2; + edid->chromacity_coorditates_green_x += + (unsigned short)raw_data[29] << 2; + edid->chromacity_coorditates_green_y = (raw_data[25] & 0x03); + edid->chromacity_coorditates_green_y += + (unsigned short)raw_data[30] << 2; + + /*blue */ + edid->chromacity_coorditates_blue_x = (raw_data[26] & 0xC0) >> 6; + edid->chromacity_coorditates_blue_x += + (unsigned short)raw_data[31] << 2; + edid->chromacity_coorditates_blue_y = (raw_data[26] & 0x30) >> 4; + edid->chromacity_coorditates_blue_y += + (unsigned short)raw_data[32] << 2; + + /*blue */ + edid->chromacity_coorditates_white_x = (raw_data[26] & 0x0C) >> 2; + edid->chromacity_coorditates_white_x += + (unsigned short)raw_data[33] << 2; + edid->chromacity_coorditates_white_y = (raw_data[26] & 0x03); + edid->chromacity_coorditates_white_y += + (unsigned short)raw_data[34] << 2; + + /*ESTABLISHED TIMINGS */ + edid->established_timing_1 = raw_data[35]; + edid->established_timing_2 = raw_data[36]; + edid->manufacturer_timing = raw_data[37]; + + /*STANDARD TIMINGS */ + for (raw_data_index = 0; raw_data_index < 8; raw_data_index++) { + edid->standard_timings[raw_data_index] = + raw_data[38 + (2 * raw_data_index)]; + edid->standard_timings[raw_data_index] += + (unsigned short)raw_data[38 + (2 * raw_data_index + 1)]; + } + /*extensions */ + edid->extensions = raw_data[126]; + + /*DESCRIPTORS */ + unsigned int descriptor_index; + raw_data_index = 54; + for (descriptor_index = 0; descriptor_index < 4; descriptor_index++) { + if (raw_data[raw_data_index] == 0 && + raw_data[raw_data_index] == 0) { + /*display descriptor found */ + unsigned char tag = raw_data[raw_data_index + 3]; + if (tag == 0xFF) { + /*display product serial number */ + S_SERIAL_NUMBER_DATA *descriptor = + (S_SERIAL_NUMBER_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_serial_number + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xFE) { + /*alphanumeric data string */ + S_DATA_STRING_DATA *descriptor = + (S_DATA_STRING_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_data_string + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xFD) { + /*display range limits */ + S_RANGE_LIMITS_DATA *descriptor = + (S_RANGE_LIMITS_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_range_limits + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xFC) { + /*display product name */ + S_PRODUCT_NAME_DATA *descriptor = + (S_PRODUCT_NAME_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_product_name + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xFB) { + /*color point data */ + S_COLOR_POINT_DATA *descriptor = + (S_COLOR_POINT_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_color_point + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xFA) { + /*standard timing identifications */ + S_STANDARD_TIMING_DATA *descriptor = + (S_STANDARD_TIMING_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_standard_timing + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xF9) { + /*display color management (DCM) */ + S_COLOR_MANAGEMENT_DATA *descriptor = + (S_COLOR_MANAGEMENT_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_color_management + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xF8) { + /*CVT 3 byte timing codes */ + S_CVT_TIMING_CODES_DATA *descriptor = + (S_CVT_TIMING_CODES_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_cvt_timing_codes + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0xF7) { + /*established timings III */ + S_ESTABLISHED_TIMINGS_3_DATA *descriptor = + (S_ESTABLISHED_TIMINGS_3_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_established_timings_3 + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag == 0x10) { + /*dummy */ + S_DUMMY_DATA *descriptor = + (S_DUMMY_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_dummy + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + + } else if (tag <= 0x0F) { + /*manufacturer specific data */ + S_MANUFACTURER_SPECIFIC_DATA *descriptor = + (S_MANUFACTURER_SPECIFIC_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_manufacturer_specific + (descriptor, raw_data + raw_data_index, + tag) != EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + } + } else { + /*detailed timing definition */ + S_DTD_DATA *descriptor = + (S_DTD_DATA *)edid-> + descriptors[descriptor_index]; + if (edid_parse_dtd + (descriptor, + raw_data + raw_data_index) != + EDID_PARSER_SUCCESS) + return EDID_PARSER_ERROR; + } + raw_data_index += 18; + } + + return EDID_PARSER_SUCCESS; +} diff --git a/drivers/video/imx/hdp/edid_parser.h b/drivers/video/imx/hdp/edid_parser.h new file mode 100644 index 000000000000..13eb0b1882bc --- /dev/null +++ b/drivers/video/imx/hdp/edid_parser.h @@ -0,0 +1,297 @@ +/****************************************************************************** + * + * Copyright (C) 2015-2016 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * edid_parser.h + * + ****************************************************************************** + */ + +#ifndef EDID_PARSER_H +#define EDID_PARSER_H + +#define MAX_DESCRIPTOR_LENGTH 36 +#define MAX_RANGE_LIMITS_VIDEO_TIMING_LENGTH 12 +#define EDID_HEADER_LENGTH 8 +#define EDID_LENGTH 128 + +typedef enum { + EDID_PARSER_SUCCESS, + EDID_PARSER_ERROR, +} EDID_PARSER_RESULT; + +typedef enum { + DESCRIPTOR_TYPE_DTD, + DESCRIPTOR_TYPE_SERIAL_NUMBER, + DESCRIPTOR_TYPE_DATA_STRING, + DESCRIPTOR_TYPE_RANGE_LIMITS, + DESCRIPTOR_TYPE_PRODUCT_NAME, + DESCRIPTOR_TYPE_COLOR_POINT, + DESCRIPTOR_TYPE_STANDARD_TIMING, + DESCRIPTOR_TYPE_COLOR_MANAGEMENT, + DESCRIPTOR_TYPE_CVT_TIMING_CODES, + DESCRIPTOR_TYPE_ESTABLISHED_TIMINGS_3, + DESCRIPTOR_TYPE_DUMMY, + DESCRIPTOR_TYPE_MANUFACTURER_SPECIFIC +} EDID_DESCRIPTOR_TYPE; + +typedef enum { + VIDEO_TIMING_DEFAULT_GTF, + VIDEO_TIMING_RANGE_LIMITS_ONLY, + VIDEO_TIMING_SECONDARY_GTF, + VIDEO_TIMING_CVT, +} RANGE_LIMITS_VIDEO_TIMING_TYPE; + +/** + * \brief Common descriptor header structure + */ +typedef struct { + EDID_DESCRIPTOR_TYPE type; + unsigned char tag; + +} S_DESCRIPTOR_HEADER_DATA; +/** + * \brief Detailed Timing Descriptor (DTD) structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned short pixel_clock; + unsigned short horizontal_addressable_video; + unsigned short horizontal_blanking; + unsigned short vertical_addressable_video; + unsigned short vertical_blanking; + unsigned short horizontal_front_porch; + unsigned short horizontal_sync_pulse_width; + unsigned short vertical_front_porch; + unsigned short vertical_sync_pulse_width; + unsigned short horizontal_addressable_video_image_size; + unsigned short vertical_addressable_video_image_size; + unsigned char horizontal_border; + unsigned char vertical_border; + unsigned char signal_features; +} S_DTD_DATA; + +/** + * \brief Serial Number Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char serial_number[13]; + +} S_SERIAL_NUMBER_DATA; + +/** + * \brief Data String Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + char data_string[13]; + +} S_DATA_STRING_DATA; + +/** + * \brief Range Limits Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char offset_flags; + unsigned char min_vertical_rate; + unsigned char max_vertical_rate; + unsigned char min_horizontal_rate; + unsigned char max_horizontal_rate; + unsigned char max_pixel_clock; + RANGE_LIMITS_VIDEO_TIMING_TYPE type; + unsigned char suport_flags[MAX_RANGE_LIMITS_VIDEO_TIMING_LENGTH]; +} S_RANGE_LIMITS_DATA; + +/** + * \brief Range Limits Secondary GTF Flags structure + */ +typedef struct { + unsigned char start_break_frequency; + unsigned char c; + unsigned short m; + unsigned char k; + unsigned char j; + +} S_RANGE_LIMITS_VIDEO_TIMING_SECONDARY_GTF; + +/** + * \brief Range Limits CVT Flags structure + */ +typedef struct { + unsigned char cvt_version; + unsigned char additional_pixel_clock_precision; + unsigned short max_active_pixels; + unsigned char supported_ar; + unsigned char preferred_ar; + unsigned char blanking_support; + unsigned char supported_scalling; + unsigned char preferred_vertical_refresh_rate; +} S_RANGE_LIMITS_VIDEO_TIMING_CVT; + +/** + * \brief Product Name Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + char product_name[13]; + +} S_PRODUCT_NAME_DATA; + +/** + * \brief Color point Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char white_point_index_1; + unsigned short white_x_1; + unsigned short white_y_1; + unsigned char gamma_1; + unsigned char white_point_index_2; + unsigned short white_x_2; + unsigned short white_y_2; + unsigned char gamma_2; +} S_COLOR_POINT_DATA; + +/** + * \brief Standard Timing Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned short standard_timings[6]; +} S_STANDARD_TIMING_DATA; + +/** + * \brief Color Management Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char version; + unsigned short red_a3; + unsigned short red_a2; + unsigned short green_a3; + unsigned short green_a2; + unsigned short blue_a3; + unsigned short blue_a2; +} S_COLOR_MANAGEMENT_DATA; + +/** + * \brief CVT 3 Byte Code Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char version; + unsigned short addressable_lines[4]; + unsigned char aspect_ratio[4]; + unsigned char preferred_vertical_rate[4]; + unsigned char supported_vertical_rate_and_blanking[4]; + +} S_CVT_TIMING_CODES_DATA; + +/** + * \brief Established Timings 3 Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char version; + unsigned char established_timings[6]; +} S_ESTABLISHED_TIMINGS_3_DATA; + +/** + * \brief Dummy Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; +} S_DUMMY_DATA; + +/** + * \brief Manufacturer Specific Descriptor structure + */ +typedef struct { + S_DESCRIPTOR_HEADER_DATA header; + unsigned char desc_data[18]; +} S_MANUFACTURER_SPECIFIC_DATA; + +/** + * \brief CEA-861 extension structure + */ +typedef struct { + unsigned char revision; + unsigned char underscan; + unsigned char audio; +} S_CEA861_DATA; + +/** + * \brief Extended Display Identification Data (EDID) structure + */ +typedef struct { + unsigned char header[8]; + char manufacturer_name[4]; + unsigned short product_code; + unsigned int serial_number; + unsigned char week; + unsigned short year; + unsigned short edid_version; + unsigned char video_input_definition; + unsigned char horizontal_size; + unsigned char vertical_size; + unsigned char gamma; + unsigned char feature_support; + unsigned short chromacity_coorditates_red_x; + unsigned short chromacity_coorditates_red_y; + unsigned short chromacity_coorditates_green_x; + unsigned short chromacity_coorditates_green_y; + unsigned short chromacity_coorditates_blue_x; + unsigned short chromacity_coorditates_blue_y; + unsigned short chromacity_coorditates_white_x; + unsigned short chromacity_coorditates_white_y; + unsigned char established_timing_1; + unsigned char established_timing_2; + unsigned char manufacturer_timing; + unsigned short standard_timings[8]; + unsigned char descriptors[4][MAX_DESCRIPTOR_LENGTH]; + unsigned char extensions; +} S_EDID_DATA; + +EDID_PARSER_RESULT edid_parse(S_EDID_DATA *edid, unsigned char *raw_data, + unsigned int len); + +#endif /* EDID_PARSER_H */ diff --git a/drivers/video/imx/hdp/externs.h b/drivers/video/imx/hdp/externs.h index a222d2658edc..fe4b13e4755c 100644 --- a/drivers/video/imx/hdp/externs.h +++ b/drivers/video/imx/hdp/externs.h @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/general_handler.h b/drivers/video/imx/hdp/general_handler.h index 3656ef8848e8..4a3132cf06e8 100644 --- a/drivers/video/imx/hdp/general_handler.h +++ b/drivers/video/imx/hdp/general_handler.h @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * @@ -66,6 +66,7 @@ #define GENERAL_WRITE_REGISTER 0x05 #define GENERAL_WRITE_FIELD 0x06 #define GENERAL_READ_REGISTER 0x07 +#define GENERAL_GET_HPD_STATE 0x11 #define GENERAL_TEST_TRNG_SIMPLE 0xF0 diff --git a/drivers/video/imx/hdp/hdmi.h b/drivers/video/imx/hdp/hdmi.h new file mode 100644 index 000000000000..a8989829f260 --- /dev/null +++ b/drivers/video/imx/hdp/hdmi.h @@ -0,0 +1,124 @@ +/****************************************************************************** + * + * Copyright (C) 2015-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * hdmi.h + * + ****************************************************************************** + */ + +#ifndef _HDMI__ +#define _HDMI__ +/* ONLY ENUMS AND #DEFINES IN THIS FILE * + * THIS FILE WILL BE USED IN HOST'S API */ + +#define EDID_SLAVE_ADDRESS 0x50 +#define EDID_SEGMENT_SLAVE_ADDRESS 0x30 +#define SCDC_SLAVE_ADDRESS 0x54 + +typedef enum { + HDMI_TX_READ, + HDMI_TX_WRITE, + HDMI_TX_UPDATE_READ, + HDMI_TX_EDID, + HDMI_TX_EVENTS, + HDMI_TX_HPD_STATUS, + HDMI_TX_DEBUG_ECHO = 0xAA, + HDMI_TX_TEST = 0xBB, + HDMI_TX_EDID_INTERNAL = 0xF0, +} HDMI_TX_OPCODE; + +typedef enum { + HDMI_I2C_ACK, + HDMI_I2C_NACK, + HDMI_I2C_TO, + HDMI_I2C_ARB_LOST, + HDMI_I2C_RRTO, + HDMI_I2C_RRT, + /** when i2c hardware didn't respond after some time */ + HDMI_I2C_HW_TO, + HDMI_I2C_ERR /*unspecified error */ +} HDMI_I2C_STATUS; + +typedef enum { + HDMI_RX_SET_EDID, + HDMI_RX_SCDC_SET, + HDMI_RX_SCDC_GET, + HDMI_RX_READ_EVENTS, + HDMI_RX_SET_HPD, + + HDMI_RX_DEBUG_ECHO = 0xAA, + HDMI_RX_TEST = 0xBB, +} HDMI_RX_OPCODE; + +typedef enum { + HDMI_SCDC_SINK_VER, + HDMI_SCDC_SOURCE_VER, +} HDMI_SCDC_FIELD; + +/*/////////////////////////////////////// */ +/*/////////////////////////////////////// */ +typedef struct { + unsigned char sink_ver; + unsigned char manufacturer_oui_1; + unsigned char manufacturer_oui_2; + unsigned char manufacturer_oui_3; + unsigned char devId[8]; + unsigned char hardware_major_rev; + unsigned char hardware_minor_rev; + unsigned char software_major_rev; + unsigned char software_minor_rev; + unsigned char manufacturerSpecific[34]; +} S_HDMI_SCDC_SET_MSG; + +typedef struct { + unsigned char source_ver; + unsigned char TMDS_Config; + unsigned char config_0; + unsigned char manufacturerSpecific[34]; +} S_HDMI_SCDC_GET_MSG; + +/*hpd events location */ +#define HDMI_RX_EVENT_5V_HIGH 0 +#define HDMI_RX_EVENT_5V_LOW 1 +#define HDMI_TX_EVENT_reserved 2 +#define HDMI_RX_EVENT_5V_VAL 3 + +#endif /*_HDMI__ */ diff --git a/drivers/video/imx/hdp/mhl_hdtx_top.h b/drivers/video/imx/hdp/mhl_hdtx_top.h new file mode 100644 index 000000000000..ee105f824891 --- /dev/null +++ b/drivers/video/imx/hdp/mhl_hdtx_top.h @@ -0,0 +1,220 @@ +/****************************************************************************** + * + * Copyright (C) 2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * mhl_hdtx_top.h + * + ****************************************************************************** + */ + +#ifndef MHL_HDTX_TOP_H_ +#define MHL_HDTX_TOP_H_ + +/* register SCHEDULER_H_SIZE */ +#define SCHEDULER_H_SIZE 0 +#define F_H_BLANK_SIZE(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_H_BLANK_SIZE_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) +#define F_H_ACTIVE_SIZE(x) (((x) & ((1 << 16) - 1)) << 16) +#define F_H_ACTIVE_SIZE_RD(x) (((x) & (((1 << 16) - 1) << 16)) >> 16) + +/* register SCHEDULER_V_SIZE */ +#define SCHEDULER_V_SIZE 1 +#define F_V_BLANK_SIZE(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_V_BLANK_SIZE_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) +#define F_V_ACTIVE_SIZE(x) (((x) & ((1 << 16) - 1)) << 16) +#define F_V_ACTIVE_SIZE_RD(x) (((x) & (((1 << 16) - 1) << 16)) >> 16) + +/* register SCHEDULER_KEEP_OUT */ +#define SCHEDULER_KEEP_OUT 2 +#define F_HKEEP_OUT(x) (((x) & ((1 << 9) - 1)) << 0) +#define F_HKEEP_OUT_RD(x) (((x) & (((1 << 9) - 1) << 0)) >> 0) +#define F_VKEEP_OUT_START(x) (((x) & ((1 << 11) - 1)) << 9) +#define F_VKEEP_OUT_START_RD(x) (((x) & (((1 << 11) - 1) << 9)) >> 9) +#define F_VKEEP_OUT_ZONE(x) (((x) & ((1 << 8) - 1)) << 20) +#define F_VKEEP_OUT_ZONE_RD(x) (((x) & (((1 << 8) - 1) << 20)) >> 20) + +/* register HDTX_SIGNAL_FRONT_WIDTH */ +#define HDTX_SIGNAL_FRONT_WIDTH 3 +#define F_HFRONT(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_HFRONT_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) +#define F_VFRONT(x) (((x) & ((1 << 16) - 1)) << 16) +#define F_VFRONT_RD(x) (((x) & (((1 << 16) - 1) << 16)) >> 16) + +/* register HDTX_SIGNAL_SYNC_WIDTH */ +#define HDTX_SIGNAL_SYNC_WIDTH 4 +#define F_HSYNC(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_HSYNC_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) +#define F_VSYNC(x) (((x) & ((1 << 16) - 1)) << 16) +#define F_VSYNC_RD(x) (((x) & (((1 << 16) - 1) << 16)) >> 16) + +/* register HDTX_SIGNAL_BACK_WIDTH */ +#define HDTX_SIGNAL_BACK_WIDTH 5 +#define F_HBACK(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_HBACK_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) +#define F_VBACK(x) (((x) & ((1 << 16) - 1)) << 16) +#define F_VBACK_RD(x) (((x) & (((1 << 16) - 1) << 16)) >> 16) + +/* register HDTX_CONTROLLER */ +#define HDTX_CONTROLLER 6 +#define F_HDMI_MODE(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_HDMI_MODE_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) +#define F_VIF_DATA_WIDTH(x) (((x) & ((1 << 2) - 1)) << 2) +#define F_VIF_DATA_WIDTH_RD(x) (((x) & (((1 << 2) - 1) << 2)) >> 2) +#define F_AUTO_MODE(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_AUTO_MODE_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_IL_PROG(x) (((x) & ((1 << 2) - 1)) << 5) +#define F_IL_PROG_RD(x) (((x) & (((1 << 2) - 1) << 5)) >> 5) +#define F_PIC_3D(x) (((x) & ((1 << 4) - 1)) << 7) +#define F_PIC_3D_RD(x) (((x) & (((1 << 4) - 1) << 7)) >> 7) +#define F_BCH_EN(x) (((x) & ((1 << 1) - 1)) << 11) +#define F_BCH_EN_RD(x) (((x) & (((1 << 1) - 1) << 11)) >> 11) +#define F_GCP_EN(x) (((x) & ((1 << 1) - 1)) << 12) +#define F_GCP_EN_RD(x) (((x) & (((1 << 1) - 1) << 12)) >> 12) +#define F_SET_AVMUTE(x) (((x) & ((1 << 1) - 1)) << 13) +#define F_SET_AVMUTE_RD(x) (((x) & (((1 << 1) - 1) << 13)) >> 13) +#define F_CLEAR_AVMUTE(x) (((x) & ((1 << 1) - 1)) << 14) +#define F_CLEAR_AVMUTE_RD(x) (((x) & (((1 << 1) - 1) << 14)) >> 14) +#define F_DATA_EN(x) (((x) & ((1 << 1) - 1)) << 15) +#define F_DATA_EN_RD(x) (((x) & (((1 << 1) - 1) << 15)) >> 15) +#define F_HDMI_ENCODING(x) (((x) & ((1 << 2) - 1)) << 16) +#define F_HDMI_ENCODING_RD(x) (((x) & (((1 << 2) - 1) << 16)) >> 16) +#define F_HDMI2_PREAMBLE_EN(x) (((x) & ((1 << 1) - 1)) << 18) +#define F_HDMI2_PREAMBLE_EN_RD(x) (((x) & (((1 << 1) - 1) << 18)) >> 18) +#define F_HDMI2_CTRL_IL_MODE(x) (((x) & ((1 << 1) - 1)) << 19) +#define F_HDMI2_CTRL_IL_MODE_RD(x) (((x) & (((1 << 1) - 1) << 19)) >> 19) + +/* register HDTX_HDCP */ +#define HDTX_HDCP 7 +#define F_HDTX_HDCP_SELECT(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_HDTX_HDCP_SELECT_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) +#define F_ENC_BIT(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_ENC_BIT_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_HDCP_ENABLE_1P1_FEATURES(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_HDCP_ENABLE_1P1_FEATURES_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) +#define F_HDCP_DELAY_FIFO_SW_RST(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_HDCP_DELAY_FIFO_SW_RST_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_HDCP_DELAY_FIFO_SW_START(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_HDCP_DELAY_FIFO_SW_START_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_HDCP_DOUBLE_FIFO_SW_RST(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_HDCP_DOUBLE_FIFO_SW_RST_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_HDCP_SINGLE_FIFO_SW_RST(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_HDCP_SINGLE_FIFO_SW_RST_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) +#define F_HDCP_DELAY_FIFO_AFULL_THR(x) (((x) & ((1 << 4) - 1)) << 8) +#define F_HDCP_DELAY_FIFO_AFULL_THR_RD(x) (((x) & (((1 << 4) - 1) << 8)) >> 8) +#define F_HDCP_CTRL_SW_RST(x) (((x) & ((1 << 1) - 1)) << 12) +#define F_HDCP_CTRL_SW_RST_RD(x) (((x) & (((1 << 1) - 1) << 12)) >> 12) +#define F_HDCP_CTRL_IL_MODE(x) (((x) & ((1 << 1) - 1)) << 13) +#define F_HDCP_CTRL_IL_MODE_RD(x) (((x) & (((1 << 1) - 1) << 13)) >> 13) + +/* register HDTX_HPD */ +#define HDTX_HPD 8 +#define F_HPD_VALID_WIDTH(x) (((x) & ((1 << 12) - 1)) << 0) +#define F_HPD_VALID_WIDTH_RD(x) (((x) & (((1 << 12) - 1) << 0)) >> 0) +#define F_HPD_GLITCH_WIDTH(x) (((x) & ((1 << 8) - 1)) << 12) +#define F_HPD_GLITCH_WIDTH_RD(x) (((x) & (((1 << 8) - 1) << 12)) >> 12) + +/* register HDTX_CLOCK_REG_0 */ +#define HDTX_CLOCK_REG_0 9 +#define F_DATA_REGISTER_VAL_0(x) (((x) & ((1 << 20) - 1)) << 0) +#define F_DATA_REGISTER_VAL_0_RD(x) (((x) & (((1 << 20) - 1) << 0)) >> 0) + +/* register HDTX_CLOCK_REG_1 */ +#define HDTX_CLOCK_REG_1 10 +#define F_DATA_REGISTER_VAL_1(x) (((x) & ((1 << 20) - 1)) << 0) +#define F_DATA_REGISTER_VAL_1_RD(x) (((x) & (((1 << 20) - 1) << 0)) >> 0) + +/* register HPD_PLUG_IN */ +#define HPD_PLUG_IN 11 +#define F_FILTER_HPD(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_FILTER_HPD_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register HDCP_IN */ +#define HDCP_IN 12 +#define F_HDCP_ESS_STATE(x) (((x) & ((1 << 4) - 1)) << 0) +#define F_HDCP_ESS_STATE_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +#define F_HDCP_DOUBLE_FIFO_WFULL(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_HDCP_DOUBLE_FIFO_WFULL_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_HDCP_DOUBLE_FIFO_REMPTY(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_HDCP_DOUBLE_FIFO_REMPTY_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_HDCP_DOUBLE_FIFO_OVERRUN(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_HDCP_DOUBLE_FIFO_OVERRUN_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_HDCP_DOUBLE_FIFO_UNDERRUN(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_HDCP_DOUBLE_FIFO_UNDERRUN_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) +#define F_HDCP_DELAY_FIFO_EMPTY(x) (((x) & ((1 << 1) - 1)) << 8) +#define F_HDCP_DELAY_FIFO_EMPTY_RD(x) (((x) & (((1 << 1) - 1) << 8)) >> 8) +#define F_HDCP_DELAY_FIFO_FULL(x) (((x) & ((1 << 1) - 1)) << 9) +#define F_HDCP_DELAY_FIFO_FULL_RD(x) (((x) & (((1 << 1) - 1) << 9)) >> 9) +#define F_HDCP_SINGLE_FIFO_WFULL(x) (((x) & ((1 << 2) - 1)) << 10) +#define F_HDCP_SINGLE_FIFO_WFULL_RD(x) (((x) & (((1 << 2) - 1) << 10)) >> 10) +#define F_HDCP_SINGLE_FIFO_REMPTY(x) (((x) & ((1 << 2) - 1)) << 12) +#define F_HDCP_SINGLE_FIFO_REMPTY_RD(x) (((x) & (((1 << 2) - 1) << 12)) >> 12) +#define F_HDCP_SINGLE_FIFO_OVERRUN(x) (((x) & ((1 << 2) - 1)) << 14) +#define F_HDCP_SINGLE_FIFO_OVERRUN_RD(x) (((x) & (((1 << 2) - 1) << 14)) >> 14) +#define F_HDCP_SINGLE_FIFO_UNDERRUN(x) (((x) & ((1 << 2) - 1)) << 16) +#define F_HDCP_SINGLE_FIFO_UNDERRUN_RD(x) (((x) & (((1 << 2) - 1) << 16)) >> 16) + +/* register GCP_FORCE_COLOR_DEPTH_CODING */ +#define GCP_FORCE_COLOR_DEPTH_CODING 13 +#define F_COLOR_DEPTH_VAL(x) (((x) & ((1 << 4) - 1)) << 0) +#define F_COLOR_DEPTH_VAL_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +#define F_COLOR_DEPTH_FORCE(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_COLOR_DEPTH_FORCE_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_DEFAULT_PHASE_VAL(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_DEFAULT_PHASE_VAL_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) + +/* register SSCP_POSITIONING */ +#define SSCP_POSITIONING 14 +#define F_SSCP_ROW_VAL(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_SSCP_ROW_VAL_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) +#define F_SSCP_COL_VAL(x) (((x) & ((1 << 16) - 1)) << 16) +#define F_SSCP_COL_VAL_RD(x) (((x) & (((1 << 16) - 1) << 16)) >> 16) + +/* register HDCP_WIN_OF_OPP_POSITION */ +#define HDCP_WIN_OF_OPP_POSITION 15 +#define F_HDCP_WIN_OF_OPP_START(x) (((x) & ((1 << 10) - 1)) << 0) +#define F_HDCP_WIN_OF_OPP_START_RD(x) (((x) & (((1 << 10) - 1) << 0)) >> 0) +#define F_HDCP_WIN_OF_OPP_SIZE(x) (((x) & ((1 << 6) - 1)) << 10) +#define F_HDCP_WIN_OF_OPP_SIZE_RD(x) (((x) & (((1 << 6) - 1) << 10)) >> 10) + +#endif /*MHL_HDTX_TOP */ diff --git a/drivers/video/imx/hdp/opcodes.h b/drivers/video/imx/hdp/opcodes.h index e0e7d93412b1..fdc661c119bc 100644 --- a/drivers/video/imx/hdp/opcodes.h +++ b/drivers/video/imx/hdp/opcodes.h @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/source_car.h b/drivers/video/imx/hdp/source_car.h new file mode 100644 index 000000000000..1a5f85f8aaad --- /dev/null +++ b/drivers/video/imx/hdp/source_car.h @@ -0,0 +1,179 @@ +/****************************************************************************** + * + * Copyright (C) 2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * source_car.h + * + ****************************************************************************** + */ + +#ifndef SOURCE_CAR_H_ +#define SOURCE_CAR_H_ + +/* register SOURCE_HDTX_CAR */ +#define SOURCE_HDTX_CAR 0 +#define F_HDTX_PIXEL_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_HDTX_PIXEL_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_HDTX_PIXEL_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_HDTX_PIXEL_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_HDTX_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_HDTX_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_HDTX_SYS_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_HDTX_SYS_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) +#define F_HDTX_PHY_DATA_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_HDTX_PHY_DATA_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_HDTX_PHY_DATA_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_HDTX_PHY_DATA_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_HDTX_PHY_CHAR_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_HDTX_PHY_CHAR_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_HDTX_PHY_CHAR_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_HDTX_PHY_CHAR_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) + +/* register SOURCE_DPTX_CAR */ +#define SOURCE_DPTX_CAR 1 +#define F_CFG_DPTX_VIF_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_CFG_DPTX_VIF_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_CFG_DPTX_VIF_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_CFG_DPTX_VIF_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_DPTX_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_DPTX_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_DPTX_SYS_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_DPTX_SYS_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) +#define F_SOURCE_AUX_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_SOURCE_AUX_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_SOURCE_AUX_SYS_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_SOURCE_AUX_SYS_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_DPTX_PHY_CHAR_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_DPTX_PHY_CHAR_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_DPTX_PHY_CHAR_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_DPTX_PHY_CHAR_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) +#define F_DPTX_PHY_DATA_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 8) +#define F_DPTX_PHY_DATA_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 8)) >> 8) +#define F_DPTX_PHY_DATA_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 9) +#define F_DPTX_PHY_DATA_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 9)) >> 9) +#define F_DPTX_FRMR_DATA_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 10) +#define F_DPTX_FRMR_DATA_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 10)) >> 10) +#define F_DPTX_FRMR_DATA_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 11) +#define F_DPTX_FRMR_DATA_CLK_RSTN_EN_RD(x) \ + (((x) & (((1 << 1) - 1) << 11)) >> 11) + +/* register SOURCE_PHY_CAR */ +#define SOURCE_PHY_CAR 2 +#define F_SOURCE_PHY_DATA_OUT_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_PHY_DATA_OUT_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_DATA_OUT_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_PHY_DATA_OUT_CLK_RSTN_EN_RD(x) \ + (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_SOURCE_PHY_CHAR_OUT_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_SOURCE_PHY_CHAR_OUT_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_SOURCE_PHY_CHAR_OUT_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_SOURCE_PHY_CHAR_OUT_CLK_RSTN_EN_RD(x) \ + (((x) & (((1 << 1) - 1) << 3)) >> 3) + +/* register SOURCE_CEC_CAR */ +#define SOURCE_CEC_CAR 3 +#define F_SOURCE_CEC_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_CEC_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_CEC_SYS_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_CEC_SYS_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) + +/* register SOURCE_CBUS_CAR */ +#define SOURCE_CBUS_CAR 4 +#define F_SOURCE_CBUS_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_CBUS_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_CBUS_SYS_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_CBUS_SYS_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) + +/* register SOURCE_PKT_CAR */ +#define SOURCE_PKT_CAR 6 +#define F_SOURCE_PKT_DATA_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_PKT_DATA_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_PKT_DATA_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_PKT_DATA_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_SOURCE_PKT_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_SOURCE_PKT_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_SOURCE_PKT_SYS_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_SOURCE_PKT_SYS_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) + +/* register SOURCE_AIF_CAR */ +#define SOURCE_AIF_CAR 7 +#define F_SOURCE_AIF_PKT_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_AIF_PKT_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_AIF_PKT_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_AIF_PKT_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_SOURCE_AIF_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_SOURCE_AIF_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_SOURCE_AIF_SYS_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_SOURCE_AIF_SYS_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) +#define F_SPDIF_CDR_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_SPDIF_CDR_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_SPDIF_CDR_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_SPDIF_CDR_CLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_SPDIF_MCLK_EN(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_SPDIF_MCLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_SPDIF_MCLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_SPDIF_MCLK_RSTN_EN_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) + +/* register SOURCE_CIPHER_CAR */ +#define SOURCE_CIPHER_CAR 8 +#define F_SOURCE_CIPHER_CHAR_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_CIPHER_CHAR_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_CIPHER_CHAR_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_CIPHER_CHAR_CLK_RSTN_EN_RD(x) \ + (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_SOURCE_CIPHER_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_SOURCE_CIPHER_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_SOURCE_CIPHER_SYSTEM_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_SOURCE_CIPHER_SYSTEM_CLK_RSTN_EN_RD(x) \ + (((x) & (((1 << 1) - 1) << 3)) >> 3) + +/* register SOURCE_CRYPTO_CAR */ +#define SOURCE_CRYPTO_CAR 9 +#define F_SOURCE_CRYPTO_SYS_CLK_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SOURCE_CRYPTO_SYS_CLK_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_SOURCE_CRYPTO_SYS_CLK_RSTN_EN(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_SOURCE_CRYPTO_SYS_CLK_RSTN_EN_RD(x) \ + (((x) & (((1 << 1) - 1) << 1)) >> 1) + +#endif /*SOURCE_CAR */ diff --git a/drivers/video/imx/hdp/source_phy.h b/drivers/video/imx/hdp/source_phy.h new file mode 100644 index 000000000000..540809db9713 --- /dev/null +++ b/drivers/video/imx/hdp/source_phy.h @@ -0,0 +1,181 @@ +/****************************************************************************** + * + * Copyright (C) 2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * source_phy.h + * + ****************************************************************************** + */ + +#ifndef SOURCE_PHY_H_ +#define SOURCE_PHY_H_ + +/* register SHIFT_PATTERN_IN_3_0 */ +#define SHIFT_PATTERN_IN_3_0 0 +#define F_SOURCE_PHY_SHIFT_PATTERN0(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SOURCE_PHY_SHIFT_PATTERN0_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_SHIFT_PATTERN1(x) (((x) & ((1 << 8) - 1)) << 8) +#define F_SOURCE_PHY_SHIFT_PATTERN1_RD(x) (((x) & (((1 << 8) - 1) << 8)) >> 8) +#define F_SOURCE_PHY_SHIFT_PATTERN2(x) (((x) & ((1 << 8) - 1)) << 16) +#define F_SOURCE_PHY_SHIFT_PATTERN2_RD(x) (((x) & (((1 << 8) - 1) << 16)) >> 16) +#define F_SOURCE_PHY_SHIFT_PATTERN3(x) (((x) & ((1 << 8) - 1)) << 24) +#define F_SOURCE_PHY_SHIFT_PATTERN3_RD(x) (((x) & (((1 << 8) - 1) << 24)) >> 24) + +/* register SHIFT_PATTERN_IN_4_7 */ +#define SHIFT_PATTERN_IN_4_7 1 +#define F_SOURCE_PHY_SHIFT_PATTERN4(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SOURCE_PHY_SHIFT_PATTERN4_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_SHIFT_PATTERN5(x) (((x) & ((1 << 8) - 1)) << 8) +#define F_SOURCE_PHY_SHIFT_PATTERN5_RD(x) (((x) & (((1 << 8) - 1) << 8)) >> 8) +#define F_SOURCE_PHY_SHIFT_PATTERN6(x) (((x) & ((1 << 8) - 1)) << 16) +#define F_SOURCE_PHY_SHIFT_PATTERN6_RD(x) (((x) & (((1 << 8) - 1) << 16)) >> 16) +#define F_SOURCE_PHY_SHIFT_PATTERN7(x) (((x) & ((1 << 8) - 1)) << 24) +#define F_SOURCE_PHY_SHIFT_PATTERN7_RD(x) (((x) & (((1 << 8) - 1) << 24)) >> 24) + +/* register SHIFT_PATTERN_IN9_8 */ +#define SHIFT_PATTERN_IN9_8 2 +#define F_SOURCE_PHY_SHIFT_PATTERN8(x) (((x) & ((1 << 8) - 1)) << 0) +#define F_SOURCE_PHY_SHIFT_PATTERN8_RD(x) (((x) & (((1 << 8) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_SHIFT_PATTERN9(x) (((x) & ((1 << 8) - 1)) << 8) +#define F_SOURCE_PHY_SHIFT_PATTERN9_RD(x) (((x) & (((1 << 8) - 1) << 8)) >> 8) +#define F_SOURCE_PHY_SHIFT_LOAD(x) (((x) & ((1 << 1) - 1)) << 16) +#define F_SOURCE_PHY_SHIFT_LOAD_RD(x) (((x) & (((1 << 1) - 1) << 16)) >> 16) +#define F_SOURCE_PHY_SHIFT_EN(x) (((x) & ((1 << 1) - 1)) << 17) +#define F_SOURCE_PHY_SHIFT_EN_RD(x) (((x) & (((1 << 1) - 1) << 17)) >> 17) +#define F_SOURCE_PHY_SHIFT_REPETITION(x) (((x) & ((1 << 3) - 1)) << 18) +#define F_SOURCE_PHY_SHIFT_REPETITION_RD(x) \ + (((x) & (((1 << 3) - 1) << 18)) >> 18) + +/* register PRBS_CNTRL */ +#define PRBS_CNTRL 3 +#define F_SOURCE_PHY_PRBS0_MODE(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_SOURCE_PHY_PRBS0_MODE_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_PRBS0_OUT_MODE(x) (((x) & ((1 << 2) - 1)) << 2) +#define F_SOURCE_PHY_PRBS0_OUT_MODE_RD(x) (((x) & (((1 << 2) - 1) << 2)) >> 2) +#define F_SOURCE_PHY_PRBS1_MODE(x) (((x) & ((1 << 2) - 1)) << 4) +#define F_SOURCE_PHY_PRBS1_MODE_RD(x) (((x) & (((1 << 2) - 1) << 4)) >> 4) +#define F_SOURCE_PHY_PRBS1_OUT_MODE(x) (((x) & ((1 << 2) - 1)) << 6) +#define F_SOURCE_PHY_PRBS1_OUT_MODE_RD(x) (((x) & (((1 << 2) - 1) << 6)) >> 6) +#define F_SOURCE_PHY_PRBS2_MODE(x) (((x) & ((1 << 2) - 1)) << 8) +#define F_SOURCE_PHY_PRBS2_MODE_RD(x) (((x) & (((1 << 2) - 1) << 8)) >> 8) +#define F_SOURCE_PHY_PRBS2_OUT_MODE(x) (((x) & ((1 << 2) - 1)) << 10) +#define F_SOURCE_PHY_PRBS2_OUT_MODE_RD(x) (((x) & (((1 << 2) - 1) << 10)) >> 10) +#define F_SOURCE_PHY_PRBS3_MODE(x) (((x) & ((1 << 2) - 1)) << 12) +#define F_SOURCE_PHY_PRBS3_MODE_RD(x) (((x) & (((1 << 2) - 1) << 12)) >> 12) +#define F_SOURCE_PHY_PRBS3_OUT_MODE(x) (((x) & ((1 << 2) - 1)) << 14) +#define F_SOURCE_PHY_PRBS3_OUT_MODE_RD(x) (((x) & (((1 << 2) - 1) << 14)) >> 14) + +/* register PRBS_ERR_INSERTION */ +#define PRBS_ERR_INSERTION 4 +#define F_ADD_ERROR0(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_ADD_ERROR0_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_NUMBER_OF_ERRORS0(x) (((x) & ((1 << 5) - 1)) << 1) +#define F_NUMBER_OF_ERRORS0_RD(x) (((x) & (((1 << 5) - 1) << 1)) >> 1) +#define F_ADD_ERROR1(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_ADD_ERROR1_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_NUMBER_OF_ERRORS1(x) (((x) & ((1 << 5) - 1)) << 7) +#define F_NUMBER_OF_ERRORS1_RD(x) (((x) & (((1 << 5) - 1) << 7)) >> 7) +#define F_ADD_ERROR2(x) (((x) & ((1 << 1) - 1)) << 12) +#define F_ADD_ERROR2_RD(x) (((x) & (((1 << 1) - 1) << 12)) >> 12) +#define F_NUMBER_OF_ERRORS2(x) (((x) & ((1 << 5) - 1)) << 13) +#define F_NUMBER_OF_ERRORS2_RD(x) (((x) & (((1 << 5) - 1) << 13)) >> 13) +#define F_ADD_ERROR3(x) (((x) & ((1 << 1) - 1)) << 18) +#define F_ADD_ERROR3_RD(x) (((x) & (((1 << 1) - 1) << 18)) >> 18) +#define F_NUMBER_OF_ERRORS3(x) (((x) & ((1 << 5) - 1)) << 19) +#define F_NUMBER_OF_ERRORS3_RD(x) (((x) & (((1 << 5) - 1) << 19)) >> 19) + +/* register LANES_CONFIG */ +#define LANES_CONFIG 5 +#define F_SOURCE_PHY_LANE0_SWAP(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_SOURCE_PHY_LANE0_SWAP_RD(x) (((x) & (((1 << 2) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_LANE1_SWAP(x) (((x) & ((1 << 2) - 1)) << 2) +#define F_SOURCE_PHY_LANE1_SWAP_RD(x) (((x) & (((1 << 2) - 1) << 2)) >> 2) +#define F_SOURCE_PHY_LANE2_SWAP(x) (((x) & ((1 << 2) - 1)) << 4) +#define F_SOURCE_PHY_LANE2_SWAP_RD(x) (((x) & (((1 << 2) - 1) << 4)) >> 4) +#define F_SOURCE_PHY_LANE3_SWAP(x) (((x) & ((1 << 2) - 1)) << 6) +#define F_SOURCE_PHY_LANE3_SWAP_RD(x) (((x) & (((1 << 2) - 1) << 6)) >> 6) +#define F_SOURCE_PHY_LANE0_LSB_MSB(x) (((x) & ((1 << 1) - 1)) << 8) +#define F_SOURCE_PHY_LANE0_LSB_MSB_RD(x) (((x) & (((1 << 1) - 1) << 8)) >> 8) +#define F_SOURCE_PHY_LANE1_LSB_MSB(x) (((x) & ((1 << 1) - 1)) << 9) +#define F_SOURCE_PHY_LANE1_LSB_MSB_RD(x) (((x) & (((1 << 1) - 1) << 9)) >> 9) +#define F_SOURCE_PHY_LANE2_LSB_MSB(x) (((x) & ((1 << 1) - 1)) << 10) +#define F_SOURCE_PHY_LANE2_LSB_MSB_RD(x) (((x) & (((1 << 1) - 1) << 10)) >> 10) +#define F_SOURCE_PHY_LANE3_LSB_MSB(x) (((x) & ((1 << 1) - 1)) << 11) +#define F_SOURCE_PHY_LANE3_LSB_MSB_RD(x) (((x) & (((1 << 1) - 1) << 11)) >> 11) +#define F_SOURCE_PHY_AUX_SPARE(x) (((x) & ((1 << 4) - 1)) << 12) +#define F_SOURCE_PHY_AUX_SPARE_RD(x) (((x) & (((1 << 4) - 1) << 12)) >> 12) +#define F_SOURCE_PHY_LANE0_POLARITY(x) (((x) & ((1 << 1) - 1)) << 16) +#define F_SOURCE_PHY_LANE0_POLARITY_RD(x) (((x) & (((1 << 1) - 1) << 16)) >> 16) +#define F_SOURCE_PHY_LANE1_POLARITY(x) (((x) & ((1 << 1) - 1)) << 17) +#define F_SOURCE_PHY_LANE1_POLARITY_RD(x) (((x) & (((1 << 1) - 1) << 17)) >> 17) +#define F_SOURCE_PHY_LANE2_POLARITY(x) (((x) & ((1 << 1) - 1)) << 18) +#define F_SOURCE_PHY_LANE2_POLARITY_RD(x) (((x) & (((1 << 1) - 1) << 18)) >> 18) +#define F_SOURCE_PHY_LANE3_POLARITY(x) (((x) & ((1 << 1) - 1)) << 19) +#define F_SOURCE_PHY_LANE3_POLARITY_RD(x) (((x) & (((1 << 1) - 1) << 19)) >> 19) +#define F_SOURCE_PHY_DATA_DEL_EN(x) (((x) & ((1 << 1) - 1)) << 20) +#define F_SOURCE_PHY_DATA_DEL_EN_RD(x) (((x) & (((1 << 1) - 1) << 20)) >> 20) +#define F_SOURCE_PHY_COMB_BYPASS(x) (((x) & ((1 << 1) - 1)) << 21) +#define F_SOURCE_PHY_COMB_BYPASS_RD(x) (((x) & (((1 << 1) - 1) << 21)) >> 21) +#define F_SOURCE_PHY_20_10(x) (((x) & ((1 << 1) - 1)) << 22) +#define F_SOURCE_PHY_20_10_RD(x) (((x) & (((1 << 1) - 1) << 22)) >> 22) + +/* register PHY_DATA_SEL */ +#define PHY_DATA_SEL 6 +#define F_SOURCE_PHY_DATA_SEL(x) (((x) & ((1 << 3) - 1)) << 0) +#define F_SOURCE_PHY_DATA_SEL_RD(x) (((x) & (((1 << 3) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_MHDP_SEL(x) (((x) & ((1 << 2) - 1)) << 3) +#define F_SOURCE_PHY_MHDP_SEL_RD(x) (((x) & (((1 << 2) - 1) << 3)) >> 3) + +/* register LANES_DEL_VAL */ +#define LANES_DEL_VAL 7 +#define F_SOURCE_PHY_LANE0_DEL_VAL(x) (((x) & ((1 << 4) - 1)) << 0) +#define F_SOURCE_PHY_LANE0_DEL_VAL_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +#define F_SOURCE_PHY_LANE1_DEL_VAL(x) (((x) & ((1 << 4) - 1)) << 4) +#define F_SOURCE_PHY_LANE1_DEL_VAL_RD(x) (((x) & (((1 << 4) - 1) << 4)) >> 4) +#define F_SOURCE_PHY_LANE2_DEL_VAL(x) (((x) & ((1 << 4) - 1)) << 8) +#define F_SOURCE_PHY_LANE2_DEL_VAL_RD(x) (((x) & (((1 << 4) - 1) << 8)) >> 8) +#define F_SOURCE_PHY_LANE3_DEL_VAL(x) (((x) & ((1 << 4) - 1)) << 12) +#define F_SOURCE_PHY_LANE3_DEL_VAL_RD(x) (((x) & (((1 << 4) - 1) << 12)) >> 12) + +#endif /*SOURCE_PHY */ diff --git a/drivers/video/imx/hdp/source_pif.h b/drivers/video/imx/hdp/source_pif.h new file mode 100644 index 000000000000..b9cbe16659d0 --- /dev/null +++ b/drivers/video/imx/hdp/source_pif.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * Copyright (C) 2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * source_pif.h + * + ****************************************************************************** + */ + +#ifndef SOURCE_PIF_H_ +#define SOURCE_PIF_H_ + +/* register SOURCE_PIF_WR_ADDR */ +#define SOURCE_PIF_WR_ADDR 0 +#define F_WR_ADDR(x) (((x) & ((1 << 4) - 1)) << 0) +#define F_WR_ADDR_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_WR_REQ */ +#define SOURCE_PIF_WR_REQ 1 +#define F_HOST_WR(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_HOST_WR_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_RD_ADDR */ +#define SOURCE_PIF_RD_ADDR 2 +#define F_RD_ADDR(x) (((x) & ((1 << 4) - 1)) << 0) +#define F_RD_ADDR_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_RD_REQ */ +#define SOURCE_PIF_RD_REQ 3 +#define F_HOST_RD(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_HOST_RD_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_DATA_WR */ +#define SOURCE_PIF_DATA_WR 4 +/*# define F_DATA_WR(x) (((x) & ((1 << 32) - 1)) << 0) */ +/*# define F_DATA_WR_RD(x) (((x) & (((1 << 32) - 1) << 0)) >> 0) */ +#define F_DATA_WR(x) (((x) & 0xffffffff) << 0) +#define F_DATA_WR_RD(x) (((x) & 0xffffffff) >> 0) + +/* register SOURCE_PIF_DATA_RD */ +#define SOURCE_PIF_DATA_RD 5 +#define F_FIFO2_DATA_OUT(x) (((x) & ((1 << 32) - 1)) << 0) +#define F_FIFO2_DATA_OUT_RD(x) (((x) & (((1 << 32) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_FIFO1_FLUSH */ +#define SOURCE_PIF_FIFO1_FLUSH 6 +#define F_FIFO1_FLUSH(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_FIFO1_FLUSH_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_FIFO2_FLUSH */ +#define SOURCE_PIF_FIFO2_FLUSH 7 +#define F_FIFO2_FLUSH(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_FIFO2_FLUSH_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_STATUS */ +#define SOURCE_PIF_STATUS 8 +#define F_SOURCE_PKT_MEM_CTRL_FSM_STATE(x) (((x) & ((1 << 2) - 1)) << 0) +#define F_SOURCE_PKT_MEM_CTRL_FSM_STATE_RD(x) \ + (((x) & (((1 << 2) - 1) << 0)) >> 0) +#define F_FIFO1_FULL(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_FIFO1_FULL_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_FIFO2_EMPTY(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_FIFO2_EMPTY_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) + +/* register SOURCE_PIF_INTERRUPT_SOURCE */ +#define SOURCE_PIF_INTERRUPT_SOURCE 9 +#define F_HOST_WR_DONE_INT(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_HOST_WR_DONE_INT_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_HOST_RD_DONE_INT(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_HOST_RD_DONE_INT_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_NONVALID_TYPE_REQUESTED_INT(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_NONVALID_TYPE_REQUESTED_INT_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_PSLVERR(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_PSLVERR_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) +#define F_ALLOC_WR_DONE(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_ALLOC_WR_DONE_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_ALLOC_WR_ERROR(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_ALLOC_WR_ERROR_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_FIFO1_OVERFLOW(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_FIFO1_OVERFLOW_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_FIFO1_UNDERFLOW(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_FIFO1_UNDERFLOW_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) +#define F_FIFO2_OVERFLOW(x) (((x) & ((1 << 1) - 1)) << 8) +#define F_FIFO2_OVERFLOW_RD(x) (((x) & (((1 << 1) - 1) << 8)) >> 8) +#define F_FIFO2_UNDERFLOW(x) (((x) & ((1 << 1) - 1)) << 9) +#define F_FIFO2_UNDERFLOW_RD(x) (((x) & (((1 << 1) - 1) << 9)) >> 9) + +/* register SOURCE_PIF_INTERRUPT_MASK */ +#define SOURCE_PIF_INTERRUPT_MASK 10 +#define F_HOST_WR_DONE_INT_MASK(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_HOST_WR_DONE_INT_MASK_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_HOST_RD_DONE_INT_MASK(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_HOST_RD_DONE_INT_MASK_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_NONVALID_TYPE_REQUESTED_INT_MASK(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_NONVALID_TYPE_REQUESTED_INT_MASK_RD(x) \ + (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_PSLVERR_MASK(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_PSLVERR_MASK_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) +#define F_ALLOC_WR_DONE_MASK(x) (((x) & ((1 << 1) - 1)) << 4) +#define F_ALLOC_WR_DONE_MASK_RD(x) (((x) & (((1 << 1) - 1) << 4)) >> 4) +#define F_ALLOC_WR_ERROR_MASK(x) (((x) & ((1 << 1) - 1)) << 5) +#define F_ALLOC_WR_ERROR_MASK_RD(x) (((x) & (((1 << 1) - 1) << 5)) >> 5) +#define F_FIFO1_OVERFLOW_MASK(x) (((x) & ((1 << 1) - 1)) << 6) +#define F_FIFO1_OVERFLOW_MASK_RD(x) (((x) & (((1 << 1) - 1) << 6)) >> 6) +#define F_FIFO1_UNDERFLOW_MASK(x) (((x) & ((1 << 1) - 1)) << 7) +#define F_FIFO1_UNDERFLOW_MASK_RD(x) (((x) & (((1 << 1) - 1) << 7)) >> 7) +#define F_FIFO2_OVERFLOW_MASK(x) (((x) & ((1 << 1) - 1)) << 8) +#define F_FIFO2_OVERFLOW_MASK_RD(x) (((x) & (((1 << 1) - 1) << 8)) >> 8) +#define F_FIFO2_UNDERFLOW_MASK(x) (((x) & ((1 << 1) - 1)) << 9) +#define F_FIFO2_UNDERFLOW_MASK_RD(x) (((x) & (((1 << 1) - 1) << 9)) >> 9) + +/* register SOURCE_PIF_PKT_ALLOC_REG */ +#define SOURCE_PIF_PKT_ALLOC_REG 11 +#define F_PKT_ALLOC_ADDRESS(x) (((x) & ((1 << 4) - 1)) << 0) +#define F_PKT_ALLOC_ADDRESS_RD(x) (((x) & (((1 << 4) - 1) << 0)) >> 0) +#define F_PACKET_TYPE(x) (((x) & ((1 << 8) - 1)) << 8) +#define F_PACKET_TYPE_RD(x) (((x) & (((1 << 8) - 1) << 8)) >> 8) +#define F_TYPE_VALID(x) (((x) & ((1 << 1) - 1)) << 16) +#define F_TYPE_VALID_RD(x) (((x) & (((1 << 1) - 1) << 16)) >> 16) +#define F_ACTIVE_IDLE_TYPE(x) (((x) & ((1 << 1) - 1)) << 17) +#define F_ACTIVE_IDLE_TYPE_RD(x) (((x) & (((1 << 1) - 1) << 17)) >> 17) + +/* register SOURCE_PIF_PKT_ALLOC_WR_EN */ +#define SOURCE_PIF_PKT_ALLOC_WR_EN 12 +#define F_PKT_ALLOC_WR_EN(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_PKT_ALLOC_WR_EN_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +/* register SOURCE_PIF_SW_RESET */ +#define SOURCE_PIF_SW_RESET 13 +#define F_SW_RST(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_SW_RST_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +#endif /*SOURCE_PIF */ diff --git a/drivers/video/imx/hdp/source_vif.h b/drivers/video/imx/hdp/source_vif.h new file mode 100644 index 000000000000..a9b6c00154fb --- /dev/null +++ b/drivers/video/imx/hdp/source_vif.h @@ -0,0 +1,93 @@ +/****************************************************************************** + * + * Copyright (C) 2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * source_vif.h + * + ****************************************************************************** + */ + +#ifndef SOURCE_VIF_H_ +#define SOURCE_VIF_H_ + +/* register BND_HSYNC2VSYNC */ +#define BND_HSYNC2VSYNC 0 +#define F_IP_DTCT_WIN(x) (((x) & ((1 << 12) - 1)) << 0) +#define F_IP_DTCT_WIN_RD(x) (((x) & (((1 << 12) - 1) << 0)) >> 0) +#define F_IP_DET_EN(x) (((x) & ((1 << 1) - 1)) << 12) +#define F_IP_DET_EN_RD(x) (((x) & (((1 << 1) - 1) << 12)) >> 12) +#define F_IP_VIF_BYPASS(x) (((x) & ((1 << 1) - 1)) << 13) +#define F_IP_VIF_BYPASS_RD(x) (((x) & (((1 << 1) - 1) << 13)) >> 13) + +/* register HSYNC2VSYNC_F1_L1 */ +#define HSYNC2VSYNC_F1_L1 1 +#define F_IP_DTCT_HSYNC2VSYNC_F1(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_IP_DTCT_HSYNC2VSYNC_F1_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) + +/* register HSYNC2VSYNC_F2_L1 */ +#define HSYNC2VSYNC_F2_L1 2 +#define F_IP_DTCT_HSYNC2VSYNC_F2(x) (((x) & ((1 << 16) - 1)) << 0) +#define F_IP_DTCT_HSYNC2VSYNC_F2_RD(x) (((x) & (((1 << 16) - 1) << 0)) >> 0) + +/* register HSYNC2VSYNC_STATUS */ +#define HSYNC2VSYNC_STATUS 3 +#define F_IP_DTCT_ERR(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_IP_DTCT_ERR_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) +#define F_IP_DCT_IP(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_IP_DCT_IP_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_IP_DTCT_VJITTER(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_IP_DTCT_VJITTER_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_IP_DTCT_HJITTER(x) (((x) & ((1 << 1) - 1)) << 3) +#define F_IP_DTCT_HJITTER_RD(x) (((x) & (((1 << 1) - 1) << 3)) >> 3) + +/* register HSYNC2VSYNC_POL_CTRL */ +#define HSYNC2VSYNC_POL_CTRL 4 +#define F_VPOL(x) (((x) & ((1 << 1) - 1)) << 2) +#define F_VPOL_RD(x) (((x) & (((1 << 1) - 1) << 2)) >> 2) +#define F_HPOL(x) (((x) & ((1 << 1) - 1)) << 1) +#define F_HPOL_RD(x) (((x) & (((1 << 1) - 1) << 1)) >> 1) +#define F_VIF_AUTO_MODE(x) (((x) & ((1 << 1) - 1)) << 0) +#define F_VIF_AUTO_MODE_RD(x) (((x) & (((1 << 1) - 1) << 0)) >> 0) + +#endif /*SOURCE_VIF */ diff --git a/drivers/video/imx/hdp/test_base_sw.c b/drivers/video/imx/hdp/test_base_sw.c index 46a8ffa650ac..973778c549cd 100644 --- a/drivers/video/imx/hdp/test_base_sw.c +++ b/drivers/video/imx/hdp/test_base_sw.c @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/util.c b/drivers/video/imx/hdp/util.c index 727946a79636..e74aaa509cce 100644 --- a/drivers/video/imx/hdp/util.c +++ b/drivers/video/imx/hdp/util.c @@ -35,7 +35,7 @@ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * - * Copyright 2017 NXP + * Copyright 2017-2018 NXP * ****************************************************************************** * diff --git a/drivers/video/imx/hdp/util.h b/drivers/video/imx/hdp/util.h index 605f0f933baf..6e8b6b7f6f7f 100644 --- a/drivers/video/imx/hdp/util.h +++ b/drivers/video/imx/hdp/util.h @@ -273,6 +273,9 @@ typedef struct { unsigned int tmp; } state_struct; +extern state_struct state; +extern int cdn_bus_read(unsigned int addr, unsigned int* value); +extern int cdn_bus_write(unsigned int addr, unsigned int value); unsigned short internal_get_msg_len(void); #endif diff --git a/drivers/video/imx/hdp/vic_table.c b/drivers/video/imx/hdp/vic_table.c new file mode 100644 index 000000000000..c49840081899 --- /dev/null +++ b/drivers/video/imx/hdp/vic_table.c @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * vic_table.c + * + ****************************************************************************** + */ +#include "vic_table.h" + +const unsigned int vic_table[VIC_MODE_COUNT][27] = { + {858, 720, 138, 62, 16, 60, 525, 480, 45, 6, 9, 30, 59, 27000, + PROGRESSIVE, ACTIVE_LOW, ACTIVE_LOW, 1, 65535, 1, 46, 65535, 65535, 3, + 8, 0}, + {1650, 1280, 370, 40, 110, 220, 750, 720, 30, 5, 5, 20, 60, 74250, + PROGRESSIVE, ACTIVE_HIGH, ACTIVE_HIGH, 1, 65535, 1, 31, 65535, 65535, + 4, 8, 0}, + {2200, 1920, 280, 44, 88, 148, 1125, 1080, 45, 5, 4, + 36, 60, 148500, PROGRESSIVE, ACTIVE_HIGH, + ACTIVE_HIGH, 1, 65535, 1, 46, 65535, 65535, 16, 8, 0}, + {4400, 3840, 560, 88, 176, 296, 2250, 2160, 90, 10, 8, 72, 60, + 594000, PROGRESSIVE, ACTIVE_HIGH, ACTIVE_HIGH, 4, 266, 262, 22, 525, + 285, 97, 8, 0}, + {4400, 3840, 560, 88, 176, 296, 2250, 2160, 90, 10, 8, 72, 30, + 297000, PROGRESSIVE, ACTIVE_HIGH, ACTIVE_HIGH, 4, 266, 262, 22, 525, + 285, 95, 8, 0}, +}; diff --git a/drivers/video/imx/hdp/vic_table.h b/drivers/video/imx/hdp/vic_table.h new file mode 100644 index 000000000000..dce88347b7e4 --- /dev/null +++ b/drivers/video/imx/hdp/vic_table.h @@ -0,0 +1,140 @@ +/****************************************************************************** + * + * Copyright (C) 2016-2017 Cadence Design Systems, Inc. + * All rights reserved worldwide. + * + * Copyright 2017-2018 NXP + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. THE SOFTWARE IS PROVIDED "AS IS", + * WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED + * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE + * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + ****************************************************************************** + * + * This file was auto-generated. Do not edit it manually. + * + ****************************************************************************** + * + * vic_table.h + * + ****************************************************************************** + */ + +#ifndef VIC_TABLE_H_ +#define VIC_TABLE_H_ + +#define PROGRESSIVE 0 +#define INTERLACED 1 + +#define ACTIVE_LOW 0 +#define ACTIVE_HIGH 1 + +typedef enum { + H_TOTAL, + H_ACTIVE, + H_BLANK, + HSYNC, + FRONT_PORCH, + BACK_PORCH, + /* H_FREQ_KHZ, */ + V_TOTAL, + V_ACTIVE, + V_BLANK, + VSYNC, + TYPE_EOF, + SOF, + V_FREQ_HZ, + PIXEL_FREQ_KHZ, + I_P, + HSYNC_POL, + VSYNC_POL, + START_OF_F0, + START_OF_F1, + VSYNC_START_INTERLACED_F0, + VSYNC_END_INTERLACED_F0, + VSYNC_START_INTERLACED_F1, + VSYNC_END_INTERLACED_F1, + VIC, + VIC_R3_0, + VIC_PR, +} MSA_PARAM; + +typedef enum { + NUM_OF_LANES_1 = 1, + NUM_OF_LANES_2 = 2, + NUM_OF_LANES_4 = 4, +} VIC_NUM_OF_LANES; + +typedef enum { + RATE_1_6 = 162, + RATE_2_7 = 270, + RATE_5_4 = 540, + RATE_8_1 = 810, +} VIC_SYMBOL_RATE; + +typedef enum { + PXL_RGB = 0x1, + YCBCR_4_4_4 = 0x2, + YCBCR_4_2_2 = 0x4, + YCBCR_4_2_0 = 0x8, + Y_ONLY = 0x10, +} VIC_PXL_ENCODING_FORMAT; + +typedef enum { + BCS_6 = 0x1, + BCS_8 = 0x2, + BCS_10 = 0x4, + BCS_12 = 0x8, + BCS_16 = 0x10, +} VIC_COLOR_DEPTH; + +typedef enum { + STEREO_VIDEO_LEFT = 0x0, + STEREO_VIDEO_RIGHT = 0x1, +} STEREO_VIDEO_ATTR; + +typedef enum { + BT_601 = 0x0, + BT_709 = 0x1, +} BT_TYPE; + +typedef enum { + VIC_MODE_3_59_94Hz, + VIC_MODE_4_60Hz, + VIC_MODE_16_60Hz, + VIC_MODE_97_60Hz, + VIC_MODE_95_30Hz, + VIC_MODE_COUNT +} VIC_MODES; + +extern const unsigned int vic_table[VIC_MODE_COUNT][27]; + +#endif diff --git a/drivers/video/imx/imx8_hdmi.c b/drivers/video/imx/imx8_hdmi.c new file mode 100644 index 000000000000..eb281f0d3341 --- /dev/null +++ b/drivers/video/imx/imx8_hdmi.c @@ -0,0 +1,293 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include + +#include "API_General.h" +#include "vic_table.h" +#include "API_HDMITX.h" +#include "apb_cfg.h" +#include "externs.h" +#include "API_AVI.h" +#include "address.h" +#include "source_car.h" +#include "source_phy.h" +#include "API_AFE.h" +#include "source_vif.h" +#include "general_handler.h" +#include "mhl_hdtx_top.h" + + +#ifdef CONFIG_MX8QM +#include "API_AFE_mcu1_dp.h" +#include "API_AFE_ss28fdsoi_kiran_hdmitx.h" +#endif + +#ifdef CONFIG_MX8M +#include "API_AFE_t28hpc_hdmitx.h" +#endif + +DECLARE_GLOBAL_DATA_PTR; + +#define ON 1 +#define OFF 0 + +unsigned long g_encoding = 1; /* 1 RGB, 2 YUV 444, 4 YUV 422, 8 YUV 420 */ +unsigned long g_color_depth = 8; /* 8 pits per color */ + +static int imx8_hdmi_set_vic_mode(int vic, + struct video_mode_settings *vms) +{ + /*struct video_mode_settings *vms = &vm_settings[VM_USER]; */ + uint32_t pixel_clock_kHz; + uint32_t frame_rate_Hz; + uint32_t frame_rate_frac_Hz; + uint32_t cea_vic; + char iflag; + + if (vic >= VIC_MODE_COUNT) { + debug("%s(): unsupported VIC\n", __func__); + return -1; + } + + + vms->hfp = vic_table[vic][FRONT_PORCH]; + vms->hbp = vic_table[vic][BACK_PORCH]; + vms->hsync = vic_table[vic][HSYNC]; + vms->vfp = vic_table[vic][TYPE_EOF]; + vms->vbp = vic_table[vic][SOF]; + vms->vsync = vic_table[vic][VSYNC]; + vms->xres = vic_table[vic][H_ACTIVE]; + vms->yres = vic_table[vic][V_ACTIVE]; + + vms->hpol = vic_table[vic][HSYNC_POL] != 0; + vms->vpol = vic_table[vic][VSYNC_POL] != 0; + + cea_vic = vic_table[vic][VIC]; + if (vic_table[vic][I_P] != 0) + iflag = 'i'; + else + iflag = 'p'; + pixel_clock_kHz = vic_table[vic][PIXEL_FREQ_KHZ]; + frame_rate_Hz = vic_table[vic][V_FREQ_HZ] * 1000; + frame_rate_frac_Hz = frame_rate_Hz % 1000; + frame_rate_Hz /= 1000; + + vms->pixelclock = pixel_clock_kHz; + + debug("Cadence VIC %3d, CEA VIC %3d: %4d x %4d %c @ %3d.%03d [%6d kHz] Vpol=%d Hpol=%d\n", + vic, cea_vic, vms->xres, vms->yres, iflag, frame_rate_Hz, + frame_rate_frac_Hz, pixel_clock_kHz, vms->vpol, vms->hpol); + + debug(" mode timing fp sync bp h:%3d %3d %3d v:%3d %3d %3d\n", + vms->hfp, vms->hsync, vms->hbp, vms->vfp, vms->vsync, vms->vbp); + + return 0; + /*debug("leaving %s() ...\n", __func__); */ +} + +static int imx8_hdmi_init(int vic, + int encoding, + int color_depth, + bool pixel_clk_from_phy) +{ + int ret; +#ifdef CONFIG_MX8QM + sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle; + void __iomem *hdmi_csr_base = (void __iomem *)0x56261000; +#endif + /*GENERAL_Read_Register_response regresp; */ + /*uint8_t sts; */ + uint32_t character_freq_khz; + + uint8_t echo_msg[] = "echo test"; + uint8_t echo_resp[sizeof(echo_msg) + 1]; + /*uint8_t response; */ + /*uint8_t dpcd_resp; */ + /*uint8_t hdcp_resp; */ + /*uint8_t capb_resp; */ + /*uint32_t temp; */ + + /*================================================================== */ + /* Parameterization: */ + /*================================================================== */ + + /* VIC Mode - index from vic_table (see API_SRC/vic_table.c) */ + VIC_MODES vic_mode = vic; + + /* Pixel Encodeing Format */ + /* PXL_RGB = 0x1, */ + /* YCBCR_4_4_4 = 0x2, */ + /* YCBCR_4_2_2 = 0x4, */ + /* YCBCR_4_2_0 = 0x8, */ + /* Y_ONLY = 0x10, */ + VIC_PXL_ENCODING_FORMAT format = encoding; + /*VIC_PXL_ENCODING_FORMAT format = 1; */ + + /* B/W Balance Type: 0 no data, 1 IT601, 2 ITU709 */ + BT_TYPE bw_type = 0; + + /* bpp (bits per subpixel) - 8 24bpp, 10 30bpp, 12 36bpp, 16 48bpp */ + uint8_t bps = color_depth; + + /* Set HDMI TX Mode */ + /* Mode = 0 - DVI, 1 - HDMI1.4, 2 HDMI 2.0 */ + HDMI_TX_MAIL_HANDLER_PROTOCOL_TYPE ptype = 1; + + if (vic_mode == VIC_MODE_97_60Hz) + ptype = 2; + + /*================================================================== */ + /* Parameterization done */ + /*================================================================== */ +#ifdef CONFIG_MX8QM + /* set the pixel link mode and pixel type */ + SC_MISC_SET_CONTROL(ipcHndl, SC_R_HDMI, SC_C_PHY_RESET, 0); +#if 1 + SC_MISC_SET_CONTROL(ipcHndl, SC_R_DC_0, SC_C_PXL_LINK_MST1_ADDR, 1); + /*SC_MISC_SET_CONTROL(ipcHndl, SC_R_DC_0, SC_C_PXL_LINK_MST1_ADDR, 0);*/ + if (g_clock_mode == CLOCK_MODES_HDMI_DUAL) { + SC_MISC_SET_CONTROL(ipcHndl, SC_R_DC_0, + SC_C_PXL_LINK_MST2_ADDR, 2); + /*SC_MISC_SET_CONTROL(ipcHndl, SC_R_DC_0, + SC_C_PXL_LINK_MST2_ADDR, 0); */ + __raw_writel(0x6, hdmi_csr_base); + } else +#endif + __raw_writel(0x34, hdmi_csr_base); +#endif + cdn_api_init(); + debug("CDN_API_Init completed\n"); + + ret = cdn_api_checkalive_blocking(); + debug("CDN_API_CheckAlive returned ret = %d\n", ret); + + ret = cdn_api_general_test_echo_ext_blocking(echo_msg, + echo_resp, + sizeof(echo_msg), + CDN_BUS_TYPE_APB); + debug("_General_Test_Echo_Ext_blocking - (ret = %d echo_resp = %s)\n", + ret, echo_resp); + + /* Configure PHY */ + character_freq_khz = phy_cfg_t28hpc(4, vic_mode, bps, + format, pixel_clk_from_phy); + debug("phy_cfg_t28hpc (character_freq_mhz = %d)\n", + character_freq_khz); + + /*phy_reset(1); */ + +#ifdef CONFIG_MX8QM + SC_MISC_SET_CONTROL(ipcHndl, SC_R_HDMI, SC_C_PHY_RESET, 1); +#endif + hdmi_tx_t28hpc_power_config_seq(4); +#ifdef CONFIG_MX8QM + /* Set the lane swapping */ + ret = cdn_api_general_write_register_blocking + (ADDR_SOURCD_PHY + (LANES_CONFIG << 2), + F_SOURCE_PHY_LANE0_SWAP(3) | F_SOURCE_PHY_LANE1_SWAP(0) | + F_SOURCE_PHY_LANE2_SWAP(1) | F_SOURCE_PHY_LANE3_SWAP(2) | + F_SOURCE_PHY_COMB_BYPASS(0) | F_SOURCE_PHY_20_10(1)); +#else + /* Set the lane swapping */ + ret = cdn_api_general_write_register_blocking + (ADDR_SOURCD_PHY + (LANES_CONFIG << 2), + F_SOURCE_PHY_LANE0_SWAP(0) | F_SOURCE_PHY_LANE1_SWAP(1) | + F_SOURCE_PHY_LANE2_SWAP(2) | F_SOURCE_PHY_LANE3_SWAP(3) | + F_SOURCE_PHY_COMB_BYPASS(0) | F_SOURCE_PHY_20_10(1)); +#endif + debug("_General_Write_Register_blocking LANES_CONFIG ret = %d\n", ret); + + ret = CDN_API_HDMITX_Init_blocking(); + debug("CDN_API_STATUS CDN_API_HDMITX_Init_blocking ret = %d\n", ret); + + ret = CDN_API_HDMITX_Init_blocking(); + debug("CDN_API_STATUS CDN_API_HDMITX_Init_blocking ret = %d\n", ret); + + ret = CDN_API_HDMITX_Set_Mode_blocking(ptype, character_freq_khz); + debug("CDN_API_HDMITX_Set_Mode_blocking ret = %d\n", ret); + + ret = cdn_api_set_avi(vic_mode, format, bw_type); + debug("cdn_api_set_avi ret = %d\n", ret); + + ret = CDN_API_HDMITX_SetVic_blocking(vic_mode, bps, format); + debug("CDN_API_HDMITX_SetVic_blocking ret = %d\n", ret); + +#ifdef CONFIG_MX8QM + { + GENERAL_Read_Register_response regresp; + /* adjust the vsync/hsync polarity */ + cdn_api_general_read_register_blocking(ADDR_SOURCE_VIF + + (HSYNC2VSYNC_POL_CTRL + << 2), + ®resp); + debug("Initial HSYNC2VSYNC_POL_CTRL: 0x%x\n", regresp.val); + if ((regresp.val & 0x3) != 0) + __raw_writel(0x4, hdmi_csr_base); + } +#endif + /*regresp.val &= ~0x03; // clear HSP and VSP bits */ + /*debug("Final HSYNC2VSYNC_POL_CTRL: 0x%x\n",regresp.val); */ + /*CDN_API_General_Write_Register_blocking(ADDR_DPTX_FRAMER + + (DP_FRAMER_SP << 2), + regresp.val); */ + + udelay(20000); + + return 0; +} + +void imx8_hdmi_enable(int encoding, + struct video_mode_settings *vms) +{ + int vic = 0; + const int use_phy_pixel_clk = 1; + + /* map the resolution to a VIC index in the vic table*/ + if ((vms->xres == 1280) && (vms->yres == 720)) + vic = 1; /* 720p60 */ + else if ((vms->xres == 1920) && (vms->yres == 1080)) + vic = 2; /* 1080p60 */ + else if ((vms->xres == 3840) && (vms->yres == 2160)) + vic = 3; /* 2160p60 */ + else /* if ((vms->xres == 720) && (vms->yres == 480)) */ + vic = 0; /* 480p60 */ + + imx8_hdmi_set_vic_mode(vic, vms); + imx8_hdmi_init(vic, encoding, g_color_depth, use_phy_pixel_clk); +} + +void imx8_hdmi_disable(void) +{ + int ret; + GENERAL_READ_REGISTER_RESPONSE resp; + + resp.val = 0; + ret = cdn_api_general_read_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + &resp); + if (ret != CDN_OK) { + printf("%s(): dn_api_general_read_register_blocking failed\n", + __func__); + /*return;*/ + } + + resp.val &= ~F_DATA_EN(1); /* disable HDMI */ + /*resp.val |= F_SET_AVMUTE( 1);*/ + + ret = cdn_api_general_write_register_blocking(ADDR_SOURCE_MHL_HD + + (HDTX_CONTROLLER << 2), + resp.val); + if (ret != CDN_OK) { + printf("%s(): dn_api_general_write_register_blocking failed\n", + __func__); + return; + } +} From 82b578aaafa3727d105fd7e7c5b5476387618cca Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Mon, 29 Jan 2018 14:08:44 -0600 Subject: [PATCH 11/62] MLK-17404-2 include: Adding header for i.MX8 HDMI support Adding header file for i.MX8 HDMI support Signed-off-by: Oliver Brown --- include/imx8_hdmi.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 include/imx8_hdmi.h diff --git a/include/imx8_hdmi.h b/include/imx8_hdmi.h new file mode 100644 index 000000000000..741f86d2fd48 --- /dev/null +++ b/include/imx8_hdmi.h @@ -0,0 +1,13 @@ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __IMX8_HDMI_H__ +#define __IMX8_HDMI_H__ + +void imx8_hdmi_enable(int encoding, struct video_mode_settings *vms); +void imx8_hdmi_disable(void); + +#endif /* __IMX8_HDMI_H__*/ From cd472bd17470274165d115a44960df6b5eeb0605 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Wed, 28 Feb 2018 05:23:49 -0800 Subject: [PATCH 12/62] MLK-17638 video: imx8m_hdmi: Checks HDMI FW before enabling video output Checks whether the HDMI FW is running before initialize the HDMI display. So that for cases like mfgtool and imx-boot image without HDMI FW, the u-boot won't be blocked. Signed-off-by: Ye Li (cherry picked from commit 273b45dd3cf8773462400857c8b48b70bcfe96bb) --- arch/arm/mach-imx/mx8m/video_common.c | 7 ++++++- drivers/video/imx/imx8_hdmi.c | 9 ++++++--- include/imx8_hdmi.h | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/arch/arm/mach-imx/mx8m/video_common.c b/arch/arm/mach-imx/mx8m/video_common.c index ee7c844049e8..690ebb3149c0 100644 --- a/arch/arm/mach-imx/mx8m/video_common.c +++ b/arch/arm/mach-imx/mx8m/video_common.c @@ -656,6 +656,7 @@ void *video_hw_init(void) { void *fb; int encoding = 1; + int ret; debug("%s()\n", __func__); @@ -680,7 +681,11 @@ void *video_hw_init(void) imx8m_create_color_bar((void *)((uint64_t) fb), &gmode); - imx8_hdmi_enable(encoding, &gmode); /* may change gmode */ + ret = imx8_hdmi_enable(encoding, &gmode); /* may change gmode */ + if (ret) { + printf("HDMI enable failed!\n"); + return NULL; + } /* start dccs */ imx8m_display_init((uint64_t) fb, encoding, &gmode); diff --git a/drivers/video/imx/imx8_hdmi.c b/drivers/video/imx/imx8_hdmi.c index eb281f0d3341..32eda3e1472e 100644 --- a/drivers/video/imx/imx8_hdmi.c +++ b/drivers/video/imx/imx8_hdmi.c @@ -166,9 +166,12 @@ static int imx8_hdmi_init(int vic, cdn_api_init(); debug("CDN_API_Init completed\n"); - ret = cdn_api_checkalive_blocking(); + ret = cdn_api_checkalive(); debug("CDN_API_CheckAlive returned ret = %d\n", ret); + if (ret) + return -EPERM; + ret = cdn_api_general_test_echo_ext_blocking(echo_msg, echo_resp, sizeof(echo_msg), @@ -244,7 +247,7 @@ static int imx8_hdmi_init(int vic, return 0; } -void imx8_hdmi_enable(int encoding, +int imx8_hdmi_enable(int encoding, struct video_mode_settings *vms) { int vic = 0; @@ -261,7 +264,7 @@ void imx8_hdmi_enable(int encoding, vic = 0; /* 480p60 */ imx8_hdmi_set_vic_mode(vic, vms); - imx8_hdmi_init(vic, encoding, g_color_depth, use_phy_pixel_clk); + return imx8_hdmi_init(vic, encoding, g_color_depth, use_phy_pixel_clk); } void imx8_hdmi_disable(void) diff --git a/include/imx8_hdmi.h b/include/imx8_hdmi.h index 741f86d2fd48..eb1253cf51f2 100644 --- a/include/imx8_hdmi.h +++ b/include/imx8_hdmi.h @@ -7,7 +7,7 @@ #ifndef __IMX8_HDMI_H__ #define __IMX8_HDMI_H__ -void imx8_hdmi_enable(int encoding, struct video_mode_settings *vms); +int imx8_hdmi_enable(int encoding, struct video_mode_settings *vms); void imx8_hdmi_disable(void); #endif /* __IMX8_HDMI_H__*/ From 2c172e686c58bb92dc6e62c272fc7cd6a36363d7 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 22 Jun 2018 17:17:58 -0700 Subject: [PATCH 13/62] video_common: fix compile errors Signed-off-by: Troy Kisky --- arch/arm/mach-imx/mx8m/video_common.c | 34 ++++++++++++++------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-imx/mx8m/video_common.c b/arch/arm/mach-imx/mx8m/video_common.c index 690ebb3149c0..cd45c9c81c36 100644 --- a/arch/arm/mach-imx/mx8m/video_common.c +++ b/arch/arm/mach-imx/mx8m/video_common.c @@ -146,21 +146,23 @@ void imx8m_create_color_bar(void *start_address, static void imx8m_set_clocks(int apb_clk, int b_clk, int hdmi_core_clk, int p_clk, int rtr_clk) { + struct ccm_reg *ccm_reg = (struct ccm_reg *)CCM_BASE_ADDR; + if (b_clk == 800) { /* b_clk: bus_clk_root(4) sel 2nd input source and pre_div to 0; output should be 800M */ - reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_CLR(4), + reg32_write(&ccm_reg->bus_root[4].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_SET(4), (0x2 << 24)); + reg32_write(&ccm_reg->bus_root[4].target_root_set, (0x2 << 24)); } else { printf("b_clk does not match a supported frequency"); } if (rtr_clk == 400) { /* rtr_clk: bus_clk_root(6) sel 1st input source and pre_div to 1; output should be 400M */ - reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_CLR(6), + reg32_write(&ccm_reg->bus_root[6].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_SET(6), + reg32_write(&ccm_reg->bus_root[6].target_root_set, (0x1 << 24) | (0x1 << 16)); } else { debug("rtr_clk does not match a supported frequency"); @@ -171,9 +173,9 @@ static void imx8m_set_clocks(int apb_clk, int b_clk, int hdmi_core_clk, if (hdmi_core_clk == 200) { /* hdmi_core_clk: ip_clk_root(69) sel 1st input source and pre_div to 0 */ - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(69), + reg32_write(&ccm_reg->bus_root[69].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(69), (0x1 << 24)); + reg32_write(&ccm_reg->bus_root[69].target_root_set, (0x1 << 24)); g_hdmi_core_clock = 200000000; } else { debug("hdmi_core_clk does not match a supported frequency"); @@ -185,39 +187,39 @@ static void imx8m_set_clocks(int apb_clk, int b_clk, int hdmi_core_clk, if (p_clk == 27) { /* p_clk: ip_clk_root(9) sel 1st input source and pre_div to 1; post_div to 5, output 100M */ - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + reg32_write(&ccm_reg->bus_root[9].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + reg32_write(&ccm_reg->bus_root[9].target_root_set, (0x1 << 24) | (29 << 16)); } else if (p_clk == 100) { /* p_clk: ip_clk_root(9) sel 1st input source and pre_div to 1; post_div to 5, output 100M */ - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + reg32_write(&ccm_reg->bus_root[9].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + reg32_write(&ccm_reg->bus_root[9].target_root_set, (0x1 << 24) | (0x5 << 16)); } else if (p_clk == 120) { /* p_clk: ip_clk_root(9) sel 1st input source and pre_div to 1; post_div to 4, output 120M */ - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + reg32_write(&ccm_reg->bus_root[9].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + reg32_write(&ccm_reg->bus_root[9].target_root_set, (0x1 << 24) | (0x4 << 16)); } else if (p_clk == 200) { /* I added this to speed up the pixel clock and get frames out faster. may need to adjust this. */ - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + reg32_write(&ccm_reg->bus_root[9].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + reg32_write(&ccm_reg->bus_root[9].target_root_set, (0x4 << 24) | (0x3 << 16)); /*for emu use 800 / 4 */ } else if (p_clk == 400) { /* I added this to speed up the pixel clock and get frames out faster. may need to adjust this. */ - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9), + reg32_write(&ccm_reg->bus_root[9].target_root_clr, (0x7 << 24) | (0x7 << 16)); - reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9), + reg32_write(&ccm_reg->bus_root[9].target_root_set, (0x4 << 24) | (0x1 << 16)); /*for emu use 800 / 2 */ } else if (p_clk == 40) { /* Do not reprogram, will get 40MHz */ } else { From c59445e53cb964f587c1da65fad96f81d87251bd Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Mon, 29 Jan 2018 14:23:56 -0600 Subject: [PATCH 14/62] MLK-17404-6 video: Adding i.MX8 HDMI support to configuration Adding i.MX8 HDMI support to build configuration. Signed-off-by: Oliver Brown Signed-off-by: Troy Kisky --- drivers/video/Kconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 25c94f4a9e36..6dccf273177f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -552,6 +552,20 @@ config VIDEO_IPUV3 This enables framebuffer driver for i.MX processors working on the IPUv3(Image Processing Unit) internal graphic processor. +config VIDEO_IMXDCSS + bool "i.MX8 DCSS display support" + default n + depends on VIDEO && MX8M + help + Support for DCSS display controller for i.MX8 processors. + +config VIDEO_IMX8_HDMI + bool "i.MX8 HDMI Splash screen" + default n + depends on VIDEO && MX8M + help + Support for HDMI i.MX8 processors. + config CFB_CONSOLE bool "Enable colour frame buffer console" depends on VIDEO From ca70dd93a7f042f8d8ef3010d9eb8e2059ef7dba Mon Sep 17 00:00:00 2001 From: Oliver Brown Date: Wed, 13 Dec 2017 17:12:45 -0600 Subject: [PATCH 15/62] MLK-17205-2 video: imx: hdp: Adding HDP firmware loading to the build Adding the HDP firmware loading to the build. Signed-off-by: Oliver Brown --- drivers/video/Kconfig | 9 +++++++++ drivers/video/Makefile | 1 + 2 files changed, 10 insertions(+) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6dccf273177f..55448905f7a6 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -559,6 +559,15 @@ config VIDEO_IMXDCSS help Support for DCSS display controller for i.MX8 processors. +config VIDEO_IMX_HDP_LOAD + bool "i.MX8 HDMI/DP firmware loading" + default n + depends on VIDEO && MX8QM + help + Support for HDMI/DP firmware loading for i.MX8QM processors. The + firmware is copied from system memory to the HDMI/DP IRAM and + DRAM memory. + config VIDEO_IMX8_HDMI bool "i.MX8 HDMI Splash screen" default n diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 80e1e829033a..98eabd9863c1 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -63,4 +63,5 @@ obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o obj-$(CONFIG_VIDEO_VESA) += vesa.o obj-y += bridge/ +obj-y += imx/ obj-y += sunxi/ From fc3f8d1015343092951592294a47c1463008f839 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 2 Jul 2018 09:55:17 -0700 Subject: [PATCH 16/62] serial: Kconfig: allow MXC_UART for MX8M Signed-off-by: Troy Kisky --- drivers/serial/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 597db4b9cbba..2b4ba3c89453 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -522,7 +522,7 @@ config MVEBU_A3700_UART config MXC_UART bool "IMX serial port support" - depends on MX5 || MX6 + depends on MX5 || MX6 || MX7 || MX8M help If you have a machine based on a Motorola IMX CPU you can enable its onboard serial port by enabling this option. From 6337608c0a1c288f30651f255b21c202e107f26f Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 2 Jul 2018 10:33:29 -0700 Subject: [PATCH 17/62] fsl-imx8mq.dtsi: add uart1-4 Signed-off-by: Troy Kisky --- arch/arm/dts/fsl-imx8mq.dtsi | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/arch/arm/dts/fsl-imx8mq.dtsi b/arch/arm/dts/fsl-imx8mq.dtsi index 814a1b7df4cf..bd855009aeb3 100644 --- a/arch/arm/dts/fsl-imx8mq.dtsi +++ b/arch/arm/dts/fsl-imx8mq.dtsi @@ -29,6 +29,10 @@ aliases { ethernet0 = &fec1; + serial0 = &uart1; + serial1 = &uart2; + serial2 = &uart3; + serial3 = &uart4; mmc0 = &usdhc1; mmc1 = &usdhc2; gpio0 = &gpio1; @@ -278,6 +282,57 @@ interrupt-parent = <&gic>; }; + uart1: serial@30860000 { + compatible = "fsl,imx8mq-uart", "fsl,imx6ul-uart", + "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x0 0x30860000 0x0 0x10000>; + interrupts = ; + clocks = <&clk IMX8MQ_CLK_UART1_ROOT>, + <&clk IMX8MQ_CLK_UART1_ROOT>; + clock-names = "ipg", "per"; + interrupt-parent = <&gpc>; + status = "disabled"; + }; + + uart3: serial@30880000 { + compatible = "fsl,imx8mq-uart", "fsl,imx6ul-uart", + "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x0 0x30880000 0x0 0x10000>; + interrupts = ; + clocks = <&clk IMX8MQ_CLK_UART3_ROOT>, + <&clk IMX8MQ_CLK_UART3_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 26 4 0>, <&sdma1 27 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart2: serial@30890000 { + compatible = "fsl,imx8mq-uart", "fsl,imx6ul-uart", + "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x0 0x30890000 0x0 0x10000>; + interrupts = ; + clocks = <&clk IMX8MQ_CLK_UART2_ROOT>, + <&clk IMX8MQ_CLK_UART2_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 24 4 0>, <&sdma1 25 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + + uart4: serial@30a60000 { + compatible = "fsl,imx8mq-uart", "fsl,imx6ul-uart", + "fsl,imx6q-uart", "fsl,imx21-uart"; + reg = <0x0 0x30a60000 0x0 0x10000>; + interrupts = ; + clocks = <&clk IMX8MQ_CLK_UART4_ROOT>, + <&clk IMX8MQ_CLK_UART4_ROOT>; + clock-names = "ipg", "per"; + dmas = <&sdma1 28 4 0>, <&sdma1 29 4 0>; + dma-names = "rx", "tx"; + status = "disabled"; + }; + usdhc1: usdhc@30b40000 { compatible = "fsl,imx8mq-usdhc", "fsl,imx7d-usdhc"; reg = <0x0 0x30b40000 0x0 0x10000>; @@ -308,6 +363,30 @@ status = "disabled"; }; + sdma1: sdma@30bd0000 { + compatible = "fsl,imx8mq-sdma", "fsl,imx7d-sdma"; + reg = <0x0 0x30bd0000 0x0 0x10000>; + interrupts = ; + clocks = <&clk IMX8MQ_CLK_SDMA1_ROOT>, + <&clk IMX8MQ_CLK_SDMA1_ROOT>; + clock-names = "ipg", "ahb"; + #dma-cells = <3>; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + status = "okay"; + }; + + sdma2: sdma@302c0000 { + compatible = "fsl,imx8mq-sdma", "fsl,imx7d-sdma"; + reg = <0x0 0x302c0000 0x0 0x10000>; + interrupts = ; + clocks = <&clk IMX8MQ_CLK_SDMA2_ROOT>, + <&clk IMX8MQ_CLK_SDMA2_ROOT>; + clock-names = "ipg", "ahb"; + #dma-cells = <3>; + fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; + status = "okay"; + }; + fec1: ethernet@30be0000 { compatible = "fsl,imx8mq-fec", "fsl,imx6sx-fec"; reg = <0x0 0x30be0000 0x0 0x10000>; From 58a2cd9bab091524cb02279a65fd8494e0beeb2d Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 9 Jul 2018 12:18:13 -0700 Subject: [PATCH 18/62] fsl-imx8mq.dtsi: add usb nodes Signed-off-by: Troy Kisky --- arch/arm/dts/fsl-imx8mq.dtsi | 80 ++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/arch/arm/dts/fsl-imx8mq.dtsi b/arch/arm/dts/fsl-imx8mq.dtsi index bd855009aeb3..14d4b134f232 100644 --- a/arch/arm/dts/fsl-imx8mq.dtsi +++ b/arch/arm/dts/fsl-imx8mq.dtsi @@ -333,6 +333,86 @@ status = "disabled"; }; + usb3_phy0: phy@381f0040 { + compatible = "fsl,imx8mq-usb-phy"; + #phy-cells = <1>; + reg = <0x0 0x381f0040 0x0 0x40>; + clocks = <&clk IMX8MQ_CLK_USB1_PHY_ROOT>; + clock-names = "usb_phy_root_clk"; + assigned-clocks = <&clk IMX8MQ_CLK_USB_PHY_REF_SRC>; + assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_100M>; + assigned-clock-rates = <100000000>; + status = "disabled"; + }; + + usb3_0: usb@38100000 { + compatible = "fsl, imx8mq-dwc3"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&clk IMX8MQ_CLK_USB1_CTRL_ROOT>; + clock-names = "usb1_ctrl_root_clk"; + assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS_SRC>, + <&clk IMX8MQ_CLK_USB_CORE_REF_SRC>; + assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_500M>, + <&clk IMX8MQ_SYS1_PLL_100M>; + assigned-clock-rates = <500000000>, <100000000>; + status = "disabled"; + + usb_dwc3_0: dwc3 { + compatible = "snps,dwc3"; + reg = <0x0 0x38100000 0x0 0x10000>; + interrupts = ; + interrupt-parent = <&gpc>; + phys = <&usb3_phy0 0>, <&usb3_phy0 1>; + phy-names = "usb2-phy", "usb3-phy"; + power-domains = <&power 2>; + snps,power-down-scale = <2>; + snps,dis_u2_susphy_quirk; + status = "disabled"; + }; + }; + + usb3_phy1: phy@382f0040 { + compatible = "fsl,imx8mq-usb-phy"; + #phy-cells = <1>; + reg = <0x0 0x382f0040 0x0 0x40>; + clocks = <&clk IMX8MQ_CLK_USB2_PHY_ROOT>; + clock-names = "usb_phy_root_clk"; + assigned-clocks = <&clk IMX8MQ_CLK_USB_PHY_REF_SRC>; + assigned-clock-parents = <&clk IMX8MQ_SYS1_PLL_100M>; + assigned-clock-rates = <100000000>; + status = "disabled"; + }; + + usb3_1: usb@38200000 { + compatible = "fsl, imx8mq-dwc3"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&clk IMX8MQ_CLK_USB2_CTRL_ROOT>; + clock-names = "usb2_ctrl_root_clk"; + assigned-clocks = <&clk IMX8MQ_CLK_USB_BUS_SRC>, + <&clk IMX8MQ_CLK_USB_CORE_REF_SRC>; + assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_500M>, + <&clk IMX8MQ_SYS1_PLL_100M>; + assigned-clock-rates = <500000000>, <100000000>; + status = "disabled"; + + usb_dwc3_1: dwc3 { + compatible = "snps,dwc3"; + reg = <0x0 0x38200000 0x0 0x10000>; + interrupts = ; + interrupt-parent = <&gpc>; + phys = <&usb3_phy1 0>, <&usb3_phy1 1>; + phy-names = "usb2-phy", "usb3-phy"; + power-domains = <&power 3>; + snps,power-down-scale = <2>; + snps,dis_u2_susphy_quirk; + status = "disabled"; + }; + }; + usdhc1: usdhc@30b40000 { compatible = "fsl,imx8mq-usdhc", "fsl,imx7d-usdhc"; reg = <0x0 0x30b40000 0x0 0x10000>; From 78a7e32762ca585d40b5d60905973ce8ceba89c2 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 9 Jul 2018 10:48:22 -0700 Subject: [PATCH 19/62] mmc: fsl_esdhc: add reset-gpios for DM Signed-off-by: Troy Kisky --- drivers/mmc/fsl_esdhc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 74007e2ad43f..39e708878abd 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -146,6 +146,7 @@ struct fsl_esdhc_priv { #ifdef CONFIG_DM_GPIO struct gpio_desc cd_gpio; struct gpio_desc wp_gpio; + struct gpio_desc reset_gpio; #endif }; @@ -1449,6 +1450,8 @@ static int fsl_esdhc_probe(struct udevice *dev) GPIOD_IS_IN); if (ret) priv->wp_enable = 0; + gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio, + GPIOD_IS_OUT_ACTIVE); #endif priv->vs18_enable = 0; @@ -1520,6 +1523,12 @@ static int fsl_esdhc_probe(struct udevice *dev) } } +#ifdef CONFIG_DM_GPIO + if (dm_gpio_is_valid(&priv->reset_gpio)) { + udelay(500); + dm_gpio_set_value(&priv->reset_gpio, 0); /* release reset */ + } +#endif ret = fsl_esdhc_init(priv, plat); if (ret) { dev_err(dev, "fsl_esdhc_init failure\n"); From 3d047424a5dc6daa2d52afea3b7acb2f6b052295 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 9 Jul 2018 12:05:06 -0700 Subject: [PATCH 20/62] mach-imx: video: call imx8m_fb_init if CONFIG_VIDEO_IMXDCSS Signed-off-by: Troy Kisky --- arch/arm/mach-imx/Makefile | 1 + arch/arm/mach-imx/video.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index d236e4051083..2d501d5145d6 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -16,6 +16,7 @@ endif obj-$(CONFIG_ENV_IS_IN_MMC) += mmc_env.o obj-$(CONFIG_FEC_MXC) += mac.o obj-$(CONFIG_SYS_I2C_MXC) += i2c-mxv7.o +obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o obj-y += cpu.o endif diff --git a/arch/arm/mach-imx/video.c b/arch/arm/mach-imx/video.c index b40ce53405ae..a6baaec54881 100644 --- a/arch/arm/mach-imx/video.c +++ b/arch/arm/mach-imx/video.c @@ -3,6 +3,9 @@ #include #include #include +#ifdef CONFIG_VIDEO_IMXDCSS +#include +#endif int board_video_skip(void) { @@ -32,8 +35,13 @@ int board_video_skip(void) } if (i < display_count) { +#if defined(CONFIG_VIDEO_IPUV3) ret = ipuv3_fb_init(&displays[i].mode, displays[i].di ? 1 : 0, displays[i].pixfmt); +#elif defined(CONFIG_VIDEO_IMXDCSS) + ret = imx8m_fb_init(&displays[i].mode, displays[i].bus, + displays[i].pixfmt); +#endif if (!ret) { if (displays[i].enable) displays[i].enable(displays + i); From 37c2e6666b17282d1a2f08f208aa406dcd9700d4 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 9 Jul 2018 16:01:46 -0700 Subject: [PATCH 21/62] fsl-imx8mq.dtsi: add reg to usb3_0/usb3_1 Signed-off-by: Troy Kisky --- arch/arm/dts/fsl-imx8mq.dtsi | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm/dts/fsl-imx8mq.dtsi b/arch/arm/dts/fsl-imx8mq.dtsi index 14d4b134f232..0857c9f95ff5 100644 --- a/arch/arm/dts/fsl-imx8mq.dtsi +++ b/arch/arm/dts/fsl-imx8mq.dtsi @@ -346,7 +346,7 @@ }; usb3_0: usb@38100000 { - compatible = "fsl, imx8mq-dwc3"; + compatible = "fsl,imx8mq-dwc3"; #address-cells = <2>; #size-cells = <2>; ranges; @@ -357,6 +357,7 @@ assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_500M>, <&clk IMX8MQ_SYS1_PLL_100M>; assigned-clock-rates = <500000000>, <100000000>; + reg = <0x0 0x38100000 0x0 0x10000>; status = "disabled"; usb_dwc3_0: dwc3 { @@ -386,7 +387,7 @@ }; usb3_1: usb@38200000 { - compatible = "fsl, imx8mq-dwc3"; + compatible = "fsl,imx8mq-dwc3"; #address-cells = <2>; #size-cells = <2>; ranges; @@ -397,6 +398,7 @@ assigned-clock-parents = <&clk IMX8MQ_SYS2_PLL_500M>, <&clk IMX8MQ_SYS1_PLL_100M>; assigned-clock-rates = <500000000>, <100000000>; + reg = <0x0 0x38200000 0x0 0x10000>; status = "disabled"; usb_dwc3_1: dwc3 { From 1ff35a956da4f4a8dbc5d0d50c765df184150f59 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Tue, 10 Jul 2018 13:05:57 -0700 Subject: [PATCH 22/62] xhci-imx8m: create imx8m_usb_common_init, for use with CONFIG_DM_USB Signed-off-by: Troy Kisky --- drivers/usb/host/xhci-imx8m.c | 38 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/usb/host/xhci-imx8m.c b/drivers/usb/host/xhci-imx8m.c index 32ae1f927e59..e07bd76d4c99 100644 --- a/drivers/usb/host/xhci-imx8m.c +++ b/drivers/usb/host/xhci-imx8m.c @@ -47,7 +47,6 @@ struct imx8m_usbctrl_data { u32 usb_id; unsigned long ctr_addr; }; -static struct imx8m_xhci imx8m_xhci; static struct imx8m_usbctrl_data ctr_data[] = { {0, USB1_BASE_ADDR}, {1, USB2_BASE_ADDR}, @@ -110,30 +109,22 @@ static int imx8m_xhci_core_init(struct imx8m_xhci *imx8m_xhci) return ret; } -int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) +int imx8m_usb_common_init(void *base, struct xhci_hccr **hccr, struct xhci_hcor **hcor) { - struct imx8m_xhci *ctx = &imx8m_xhci; - int ret = 0; + int ret; + struct imx8m_xhci ctx; - ctx->hcd = (struct xhci_hccr *)(ctr_data[index].ctr_addr); - ctx->dwc3_reg = (struct dwc3 *)((char *)(ctx->hcd) + DWC3_REG_OFFSET); - ctx->usbmix_reg = (struct imx8m_usbmix *)((char *)(ctx->hcd) + - USBMIX_PHY_OFFSET); + ctx.hcd = (struct xhci_hccr *)base; + ctx.dwc3_reg = (struct dwc3 *)(base + DWC3_REG_OFFSET); + ctx.usbmix_reg = (struct imx8m_usbmix *)(base + USBMIX_PHY_OFFSET); - ret = board_usb_init(ctr_data[index].usb_id, USB_INIT_HOST); - if (ret != 0) { - imx8m_usb_power(ctr_data[index].usb_id, false); - puts("Failed to initialize board for imx8m USB\n"); - return ret; - } - - ret = imx8m_xhci_core_init(ctx); + ret = imx8m_xhci_core_init(&ctx); if (ret < 0) { puts("Failed to initialize imx8m xhci\n"); return ret; } - *hccr = (struct xhci_hccr *)ctx->hcd; + *hccr = (struct xhci_hccr *)ctx.hcd; *hcor = (struct xhci_hcor *)((uintptr_t) *hccr + HC_LENGTH(xhci_readl(&(*hccr)->cr_capbase))); @@ -144,6 +135,19 @@ int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) return ret; } +int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) +{ + int ret = 0; + + ret = board_usb_init(ctr_data[index].usb_id, USB_INIT_HOST); + if (ret != 0) { + imx8m_usb_power(ctr_data[index].usb_id, false); + puts("Failed to initialize board for imx8m USB\n"); + return ret; + } + return imx8m_usb_common_init((void*)ctr_data[index].ctr_addr, hccr, hcor); +} + void xhci_hcd_stop(int index) { board_usb_cleanup(ctr_data[index].usb_id, USB_INIT_HOST); From 05148548dd9163ef49437861e6cc765c58c13a14 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Tue, 10 Jul 2018 13:23:04 -0700 Subject: [PATCH 23/62] xhci-imx8m: add CONFIG_DM_USB support Signed-off-by: Troy Kisky --- drivers/usb/host/xhci-imx8m.c | 108 ++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) diff --git a/drivers/usb/host/xhci-imx8m.c b/drivers/usb/host/xhci-imx8m.c index e07bd76d4c99..62c88ee62058 100644 --- a/drivers/usb/host/xhci-imx8m.c +++ b/drivers/usb/host/xhci-imx8m.c @@ -9,12 +9,15 @@ */ #include +#include +#include #include #include #include #include #include #include "xhci.h" +#include /* Declare global data pointer */ DECLARE_GLOBAL_DATA_PTR; @@ -47,10 +50,22 @@ struct imx8m_usbctrl_data { u32 usb_id; unsigned long ctr_addr; }; + + +#ifdef CONFIG_DM_USB +struct xhci_imx8m_priv { + struct xhci_ctrl xhci; + struct clk_bulk clks; +#ifdef CONFIG_DM_GPIO + struct gpio_desc reset_gpio; +#endif +}; +#else static struct imx8m_usbctrl_data ctr_data[] = { {0, USB1_BASE_ADDR}, {1, USB2_BASE_ADDR}, }; +#endif static void imx8m_usb_phy_init(struct imx8m_usbmix *usbmix_reg) { @@ -135,6 +150,98 @@ int imx8m_usb_common_init(void *base, struct xhci_hccr **hccr, struct xhci_hcor return ret; } +#ifdef CONFIG_DM_USB +static int imx8_of_clk_init(struct udevice *dev, + struct xhci_imx8m_priv *priv) +{ + int ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret == -ENOSYS) + return 0; + if (ret) + return ret; + +#if CONFIG_IS_ENABLED(CLK) + ret = clk_enable_bulk(&priv->clks); + if (ret) { + clk_release_bulk(&priv->clks); + return ret; + } +#endif + + return 0; +} + +#ifdef CONFIG_DM_GPIO +static void imx8_of_reset_gpio_init(struct udevice *dev, + struct xhci_imx8m_priv *priv) +{ + gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio, + GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); + if (dm_gpio_is_valid(&priv->reset_gpio)) { + udelay(500); + /* release reset */ + dm_gpio_set_value(&priv->reset_gpio, 0); + } +} +#else +static void imx8_of_reset_gpio_init(struct udevice *dev, + struct xhci_imx8m_priv *priv) +{ +} +#endif + +static int imx8m_xhci_probe(struct udevice *dev) +{ + struct xhci_imx8m_priv *priv = dev_get_priv(dev); + struct xhci_hccr *hccr; + struct xhci_hcor *hcor; + fdt_addr_t hcd_base; + + int ret = 0; + + /* + * Get the base address for XHCI controller from the device node + */ + hcd_base = devfdt_get_addr(dev); + if (hcd_base == FDT_ADDR_T_NONE) { + printf("Can't get the XHCI register base address\n"); + return -ENXIO; + } + imx8m_usb_power(hcd_base == USB1_BASE_ADDR ? 0 : 1, true); + + imx8_of_clk_init(dev, priv); + imx8_of_reset_gpio_init(dev, priv); + ret = imx8m_usb_common_init((void *)hcd_base, &hccr, &hcor); + if (ret < 0) + return ret; + + return xhci_register(dev, hccr, hcor); +} + +static int imx8m_xhci_remove(struct udevice *dev) +{ + return xhci_deregister(dev); +} + +static const struct udevice_id xhci_usb_ids[] = { + { .compatible = "fsl,imx8mq-dwc3", }, + { } +}; + +U_BOOT_DRIVER(imx8m_xhci) = { + .name = "imx8m_xhci", + .id = UCLASS_USB, + .of_match = xhci_usb_ids, + .probe = imx8m_xhci_probe, + .remove = imx8m_xhci_remove, + .ops = &xhci_usb_ops, + .platdata_auto_alloc_size = sizeof(struct usb_platdata), + .priv_auto_alloc_size = sizeof(struct xhci_imx8m_priv), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#else int xhci_hcd_init(int index, struct xhci_hccr **hccr, struct xhci_hcor **hcor) { int ret = 0; @@ -152,3 +259,4 @@ void xhci_hcd_stop(int index) { board_usb_cleanup(ctr_data[index].usb_id, USB_INIT_HOST); } +#endif From 0fd672687e3a222048b63653ece8479b9dead90a Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Tue, 10 Jul 2018 15:13:41 -0700 Subject: [PATCH 24/62] devres: check for NULL dev in devm_kmalloc Signed-off-by: Troy Kisky --- drivers/core/devres.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/core/devres.c b/drivers/core/devres.c index f2a19ec61b19..6c429c89cc95 100644 --- a/drivers/core/devres.c +++ b/drivers/core/devres.c @@ -240,6 +240,10 @@ void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp) { void *data; + if (!dev) { + debug("%s: dev=%p\n", __func__, dev); + return kmalloc(size, gfp); + } data = _devres_alloc(devm_kmalloc_release, size, gfp); if (unlikely(!data)) return NULL; From 0e6a4df5a30208792745e466d5177aae5d66a316 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Tue, 10 Jul 2018 15:17:02 -0700 Subject: [PATCH 25/62] arm: mach-imx: mx8m: clock: turn on clock CCGR_USB_CTRL2 even if booted from USB Signed-off-by: Troy Kisky --- arch/arm/mach-imx/imx8m/clock.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/arch/arm/mach-imx/imx8m/clock.c b/arch/arm/mach-imx/imx8m/clock.c index 3766d988ba8d..31049988606d 100644 --- a/arch/arm/mach-imx/imx8m/clock.c +++ b/arch/arm/mach-imx/imx8m/clock.c @@ -373,25 +373,28 @@ void init_wdog_clk(void) clock_enable(CCGR_WDOG3, 1); } -void init_usb_clk(void) +void init_usb_clk(int usbno) { - if (!is_usb_boot()) { - clock_enable(CCGR_USB_CTRL1, 0); - clock_enable(CCGR_USB_CTRL2, 0); - clock_enable(CCGR_USB_PHY1, 0); - clock_enable(CCGR_USB_PHY2, 0); - /* 500MHz */ - clock_set_target_val(USB_BUS_CLK_ROOT, CLK_ROOT_ON | + if (!usbno) { + if (!is_usb_boot()) { + clock_enable(CCGR_USB_CTRL1, 0); + clock_enable(CCGR_USB_PHY1, 0); + clock_enable(CCGR_USB_CTRL2, 0); + clock_enable(CCGR_USB_PHY2, 0); + /* 500MHz */ + clock_set_target_val(USB_BUS_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1)); - /* 100MHz */ - clock_set_target_val(USB_CORE_REF_CLK_ROOT, CLK_ROOT_ON | + /* 100MHz */ + clock_set_target_val(USB_CORE_REF_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1)); - /* 100MHz */ - clock_set_target_val(USB_PHY_REF_CLK_ROOT, CLK_ROOT_ON | + /* 100MHz */ + clock_set_target_val(USB_PHY_REF_CLK_ROOT, CLK_ROOT_ON | CLK_ROOT_SOURCE_SEL(1)); + } clock_enable(CCGR_USB_CTRL1, 1); - clock_enable(CCGR_USB_CTRL2, 1); clock_enable(CCGR_USB_PHY1, 1); + } else { + clock_enable(CCGR_USB_CTRL2, 1); clock_enable(CCGR_USB_PHY2, 1); } } From bb11ab4bca0282c22aa83c5c020554c287424d5a Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Wed, 11 Jul 2018 17:04:14 -0700 Subject: [PATCH 26/62] mach-imx: cpu: call imx8m_fb_disable in arch_preboot_os Signed-off-by: Troy Kisky --- arch/arm/mach-imx/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index 80d9ff48a439..5fdb6f317e70 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -15,6 +15,9 @@ #include #include #include +#if defined(CONFIG_VIDEO_IMXDCSS) +#include +#endif #include #include #include @@ -298,6 +301,9 @@ void arch_preboot_os(void) #if defined(CONFIG_VIDEO_MXS) lcdif_power_down(); #endif +#if defined(CONFIG_VIDEO_IMXDCSS) + imx8m_fb_disable(); +#endif } #ifndef CONFIG_IMX8M From a75ad6bbbd710baa29f3b3b65b966f044212e3c2 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Tue, 7 Mar 2017 18:01:12 +0100 Subject: [PATCH 27/62] image-sparse: disable data cache to avoid misaligned warnings Signed-off-by: Gary Bisson --- lib/image-sparse.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/image-sparse.c b/lib/image-sparse.c index 036062139bb9..ef959f3cd9c0 100644 --- a/lib/image-sparse.c +++ b/lib/image-sparse.c @@ -62,6 +62,7 @@ int write_sparse_image(struct sparse_storage *info, chunk_header_t *chunk_header; uint32_t total_blocks = 0; int fill_buf_num_blks; + int dcache_enabled = dcache_status(); int i; int j; @@ -106,6 +107,10 @@ int write_sparse_image(struct sparse_storage *info, puts("Flashing Sparse Image\n"); + /* Disable data cache since chunks might not be aligned */ + if (dcache_enabled) + dcache_disable(); + /* Start processing chunks */ blk = info->start; for (chunk = 0; chunk < sparse_header->total_chunks; chunk++) { @@ -248,6 +253,10 @@ int write_sparse_image(struct sparse_storage *info, } } + /* Re-enable data cache it in case it was in the first place */ + if (dcache_enabled) + dcache_enable(); + debug("Wrote %d blocks, expected to write %d blocks\n", total_blocks, sparse_header->total_blks); printf("........ wrote %u bytes to '%s'\n", bytes_written, part_name); From ae5de283d4bed0a69843193e85d3fed5b702928b Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 12 Jul 2018 17:07:22 -0700 Subject: [PATCH 28/62] autoboot: use default environment if debricking board Signed-off-by: Troy Kisky --- common/autoboot.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/common/autoboot.c b/common/autoboot.c index 94133eaeda78..ef672d7f3f13 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include DECLARE_GLOBAL_DATA_PTR; @@ -296,6 +298,10 @@ const char *bootdelay_process(void) s = env_get("bootdelay"); bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; + if (is_usb_boot()) { + bootdelay = 1; + set_default_env("!Started from usb", 0); + } #ifdef CONFIG_OF_CONTROL bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", From 32653c1d327f7000b98d12fb169ff659a3c5c9c8 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 6 May 2016 10:28:49 -0700 Subject: [PATCH 29/62] i2c: add CONFIG_SYS_I2C_MASK Signed-off-by: Troy Kisky --- cmd/i2c.c | 6 ++--- drivers/i2c/i2c_core.c | 58 +++++++++++++++++++++++------------------- include/i2c.h | 3 ++- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/cmd/i2c.c b/cmd/i2c.c index 56df8eb3bca5..738d68603e0a 100644 --- a/cmd/i2c.c +++ b/cmd/i2c.c @@ -1823,11 +1823,9 @@ static int do_i2c_bus_num(cmd_tbl_t *cmdtp, int flag, int argc, printf("Current bus is %d\n", bus_no); } else { bus_no = simple_strtoul(argv[1], NULL, 10); -#if defined(CONFIG_SYS_I2C) - if (bus_no >= CONFIG_SYS_NUM_I2C_BUSES) { - printf("Invalid bus %d\n", bus_no); +#ifndef CONFIG_DM_I2C + if (!i2c_get_adapter(bus_no)) return -1; - } #endif printf("Setting bus to %d\n", bus_no); #ifdef CONFIG_DM_I2C diff --git a/drivers/i2c/i2c_core.c b/drivers/i2c/i2c_core.c index 234277a299c7..cf0d76718597 100644 --- a/drivers/i2c/i2c_core.c +++ b/drivers/i2c/i2c_core.c @@ -10,25 +10,42 @@ #include #include -struct i2c_adapter *i2c_get_adapter(int index) +struct i2c_adapter *i2c_get_adapter(int bus) { - struct i2c_adapter *i2c_adap_p = ll_entry_start(struct i2c_adapter, - i2c); - int max = ll_entry_count(struct i2c_adapter, i2c); - int i; + struct i2c_adapter *i2cp = ll_entry_start(struct i2c_adapter, i2c); - if (index >= max) { - printf("Error, wrong i2c adapter %d max %d possible\n", - index, max); - return i2c_adap_p; + bus = I2C_ADAPTER(bus); +#ifndef CONFIG_SYS_I2C_DIRECT_BUS + if (bus >= CONFIG_SYS_NUM_I2C_BUSES) { + printf("Invalid bus %d, max is %d\n", bus, + CONFIG_SYS_NUM_I2C_BUSES - 1); + return NULL; } - if (index == 0) - return i2c_adap_p; +#endif - for (i = 0; i < index; i++) - i2c_adap_p++; +#ifdef CONFIG_SYS_I2C_MASK + if (!(BIT(bus) & CONFIG_SYS_I2C_MASK)) { + printf("Invalid bus %d\n", bus); + return NULL; + } +#else + { + int max = ll_entry_count(struct i2c_adapter, i2c); + if (bus >= max) { + printf("Error, wrong i2c adapter %d max %d possible\n", + bus, max); + return NULL; + } + } +#endif + return i2cp + bus; +} - return i2c_adap_p; +struct i2c_adapter *i2c_get_adapter_valid(int bus) +{ + struct i2c_adapter *i2cp = i2c_get_adapter(bus); + + return i2cp ? i2cp : ll_entry_start(struct i2c_adapter, i2c); } #if !defined(CONFIG_SYS_I2C_DIRECT_BUS) @@ -235,22 +252,11 @@ unsigned int i2c_get_bus_num(void) */ int i2c_set_bus_num(unsigned int bus) { - int max; - if ((bus == I2C_BUS) && (I2C_ADAP->init_done > 0)) return 0; -#ifndef CONFIG_SYS_I2C_DIRECT_BUS - if (bus >= CONFIG_SYS_NUM_I2C_BUSES) + if (!i2c_get_adapter(bus)) return -1; -#endif - - max = ll_entry_count(struct i2c_adapter, i2c); - if (I2C_ADAPTER(bus) >= max) { - printf("Error, wrong i2c adapter %d max %d possible\n", - I2C_ADAPTER(bus), max); - return -2; - } #ifndef CONFIG_SYS_I2C_DIRECT_BUS i2c_mux_disconnect_all(); diff --git a/include/i2c.h b/include/i2c.h index d33f827500b1..622dd316c68d 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -615,6 +615,7 @@ struct i2c_adapter { _set_speed, _speed, _slaveaddr, _hwadapnr, _name); struct i2c_adapter *i2c_get_adapter(int index); +struct i2c_adapter *i2c_get_adapter_valid(int index); #ifndef CONFIG_SYS_I2C_DIRECT_BUS struct i2c_mux { @@ -641,7 +642,7 @@ extern struct i2c_bus_hose i2c_bus[]; #endif #define I2C_BUS gd->cur_i2c_bus -#define I2C_ADAP_NR(bus) i2c_get_adapter(I2C_ADAPTER(bus)) +#define I2C_ADAP_NR(bus) i2c_get_adapter_valid(bus) #define I2C_ADAP I2C_ADAP_NR(gd->cur_i2c_bus) #define I2C_ADAP_HWNR (I2C_ADAP->hwadapnr) From d3f738355e51a72deab83f8a69d808d622af3818 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Sat, 14 Jan 2017 13:55:02 -0700 Subject: [PATCH 30/62] crm_regs: add define for CCM_CCGR7 Signed-off-by: Troy Kisky --- arch/arm/include/asm/arch-mx6/crm_regs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index 4174f244afa1..dccf9ed7d1b3 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -14,6 +14,7 @@ #define CCM_CCGR4 0x020C4078 #define CCM_CCGR5 0x020C407c #define CCM_CCGR6 0x020C4080 +#define CCM_CCGR7 0x020C4084 #define PMU_MISC2 0x020C8170 From 66d5b5214de09da3a2f7dcaa2e816b18f5c8cd19 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 1 May 2017 11:18:29 -0700 Subject: [PATCH 31/62] crm_regs: add CCM_CBCMR/CCM_ANALOG_PFD_528 for cfg files Signed-off-by: Troy Kisky --- arch/arm/include/asm/arch-mx6/crm_regs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/include/asm/arch-mx6/crm_regs.h b/arch/arm/include/asm/arch-mx6/crm_regs.h index dccf9ed7d1b3..13d85385136d 100644 --- a/arch/arm/include/asm/arch-mx6/crm_regs.h +++ b/arch/arm/include/asm/arch-mx6/crm_regs.h @@ -6,6 +6,7 @@ #ifndef __ARCH_ARM_MACH_MX6_CCM_REGS_H__ #define __ARCH_ARM_MACH_MX6_CCM_REGS_H__ +#define CCM_CBCMR 0x020c4018 #define CCM_CCOSR 0x020c4060 #define CCM_CCGR0 0x020C4068 #define CCM_CCGR1 0x020C406c @@ -16,6 +17,7 @@ #define CCM_CCGR6 0x020C4080 #define CCM_CCGR7 0x020C4084 +#define CCM_ANALOG_PFD_528 0x020c8100 #define PMU_MISC2 0x020C8170 #ifndef __ASSEMBLY__ From 3e9831da4be0d5ebb8c410629d93c93f3e8e5a12 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Tue, 17 Jan 2017 17:23:20 -0700 Subject: [PATCH 32/62] phy: enable auto-negotiate with software reset commit a058052c358c3ecf5f394ff37def6a45eb26768c net: phy: do not read configuration register on reset broke atheros phy at8035 for the nitrogen6sx board maybe others too. This was supposed to be fixed by commit 903d384d401bdfc517266787549caf4630a7f305 Author: Alison Wang Date: Fri Feb 19 15:52:28 2016 +0800 net: phy: atheros: Fix problem with phy_reset() clearing BMCR ___ But still broken on Nitrogen6sx Signed-off-by: Troy Kisky --- drivers/net/phy/phy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index e837eb7688cc..6edd0aab0af2 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -797,7 +797,7 @@ int phy_reset(struct phy_device *phydev) } #endif - if (phy_write(phydev, devad, MII_BMCR, BMCR_RESET) < 0) { + if (phy_write(phydev, devad, MII_BMCR, BMCR_RESET|BMCR_ANENABLE) < 0) { debug("PHY reset failed\n"); return -1; } From 1253b6ca267ec3070f954eb7d66b6ca6ae81e54c Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Wed, 22 Mar 2017 15:57:47 -0700 Subject: [PATCH 33/62] fuse: make fuse read set an environment variable Signed-off-by: Troy Kisky --- cmd/fuse.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/fuse.c b/cmd/fuse.c index 42d74fa8837a..f1626a27bb2e 100644 --- a/cmd/fuse.c +++ b/cmd/fuse.c @@ -62,14 +62,19 @@ static int do_fuse(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) printf("Reading bank %u:\n", bank); for (i = 0; i < cnt; i++, word++) { + char name[16]; + char vbuf[16]; if (!(i % 4)) - printf("\nWord 0x%.8x:", word); + printf("\nWord 0x%.8x: ", word); ret = fuse_read(bank, word, &val); if (ret) goto err; - printf(" %.8x", val); + snprintf(name, sizeof(name), "fuse_read_val%x", i); + snprintf(vbuf, sizeof(vbuf), "%.8x", val); + env_set(name, vbuf); + puts(vbuf); } putc('\n'); } else if (!strcmp(op, "sense")) { From 196e5dcdf7ac5b252663b81d12857a3b864a3476 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 16 Jun 2017 14:00:10 -0700 Subject: [PATCH 34/62] spi: add s25fl064l cypress(spansion) 8MB spi-nor Signed-off-by: Troy Kisky --- drivers/mtd/spi/spi_flash_ids.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/spi/spi_flash_ids.c b/drivers/mtd/spi/spi_flash_ids.c index ad0a0c815014..a3682115ee9d 100644 --- a/drivers/mtd/spi/spi_flash_ids.c +++ b/drivers/mtd/spi/spi_flash_ids.c @@ -107,6 +107,7 @@ const struct spi_flash_info spi_flash_ids[] = { {"s25fl128p_64k", INFO(0x012018, 0x0301, 64 * 1024, 256, RD_FULL | WR_QPP) }, {"s25fl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, RD_FULL | WR_QPP) }, {"s25fl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, RD_FULL | WR_QPP) }, + {"s25fl064l", INFO(0x016017, 0x0, 64 * 1024, 128, RD_FULL | WR_QPP | SECT_4K) }, {"s25fl128s_256k", INFO(0x012018, 0x4d00, 256 * 1024, 64, RD_FULL | WR_QPP) }, {"s25fl128s_64k", INFO(0x012018, 0x4d01, 64 * 1024, 256, RD_FULL | WR_QPP) }, {"s25fl128l", INFO(0x016018, 0, 64 * 1024, 256, RD_FULL | WR_QPP) }, From be47fe9e24b12445b5f7ce5414d0eced080d381a Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Fri, 30 Jun 2017 12:59:04 +0200 Subject: [PATCH 35/62] config_distro_bootcmd: allow to add extra scripts and prefixes Signed-off-by: Gary Bisson --- include/config_distro_bootcmd.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 373fee78a999..e53fc34875cd 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -337,6 +337,12 @@ BOOTENV_DEV_NAME_##devtypeu(devtypeu, devtypel, instance) #define BOOTENV_BOOT_TARGETS \ "boot_targets=" BOOT_TARGET_DEVICES(BOOTENV_DEV_NAME) "\0" +#ifndef BOOTENV_EXTRA_BOOT_PREFIXES +#define BOOTENV_EXTRA_BOOT_PREFIXES "" +#endif +#ifndef BOOTENV_EXTRA_BOOT_SCRIPTS +#define BOOTENV_EXTRA_BOOT_SCRIPTS "" +#endif #define BOOTENV_DEV(devtypeu, devtypel, instance) \ BOOTENV_DEV_##devtypeu(devtypeu, devtypel, instance) @@ -350,9 +356,9 @@ BOOTENV_SHARED_IDE \ BOOTENV_SHARED_UBIFS \ BOOTENV_SHARED_EFI \ - "boot_prefixes=/ /boot/\0" \ - "boot_scripts=boot.scr.uimg boot.scr\0" \ - "boot_script_dhcp=boot.scr.uimg\0" \ + "boot_prefixes=/ /boot/" BOOTENV_EXTRA_BOOT_PREFIXES "\0" \ + "boot_scripts=boot.scr.uimg boot.scr" BOOTENV_EXTRA_BOOT_SCRIPTS "\0" \ + "boot_script_dhcp=boot.scr.uimg" BOOTENV_EXTRA_BOOT_SCRIPTS "\0" \ BOOTENV_BOOT_TARGETS \ \ "boot_extlinux=" \ From 0bea657daf911a0dcfc102e1038af96a13231ef6 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Fri, 30 Jun 2017 12:59:44 +0200 Subject: [PATCH 36/62] config_distro_bootcmd: workaround 6x_bootscript legacy The script currently doesn't use the standard distro variables. Signed-off-by: Gary Bisson --- include/config_distro_bootcmd.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index e53fc34875cd..13336a146c30 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -375,6 +375,9 @@ "fi\0" \ \ "boot_a_script=" \ + "setenv disk ${devnum}; " \ + "setenv dtype ${devtype}; " \ + "setenv bootpart ${distro_bootpart}; " \ "load ${devtype} ${devnum}:${distro_bootpart} " \ "${scriptaddr} ${prefix}${script}; " \ "source ${scriptaddr}\0" \ From 13fcbb91d38fa556d4d31ff27c7482b3b5f72a25 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Mon, 7 Aug 2017 15:15:44 -0700 Subject: [PATCH 37/62] arch: arm: relocate: print invalid relocation entries Signed-off-by: Troy Kisky --- arch/arm/lib/relocate.S | 91 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/arch/arm/lib/relocate.S b/arch/arm/lib/relocate.S index e5f7267be193..0b6092e2ec41 100644 --- a/arch/arm/lib/relocate.S +++ b/arch/arm/lib/relocate.S @@ -78,6 +78,7 @@ ENDPROC(relocate_vectors) */ ENTRY(relocate_code) + stmdb sp!, {lr} ldr r1, =__image_copy_start /* r1 <- SRC &__image_copy_start */ subs r4, r0, r1 /* r4 <- relocation offset */ beq relocate_done /* skip relocation */ @@ -100,6 +101,20 @@ fixloop: cmp r1, #R_ARM_RELATIVE bne fixnext + tst r0, #3 + beq 1f + sub r0, r2, #8 + bl prhex + mov r0, #':' + bl pr_c + ldr r0,[r2, #-8] + bl prhex + mov r0, #'_' + bl pr_c + ldr r0,[r2, #-4] + bl prhex + b fixnext +1: /* relative fix: increase location by offset */ add r0, r0, r4 ldr r1, [r0] @@ -125,7 +140,81 @@ relocate_done: #ifdef __ARM_ARCH_4__ mov pc, lr #else - bx lr + ldmia sp!, {pc} #endif ENDPROC(relocate_code) + +ENTRY(prhex) + stmdb sp!, {r0-r6,lr} + mov r6, #8 + mov r5, r0 +1: mov r0, r5, lsr #28 + cmp r0, #10 + addlt r0, r0, #'0' + addge r0, r0, #'a' - 10 + bl pr_c + mov r5, r5, lsl #4 + subs r6, r6, #1 + bne 1b + + mov r0,#'\n' + bl pr_c + mov r0,#'\r' + bl pr_c + ldmia sp!, {r0-r6,pc} +ENDPROC(prhex) + +#define UTXD 0x40 +#define UTS 0xb4 +#define UTS_TXEMPTY (1<<6) + +ENTRY(pr_c) + stmdb sp!, {r0-r1,lr} + ldr r1, =CONFIG_MXC_UART_BASE + str r0, [r1,#UTXD] + +1: ldr r0, [r1,#UTS] + tst r0, #UTS_TXEMPTY + beq 1b + ldmia sp!, {r0-r1,pc} +ENDPROC(pr_c) + +#if 0 +ENTRY(verify_relocate_table) + stmdb sp!, {lr} + /* + * check .rel.dyn relocations + */ + ldr r2, =__rel_dyn_start /* r2 <- SRC &__rel_dyn_start */ + ldr r3, =__rel_dyn_end /* r3 <- SRC &__rel_dyn_end */ +1: + ldmia r2!, {r0-r1} /* (r0,r1) <- (SRC location,fixup) */ + and r1, r1, #0xff + cmp r1, #R_ARM_RELATIVE + bne 3f + + tst r0, #3 + beq 2f + sub r0, r2, #8 + bl prhex + mov r0, #':' + bl pr_c + ldr r0,[r2, #-8] + bl prhex + mov r0, #'_' + bl pr_c + ldr r0,[r2, #-4] + bl prhex + mov r0, #1 + ldmia sp!, {pc} +2: +3: + cmp r2, r3 + blo 1b + + mov r0, #0 + ldmia sp!, {pc} + +ENDPROC(verify_relocate_table) +#endif From 5eb2c3b35fe15c4d26d63b5aa3dab559cad7a9f6 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Sun, 3 Sep 2017 14:06:39 -0700 Subject: [PATCH 38/62] config_distro_bootcmd: search /boot/ before / Signed-off-by: Troy Kisky --- include/config_distro_bootcmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config_distro_bootcmd.h b/include/config_distro_bootcmd.h index 13336a146c30..505c18dd6c60 100644 --- a/include/config_distro_bootcmd.h +++ b/include/config_distro_bootcmd.h @@ -356,7 +356,7 @@ BOOTENV_SHARED_IDE \ BOOTENV_SHARED_UBIFS \ BOOTENV_SHARED_EFI \ - "boot_prefixes=/ /boot/" BOOTENV_EXTRA_BOOT_PREFIXES "\0" \ + "boot_prefixes=/boot/ /" BOOTENV_EXTRA_BOOT_PREFIXES "\0" \ "boot_scripts=boot.scr.uimg boot.scr" BOOTENV_EXTRA_BOOT_SCRIPTS "\0" \ "boot_script_dhcp=boot.scr.uimg" BOOTENV_EXTRA_BOOT_SCRIPTS "\0" \ BOOTENV_BOOT_TARGETS \ From 8263850f0409488a10c6c37befa0ecc32f4f91fe Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 12 Oct 2017 18:00:03 -0700 Subject: [PATCH 39/62] usb_hub: check for timeout if no connection as well Signed-off-by: Troy Kisky --- common/usb_hub.c | 44 ++++++++++++++++++++------------------------ 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/common/usb_hub.c b/common/usb_hub.c index e1d93b833358..4b1e899a2946 100644 --- a/common/usb_hub.c +++ b/common/usb_hub.c @@ -196,7 +196,7 @@ static void usb_hub_power_on(struct usb_hub_device *hub) * Do a minimum delay of the larger value of 100ms or pgood_delay * so that the power can stablize before the devices are queried */ - hub->query_delay = get_timer(0) + max(100, (int)pgood_delay); + hub->query_delay = max(100, (int)pgood_delay); /* * Record the power-on timeout here. The max. delay (timeout) @@ -427,7 +427,7 @@ int usb_hub_port_connect_change(struct usb_device *dev, int port) return ret; } -static int usb_scan_port(struct usb_device_scan *usb_scan) +static int usb_scan_port(struct usb_device_scan *usb_scan, unsigned long start) { ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1); unsigned short portstatus; @@ -445,21 +445,13 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) * Don't talk to the device before the query delay is expired. * This is needed for voltages to stabalize. */ - if (get_timer(0) < hub->query_delay) + if (get_timer(start) < hub->query_delay) return 0; ret = usb_get_port_status(dev, i + 1, portsts); if (ret < 0) { debug("get_port_status failed\n"); - if (get_timer(0) >= hub->connect_timeout) { - debug("devnum=%d port=%d: timeout\n", - dev->devnum, i + 1); - /* Remove this device from scanning list */ - list_del(&usb_scan->list); - free(usb_scan); - return 0; - } - return 0; + goto check_timeout; } portstatus = le16_to_cpu(portsts->wPortStatus); @@ -474,17 +466,8 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) * in the PORTSC register of a root hub), ignore such case. */ if (!(portchange & USB_PORT_STAT_C_CONNECTION) && - !(portstatus & USB_PORT_STAT_CONNECTION)) { - if (get_timer(0) >= hub->connect_timeout) { - debug("devnum=%d port=%d: timeout\n", - dev->devnum, i + 1); - /* Remove this device from scanning list */ - list_del(&usb_scan->list); - free(usb_scan); - return 0; - } - return 0; - } + !(portstatus & USB_PORT_STAT_CONNECTION)) + goto check_timeout; if (portchange & USB_PORT_STAT_C_RESET) { debug("port %d reset change\n", i + 1); @@ -558,6 +541,16 @@ static int usb_scan_port(struct usb_device_scan *usb_scan) list_del(&usb_scan->list); free(usb_scan); + return 0; +check_timeout: + if (get_timer(start) >= hub->connect_timeout) { + debug("devnum=%d port=%d: timeout\n", + dev->devnum, i + 1); + /* Remove this device from scanning list */ + list_del(&usb_scan->list); + free(usb_scan); + return 0; + } return 0; } @@ -567,6 +560,7 @@ static int usb_device_list_scan(void) struct usb_device_scan *tmp; static int running; int ret = 0; + unsigned long start; /* Only run this loop once for each controller */ if (running) @@ -574,16 +568,18 @@ static int usb_device_list_scan(void) running = 1; + start = get_timer(0); while (1) { /* We're done, once the list is empty again */ if (list_empty(&usb_scan_list)) goto out; + mdelay(1); list_for_each_entry_safe(usb_scan, tmp, &usb_scan_list, list) { int ret; /* Scan this port */ - ret = usb_scan_port(usb_scan); + ret = usb_scan_port(usb_scan, start); if (ret) goto out; } From a8a88d9d949836a6078221689f4e0edcc40c4a1f Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Thu, 24 May 2018 15:58:02 -0700 Subject: [PATCH 40/62] mmc: fsl_esdhc: send 80 clocks before 1st command Signed-off-by: Troy Kisky --- drivers/mmc/fsl_esdhc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c index 39e708878abd..655c2d7504fd 100644 --- a/drivers/mmc/fsl_esdhc.c +++ b/drivers/mmc/fsl_esdhc.c @@ -148,6 +148,7 @@ struct fsl_esdhc_priv { struct gpio_desc wp_gpio; struct gpio_desc reset_gpio; #endif + int sysctrl_inita_needed; }; /* Return the XFERTYP flags for a given command and data packet */ @@ -421,6 +422,18 @@ static int esdhc_send_cmd_common(struct fsl_esdhc_priv *priv, struct mmc *mmc, * resolve timing issues with some cards */ udelay(1000); + if (priv->sysctrl_inita_needed) { + unsigned long start; + + /* send 80 clocks before 1st command */ + priv->sysctrl_inita_needed = 0; + esdhc_setbits32(®s->sysctl, SYSCTL_INITA); + start = get_timer(0); + while (esdhc_read32(®s->sysctl) & SYSCTL_INITA) { + if (get_timer(start) >= 10) + break; + } + } /* Set up for a data transfer if we have one */ if (data) { @@ -981,7 +994,7 @@ static int esdhc_init_common(struct fsl_esdhc_priv *priv, struct mmc *mmc) /* Reset the entire host controller */ esdhc_setbits32(®s->sysctl, SYSCTL_RSTA); - + priv->sysctrl_inita_needed = 1; /* Wait until the controller is available */ start = get_timer(0); while ((esdhc_read32(®s->sysctl) & SYSCTL_RSTA)) { @@ -1129,6 +1142,7 @@ static int fsl_esdhc_init(struct fsl_esdhc_priv *priv, regs = priv->esdhc_regs; /* First reset the eSDHC controller */ + priv->sysctrl_inita_needed = 1; ret = esdhc_reset(regs); if (ret) return ret; From 21747e8e4a61e0677893411a275a96e9be7cd5a7 Mon Sep 17 00:00:00 2001 From: Troy Kisky Date: Fri, 20 Jul 2018 17:03:42 -0700 Subject: [PATCH 41/62] arm: mach-imx: cpu: add is_usb_boot Signed-off-by: Troy Kisky --- arch/arm/include/asm/arch-mx5/sys_proto.h | 1 + arch/arm/include/asm/arch-mx6/sys_proto.h | 1 + arch/arm/include/asm/arch-mx7/sys_proto.h | 1 + arch/arm/mach-imx/cpu.c | 41 +++++++++++++++++++++++ arch/arm/mach-imx/imx8m/soc.c | 5 --- 5 files changed, 44 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/arch-mx5/sys_proto.h b/arch/arm/include/asm/arch-mx5/sys_proto.h index c8aff2b65dc9..e94b7da99193 100644 --- a/arch/arm/include/asm/arch-mx5/sys_proto.h +++ b/arch/arm/include/asm/arch-mx5/sys_proto.h @@ -8,4 +8,5 @@ #include +bool is_usb_boot(void); #endif /* __SYS_PROTO_IMX5_ */ diff --git a/arch/arm/include/asm/arch-mx6/sys_proto.h b/arch/arm/include/asm/arch-mx6/sys_proto.h index 4bf7dff8b4d0..a38841605863 100644 --- a/arch/arm/include/asm/arch-mx6/sys_proto.h +++ b/arch/arm/include/asm/arch-mx6/sys_proto.h @@ -30,4 +30,5 @@ static inline void iomuxc_set_rgmii_io_voltage(int io_vol) __raw_writel(io_vol, IOMUXC_SW_PAD_CTL_GRP_DDR_TYPE_RGMII); } +bool is_usb_boot(void); #endif /* __SYS_PROTO_IMX6_ */ diff --git a/arch/arm/include/asm/arch-mx7/sys_proto.h b/arch/arm/include/asm/arch-mx7/sys_proto.h index e46a02198d66..42663a438879 100644 --- a/arch/arm/include/asm/arch-mx7/sys_proto.h +++ b/arch/arm/include/asm/arch-mx7/sys_proto.h @@ -9,5 +9,6 @@ void set_wdog_reset(struct wdog_regs *wdog); enum boot_device get_boot_device(void); +bool is_usb_boot(void); #endif /* __SYS_PROTO_IMX7_ */ diff --git a/arch/arm/mach-imx/cpu.c b/arch/arm/mach-imx/cpu.c index 5fdb6f317e70..eeea0156d36c 100644 --- a/arch/arm/mach-imx/cpu.c +++ b/arch/arm/mach-imx/cpu.c @@ -455,6 +455,47 @@ enum boot_device get_boot_device(void) return boot_dev; } + +bool is_usb_boot(void) +{ + return get_boot_device() == USB_BOOT; +} +#elif defined(CONFIG_MX6) +bool is_usb_boot(void) +{ + unsigned int bmode = readl(&src_base->sbmr2); + u32 reg; + + /* + * Check for BMODE if serial downloader is enabled + * BOOT_MODE - see IMX6DQRM Table 8-1 + */ + if (((bmode >> 24) & 0x03) == 0x01) /* Serial Downloader */ + return true; + + /* + * The above method does not detect that the boot ROM used + * serial downloader in case the boot ROM decided to use the + * serial downloader as a fall back (primary boot source failed). + * + * Infer that the boot ROM used the USB serial downloader by + * checking whether the USB PHY is currently active... This + * assumes that SPL did not (yet) initialize the USB PHY... + */ + if (is_usbotg_phy_active()) + return true; + + reg = (imx6_src_get_boot_mode() & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT; + + if (reg == IMX6_BMODE_RESERVED) + return true; + return false; +} +#else +bool is_usb_boot(void) +{ + return false; +} #endif #ifdef CONFIG_NXP_BOARD_REVISION diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index 593a7dfb111b..f67dad49ecf0 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -167,11 +167,6 @@ int arch_cpu_init(void) return 0; } -bool is_usb_boot(void) -{ - return get_boot_device() == USB_BOOT; -} - #ifdef CONFIG_OF_SYSTEM_SETUP int ft_system_setup(void *blob, bd_t *bd) { From 1e365abcd8637c8c6afa2ea6341317badfdb8a7a Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Wed, 28 Nov 2018 20:12:48 +0100 Subject: [PATCH 42/62] imx: fixup Kconfig to align with MX8M to IMX8M change pending patch imx: rename mx8m,MX8M to imx8m,IMX8M failed to change a few Kconfig options that depended on the MX8M naming. This updates them to reflect the proposed patch. Signed-off-by: Jon Nettleton --- drivers/serial/Kconfig | 2 +- drivers/video/Kconfig | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 2b4ba3c89453..ed3943ce2918 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -522,7 +522,7 @@ config MVEBU_A3700_UART config MXC_UART bool "IMX serial port support" - depends on MX5 || MX6 || MX7 || MX8M + depends on MX5 || MX6 || MX7 || IMX8M help If you have a machine based on a Motorola IMX CPU you can enable its onboard serial port by enabling this option. diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 55448905f7a6..6e536bbf5fe2 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -555,7 +555,7 @@ config VIDEO_IPUV3 config VIDEO_IMXDCSS bool "i.MX8 DCSS display support" default n - depends on VIDEO && MX8M + depends on VIDEO && IMX8M help Support for DCSS display controller for i.MX8 processors. @@ -571,7 +571,7 @@ config VIDEO_IMX_HDP_LOAD config VIDEO_IMX8_HDMI bool "i.MX8 HDMI Splash screen" default n - depends on VIDEO && MX8M + depends on VIDEO && IMX8M help Support for HDMI i.MX8 processors. From 4010dc3f606e07991078296b6349ca6797ad57cb Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Wed, 28 Nov 2018 20:05:49 +0100 Subject: [PATCH 43/62] imx: add preliminary i.MX8MQ support for SolidRun boards Add imx8mq_hb support which is the first i.MX8MQ based board from SolidRun. This commit is based on the support that has already or been merged upstream, including the soon to be merged lpddr4 initialization code. U-Boot SPL 2018.11-00058-g517ec4c76c (Nov 28 2018 - 20:01:44 +0100) PMIC: PFUZE100 ID=0x10 Normal Boot Trying to boot from MMC2 NOTICE: Configureing TZASC380 NOTICE: BL31: v1.6(release):v1.6-110-gb86481c5 NOTICE: BL31: Built : 09:03:59, Sep 30 2018 NOTICE: sip svc init U-Boot 2018.11-00058-g517ec4c76c (Nov 28 2018 - 20:01:44 +0100) CPU: Freescale i.MX8MQ rev2.0 at 1000 MHz Reset cause: POR Model: SolidRun i.MX8MQ HummingBoard Pulse DRAM: 3 GiB MMC: FSL_SDHC: 0, FSL_SDHC: 1 Loading Environment from MMC... OK In: serial Out: serial Err: serial Net: Error: ethernet@30be0000 address not set. Signed-off-by: Jon Nettleton --- arch/arm/dts/Makefile | 3 +- arch/arm/dts/fsl-imx8mq-hb.dts | 439 ++++++++ arch/arm/mach-imx/imx8m/Kconfig | 6 + board/solidrun/imx8mq_hb/Kconfig | 12 + board/solidrun/imx8mq_hb/MAINTAINERS | 6 + board/solidrun/imx8mq_hb/Makefile | 15 + board/solidrun/imx8mq_hb/README | 38 + board/solidrun/imx8mq_hb/imx8mq_hb.c | 162 +++ board/solidrun/imx8mq_hb/lpddr4_timing.c | 1201 ++++++++++++++++++++++ board/solidrun/imx8mq_hb/spl.c | 243 +++++ configs/imx8mq_hb_defconfig | 66 ++ include/configs/imx8mq_hb.h | 270 +++++ 12 files changed, 2460 insertions(+), 1 deletion(-) create mode 100644 arch/arm/dts/fsl-imx8mq-hb.dts create mode 100644 board/solidrun/imx8mq_hb/Kconfig create mode 100644 board/solidrun/imx8mq_hb/MAINTAINERS create mode 100644 board/solidrun/imx8mq_hb/Makefile create mode 100644 board/solidrun/imx8mq_hb/README create mode 100644 board/solidrun/imx8mq_hb/imx8mq_hb.c create mode 100644 board/solidrun/imx8mq_hb/lpddr4_timing.c create mode 100644 board/solidrun/imx8mq_hb/spl.c create mode 100644 configs/imx8mq_hb_defconfig create mode 100644 include/configs/imx8mq_hb.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index b0ba033549db..c2809ab9e0b1 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -456,7 +456,8 @@ dtb-$(CONFIG_ARCH_MX7ULP) += imx7ulp-evk.dtb dtb-$(CONFIG_ARCH_IMX8) += fsl-imx8qxp-mek.dtb -dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb +dtb-$(CONFIG_ARCH_IMX8M) += fsl-imx8mq-evk.dtb \ + fsl-imx8mq-hb.dtb dtb-$(CONFIG_RCAR_GEN3) += \ r8a7795-h3ulcb-u-boot.dtb \ diff --git a/arch/arm/dts/fsl-imx8mq-hb.dts b/arch/arm/dts/fsl-imx8mq-hb.dts new file mode 100644 index 000000000000..7766f7523e11 --- /dev/null +++ b/arch/arm/dts/fsl-imx8mq-hb.dts @@ -0,0 +1,439 @@ +/* + * Copyright (C) 2016 Freescale Semiconductor, Inc. + * Copyright 2017 NXP + * + * 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. + */ + +/dts-v1/; + +/* First 128KB is for PSCI ATF. */ +/memreserve/ 0x40000000 0x00020000; + +#include "fsl-imx8mq.dtsi" + +/ { + model = "SolidRun i.MX8MQ HummingBoard Pulse"; + compatible = "solidrun,hummingboard-pulse", "fsl,imx8mq"; + + chosen { + bootargs = "console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200"; + stdout-path = &uart1; + }; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_usdhc2_vmmc: usdhc2_vmmc { + compatible = "regulator-fixed"; + regulator-name = "VSD_3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; + enable-active-high; + }; + }; +}; + +&iomuxc { + pinctrl-names = "default"; + + imx8mq-sr-hb { + pinctrl_fec1: fec1grp { + fsl,pins = < + MX8MQ_IOMUXC_ENET_MDC_ENET1_MDC 0x3 + MX8MQ_IOMUXC_ENET_MDIO_ENET1_MDIO 0x23 + MX8MQ_IOMUXC_ENET_TD3_ENET1_RGMII_TD3 0x1f + MX8MQ_IOMUXC_ENET_TD2_ENET1_RGMII_TD2 0x1f + MX8MQ_IOMUXC_ENET_TD1_ENET1_RGMII_TD1 0x1f + MX8MQ_IOMUXC_ENET_TD0_ENET1_RGMII_TD0 0x1f + MX8MQ_IOMUXC_ENET_RD3_ENET1_RGMII_RD3 0x91 + MX8MQ_IOMUXC_ENET_RD2_ENET1_RGMII_RD2 0x91 + MX8MQ_IOMUXC_ENET_RD1_ENET1_RGMII_RD1 0x91 + MX8MQ_IOMUXC_ENET_RD0_ENET1_RGMII_RD0 0x91 + MX8MQ_IOMUXC_ENET_TXC_ENET1_RGMII_TXC 0x1f + MX8MQ_IOMUXC_ENET_RXC_ENET1_RGMII_RXC 0x91 + MX8MQ_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL 0x91 + MX8MQ_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL 0x1f + MX8MQ_IOMUXC_GPIO1_IO09_GPIO1_IO9 0x19 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C1_SCL_I2C1_SCL 0x4000007f + MX8MQ_IOMUXC_I2C1_SDA_I2C1_SDA 0x4000007f + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX8MQ_IOMUXC_I2C2_SCL_I2C2_SCL 0x4000007f + MX8MQ_IOMUXC_I2C2_SDA_I2C2_SDA 0x4000007f + >; + }; + + + pinctrl_qspi: qspigrp { + fsl,pins = < + MX8MQ_IOMUXC_NAND_ALE_QSPI_A_SCLK 0x82 + MX8MQ_IOMUXC_NAND_CE0_B_QSPI_A_SS0_B 0x82 + MX8MQ_IOMUXC_NAND_DATA00_QSPI_A_DATA0 0x82 + MX8MQ_IOMUXC_NAND_DATA01_QSPI_A_DATA1 0x82 + MX8MQ_IOMUXC_NAND_DATA02_QSPI_A_DATA2 0x82 + MX8MQ_IOMUXC_NAND_DATA03_QSPI_A_DATA3 0x82 + + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX8MQ_IOMUXC_UART1_RXD_UART1_DCE_RX 0x49 + MX8MQ_IOMUXC_UART1_TXD_UART1_DCE_TX 0x49 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX8MQ_IOMUXC_UART2_TXD_UART2_DCE_TX 0x49 + MX8MQ_IOMUXC_UART2_RXD_UART2_DCE_RX 0x49 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX8MQ_IOMUXC_UART3_TXD_UART3_DCE_TX 0x79 + MX8MQ_IOMUXC_UART3_RXD_UART3_DCE_RX 0x79 + MX8MQ_IOMUXC_ECSPI1_MISO_UART3_DCE_CTS_B 0x79 + MX8MQ_IOMUXC_ECSPI1_SS0_UART3_DCE_RTS_B 0x79 + MX8MQ_IOMUXC_NAND_CLE_GPIO3_IO5 0x19 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x83 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc3 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc3 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc3 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc3 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc3 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc3 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc3 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc3 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc3 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x83 + MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 + >; + }; + + pinctrl_usdhc1_100mhz: usdhc1grp100mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x85 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc5 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc5 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc5 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc5 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc5 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc5 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc5 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc5 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc5 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x85 + MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 + >; + }; + + pinctrl_usdhc1_200mhz: usdhc1grp200mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK 0x87 + MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0xc7 + MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0xc7 + MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0xc7 + MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0xc7 + MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3 0xc7 + MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4 0xc7 + MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5 0xc7 + MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6 0xc7 + MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7 0xc7 + MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE 0x87 + MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B 0xc1 + >; + }; + + pinctrl_usdhc2_gpio: usdhc2grpgpio { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CD_B_GPIO2_IO12 0x41 + MX8MQ_IOMUXC_SD2_RESET_B_GPIO2_IO19 0x41 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x83 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc3 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc3 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc3 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc3 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc3 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_100mhz: usdhc2grp100mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x85 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc5 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc5 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc5 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc5 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc5 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_usdhc2_200mhz: usdhc2grp200mhz { + fsl,pins = < + MX8MQ_IOMUXC_SD2_CLK_USDHC2_CLK 0x87 + MX8MQ_IOMUXC_SD2_CMD_USDHC2_CMD 0xc7 + MX8MQ_IOMUXC_SD2_DATA0_USDHC2_DATA0 0xc7 + MX8MQ_IOMUXC_SD2_DATA1_USDHC2_DATA1 0xc7 + MX8MQ_IOMUXC_SD2_DATA2_USDHC2_DATA2 0xc7 + MX8MQ_IOMUXC_SD2_DATA3_USDHC2_DATA3 0xc7 + MX8MQ_IOMUXC_GPIO1_IO04_USDHC2_VSELECT 0xc1 + >; + }; + + pinctrl_sai2: sai2grp { + fsl,pins = < + MX8MQ_IOMUXC_SAI2_TXFS_SAI2_TX_SYNC 0xd6 + MX8MQ_IOMUXC_SAI2_TXC_SAI2_TX_BCLK 0xd6 + MX8MQ_IOMUXC_SAI2_MCLK_SAI2_MCLK 0xd6 + MX8MQ_IOMUXC_SAI2_TXD0_SAI2_TX_DATA0 0xd6 + MX8MQ_IOMUXC_GPIO1_IO08_GPIO1_IO8 0xd6 + >; + }; + + pinctrl_wdog: wdoggrp { + fsl,pins = < + MX8MQ_IOMUXC_GPIO1_IO02_WDOG1_WDOG_B 0xc6 + >; + }; + }; +}; + +&fec1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_fec1>; + phy-mode = "rgmii-id"; + phy-handle = <ðphy0>; + fsl,magic-packet; + status = "okay"; + + mdio { + #address-cells = <1>; + #size-cells = <0>; + + ethphy0: ethernet-phy@0 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <0>; + at803x,led-act-blind-workaround; + at803x,eee-disabled; + }; + }; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + + pmic: pfuze100@08 { + compatible = "fsl,pfuze100"; + reg = <0x08>; + + regulators { + sw1a_reg: sw1ab { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-always-on; + }; + + sw1c_reg: sw1c { + regulator-min-microvolt = <300000>; + regulator-max-microvolt = <1875000>; + regulator-always-on; + }; + + sw2_reg: sw2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + sw3a_reg: sw3ab { + regulator-min-microvolt = <400000>; + regulator-max-microvolt = <1975000>; + regulator-always-on; + }; + + sw4_reg: sw4 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + swbst_reg: swbst { + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5150000>; + }; + + snvs_reg: vsnvs { + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <3000000>; + regulator-always-on; + }; + + vref_reg: vrefddr { + regulator-always-on; + }; + + vgen1_reg: vgen1 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + }; + + vgen2_reg: vgen2 { + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1550000>; + regulator-always-on; + }; + + vgen3_reg: vgen3 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen4_reg: vgen4 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen5_reg: vgen5 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vgen6_reg: vgen6 { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + }; + }; + }; +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "disabled"; +}; + +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_qspi>; + status = "okay"; + + flash0: n25q256a@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + compatible = "micron,n25q256a"; + spi-max-frequency = <29000000>; + spi-nor,ddr-quad-read-dummy = <6>; + }; +}; + +&uart1 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + assigned-clocks = <&clk IMX8MQ_CLK_UART1_SRC>; + assigned-clock-parents = <&clk IMX8MQ_CLK_25M>; + status = "okay"; +}; + +&uart2 { /* console */ + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + assigned-clocks = <&clk IMX8MQ_CLK_UART2_SRC>; + assigned-clock-parents = <&clk IMX8MQ_CLK_25M>; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc1>; + pinctrl-1 = <&pinctrl_usdhc1_100mhz>; + pinctrl-2 = <&pinctrl_usdhc1_200mhz>; + bus-width = <8>; + non-removable; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default", "state_100mhz", "state_200mhz"; + pinctrl-0 = <&pinctrl_usdhc2>, <&pinctrl_usdhc2_gpio>; + pinctrl-1 = <&pinctrl_usdhc2_100mhz>, <&pinctrl_usdhc2_gpio>; + pinctrl-2 = <&pinctrl_usdhc2_200mhz>, <&pinctrl_usdhc2_gpio>; + bus-width = <4>; + cd-gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + vmmc-supply = <®_usdhc2_vmmc>; + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +&usb3_0 { + status = "okay"; +}; + +&usb_dwc3_0 { + status = "okay"; + dr_mode = "peripheral"; +}; + +&usb3_phy1 { + status = "okay"; +}; + +&usb3_1 { + status = "okay"; +}; + +&usb_dwc3_1 { + status = "okay"; + dr_mode = "host"; +}; + +&wdog1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_wdog>; + fsl,ext-reset-output; + status = "okay"; +}; diff --git a/arch/arm/mach-imx/imx8m/Kconfig b/arch/arm/mach-imx/imx8m/Kconfig index 317dee9bc191..175179ffb0eb 100644 --- a/arch/arm/mach-imx/imx8m/Kconfig +++ b/arch/arm/mach-imx/imx8m/Kconfig @@ -16,8 +16,14 @@ config TARGET_IMX8MQ_EVK select IMX8M select IMX8M_LPDDR4 +config TARGET_IMX8MQ_HB + bool "imx8mq_hb" + select IMX8M + select IMX8M_LPDDR4 + endchoice source "board/freescale/imx8mq_evk/Kconfig" +source "board/solidrun/imx8mq_hb/Kconfig" endif diff --git a/board/solidrun/imx8mq_hb/Kconfig b/board/solidrun/imx8mq_hb/Kconfig new file mode 100644 index 000000000000..2e6e317e6e95 --- /dev/null +++ b/board/solidrun/imx8mq_hb/Kconfig @@ -0,0 +1,12 @@ +if TARGET_IMX8MQ_HB + +config SYS_BOARD + default "imx8mq_hb" + +config SYS_VENDOR + default "solidrun" + +config SYS_CONFIG_NAME + default "imx8mq_hb" + +endif diff --git a/board/solidrun/imx8mq_hb/MAINTAINERS b/board/solidrun/imx8mq_hb/MAINTAINERS new file mode 100644 index 000000000000..789c8cb895a7 --- /dev/null +++ b/board/solidrun/imx8mq_hb/MAINTAINERS @@ -0,0 +1,6 @@ +i.MX8MQ HB BOARD +M: Jon Nettleton +S: Maintained +F: board/solidrun/imx8mq_hb/ +F: include/configs/imx8mq_hb.h +F: configs/imx8mq_hb_defconfig diff --git a/board/solidrun/imx8mq_hb/Makefile b/board/solidrun/imx8mq_hb/Makefile new file mode 100644 index 000000000000..c6be648e32ef --- /dev/null +++ b/board/solidrun/imx8mq_hb/Makefile @@ -0,0 +1,15 @@ +# +# Copyright 2018 Solid-Run Ltd. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y += imx8mq_hb.o + +ifdef CONFIG_SPL_BUILD +obj-y += spl.o +obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing.o +endif + +obj-$(CONFIG_POWER_PFUZE100) += ../../freescale/common/pfuze.o +obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += ../../freescale/common/pfuze_dm.o diff --git a/board/solidrun/imx8mq_hb/README b/board/solidrun/imx8mq_hb/README new file mode 100644 index 000000000000..54d8a2cdaed1 --- /dev/null +++ b/board/solidrun/imx8mq_hb/README @@ -0,0 +1,38 @@ +U-Boot for the NXP i.MX8MQ EVK board + +Quick Start +==================== +- Build the ARM Trusted firmware binary +- Get ddr and hdmi fimware +- Build U-Boot +- Boot + +Get and Build the ARM Trusted firmware +==================== +Note: srctree is U-Boot source directory +Get ATF from: https://github.com/SolidRun/arm-trusted-firmware.git +branch: imx-atf-v1.6 +$ make PLAT=imx8mq bl31 +$ cp build/imx8mq/release/bl31.bin $(srctree) + +Get the ddr and hdmi firmware +==================== +Note: srctree is U-Boot source directory +$ wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-7.9.bin +$ chmod +x firmware-imx-7.9.bin +$ cp firmware-imx-7.9/firmware/hdmi/cadence/signed_hdmi_imx8m.bin $(srctree) +$ cp firmware-imx-7.9/firmware-imx-7.9/firmware/ddr/synopsys/lpddr4*.bin $(srctree) + +Build U-Boot +==================== +$ export ARCH=arm64 +$ export CROSS_COMPILE=aarch64-poky-linux- +$ make imx8mq_hb_defconfig +$ make flash.bin + +Burn the flash.bin to MicroSD card offset 33KB +$sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 + +Boot +==================== +Set Boot switch SW801: 1100 and Bmode: 10 to boot from Micro SD. diff --git a/board/solidrun/imx8mq_hb/imx8mq_hb.c b/board/solidrun/imx8mq_hb/imx8mq_hb.c new file mode 100644 index 000000000000..851b455e9854 --- /dev/null +++ b/board/solidrun/imx8mq_hb/imx8mq_hb.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../freescale/common/pfuze.h" + +DECLARE_GLOBAL_DATA_PTR; + +#define QSPI_PAD_CTRL (PAD_CTL_DSE2 | PAD_CTL_HYS) + +#define UART_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_FSEL1) + +#define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE) + +static iomux_v3_cfg_t const wdog_pads[] = { + IMX8MQ_PAD_GPIO1_IO02__WDOG1_WDOG_B | MUX_PAD_CTRL(WDOG_PAD_CTRL), +}; + +static iomux_v3_cfg_t const uart_pads[] = { + IMX8MQ_PAD_UART1_RXD__UART1_RX | MUX_PAD_CTRL(UART_PAD_CTRL), + IMX8MQ_PAD_UART1_TXD__UART1_TX | MUX_PAD_CTRL(UART_PAD_CTRL), +}; + +#ifdef CONFIG_FSL_QSPI +static iomux_v3_cfg_t const qspi_pads[] = { + IMX8MQ_PAD_NAND_ALE__QSPI_A_SCLK | MUX_PAD_CTRL(QSPI_PAD_CTRL), + IMX8MQ_PAD_NAND_CE0_B__QSPI_A_SS0_B | MUX_PAD_CTRL(QSPI_PAD_CTRL), + + IMX8MQ_PAD_NAND_DATA00__QSPI_A_DATA0 | MUX_PAD_CTRL(QSPI_PAD_CTRL), + IMX8MQ_PAD_NAND_DATA01__QSPI_A_DATA1 | MUX_PAD_CTRL(QSPI_PAD_CTRL), + IMX8MQ_PAD_NAND_DATA02__QSPI_A_DATA2 | MUX_PAD_CTRL(QSPI_PAD_CTRL), + IMX8MQ_PAD_NAND_DATA03__QSPI_A_DATA3 | MUX_PAD_CTRL(QSPI_PAD_CTRL), +}; +#endif + +#ifdef CONFIG_FSL_QSPI +int board_qspi_init(void) +{ + imx_iomux_v3_setup_multiple_pads(qspi_pads, ARRAY_SIZE(qspi_pads)); + + set_clk_qspi(); + + return 0; +} +#endif + +int board_early_init_f(void) +{ + struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR; + + imx_iomux_v3_setup_multiple_pads(wdog_pads, ARRAY_SIZE(wdog_pads)); + set_wdog_reset(wdog); + + imx_iomux_v3_setup_multiple_pads(uart_pads, ARRAY_SIZE(uart_pads)); + + return 0; +} + +int dram_init(void) +{ + /* rom_pointer[1] contains the size of TEE occupies */ + if (rom_pointer[1]) + gd->ram_size = PHYS_SDRAM_SIZE - rom_pointer[1]; + else + gd->ram_size = PHYS_SDRAM_SIZE; + + return 0; +} + +#ifdef CONFIG_FEC_MXC +#define FEC_RST_PAD IMX_GPIO_NR(1, 9) +static iomux_v3_cfg_t const fec1_rst_pads[] = { + IMX8MQ_PAD_GPIO1_IO09__GPIO1_IO9 | MUX_PAD_CTRL(NO_PAD_CTRL), +}; + +static void setup_iomux_fec(void) +{ + imx_iomux_v3_setup_multiple_pads(fec1_rst_pads, + ARRAY_SIZE(fec1_rst_pads)); + + gpio_request(IMX_GPIO_NR(1, 9), "fec1_rst"); + gpio_direction_output(IMX_GPIO_NR(1, 9), 0); + udelay(500); + gpio_direction_output(IMX_GPIO_NR(1, 9), 1); +} + +static int setup_fec(void) +{ + struct iomuxc_gpr_base_regs *gpr = + (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR; + + setup_iomux_fec(); + + /* Use 125M anatop REF_CLK1 for ENET1, not from external */ + clrsetbits_le32(&gpr->gpr[1], BIT(13) | BIT(17), 0); + return set_clk_enet(ENET_125MHZ); +} + +int board_phy_config(struct phy_device *phydev) +{ + /* enable rgmii rxc skew and phy mode select to RGMII copper */ + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f); + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8); + + phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05); + phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100); + + if (phydev->drv->config) + phydev->drv->config(phydev); + return 0; +} +#endif + +int board_init(void) +{ +#ifdef CONFIG_FEC_MXC + setup_fec(); +#endif + + return 0; +} + +int board_mmc_get_env_dev(int devno) +{ + return devno; +} + +#ifdef CONFIG_OF_BOARD_SETUP +int ft_board_setup(void *blob, bd_t *bd) +{ + return 0; +} +#endif + +int board_late_init(void) +{ +#ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG + env_set("board_name", "HummingBoard Pulse"); + env_set("board_rev", "iMX8MQ"); +#endif + + return 0; +} diff --git a/board/solidrun/imx8mq_hb/lpddr4_timing.c b/board/solidrun/imx8mq_hb/lpddr4_timing.c new file mode 100644 index 000000000000..7112cd2c2aa1 --- /dev/null +++ b/board/solidrun/imx8mq_hb/lpddr4_timing.c @@ -0,0 +1,1201 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + */ + +#include +#include +#include +#include + +#define WR_POST_EXT_3200 /* recommened to define */ + +struct dram_cfg_param lpddr4_ddrc_cfg[] = { + /* Start to config, default 3200mbps */ + { DDRC_DBG1(0), 0x00000001 }, + { DDRC_PWRCTL(0), 0x00000001 }, + { DDRC_MSTR(0), 0xa3080020 }, + { DDRC_MSTR2(0), 0x00000000 }, + { DDRC_DERATEEN(0), 0x00000203 }, + { DDRC_DERATEINT(0), 0x0186a000 }, + { DDRC_RFSHTMG(0), 0x006100e0 }, + { DDRC_INIT0(0), 0xc003061c }, + { DDRC_INIT1(0), 0x009E0000 }, + { DDRC_INIT3(0), 0x00d4002d }, +#ifdef WR_POST_EXT_3200 + { DDRC_INIT4(0), 0x00330008 }, +#else + { DDRC_INIT4(0), 0x00310008 }, +#endif + { DDRC_INIT6(0), 0x0066004a }, + { DDRC_INIT7(0), 0x0015004a }, + + { DDRC_DRAMTMG0(0), 0x1a201b22 }, + { DDRC_DRAMTMG1(0), 0x00060633 }, + { DDRC_DRAMTMG2(0), 0x070e1214 }, + { DDRC_DRAMTMG3(0), 0x00c0c000 }, + { DDRC_DRAMTMG4(0), 0x0f04080f }, + { DDRC_DRAMTMG5(0), 0x02040c0c }, + { DDRC_DRAMTMG6(0), 0x01010007 }, + { DDRC_DRAMTMG7(0), 0x00000401 }, + { DDRC_DRAMTMG12(0), 0x00020600 }, + { DDRC_DRAMTMG13(0), 0x0c100002 }, + { DDRC_DRAMTMG14(0), 0x000000e6 }, + { DDRC_DRAMTMG17(0), 0x00a00050 }, + + { DDRC_ZQCTL0(0), 0xc3200018 }, + { DDRC_ZQCTL1(0), 0x028061a8 }, + { DDRC_ZQCTL2(0), 0x00000000 }, + + { DDRC_DFITMG0(0), 0x0497820a }, + { DDRC_DFITMG1(0), 0x00080303 }, + { DDRC_DFIUPD0(0), 0xe0400018 }, + { DDRC_DFIUPD1(0), 0x00df00e4 }, + { DDRC_DFIUPD2(0), 0x80000000 }, + { DDRC_DFIMISC(0), 0x00000011 }, + { DDRC_DFITMG2(0), 0x0000170a }, + + { DDRC_DBICTL(0), 0x00000001 }, + { DDRC_DFIPHYMSTR(0), 0x00000001 }, + { DDRC_RANKCTL(0), 0x00000639 }, + { DDRC_DRAMTMG2(0), 0x070e1214 }, + + { DDRC_ADDRMAP0(0), 0x00000015 }, + { DDRC_ADDRMAP3(0), 0x00000000 }, + { DDRC_ADDRMAP4(0), 0x00001f1f }, + /* bank interleave */ + { DDRC_ADDRMAP1(0), 0x00080808 }, + { DDRC_ADDRMAP5(0), 0x07070707 }, + { DDRC_ADDRMAP6(0), 0x48080707 }, + + /* Frequency 1: 667mts */ + { DDRC_FREQ1_DERATEEN(0), 0x00000001 }, + { DDRC_FREQ1_DERATEINT(0), 0x00518b00 }, + { DDRC_FREQ1_RFSHCTL0(0), 0x0020d040 }, + { DDRC_FREQ1_RFSHTMG(0), 0x0014002f }, + { DDRC_FREQ1_INIT3(0), 0x00940009 }, + { DDRC_FREQ1_INIT4(0), 0x00310000 }, + { DDRC_FREQ1_INIT6(0), 0x0066004a }, + { DDRC_FREQ1_INIT7(0), 0x0016004a }, + { DDRC_FREQ1_DRAMTMG0(0), 0x0b070508 }, + { DDRC_FREQ1_DRAMTMG1(0), 0x0003040b }, + { DDRC_FREQ1_DRAMTMG2(0), 0x0305090c }, + { DDRC_FREQ1_DRAMTMG3(0), 0x00505000 }, + { DDRC_FREQ1_DRAMTMG4(0), 0x04040204 }, + { DDRC_FREQ1_DRAMTMG5(0), 0x02030303 }, + { DDRC_FREQ1_DRAMTMG6(0), 0x01010004 }, + { DDRC_FREQ1_DRAMTMG7(0), 0x00000301 }, + { DDRC_FREQ1_DRAMTMG12(0), 0x00020300 }, + { DDRC_FREQ1_DRAMTMG13(0), 0x0a100002 }, + { DDRC_FREQ1_DRAMTMG14(0), 0x00000031 }, + { DDRC_FREQ1_DRAMTMG17(0), 0x00220011 }, + { DDRC_FREQ1_ZQCTL0(0), 0xc0a70006 }, + { DDRC_FREQ1_DFITMG0(0), 0x3858202 }, + { DDRC_FREQ1_DFITMG1(0), 0x80303 }, + { DDRC_FREQ1_DFITMG2(0), 0x502 }, + + { DDRC_DFITMG0_SHADOW(0), 0x03858202 }, + { DDRC_DFITMG1_SHADOW(0), 0x00080303 }, + { DDRC_DFITMG2_SHADOW(0), 0x00000502 }, + + /* performance setting */ + { DDRC_ODTMAP(0), 0x00000000 }, + { DDRC_SCHED(0), 0x29001505 }, + { DDRC_SCHED1(0), 0x0000002c }, + { DDRC_PERFHPR1(0), 0x5900575b }, + { DDRC_PERFLPR1(0), 0x90000096 }, + { DDRC_PERFWR1(0), 0x1000012c }, + { DDRC_DBG0(0), 0x00000016 }, + { DDRC_DBG1(0), 0x00000000 }, + { DDRC_DBGCMD(0), 0x00000000 }, + { DDRC_SWCTL(0), 0x00000001 }, + { DDRC_POISONCFG(0), 0x00000011 }, + { DDRC_PCCFG(0), 0x00000111 }, + { DDRC_PCFGR_0(0), 0x000010f3 }, + { DDRC_PCFGW_0(0), 0x000072ff }, + { DDRC_PCTRL_0(0), 0x00000001 }, + { DDRC_PCFGQOS0_0(0), 0x00000e00 }, + { DDRC_PCFGQOS1_0(0), 0x0062ffff }, + { DDRC_PCFGWQOS0_0(0), 0x00000e00 }, + { DDRC_PCFGWQOS1_0(0), 0x0000ffff }, +}; + +/* PHY Initialize Configuration */ +struct dram_cfg_param lpddr4_ddrphy_cfg[] = { + { 0x100a0, 0x5 }, + { 0x100a1, 0x7 }, + { 0x100a2, 0x6 }, + { 0x100a3, 0x4 }, + { 0x100a4, 0x2 }, + { 0x100a5, 0x3 }, + { 0x100a6, 0x0 }, + { 0x100a7, 0x1 }, + { 0x110a0, 0x2 }, + { 0x110a1, 0x0 }, + { 0x110a2, 0x6 }, + { 0x110a3, 0x7 }, + { 0x110a4, 0x4 }, + { 0x110a5, 0x5 }, + { 0x110a6, 0x1 }, + { 0x110a7, 0x3 }, + { 0x120a0, 0x5 }, + { 0x120a1, 0x4 }, + { 0x120a2, 0x1 }, + { 0x120a3, 0x3 }, + { 0x120a4, 0x2 }, + { 0x120a5, 0x0 }, + { 0x120a6, 0x7 }, + { 0x120a7, 0x6 }, + { 0x130a0, 0x2 }, + { 0x130a1, 0x5 }, + { 0x130a2, 0x4 }, + { 0x130a3, 0x7 }, + { 0x130a4, 0x6 }, + { 0x130a5, 0x0 }, + { 0x130a6, 0x1 }, + { 0x130a7, 0x3 }, + + { 0x20110, 0x2 }, + { 0x20111, 0x3 }, + { 0x20112, 0x4 }, + { 0x20113, 0x5 }, + { 0x20114, 0x0 }, + { 0x20115, 0x1 }, + + { 0x1005f, 0x1ff }, + { 0x1015f, 0x1ff }, + { 0x1105f, 0x1ff }, + { 0x1115f, 0x1ff }, + { 0x1205f, 0x1ff }, + { 0x1215f, 0x1ff }, + { 0x1305f, 0x1ff }, + { 0x1315f, 0x1ff }, + + { 0x11005f, 0x1ff }, + { 0x11015f, 0x1ff }, + { 0x11105f, 0x1ff }, + { 0x11115f, 0x1ff }, + { 0x11205f, 0x1ff }, + { 0x11215f, 0x1ff }, + { 0x11305f, 0x1ff }, + { 0x11315f, 0x1ff }, + + { 0x55, 0x1ff }, + { 0x1055, 0x1ff }, + { 0x2055, 0x1ff }, + { 0x3055, 0x1ff }, + { 0x4055, 0x1ff }, + { 0x5055, 0x1ff }, + { 0x6055, 0x1ff }, + { 0x7055, 0x1ff }, + { 0x8055, 0x1ff }, + { 0x9055, 0x1ff }, + + { 0x200c5, 0x19 }, + { 0x1200c5, 0x7 }, + + { 0x2002e, 0x2 }, + { 0x12002e, 0x2 }, + + { 0x90204, 0x0 }, + { 0x190204, 0x0 }, + +#ifdef WR_POST_EXT_3200 + { 0x20024, 0xeb }, +#else + { 0x20024, 0xab }, +#endif + { 0x2003a, 0x0 }, + { 0x120024, 0xab }, + { 0x2003a, 0x0 }, + { 0x2003a, 0x0 }, + { 0x20056, 0x3 }, + { 0x120056, 0xa }, + { 0x1004d, 0xe00 }, + { 0x1014d, 0xe00 }, + { 0x1104d, 0xe00 }, + { 0x1114d, 0xe00 }, + { 0x1204d, 0xe00 }, + { 0x1214d, 0xe00 }, + { 0x1304d, 0xe00 }, + { 0x1314d, 0xe00 }, + { 0x11004d, 0xe00 }, + { 0x11014d, 0xe00 }, + { 0x11104d, 0xe00 }, + { 0x11114d, 0xe00 }, + { 0x11204d, 0xe00 }, + { 0x11214d, 0xe00 }, + { 0x11304d, 0xe00 }, + { 0x11314d, 0xe00 }, + + { 0x10049, 0xfbe }, + { 0x10149, 0xfbe }, + { 0x11049, 0xfbe }, + { 0x11149, 0xfbe }, + { 0x12049, 0xfbe }, + { 0x12149, 0xfbe }, + { 0x13049, 0xfbe }, + { 0x13149, 0xfbe }, + { 0x110049, 0xfbe }, + { 0x110149, 0xfbe }, + { 0x111049, 0xfbe }, + { 0x111149, 0xfbe }, + { 0x112049, 0xfbe }, + { 0x112149, 0xfbe }, + { 0x113049, 0xfbe }, + { 0x113149, 0xfbe }, + + { 0x43, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x1043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x2043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x3043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x4043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x5043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x6043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x7043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x8043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + { 0x9043, ((LPDDR4_PHY_ADDR_RON << 5) | LPDDR4_PHY_ADDR_RON) }, + + { 0x20018, 0x3 }, + { 0x20075, 0x4 }, + { 0x20050, 0x0 }, + { 0x20008, 0x320 }, + { 0x120008, 0xa7 }, + { 0x20088, 0x9 }, + { 0x200b2, 0xdc }, + { 0x10043, 0x5a1 }, + { 0x10143, 0x5a1 }, + { 0x11043, 0x5a1 }, + { 0x11143, 0x5a1 }, + { 0x12043, 0x5a1 }, + { 0x12143, 0x5a1 }, + { 0x13043, 0x5a1 }, + { 0x13143, 0x5a1 }, + { 0x1200b2, 0xdc }, + { 0x110043, 0x5a1 }, + { 0x110143, 0x5a1 }, + { 0x111043, 0x5a1 }, + { 0x111143, 0x5a1 }, + { 0x112043, 0x5a1 }, + { 0x112143, 0x5a1 }, + { 0x113043, 0x5a1 }, + { 0x113143, 0x5a1 }, + { 0x200fa, 0x1 }, + { 0x1200fa, 0x1 }, + { 0x20019, 0x1 }, + { 0x120019, 0x1 }, + { 0x200f0, 0x0 }, + { 0x200f1, 0x0 }, + { 0x200f2, 0x4444 }, + { 0x200f3, 0x8888 }, + { 0x200f4, 0x5555 }, + { 0x200f5, 0x0 }, + { 0x200f6, 0x0 }, + { 0x200f7, 0xf000 }, + { 0x20025, 0x0 }, + { 0x2002d, 0x0 }, + { 0x12002d, 0x0 }, + { 0x20060, 0x2 }, +}; + +/* P0 message block paremeter for training firmware */ +struct dram_cfg_param lpddr4_fsp0_cfg[] = { + { 0xd0000, 0x0 }, + { 0x54000, 0x0 }, + { 0x54001, 0x0 }, + { 0x54002, 0x0 }, + { 0x54003, 0xc80 }, + { 0x54004, 0x2 }, + { 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) }, /* PHY Ron/Rtt */ + { 0x54006, LPDDR4_PHY_VREF_VALUE }, + { 0x54007, 0x0 }, + { 0x54008, 0x131f }, + { 0x54009, LPDDR4_HDT_CTL_3200_1D }, + { 0x5400a, 0x0 }, + { 0x5400b, 0x2 }, + { 0x5400c, 0x0 }, + { 0x5400d, (LPDDR4_CATRAIN_3200_1d << 8) }, + { 0x5400e, 0x0 }, + { 0x5400f, 0x0 }, + { 0x54010, 0x0 }, + { 0x54011, 0x0 }, + { 0x54012, 0x310 }, + { 0x54013, 0x0 }, + { 0x54014, 0x0 }, + { 0x54015, 0x0 }, + { 0x54016, 0x0 }, + { 0x54017, 0x0 }, + { 0x54018, 0x0 }, + + { 0x54019, 0x2dd4 }, +#ifdef WR_POST_EXT_3200 + { 0x5401a, (((LPDDR4_RON) << 3) | 0x3) }, +#else + { 0x5401a, (((LPDDR4_RON) << 3) | 0x1) }, +#endif + { 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) | + (LPDDR4_RTT_CA_BANK0 << 4) | LPDDR4_RTT_DQ) }, + { 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) }, + { 0x5401d, 0x0 }, + { 0x5401e, LPDDR4_MR22_RANK0 }, + { 0x5401f, 0x2dd4 }, +#ifdef WR_POST_EXT_3200 + { 0x54020, (((LPDDR4_RON) << 3) | 0x3) }, +#else + { 0x54020, (((LPDDR4_RON) << 3) | 0x1) }, +#endif + { 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) | + (LPDDR4_RTT_CA_BANK1 << 4) | LPDDR4_RTT_DQ) }, + { 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08) }, + { 0x54023, 0x0 }, + { 0x54024, LPDDR4_MR22_RANK1 }, + + { 0x54025, 0x0 }, + { 0x54026, 0x0 }, + { 0x54027, 0x0 }, + { 0x54028, 0x0 }, + { 0x54029, 0x0 }, + { 0x5402a, 0x0 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x3 }, + { 0x5402d, 0x0 }, + { 0x5402e, 0x0 }, + { 0x5402f, 0x0 }, + { 0x54030, 0x0 }, + { 0x54031, 0x0 }, + { 0x54032, 0xd400 }, + /* MR3/MR2 */ +#ifdef WR_POST_EXT_3200 + { 0x54033, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d /*0x312d*/ }, +#else + { 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d/*0x312d*/ }, +#endif + /* MR11/MR4 */ + { 0x54034, 0x6600 }, + /* self:0x284d//MR13/MR12 */ + { 0x54035, 0x84a }, + /* MR16/MR14*/ + { 0x54036, 0x4a }, + { 0x54037, 0x1500 }, + /* MR1 */ + { 0x54038, 0xd400 }, + /* MR3/MR2 */ +#ifdef WR_POST_EXT_3200 + { 0x54039, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d/*0x312d*/ }, +#else + { 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d/*0x312d*/ }, +#endif + /* MR11/MR4 */ + { 0x5403a, 0x6600 }, + /* self:0x284d//MR13/MR12 */ + { 0x5403b, 0x84a }, + /* MR16/MR14 */ + { 0x5403c, 0x4a }, + { 0x5403d, 0x1500 }, + /* { 0x5403d, 0x500 } */ + { 0x5403e, 0x0 }, + { 0x5403f, 0x0 }, + { 0x54040, 0x0 }, + { 0x54041, 0x0 }, + { 0x54042, 0x0 }, + { 0x54043, 0x0 }, + { 0x54044, 0x0 }, + { 0xd0000, 0x1 }, +}; + +/* P1 message block paremeter for training firmware */ +struct dram_cfg_param lpddr4_fsp1_cfg[] = { + { 0xd0000, 0x0 }, + { 0x54000, 0x0 }, + { 0x54001, 0x0 }, + { 0x54002, 0x1 }, + { 0x54003, 0x29c }, + { 0x54004, 0x2 }, + /* PHY Ron/Rtt */ + { 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT)/*0x2828*/ }, + { 0x54006, LPDDR4_PHY_VREF_VALUE }, + { 0x54007, 0x0 }, + { 0x54008, LPDDR4_TRAIN_SEQ_400 }, + { 0x54009, LPDDR4_HDT_CTL_400_1D }, + { 0x5400a, 0x0 }, + { 0x5400b, 0x2 }, + { 0x5400c, 0x0 }, + { 0x5400d, (LPDDR4_CATRAIN_400 << 8) }, + { 0x5400e, 0x0 }, + { 0x5400f, 0x0 }, + { 0x54010, 0x0 }, + { 0x54011, 0x0 }, + { 0x54012, 0x310 }, + { 0x54013, 0x0 }, + { 0x54014, 0x0 }, + { 0x54015, 0x0 }, + { 0x54016, 0x0 }, + { 0x54017, 0x0 }, + { 0x54018, 0x0 }, + { 0x54019, 0x994 }, + /* MR4/MR3 */ + { 0x5401a, (((LPDDR4_RON) << 3) | 0x1)/*0x31*/ }, + /* MR12/MR11 */ + { 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) | (LPDDR4_RTT_CA << 4) | + LPDDR4_RTT_DQ)/*0x4d46*/ }, + /* self:0x4d28//MR14/MR13 */ + { 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08)/*0x4d08*/ }, + { 0x5401d, 0x0 }, + { 0x5401e, 0x15 }, + { 0x5401f, 0x994 }, + { 0x54020, (((LPDDR4_RON) << 3) | 0x1)/*0x31*/ }, /* MR4/MR3 */ + { 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) | (LPDDR4_RTT_CA << 4) | + LPDDR4_RTT_DQ)/*0x4d46*/ },/* MR12/MR11 */ + /* self:0x4d28//MR14/MR13 */ + { 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK1 << 8) | 0x08)/*0x4d08*/ }, + { 0x54023, 0x0 }, + { 0x54024, 0x15 }, + { 0x54025, 0x0 }, + { 0x54026, 0x0 }, + { 0x54027, 0x0 }, + { 0x54028, 0x0 }, + { 0x54029, 0x0 }, + { 0x5402a, 0x0 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x3 }, + { 0x5402d, 0x0 }, + { 0x5402e, 0x0 }, + { 0x5402f, 0x0 }, + { 0x54030, 0x0 }, + { 0x54031, 0x0 }, + { 0x54032, 0x9400 }, + { 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x09 }, + { 0x54034, (((LPDDR4_RTT60 << 4) | LPDDR4_RTT_DQ) << 8) }, + { 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) }, + { 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 }, + { 0x54037, (((0 << 5) | (1 << 4) | (0 << 3) | LPDDR4_RTT48) << 8) }, + { 0x54038, 0x9400 }, + { 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x09 }, + { 0x5403a, (((LPDDR4_RTT60 << 4) | LPDDR4_RTT_DQ) << 8) }, + { 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) }, + { 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK0 }, + { 0x5403d, (((0 << 5) | (1 << 4) | (0 << 3) | LPDDR4_RTT48) << 8) }, + { 0x5403e, 0x0 }, + { 0x5403f, 0x0 }, + { 0x54040, 0x0 }, + { 0x54041, 0x0 }, + { 0x54042, 0x0 }, + { 0x54043, 0x0 }, + { 0x54044, 0x0 }, + { 0xd0000, 0x1 }, +}; + +/* P0 2D message block paremeter for training firmware */ +struct dram_cfg_param lpddr4_fsp0_2d_cfg[] = { + { 0xd0000, 0x0 }, + { 0x54000, 0x0 }, + { 0x54001, 0x0 }, + { 0x54002, 0x0 }, + { 0x54003, 0xc80 }, + { 0x54004, 0x2 }, + { 0x54005, ((LPDDR4_PHY_RON << 8) | LPDDR4_PHY_RTT) }, + { 0x54006, LPDDR4_PHY_VREF_VALUE }, + { 0x54007, 0x0 }, + { 0x54008, 0x61 }, + { 0x54009, LPDDR4_HDT_CTL_2D }, + { 0x5400a, 0x0 }, + { 0x5400b, 0x2 }, + { 0x5400c, 0x0 }, + { 0x5400d, (LPDDR4_CATRAIN_3200_2d << 8) }, + { 0x5400e, 0x0 }, + { 0x5400f, (LPDDR4_2D_SHARE << 8) | 0x00 }, + { 0x54010, LPDDR4_2D_WEIGHT }, + { 0x54011, 0x0 }, + { 0x54012, 0x310 }, + { 0x54013, 0x0 }, + { 0x54014, 0x0 }, + { 0x54015, 0x0 }, + { 0x54016, 0x0 }, + { 0x54017, 0x0 }, + { 0x54018, 0x0 }, + { 0x54019, 0x2dd4 }, +#ifdef WR_POST_EXT_3200 + { 0x5401a, (((LPDDR4_RON) << 3) | 0x3) }, +#else + { 0x5401a, (((LPDDR4_RON) << 3) | 0x1) }, +#endif + { 0x5401b, ((LPDDR4_VREF_VALUE_CA << 8) | + (LPDDR4_RTT60 << 4) | LPDDR4_RTT_DQ) }, + { 0x5401c, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) }, + { 0x5401d, 0x0 }, + { 0x5401e, ((0 << 5) | (1 << 4) | (0 << 3) | LPDDR4_RTT48) }, + { 0x5401f, 0x2dd4 }, +#ifdef WR_POST_EXT_3200 + { 0x54020, (((LPDDR4_RON) << 3) | 0x3) }, +#else + { 0x54020, (((LPDDR4_RON) << 3) | 0x1) }, +#endif + { 0x54021, ((LPDDR4_VREF_VALUE_CA << 8) | + (LPDDR4_RTT60 << 4) | LPDDR4_RTT_DQ) }, + { 0x54022, ((LPDDR4_VREF_VALUE_DQ_RANK0 << 8) | 0x08) }, + { 0x54023, 0x0 }, + { 0x54024, ((0 << 5) | (1 << 4) | (0 << 3) | LPDDR4_RTT48) }, + { 0x54025, 0x0 }, + { 0x54026, 0x0 }, + { 0x54027, 0x0 }, + { 0x54028, 0x0 }, + { 0x54029, 0x0 }, + { 0x5402a, 0x0 }, + { 0x5402b, 0x1000 }, + { 0x5402c, 0x3 }, + { 0x5402d, 0x0 }, + { 0x5402e, 0x0 }, + { 0x5402f, 0x0 }, + { 0x54030, 0x0 }, + { 0x54031, 0x0 }, + + { 0x54032, 0xd400 }, +#ifdef WR_POST_EXT_3200 + { 0x54033, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d }, +#else + { 0x54033, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d }, +#endif + { 0x54034, (((LPDDR4_RTT60 << 4) | LPDDR4_RTT_DQ) << 8) }, + { 0x54035, (0x0800 | LPDDR4_VREF_VALUE_CA) }, + { 0x54036, LPDDR4_VREF_VALUE_DQ_RANK0 }, + { 0x54037, (LPDDR4_MR22_RANK0 << 8) }, + { 0x54038, 0xd400 }, +#ifdef WR_POST_EXT_3200 + { 0x54039, ((((LPDDR4_RON) << 3) | 0x3) << 8) | 0x2d }, +#else + { 0x54039, ((((LPDDR4_RON) << 3) | 0x1) << 8) | 0x2d }, +#endif + { 0x5403a, (((LPDDR4_RTT60 << 4) | LPDDR4_RTT_DQ) << 8) }, + { 0x5403b, (0x0800 | LPDDR4_VREF_VALUE_CA) }, + { 0x5403c, LPDDR4_VREF_VALUE_DQ_RANK1 }, + { 0x5403d, 0x1500 }, + { 0x5403e, 0x0 }, + { 0x5403f, 0x0 }, + { 0x54040, 0x0 }, + { 0x54041, 0x0 }, + { 0x54042, 0x0 }, + { 0x54043, 0x0 }, + { 0x54044, 0x0 }, + { 0xd0000, 0x1 }, +}; + +/* DRAM PHY init engine image */ +struct dram_cfg_param lpddr4_phy_pie[] = { + { 0xd0000, 0x0 }, + { 0x90000, 0x10 }, + { 0x90001, 0x400 }, + { 0x90002, 0x10e }, + { 0x90003, 0x0 }, + { 0x90004, 0x0 }, + { 0x90005, 0x8 }, + { 0x90029, 0xb }, + { 0x9002a, 0x480 }, + { 0x9002b, 0x109 }, + { 0x9002c, 0x8 }, + { 0x9002d, 0x448 }, + { 0x9002e, 0x139 }, + { 0x9002f, 0x8 }, + { 0x90030, 0x478 }, + { 0x90031, 0x109 }, + { 0x90032, 0x0 }, + { 0x90033, 0xe8 }, + { 0x90034, 0x109 }, + { 0x90035, 0x2 }, + { 0x90036, 0x10 }, + { 0x90037, 0x139 }, + { 0x90038, 0xf }, + { 0x90039, 0x7c0 }, + { 0x9003a, 0x139 }, + { 0x9003b, 0x44 }, + { 0x9003c, 0x630 }, + { 0x9003d, 0x159 }, + { 0x9003e, 0x14f }, + { 0x9003f, 0x630 }, + { 0x90040, 0x159 }, + { 0x90041, 0x47 }, + { 0x90042, 0x630 }, + { 0x90043, 0x149 }, + { 0x90044, 0x4f }, + { 0x90045, 0x630 }, + { 0x90046, 0x179 }, + { 0x90047, 0x8 }, + { 0x90048, 0xe0 }, + { 0x90049, 0x109 }, + { 0x9004a, 0x0 }, + { 0x9004b, 0x7c8 }, + { 0x9004c, 0x109 }, + { 0x9004d, 0x0 }, + { 0x9004e, 0x1 }, + { 0x9004f, 0x8 }, + { 0x90050, 0x0 }, + { 0x90051, 0x45a }, + { 0x90052, 0x9 }, + { 0x90053, 0x0 }, + { 0x90054, 0x448 }, + { 0x90055, 0x109 }, + { 0x90056, 0x40 }, + { 0x90057, 0x630 }, + { 0x90058, 0x179 }, + { 0x90059, 0x1 }, + { 0x9005a, 0x618 }, + { 0x9005b, 0x109 }, + { 0x9005c, 0x40c0 }, + { 0x9005d, 0x630 }, + { 0x9005e, 0x149 }, + { 0x9005f, 0x8 }, + { 0x90060, 0x4 }, + { 0x90061, 0x48 }, + { 0x90062, 0x4040 }, + { 0x90063, 0x630 }, + { 0x90064, 0x149 }, + { 0x90065, 0x0 }, + { 0x90066, 0x4 }, + { 0x90067, 0x48 }, + { 0x90068, 0x40 }, + { 0x90069, 0x630 }, + { 0x9006a, 0x149 }, + { 0x9006b, 0x10 }, + { 0x9006c, 0x4 }, + { 0x9006d, 0x18 }, + { 0x9006e, 0x0 }, + { 0x9006f, 0x4 }, + { 0x90070, 0x78 }, + { 0x90071, 0x549 }, + { 0x90072, 0x630 }, + { 0x90073, 0x159 }, + { 0x90074, 0xd49 }, + { 0x90075, 0x630 }, + { 0x90076, 0x159 }, + { 0x90077, 0x94a }, + { 0x90078, 0x630 }, + { 0x90079, 0x159 }, + { 0x9007a, 0x441 }, + { 0x9007b, 0x630 }, + { 0x9007c, 0x149 }, + { 0x9007d, 0x42 }, + { 0x9007e, 0x630 }, + { 0x9007f, 0x149 }, + { 0x90080, 0x1 }, + { 0x90081, 0x630 }, + { 0x90082, 0x149 }, + { 0x90083, 0x0 }, + { 0x90084, 0xe0 }, + { 0x90085, 0x109 }, + { 0x90086, 0xa }, + { 0x90087, 0x10 }, + { 0x90088, 0x109 }, + { 0x90089, 0x9 }, + { 0x9008a, 0x3c0 }, + { 0x9008b, 0x149 }, + { 0x9008c, 0x9 }, + { 0x9008d, 0x3c0 }, + { 0x9008e, 0x159 }, + { 0x9008f, 0x18 }, + { 0x90090, 0x10 }, + { 0x90091, 0x109 }, + { 0x90092, 0x0 }, + { 0x90093, 0x3c0 }, + { 0x90094, 0x109 }, + { 0x90095, 0x18 }, + { 0x90096, 0x4 }, + { 0x90097, 0x48 }, + { 0x90098, 0x18 }, + { 0x90099, 0x4 }, + { 0x9009a, 0x58 }, + { 0x9009b, 0xa }, + { 0x9009c, 0x10 }, + { 0x9009d, 0x109 }, + { 0x9009e, 0x2 }, + { 0x9009f, 0x10 }, + { 0x900a0, 0x109 }, + { 0x900a1, 0x5 }, + { 0x900a2, 0x7c0 }, + { 0x900a3, 0x109 }, + { 0x900a4, 0x10 }, + { 0x900a5, 0x10 }, + { 0x900a6, 0x109 }, + { 0x40000, 0x811 }, + { 0x40020, 0x880 }, + { 0x40040, 0x0 }, + { 0x40060, 0x0 }, + { 0x40001, 0x4008 }, + { 0x40021, 0x83 }, + { 0x40041, 0x4f }, + { 0x40061, 0x0 }, + { 0x40002, 0x4040 }, + { 0x40022, 0x83 }, + { 0x40042, 0x51 }, + { 0x40062, 0x0 }, + { 0x40003, 0x811 }, + { 0x40023, 0x880 }, + { 0x40043, 0x0 }, + { 0x40063, 0x0 }, + { 0x40004, 0x720 }, + { 0x40024, 0xf }, + { 0x40044, 0x1740 }, + { 0x40064, 0x0 }, + { 0x40005, 0x16 }, + { 0x40025, 0x83 }, + { 0x40045, 0x4b }, + { 0x40065, 0x0 }, + { 0x40006, 0x716 }, + { 0x40026, 0xf }, + { 0x40046, 0x2001 }, + { 0x40066, 0x0 }, + { 0x40007, 0x716 }, + { 0x40027, 0xf }, + { 0x40047, 0x2800 }, + { 0x40067, 0x0 }, + { 0x40008, 0x716 }, + { 0x40028, 0xf }, + { 0x40048, 0xf00 }, + { 0x40068, 0x0 }, + { 0x40009, 0x720 }, + { 0x40029, 0xf }, + { 0x40049, 0x1400 }, + { 0x40069, 0x0 }, + { 0x4000a, 0xe08 }, + { 0x4002a, 0xc15 }, + { 0x4004a, 0x0 }, + { 0x4006a, 0x0 }, + { 0x4000b, 0x623 }, + { 0x4002b, 0x15 }, + { 0x4004b, 0x0 }, + { 0x4006b, 0x0 }, + { 0x4000c, 0x4028 }, + { 0x4002c, 0x80 }, + { 0x4004c, 0x0 }, + { 0x4006c, 0x0 }, + { 0x4000d, 0xe08 }, + { 0x4002d, 0xc1a }, + { 0x4004d, 0x0 }, + { 0x4006d, 0x0 }, + { 0x4000e, 0x623 }, + { 0x4002e, 0x1a }, + { 0x4004e, 0x0 }, + { 0x4006e, 0x0 }, + { 0x4000f, 0x4040 }, + { 0x4002f, 0x80 }, + { 0x4004f, 0x0 }, + { 0x4006f, 0x0 }, + { 0x40010, 0x2604 }, + { 0x40030, 0x15 }, + { 0x40050, 0x0 }, + { 0x40070, 0x0 }, + { 0x40011, 0x708 }, + { 0x40031, 0x5 }, + { 0x40051, 0x0 }, + { 0x40071, 0x2002 }, + { 0x40012, 0x8 }, + { 0x40032, 0x80 }, + { 0x40052, 0x0 }, + { 0x40072, 0x0 }, + { 0x40013, 0x2604 }, + { 0x40033, 0x1a }, + { 0x40053, 0x0 }, + { 0x40073, 0x0 }, + { 0x40014, 0x708 }, + { 0x40034, 0xa }, + { 0x40054, 0x0 }, + { 0x40074, 0x2002 }, + { 0x40015, 0x4040 }, + { 0x40035, 0x80 }, + { 0x40055, 0x0 }, + { 0x40075, 0x0 }, + { 0x40016, 0x60a }, + { 0x40036, 0x15 }, + { 0x40056, 0x1200 }, + { 0x40076, 0x0 }, + { 0x40017, 0x61a }, + { 0x40037, 0x15 }, + { 0x40057, 0x1300 }, + { 0x40077, 0x0 }, + { 0x40018, 0x60a }, + { 0x40038, 0x1a }, + { 0x40058, 0x1200 }, + { 0x40078, 0x0 }, + { 0x40019, 0x642 }, + { 0x40039, 0x1a }, + { 0x40059, 0x1300 }, + { 0x40079, 0x0 }, + { 0x4001a, 0x4808 }, + { 0x4003a, 0x880 }, + { 0x4005a, 0x0 }, + { 0x4007a, 0x0 }, + { 0x900a7, 0x0 }, + { 0x900a8, 0x790 }, + { 0x900a9, 0x11a }, + { 0x900aa, 0x8 }, + { 0x900ab, 0x7aa }, + { 0x900ac, 0x2a }, + { 0x900ad, 0x10 }, + { 0x900ae, 0x7b2 }, + { 0x900af, 0x2a }, + { 0x900b0, 0x0 }, + { 0x900b1, 0x7c8 }, + { 0x900b2, 0x109 }, + { 0x900b3, 0x10 }, + { 0x900b4, 0x2a8 }, + { 0x900b5, 0x129 }, + { 0x900b6, 0x8 }, + { 0x900b7, 0x370 }, + { 0x900b8, 0x129 }, + { 0x900b9, 0xa }, + { 0x900ba, 0x3c8 }, + { 0x900bb, 0x1a9 }, + { 0x900bc, 0xc }, + { 0x900bd, 0x408 }, + { 0x900be, 0x199 }, + { 0x900bf, 0x14 }, + { 0x900c0, 0x790 }, + { 0x900c1, 0x11a }, + { 0x900c2, 0x8 }, + { 0x900c3, 0x4 }, + { 0x900c4, 0x18 }, + { 0x900c5, 0xe }, + { 0x900c6, 0x408 }, + { 0x900c7, 0x199 }, + { 0x900c8, 0x8 }, + { 0x900c9, 0x8568 }, + { 0x900ca, 0x108 }, + { 0x900cb, 0x18 }, + { 0x900cc, 0x790 }, + { 0x900cd, 0x16a }, + { 0x900ce, 0x8 }, + { 0x900cf, 0x1d8 }, + { 0x900d0, 0x169 }, + { 0x900d1, 0x10 }, + { 0x900d2, 0x8558 }, + { 0x900d3, 0x168 }, + { 0x900d4, 0x70 }, + { 0x900d5, 0x788 }, + { 0x900d6, 0x16a }, + { 0x900d7, 0x1ff8 }, + { 0x900d8, 0x85a8 }, + { 0x900d9, 0x1e8 }, + { 0x900da, 0x50 }, + { 0x900db, 0x798 }, + { 0x900dc, 0x16a }, + { 0x900dd, 0x60 }, + { 0x900de, 0x7a0 }, + { 0x900df, 0x16a }, + { 0x900e0, 0x8 }, + { 0x900e1, 0x8310 }, + { 0x900e2, 0x168 }, + { 0x900e3, 0x8 }, + { 0x900e4, 0xa310 }, + { 0x900e5, 0x168 }, + { 0x900e6, 0xa }, + { 0x900e7, 0x408 }, + { 0x900e8, 0x169 }, + { 0x900e9, 0x6e }, + { 0x900ea, 0x0 }, + { 0x900eb, 0x68 }, + { 0x900ec, 0x0 }, + { 0x900ed, 0x408 }, + { 0x900ee, 0x169 }, + { 0x900ef, 0x0 }, + { 0x900f0, 0x8310 }, + { 0x900f1, 0x168 }, + { 0x900f2, 0x0 }, + { 0x900f3, 0xa310 }, + { 0x900f4, 0x168 }, + { 0x900f5, 0x1ff8 }, + { 0x900f6, 0x85a8 }, + { 0x900f7, 0x1e8 }, + { 0x900f8, 0x68 }, + { 0x900f9, 0x798 }, + { 0x900fa, 0x16a }, + { 0x900fb, 0x78 }, + { 0x900fc, 0x7a0 }, + { 0x900fd, 0x16a }, + { 0x900fe, 0x68 }, + { 0x900ff, 0x790 }, + { 0x90100, 0x16a }, + { 0x90101, 0x8 }, + { 0x90102, 0x8b10 }, + { 0x90103, 0x168 }, + { 0x90104, 0x8 }, + { 0x90105, 0xab10 }, + { 0x90106, 0x168 }, + { 0x90107, 0xa }, + { 0x90108, 0x408 }, + { 0x90109, 0x169 }, + { 0x9010a, 0x58 }, + { 0x9010b, 0x0 }, + { 0x9010c, 0x68 }, + { 0x9010d, 0x0 }, + { 0x9010e, 0x408 }, + { 0x9010f, 0x169 }, + { 0x90110, 0x0 }, + { 0x90111, 0x8b10 }, + { 0x90112, 0x168 }, + { 0x90113, 0x0 }, + { 0x90114, 0xab10 }, + { 0x90115, 0x168 }, + { 0x90116, 0x0 }, + { 0x90117, 0x1d8 }, + { 0x90118, 0x169 }, + { 0x90119, 0x80 }, + { 0x9011a, 0x790 }, + { 0x9011b, 0x16a }, + { 0x9011c, 0x18 }, + { 0x9011d, 0x7aa }, + { 0x9011e, 0x6a }, + { 0x9011f, 0xa }, + { 0x90120, 0x0 }, + { 0x90121, 0x1e9 }, + { 0x90122, 0x8 }, + { 0x90123, 0x8080 }, + { 0x90124, 0x108 }, + { 0x90125, 0xf }, + { 0x90126, 0x408 }, + { 0x90127, 0x169 }, + { 0x90128, 0xc }, + { 0x90129, 0x0 }, + { 0x9012a, 0x68 }, + { 0x9012b, 0x9 }, + { 0x9012c, 0x0 }, + { 0x9012d, 0x1a9 }, + { 0x9012e, 0x0 }, + { 0x9012f, 0x408 }, + { 0x90130, 0x169 }, + { 0x90131, 0x0 }, + { 0x90132, 0x8080 }, + { 0x90133, 0x108 }, + { 0x90134, 0x8 }, + { 0x90135, 0x7aa }, + { 0x90136, 0x6a }, + { 0x90137, 0x0 }, + { 0x90138, 0x8568 }, + { 0x90139, 0x108 }, + { 0x9013a, 0xb7 }, + { 0x9013b, 0x790 }, + { 0x9013c, 0x16a }, + { 0x9013d, 0x1f }, + { 0x9013e, 0x0 }, + { 0x9013f, 0x68 }, + { 0x90140, 0x8 }, + { 0x90141, 0x8558 }, + { 0x90142, 0x168 }, + { 0x90143, 0xf }, + { 0x90144, 0x408 }, + { 0x90145, 0x169 }, + { 0x90146, 0xc }, + { 0x90147, 0x0 }, + { 0x90148, 0x68 }, + { 0x90149, 0x0 }, + { 0x9014a, 0x408 }, + { 0x9014b, 0x169 }, + { 0x9014c, 0x0 }, + { 0x9014d, 0x8558 }, + { 0x9014e, 0x168 }, + { 0x9014f, 0x8 }, + { 0x90150, 0x3c8 }, + { 0x90151, 0x1a9 }, + { 0x90152, 0x3 }, + { 0x90153, 0x370 }, + { 0x90154, 0x129 }, + { 0x90155, 0x20 }, + { 0x90156, 0x2aa }, + { 0x90157, 0x9 }, + { 0x90158, 0x0 }, + { 0x90159, 0x400 }, + { 0x9015a, 0x10e }, + { 0x9015b, 0x8 }, + { 0x9015c, 0xe8 }, + { 0x9015d, 0x109 }, + { 0x9015e, 0x0 }, + { 0x9015f, 0x8140 }, + { 0x90160, 0x10c }, + { 0x90161, 0x10 }, + { 0x90162, 0x8138 }, + { 0x90163, 0x10c }, + { 0x90164, 0x8 }, + { 0x90165, 0x7c8 }, + { 0x90166, 0x101 }, + { 0x90167, 0x8 }, + { 0x90168, 0x0 }, + { 0x90169, 0x8 }, + { 0x9016a, 0x8 }, + { 0x9016b, 0x448 }, + { 0x9016c, 0x109 }, + { 0x9016d, 0xf }, + { 0x9016e, 0x7c0 }, + { 0x9016f, 0x109 }, + { 0x90170, 0x0 }, + { 0x90171, 0xe8 }, + { 0x90172, 0x109 }, + { 0x90173, 0x47 }, + { 0x90174, 0x630 }, + { 0x90175, 0x109 }, + { 0x90176, 0x8 }, + { 0x90177, 0x618 }, + { 0x90178, 0x109 }, + { 0x90179, 0x8 }, + { 0x9017a, 0xe0 }, + { 0x9017b, 0x109 }, + { 0x9017c, 0x0 }, + { 0x9017d, 0x7c8 }, + { 0x9017e, 0x109 }, + { 0x9017f, 0x8 }, + { 0x90180, 0x8140 }, + { 0x90181, 0x10c }, + { 0x90182, 0x0 }, + { 0x90183, 0x1 }, + { 0x90184, 0x8 }, + { 0x90185, 0x8 }, + { 0x90186, 0x4 }, + { 0x90187, 0x8 }, + { 0x90188, 0x8 }, + { 0x90189, 0x7c8 }, + { 0x9018a, 0x101 }, + { 0x90006, 0x0 }, + { 0x90007, 0x0 }, + { 0x90008, 0x8 }, + { 0x90009, 0x0 }, + { 0x9000a, 0x0 }, + { 0x9000b, 0x0 }, + { 0xd00e7, 0x400 }, + { 0x90017, 0x0 }, + { 0x9001f, 0x2a }, + { 0x90026, 0x6a }, + { 0x400d0, 0x0 }, + { 0x400d1, 0x101 }, + { 0x400d2, 0x105 }, + { 0x400d3, 0x107 }, + { 0x400d4, 0x10f }, + { 0x400d5, 0x202 }, + { 0x400d6, 0x20a }, + { 0x400d7, 0x20b }, + { 0x2003a, 0x2 }, + { 0x2000b, 0x65 }, + { 0x2000c, 0xc9 }, + { 0x2000d, 0x7d1 }, + { 0x2000e, 0x2c }, + { 0x12000b, 0x65 }, + { 0x12000c, 0xc9 }, + { 0x12000d, 0x7d1 }, + { 0x12000e, 0x2c }, + { 0x9000c, 0x0 }, + { 0x9000d, 0x173 }, + { 0x9000e, 0x60 }, + { 0x9000f, 0x6110 }, + { 0x90010, 0x2152 }, + { 0x90011, 0xdfbd }, + { 0x90012, 0x60 }, + { 0x90013, 0x6152 }, + { 0x20010, 0x5a }, + { 0x20011, 0x3 }, + { 0x120010, 0x5a }, + { 0x120011, 0x3 }, + { 0x40080, 0xe0 }, + { 0x40081, 0x12 }, + { 0x40082, 0xe0 }, + { 0x40083, 0x12 }, + { 0x40084, 0xe0 }, + { 0x40085, 0x12 }, + { 0x140080, 0xe0 }, + { 0x140081, 0x12 }, + { 0x140082, 0xe0 }, + { 0x140083, 0x12 }, + { 0x140084, 0xe0 }, + { 0x140085, 0x12 }, + { 0x400fd, 0xf }, + { 0x10011, 0x1 }, + { 0x10012, 0x1 }, + { 0x10013, 0x180 }, + { 0x10018, 0x1 }, + { 0x10002, 0x6209 }, + { 0x100b2, 0x1 }, + { 0x101b4, 0x1 }, + { 0x102b4, 0x1 }, + { 0x103b4, 0x1 }, + { 0x104b4, 0x1 }, + { 0x105b4, 0x1 }, + { 0x106b4, 0x1 }, + { 0x107b4, 0x1 }, + { 0x108b4, 0x1 }, + { 0x11011, 0x1 }, + { 0x11012, 0x1 }, + { 0x11013, 0x180 }, + { 0x11018, 0x1 }, + { 0x11002, 0x6209 }, + { 0x110b2, 0x1 }, + { 0x111b4, 0x1 }, + { 0x112b4, 0x1 }, + { 0x113b4, 0x1 }, + { 0x114b4, 0x1 }, + { 0x115b4, 0x1 }, + { 0x116b4, 0x1 }, + { 0x117b4, 0x1 }, + { 0x118b4, 0x1 }, + { 0x12011, 0x1 }, + { 0x12012, 0x1 }, + { 0x12013, 0x180 }, + { 0x12018, 0x1 }, + { 0x12002, 0x6209 }, + { 0x120b2, 0x1 }, + { 0x121b4, 0x1 }, + { 0x122b4, 0x1 }, + { 0x123b4, 0x1 }, + { 0x124b4, 0x1 }, + { 0x125b4, 0x1 }, + { 0x126b4, 0x1 }, + { 0x127b4, 0x1 }, + { 0x128b4, 0x1 }, + { 0x13011, 0x1 }, + { 0x13012, 0x1 }, + { 0x13013, 0x180 }, + { 0x13018, 0x1 }, + { 0x13002, 0x6209 }, + { 0x130b2, 0x1 }, + { 0x131b4, 0x1 }, + { 0x132b4, 0x1 }, + { 0x133b4, 0x1 }, + { 0x134b4, 0x1 }, + { 0x135b4, 0x1 }, + { 0x136b4, 0x1 }, + { 0x137b4, 0x1 }, + { 0x138b4, 0x1 }, + { 0x2003a, 0x2 }, + { 0xc0080, 0x2 }, + { 0xd0000, 0x1 }, +}; + +struct dram_fsp_msg lpddr4_dram_fsp_msg[] = { + { + /* P0 3200mts 1D */ + .drate = 3200, + .fw_type = FW_1D_IMAGE, + .fsp_cfg = lpddr4_fsp0_cfg, + .fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_cfg), + }, + { + /* P1 667mts 1D */ + .drate = 667, + .fw_type = FW_1D_IMAGE, + .fsp_cfg = lpddr4_fsp1_cfg, + .fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp1_cfg), + }, + { + /* P0 3200mts 2D */ + .drate = 3200, + .fw_type = FW_2D_IMAGE, + .fsp_cfg = lpddr4_fsp0_2d_cfg, + .fsp_cfg_num = ARRAY_SIZE(lpddr4_fsp0_2d_cfg), + }, +}; + +/* lpddr4 timing config params on EVK board */ +struct dram_timing_info dram_timing = { + .ddrc_cfg = lpddr4_ddrc_cfg, + .ddrc_cfg_num = ARRAY_SIZE(lpddr4_ddrc_cfg), + .ddrphy_cfg = lpddr4_ddrphy_cfg, + .ddrphy_cfg_num = ARRAY_SIZE(lpddr4_ddrphy_cfg), + .fsp_msg = lpddr4_dram_fsp_msg, + .fsp_msg_num = ARRAY_SIZE(lpddr4_dram_fsp_msg), + .ddrphy_pie = lpddr4_phy_pie, + .ddrphy_pie_num = ARRAY_SIZE(lpddr4_phy_pie), + .fsp_table = { 3200, 667, }, +}; diff --git a/board/solidrun/imx8mq_hb/spl.c b/board/solidrun/imx8mq_hb/spl.c new file mode 100644 index 000000000000..ebb730db12e5 --- /dev/null +++ b/board/solidrun/imx8mq_hb/spl.c @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2018 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../freescale/common/pfuze.h" + +DECLARE_GLOBAL_DATA_PTR; + +extern struct dram_timing_info dram_timing; + +void spl_dram_init(void) +{ + /* ddr init */ + ddr_init(&dram_timing); +} + +#define I2C_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE) +#define PC MUX_PAD_CTRL(I2C_PAD_CTRL) +struct i2c_pads_info i2c_pad_info1 = { + .scl = { + .i2c_mode = IMX8MQ_PAD_I2C1_SCL__I2C1_SCL | PC, + .gpio_mode = IMX8MQ_PAD_I2C1_SCL__GPIO5_IO14 | PC, + .gp = IMX_GPIO_NR(5, 14), + }, + .sda = { + .i2c_mode = IMX8MQ_PAD_I2C1_SDA__I2C1_SDA | PC, + .gpio_mode = IMX8MQ_PAD_I2C1_SDA__GPIO5_IO15 | PC, + .gp = IMX_GPIO_NR(5, 15), + }, +}; + +#define USDHC2_CD_GPIO IMX_GPIO_NR(2, 12) +#define USDHC1_PWR_GPIO IMX_GPIO_NR(2, 10) +#define USDHC2_PWR_GPIO IMX_GPIO_NR(2, 19) + +int board_mmc_getcd(struct mmc *mmc) +{ + struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv; + int ret = 0; + + switch (cfg->esdhc_base) { + case USDHC1_BASE_ADDR: + ret = 1; + break; + case USDHC2_BASE_ADDR: + ret = !gpio_get_value(USDHC2_CD_GPIO); + return ret; + } + + return 1; +} + +#define USDHC_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_HYS | PAD_CTL_PUE | \ + PAD_CTL_FSEL2) +#define USDHC_GPIO_PAD_CTRL (PAD_CTL_PUE | PAD_CTL_DSE1) + +static iomux_v3_cfg_t const usdhc1_pads[] = { + IMX8MQ_PAD_SD1_CLK__USDHC1_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_CMD__USDHC1_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA0__USDHC1_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA1__USDHC1_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA2__USDHC1_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA3__USDHC1_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA4__USDHC1_DATA4 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA5__USDHC1_DATA5 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA6__USDHC1_DATA6 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_DATA7__USDHC1_DATA7 | MUX_PAD_CTRL(USDHC_PAD_CTRL), + IMX8MQ_PAD_SD1_RESET_B__GPIO2_IO10 | MUX_PAD_CTRL(NO_PAD_CTRL), +}; + +static iomux_v3_cfg_t const usdhc2_pads[] = { + IMX8MQ_PAD_SD2_CLK__USDHC2_CLK | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */ + IMX8MQ_PAD_SD2_CMD__USDHC2_CMD | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */ + IMX8MQ_PAD_SD2_DATA0__USDHC2_DATA0 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */ + IMX8MQ_PAD_SD2_DATA1__USDHC2_DATA1 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */ + IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0x16 */ + IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */ + IMX8MQ_PAD_SD2_CD_B__GPIO2_IO12 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), + IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), +}; + +static struct fsl_esdhc_cfg usdhc_cfg[2] = { + {USDHC1_BASE_ADDR, 0, 8}, + {USDHC2_BASE_ADDR, 0, 4}, +}; + +int board_mmc_init(bd_t *bis) +{ + int i, ret; + /* + * According to the board_mmc_init() the following map is done: + * (U-Boot device node) (Physical Port) + * mmc0 USDHC1 + * mmc1 USDHC2 + */ + for (i = 0; i < CONFIG_SYS_FSL_USDHC_NUM; i++) { + switch (i) { + case 0: + init_clk_usdhc(0); + usdhc_cfg[0].sdhc_clk = mxc_get_clock(USDHC1_CLK_ROOT); + imx_iomux_v3_setup_multiple_pads(usdhc1_pads, + ARRAY_SIZE(usdhc1_pads)); + gpio_request(USDHC1_PWR_GPIO, "usdhc1_reset"); + gpio_direction_output(USDHC1_PWR_GPIO, 0); + udelay(500); + gpio_direction_output(USDHC1_PWR_GPIO, 1); + break; + case 1: + init_clk_usdhc(1); + usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT); + imx_iomux_v3_setup_multiple_pads(usdhc2_pads, + ARRAY_SIZE(usdhc2_pads)); + gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset"); + gpio_direction_output(USDHC2_PWR_GPIO, 0); + udelay(500); + gpio_direction_output(USDHC2_PWR_GPIO, 1); + break; + default: + printf("Warning: you configured more USDHC controllers(%d) than supported by the board\n", i + 1); + return -EINVAL; + } + + ret = fsl_esdhc_initialize(bis, &usdhc_cfg[i]); + if (ret) + return ret; + } + + return 0; +} + +#ifdef CONFIG_POWER +#define I2C_PMIC 0 +int power_init_board(void) +{ + struct pmic *p; + int ret; + unsigned int reg; + + ret = power_pfuze100_init(I2C_PMIC); + if (ret) + return -ENODEV; + + p = pmic_get("PFUZE100"); + ret = pmic_probe(p); + if (ret) + return -ENODEV; + + pmic_reg_read(p, PFUZE100_DEVICEID, ®); + printf("PMIC: PFUZE100 ID=0x%02x\n", reg); + + pmic_reg_read(p, PFUZE100_SW3AVOL, ®); + if ((reg & 0x3f) != 0x18) { + reg &= ~0x3f; + reg |= 0x18; + pmic_reg_write(p, PFUZE100_SW3AVOL, reg); + } + + ret = pfuze_mode_init(p, APS_PFM); + if (ret < 0) + return ret; + + /* set SW3A standby mode to off */ + pmic_reg_read(p, PFUZE100_SW3AMODE, ®); + reg &= ~0xf; + reg |= APS_OFF; + pmic_reg_write(p, PFUZE100_SW3AMODE, reg); + + return 0; +} +#endif + +void spl_board_init(void) +{ + puts("Normal Boot\n"); +} + +#ifdef CONFIG_SPL_LOAD_FIT +int board_fit_config_name_match(const char *name) +{ + /* Just empty function now - can't decide what to choose */ + debug("%s: %s\n", __func__, name); + + return 0; +} +#endif + +void board_init_f(ulong dummy) +{ + int ret; + + /* Clear global data */ + memset((void *)gd, 0, sizeof(gd_t)); + + arch_cpu_init(); + + init_uart_clk(0); + + board_early_init_f(); + + timer_init(); + + preloader_console_init(); + + /* Clear the BSS. */ + memset(__bss_start, 0, __bss_end - __bss_start); + + ret = spl_init(); + if (ret) { + debug("spl_init() failed: %d\n", ret); + hang(); + } + + enable_tzc380(); + + /* Adjust pmic voltage to 1.0V for 800M */ + setup_i2c(0, CONFIG_SYS_I2C_SPEED, 0x7f, &i2c_pad_info1); + + power_init_board(); + + /* DDR initialization */ + spl_dram_init(); + + board_init_r(NULL, 0); +} diff --git a/configs/imx8mq_hb_defconfig b/configs/imx8mq_hb_defconfig new file mode 100644 index 000000000000..2f60990d6846 --- /dev/null +++ b/configs/imx8mq_hb_defconfig @@ -0,0 +1,66 @@ +CONFIG_ARM=y +CONFIG_ARCH_IMX8M=y +CONFIG_SYS_TEXT_BASE=0x40200000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_SPL_GPIO_SUPPORT=y +CONFIG_SPL_LIBCOMMON_SUPPORT=y +CONFIG_SPL_LIBGENERIC_SUPPORT=y +CONFIG_TARGET_IMX8MQ_HB=y +CONFIG_SPL_SERIAL_SUPPORT=y +CONFIG_SPL_MMC_SUPPORT=y +CONFIG_SPL_I2C_SUPPORT=y +CONFIG_SPL_POWER_SUPPORT=y +CONFIG_SPL_WATCHDOG_SUPPORT=y +CONFIG_SAVED_DRAM_TIMING_BASE=0x40000000 +CONFIG_DEFAULT_DEVICE_TREE="fsl-imx8mq-hb" +CONFIG_OF_LIST="fsl-imx8mq-hb" +CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/imx8m/imximage.cfg" +CONFIG_SPL_FIT_GENERATOR="arch/arm/mach-imx/mkimage_fit_atf.sh" +CONFIG_OF_BOARD_SETUP=y +CONFIG_SUPPORT_RAW_INITRD=y +CONFIG_FIT=y +CONFIG_SPL_LOAD_FIT=y +CONFIG_DISTRO_DEFAULTS=y +#CONFIG_SYS_EXTRA_OPTIONS="IMX_CONFIG=arch/arm/mach-imx/spl_sd.cfg" +CONFIG_SPL=y +CONFIG_SPL_BOARD_INIT=y +CONFIG_HUSH_PARSER=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_MMC_RPMB=y +CONFIG_CMD_PART=y +CONFIG_CMD_PING=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT2=y +CONFIG_CMD_EXT4=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_CMD_FAT=y +CONFIG_CMD_FS_GENERIC=y +CONFIG_CMD_FS_UUID=y +CONFIG_DOS_PARTITION=y +CONFIG_EFI_PARTITION=y +CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=128 +CONFIG_EFI_PARTITION_ENTRIES_OFF=0 +CONFIG_PARTITION_UUIDS=y +CONFIG_PARTITION_TYPE_GUID=y +CONFIG_ENV_IS_IN_MMC=y +CONFIG_OF_CONTROL=y +CONFIG_DM_GPIO=y +CONFIG_DM_I2C=y +CONFIG_DM_MMC=y +CONFIG_DM_ETH=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_IMX8M=y +CONFIG_SYS_I2C_MXC=y +CONFIG_DM_PMIC_PFUZE100=y +CONFIG_DM_REGULATOR=y +CONFIG_DM_REGULATOR_PFUZE100=y +CONFIG_DM_REGULATOR_FIXED=y +CONFIG_DM_REGULATOR_GPIO=y +CONFIG_DM_THERMAL=y +CONFIG_FIT_EXTERNAL_OFFSET=0x3000 +CONFIG_FSL_ESDHC=y +CONFIG_MXC_UART=y diff --git a/include/configs/imx8mq_hb.h b/include/configs/imx8mq_hb.h new file mode 100644 index 000000000000..932d159b93e3 --- /dev/null +++ b/include/configs/imx8mq_hb.h @@ -0,0 +1,270 @@ +/* + * Copyright 2018 SolidRun Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __IMX8M_HB_H +#define __IMX8M_HB_H + +#include +#include + +#ifdef CONFIG_SECURE_BOOT +#define CONFIG_CSF_SIZE 0x2000 /* 8K region */ +#endif + +#define CONFIG_SPL_TEXT_BASE 0x7E1000 +#define CONFIG_SPL_MAX_SIZE (124 * 1024) +#define CONFIG_SYS_MONITOR_LEN (512 * 1024) +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR +#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 0x300 +#define CONFIG_SYS_MMCSD_FS_BOOT_PARTITION 1 + +#ifdef CONFIG_SPL_BUILD +/*#define CONFIG_ENABLE_DDR_TRAINING_DEBUG*/ +#define CONFIG_SPL_LDSCRIPT "arch/arm/cpu/armv8/u-boot-spl.lds" +#define CONFIG_SPL_STACK 0x187FF0 +#define CONFIG_SPL_BSS_START_ADDR 0x00180000 +#define CONFIG_SPL_BSS_MAX_SIZE 0x2000 /* 8 KB */ +#define CONFIG_SYS_SPL_MALLOC_START 0x42200000 +#define CONFIG_SYS_SPL_MALLOC_SIZE 0x8000 /* 8 KB */ +#define CONFIG_SYS_SPL_PTE_RAM_BASE 0x41580000 +#define CONFIG_SYS_ICACHE_OFF +#define CONFIG_SYS_DCACHE_OFF + +/* malloc f used before GD_FLG_FULL_MALLOC_INIT set */ +#define CONFIG_MALLOC_F_ADDR 0x182000 +#define CONFIG_SPL_ABORT_ON_RAW_IMAGE /* For RAW image gives a error info not panic */ + +#undef CONFIG_DM_MMC +#undef CONFIG_DM_PMIC +#undef CONFIG_DM_PMIC_PFUZE100 + +#define CONFIG_SYS_I2C +#define CONFIG_SYS_I2C_MXC_I2C1 /* enable I2C bus 1 */ +#define CONFIG_SYS_I2C_MXC_I2C2 /* enable I2C bus 2 */ +#define CONFIG_SYS_I2C_MXC_I2C3 /* enable I2C bus 3 */ + +#define CONFIG_POWER +#define CONFIG_POWER_I2C +#define CONFIG_POWER_PFUZE100 +#define CONFIG_POWER_PFUZE100_I2C_ADDR 0x08 +#endif + +#define CONFIG_PREBOOT + +#define CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG + +#define CONFIG_REMAKE_ELF + +#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_BOARD_LATE_INIT + +/* Flat Device Tree Definitions */ +#ifndef CONFIG_OF_BOARD_SETUP +#define CONFIG_OF_BOARD_SETUP +#endif + +#undef CONFIG_CMD_EXPORTENV +#undef CONFIG_CMD_IMPORTENV +#undef CONFIG_CMD_IMLS + +/* #define CONFIG_CMD_BMODE */ +#undef CONFIG_CMD_CRC32 +#undef CONFIG_BOOTM_NETBSD + +/* ENET Config */ +/* ENET1 */ +#if defined(CONFIG_CMD_NET) +#define CONFIG_MII +#define CONFIG_ETHPRIME "FEC" + +#define CONFIG_FEC_MXC +#define CONFIG_FEC_XCV_TYPE RGMII +#define CONFIG_FEC_MXC_PHYADDR 4 +#define FEC_QUIRK_ENET_MAC +#define GP_RGMII_PHY_RESET IMX_GPIO_NR(1, 9) + +#define CONFIG_PHY_GIGE +#define IMX_FEC_BASE 0x30BE0000 + +#define CONFIG_PHYLIB +#define CONFIG_PHY_ATHEROS +#endif + +/* Link Definitions */ +#define CONFIG_LOADADDR 0x40480000 +#define CONFIG_SYS_TEXT_BASE 0x40200000 + +#define CONFIG_SYS_LOAD_ADDR CONFIG_LOADADDR + +#define CONFIG_SYS_INIT_RAM_ADDR 0x40000000 +#define CONFIG_SYS_INIT_RAM_SIZE 0x80000 +#define CONFIG_SYS_INIT_SP_OFFSET \ + (CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE) +#define CONFIG_SYS_INIT_SP_ADDR \ + (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_SP_OFFSET) + +#define CONFIG_ENV_OVERWRITE +#define CONFIG_ENV_SIZE 0x2000 +#define CONFIG_ENV_OFFSET (SZ_1M - CONFIG_ENV_SIZE) +#define CONFIG_SYS_MMC_ENV_DEV 1 /* USDHC1 */ + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN ((CONFIG_ENV_SIZE + (2*1024) + (16*1024)) * 1024) + +#define CONFIG_SYS_SDRAM_BASE 0x40000000 +#define PHYS_SDRAM 0x40000000 +#define PHYS_SDRAM_SIZE 0xC0000000 /* 3GB DDR */ + +#define CONFIG_BAUDRATE 115200 + +#define CONFIG_MXC_UART_BASE UART1_BASE_ADDR + +/* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 2048 +#define CONFIG_SYS_MAXARGS 64 +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE +#define CONFIG_SYS_PBSIZE (CONFIG_SYS_CBSIZE + \ + sizeof(CONFIG_SYS_PROMPT) + 16) + +#define CONFIG_IMX_BOOTAUX + +#define CONFIG_FSL_USDHC + +#define CONFIG_SYS_FSL_USDHC_NUM 2 +#define CONFIG_SYS_FSL_ESDHC_ADDR 0 + +#define CONFIG_SUPPORT_EMMC_BOOT /* eMMC specific */ +#define CONFIG_SUPPORT_EMMC_RPMB +#define CONFIG_SYS_MMC_IMG_LOAD_PART 1 + +#define CONFIG_MXC_GPIO + +#define CONFIG_MXC_OCOTP +#define CONFIG_CMD_FUSE + +/* I2C Configs */ +#define CONFIG_SYS_I2C_SPEED 100000 + +/* USB configs */ +#ifndef CONFIG_SPL_BUILD +#define CONFIG_HAS_FSL_XHCI_USB + +#ifdef CONFIG_HAS_FSL_XHCI_USB +#define CONFIG_USB_MAX_CONTROLLER_COUNT 2 +#endif + +#define CONFIG_USB_DWC3 +#define CONFIG_USB_DWC3_GADGET +#define CONFIG_USBD_HS + +#define CONFIG_USB_GADGET_MASS_STORAGE +#define CONFIG_USB_GADGET_VBUS_DRAW 2 +#define CONFIG_USB_GADGET_DUALSPEED + +#endif + +#define CONFIG_OF_SYSTEM_SETUP + +/* Framebuffer */ +#ifdef CONFIG_VIDEO +#define CONFIG_VIDEO_BMP_RLE8 +#define CONFIG_SPLASH_SCREEN +#define CONFIG_SPLASH_SCREEN_ALIGN +#define CONFIG_BMP_16BPP +#define CONFIG_VIDEO_LOGO +#define CONFIG_VIDEO_BMP_LOGO +#endif + +#ifdef CONFIG_CMD_MMC +#if (CONFIG_SYS_FSL_USDHC_NUM == 1) +#define DISTRO_BOOT_DEV_MMC(func) func(MMC, mmc, 0) +#elif (CONFIG_SYS_FSL_USDHC_NUM == 2) +#define DISTRO_BOOT_DEV_MMC(func) func(MMC, mmc, 0) func(MMC, mmc, 1) +#else +#define DISTRO_BOOT_DEV_MMC(func) func(MMC, mmc, 0) func(MMC, mmc, 1) func(MMC, mmc, 2) +#endif +#else +#define DISTRO_BOOT_DEV_MMC(func) +#endif + +#ifdef CONFIG_USB_STORAGE +#define DISTRO_BOOT_DEV_USB(func) func(USB, usb, 0) +#else +#define DISTRO_BOOT_DEV_USB(func) +#endif + +#ifndef BOOT_TARGET_DEVICES +#define BOOT_TARGET_DEVICES(func) \ + DISTRO_BOOT_DEV_MMC(func) \ + DISTRO_BOOT_DEV_USB(func) +#endif + +#include + +#define BD_RAM_BASE 0x80000000 +#define BD_RAM_SCRIPT "40008000" +#define BD_RAM_KERNEL "40800000" +#define BD_RAM_RAMDISK "42800000" +#define BD_RAM_FDT "43000000" + +/* M4 specific */ +#define SYS_AUXCORE_BOOTDATA_DDR 0x80000000 +#define SYS_AUXCORE_BOOTDATA_TCM 0x007E0000 + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "console=ttymxc0,115200 earlycon=ec_imx6q,0x30860000,115200\0" \ + "env_dev=" __stringify(CONFIG_SYS_MMC_ENV_DEV) "\0" \ + "env_part=" __stringify(CONFIG_SYS_MMC_ENV_PART) "\0" \ + "fdt_addr_r=0x43000000\0" \ + "fdt_file=fsl-imx8mq-hummingboard-pulse.dtb\0" \ + "fdtfile=fsl-imx8mq-hummingboard-pulse.dtb\0" \ + "ramdisk_addr_r=0x43800000\0" \ + "kernel_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \ + "pxefile_addr_r=" __stringify(CONFIG_LOADADDR) "\0" \ + "scriptaddr=" __stringify(CONFIG_LOADADDR) "\0" \ + "fdt_high=0xffffffffffffffff\0" \ + "initrd_high=0xffffffffffffffff\0" \ + "m4boot=load ${devtype} ${devnum}:1 ${m4loadaddr} ${m4image}; " \ + "dcache flush; bootaux ${m4loadaddr}\0" \ + "m4image=m4_fw.bin\0" \ + "m4loadaddr="__stringify(SYS_AUXCORE_BOOTDATA_TCM)"\0" \ + "netargs=setenv bootargs console=${console},115200 root=/dev/nfs rw " \ + "ip=dhcp nfsroot=${tftpserverip}:${nfsroot},v3,tcp\0" \ + "netboot=run netargs; " \ + "if test -z \"${fdt_file}\" -a -n \"${soc}\"; then " \ + "setenv fdt_file ${soc}-${board}${boardver}.dtb; " \ + "fi; " \ + "if test ${ip_dyn} = yes; then " \ + "setenv get_cmd dhcp; " \ + "else " \ + "setenv get_cmd tftp; " \ + "fi; " \ + "${get_cmd} ${loadaddr} ${tftpserverip}:Image; " \ + "if ${get_cmd} ${fdt_addr_r} ${tftpserverip}:${fdt_file}; then " \ + "booti ${loadaddr} - ${fdt_addr_r}; " \ + "else " \ + "echo WARN: Cannot load the DT; " \ + "fi;\0" \ + "net_upgradeu=dhcp " BD_RAM_SCRIPT " net_upgradeu.scr && source " BD_RAM_SCRIPT "\0" \ + "otg_upgradeu=run usbnetwork; tftp " BD_RAM_SCRIPT " net_upgradeu.scr && source " BD_RAM_SCRIPT "\0" \ + "upgradeu=setenv boot_scripts upgrade.scr; boot;" \ + "echo Upgrade failed!; setenv boot_scripts boot.scr\0" \ + "usbnet_devaddr=00:19:b8:00:00:02\0" \ + "usbnet_hostaddr=00:19:b8:00:00:01\0" \ + "usbnetwork=setenv ethact usb_ether; " \ + "setenv ipaddr 10.0.0.2; " \ + "setenv netmask 255.255.255.0; " \ + "setenv serverip 10.0.0.1;\0" \ + BOOTENV + +/* + * PCI express + */ +#ifdef CONFIG_CMD_PCI +#define CONFIG_PCI_SCAN_SHOW +#define CONFIG_PCIE_IMX +#endif +#endif From e2da404b0825998079451e4b743747358188f05d Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Wed, 14 Nov 2018 17:55:28 +0100 Subject: [PATCH 44/62] imx: mx8m: add memory mapping for CAAM and TCM Otherwise can't boot the M4 core as it is impossible to load its firmware into the TCM memory. Signed-off-by: Gary Bisson Reviewed-by: Peng Fan --- arch/arm/mach-imx/imx8m/soc.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index f67dad49ecf0..f8fc3bcbe76d 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -77,6 +77,22 @@ static struct mm_region imx8m_mem_map[] = { .size = 0x100000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_OUTER_SHARE + }, { + /* CAAM */ + .virt = 0x100000UL, + .phys = 0x100000UL, + .size = 0x8000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* TCM */ + .virt = 0x7C0000UL, + .phys = 0x7C0000UL, + .size = 0x80000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN }, { /* OCRAM */ .virt = 0x900000UL, From 360bff621914111f2529a60fa1519623caa491d8 Mon Sep 17 00:00:00 2001 From: Gary Bisson Date: Wed, 14 Nov 2018 17:55:29 +0100 Subject: [PATCH 45/62] imx: bootaux: fix stack and pc assignment on 64-bit platforms Using ulong is wrong as its size depends on the Host CPU architecture (32-bit vs. 64-bit) although the Cortex-M4 is always 32-bit. Without this patch, the stack and PC are obviously wrong and it generates an abort when used on 64-bit processors such as the i.MX8MQ. Signed-off-by: Gary Bisson Reviewed-by: Peng Fan --- arch/arm/mach-imx/imx_bootaux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c index ae3734ecb9a5..18d7e6819cb1 100644 --- a/arch/arm/mach-imx/imx_bootaux.c +++ b/arch/arm/mach-imx/imx_bootaux.c @@ -17,8 +17,8 @@ int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) if (!boot_private_data) return -EINVAL; - stack = *(ulong *)boot_private_data; - pc = *(ulong *)(boot_private_data + 4); + stack = *(u32 *)boot_private_data; + pc = *(u32 *)(boot_private_data + 4); /* Set the stack and pc to M4 bootROM */ writel(stack, M4_BOOTROM_BASE_ADDR); From fbf18a2e87466401b97c13487c0253c49ebc4f50 Mon Sep 17 00:00:00 2001 From: Li Jun Date: Sat, 26 Aug 2017 01:49:51 +0800 Subject: [PATCH 46/62] MLK-16273-1 usb: dwc3: add suspend clock setting interface Some dwc3 based USB3 IP may have a wrong default suspend clk setting, so add an interface to correct it by board setting. Acked-by: Peng Fan Signed-off-by: Li Jun --- drivers/usb/dwc3/core.c | 24 ++++++++++++++++++++++++ drivers/usb/dwc3/core.h | 2 ++ include/dwc3-uboot.h | 1 + 3 files changed, 27 insertions(+) diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 1ab5cee60969..c10d1264ceb3 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -396,6 +396,25 @@ static void dwc3_phy_setup(struct dwc3 *dwc) mdelay(100); } +void dwc3_set_suspend_clk(struct dwc3 *dwc) +{ + u32 reg; + + /* + * DWC3_GCTL.PWRDNSCALE: The USB3 suspend_clk input replaces + * pipe3_rx_pclk as a clock source to a small part of the USB3 + * core that operates when the SS PHY is in its lowest power + * (P3) state, and therefore does not provide a clock. + * The Power Down Scale field specifies how many suspend_clk + * periods fit into a 16 kHz clock period. When performing the + * division, round up the remainder. + */ + reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg &= ~(DWC3_GCTL_PWRDNSCALE(0x1fff)); + reg |= DWC3_GCTL_PWRDNSCALE(dwc->power_down_scale); + dwc3_writel(dwc->regs, DWC3_GCTL, reg); +} + /** * dwc3_core_init - Low-level initialization of DWC3 Core * @dwc: Pointer to our controller context structure @@ -444,6 +463,9 @@ static int dwc3_core_init(struct dwc3 *dwc) if (ret) goto err0; + if (dwc->power_down_scale) + dwc3_set_suspend_clk(dwc); + reg = dwc3_readl(dwc->regs, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; @@ -674,6 +696,8 @@ int dwc3_uboot_init(struct dwc3_device *dwc3_dev) if (dwc3_dev->tx_de_emphasis) tx_de_emphasis = dwc3_dev->tx_de_emphasis; + dwc->power_down_scale = dwc3_dev->power_down_scale; + /* default to superspeed if no maximum_speed passed */ if (dwc->maximum_speed == USB_SPEED_UNKNOWN) dwc->maximum_speed = USB_SPEED_SUPER; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 58fe91dc5131..ba70ecf14740 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -642,6 +642,7 @@ struct dwc3_scratchpad_array { * @dr_mode: requested mode of operation * @dcfg: saved contents of DCFG register * @gctl: saved contents of GCTL register + * @power_down_scale: 16KHz clock periods for suspend_clk * @isoch_delay: wValue from Set Isochronous Delay request; * @u2sel: parameter from Set SEL request. * @u2pel: parameter from Set SEL request. @@ -766,6 +767,7 @@ struct dwc3 { enum dwc3_ep0_state ep0state; enum dwc3_link_state link_state; + u16 power_down_scale; u16 isoch_delay; u16 u2sel; u16 u2pel; diff --git a/include/dwc3-uboot.h b/include/dwc3-uboot.h index 228ab3b10294..fe6fe8eb0e1a 100644 --- a/include/dwc3-uboot.h +++ b/include/dwc3-uboot.h @@ -15,6 +15,7 @@ struct dwc3_device { unsigned long base; enum usb_dr_mode dr_mode; u32 maximum_speed; + u16 power_down_scale; unsigned tx_fifo_resize:1; unsigned has_lpm_erratum; u8 lpm_nyet_threshold; From 8c6e3486558b1cbf109beb1dd020ee9b549eb179 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Thu, 30 Nov 2017 01:23:56 -0600 Subject: [PATCH 47/62] MLK-17044-1 imx-common: Adding new argument for SIP call interface Need to pass total 5 arguments for SIP HAB call, so update the interface to add new argument. Signed-off-by: Ye Li --- arch/arm/include/asm/mach-imx/sys_proto.h | 3 ++- arch/arm/mach-imx/imx_bootaux.c | 4 ++-- arch/arm/mach-imx/sip.c | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/asm/mach-imx/sys_proto.h b/arch/arm/include/asm/mach-imx/sys_proto.h index 8d6832a33104..4f088ec185ac 100644 --- a/arch/arm/include/asm/mach-imx/sys_proto.h +++ b/arch/arm/include/asm/mach-imx/sys_proto.h @@ -133,5 +133,6 @@ int mxs_wait_mask_set(struct mxs_register_32 *reg, u32 mask, u32 timeout); int mxs_wait_mask_clr(struct mxs_register_32 *reg, u32 mask, u32 timeout); unsigned long call_imx_sip(unsigned long id, unsigned long reg0, - unsigned long reg1, unsigned long reg2); + unsigned long reg1, unsigned long reg2, + unsigned long reg3); #endif diff --git a/arch/arm/mach-imx/imx_bootaux.c b/arch/arm/mach-imx/imx_bootaux.c index 18d7e6819cb1..3d9422d5a219 100644 --- a/arch/arm/mach-imx/imx_bootaux.c +++ b/arch/arm/mach-imx/imx_bootaux.c @@ -26,7 +26,7 @@ int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) /* Enable M4 */ #ifdef CONFIG_IMX8M - call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0); + call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_START, 0, 0, 0); #else clrsetbits_le32(SRC_BASE_ADDR + SRC_M4_REG_OFFSET, SRC_M4C_NON_SCLR_RST_MASK, SRC_M4_ENABLE_MASK); @@ -38,7 +38,7 @@ int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data) int arch_auxiliary_core_check_up(u32 core_id) { #ifdef CONFIG_IMX8M - return call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0); + return call_imx_sip(IMX_SIP_SRC, IMX_SIP_SRC_M4_STARTED, 0, 0, 0); #else unsigned int val; diff --git a/arch/arm/mach-imx/sip.c b/arch/arm/mach-imx/sip.c index 813c2ae5e11c..db8c7e5f9c51 100644 --- a/arch/arm/mach-imx/sip.c +++ b/arch/arm/mach-imx/sip.c @@ -7,7 +7,8 @@ #include unsigned long call_imx_sip(unsigned long id, unsigned long reg0, - unsigned long reg1, unsigned long reg2) + unsigned long reg1, unsigned long reg2, + unsigned long reg3) { struct pt_regs regs; @@ -15,6 +16,7 @@ unsigned long call_imx_sip(unsigned long id, unsigned long reg0, regs.regs[1] = reg0; regs.regs[2] = reg1; regs.regs[3] = reg2; + regs.regs[4] = reg3; smc_call(®s); From ae8f31b7e8908a4fed4e74154373323e7412be54 Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Thu, 29 Nov 2018 09:06:11 +0100 Subject: [PATCH 48/62] imx8mq_hb: Add Build.md This is marked up build instructions for generating a bootable FIT Image for the iMX8M based SolidRun Products Signed-off-by: Jon Nettleton --- board/solidrun/imx8mq_hb/BUILD.md | 51 +++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 board/solidrun/imx8mq_hb/BUILD.md diff --git a/board/solidrun/imx8mq_hb/BUILD.md b/board/solidrun/imx8mq_hb/BUILD.md new file mode 100644 index 000000000000..81f26544825c --- /dev/null +++ b/board/solidrun/imx8mq_hb/BUILD.md @@ -0,0 +1,51 @@ +### Toolchain +You can either build or download a ready-to-use toolchain. An example of such toolchains are from Linaro website. + +When writing this document the following toolchain was used – http://releases.linaro.org/components/toolchain/binaries/7.3-2018.05/aarch64-linux-gnu/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu.tar.xz + +Linaro updates it’s toolchain quite often and more frequent one can be downloaded from here – http://releases.linaro.org/components/toolchain/binaries/ + +Download and extract the toolchain into some place; and as instructed below the CROSS_COMPILE environment variables needs to be set to the path of the toolchain prefex. + +For instance if the toolchain was extracted under /opt/imx8m/toolchain/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu/ then the CROSS_COMPILE needs to be set as follows – +``` +export ARCH=arm64 +export CROSS_COMPILE=/opt/imx8m/toolchain/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu +``` + +### Download Source and Firmware +``` +git clone https://github.com/SolidRun/arm-trusted-firmware.git -b imx-atf-v1.6 +git clone https://github.com/SolidRun/u-boot.git -b v2018.11-solidrun +wget https://www.nxp.com/lgfiles/NMG/MAD/YOCTO/firmware-imx-7.9.bin +``` + +### ATF +Building ATF is as follows – *make sure you have set your ARCH and CROSS_COMPILE environment variables as noted above* +``` +cd arm-trusted-firmware +make PLAT=imx8mq bl31 +cp build/imx8mq/release/bl31.bin ../u-boot/ +cd .. +``` + +### Extract and copy firmware +Extract the NXP firmware archive and accept the end user agreement +``` +chmod +x firmware-imx-7.9.bin +./firmware-imx-7.9.bin +cp firmware-imx-7.9/firmware/hdmi/cadence/signed_hdmi_imx8m.bin u-boot/ +cp firmware-imx-7.9/firmware-imx-7.9/firmware/ddr/synopsys/lpddr4*.bin u-boot/ +``` + +### U-Boot +Build U-Boot and generate the image - *make sure you have set your ARCH and CROSS_COMPILE environment variables as noted above* +``` +make imx8mq_hb_defconfig +make flash.bin +``` + +### Writing to SD-Card +``` +sudo dd if=flash.bin of=/dev/sd[x] bs=1024 seek=33 +``` From 2c0f2ce53fdb1fb854fa00433b95588e0b6742cb Mon Sep 17 00:00:00 2001 From: Jon Nettleton <35342700+jnettlet@users.noreply.github.com> Date: Fri, 30 Nov 2018 08:04:40 +0100 Subject: [PATCH 49/62] Update BUILD.md Missed a spelling error --- board/solidrun/imx8mq_hb/BUILD.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/board/solidrun/imx8mq_hb/BUILD.md b/board/solidrun/imx8mq_hb/BUILD.md index 81f26544825c..ed82a01adfc4 100644 --- a/board/solidrun/imx8mq_hb/BUILD.md +++ b/board/solidrun/imx8mq_hb/BUILD.md @@ -10,7 +10,7 @@ Download and extract the toolchain into some place; and as instructed below the For instance if the toolchain was extracted under /opt/imx8m/toolchain/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu/ then the CROSS_COMPILE needs to be set as follows – ``` export ARCH=arm64 -export CROSS_COMPILE=/opt/imx8m/toolchain/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu +export CROSS_COMPILE=/opt/imx8m/toolchain/gcc-linaro-7.3.1-2018.05-i686_aarch64-linux-gnu/bin/aarch64-linux-gnu- ``` ### Download Source and Firmware From 49b8c8027df04c4ebde3f8660c43842cec259a39 Mon Sep 17 00:00:00 2001 From: TalPilo Date: Sun, 9 Dec 2018 19:14:04 +0200 Subject: [PATCH 50/62] Add uboot support for armada 8040 cex(dts and defconfig) Signed-off-by: TalPilo --- arch/arm/dts/Makefile | 1 + arch/arm/dts/armada-8040-cex.dts | 299 ++++++++++++++++++++++++++++ configs/mvebu_cex-88f8040_defconfig | 75 +++++++ 3 files changed, 375 insertions(+) create mode 100644 arch/arm/dts/armada-8040-cex.dts create mode 100644 configs/mvebu_cex-88f8040_defconfig diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index c2809ab9e0b1..20aaf9dbe632 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -100,6 +100,7 @@ dtb-$(CONFIG_ARCH_MVEBU) += \ armada-7040-db-nand.dtb \ armada-8040-db.dtb \ armada-8040-mcbin.dtb \ + armada-8040-cex.dtb \ armada-xp-gp.dtb \ armada-xp-maxbcm.dtb \ armada-xp-synology-ds414.dtb \ diff --git a/arch/arm/dts/armada-8040-cex.dts b/arch/arm/dts/armada-8040-cex.dts new file mode 100644 index 000000000000..0663743b8f9f --- /dev/null +++ b/arch/arm/dts/armada-8040-cex.dts @@ -0,0 +1,299 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2016 Marvell International Ltd. + */ + +#include "armada-8040.dtsi" /* include SoC device tree */ + +/ { + model = "Armada-8040-cex"; + compatible = "marvell,armada-8040-cex", + "marvell,armada8040"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + i2c0 = &cpm_i2c0; + i2c1 = &cpm_i2c1; + i2c2 = &cps_i2c1; + spi0 = &cps_spi1; + gpio0 = &ap_gpio0; + gpio1 = &cpm_gpio0; + gpio2 = &cpm_gpio1; + }; + + memory@00000000 { + device_type = "memory"; + reg = <0x0 0x0 0x0 0x80000000>; + }; + + simple-bus { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_usb3h0_vbus: usb3-vbus0 { + compatible = "regulator-fixed"; + pinctrl-names = "default"; + pinctrl-0 = <&cpm_xhci_vbus_pins>; + regulator-name = "reg-usb3h0-vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + startup-delay-us = <500000>; + enable-active-high; + regulator-always-on; + regulator-boot-on; + gpio = <&cpm_gpio1 15 GPIO_ACTIVE_HIGH>; /* GPIO[47] */ + }; + }; +}; + +/* Accessible over the mini-USB CON9 connector on the main board */ +&uart0 { + status = "okay"; +}; + +&ap_pinctl { + /* + * MPP Bus: + * eMMC [0-10] + * UART0 [11,19] + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 1 1 1 1 1 1 1 1 1 1 + 1 3 0 0 0 0 0 0 0 3 >; +}; + +/* on-board eMMC */ +&ap_sdhci0 { + pinctrl-names = "default"; + pinctrl-0 = <&ap_emmc_pins>; + bus-width= <8>; + status = "okay"; +}; + +&cpm_pinctl { + /* + * MPP Bus: + * [0-31] = 0xff: Keep default CP0_shared_pins: + * [11] CLKOUT_MPP_11 (out) + * [23] LINK_RD_IN_CP2CP (in) + * [25] CLKOUT_MPP_25 (out) + * [29] AVS_FB_IN_CP2CP (in) + * [32,34] SMI + * [33] MSS power down + * [35-38] CP0 I2C1 and I2C0 + * [39] MSS CKE Enable + * [40,41] CP0 UART1 TX/RX + * [42,43] XSMI (controls two 10G phys) + * [47] USB VBUS EN + * [48] FAN PWM + * [49] 10G port 1 interrupt + * [50] 10G port 0 interrupt + * [51] 2.5G SFP TX fault + * [52] PCIe reset out + * [53] 2.5G SFP mode + * [54] 2.5G SFP LOS + * [55] Micro SD card detect + * [56-61] Micro SD + * [62] CP1 SFI SFP FAULT + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0 7 0xa 7 2 2 2 2 0xa + 7 7 8 8 0 0 0 0 0 0 + 0 0 0 0 0 0 0xe 0xe 0xe 0xe + 0xe 0xe 0 >; + + cpm_xhci_vbus_pins: cpm-xhci-vbus-pins { + marvell,pins = < 47 >; + marvell,function = <0>; + }; + + cpm_pcie_reset_pins: cpm-pcie-reset-pins { + marvell,pins = < 52 >; + marvell,function = <0>; + }; +}; + +/* uSD slot */ +&cpm_sdhci0 { + pinctrl-names = "default"; + pinctrl-0 = <&cpm_sdhci_pins>; + bus-width= <4>; + status = "okay"; +}; + +/* PCIe x4 */ +&cpm_pcie0 { + num-lanes = <4>; + pinctrl-names = "default"; + pinctrl-0 = <&cpm_pcie_reset_pins>; + marvell,reset-gpio = <&cpm_gpio1 20 GPIO_ACTIVE_HIGH>; /* GPIO[52] */ + status = "okay"; +}; + +&cpm_i2c0 { + pinctrl-names = "default"; + pinctrl-0 = <&cpm_i2c0_pins>; + status = "okay"; + clock-frequency = <100000>; +}; + +&cpm_i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&cpm_i2c1_pins>; + status = "okay"; + clock-frequency = <100000>; +}; + +&cpm_sata0 { + status = "okay"; +}; + +&cpm_comphy { + /* + * CP0 Serdes Configuration: + * Lane 0: PCIe0 (x4) + * Lane 1: PCIe0 (x4) + * Lane 2: PCIe0 (x4) + * Lane 3: PCIe0 (x4) + * Lane 4: SFI (10G) + * Lane 5: SATA1 + */ + phy0 { + phy-type = ; + }; + phy1 { + phy-type = ; + }; + phy2 { + phy-type = ; + }; + phy3 { + phy-type = ; + }; + phy4 { + phy-type = ; + }; + phy5 { + phy-type = ; + }; +}; + +&cps_i2c1 { + pinctrl-names = "default"; + pinctrl-0 = <&cps_i2c1_pins>; + status = "okay"; + clock-frequency = <100000>; +}; + +&cps_sata0 { + status = "okay"; +}; + +&cps_usb3_0 { + vbus-supply = <®_usb3h0_vbus>; + status = "okay"; +}; + +&cps_utmi0 { + status = "okay"; +}; + +&cps_pinctl { + /* + * MPP Bus: + * [0-5] TDM + * [6,7] CP1_UART 0 + * [8] CP1 10G SFP LOS + * [9] CP1 10G PHY RESET + * [10] CP1 10G SFP TX Disable + * [11] CP1 10G SFP Mode + * [12] SPI1 CS1n + * [13] SPI1 MISO (TDM and SPI ROM shared) + * [14] SPI1 CS0n + * [15] SPI1 MOSI (TDM and SPI ROM shared) + * [16] SPI1 CLK (TDM and SPI ROM shared) + * [24] CP1 2.5G SFP TX Disable + * [26] CP0 10G SFP TX Fault + * [27] CP0 10G SFP Mode + * [28] CP0 10G SFP LOS + * [29] CP0 10G SFP TX Disable + * [30] USB Over current indication + * [31] 10G Port 0 phy reset + * [32-62] = 0xff: Keep default CP1_shared_pins: + */ + /* 0 1 2 3 4 5 6 7 8 9 */ + pin-func = < 0x4 0x4 0x4 0x4 0x4 0x4 0x8 0x8 0x0 0x0 + 0x0 0x0 0x3 0x3 0x3 0x3 0x3 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0x0 0xff 0x0 0x0 0x0 0x0 + 0x0 0x0 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff + 0xff 0xff 0xff>; +}; + +&cps_spi1 { + pinctrl-names = "default"; + pinctrl-0 = <&cps_spi1_pins>; + status = "okay"; + + spi-flash@0 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <10000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "U-Boot"; + reg = <0 0x200000>; + }; + partition@400000 { + label = "Filesystem"; + reg = <0x200000 0xce0000>; + }; + }; + }; +}; + +&cps_comphy { + /* + * CP1 Serdes Configuration: + * Lane 0: mPCIe0 (x1) + * Lane 1: SATA 0 + * Lane 2: USB HOST 0 + * Lane 3: SGMII1 + * Lane 4: SFI (10G) + * Lane 5: mPCIe1 (x1) + */ + phy0 { + phy-type = ; + }; + phy1 { + phy-type = ; + }; + phy2 { + phy-type = ; + }; + phy3 { + phy-type = ; + phy-speed = ; + }; + phy4 { + phy-type = ; + }; + phy5 { + phy-type = ; + }; +}; diff --git a/configs/mvebu_cex-88f8040_defconfig b/configs/mvebu_cex-88f8040_defconfig new file mode 100644 index 000000000000..8413671b3952 --- /dev/null +++ b/configs/mvebu_cex-88f8040_defconfig @@ -0,0 +1,75 @@ +CONFIG_ARM=y +CONFIG_ARCH_MVEBU=y +CONFIG_SYS_TEXT_BASE=0x00000000 +CONFIG_SYS_MALLOC_F_LEN=0x2000 +CONFIG_TARGET_MVEBU_ARMADA_8K=y +CONFIG_DEBUG_UART_BASE=0xf0512000 +CONFIG_DEBUG_UART_CLOCK=200000000 +CONFIG_SMBIOS_PRODUCT_NAME="" +CONFIG_DEBUG_UART=y +CONFIG_AHCI=y +CONFIG_DISTRO_DEFAULTS=y +CONFIG_NR_DRAM_BANKS=2 +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_SYS_CONSOLE_INFO_QUIET=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_DISPLAY_BOARDINFO is not set +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_ARCH_EARLY_INIT_R=y +CONFIG_BOARD_EARLY_INIT_F=y +# CONFIG_CMD_FLASH is not set +CONFIG_CMD_GPIO=y +CONFIG_CMD_I2C=y +CONFIG_CMD_MMC=y +CONFIG_CMD_PCI=y +CONFIG_CMD_SF=y +CONFIG_CMD_SPI=y +CONFIG_CMD_USB=y +# CONFIG_CMD_SETEXPR is not set +CONFIG_CMD_TFTPPUT=y +CONFIG_CMD_CACHE=y +CONFIG_CMD_TIME=y +CONFIG_CMD_MVEBU_BUBT=y +CONFIG_CMD_REGULATOR=y +CONFIG_CMD_EXT4_WRITE=y +CONFIG_MAC_PARTITION=y +CONFIG_DEFAULT_DEVICE_TREE="armada-8040-cex" +CONFIG_ENV_IS_IN_SPI_FLASH=y +CONFIG_AHCI_MVEBU=y +CONFIG_DM_GPIO=y +CONFIG_DM_I2C=y +CONFIG_SYS_I2C_MVTWSI=y +CONFIG_MISC=y +CONFIG_DM_MMC=y +CONFIG_MMC_SDHCI=y +CONFIG_MMC_SDHCI_XENON=y +CONFIG_SPI_FLASH=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_WINBOND=y +CONFIG_PHYLIB=y +CONFIG_PHY_GIGE=y +CONFIG_PCI=y +CONFIG_DM_PCI=y +CONFIG_PCIE_DW_MVEBU=y +CONFIG_MVEBU_COMPHY_SUPPORT=y +CONFIG_PINCTRL=y +CONFIG_PINCTRL_ARMADA_8K=y +CONFIG_DM_REGULATOR_FIXED=y +# CONFIG_SPL_SERIAL_PRESENT is not set +CONFIG_DEBUG_UART_SHIFT=2 +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_SYS_NS16550=y +CONFIG_KIRKWOOD_SPI=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_STORAGE=y +CONFIG_USB_HOST_ETHER=y +CONFIG_USB_ETHER_ASIX=y +CONFIG_USB_ETHER_MCS7830=y +CONFIG_USB_ETHER_RTL8152=y +CONFIG_USB_ETHER_SMSC95XX=y +CONFIG_SMBIOS_MANUFACTURER="" From 61a02147e466b2d6ef4dff1a185875f69bb30288 Mon Sep 17 00:00:00 2001 From: TalPilo Date: Tue, 11 Dec 2018 11:43:02 +0200 Subject: [PATCH 51/62] Add support for 16Gb DRAM detection Signed-off-by: TalPilo --- arch/arm/dts/armada-8040-cex.dts | 2 +- arch/arm/mach-mvebu/arm64-common.c | 48 +++++++++++++++++++++- arch/arm/mach-tegra/tegra186/nvtboot_mem.c | 3 +- include/linux/sizes.h | 4 ++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/arch/arm/dts/armada-8040-cex.dts b/arch/arm/dts/armada-8040-cex.dts index 0663743b8f9f..0c1cf94bb86e 100644 --- a/arch/arm/dts/armada-8040-cex.dts +++ b/arch/arm/dts/armada-8040-cex.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) 2016 Marvell International Ltd. + * Copyright (C) 2018 SolidRun International Ltd. */ #include "armada-8040.dtsi" /* include SoC device tree */ diff --git a/arch/arm/mach-mvebu/arm64-common.c b/arch/arm/mach-mvebu/arm64-common.c index f47273fde9c6..15bb14e45112 100644 --- a/arch/arm/mach-mvebu/arm64-common.c +++ b/arch/arm/mach-mvebu/arm64-common.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -45,15 +46,60 @@ const struct mbus_dram_target_info *mvebu_mbus_dram_info(void) /* DRAM init code ... */ +#define MV_SIP_DRAM_SIZE 0x82000010 + +static u64 a8k_dram_scan_ap_sz(void) +{ + struct pt_regs pregs; + + pregs.regs[0] = MV_SIP_DRAM_SIZE; + pregs.regs[1] = SOC_REGS_PHY_BASE; + smc_call(&pregs); + + return pregs.regs[0]; +} + +static void a8k_dram_init_banksize(void) +{ + /* + * Config 2 DRAM banks: + * Bank 0 - max size 4G - 1G + * Bank 1 - ram size - 4G + 1G + */ + phys_size_t max_bank0_size = SZ_4G - SZ_1G; + + gd->bd->bi_dram[0].start = CONFIG_SYS_SDRAM_BASE; + if (gd->ram_size <= max_bank0_size) { + gd->bd->bi_dram[0].size = gd->ram_size; + return; + } + + gd->bd->bi_dram[0].size = max_bank0_size; + if (CONFIG_NR_DRAM_BANKS > 1) { + gd->bd->bi_dram[1].start = SZ_4G; + gd->bd->bi_dram[1].size = gd->ram_size - max_bank0_size; + } +} + + int dram_init_banksize(void) { - fdtdec_setup_memory_banksize(); + if (CONFIG_IS_ENABLED(ARMADA_8K)) + a8k_dram_init_banksize(); + else + fdtdec_setup_memory_banksize(); return 0; } int dram_init(void) { + if (CONFIG_IS_ENABLED(ARMADA_8K)) { + gd->ram_size = a8k_dram_scan_ap_sz(); + if (gd->ram_size != 0) + return 0; + } + if (fdtdec_setup_mem_size_base() != 0) return -EINVAL; diff --git a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c index 5c9467bfe8be..62142821a595 100644 --- a/arch/arm/mach-tegra/tegra186/nvtboot_mem.c +++ b/arch/arm/mach-tegra/tegra186/nvtboot_mem.c @@ -6,11 +6,10 @@ #include #include #include +#include #include #include -#define SZ_4G 0x100000000ULL - /* * Size of a region that's large enough to hold the relocated U-Boot and all * other allocations made around it (stack, heap, page tables, etc.) diff --git a/include/linux/sizes.h b/include/linux/sizes.h index ce3e8150c174..e32e4343cf8b 100644 --- a/include/linux/sizes.h +++ b/include/linux/sizes.h @@ -8,6 +8,8 @@ #ifndef __LINUX_SIZES_H__ #define __LINUX_SIZES_H__ +#include + #define SZ_1 0x00000001 #define SZ_2 0x00000002 #define SZ_4 0x00000004 @@ -44,4 +46,6 @@ #define SZ_1G 0x40000000 #define SZ_2G 0x80000000 +#define SZ_4G _AC(0x100000000, ULL) + #endif /* __LINUX_SIZES_H__ */ From a6eb67fc9f1a6be4c9bfa789310639b02983482f Mon Sep 17 00:00:00 2001 From: Ye Li Date: Tue, 12 Sep 2017 04:38:00 -0500 Subject: [PATCH 52/62] MLK-16431-2 imx8qxp_mek: Add driver for USB typec port controller (TCPC) Add an simple driver for USB typec port controller in freescale common codes. The functions in this driver help to initialize the TCPC, set and work with fixed DFP role. Will improve it later to support UFP and move to driver directory. Signed-off-by: Ye Li --- board/freescale/common/Makefile | 1 + board/freescale/common/tcpc.c | 223 ++++++++++++++++++++++++++++++++ board/freescale/common/tcpc.h | 88 +++++++++++++ 3 files changed, 312 insertions(+) create mode 100644 board/freescale/common/tcpc.c create mode 100644 board/freescale/common/tcpc.h diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index e3c5eaeb7026..cfd2dd3ef204 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -78,4 +78,5 @@ obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o endif obj-$(CONFIG_CHAIN_OF_TRUST) += fsl_chain_of_trust.o +obj-$(CONFIG_USB_XHCI_IMX8) += tcpc.o endif diff --git a/board/freescale/common/tcpc.c b/board/freescale/common/tcpc.c new file mode 100644 index 000000000000..5931cb1f1193 --- /dev/null +++ b/board/freescale/common/tcpc.c @@ -0,0 +1,223 @@ +/* + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ +#include +#include +#include +#include "tcpc.h" + +int tcpc_set_cc_to_source(struct udevice *i2c_dev) +{ + uint8_t valb; + int err; + + valb = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) | + (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) | + (TCPC_ROLE_CTRL_RP_VAL_DEF << + TCPC_ROLE_CTRL_RP_VAL_SHIFT); + + err = dm_i2c_write(i2c_dev, TCPC_ROLE_CTRL, &valb, 1); + if (err) + printf("%s dm_i2c_write failed, err %d\n", __func__, err); + return err; +} + +int tcpc_set_plug_orientation(struct udevice *i2c_dev, enum typec_cc_polarity polarity) +{ + uint8_t valb; + int err; + + err = dm_i2c_read(i2c_dev, TCPC_TCPC_CTRL, &valb, 1); + if (err) { + printf("%s dm_i2c_read failed, err %d\n", __func__, err); + return -EIO; + } + + if (polarity == TYPEC_POLARITY_CC2) + valb |= TCPC_TCPC_CTRL_ORIENTATION; + else + valb &= ~TCPC_TCPC_CTRL_ORIENTATION; + + err = dm_i2c_write(i2c_dev, TCPC_TCPC_CTRL, &valb, 1); + if (err) { + printf("%s dm_i2c_write failed, err %d\n", __func__, err); + return -EIO; + } + + return 0; +} + +int tcpc_get_cc_polarity(struct udevice *i2c_dev, enum typec_cc_polarity *polarity) +{ + + uint8_t valb; + int err; + + err = dm_i2c_read(i2c_dev, TCPC_CC_STATUS, &valb, 1); + if (err) { + printf("%s dm_i2c_read failed, err %d\n", __func__, err); + return -EIO; + } + + debug("cc status 0x%x\n", valb); + + /* Set to Rp at default */ + if (valb & TCPC_CC_STATUS_TERM) + return -EPERM; + + if (((valb >> TCPC_CC_STATUS_CC1_SHIFT) & TCPC_CC_STATUS_CC1_MASK) == 0x2) + *polarity = TYPEC_POLARITY_CC1; + else if (((valb >> TCPC_CC_STATUS_CC2_SHIFT) & TCPC_CC_STATUS_CC2_MASK) == 0x2) + *polarity = TYPEC_POLARITY_CC2; + else + return -EFAULT; + return 0; +} + +int tcpc_clear_alert(struct udevice *i2c_dev, uint16_t clear_mask) +{ + int err; + err = dm_i2c_write(i2c_dev, TCPC_ALERT, (const uint8_t *)&clear_mask, 2); + if (err) { + printf("%s dm_i2c_write failed, err %d\n", __func__, err); + return -EIO; + } + + return 0; +} + +int tcpc_send_command(struct udevice *i2c_dev, uint8_t command) +{ + int err; + err = dm_i2c_write(i2c_dev, TCPC_COMMAND, (const uint8_t *)&command, 1); + if (err) { + printf("%s dm_i2c_write failed, err %d\n", __func__, err); + return -EIO; + } + + return 0; +} + +int tcpc_polling_reg(struct udevice *i2c_dev, uint8_t reg, + uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms) +{ + uint16_t val = 0; + int err; + ulong start; + + debug("%s reg 0x%x, mask 0x%x, value 0x%x\n", __func__, reg, mask, value); + + /* TCPC registers is 8 bits or 16 bits */ + if (reg_width != 1 && reg_width != 2) + return -EINVAL; + + start = get_timer(0); /* Get current timestamp */ + do { + err = dm_i2c_read(i2c_dev, reg, (uint8_t *)&val, reg_width); + if (err) + return -EIO; + + debug("val = 0x%x\n", val); + + if ((val & mask) == value) + return 0; + } while (get_timer(0) < (start + timeout_ms)); + + return -ETIME; +} + +int tcpc_init(struct udevice *i2c_dev) +{ + int ret; + + /* Check the Initialization Status bit in 1s */ + ret = tcpc_polling_reg(i2c_dev, TCPC_POWER_STATUS, 1, TCPC_POWER_STATUS_UNINIT, 0, 1000); + if (ret) { + printf("%s: Polling TCPC POWER STATUS Initialization Status bit failed, ret = %d\n", + __func__, ret); + return ret; + } + + tcpc_clear_alert(i2c_dev, 0xffff); + + return 0; +} + +int tcpc_setup_dfp_mode(struct udevice *i2c_dev, ss_mux_sel ss_sel_func) +{ + enum typec_cc_polarity pol; + int ret; + + tcpc_set_cc_to_source(i2c_dev); + + ret = tcpc_send_command(i2c_dev, TCPC_CMD_LOOK4CONNECTION); + if (ret) + return ret; + + /* At least wait tCcStatusDelay + tTCPCFilter + tCcTCPCSampleRate (max) = 200us + 500us + ?ms + * PTN5110 datasheet does not contain the sample rate value, according other productions, + * the sample rate is at ms level, about 2 ms -10ms. So wait 100ms should be enough. + */ + mdelay(100); + + ret = tcpc_polling_reg(i2c_dev, TCPC_ALERT, 2, TCPC_ALERT_CC_STATUS, TCPC_ALERT_CC_STATUS, 100); + if (ret) { + printf("%s: Polling ALERT register, TCPC_ALERT_CC_STATUS bit failed, ret = %d\n", + __func__, ret); + return ret; + } + + ret = tcpc_get_cc_polarity(i2c_dev, &pol); + tcpc_clear_alert(i2c_dev, TCPC_ALERT_CC_STATUS); + + if (!ret) { + if (pol == TYPEC_POLARITY_CC1) + debug("polarity cc1\n"); + else + debug("polarity cc2\n"); + + if (ss_sel_func) + ss_sel_func(pol); + + ret = tcpc_set_plug_orientation(i2c_dev, pol); + if (ret) + return ret; + + /* Disable sink vbus */ + ret = tcpc_send_command(i2c_dev, TCPC_CMD_DISABLE_SINK_VBUS); + if (ret) + return ret; + + /* Enable source vbus default voltage */ + ret = tcpc_send_command(i2c_dev, TCPC_CMD_SRC_VBUS_DEFAULT); + if (ret) + return ret; + + /* The max vbus on time is 200ms, we add margin 100ms */ + mdelay(300); + + } + + return 0; +} + +int tcpc_disable_vbus(struct udevice *i2c_dev) +{ + int ret; + + /* Disable VBUS*/ + ret = tcpc_send_command(i2c_dev, TCPC_CMD_DISABLE_SINK_VBUS); + if (ret) + return ret; + + ret = tcpc_send_command(i2c_dev, TCPC_CMD_DISABLE_SRC_VBUS); + if (ret) + return ret; + + /* The max vbus off time is 0.5ms, we add margin 0.5 ms */ + mdelay(1); + + return 0; +} diff --git a/board/freescale/common/tcpc.h b/board/freescale/common/tcpc.h new file mode 100644 index 000000000000..ad981d182042 --- /dev/null +++ b/board/freescale/common/tcpc.h @@ -0,0 +1,88 @@ +/* + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __TCPCI_H +#define __TCPCI_H + +#include + +#define TCPC_TCPC_CTRL 0x19 +#define TCPC_TCPC_CTRL_ORIENTATION BIT(0) + +#define TCPC_CC_STATUS 0x1d +#define TCPC_CC_STATUS_TERM BIT(4) +#define TCPC_CC_STATUS_CC2_SHIFT 2 +#define TCPC_CC_STATUS_CC2_MASK 0x3 +#define TCPC_CC_STATUS_CC1_SHIFT 0 +#define TCPC_CC_STATUS_CC1_MASK 0x3 + +#define TCPC_ROLE_CTRL 0x1a +#define TCPC_ROLE_CTRL_DRP BIT(6) +#define TCPC_ROLE_CTRL_RP_VAL_SHIFT 4 +#define TCPC_ROLE_CTRL_RP_VAL_MASK 0x3 +#define TCPC_ROLE_CTRL_RP_VAL_DEF 0x0 +#define TCPC_ROLE_CTRL_RP_VAL_1_5 0x1 +#define TCPC_ROLE_CTRL_RP_VAL_3_0 0x2 +#define TCPC_ROLE_CTRL_CC2_SHIFT 2 +#define TCPC_ROLE_CTRL_CC2_MASK 0x3 +#define TCPC_ROLE_CTRL_CC1_SHIFT 0 +#define TCPC_ROLE_CTRL_CC1_MASK 0x3 +#define TCPC_ROLE_CTRL_CC_RA 0x0 +#define TCPC_ROLE_CTRL_CC_RP 0x1 +#define TCPC_ROLE_CTRL_CC_RD 0x2 +#define TCPC_ROLE_CTRL_CC_OPEN 0x3 + +#define TCPC_COMMAND 0x23 +#define TCPC_CMD_WAKE_I2C 0x11 +#define TCPC_CMD_DISABLE_VBUS_DETECT 0x22 +#define TCPC_CMD_ENABLE_VBUS_DETECT 0x33 +#define TCPC_CMD_DISABLE_SINK_VBUS 0x44 +#define TCPC_CMD_SINK_VBUS 0x55 +#define TCPC_CMD_DISABLE_SRC_VBUS 0x66 +#define TCPC_CMD_SRC_VBUS_DEFAULT 0x77 +#define TCPC_CMD_SRC_VBUS_HIGH 0x88 +#define TCPC_CMD_LOOK4CONNECTION 0x99 +#define TCPC_CMD_RXONEMORE 0xAA +#define TCPC_CMD_I2C_IDLE 0xFF + +#define TCPC_ALERT 0x10 +#define TCPC_ALERT_VBUS_DISCNCT BIT(11) +#define TCPC_ALERT_RX_BUF_OVF BIT(10) +#define TCPC_ALERT_FAULT BIT(9) +#define TCPC_ALERT_V_ALARM_LO BIT(8) +#define TCPC_ALERT_V_ALARM_HI BIT(7) +#define TCPC_ALERT_TX_SUCCESS BIT(6) +#define TCPC_ALERT_TX_DISCARDED BIT(5) +#define TCPC_ALERT_TX_FAILED BIT(4) +#define TCPC_ALERT_RX_HARD_RST BIT(3) +#define TCPC_ALERT_RX_STATUS BIT(2) +#define TCPC_ALERT_POWER_STATUS BIT(1) +#define TCPC_ALERT_CC_STATUS BIT(0) + +#define TCPC_POWER_STATUS 0x1e +#define TCPC_POWER_STATUS_UNINIT BIT(6) +#define TCPC_POWER_STATUS_VBUS_DET BIT(3) +#define TCPC_POWER_STATUS_VBUS_PRES BIT(2) + +enum typec_cc_polarity { + TYPEC_POLARITY_CC1, + TYPEC_POLARITY_CC2, +}; + +typedef void (*ss_mux_sel)(enum typec_cc_polarity pol); + +int tcpc_set_cc_to_source(struct udevice *i2c_dev); +int tcpc_set_plug_orientation(struct udevice *i2c_dev, enum typec_cc_polarity polarity); +int tcpc_get_cc_polarity(struct udevice *i2c_dev, enum typec_cc_polarity *polarity); +int tcpc_clear_alert(struct udevice *i2c_dev, uint16_t clear_mask); +int tcpc_send_command(struct udevice *i2c_dev, uint8_t command); +int tcpc_polling_reg(struct udevice *i2c_dev, uint8_t reg, + uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms); +int tcpc_setup_dfp_mode(struct udevice *i2c_dev, ss_mux_sel ss_sel_func); +int tcpc_disable_vbus(struct udevice *i2c_dev); +int tcpc_init(struct udevice *i2c_dev); + +#endif /* __TCPCI_H */ From 51853ccf7d06707b4fda91c083f138b26ec6d01e Mon Sep 17 00:00:00 2001 From: Ye Li Date: Mon, 8 Jan 2018 08:05:51 -0600 Subject: [PATCH 53/62] MLK-17313-1 tcpc: Add support for power sink in dead battery To add support for power sink when booting in dead battery, we have to setup PD connection with PD source and send/receive PD messages to negotiate a proper voltage and current. This patch refactors the TCPC driver with this new function and also keep DFP mode support for USB host. Signed-off-by: Ye Li Acked-by: Jun Li --- board/freescale/common/Kconfig | 6 + board/freescale/common/Makefile | 4 +- board/freescale/common/tcpc.c | 733 +++++++++++++++++++++++++++++--- board/freescale/common/tcpc.h | 454 +++++++++++++++++--- 4 files changed, 1082 insertions(+), 115 deletions(-) diff --git a/board/freescale/common/Kconfig b/board/freescale/common/Kconfig index 8b89c10aba6c..4982ccb72fab 100644 --- a/board/freescale/common/Kconfig +++ b/board/freescale/common/Kconfig @@ -21,6 +21,12 @@ config CMD_ESBC_VALIDATE esbc_validate - validate signature using RSA verification esbc_halt - put the core in spin loop (Secure Boot Only) +config USB_TCPC + bool "USB Typec port controller simple driver" + default n + help + Enable USB type-c port controller (TCPC) driver + config VOL_MONITOR_LTC3882_READ depends on VID bool "Enable the LTC3882 voltage monitor read" diff --git a/board/freescale/common/Makefile b/board/freescale/common/Makefile index cfd2dd3ef204..e77c035f48d2 100644 --- a/board/freescale/common/Makefile +++ b/board/freescale/common/Makefile @@ -78,5 +78,7 @@ obj-$(CONFIG_CMD_ESBC_VALIDATE) += fsl_validate.o cmd_esbc_validate.o endif obj-$(CONFIG_CHAIN_OF_TRUST) += fsl_chain_of_trust.o -obj-$(CONFIG_USB_XHCI_IMX8) += tcpc.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_USB_TCPC) += tcpc.o +endif endif diff --git a/board/freescale/common/tcpc.c b/board/freescale/common/tcpc.c index 5931cb1f1193..2982ded75f35 100644 --- a/board/freescale/common/tcpc.c +++ b/board/freescale/common/tcpc.c @@ -8,30 +8,57 @@ #include #include "tcpc.h" -int tcpc_set_cc_to_source(struct udevice *i2c_dev) +#ifdef DEBUG +#define tcpc_debug_log(port, fmt, args...) tcpc_log(port, fmt, ##args) +#else +#define tcpc_debug_log(port, fmt, args...) +#endif + +static int tcpc_log(struct tcpc_port *port, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i = vscnprintf(port->log_p, port->log_size, fmt, args); + va_end(args); + + port->log_size -= i; + port->log_p += i; + + return i; +} + +int tcpc_set_cc_to_source(struct tcpc_port *port) { uint8_t valb; int err; + if (port == NULL) + return -EINVAL; + valb = (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC1_SHIFT) | (TCPC_ROLE_CTRL_CC_RP << TCPC_ROLE_CTRL_CC2_SHIFT) | (TCPC_ROLE_CTRL_RP_VAL_DEF << TCPC_ROLE_CTRL_RP_VAL_SHIFT); - err = dm_i2c_write(i2c_dev, TCPC_ROLE_CTRL, &valb, 1); + err = dm_i2c_write(port->i2c_dev, TCPC_ROLE_CTRL, &valb, 1); if (err) - printf("%s dm_i2c_write failed, err %d\n", __func__, err); + tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err); return err; } -int tcpc_set_plug_orientation(struct udevice *i2c_dev, enum typec_cc_polarity polarity) +int tcpc_set_plug_orientation(struct tcpc_port *port, enum typec_cc_polarity polarity) { uint8_t valb; int err; - err = dm_i2c_read(i2c_dev, TCPC_TCPC_CTRL, &valb, 1); + if (port == NULL) + return -EINVAL; + + err = dm_i2c_read(port->i2c_dev, TCPC_TCPC_CTRL, &valb, 1); if (err) { - printf("%s dm_i2c_read failed, err %d\n", __func__, err); + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); return -EIO; } @@ -40,74 +67,179 @@ int tcpc_set_plug_orientation(struct udevice *i2c_dev, enum typec_cc_polarity po else valb &= ~TCPC_TCPC_CTRL_ORIENTATION; - err = dm_i2c_write(i2c_dev, TCPC_TCPC_CTRL, &valb, 1); + err = dm_i2c_write(port->i2c_dev, TCPC_TCPC_CTRL, &valb, 1); if (err) { - printf("%s dm_i2c_write failed, err %d\n", __func__, err); + tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err); return -EIO; } return 0; } -int tcpc_get_cc_polarity(struct udevice *i2c_dev, enum typec_cc_polarity *polarity) +int tcpc_get_cc_status(struct tcpc_port *port, enum typec_cc_polarity *polarity, enum typec_cc_state *state) { - uint8_t valb; + uint8_t valb_cc, cc2, cc1; int err; - err = dm_i2c_read(i2c_dev, TCPC_CC_STATUS, &valb, 1); + if (port == NULL || polarity == NULL || state == NULL) + return -EINVAL; + + err = dm_i2c_read(port->i2c_dev, TCPC_CC_STATUS, (uint8_t *)&valb_cc, 1); if (err) { - printf("%s dm_i2c_read failed, err %d\n", __func__, err); + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); return -EIO; } - debug("cc status 0x%x\n", valb); + tcpc_debug_log(port, "cc status 0x%x\n", valb_cc); - /* Set to Rp at default */ - if (valb & TCPC_CC_STATUS_TERM) - return -EPERM; + cc2 = (valb_cc >> TCPC_CC_STATUS_CC2_SHIFT) & TCPC_CC_STATUS_CC2_MASK; + cc1 = (valb_cc >> TCPC_CC_STATUS_CC1_SHIFT) & TCPC_CC_STATUS_CC1_MASK; - if (((valb >> TCPC_CC_STATUS_CC1_SHIFT) & TCPC_CC_STATUS_CC1_MASK) == 0x2) - *polarity = TYPEC_POLARITY_CC1; - else if (((valb >> TCPC_CC_STATUS_CC2_SHIFT) & TCPC_CC_STATUS_CC2_MASK) == 0x2) - *polarity = TYPEC_POLARITY_CC2; - else + if (valb_cc & TCPC_CC_STATUS_LOOK4CONN) return -EFAULT; + + *state = TYPEC_STATE_OPEN; + + if (valb_cc & TCPC_CC_STATUS_TERM) { + if (cc2) { + *polarity = TYPEC_POLARITY_CC2; + + switch (cc2) { + case 0x1: + *state = TYPEC_STATE_SNK_DEFAULT; + tcpc_log(port, "SNK.Default on CC2\n"); + break; + case 0x2: + *state = TYPEC_STATE_SNK_POWER15; + tcpc_log(port, "SNK.Power1.5 on CC2\n"); + break; + case 0x3: + *state = TYPEC_STATE_SNK_POWER30; + tcpc_log(port, "SNK.Power3.0 on CC2\n"); + break; + } + } else if (cc1) { + *polarity = TYPEC_POLARITY_CC1; + + switch (cc1) { + case 0x1: + *state = TYPEC_STATE_SNK_DEFAULT; + tcpc_log(port, "SNK.Default on CC1\n"); + break; + case 0x2: + *state = TYPEC_STATE_SNK_POWER15; + tcpc_log(port, "SNK.Power1.5 on CC1\n"); + break; + case 0x3: + *state = TYPEC_STATE_SNK_POWER30; + tcpc_log(port, "SNK.Power3.0 on CC1\n"); + break; + } + } else { + *state = TYPEC_STATE_OPEN; + return -EPERM; + } + + } else { + if (cc2) { + *polarity = TYPEC_POLARITY_CC2; + + switch (cc2) { + case 0x1: + if (cc1 == 0x1) { + *state = TYPEC_STATE_SRC_BOTH_RA; + tcpc_log(port, "SRC.Ra on both CC1 and CC2\n"); + } else if (cc1 == 0x2) { + *state = TYPEC_STATE_SRC_RD_RA; + tcpc_log(port, "SRC.Ra on CC2, SRC.Rd on CC1\n"); + } else if (cc1 == 0x0) { + tcpc_log(port, "SRC.Ra only on CC2\n"); + return -EFAULT; + } else + return -EFAULT; + break; + case 0x2: + if (cc1 == 0x1) { + *state = TYPEC_STATE_SRC_RD_RA; + tcpc_log(port, "SRC.Ra on CC1, SRC.Rd on CC2\n"); + } else if (cc1 == 0x0) { + *state = TYPEC_STATE_SRC_RD; + tcpc_log(port, "SRC.Rd on CC2\n"); + } else + return -EFAULT; + break; + case 0x3: + *state = TYPEC_STATE_SRC_RESERVED; + return -EFAULT; + } + } else if (cc1) { + *polarity = TYPEC_POLARITY_CC1; + + switch (cc1) { + case 0x1: + tcpc_log(port, "SRC.Ra only on CC1\n"); + return -EFAULT; + case 0x2: + *state = TYPEC_STATE_SRC_RD; + tcpc_log(port, "SRC.Rd on CC1\n"); + break; + case 0x3: + *state = TYPEC_STATE_SRC_RESERVED; + return -EFAULT; + } + } else { + *state = TYPEC_STATE_OPEN; + return -EPERM; + } + } + return 0; } -int tcpc_clear_alert(struct udevice *i2c_dev, uint16_t clear_mask) +int tcpc_clear_alert(struct tcpc_port *port, uint16_t clear_mask) { int err; - err = dm_i2c_write(i2c_dev, TCPC_ALERT, (const uint8_t *)&clear_mask, 2); + + if (port == NULL) + return -EINVAL; + + err = dm_i2c_write(port->i2c_dev, TCPC_ALERT, (const uint8_t *)&clear_mask, 2); if (err) { - printf("%s dm_i2c_write failed, err %d\n", __func__, err); + tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err); return -EIO; } return 0; } -int tcpc_send_command(struct udevice *i2c_dev, uint8_t command) +int tcpc_send_command(struct tcpc_port *port, uint8_t command) { int err; - err = dm_i2c_write(i2c_dev, TCPC_COMMAND, (const uint8_t *)&command, 1); + + if (port == NULL) + return -EINVAL; + + err = dm_i2c_write(port->i2c_dev, TCPC_COMMAND, (const uint8_t *)&command, 1); if (err) { - printf("%s dm_i2c_write failed, err %d\n", __func__, err); + tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err); return -EIO; } return 0; } -int tcpc_polling_reg(struct udevice *i2c_dev, uint8_t reg, +int tcpc_polling_reg(struct tcpc_port *port, uint8_t reg, uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms) { uint16_t val = 0; int err; ulong start; - debug("%s reg 0x%x, mask 0x%x, value 0x%x\n", __func__, reg, mask, value); + if (port == NULL) + return -EINVAL; + + tcpc_debug_log(port, "%s reg 0x%x, mask 0x%x, value 0x%x\n", __func__, reg, mask, value); /* TCPC registers is 8 bits or 16 bits */ if (reg_width != 1 && reg_width != 2) @@ -115,12 +247,10 @@ int tcpc_polling_reg(struct udevice *i2c_dev, uint8_t reg, start = get_timer(0); /* Get current timestamp */ do { - err = dm_i2c_read(i2c_dev, reg, (uint8_t *)&val, reg_width); + err = dm_i2c_read(port->i2c_dev, reg, (uint8_t *)&val, reg_width); if (err) return -EIO; - debug("val = 0x%x\n", val); - if ((val & mask) == value) return 0; } while (get_timer(0) < (start + timeout_ms)); @@ -128,31 +258,31 @@ int tcpc_polling_reg(struct udevice *i2c_dev, uint8_t reg, return -ETIME; } -int tcpc_init(struct udevice *i2c_dev) +void tcpc_print_log(struct tcpc_port *port) { - int ret; + if (port == NULL) + return; - /* Check the Initialization Status bit in 1s */ - ret = tcpc_polling_reg(i2c_dev, TCPC_POWER_STATUS, 1, TCPC_POWER_STATUS_UNINIT, 0, 1000); - if (ret) { - printf("%s: Polling TCPC POWER STATUS Initialization Status bit failed, ret = %d\n", - __func__, ret); - return ret; - } + if (port->log_print == port->log_p) /*nothing to output*/ + return; - tcpc_clear_alert(i2c_dev, 0xffff); + printf("%s", port->log_print); - return 0; + port->log_print = port->log_p; } -int tcpc_setup_dfp_mode(struct udevice *i2c_dev, ss_mux_sel ss_sel_func) +int tcpc_setup_dfp_mode(struct tcpc_port *port) { enum typec_cc_polarity pol; + enum typec_cc_state state; int ret; - tcpc_set_cc_to_source(i2c_dev); + if (port == NULL) + return -EINVAL; + + tcpc_set_cc_to_source(port); - ret = tcpc_send_command(i2c_dev, TCPC_CMD_LOOK4CONNECTION); + ret = tcpc_send_command(port, TCPC_CMD_LOOK4CONNECTION); if (ret) return ret; @@ -162,36 +292,35 @@ int tcpc_setup_dfp_mode(struct udevice *i2c_dev, ss_mux_sel ss_sel_func) */ mdelay(100); - ret = tcpc_polling_reg(i2c_dev, TCPC_ALERT, 2, TCPC_ALERT_CC_STATUS, TCPC_ALERT_CC_STATUS, 100); + ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_CC_STATUS, TCPC_ALERT_CC_STATUS, 100); if (ret) { - printf("%s: Polling ALERT register, TCPC_ALERT_CC_STATUS bit failed, ret = %d\n", + tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_CC_STATUS bit failed, ret = %d\n", __func__, ret); return ret; } - ret = tcpc_get_cc_polarity(i2c_dev, &pol); - tcpc_clear_alert(i2c_dev, TCPC_ALERT_CC_STATUS); + ret = tcpc_get_cc_status(port, &pol, &state); + tcpc_clear_alert(port, TCPC_ALERT_CC_STATUS); if (!ret) { + /* If presenting as Rd/audio mode/open, return */ + if (state != TYPEC_STATE_SRC_RD_RA && state != TYPEC_STATE_SRC_RD) + return -EPERM; + if (pol == TYPEC_POLARITY_CC1) - debug("polarity cc1\n"); + tcpc_debug_log(port, "polarity cc1\n"); else - debug("polarity cc2\n"); - - if (ss_sel_func) - ss_sel_func(pol); + tcpc_debug_log(port, "polarity cc2\n"); - ret = tcpc_set_plug_orientation(i2c_dev, pol); - if (ret) - return ret; + if (port->ss_sel_func) + port->ss_sel_func(pol); - /* Disable sink vbus */ - ret = tcpc_send_command(i2c_dev, TCPC_CMD_DISABLE_SINK_VBUS); + ret = tcpc_set_plug_orientation(port, pol); if (ret) return ret; /* Enable source vbus default voltage */ - ret = tcpc_send_command(i2c_dev, TCPC_CMD_SRC_VBUS_DEFAULT); + ret = tcpc_send_command(port, TCPC_CMD_SRC_VBUS_DEFAULT); if (ret) return ret; @@ -203,21 +332,493 @@ int tcpc_setup_dfp_mode(struct udevice *i2c_dev, ss_mux_sel ss_sel_func) return 0; } -int tcpc_disable_vbus(struct udevice *i2c_dev) +int tcpc_disable_src_vbus(struct tcpc_port *port) { int ret; + if (port == NULL) + return -EINVAL; + /* Disable VBUS*/ - ret = tcpc_send_command(i2c_dev, TCPC_CMD_DISABLE_SINK_VBUS); + ret = tcpc_send_command(port, TCPC_CMD_DISABLE_SRC_VBUS); if (ret) return ret; - ret = tcpc_send_command(i2c_dev, TCPC_CMD_DISABLE_SRC_VBUS); + /* The max vbus off time is 0.5ms, we add margin 0.5 ms */ + mdelay(1); + + return 0; +} + +static int tcpc_pd_receive_message(struct tcpc_port *port, struct pd_message *msg) +{ + int ret; + uint8_t cnt; + uint16_t val; + + if (port == NULL) + return -EINVAL; + + /* Generally the max tSenderResponse is 30ms, max tTypeCSendSourceCap is 200ms, we set the timeout to 500ms */ + ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_RX_STATUS, TCPC_ALERT_RX_STATUS, 500); + if (ret) { + tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_RX_STATUS bit failed, ret = %d\n", + __func__, ret); + return ret; + } + + cnt = 0; + ret = dm_i2c_read(port->i2c_dev, TCPC_RX_BYTE_CNT, (uint8_t *)&cnt, 1); if (ret) + return -EIO; + + if (cnt > 0) { + ret = dm_i2c_read(port->i2c_dev, TCPC_RX_BUF_FRAME_TYPE, (uint8_t *)msg, cnt); + if (ret) + return -EIO; + + /* Clear RX status alert bit */ + val = TCPC_ALERT_RX_STATUS; + ret = dm_i2c_write(port->i2c_dev, TCPC_ALERT, (const uint8_t *)&val, 2); + if (ret) + return -EIO; + } + + return cnt; +} + +static int tcpc_pd_transmit_message(struct tcpc_port *port, struct pd_message *msg_p, uint8_t bytes) +{ + int ret; + uint8_t valb; + uint16_t val; + + if (port == NULL) + return -EINVAL; + + if (msg_p == NULL || bytes <= 0) + return -EINVAL; + + ret = dm_i2c_write(port->i2c_dev, TCPC_TX_BYTE_CNT, (const uint8_t *)&bytes, 1); + if (ret) + return -EIO; + + ret = dm_i2c_write(port->i2c_dev, TCPC_TX_HDR, (const uint8_t *)&(msg_p->header), bytes); + if (ret) + return -EIO; + + valb = (3 << TCPC_TRANSMIT_RETRY_SHIFT) | (TCPC_TX_SOP << TCPC_TRANSMIT_TYPE_SHIFT); + ret = dm_i2c_write(port->i2c_dev, TCPC_TRANSMIT, (const uint8_t *)&valb, 1); + if (ret) + return -EIO; + + /* Max tReceive is 1.1ms, we set to 5ms timeout */ + ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_TX_SUCCESS, TCPC_ALERT_TX_SUCCESS, 5); + if (ret) { + if (ret == -ETIME) { + ret = dm_i2c_read(port->i2c_dev, TCPC_ALERT, (uint8_t *)&val, 2); + if (ret) + return -EIO; + + if (val & TCPC_ALERT_TX_FAILED) + tcpc_log(port, "%s: PD TX FAILED, ALERT = 0x%x\n", __func__, val); + + if (val & TCPC_ALERT_TX_DISCARDED) + tcpc_log(port, "%s: PD TX DISCARDED, ALERT = 0x%x\n", __func__, val); + + } else { + tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_TX_SUCCESS bit failed, ret = %d\n", + __func__, ret); + } + } else { + port->tx_msg_id = (port->tx_msg_id + 1) & PD_HEADER_ID_MASK; + } + + /* Clear ALERT status */ + val &= (TCPC_ALERT_TX_FAILED | TCPC_ALERT_TX_DISCARDED | TCPC_ALERT_TX_SUCCESS); + ret = dm_i2c_write(port->i2c_dev, TCPC_ALERT, (const uint8_t *)&val, 2); + if (ret) + return -EIO; + + return ret; +} + +static void tcpc_log_source_caps(struct tcpc_port *port, uint32_t *caps, unsigned int capcount) +{ + int i; + + for (i = 0; i < capcount; i++) { + u32 pdo = caps[i]; + enum pd_pdo_type type = pdo_type(pdo); + + tcpc_log(port, "PDO %d: type %d, ", + i, type); + + switch (type) { + case PDO_TYPE_FIXED: + tcpc_log(port, "%u mV, %u mA [%s%s%s%s%s%s]\n", + pdo_fixed_voltage(pdo), + pdo_max_current(pdo), + (pdo & PDO_FIXED_DUAL_ROLE) ? + "R" : "", + (pdo & PDO_FIXED_SUSPEND) ? + "S" : "", + (pdo & PDO_FIXED_HIGHER_CAP) ? + "H" : "", + (pdo & PDO_FIXED_USB_COMM) ? + "U" : "", + (pdo & PDO_FIXED_DATA_SWAP) ? + "D" : "", + (pdo & PDO_FIXED_EXTPOWER) ? + "E" : ""); + break; + case PDO_TYPE_VAR: + tcpc_log(port, "%u-%u mV, %u mA\n", + pdo_min_voltage(pdo), + pdo_max_voltage(pdo), + pdo_max_current(pdo)); + break; + case PDO_TYPE_BATT: + tcpc_log(port, "%u-%u mV, %u mW\n", + pdo_min_voltage(pdo), + pdo_max_voltage(pdo), + pdo_max_power(pdo)); + break; + default: + tcpc_log(port, "undefined\n"); + break; + } + } +} + +static int tcpc_pd_select_pdo(uint32_t *caps, uint32_t capcount, uint32_t max_snk_mv, uint32_t max_snk_ma) +{ + unsigned int i, max_mw = 0, max_mv = 0; + int ret = -EINVAL; + + /* + * Select the source PDO providing the most power while staying within + * the board's voltage limits. Prefer PDO providing exp + */ + for (i = 0; i < capcount; i++) { + u32 pdo = caps[i]; + enum pd_pdo_type type = pdo_type(pdo); + unsigned int mv, ma, mw; + + if (type == PDO_TYPE_FIXED) + mv = pdo_fixed_voltage(pdo); + else + mv = pdo_min_voltage(pdo); + + if (type == PDO_TYPE_BATT) { + mw = pdo_max_power(pdo); + } else { + ma = min(pdo_max_current(pdo), + max_snk_ma); + mw = ma * mv / 1000; + } + + /* Perfer higher voltages if available */ + if ((mw > max_mw || (mw == max_mw && mv > max_mv)) && + mv <= max_snk_mv) { + ret = i; + max_mw = mw; + max_mv = mv; + } + } + + return ret; +} + +static int tcpc_pd_build_request(struct tcpc_port *port, + uint32_t *caps, + uint32_t capcount, + uint32_t max_snk_mv, + uint32_t max_snk_ma, + uint32_t max_snk_mw, + uint32_t operating_snk_mw, + uint32_t *rdo) +{ + unsigned int mv, ma, mw, flags; + unsigned int max_ma, max_mw; + enum pd_pdo_type type; + int index; + u32 pdo; + + index = tcpc_pd_select_pdo(caps, capcount, max_snk_mv, max_snk_ma); + if (index < 0) + return -EINVAL; + + pdo = caps[index]; + type = pdo_type(pdo); + + if (type == PDO_TYPE_FIXED) + mv = pdo_fixed_voltage(pdo); + else + mv = pdo_min_voltage(pdo); + + /* Select maximum available current within the board's power limit */ + if (type == PDO_TYPE_BATT) { + mw = pdo_max_power(pdo); + ma = 1000 * min(mw, max_snk_mw) / mv; + } else { + ma = min(pdo_max_current(pdo), + 1000 * max_snk_mw / mv); + } + ma = min(ma, max_snk_ma); + + /* XXX: Any other flags need to be set? */ + flags = 0; + + /* Set mismatch bit if offered power is less than operating power */ + mw = ma * mv / 1000; + max_ma = ma; + max_mw = mw; + if (mw < operating_snk_mw) { + flags |= RDO_CAP_MISMATCH; + max_mw = operating_snk_mw; + max_ma = max_mw * 1000 / mv; + } + + if (type == PDO_TYPE_BATT) { + *rdo = RDO_BATT(index + 1, mw, max_mw, flags); + + tcpc_log(port, "Requesting PDO %d: %u mV, %u mW%s\n", + index, mv, mw, + flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); + } else { + *rdo = RDO_FIXED(index + 1, ma, max_ma, flags); + + tcpc_log(port, "Requesting PDO %d: %u mV, %u mA%s\n", + index, mv, ma, + flags & RDO_CAP_MISMATCH ? " [mismatch]" : ""); + } + + return 0; +} + +static void tcpc_pd_sink_process(struct tcpc_port *port) +{ + int ret; + uint8_t msgtype; + uint32_t objcnt; + struct pd_message msg; + enum pd_sink_state pd_state = WAIT_SOURCE_CAP; + + while (tcpc_pd_receive_message(port, &msg) > 0) { + + msgtype = pd_header_type(msg.header); + objcnt = pd_header_cnt_le(msg.header); + + tcpc_debug_log(port, "get msg, type %d, cnt %d\n", msgtype, objcnt); + + switch (pd_state) { + case WAIT_SOURCE_CAP: + if (msgtype != PD_DATA_SOURCE_CAP) + continue; + + uint32_t *caps = (uint32_t *)&msg.payload; + uint32_t rdo = 0; + + tcpc_log_source_caps(port, caps, objcnt); + + tcpc_pd_build_request(port, caps, objcnt, + port->cfg.max_snk_mv, port->cfg.max_snk_ma, + port->cfg.max_snk_mw, port->cfg.op_snk_mv, + &rdo); + + memset(&msg, 0, sizeof(msg)); + msg.header = PD_HEADER(PD_DATA_REQUEST, 0, 0, port->tx_msg_id, 1); /* power sink, data device, id 0, len 1 */ + msg.payload[0] = rdo; + + ret = tcpc_pd_transmit_message(port, &msg, 6); + if (ret) + tcpc_log(port, "send request failed\n"); + else + pd_state = WAIT_SOURCE_ACCEPT; + + break; + case WAIT_SOURCE_ACCEPT: + if (objcnt > 0) /* Should be ctrl message */ + continue; + + if (msgtype == PD_CTRL_ACCEPT) { + pd_state = WAIT_SOURCE_READY; + tcpc_log(port, "Source accept request\n"); + } else if (msgtype == PD_CTRL_REJECT) { + tcpc_log(port, "Source reject request\n"); + return; + } + + break; + case WAIT_SOURCE_READY: + if (objcnt > 0) /* Should be ctrl message */ + continue; + + if (msgtype == PD_CTRL_PS_RDY) { + tcpc_log(port, "PD source ready! \n"); + pd_state = SINK_READY; + return; + } + + break; + default: + tcpc_log(port, "unexpect status: %u\n", pd_state); + break; + } + } +} + +static int tcpc_pd_sink_init(struct tcpc_port *port) +{ + uint8_t valb; + uint16_t val; + int err; + enum typec_cc_polarity pol; + enum typec_cc_state state; + + if (port == NULL) + return -EINVAL; + + port->pd_state = UNATTACH; + + /* Check the VBUS PRES and SINK VBUS for dead battery */ + err = dm_i2c_read(port->i2c_dev, TCPC_POWER_STATUS, &valb, 1); + if (err) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); + return -EIO; + } + + if (!(valb & TCPC_POWER_STATUS_VBUS_PRES)) { + tcpc_debug_log(port, "VBUS NOT PRES \n"); + return -EPERM; + } + + if (!(valb & TCPC_POWER_STATUS_SINKING_VBUS)) { + tcpc_debug_log(port, "SINK VBUS is not enabled for dead battery\n"); + return -EPERM; + } + + err = dm_i2c_read(port->i2c_dev, TCPC_ALERT, (uint8_t *)&val, 2); + if (err) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); + return -EIO; + } + + if (!(val & TCPC_ALERT_CC_STATUS)) { + tcpc_debug_log(port, "CC STATUS not detected for dead battery\n"); + return -EPERM; + } + + err = tcpc_get_cc_status(port, &pol, &state); + if (err || (state != TYPEC_STATE_SNK_POWER15 + && state != TYPEC_STATE_SNK_POWER30 + && state != TYPEC_STATE_SNK_DEFAULT)) { + tcpc_log(port, "TCPC wrong state for dead battery, err = %d, CC = 0x%x\n", + err, state); + return -EPERM; + } else + port->pd_state = ATTACHED; + + dm_i2c_read(port->i2c_dev, TCPC_POWER_CTRL, (uint8_t *)&valb, 1); + valb &= ~TCPC_POWER_CTRL_AUTO_DISCH_DISCO; /* disable AutoDischargeDisconnect */ + dm_i2c_write(port->i2c_dev, TCPC_POWER_CTRL, (const uint8_t *)&valb, 1); + + /* As sink role */ + valb = 0x00; + err = dm_i2c_write(port->i2c_dev, TCPC_MSG_HDR_INFO, (const uint8_t *)&valb, 1); + if (err) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); + return -EIO; + } + + /* Enable rx */ + valb = TCPC_RX_DETECT_SOP | TCPC_RX_DETECT_HARD_RESET; + err = dm_i2c_write(port->i2c_dev, TCPC_RX_DETECT, (const uint8_t *)&valb, 1); + if (err) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); + return -EIO; + } + + tcpc_pd_sink_process(port); + + return 0; +} + +int tcpc_init(struct tcpc_port *port, struct tcpc_port_config config, ss_mux_sel ss_sel_func) +{ + int ret; + uint8_t valb; + uint16_t vid, pid; + struct udevice *bus; + struct udevice *i2c_dev = NULL; + + memset(port, 0, sizeof(struct tcpc_port)); + + if (port == NULL) + return -EINVAL; + + port->cfg = config; + port->tx_msg_id = 0; + port->ss_sel_func = ss_sel_func; + port->log_p = (char *)&(port->logbuffer); + port->log_size = TCPC_LOG_BUFFER_SIZE; + port->log_print = port->log_p; + memset(&(port->logbuffer), 0, TCPC_LOG_BUFFER_SIZE); + + ret = uclass_get_device_by_seq(UCLASS_I2C, port->cfg.i2c_bus, &bus); + if (ret) { + printf("%s: Can't find bus\n", __func__); + return -EINVAL; + } + + ret = dm_i2c_probe(bus, port->cfg.addr, 0, &i2c_dev); + if (ret) { + printf("%s: Can't find device id=0x%x\n", + __func__, config.addr); + return -ENODEV; + } + + port->i2c_dev = i2c_dev; + + /* Check the Initialization Status bit in 1s */ + ret = tcpc_polling_reg(port, TCPC_POWER_STATUS, 1, TCPC_POWER_STATUS_UNINIT, 0, 1000); + if (ret) { + tcpc_log(port, "%s: Polling TCPC POWER STATUS Initialization Status bit failed, ret = %d\n", + __func__, ret); return ret; + } - /* The max vbus off time is 0.5ms, we add margin 0.5 ms */ - mdelay(1); + /* Clear AllRegistersResetToDefault */ + valb = 0x80; + ret = dm_i2c_write(port->i2c_dev, TCPC_FAULT_STATUS, (const uint8_t *)&valb, 1); + if (ret) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, ret); + return -EIO; + } + + /* Read Vendor ID and Product ID */ + ret = dm_i2c_read(port->i2c_dev, TCPC_VENDOR_ID, (uint8_t *)&vid, 2); + if (ret) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, ret); + return -EIO; + } + + ret = dm_i2c_read(port->i2c_dev, TCPC_PRODUCT_ID, (uint8_t *)&pid, 2); + if (ret) { + tcpc_log(port, "%s dm_i2c_read failed, err %d\n", __func__, ret); + return -EIO; + } + + tcpc_log(port, "TCPC: Vendor ID [0x%x], Product ID [0x%x]\n", vid, pid); + + if (port->cfg.port_type == TYPEC_PORT_UFP + || port->cfg.port_type == TYPEC_PORT_DRP) + tcpc_pd_sink_init(port); + + tcpc_clear_alert(port, 0xffff); + + tcpc_print_log(port); return 0; } diff --git a/board/freescale/common/tcpc.h b/board/freescale/common/tcpc.h index ad981d182042..c3bb9af64376 100644 --- a/board/freescale/common/tcpc.h +++ b/board/freescale/common/tcpc.h @@ -9,18 +9,29 @@ #include -#define TCPC_TCPC_CTRL 0x19 -#define TCPC_TCPC_CTRL_ORIENTATION BIT(0) +#define TCPC_VENDOR_ID 0x0 +#define TCPC_PRODUCT_ID 0x2 + +#define TCPC_ALERT 0x10 +#define TCPC_ALERT_VBUS_DISCNCT BIT(11) +#define TCPC_ALERT_RX_BUF_OVF BIT(10) +#define TCPC_ALERT_FAULT BIT(9) +#define TCPC_ALERT_V_ALARM_LO BIT(8) +#define TCPC_ALERT_V_ALARM_HI BIT(7) +#define TCPC_ALERT_TX_SUCCESS BIT(6) +#define TCPC_ALERT_TX_DISCARDED BIT(5) +#define TCPC_ALERT_TX_FAILED BIT(4) +#define TCPC_ALERT_RX_HARD_RST BIT(3) +#define TCPC_ALERT_RX_STATUS BIT(2) +#define TCPC_ALERT_POWER_STATUS BIT(1) +#define TCPC_ALERT_CC_STATUS BIT(0) -#define TCPC_CC_STATUS 0x1d -#define TCPC_CC_STATUS_TERM BIT(4) -#define TCPC_CC_STATUS_CC2_SHIFT 2 -#define TCPC_CC_STATUS_CC2_MASK 0x3 -#define TCPC_CC_STATUS_CC1_SHIFT 0 -#define TCPC_CC_STATUS_CC1_MASK 0x3 +#define TCPC_TCPC_CTRL 0x19 +#define TCPC_TCPC_CTRL_BIST_MODE BIT(1) +#define TCPC_TCPC_CTRL_ORIENTATION BIT(0) -#define TCPC_ROLE_CTRL 0x1a -#define TCPC_ROLE_CTRL_DRP BIT(6) +#define TCPC_ROLE_CTRL 0x1a +#define TCPC_ROLE_CTRL_DRP BIT(6) #define TCPC_ROLE_CTRL_RP_VAL_SHIFT 4 #define TCPC_ROLE_CTRL_RP_VAL_MASK 0x3 #define TCPC_ROLE_CTRL_RP_VAL_DEF 0x0 @@ -35,54 +46,401 @@ #define TCPC_ROLE_CTRL_CC_RD 0x2 #define TCPC_ROLE_CTRL_CC_OPEN 0x3 -#define TCPC_COMMAND 0x23 -#define TCPC_CMD_WAKE_I2C 0x11 +#define TCPC_POWER_CTRL 0x1c +#define TCPC_POWER_CTRL_EN_VCONN BIT(0) +#define TCPC_POWER_CTRL_VCONN_POWER BIT(1) +#define TCPC_POWER_CTRL_FORCE_DISCH BIT(2) +#define TCPC_POWER_CTRL_EN_BLEED_CH BIT(3) +#define TCPC_POWER_CTRL_AUTO_DISCH_DISCO BIT(4) +#define TCPC_POWER_CTRL_DIS_V_ALARMS BIT(5) +#define TCPC_POWER_CTRL_VBUS_V_MONITOR BIT(6) + +#define TCPC_CC_STATUS 0x1d +#define TCPC_CC_STATUS_LOOK4CONN BIT(5) +#define TCPC_CC_STATUS_TERM BIT(4) +#define TCPC_CC_STATUS_CC2_SHIFT 2 +#define TCPC_CC_STATUS_CC2_MASK 0x3 +#define TCPC_CC_STATUS_CC1_SHIFT 0 +#define TCPC_CC_STATUS_CC1_MASK 0x3 + +#define TCPC_POWER_STATUS 0x1e +#define TCPC_POWER_STATUS_UNINIT BIT(6) +#define TCPC_POWER_STATUS_VBUS_DET BIT(3) +#define TCPC_POWER_STATUS_VBUS_PRES BIT(2) +#define TCPC_POWER_STATUS_SINKING_VBUS BIT(0) + +#define TCPC_FAULT_STATUS 0x1f + +#define TCPC_COMMAND 0x23 +#define TCPC_CMD_WAKE_I2C 0x11 #define TCPC_CMD_DISABLE_VBUS_DETECT 0x22 -#define TCPC_CMD_ENABLE_VBUS_DETECT 0x33 -#define TCPC_CMD_DISABLE_SINK_VBUS 0x44 -#define TCPC_CMD_SINK_VBUS 0x55 -#define TCPC_CMD_DISABLE_SRC_VBUS 0x66 -#define TCPC_CMD_SRC_VBUS_DEFAULT 0x77 -#define TCPC_CMD_SRC_VBUS_HIGH 0x88 -#define TCPC_CMD_LOOK4CONNECTION 0x99 -#define TCPC_CMD_RXONEMORE 0xAA -#define TCPC_CMD_I2C_IDLE 0xFF - -#define TCPC_ALERT 0x10 -#define TCPC_ALERT_VBUS_DISCNCT BIT(11) -#define TCPC_ALERT_RX_BUF_OVF BIT(10) -#define TCPC_ALERT_FAULT BIT(9) -#define TCPC_ALERT_V_ALARM_LO BIT(8) -#define TCPC_ALERT_V_ALARM_HI BIT(7) -#define TCPC_ALERT_TX_SUCCESS BIT(6) -#define TCPC_ALERT_TX_DISCARDED BIT(5) -#define TCPC_ALERT_TX_FAILED BIT(4) -#define TCPC_ALERT_RX_HARD_RST BIT(3) -#define TCPC_ALERT_RX_STATUS BIT(2) -#define TCPC_ALERT_POWER_STATUS BIT(1) -#define TCPC_ALERT_CC_STATUS BIT(0) +#define TCPC_CMD_ENABLE_VBUS_DETECT 0x33 +#define TCPC_CMD_DISABLE_SINK_VBUS 0x44 +#define TCPC_CMD_SINK_VBUS 0x55 +#define TCPC_CMD_DISABLE_SRC_VBUS 0x66 +#define TCPC_CMD_SRC_VBUS_DEFAULT 0x77 +#define TCPC_CMD_SRC_VBUS_HIGH 0x88 +#define TCPC_CMD_LOOK4CONNECTION 0x99 +#define TCPC_CMD_RXONEMORE 0xAA +#define TCPC_CMD_I2C_IDLE 0xFF + +#define TCPC_DEV_CAP_1 0x24 +#define TCPC_DEV_CAP_2 0x26 +#define TCPC_STD_INPUT_CAP 0x28 +#define TCPC_STD_OUTPUT_CAP 0x29 + +#define TCPC_MSG_HDR_INFO 0x2e +#define TCPC_MSG_HDR_INFO_DATA_ROLE BIT(3) +#define TCPC_MSG_HDR_INFO_PWR_ROLE BIT(0) +#define TCPC_MSG_HDR_INFO_REV_SHIFT 1 +#define TCPC_MSG_HDR_INFO_REV_MASK 0x3 + +#define TCPC_RX_DETECT 0x2f +#define TCPC_RX_DETECT_HARD_RESET BIT(5) +#define TCPC_RX_DETECT_SOP BIT(0) + +#define TCPC_RX_BYTE_CNT 0x30 +#define TCPC_RX_BUF_FRAME_TYPE 0x31 +#define TCPC_RX_HDR 0x32 +#define TCPC_RX_DATA 0x34 /* through 0x4f */ + +#define TCPC_TRANSMIT 0x50 +#define TCPC_TRANSMIT_RETRY_SHIFT 4 +#define TCPC_TRANSMIT_RETRY_MASK 0x3 +#define TCPC_TRANSMIT_TYPE_SHIFT 0 +#define TCPC_TRANSMIT_TYPE_MASK 0x7 + +#define TCPC_TX_BYTE_CNT 0x51 +#define TCPC_TX_HDR 0x52 +#define TCPC_TX_DATA 0x54 /* through 0x6f */ + +#define TCPC_VBUS_VOLTAGE 0x70 +#define TCPC_VBUS_VOL_MASK 0x3ff +#define TCPC_VBUS_VOL_SCALE_FACTOR_MASK 0xc00 +#define TCPC_VBUS_VOL_SCALE_FACTOR_SHIFT 10 +#define TCPC_VBUS_VOL_MV_UNIT 25 + +#define TCPC_VBUS_SINK_DISCONNECT_THRESH 0x72 +#define TCPC_VBUS_STOP_DISCHARGE_THRESH 0x74 +#define TCPC_VBUS_VOLTAGE_ALARM_HI_CFG 0x76 +#define TCPC_VBUS_VOLTAGE_ALARM_LO_CFG 0x78 + +enum typec_role { + TYPEC_SINK, + TYPEC_SOURCE, + TYPEC_ROLE_UNKNOWN, +}; -#define TCPC_POWER_STATUS 0x1e -#define TCPC_POWER_STATUS_UNINIT BIT(6) -#define TCPC_POWER_STATUS_VBUS_DET BIT(3) -#define TCPC_POWER_STATUS_VBUS_PRES BIT(2) +enum typec_data_role { + TYPEC_DEVICE, + TYPEC_HOST, +}; enum typec_cc_polarity { TYPEC_POLARITY_CC1, TYPEC_POLARITY_CC2, }; +enum typec_cc_state { + TYPEC_STATE_OPEN, + TYPEC_STATE_SRC_BOTH_RA, + TYPEC_STATE_SRC_RD_RA, + TYPEC_STATE_SRC_RD, + TYPEC_STATE_SRC_RESERVED, + TYPEC_STATE_SNK_DEFAULT, + TYPEC_STATE_SNK_POWER15, + TYPEC_STATE_SNK_POWER30, +}; + + +/* USB PD Messages */ +enum pd_ctrl_msg_type { + /* 0 Reserved */ + PD_CTRL_GOOD_CRC = 1, + PD_CTRL_GOTO_MIN = 2, + PD_CTRL_ACCEPT = 3, + PD_CTRL_REJECT = 4, + PD_CTRL_PING = 5, + PD_CTRL_PS_RDY = 6, + PD_CTRL_GET_SOURCE_CAP = 7, + PD_CTRL_GET_SINK_CAP = 8, + PD_CTRL_DR_SWAP = 9, + PD_CTRL_PR_SWAP = 10, + PD_CTRL_VCONN_SWAP = 11, + PD_CTRL_WAIT = 12, + PD_CTRL_SOFT_RESET = 13, + /* 14-15 Reserved */ +}; + +enum pd_data_msg_type { + /* 0 Reserved */ + PD_DATA_SOURCE_CAP = 1, + PD_DATA_REQUEST = 2, + PD_DATA_BIST = 3, + PD_DATA_SINK_CAP = 4, + /* 5-14 Reserved */ + PD_DATA_VENDOR_DEF = 15, +}; + +enum tcpc_transmit_type { + TCPC_TX_SOP = 0, + TCPC_TX_SOP_PRIME = 1, + TCPC_TX_SOP_PRIME_PRIME = 2, + TCPC_TX_SOP_DEBUG_PRIME = 3, + TCPC_TX_SOP_DEBUG_PRIME_PRIME = 4, + TCPC_TX_HARD_RESET = 5, + TCPC_TX_CABLE_RESET = 6, + TCPC_TX_BIST_MODE_2 = 7 +}; + +enum pd_sink_state{ + UNATTACH = 0, + ATTACHED, + WAIT_SOURCE_CAP, + WAIT_SOURCE_ACCEPT, + WAIT_SOURCE_READY, + SINK_READY, +}; + + +#define PD_REV10 0x0 +#define PD_REV20 0x1 + +#define PD_HEADER_CNT_SHIFT 12 +#define PD_HEADER_CNT_MASK 0x7 +#define PD_HEADER_ID_SHIFT 9 +#define PD_HEADER_ID_MASK 0x7 +#define PD_HEADER_PWR_ROLE BIT(8) +#define PD_HEADER_REV_SHIFT 6 +#define PD_HEADER_REV_MASK 0x3 +#define PD_HEADER_DATA_ROLE BIT(5) +#define PD_HEADER_TYPE_SHIFT 0 +#define PD_HEADER_TYPE_MASK 0xf + +#define PD_HEADER(type, pwr, data, id, cnt) \ + ((((type) & PD_HEADER_TYPE_MASK) << PD_HEADER_TYPE_SHIFT) | \ + ((pwr) == TYPEC_SOURCE ? PD_HEADER_PWR_ROLE : 0) | \ + ((data) == TYPEC_HOST ? PD_HEADER_DATA_ROLE : 0) | \ + (PD_REV20 << PD_HEADER_REV_SHIFT) | \ + (((id) & PD_HEADER_ID_MASK) << PD_HEADER_ID_SHIFT) | \ + (((cnt) & PD_HEADER_CNT_MASK) << PD_HEADER_CNT_SHIFT)) + + +static inline unsigned int pd_header_cnt(uint16_t header) +{ + return (header >> PD_HEADER_CNT_SHIFT) & PD_HEADER_CNT_MASK; +} + +static inline unsigned int pd_header_cnt_le(__le16 header) +{ + return pd_header_cnt(le16_to_cpu(header)); +} + +static inline unsigned int pd_header_type(uint16_t header) +{ + return (header >> PD_HEADER_TYPE_SHIFT) & PD_HEADER_TYPE_MASK; +} + +static inline unsigned int pd_header_type_le(__le16 header) +{ + return pd_header_type(le16_to_cpu(header)); +} + +#define PD_MAX_PAYLOAD 7 + +struct pd_message { + uint8_t frametype; + uint16_t header; + uint32_t payload[PD_MAX_PAYLOAD]; +} __packed; + +enum pd_pdo_type { + PDO_TYPE_FIXED = 0, + PDO_TYPE_BATT = 1, + PDO_TYPE_VAR = 2, +}; + + +#define PDO_TYPE_SHIFT 30 +#define PDO_TYPE_MASK 0x3 + +#define PDO_TYPE(t) ((t) << PDO_TYPE_SHIFT) + +#define PDO_VOLT_MASK 0x3ff +#define PDO_CURR_MASK 0x3ff +#define PDO_PWR_MASK 0x3ff + +#define PDO_FIXED_DUAL_ROLE BIT(29) /* Power role swap supported */ +#define PDO_FIXED_SUSPEND BIT(28) /* USB Suspend supported (Source) */ +#define PDO_FIXED_HIGHER_CAP BIT(28) /* Requires more than vSafe5V (Sink) */ +#define PDO_FIXED_EXTPOWER BIT(27) /* Externally powered */ +#define PDO_FIXED_USB_COMM BIT(26) /* USB communications capable */ +#define PDO_FIXED_DATA_SWAP BIT(25) /* Data role swap supported */ +#define PDO_FIXED_VOLT_SHIFT 10 /* 50mV units */ +#define PDO_FIXED_CURR_SHIFT 0 /* 10mA units */ + +#define PDO_FIXED_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_FIXED_VOLT_SHIFT) +#define PDO_FIXED_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_FIXED_CURR_SHIFT) + +#define PDO_FIXED(mv, ma, flags) \ + (PDO_TYPE(PDO_TYPE_FIXED) | (flags) | \ + PDO_FIXED_VOLT(mv) | PDO_FIXED_CURR(ma)) + +#define PDO_BATT_MAX_VOLT_SHIFT 20 /* 50mV units */ +#define PDO_BATT_MIN_VOLT_SHIFT 10 /* 50mV units */ +#define PDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ + +#define PDO_BATT_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MIN_VOLT_SHIFT) +#define PDO_BATT_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_BATT_MAX_VOLT_SHIFT) +#define PDO_BATT_MAX_POWER(mw) ((((mw) / 250) & PDO_PWR_MASK) << PDO_BATT_MAX_PWR_SHIFT) + +#define PDO_BATT(min_mv, max_mv, max_mw) \ + (PDO_TYPE(PDO_TYPE_BATT) | PDO_BATT_MIN_VOLT(min_mv) | \ + PDO_BATT_MAX_VOLT(max_mv) | PDO_BATT_MAX_POWER(max_mw)) + +#define PDO_VAR_MAX_VOLT_SHIFT 20 /* 50mV units */ +#define PDO_VAR_MIN_VOLT_SHIFT 10 /* 50mV units */ +#define PDO_VAR_MAX_CURR_SHIFT 0 /* 10mA units */ + +#define PDO_VAR_MIN_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MIN_VOLT_SHIFT) +#define PDO_VAR_MAX_VOLT(mv) ((((mv) / 50) & PDO_VOLT_MASK) << PDO_VAR_MAX_VOLT_SHIFT) +#define PDO_VAR_MAX_CURR(ma) ((((ma) / 10) & PDO_CURR_MASK) << PDO_VAR_MAX_CURR_SHIFT) + +#define PDO_VAR(min_mv, max_mv, max_ma) \ + (PDO_TYPE(PDO_TYPE_VAR) | PDO_VAR_MIN_VOLT(min_mv) | \ + PDO_VAR_MAX_VOLT(max_mv) | PDO_VAR_MAX_CURR(max_ma)) + +static inline enum pd_pdo_type pdo_type(uint32_t pdo) +{ + return (pdo >> PDO_TYPE_SHIFT) & PDO_TYPE_MASK; +} + +static inline unsigned int pdo_fixed_voltage(uint32_t pdo) +{ + return ((pdo >> PDO_FIXED_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; +} + +static inline unsigned int pdo_min_voltage(uint32_t pdo) +{ + return ((pdo >> PDO_VAR_MIN_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; +} + +static inline unsigned int pdo_max_voltage(uint32_t pdo) +{ + return ((pdo >> PDO_VAR_MAX_VOLT_SHIFT) & PDO_VOLT_MASK) * 50; +} + +static inline unsigned int pdo_max_current(uint32_t pdo) +{ + return ((pdo >> PDO_VAR_MAX_CURR_SHIFT) & PDO_CURR_MASK) * 10; +} + +static inline unsigned int pdo_max_power(uint32_t pdo) +{ + return ((pdo >> PDO_BATT_MAX_PWR_SHIFT) & PDO_PWR_MASK) * 250; +} + +/* RDO: Request Data Object */ +#define RDO_OBJ_POS_SHIFT 28 +#define RDO_OBJ_POS_MASK 0x7 +#define RDO_GIVE_BACK BIT(27) /* Supports reduced operating current */ +#define RDO_CAP_MISMATCH BIT(26) /* Not satisfied by source caps */ +#define RDO_USB_COMM BIT(25) /* USB communications capable */ +#define RDO_NO_SUSPEND BIT(24) /* USB Suspend not supported */ + +#define RDO_PWR_MASK 0x3ff +#define RDO_CURR_MASK 0x3ff + +#define RDO_FIXED_OP_CURR_SHIFT 10 +#define RDO_FIXED_MAX_CURR_SHIFT 0 + +#define RDO_OBJ(idx) (((idx) & RDO_OBJ_POS_MASK) << RDO_OBJ_POS_SHIFT) + +#define PDO_FIXED_OP_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_OP_CURR_SHIFT) +#define PDO_FIXED_MAX_CURR(ma) ((((ma) / 10) & RDO_CURR_MASK) << RDO_FIXED_MAX_CURR_SHIFT) + +#define RDO_FIXED(idx, op_ma, max_ma, flags) \ + (RDO_OBJ(idx) | (flags) | \ + PDO_FIXED_OP_CURR(op_ma) | PDO_FIXED_MAX_CURR(max_ma)) + +#define RDO_BATT_OP_PWR_SHIFT 10 /* 250mW units */ +#define RDO_BATT_MAX_PWR_SHIFT 0 /* 250mW units */ + +#define RDO_BATT_OP_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_OP_PWR_SHIFT) +#define RDO_BATT_MAX_PWR(mw) ((((mw) / 250) & RDO_PWR_MASK) << RDO_BATT_MAX_PWR_SHIFT) + +#define RDO_BATT(idx, op_mw, max_mw, flags) \ + (RDO_OBJ(idx) | (flags) | \ + RDO_BATT_OP_PWR(op_mw) | RDO_BATT_MAX_PWR(max_mw)) + +static inline unsigned int rdo_index(u32 rdo) +{ + return (rdo >> RDO_OBJ_POS_SHIFT) & RDO_OBJ_POS_MASK; +} + +static inline unsigned int rdo_op_current(u32 rdo) +{ + return ((rdo >> RDO_FIXED_OP_CURR_SHIFT) & RDO_CURR_MASK) * 10; +} + +static inline unsigned int rdo_max_current(u32 rdo) +{ + return ((rdo >> RDO_FIXED_MAX_CURR_SHIFT) & + RDO_CURR_MASK) * 10; +} + +static inline unsigned int rdo_op_power(u32 rdo) +{ + return ((rdo >> RDO_BATT_OP_PWR_SHIFT) & RDO_PWR_MASK) * 250; +} + +static inline unsigned int rdo_max_power(u32 rdo) +{ + return ((rdo >> RDO_BATT_MAX_PWR_SHIFT) & RDO_PWR_MASK) * 250; +} + +#define TCPC_LOG_BUFFER_SIZE 1024 + typedef void (*ss_mux_sel)(enum typec_cc_polarity pol); -int tcpc_set_cc_to_source(struct udevice *i2c_dev); -int tcpc_set_plug_orientation(struct udevice *i2c_dev, enum typec_cc_polarity polarity); -int tcpc_get_cc_polarity(struct udevice *i2c_dev, enum typec_cc_polarity *polarity); -int tcpc_clear_alert(struct udevice *i2c_dev, uint16_t clear_mask); -int tcpc_send_command(struct udevice *i2c_dev, uint8_t command); -int tcpc_polling_reg(struct udevice *i2c_dev, uint8_t reg, +enum tcpc_port_type { + TYPEC_PORT_DFP, + TYPEC_PORT_UFP, + TYPEC_PORT_DRP, +}; + +struct tcpc_port_config { + uint8_t i2c_bus; + uint8_t addr; + enum tcpc_port_type port_type; + uint32_t max_snk_mv; + uint32_t max_snk_ma; + uint32_t max_snk_mw; + uint32_t op_snk_mv; +}; + +struct tcpc_port { + struct tcpc_port_config cfg; + struct udevice *i2c_dev; + ss_mux_sel ss_sel_func; + enum pd_sink_state pd_state; + uint32_t tx_msg_id; + uint32_t log_size; + char logbuffer[TCPC_LOG_BUFFER_SIZE]; + char *log_p; + char *log_print; +}; + +int tcpc_set_cc_to_source(struct tcpc_port *port); +int tcpc_set_plug_orientation(struct tcpc_port *port, enum typec_cc_polarity polarity); +int tcpc_get_cc_status(struct tcpc_port *port, enum typec_cc_polarity *polarity, enum typec_cc_state *state); +int tcpc_clear_alert(struct tcpc_port *port, uint16_t clear_mask); +int tcpc_send_command(struct tcpc_port *port, uint8_t command); +int tcpc_polling_reg(struct tcpc_port *port, uint8_t reg, uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms); -int tcpc_setup_dfp_mode(struct udevice *i2c_dev, ss_mux_sel ss_sel_func); -int tcpc_disable_vbus(struct udevice *i2c_dev); -int tcpc_init(struct udevice *i2c_dev); +int tcpc_setup_dfp_mode(struct tcpc_port *port); +int tcpc_disable_src_vbus(struct tcpc_port *port); +int tcpc_init(struct tcpc_port *port, struct tcpc_port_config config, ss_mux_sel ss_sel_func); +void tcpc_print_log(struct tcpc_port *port); #endif /* __TCPCI_H */ From f2e75216862793d4fd7048724054da37199621cf Mon Sep 17 00:00:00 2001 From: Jun Li Date: Tue, 16 Jan 2018 18:06:52 +0800 Subject: [PATCH 54/62] MLK-17376 typec: support power source with 2 stages of capability Some power delivery source send the source capability by 2 stages: 1st stage send the source capability message with only basic 5V PDO, after the 5V power session setup, 2nd stage it will send full source capabilities with all PDOs it can support, in this case, we should go on to process the following PD source cap to have a new power session setup. Signed-off-by: Li Jun --- board/freescale/common/tcpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/board/freescale/common/tcpc.c b/board/freescale/common/tcpc.c index 2982ded75f35..a674717d2366 100644 --- a/board/freescale/common/tcpc.c +++ b/board/freescale/common/tcpc.c @@ -614,6 +614,7 @@ static void tcpc_pd_sink_process(struct tcpc_port *port) switch (pd_state) { case WAIT_SOURCE_CAP: + case SINK_READY: if (msgtype != PD_DATA_SOURCE_CAP) continue; @@ -656,9 +657,8 @@ static void tcpc_pd_sink_process(struct tcpc_port *port) continue; if (msgtype == PD_CTRL_PS_RDY) { - tcpc_log(port, "PD source ready! \n"); - pd_state = SINK_READY; - return; + tcpc_log(port, "PD source ready!\n"); + pd_state = SINK_READY; } break; From 1274506647283935909e5297b1f0b886c9092f34 Mon Sep 17 00:00:00 2001 From: Ye Li Date: Sun, 11 Feb 2018 02:42:31 -0800 Subject: [PATCH 55/62] MLK-17573-1 tcpc: Add interface to set UFP mode Add a interface to set UFP mode, so when running as device mode, the board level codes can use it to configure the TCPC port to UFP mode. Since we have supported PD charge for dead battery, so add check before applying UFP or DFP mode. Signed-off-by: Ye Li Acked-by: Jun Li --- board/freescale/common/tcpc.c | 129 ++++++++++++++++++++++++++++++++++ board/freescale/common/tcpc.h | 2 + 2 files changed, 131 insertions(+) diff --git a/board/freescale/common/tcpc.c b/board/freescale/common/tcpc.c index a674717d2366..b3f11f3b94f5 100644 --- a/board/freescale/common/tcpc.c +++ b/board/freescale/common/tcpc.c @@ -14,6 +14,8 @@ #define tcpc_debug_log(port, fmt, args...) #endif +static bool tcpc_pd_sink_check_charging(struct tcpc_port *port); + static int tcpc_log(struct tcpc_port *port, const char *fmt, ...) { va_list args; @@ -48,6 +50,24 @@ int tcpc_set_cc_to_source(struct tcpc_port *port) return err; } +int tcpc_set_cc_to_sink(struct tcpc_port *port) +{ + uint8_t valb; + int err; + + if (port == NULL) + return -EINVAL; + + valb = (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC1_SHIFT) | + (TCPC_ROLE_CTRL_CC_RD << TCPC_ROLE_CTRL_CC2_SHIFT); + + err = dm_i2c_write(port->i2c_dev, TCPC_ROLE_CTRL, &valb, 1); + if (err) + tcpc_log(port, "%s dm_i2c_write failed, err %d\n", __func__, err); + return err; +} + + int tcpc_set_plug_orientation(struct tcpc_port *port, enum typec_cc_polarity polarity) { uint8_t valb; @@ -280,6 +300,12 @@ int tcpc_setup_dfp_mode(struct tcpc_port *port) if (port == NULL) return -EINVAL; + if (tcpc_pd_sink_check_charging(port)) { + tcpc_log(port, "%s: Can't apply DFP mode when PD is charging\n", + __func__); + return -EPERM; + } + tcpc_set_cc_to_source(port); ret = tcpc_send_command(port, TCPC_CMD_LOOK4CONNECTION); @@ -332,6 +358,69 @@ int tcpc_setup_dfp_mode(struct tcpc_port *port) return 0; } +int tcpc_setup_ufp_mode(struct tcpc_port *port) +{ + enum typec_cc_polarity pol; + enum typec_cc_state state; + int ret; + + if (port == NULL) + return -EINVAL; + + /* Check if the PD charge is working. If not, need to configure CC role for UFP */ + if (!tcpc_pd_sink_check_charging(port)) { + + /* Disable the source vbus once it is enabled by DFP mode */ + tcpc_disable_src_vbus(port); + + tcpc_set_cc_to_sink(port); + + ret = tcpc_send_command(port, TCPC_CMD_LOOK4CONNECTION); + if (ret) + return ret; + + /* At least wait tCcStatusDelay + tTCPCFilter + tCcTCPCSampleRate (max) = 200us + 500us + ?ms + * PTN5110 datasheet does not contain the sample rate value, according other productions, + * the sample rate is at ms level, about 2 ms -10ms. So wait 100ms should be enough. + */ + mdelay(100); + + ret = tcpc_polling_reg(port, TCPC_ALERT, 2, TCPC_ALERT_CC_STATUS, TCPC_ALERT_CC_STATUS, 100); + if (ret) { + tcpc_log(port, "%s: Polling ALERT register, TCPC_ALERT_CC_STATUS bit failed, ret = %d\n", + __func__, ret); + return ret; + } + + ret = tcpc_get_cc_status(port, &pol, &state); + tcpc_clear_alert(port, TCPC_ALERT_CC_STATUS); + + } else { + ret = tcpc_get_cc_status(port, &pol, &state); + } + + if (!ret) { + /* If presenting not as sink, then return */ + if (state != TYPEC_STATE_SNK_DEFAULT && state != TYPEC_STATE_SNK_POWER15 && + state != TYPEC_STATE_SNK_POWER30) + return -EPERM; + + if (pol == TYPEC_POLARITY_CC1) + tcpc_debug_log(port, "polarity cc1\n"); + else + tcpc_debug_log(port, "polarity cc2\n"); + + if (port->ss_sel_func) + port->ss_sel_func(pol); + + ret = tcpc_set_plug_orientation(port, pol); + if (ret) + return ret; + } + + return 0; +} + int tcpc_disable_src_vbus(struct tcpc_port *port) { int ret; @@ -669,6 +758,46 @@ static void tcpc_pd_sink_process(struct tcpc_port *port) } } +static bool tcpc_pd_sink_check_charging(struct tcpc_port *port) +{ + uint8_t valb; + int err; + enum typec_cc_polarity pol; + enum typec_cc_state state; + + if (port == NULL) + return false; + + /* Check the CC status, must be sink */ + err = tcpc_get_cc_status(port, &pol, &state); + if (err || (state != TYPEC_STATE_SNK_POWER15 + && state != TYPEC_STATE_SNK_POWER30 + && state != TYPEC_STATE_SNK_DEFAULT)) { + tcpc_debug_log(port, "TCPC wrong state for PD charging, err = %d, CC = 0x%x\n", + err, state); + return false; + } + + /* Check the VBUS PRES and SINK VBUS for dead battery */ + err = dm_i2c_read(port->i2c_dev, TCPC_POWER_STATUS, &valb, 1); + if (err) { + tcpc_debug_log(port, "%s dm_i2c_read failed, err %d\n", __func__, err); + return false; + } + + if (!(valb & TCPC_POWER_STATUS_VBUS_PRES)) { + tcpc_debug_log(port, "VBUS NOT PRES \n"); + return false; + } + + if (!(valb & TCPC_POWER_STATUS_SINKING_VBUS)) { + tcpc_debug_log(port, "SINK VBUS is not enabled for dead battery\n"); + return false; + } + + return true; +} + static int tcpc_pd_sink_init(struct tcpc_port *port) { uint8_t valb; diff --git a/board/freescale/common/tcpc.h b/board/freescale/common/tcpc.h index c3bb9af64376..43b5e49394d5 100644 --- a/board/freescale/common/tcpc.h +++ b/board/freescale/common/tcpc.h @@ -432,6 +432,7 @@ struct tcpc_port { }; int tcpc_set_cc_to_source(struct tcpc_port *port); +int tcpc_set_cc_to_sink(struct tcpc_port *port); int tcpc_set_plug_orientation(struct tcpc_port *port, enum typec_cc_polarity polarity); int tcpc_get_cc_status(struct tcpc_port *port, enum typec_cc_polarity *polarity, enum typec_cc_state *state); int tcpc_clear_alert(struct tcpc_port *port, uint16_t clear_mask); @@ -439,6 +440,7 @@ int tcpc_send_command(struct tcpc_port *port, uint8_t command); int tcpc_polling_reg(struct tcpc_port *port, uint8_t reg, uint8_t reg_width, uint16_t mask, uint16_t value, ulong timeout_ms); int tcpc_setup_dfp_mode(struct tcpc_port *port); +int tcpc_setup_ufp_mode(struct tcpc_port *port); int tcpc_disable_src_vbus(struct tcpc_port *port); int tcpc_init(struct tcpc_port *port, struct tcpc_port_config config, ss_mux_sel ss_sel_func); void tcpc_print_log(struct tcpc_port *port); From a10eed91280eda591a19e20bfeee6b13794d8d0f Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Sun, 16 Dec 2018 07:54:52 +0100 Subject: [PATCH 56/62] imx: imx8mq_hb: SDHC2 configuration cleanup Remove a non-existant reset pin for the SDHC2. Signed-off-by: Jon Nettleton --- board/solidrun/imx8mq_hb/spl.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/board/solidrun/imx8mq_hb/spl.c b/board/solidrun/imx8mq_hb/spl.c index ebb730db12e5..ff513eb01271 100644 --- a/board/solidrun/imx8mq_hb/spl.c +++ b/board/solidrun/imx8mq_hb/spl.c @@ -95,7 +95,6 @@ static iomux_v3_cfg_t const usdhc2_pads[] = { IMX8MQ_PAD_SD2_DATA2__USDHC2_DATA2 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0x16 */ IMX8MQ_PAD_SD2_DATA3__USDHC2_DATA3 | MUX_PAD_CTRL(USDHC_PAD_CTRL), /* 0xd6 */ IMX8MQ_PAD_SD2_CD_B__GPIO2_IO12 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), - IMX8MQ_PAD_SD2_RESET_B__GPIO2_IO19 | MUX_PAD_CTRL(USDHC_GPIO_PAD_CTRL), }; static struct fsl_esdhc_cfg usdhc_cfg[2] = { @@ -129,10 +128,6 @@ int board_mmc_init(bd_t *bis) usdhc_cfg[1].sdhc_clk = mxc_get_clock(USDHC2_CLK_ROOT); imx_iomux_v3_setup_multiple_pads(usdhc2_pads, ARRAY_SIZE(usdhc2_pads)); - gpio_request(USDHC2_PWR_GPIO, "usdhc2_reset"); - gpio_direction_output(USDHC2_PWR_GPIO, 0); - udelay(500); - gpio_direction_output(USDHC2_PWR_GPIO, 1); break; default: printf("Warning: you configured more USDHC controllers(%d) than supported by the board\n", i + 1); From 7c74c7255b824743c17cac7e0e606ad940f919b0 Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Sun, 16 Dec 2018 08:43:42 +0100 Subject: [PATCH 57/62] imx: imx8mq_hb: Add USB Host support This patch is important as currently Linux is not initializing the USB clocks correctly, so if we don't do it u-boot USB host mode does not work. This is a temporary fix until the Linux kernel is patched to work properly. Regardless we want USB working properly for booting and recovering our board, although this needs to be converted to a DM driver model. Signed-off-by: Jon Nettleton --- arch/arm/mach-imx/spl.c | 7 +- board/solidrun/imx8mq_hb/Kconfig | 2 + board/solidrun/imx8mq_hb/Makefile | 2 + board/solidrun/imx8mq_hb/imx8mq_hb.c | 148 +++++++++++++++++++++++++++ board/solidrun/imx8mq_hb/spl.c | 6 ++ configs/imx8mq_hb_defconfig | 16 +++ 6 files changed, 179 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-imx/spl.c b/arch/arm/mach-imx/spl.c index 02b69bd24d7a..2df4600a19c3 100644 --- a/arch/arm/mach-imx/spl.c +++ b/arch/arm/mach-imx/spl.c @@ -41,8 +41,9 @@ u32 spl_boot_device(void) * checking whether the USB PHY is currently active... This * assumes that SPL did not (yet) initialize the USB PHY... */ - if (is_usbotg_phy_active()) + if (is_usbotg_phy_active()) { return BOOT_DEVICE_BOARD; + } /* BOOT_CFG1[7:4] - see IMX6DQRM Table 8-8 */ switch ((reg & IMX6_BMODE_MASK) >> IMX6_BMODE_SHIFT) { @@ -119,8 +120,10 @@ u32 spl_boot_device(void) * checking whether the USB PHY is currently active... This * assumes that SPL did not (yet) initialize the USB PHY... */ - if (is_boot_from_usb()) + if (is_boot_from_usb()) { + printf("USB Phy Active Boot Board\n"); return BOOT_DEVICE_BOARD; + } #endif enum boot_device boot_device_spl = get_boot_device(); diff --git a/board/solidrun/imx8mq_hb/Kconfig b/board/solidrun/imx8mq_hb/Kconfig index 2e6e317e6e95..4420a1be26bf 100644 --- a/board/solidrun/imx8mq_hb/Kconfig +++ b/board/solidrun/imx8mq_hb/Kconfig @@ -9,4 +9,6 @@ config SYS_VENDOR config SYS_CONFIG_NAME default "imx8mq_hb" +source "board/freescale/common/Kconfig" + endif diff --git a/board/solidrun/imx8mq_hb/Makefile b/board/solidrun/imx8mq_hb/Makefile index c6be648e32ef..847a9aa51822 100644 --- a/board/solidrun/imx8mq_hb/Makefile +++ b/board/solidrun/imx8mq_hb/Makefile @@ -9,6 +9,8 @@ obj-y += imx8mq_hb.o ifdef CONFIG_SPL_BUILD obj-y += spl.o obj-$(CONFIG_IMX8M_LPDDR4) += lpddr4_timing.o +else +obj-$(CONFIG_USB_TCPC) += ../../freescale/common/tcpc.o endif obj-$(CONFIG_POWER_PFUZE100) += ../../freescale/common/pfuze.o diff --git a/board/solidrun/imx8mq_hb/imx8mq_hb.c b/board/solidrun/imx8mq_hb/imx8mq_hb.c index 851b455e9854..80f4202caef2 100644 --- a/board/solidrun/imx8mq_hb/imx8mq_hb.c +++ b/board/solidrun/imx8mq_hb/imx8mq_hb.c @@ -21,7 +21,11 @@ #include #include #include +#include +#include +#include #include "../../freescale/common/pfuze.h" +#include "../../freescale/common/tcpc.h" DECLARE_GLOBAL_DATA_PTR; @@ -130,12 +134,151 @@ int board_phy_config(struct phy_device *phydev) } #endif +#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_IMX8M) + +#define USB_PHY_CTRL0 0xF0040 +#define USB_PHY_CTRL0_REF_SSP_EN BIT(2) + +#define USB_PHY_CTRL1 0xF0044 +#define USB_PHY_CTRL1_RESET BIT(0) +#define USB_PHY_CTRL1_COMMONONN BIT(1) +#define USB_PHY_CTRL1_ATERESET BIT(3) +#define USB_PHY_CTRL1_VDATSRCENB0 BIT(19) +#define USB_PHY_CTRL1_VDATDETENB0 BIT(20) + +#define USB_PHY_CTRL2 0xF0048 +#define USB_PHY_CTRL2_TXENABLEN0 BIT(8) + +static struct dwc3_device dwc3_device_data = { + .maximum_speed = USB_SPEED_SUPER, + .base = USB1_BASE_ADDR, + .dr_mode = USB_DR_MODE_PERIPHERAL, + .index = 0, + .power_down_scale = 2, +}; + +int usb_gadget_handle_interrupts(void) +{ + dwc3_uboot_handle_interrupt(0); + return 0; +} + +static void dwc3_nxp_usb_phy_init(struct dwc3_device *dwc3) +{ + u32 RegData; + + RegData = readl(dwc3->base + USB_PHY_CTRL1); + RegData &= ~(USB_PHY_CTRL1_VDATSRCENB0 | USB_PHY_CTRL1_VDATDETENB0 | + USB_PHY_CTRL1_COMMONONN); + RegData |= USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET; + writel(RegData, dwc3->base + USB_PHY_CTRL1); + + RegData = readl(dwc3->base + USB_PHY_CTRL0); + RegData |= USB_PHY_CTRL0_REF_SSP_EN; + writel(RegData, dwc3->base + USB_PHY_CTRL0); + + RegData = readl(dwc3->base + USB_PHY_CTRL2); + RegData |= USB_PHY_CTRL2_TXENABLEN0; + writel(RegData, dwc3->base + USB_PHY_CTRL2); + + RegData = readl(dwc3->base + USB_PHY_CTRL1); + RegData &= ~(USB_PHY_CTRL1_RESET | USB_PHY_CTRL1_ATERESET); + writel(RegData, dwc3->base + USB_PHY_CTRL1); +} +#endif + +#ifdef CONFIG_USB_TCPC +struct tcpc_port port; +struct tcpc_port_config port_config = { + .i2c_bus = 0, + .addr = 0x50, + .port_type = TYPEC_PORT_UFP, + .max_snk_mv = 20000, + .max_snk_ma = 3000, + .max_snk_mw = 15000, + .op_snk_mv = 9000, +}; + +#define USB_TYPEC_SEL IMX_GPIO_NR(3, 15) + +static iomux_v3_cfg_t ss_mux_gpio[] = { + IMX8MQ_PAD_NAND_RE_B__GPIO3_IO15 | MUX_PAD_CTRL(NO_PAD_CTRL), +}; + +void ss_mux_select(enum typec_cc_polarity pol) +{ + if (pol == TYPEC_POLARITY_CC1) + gpio_direction_output(USB_TYPEC_SEL, 1); + else + gpio_direction_output(USB_TYPEC_SEL, 0); +} + +static int setup_typec(void) +{ + int ret; + + imx_iomux_v3_setup_multiple_pads(ss_mux_gpio, ARRAY_SIZE(ss_mux_gpio)); + gpio_request(USB_TYPEC_SEL, "typec_sel"); + + ret = tcpc_init(&port, port_config, &ss_mux_select); + if (ret) { + printf("%s: tcpc init failed, err=%d\n", + __func__, ret); + } + + return ret; +} +#endif + +#if defined(CONFIG_USB_DWC3) || defined(CONFIG_USB_XHCI_IMX8M) +int board_usb_init(int index, enum usb_init_type init) +{ + int ret = 0; + imx8m_usb_power(index, true); + + if (index == 0 && init == USB_INIT_DEVICE) { +#ifdef CONFIG_USB_TCPC + ret = tcpc_setup_ufp_mode(&port); +#endif + dwc3_nxp_usb_phy_init(&dwc3_device_data); + return dwc3_uboot_init(&dwc3_device_data); + } else if (index == 0 && init == USB_INIT_HOST) { +#ifdef CONFIG_USB_TCPC + ret = tcpc_setup_dfp_mode(&port); +#endif + return ret; + } + + return 0; +} + +int board_usb_cleanup(int index, enum usb_init_type init) +{ + int ret = 0; + if (index == 0 && init == USB_INIT_DEVICE) { + dwc3_uboot_exit(index); + } else if (index == 0 && init == USB_INIT_HOST) { +#ifdef CONFIG_USB_TCPC + ret = tcpc_disable_src_vbus(&port); +#endif + } + + imx8m_usb_power(index, false); + + return ret; +} +#endif + int board_init(void) { #ifdef CONFIG_FEC_MXC setup_fec(); #endif +#ifdef CONFIG_USB_TCPC + setup_typec(); +#endif + return 0; } @@ -151,6 +294,8 @@ int ft_board_setup(void *blob, bd_t *bd) } #endif +void init_usb_clk(int usbno); + int board_late_init(void) { #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG @@ -158,5 +303,8 @@ int board_late_init(void) env_set("board_rev", "iMX8MQ"); #endif + init_usb_clk(0); + init_usb_clk(1); + return 0; } diff --git a/board/solidrun/imx8mq_hb/spl.c b/board/solidrun/imx8mq_hb/spl.c index ff513eb01271..f8b59b1d012c 100644 --- a/board/solidrun/imx8mq_hb/spl.c +++ b/board/solidrun/imx8mq_hb/spl.c @@ -185,6 +185,12 @@ int power_init_board(void) void spl_board_init(void) { + /* Serial download mode */ + if (is_usb_boot()) { + puts("Back to ROM, SDP\n"); + restore_boot_params(); + } + puts("Normal Boot\n"); } diff --git a/configs/imx8mq_hb_defconfig b/configs/imx8mq_hb_defconfig index 2f60990d6846..070f66371031 100644 --- a/configs/imx8mq_hb_defconfig +++ b/configs/imx8mq_hb_defconfig @@ -40,6 +40,7 @@ CONFIG_CMD_EXT4_WRITE=y CONFIG_CMD_FAT=y CONFIG_CMD_FS_GENERIC=y CONFIG_CMD_FS_UUID=y +CONFIG_CMD_USB=y CONFIG_DOS_PARTITION=y CONFIG_EFI_PARTITION=y CONFIG_EFI_PARTITION_ENTRIES_NUMBERS=128 @@ -64,3 +65,18 @@ CONFIG_DM_THERMAL=y CONFIG_FIT_EXTERNAL_OFFSET=0x3000 CONFIG_FSL_ESDHC=y CONFIG_MXC_UART=y +CONFIG_USB=y +CONFIG_DM_USB=y +CONFIG_USB_HOST=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +# CONFIG_USB_XHCI_DWC3_OF_SIMPLE is not set +# CONFIG_USB_XHCI_PCI is not set +# CONFIG_USB_XHCI_FSL is not set +CONFIG_USB_XHCI_IMX8M=y +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_DWC2 is not set +# CONFIG_USB_DWC3 is not set +CONFIG_USB_STORAGE=y From 350104dd5a2ef2b9ea9ab677c279494df52d5d0d Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Sun, 16 Dec 2018 08:49:21 +0100 Subject: [PATCH 58/62] imx: More places to fixup after the arch rename. This is a follow up patch to 1e365abcd8637c8c6afa2ea6341317badfdb8a7a Signed-off-by: Jon Nettleton --- drivers/usb/host/Kconfig | 2 +- drivers/video/imx/hdp/test_base_sw.c | 4 ++-- drivers/video/imx/imx8_hdmi.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 20ebef673db2..985da93d96c3 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -97,7 +97,7 @@ config USB_XHCI_FSL config USB_XHCI_IMX8M bool "XHCI support for imx8M(mscale)" - depends on ARCH_MX8M + depends on ARCH_IMX8M default y help Enables support for the on-chip xHCI controller on imx8m(mscale) SoC. diff --git a/drivers/video/imx/hdp/test_base_sw.c b/drivers/video/imx/hdp/test_base_sw.c index 973778c549cd..fc2afa0fee68 100644 --- a/drivers/video/imx/hdp/test_base_sw.c +++ b/drivers/video/imx/hdp/test_base_sw.c @@ -52,7 +52,7 @@ #include #include -#ifdef CONFIG_ARCH_MX8M +#ifdef CONFIG_ARCH_IMX8M /* mscale */ #define HDMI_BASE 0x32c00000 #define HDMI_PHY_BASE 0x32c80000 @@ -68,7 +68,7 @@ #endif -#ifdef CONFIG_ARCH_MX8M +#ifdef CONFIG_ARCH_IMX8M int cdn_apb_read(unsigned int addr, unsigned int *value) { unsigned int temp; diff --git a/drivers/video/imx/imx8_hdmi.c b/drivers/video/imx/imx8_hdmi.c index 32eda3e1472e..08dc914759b6 100644 --- a/drivers/video/imx/imx8_hdmi.c +++ b/drivers/video/imx/imx8_hdmi.c @@ -30,7 +30,7 @@ #include "API_AFE_ss28fdsoi_kiran_hdmitx.h" #endif -#ifdef CONFIG_MX8M +#ifdef CONFIG_IMX8M #include "API_AFE_t28hpc_hdmitx.h" #endif From ba501c825da2a8af4d895e5b6f3ff3a255966b75 Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Sun, 16 Dec 2018 11:45:01 +0100 Subject: [PATCH 59/62] Revert "autoboot: use default environment if debricking board" This reverts commit ae5de283d4bed0a69843193e85d3fed5b702928b. Revert this for now as it breaks other platforms that do not use a sys_proto.h header. Signed-off-by: Jon Nettleton --- common/autoboot.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/common/autoboot.c b/common/autoboot.c index ef672d7f3f13..94133eaeda78 100644 --- a/common/autoboot.c +++ b/common/autoboot.c @@ -14,8 +14,6 @@ #include #include #include -#include -#include DECLARE_GLOBAL_DATA_PTR; @@ -298,10 +296,6 @@ const char *bootdelay_process(void) s = env_get("bootdelay"); bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; - if (is_usb_boot()) { - bootdelay = 1; - set_default_env("!Started from usb", 0); - } #ifdef CONFIG_OF_CONTROL bootdelay = fdtdec_get_config_int(gd->fdt_blob, "bootdelay", From c3f941c6285ebf1fc6bb58eab741adaa989f55cf Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Sun, 16 Dec 2018 11:50:31 +0100 Subject: [PATCH 60/62] Fix commit 61a02147e4 This include seems to be unneccesary and broke builds for now mvebu platforms. Removing this include allows both to build. Signed-off-by: Jon Nettleton --- include/linux/sizes.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/sizes.h b/include/linux/sizes.h index e32e4343cf8b..675e07f63ca2 100644 --- a/include/linux/sizes.h +++ b/include/linux/sizes.h @@ -8,8 +8,6 @@ #ifndef __LINUX_SIZES_H__ #define __LINUX_SIZES_H__ -#include - #define SZ_1 0x00000001 #define SZ_2 0x00000002 #define SZ_4 0x00000004 From 0dd51748c2a6783d9686ce5342613bb7da6d3501 Mon Sep 17 00:00:00 2001 From: Jon Nettleton Date: Sun, 16 Dec 2018 13:13:40 +0100 Subject: [PATCH 61/62] imx: Add gpc power control function This adds a generic controller function to handle the various GPC power regions. For the HB Pulse we use this to power off both PCIE regions on boot to help return the devices to a sane state on reboot and sudden power off. Signed-off-by: Jon Nettleton --- arch/arm/include/asm/arch-imx8m/sys_proto.h | 1 + arch/arm/mach-imx/imx8m/soc.c | 16 +++++++++++++++- board/solidrun/imx8mq_hb/imx8mq_hb.c | 3 +++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/arch-imx8m/sys_proto.h b/arch/arm/include/asm/arch-imx8m/sys_proto.h index 3e54f9b6764a..069dc3579621 100644 --- a/arch/arm/include/asm/arch-imx8m/sys_proto.h +++ b/arch/arm/include/asm/arch-imx8m/sys_proto.h @@ -12,6 +12,7 @@ void set_wdog_reset(struct wdog_regs *wdog); void enable_tzc380(void); void restore_boot_params(void); int imx8m_usb_power(int usb_id, bool on); +int imx8m_gpc_power(int id, bool on); extern unsigned long rom_pointer[]; enum boot_device get_boot_device(void); bool is_usb_boot(void); diff --git a/arch/arm/mach-imx/imx8m/soc.c b/arch/arm/mach-imx/imx8m/soc.c index f8fc3bcbe76d..676fc236ba70 100644 --- a/arch/arm/mach-imx/imx8m/soc.c +++ b/arch/arm/mach-imx/imx8m/soc.c @@ -236,9 +236,10 @@ void reset_cpu(ulong addr) } } -#ifdef CONFIG_USB_XHCI_IMX8M #define FSL_SIP_GPC 0xC2000000 #define FSL_SIP_CONFIG_GPC_PM_DOMAIN 0x03 + +#ifdef CONFIG_USB_XHCI_IMX8M int imx8m_usb_power(int usb_id, bool on) { unsigned long ret; @@ -254,3 +255,16 @@ int imx8m_usb_power(int usb_id, bool on) return 0; } #endif + +int imx8m_gpc_power(int id, bool on) +{ + unsigned long ret; + + ret = call_imx_sip(FSL_SIP_GPC, + FSL_SIP_CONFIG_GPC_PM_DOMAIN, id, on, 0); + if (ret) + return -EPERM; + + return 0; +} + diff --git a/board/solidrun/imx8mq_hb/imx8mq_hb.c b/board/solidrun/imx8mq_hb/imx8mq_hb.c index 80f4202caef2..70ca8830b5be 100644 --- a/board/solidrun/imx8mq_hb/imx8mq_hb.c +++ b/board/solidrun/imx8mq_hb/imx8mq_hb.c @@ -306,5 +306,8 @@ int board_late_init(void) init_usb_clk(0); init_usb_clk(1); + imx8m_gpc_power(10, false); + imx8m_gpc_power(1, false); + return 0; } From 22df1573e20ef9d4b6de2f296eb372215361c47e Mon Sep 17 00:00:00 2001 From: Baruch Siach Date: Mon, 31 Dec 2018 11:40:29 +0200 Subject: [PATCH 62/62] tools/imx8m_image.sh: remove bashism Use a single '=' to test string equality for compatibility with non-bash shells. Otherwise, if /bin/sh is dash, build fails: ./tools/imx8m_image.sh: 15: [: signed_hdmi_imx8m.bin: unexpected operator ./tools/imx8m_image.sh: 15: [: signed_hdmi_imx8m.bin: unexpected operator ./tools/imx8m_image.sh: 15: [: spl/u-boot-spl-ddr.bin: unexpected operator ./tools/imx8m_image.sh: 15: [: spl/u-boot-spl-ddr.bin: unexpected operator WARNING './spl/u-boot-spl-ddr.bin' not found, resulting binary is not-functional Signed-off-by: Baruch Siach --- tools/imx8m_image.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/imx8m_image.sh b/tools/imx8m_image.sh index 6346fb64d8c5..ec0881a12812 100755 --- a/tools/imx8m_image.sh +++ b/tools/imx8m_image.sh @@ -12,7 +12,7 @@ blobs=`awk '/^SIGNED_HDMI/ {print $2} /^LOADER/ {print $2} /^SECOND_LOADER/ {pri for f in $blobs; do tmp=$srctree/$f - if [ $f == "spl/u-boot-spl-ddr.bin" ] || [ $f == "u-boot.itb" ]; then + if [ $f = "spl/u-boot-spl-ddr.bin" ] || [ $f = "u-boot.itb" ]; then continue fi @@ -28,7 +28,7 @@ for f in $blobs; do sed -in "s;$f;$tmp;" $file done -if [ $post_process == 1 ]; then +if [ $post_process = 1 ]; then if [ -f $srctree/lpddr4_pmu_train_1d_imem.bin ]; then objcopy -I binary -O binary --pad-to 0x8000 --gap-fill=0x0 $srctree/lpddr4_pmu_train_1d_imem.bin lpddr4_pmu_train_1d_imem_pad.bin objcopy -I binary -O binary --pad-to 0x4000 --gap-fill=0x0 $srctree/lpddr4_pmu_train_1d_dmem.bin lpddr4_pmu_train_1d_dmem_pad.bin