diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/bios_emulator/atibios.c | 2 | ||||
-rw-r--r-- | drivers/core/uclass.c | 9 | ||||
-rw-r--r-- | drivers/gpio/intel_broadwell_gpio.c | 7 | ||||
-rw-r--r-- | drivers/i2c/intel_i2c.c | 6 | ||||
-rw-r--r-- | drivers/misc/fsl_sec_mon.c | 240 | ||||
-rw-r--r-- | drivers/pci/pci_rom.c | 62 | ||||
-rw-r--r-- | drivers/power/regulator/fixed.c | 21 | ||||
-rw-r--r-- | drivers/reset/Kconfig | 9 | ||||
-rw-r--r-- | drivers/reset/Makefile | 1 | ||||
-rw-r--r-- | drivers/reset/reset-uniphier.c | 376 | ||||
-rw-r--r-- | drivers/rtc/mc146818.c | 2 | ||||
-rw-r--r-- | drivers/spi/fsl_qspi.c | 10 | ||||
-rw-r--r-- | drivers/tpm/tpm_tis_lpc.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/ehci-pci.c | 4 | ||||
-rw-r--r-- | drivers/video/Kconfig | 23 | ||||
-rw-r--r-- | drivers/video/Makefile | 5 | ||||
-rw-r--r-- | drivers/video/broadwell_igd.c | 39 | ||||
-rw-r--r-- | drivers/video/coreboot.c | 79 | ||||
-rw-r--r-- | drivers/video/coreboot_fb.c | 108 | ||||
-rw-r--r-- | drivers/video/ivybridge_igd.c | 843 | ||||
-rw-r--r-- | drivers/video/simple_panel.c | 2 | ||||
-rw-r--r-- | drivers/video/vesa.c | 34 | ||||
-rw-r--r-- | drivers/video/vesa_fb.c | 63 | ||||
-rw-r--r-- | drivers/video/video-uclass.c | 3 |
24 files changed, 1617 insertions, 335 deletions
diff --git a/drivers/bios_emulator/atibios.c b/drivers/bios_emulator/atibios.c index 77172467b2e..2d5b5dc562e 100644 --- a/drivers/bios_emulator/atibios.c +++ b/drivers/bios_emulator/atibios.c @@ -599,7 +599,7 @@ int biosemu_run(pci_dev_t pcidev, uchar *bios_rom, int bios_len, if (clean_up) { BE_exit(); if (vga_info->BIOSImage && - (u32)(vga_info->BIOSImage) != 0xc0000) + (ulong)(vga_info->BIOSImage) != 0xc0000) free(vga_info->BIOSImage); free(vga_info); vga_info = NULL; diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index de602ae52dc..60610e5a1f5 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -148,6 +148,15 @@ int uclass_get(enum uclass_id id, struct uclass **ucp) return 0; } +const char *uclass_get_name(enum uclass_id id) +{ + struct uclass *uc; + + if (uclass_get(id, &uc)) + return NULL; + return uc->uc_drv->name; +} + int uclass_find_device(enum uclass_id id, int index, struct udevice **devp) { struct uclass *uc; diff --git a/drivers/gpio/intel_broadwell_gpio.c b/drivers/gpio/intel_broadwell_gpio.c index 8b50900f9fc..81ce446e1a1 100644 --- a/drivers/gpio/intel_broadwell_gpio.c +++ b/drivers/gpio/intel_broadwell_gpio.c @@ -9,6 +9,7 @@ #include <fdtdec.h> #include <pch.h> #include <pci.h> +#include <syscon.h> #include <asm/cpu.h> #include <asm/gpio.h> #include <asm/io.h> @@ -118,6 +119,12 @@ static int broadwell_gpio_probe(struct udevice *dev) struct broadwell_bank_platdata *plat = dev_get_platdata(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct broadwell_bank_priv *priv = dev_get_priv(dev); + struct udevice *pinctrl; + int ret; + + /* Set up pin control if available */ + ret = syscon_get_by_driver_data(X86_SYSCON_PINCONF, &pinctrl); + debug("%s, pinctrl=%p, ret=%d\n", __func__, pinctrl, ret); uc_priv->gpio_count = GPIO_PER_BANK; uc_priv->bank_name = plat->bank_name; diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c index a0182dc1cc1..550a728cdcb 100644 --- a/drivers/i2c/intel_i2c.c +++ b/drivers/i2c/intel_i2c.c @@ -248,11 +248,11 @@ static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed) static int intel_i2c_probe(struct udevice *dev) { struct intel_i2c *priv = dev_get_priv(dev); - u32 base; + ulong base; /* Save base address from PCI BAR */ - priv->base = (u32)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, - PCI_REGION_IO); + priv->base = (ulong)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4, + PCI_REGION_IO); base = priv->base; /* Set SMBus enable. */ diff --git a/drivers/misc/fsl_sec_mon.c b/drivers/misc/fsl_sec_mon.c index d482a7db9ca..415232e1c15 100644 --- a/drivers/misc/fsl_sec_mon.c +++ b/drivers/misc/fsl_sec_mon.c @@ -7,140 +7,158 @@ #include <common.h> #include <fsl_sec_mon.h> -int change_sec_mon_state(u32 initial_state, u32 final_state) +static u32 get_sec_mon_state(void) { struct ccsr_sec_mon_regs *sec_mon_regs = (void *) (CONFIG_SYS_SEC_MON_ADDR); - u32 sts = sec_mon_in32(&sec_mon_regs->hp_stat); + return sec_mon_in32(&sec_mon_regs->hp_stat) & HPSR_SSM_ST_MASK; +} + +static int set_sec_mon_state_non_sec(void) +{ + u32 sts; int timeout = 10; + struct ccsr_sec_mon_regs *sec_mon_regs = (void *) + (CONFIG_SYS_SEC_MON_ADDR); - if ((sts & HPSR_SSM_ST_MASK) != initial_state) - return -1; + sts = get_sec_mon_state(); - if (initial_state == HPSR_SSM_ST_TRUST) { - switch (final_state) { - case HPSR_SSM_ST_NON_SECURE: - printf("SEC_MON state transitioning to Soft Fail.\n"); - sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); - - /* - * poll till SEC_MON is in - * Soft Fail state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_SOFT_FAIL)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_SOFT_FAIL) - break; - - udelay(10); - timeout--; - } - } + switch (sts) { + /* + * If initial state is check or Non-Secure, then set the Software + * Security Violation Bit and transition to Non-Secure State. + */ + case HPSR_SSM_ST_CHECK: + printf("SEC_MON state transitioning to Non Secure.\n"); + sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); - if (timeout == 0) { - printf("SEC_MON state transition timeout.\n"); - return -1; - } + /* polling loop till SEC_MON is in Non Secure state */ + while (timeout) { + sts = get_sec_mon_state(); + + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_NON_SECURE) + break; + + udelay(10); + timeout--; + } - timeout = 10; + if (timeout == 0) { + printf("SEC_MON state transition timeout.\n"); + return -1; + } + break; + + /* + * If initial state is Trusted, Secure or Soft-Fail, then first set + * the Software Security Violation Bit and transition to Soft-Fail + * State. + */ + case HPSR_SSM_ST_TRUST: + case HPSR_SSM_ST_SECURE: + case HPSR_SSM_ST_SOFT_FAIL: + printf("SEC_MON state transitioning to Soft Fail.\n"); + sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_SV); + + /* polling loop till SEC_MON is in Soft-Fail state */ + while (timeout) { + sts = get_sec_mon_state(); + + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_SOFT_FAIL) + break; + + udelay(10); + timeout--; + } + + if (timeout == 0) { + printf("SEC_MON state transition timeout.\n"); + return -1; + } + + timeout = 10; + /* + * If SSM Soft Fail to Non-Secure State Transition + * disable is not set, then set SSM_ST bit and + * transition to Non-Secure State. + */ + if ((sec_mon_in32(&sec_mon_regs->hp_com) & + HPCOMR_SSM_SFNS_DIS) == 0) { printf("SEC_MON state transitioning to Non Secure.\n"); sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SSM_ST); - /* - * poll till SEC_MON is in - * Non Secure state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_NON_SECURE)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_NON_SECURE) - break; - - udelay(10); - timeout--; - } - } + /* polling loop till SEC_MON is in Non Secure*/ + while (timeout) { + sts = get_sec_mon_state(); - if (timeout == 0) { - printf("SEC_MON state transition timeout.\n"); - return -1; - } - break; - case HPSR_SSM_ST_SOFT_FAIL: - printf("SEC_MON state transitioning to Soft Fail.\n"); - sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); - - /* - * polling loop till SEC_MON is in - * Soft Fail state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_SOFT_FAIL)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_SOFT_FAIL) - break; - - udelay(10); - timeout--; - } + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_NON_SECURE) + break; + + udelay(10); + timeout--; } if (timeout == 0) { printf("SEC_MON state transition timeout.\n"); return -1; } - break; - default: - return -1; } - } else if (initial_state == HPSR_SSM_ST_NON_SECURE) { - switch (final_state) { - case HPSR_SSM_ST_SOFT_FAIL: - printf("SEC_MON state transitioning to Soft Fail.\n"); - sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); - - /* - * polling loop till SEC_MON is in - * Soft Fail state - */ - while (((sts & HPSR_SSM_ST_MASK) != - HPSR_SSM_ST_SOFT_FAIL)) { - while (timeout) { - sts = sec_mon_in32 - (&sec_mon_regs->hp_stat); - - if ((sts & HPSR_SSM_ST_MASK) == - HPSR_SSM_ST_SOFT_FAIL) - break; - - udelay(10); - timeout--; - } - } + break; + default: + printf("SEC_MON already in Non Secure state.\n"); + return 0; + } + return 0; +} - if (timeout == 0) { - printf("SEC_MON state transition timeout.\n"); - return -1; - } +static int set_sec_mon_state_soft_fail(void) +{ + u32 sts; + int timeout = 10; + struct ccsr_sec_mon_regs *sec_mon_regs = (void *) + (CONFIG_SYS_SEC_MON_ADDR); + + printf("SEC_MON state transitioning to Soft Fail.\n"); + sec_mon_setbits32(&sec_mon_regs->hp_com, HPCOMR_SW_FSV); + + /* polling loop till SEC_MON is in Soft-Fail state */ + while (timeout) { + sts = get_sec_mon_state(); + + if ((sts & HPSR_SSM_ST_MASK) == + HPSR_SSM_ST_SOFT_FAIL) break; - default: - return -1; - } + + udelay(10); + timeout--; } + if (timeout == 0) { + printf("SEC_MON state transition timeout.\n"); + return -1; + } return 0; } + +int set_sec_mon_state(u32 state) +{ + int ret = -1; + + switch (state) { + case HPSR_SSM_ST_NON_SECURE: + ret = set_sec_mon_state_non_sec(); + break; + case HPSR_SSM_ST_SOFT_FAIL: + ret = set_sec_mon_state_soft_fail(); + break; + default: + printf("SEC_MON state transition not supported.\n"); + return 0; + } + + return ret; +} diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 399055b0781..cd083f7dde8 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -31,6 +31,7 @@ #include <pci.h> #include <pci_rom.h> #include <vbe.h> +#include <video.h> #include <video_fb.h> #include <linux/screen_info.h> @@ -348,3 +349,64 @@ err: free(ram); return ret; } + +#ifdef CONFIG_DM_VIDEO +int vbe_setup_video_priv(struct vesa_mode_info *vesa, + struct video_priv *uc_priv, + struct video_uc_platdata *plat) +{ + if (!vesa->x_resolution) + return -ENXIO; + uc_priv->xsize = vesa->x_resolution; + uc_priv->ysize = vesa->y_resolution; + switch (vesa->bits_per_pixel) { + case 32: + case 24: + uc_priv->bpix = VIDEO_BPP32; + break; + case 16: + uc_priv->bpix = VIDEO_BPP16; + break; + default: + return -EPROTONOSUPPORT; + } + plat->base = vesa->phys_base_ptr; + plat->size = vesa->bytes_per_scanline * vesa->y_resolution; + + return 0; +} + +int vbe_setup_video(struct udevice *dev, int (*int15_handler)(void)) +{ + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + int ret; + + printf("Video: "); + + /* If we are running from EFI or coreboot, this can't work */ + if (!ll_boot_init()) { + printf("Not available (previous bootloader prevents it)\n"); + return -EPERM; + } + bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); + ret = dm_pci_run_vga_bios(dev, int15_handler, PCI_ROM_USE_NATIVE | + PCI_ROM_ALLOW_FALLBACK); + bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); + if (ret) { + debug("failed to run video BIOS: %d\n", ret); + return ret; + } + + ret = vbe_setup_video_priv(&mode_info.vesa, uc_priv, plat); + if (ret) { + debug("No video mode configured\n"); + return ret; + } + + printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, + mode_info.vesa.bits_per_pixel); + + return 0; +} +#endif diff --git a/drivers/power/regulator/fixed.c b/drivers/power/regulator/fixed.c index 37b8400903f..62dc47f7698 100644 --- a/drivers/power/regulator/fixed.c +++ b/drivers/power/regulator/fixed.c @@ -37,11 +37,15 @@ static int fixed_regulator_ofdata_to_platdata(struct udevice *dev) /* Set type to fixed */ uc_pdata->type = REGULATOR_TYPE_FIXED; - /* Get fixed regulator gpio desc */ + /* Get fixed regulator optional enable GPIO desc */ gpio = &dev_pdata->gpio; ret = gpio_request_by_name(dev, "gpio", 0, gpio, GPIOD_IS_OUT); - if (ret) - debug("Fixed regulator gpio - not found! Error: %d", ret); + if (ret) { + debug("Fixed regulator optional enable GPIO - not found! Error: %d\n", + ret); + if (ret != -ENOENT) + return ret; + } /* Get optional ramp up delay */ dev_pdata->startup_delay_us = fdtdec_get_uint(gd->fdt_blob, @@ -87,8 +91,9 @@ static bool fixed_regulator_get_enable(struct udevice *dev) { struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev); + /* Enable GPIO is optional */ if (!dev_pdata->gpio.dev) - return false; + return true; return dm_gpio_get_value(&dev_pdata->gpio); } @@ -98,8 +103,12 @@ static int fixed_regulator_set_enable(struct udevice *dev, bool enable) struct fixed_regulator_platdata *dev_pdata = dev_get_platdata(dev); int ret; - if (!dev_pdata->gpio.dev) - return -ENOSYS; + /* Enable GPIO is optional */ + if (!dev_pdata->gpio.dev) { + if (!enable) + return -ENOSYS; + return 0; + } ret = dm_gpio_set_value(&dev_pdata->gpio, enable); if (ret) { diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 4fcc0d95b4f..c42b0bcf0ed 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,4 +34,13 @@ config TEGRA186_RESET Enable support for manipulating Tegra's on-SoC reset signals via IPC requests to the BPMP (Boot and Power Management Processor). +config RESET_UNIPHIER + bool "Reset controller driver for UniPhier SoCs" + depends on ARCH_UNIPHIER + default y + help + Support for reset controllers on UniPhier SoCs. + Say Y if you want to control reset signals provided by System Control + block, Media I/O block, Peripheral Block. + endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 5d4ea3d79dc..5c4305cc1d5 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset.o obj-$(CONFIG_SANDBOX_MBOX) += sandbox-reset-test.o obj-$(CONFIG_TEGRA_CAR_RESET) += tegra-car-reset.o obj-$(CONFIG_TEGRA186_RESET) += tegra186-reset.o +obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c new file mode 100644 index 00000000000..29c4d4db97e --- /dev/null +++ b/drivers/reset/reset-uniphier.c @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2016 Socionext Inc. + * Author: Masahiro Yamada <yamada.masahiro@socionext.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <reset-uclass.h> +#include <dm/device.h> +#include <linux/bitops.h> +#include <linux/io.h> +#include <linux/sizes.h> + +struct uniphier_reset_data { + unsigned int id; + unsigned int reg; + unsigned int bit; + unsigned int flags; +#define UNIPHIER_RESET_ACTIVE_LOW BIT(0) +}; + +#define UNIPHIER_RESET_ID_END (unsigned int)(-1) + +#define UNIPHIER_RESET_END \ + { .id = UNIPHIER_RESET_ID_END } + +#define UNIPHIER_RESET(_id, _reg, _bit) \ + { \ + .id = (_id), \ + .reg = (_reg), \ + .bit = (_bit), \ + } + +#define UNIPHIER_RESETX(_id, _reg, _bit) \ + { \ + .id = (_id), \ + .reg = (_reg), \ + .bit = (_bit), \ + .flags = UNIPHIER_RESET_ACTIVE_LOW, \ + } + +/* System reset data */ +#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \ + UNIPHIER_RESETX((id), 0x2000, 10) + +#define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \ + UNIPHIER_RESETX((id), 0x200c, 8) + +#define UNIPHIER_PRO4_SYS_RESET_GIO(id) \ + UNIPHIER_RESETX((id), 0x2000, 6) + +#define UNIPHIER_LD20_SYS_RESET_GIO(id) \ + UNIPHIER_RESETX((id), 0x200c, 5) + +#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \ + UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17) + +const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */ + UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */ + UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = { + UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */ + UNIPHIER_PRO4_SYS_RESET_USB3(14, 0), + UNIPHIER_PRO4_SYS_RESET_USB3(15, 1), + UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */ + UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */ + UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */ + UNIPHIER_RESETX(20, 0x2014, 5), /* USB31-PHY0 */ + UNIPHIER_RESETX(21, 0x2014, 1), /* USB31-PHY1 */ + UNIPHIER_RESETX(28, 0x2014, 12), /* SATA */ + UNIPHIER_RESET(29, 0x2014, 8), /* SATA-PHY (active high) */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = { + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */ + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = { + UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */ + UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */ + UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */ + UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */ + UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */ + UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */ + UNIPHIER_RESET_END, +}; + +/* Media I/O reset data */ +#define UNIPHIER_MIO_RESET_SD(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_SD_BRIDGE(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 26) + +#define UNIPHIER_MIO_RESET_EMMC_HW_RESET(id, ch) \ + UNIPHIER_RESETX((id), 0x80 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_USB2(id, ch) \ + UNIPHIER_RESETX((id), 0x114 + 0x200 * (ch), 0) + +#define UNIPHIER_MIO_RESET_USB2_BRIDGE(id, ch) \ + UNIPHIER_RESETX((id), 0x110 + 0x200 * (ch), 24) + +#define UNIPHIER_MIO_RESET_DMAC(id) \ + UNIPHIER_RESETX((id), 0x110, 17) + +const struct uniphier_reset_data uniphier_mio_reset_data[] = { + UNIPHIER_MIO_RESET_SD(0, 0), + UNIPHIER_MIO_RESET_SD(1, 1), + UNIPHIER_MIO_RESET_SD(2, 2), + UNIPHIER_MIO_RESET_SD_BRIDGE(3, 0), + UNIPHIER_MIO_RESET_SD_BRIDGE(4, 1), + UNIPHIER_MIO_RESET_SD_BRIDGE(5, 2), + UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1), + UNIPHIER_MIO_RESET_DMAC(7), + UNIPHIER_MIO_RESET_USB2(8, 0), + UNIPHIER_MIO_RESET_USB2(9, 1), + UNIPHIER_MIO_RESET_USB2(10, 2), + UNIPHIER_MIO_RESET_USB2(11, 3), + UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0), + UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1), + UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2), + UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3), + UNIPHIER_RESET_END, +}; + +/* Peripheral reset data */ +#define UNIPHIER_PERI_RESET_UART(id, ch) \ + UNIPHIER_RESETX((id), 0x114, 19 + (ch)) + +#define UNIPHIER_PERI_RESET_I2C(id, ch) \ + UNIPHIER_RESETX((id), 0x114, 5 + (ch)) + +#define UNIPHIER_PERI_RESET_FI2C(id, ch) \ + UNIPHIER_RESETX((id), 0x114, 24 + (ch)) + +const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = { + UNIPHIER_PERI_RESET_UART(0, 0), + UNIPHIER_PERI_RESET_UART(1, 1), + UNIPHIER_PERI_RESET_UART(2, 2), + UNIPHIER_PERI_RESET_UART(3, 3), + UNIPHIER_PERI_RESET_I2C(4, 0), + UNIPHIER_PERI_RESET_I2C(5, 1), + UNIPHIER_PERI_RESET_I2C(6, 2), + UNIPHIER_PERI_RESET_I2C(7, 3), + UNIPHIER_PERI_RESET_I2C(8, 4), + UNIPHIER_RESET_END, +}; + +const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = { + UNIPHIER_PERI_RESET_UART(0, 0), + UNIPHIER_PERI_RESET_UART(1, 1), + UNIPHIER_PERI_RESET_UART(2, 2), + UNIPHIER_PERI_RESET_UART(3, 3), + UNIPHIER_PERI_RESET_FI2C(4, 0), + UNIPHIER_PERI_RESET_FI2C(5, 1), + UNIPHIER_PERI_RESET_FI2C(6, 2), + UNIPHIER_PERI_RESET_FI2C(7, 3), + UNIPHIER_PERI_RESET_FI2C(8, 4), + UNIPHIER_PERI_RESET_FI2C(9, 5), + UNIPHIER_PERI_RESET_FI2C(10, 6), + UNIPHIER_RESET_END, +}; + +/* core implementaton */ +struct uniphier_reset_priv { + void __iomem *base; + const struct uniphier_reset_data *data; +}; + +static int uniphier_reset_request(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int uniphier_reset_free(struct reset_ctl *reset_ctl) +{ + return 0; +} + +static int uniphier_reset_update(struct reset_ctl *reset_ctl, int assert) +{ + struct uniphier_reset_priv *priv = dev_get_priv(reset_ctl->dev); + unsigned long id = reset_ctl->id; + const struct uniphier_reset_data *p; + + for (p = priv->data; p->id != UNIPHIER_RESET_ID_END; p++) { + u32 mask, val; + + if (p->id != id) + continue; + + val = readl(priv->base + p->reg); + + if (p->flags & UNIPHIER_RESET_ACTIVE_LOW) + assert = !assert; + + mask = BIT(p->bit); + + if (assert) + val |= mask; + else + val &= ~mask; + + writel(val, priv->base + p->reg); + + return 0; + } + + dev_err(priv->dev, "reset_id=%lu was not handled\n", id); + return -EINVAL; +} + +static int uniphier_reset_assert(struct reset_ctl *reset_ctl) +{ + return uniphier_reset_update(reset_ctl, 1); +} + +static int uniphier_reset_deassert(struct reset_ctl *reset_ctl) +{ + return uniphier_reset_update(reset_ctl, 0); +} + +static const struct reset_ops uniphier_reset_ops = { + .request = uniphier_reset_request, + .free = uniphier_reset_free, + .rst_assert = uniphier_reset_assert, + .rst_deassert = uniphier_reset_deassert, +}; + +static int uniphier_reset_probe(struct udevice *dev) +{ + struct uniphier_reset_priv *priv = dev_get_priv(dev); + fdt_addr_t addr; + + addr = dev_get_addr(dev->parent); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->base = devm_ioremap(dev, addr, SZ_4K); + if (!priv->base) + return -ENOMEM; + + priv->data = (void *)dev_get_driver_data(dev); + + return 0; +} + +static const struct udevice_id uniphier_reset_match[] = { + /* System reset */ + { + .compatible = "socionext,uniphier-sld3-reset", + .data = (ulong)uniphier_sld3_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-ld4-reset", + .data = (ulong)uniphier_sld3_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-pro4-reset", + .data = (ulong)uniphier_pro4_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-sld8-reset", + .data = (ulong)uniphier_sld3_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-reset", + .data = (ulong)uniphier_pro5_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-reset", + .data = (ulong)uniphier_pxs2_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-ld11-reset", + .data = (ulong)uniphier_ld11_sys_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-reset", + .data = (ulong)uniphier_ld20_sys_reset_data, + }, + /* Media I/O reset */ + { + .compatible = "socionext,uniphier-sld3-mio-clock", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-ld4-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-pro4-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-sld8-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-ld11-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-mio-reset", + .data = (ulong)uniphier_mio_reset_data, + }, + /* Peripheral reset */ + { + .compatible = "socionext,uniphier-ld4-peri-reset", + .data = (ulong)uniphier_ld4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-pro4-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-sld8-peri-reset", + .data = (ulong)uniphier_ld4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-pro5-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-pxs2-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-ld11-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { + .compatible = "socionext,uniphier-ld20-peri-reset", + .data = (ulong)uniphier_pro4_peri_reset_data, + }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(uniphier_reset) = { + .name = "uniphier-reset", + .id = UCLASS_RESET, + .of_match = uniphier_reset_match, + .probe = uniphier_reset_probe, + .priv_auto_alloc_size = sizeof(struct uniphier_reset_priv), + .ops = &uniphier_reset_ops, +}; diff --git a/drivers/rtc/mc146818.c b/drivers/rtc/mc146818.c index da804d54595..4df9eda086f 100644 --- a/drivers/rtc/mc146818.c +++ b/drivers/rtc/mc146818.c @@ -14,7 +14,7 @@ #include <dm.h> #include <rtc.h> -#if defined(__I386__) || defined(CONFIG_MALTA) +#if defined(CONFIG_X86) || defined(CONFIG_MALTA) #include <asm/io.h> #define in8(p) inb(p) #define out8(p, v) outb(v, p) diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 2144fca665e..729ded9a050 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -865,6 +865,7 @@ static inline struct fsl_qspi *to_qspi_spi(struct spi_slave *slave) struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, unsigned int max_hz, unsigned int mode) { + u32 mcr_val; struct fsl_qspi *qspi; struct fsl_qspi_regs *regs; u32 total_size; @@ -896,8 +897,10 @@ struct spi_slave *spi_setup_slave(unsigned int bus, unsigned int cs, qspi->slave.max_write_size = TX_BUFFER_SIZE; + mcr_val = qspi_read32(qspi->priv.flags, ®s->mcr); qspi_write32(qspi->priv.flags, ®s->mcr, - QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK); + QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK | + (mcr_val & QSPI_MCR_END_CFD_MASK)); qspi_cfg_smpr(&qspi->priv, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK | @@ -975,6 +978,7 @@ static int fsl_qspi_child_pre_probe(struct udevice *dev) static int fsl_qspi_probe(struct udevice *bus) { + u32 mcr_val; u32 amba_size_per_chip; struct fsl_qspi_platdata *plat = dev_get_platdata(bus); struct fsl_qspi_priv *priv = dev_get_priv(bus); @@ -999,8 +1003,10 @@ static int fsl_qspi_probe(struct udevice *bus) priv->flash_num = plat->flash_num; priv->num_chipselect = plat->num_chipselect; + mcr_val = qspi_read32(priv->flags, &priv->regs->mcr); qspi_write32(priv->flags, &priv->regs->mcr, - QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK); + QSPI_MCR_RESERVED_MASK | QSPI_MCR_MDIS_MASK | + (mcr_val & QSPI_MCR_END_CFD_MASK)); qspi_cfg_smpr(priv, ~(QSPI_SMPR_FSDLY_MASK | QSPI_SMPR_DDRSMP_MASK | QSPI_SMPR_FSPHS_MASK | QSPI_SMPR_HSENA_MASK), 0); diff --git a/drivers/tpm/tpm_tis_lpc.c b/drivers/tpm/tpm_tis_lpc.c index 257d035d726..b4efbb5033f 100644 --- a/drivers/tpm/tpm_tis_lpc.c +++ b/drivers/tpm/tpm_tis_lpc.c @@ -204,7 +204,7 @@ static int tis_senddata(struct udevice *dev, const u8 *data, size_t len) /* Wait till the device is ready to accept more data. */ while (!burst) { if (max_cycles++ == MAX_DELAY_US) { - printf("%s:%d failed to feed %d bytes of %d\n", + printf("%s:%d failed to feed %zd bytes of %zd\n", __FILE__, __LINE__, len - offset, len); return -ETIMEDOUT; } @@ -224,7 +224,7 @@ static int tis_senddata(struct udevice *dev, const u8 *data, size_t len) * changes to zero exactly after the last byte is fed into the * FIFO. */ - count = min((u32)burst, len - offset - 1); + count = min((size_t)burst, len - offset - 1); while (count--) tpm_write_byte(priv, data[offset++], ®s[locality].data); diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 6fc24792af9..f20fc3354cc 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -32,8 +32,8 @@ static void ehci_pci_init(struct udevice *dev, struct ehci_hccr **ret_hccr, hcor = (struct ehci_hcor *)((uintptr_t) hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase))); - debug("EHCI-PCI init hccr 0x%x and hcor 0x%x hc_length %d\n", - (u32)hccr, (u32)hcor, + debug("EHCI-PCI init hccr %#lx and hcor %#lx hc_length %d\n", + (ulong)hccr, (ulong)hcor, (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase))); *ret_hccr = hccr; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8361a717e76..86db0dac5a6 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -101,6 +101,15 @@ config VIDCONSOLE_AS_LCD to update the environment, the breakage may be confusing for users. This option will be removed around the end of 2016. +config VIDEO_COREBOOT + bool "Enable coreboot framebuffer driver support" + depends on X86 && SYS_COREBOOT + help + Turn on this option to enable a framebuffer driver when U-Boot is + loaded by coreboot where the graphics device is configured by + coreboot already. This can in principle be used with any platform + that coreboot supports. + config VIDEO_VESA bool "Enable VESA video driver support" default n @@ -366,7 +375,19 @@ config VIDEO_BROADWELL_IGD bool "Enable Intel Broadwell integrated graphics device" depends on X86 help - This enabled support for integrated graphics on Intel broadwell + This enables support for integrated graphics on Intel broadwell + devices. Initialisation is mostly performed by a VGA boot ROM, with + some setup handled by U-Boot itself. The graphics adaptor works as + a VESA device and supports LCD panels, eDP and LVDS outputs. + Configuration of most aspects of device operation is performed using + a special tool which configures the VGA ROM, but the graphics + resolution can be selected in U-Boot. + +config VIDEO_IVYBRIDGE_IGD + bool "Enable Intel Ivybridge integration graphics support" + depends on X86 + help + This enables support for integrated graphics on Intel ivybridge devices. Initialisation is mostly performed by a VGA boot ROM, with some setup handled by U-Boot itself. The graphics adaptor works as a VESA device and supports LCD panels, eDP and LVDS outputs. diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 3f045fe5781..4a4241750de 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_CONSOLE_TRUETYPE) += console_truetype.o fonts/ endif obj-$(CONFIG_VIDEO_BROADWELL_IGD) += broadwell_igd.o +obj-$(CONFIG_VIDEO_IVYBRIDGE_IGD) += ivybridge_igd.o obj-$(CONFIG_ATI_RADEON_FB) += ati_radeon_fb.o videomodes.o obj-$(CONFIG_ATMEL_HLCD) += atmel_hlcdfb.o @@ -36,7 +37,7 @@ obj-$(CONFIG_S6E63D6) += s6e63d6.o obj-$(CONFIG_LD9040) += ld9040.o obj-$(CONFIG_SED156X) += sed156x.o obj-$(CONFIG_VIDEO_BCM2835) += bcm2835.o -obj-$(CONFIG_VIDEO_COREBOOT) += coreboot_fb.o +obj-$(CONFIG_VIDEO_COREBOOT) += coreboot.o obj-$(CONFIG_VIDEO_CT69000) += ct69000.o videomodes.o obj-$(CONFIG_VIDEO_DA8XX) += da8xx-fb.o videomodes.o obj-$(CONFIG_VIDEO_IMX25LCDC) += imx25lcdc.o videomodes.o @@ -57,7 +58,7 @@ obj-$(CONFIG_VIDEO_SMI_LYNXEM) += smiLynxEM.o videomodes.o obj-$(CONFIG_VIDEO_SUNXI) += sunxi_display.o videomodes.o obj-$(CONFIG_VIDEO_TEGRA20) += tegra.o obj-$(CONFIG_VIDEO_VCXK) += bus_vcxk.o -obj-$(CONFIG_VIDEO_VESA) += vesa_fb.o +obj-$(CONFIG_VIDEO_VESA) += vesa.o obj-$(CONFIG_FORMIKE) += formike.o obj-$(CONFIG_LG4573) += lg4573.o obj-$(CONFIG_AM335X_LCD) += am335x-fb.o diff --git a/drivers/video/broadwell_igd.c b/drivers/video/broadwell_igd.c index 4286fd0648b..beef770f920 100644 --- a/drivers/video/broadwell_igd.c +++ b/drivers/video/broadwell_igd.c @@ -9,10 +9,8 @@ #include <common.h> #include <bios_emul.h> #include <dm.h> -#include <pci_rom.h> #include <vbe.h> #include <video.h> -#include <video_fb.h> #include <asm/cpu.h> #include <asm/intel_regs.h> #include <asm/io.h> @@ -20,11 +18,9 @@ #include <asm/arch/cpu.h> #include <asm/arch/iomap.h> #include <asm/arch/pch.h> -#include <linux/log2.h> #include "i915_reg.h" struct broadwell_igd_priv { - GraphicDevice ctfb; u8 *regs; }; @@ -664,10 +660,7 @@ static int broadwell_igd_probe(struct udevice *dev) { struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); - struct broadwell_igd_priv *priv = dev_get_priv(dev); bool is_broadwell; - GraphicDevice *gdev = &priv->ctfb; - int bits_per_pixel; int ret; if (!ll_boot_init()) { @@ -683,13 +676,9 @@ static int broadwell_igd_probe(struct udevice *dev) debug("%s: is_broadwell=%d\n", __func__, is_broadwell); ret = igd_pre_init(dev, is_broadwell); if (!ret) { - ret = dm_pci_run_vga_bios(dev, broadwell_igd_int15_handler, - PCI_ROM_USE_NATIVE | - PCI_ROM_ALLOW_FALLBACK); - if (ret) { - printf("failed to run video BIOS: %d\n", ret); - ret = -EIO; - } + ret = vbe_setup_video(dev, broadwell_igd_int15_handler); + if (ret) + debug("failed to run video BIOS: %d\n", ret); } if (!ret) ret = igd_post_init(dev, is_broadwell); @@ -697,13 +686,8 @@ static int broadwell_igd_probe(struct udevice *dev) if (ret) return ret; - if (vbe_get_video_info(gdev)) { - printf("No video mode configured\n"); - return -ENXIO; - } - - /* Use write-through for the graphics memory, 256MB */ - ret = mtrr_add_request(MTRR_TYPE_WRTHROUGH, gdev->pciBase, 256 << 20); + /* Use write-combining for the graphics memory, 256MB */ + ret = mtrr_add_request(MTRR_TYPE_WRCOMB, plat->base, 256 << 20); if (!ret) ret = mtrr_commit(true); if (ret && ret != -ENOSYS) { @@ -711,17 +695,8 @@ static int broadwell_igd_probe(struct udevice *dev) ret); } - bits_per_pixel = gdev->gdfBytesPP * 8; - sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY, - bits_per_pixel); - printf("%s\n", gdev->modeIdent); - uc_priv->xsize = gdev->winSizeX; - uc_priv->ysize = gdev->winSizeY; - uc_priv->bpix = ilog2(bits_per_pixel); - plat->base = gdev->pciBase; - plat->size = gdev->memSize; - debug("fb=%x, size %x, display size=%d %d %d\n", gdev->pciBase, - gdev->memSize, uc_priv->xsize, uc_priv->ysize, uc_priv->bpix); + debug("fb=%lx, size %x, display size=%d %d %d\n", plat->base, + plat->size, uc_priv->xsize, uc_priv->ysize, uc_priv->bpix); return 0; } diff --git a/drivers/video/coreboot.c b/drivers/video/coreboot.c new file mode 100644 index 00000000000..3a94aa14728 --- /dev/null +++ b/drivers/video/coreboot.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <vbe.h> +#include <video.h> +#include <asm/arch/sysinfo.h> + +static int save_vesa_mode(struct cb_framebuffer *fb, + struct vesa_mode_info *vesa) +{ + /* + * If there is no framebuffer structure, bail out and keep + * running on the serial console. + */ + if (!fb) + return -ENXIO; + + vesa->x_resolution = fb->x_resolution; + vesa->y_resolution = fb->y_resolution; + vesa->bits_per_pixel = fb->bits_per_pixel; + vesa->bytes_per_scanline = fb->bytes_per_line; + vesa->phys_base_ptr = fb->physical_address; + vesa->red_mask_size = fb->red_mask_size; + vesa->red_mask_pos = fb->red_mask_pos; + vesa->green_mask_size = fb->green_mask_size; + vesa->green_mask_pos = fb->green_mask_pos; + vesa->blue_mask_size = fb->blue_mask_size; + vesa->blue_mask_pos = fb->blue_mask_pos; + vesa->reserved_mask_size = fb->reserved_mask_size; + vesa->reserved_mask_pos = fb->reserved_mask_pos; + + return 0; +} + +static int coreboot_video_probe(struct udevice *dev) +{ + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); + struct cb_framebuffer *fb = lib_sysinfo.framebuffer; + struct vesa_mode_info *vesa = &mode_info.vesa; + int ret; + + printf("Video: "); + + /* Initialize vesa_mode_info structure */ + ret = save_vesa_mode(fb, vesa); + if (ret) + goto err; + + ret = vbe_setup_video_priv(vesa, uc_priv, plat); + if (ret) + goto err; + + printf("%dx%dx%d\n", uc_priv->xsize, uc_priv->ysize, + vesa->bits_per_pixel); + + return 0; + +err: + printf("No video mode configured in coreboot!\n"); + return ret; +} + +static const struct udevice_id coreboot_video_ids[] = { + { .compatible = "coreboot-fb" }, + { } +}; + +U_BOOT_DRIVER(coreboot_video) = { + .name = "coreboot_video", + .id = UCLASS_VIDEO, + .of_match = coreboot_video_ids, + .probe = coreboot_video_probe, +}; diff --git a/drivers/video/coreboot_fb.c b/drivers/video/coreboot_fb.c deleted file mode 100644 index feb5463f478..00000000000 --- a/drivers/video/coreboot_fb.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * coreboot Framebuffer driver. - * - * Copyright (C) 2011 The Chromium OS authors - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <asm/arch/sysinfo.h> -#include <vbe.h> -#include <video_fb.h> -#include "videomodes.h" - -/* - * The Graphic Device - */ -GraphicDevice ctfb; - -static void save_vesa_mode(void) -{ - struct vesa_mode_info *vesa = &mode_info.vesa; - struct cb_framebuffer *fb = lib_sysinfo.framebuffer; - - vesa->x_resolution = fb->x_resolution; - vesa->y_resolution = fb->y_resolution; - vesa->bits_per_pixel = fb->bits_per_pixel; - vesa->bytes_per_scanline = fb->bytes_per_line; - vesa->phys_base_ptr = fb->physical_address; - vesa->red_mask_size = fb->red_mask_size; - vesa->red_mask_pos = fb->red_mask_pos; - vesa->green_mask_size = fb->green_mask_size; - vesa->green_mask_pos = fb->green_mask_pos; - vesa->blue_mask_size = fb->blue_mask_size; - vesa->blue_mask_pos = fb->blue_mask_pos; - vesa->reserved_mask_size = fb->reserved_mask_size; - vesa->reserved_mask_pos = fb->reserved_mask_pos; -} - -static int parse_coreboot_table_fb(GraphicDevice *gdev) -{ - struct cb_framebuffer *fb = lib_sysinfo.framebuffer; - - /* If there is no framebuffer structure, bail out and keep - * running on the serial console. - */ - if (!fb) - return 0; - - gdev->winSizeX = fb->x_resolution; - gdev->winSizeY = fb->y_resolution; - - gdev->plnSizeX = fb->x_resolution; - gdev->plnSizeY = fb->y_resolution; - - gdev->gdfBytesPP = fb->bits_per_pixel / 8; - - switch (fb->bits_per_pixel) { - case 24: - gdev->gdfIndex = GDF_32BIT_X888RGB; - break; - case 16: - gdev->gdfIndex = GDF_16BIT_565RGB; - break; - default: - gdev->gdfIndex = GDF__8BIT_INDEX; - break; - } - - gdev->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS; - gdev->pciBase = (unsigned int)fb->physical_address; - - gdev->frameAdrs = (unsigned int)fb->physical_address; - gdev->memSize = fb->bytes_per_line * fb->y_resolution; - - gdev->vprBase = (unsigned int)fb->physical_address; - gdev->cprBase = (unsigned int)fb->physical_address; - - return 1; -} - -void *video_hw_init(void) -{ - GraphicDevice *gdev = &ctfb; - int bits_per_pixel; - - printf("Video: "); - - if (!parse_coreboot_table_fb(gdev)) { - printf("No video mode configured in coreboot!\n"); - return NULL; - } - - bits_per_pixel = gdev->gdfBytesPP * 8; - - /* fill in Graphic device struct */ - sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY, - bits_per_pixel); - printf("%s\n", gdev->modeIdent); - - memset((void *)gdev->pciBase, 0, - gdev->winSizeX * gdev->winSizeY * gdev->gdfBytesPP); - - /* Initialize vesa_mode_info structure */ - save_vesa_mode(); - - return (void *)gdev; -} diff --git a/drivers/video/ivybridge_igd.c b/drivers/video/ivybridge_igd.c new file mode 100644 index 00000000000..94db3dda442 --- /dev/null +++ b/drivers/video/ivybridge_igd.c @@ -0,0 +1,843 @@ +/* + * Copyright (C) 2016 Google, Inc + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <bios_emul.h> +#include <dm.h> +#include <errno.h> +#include <fdtdec.h> +#include <pci_rom.h> +#include <vbe.h> +#include <asm/intel_regs.h> +#include <asm/io.h> +#include <asm/mtrr.h> +#include <asm/pci.h> +#include <asm/arch/pch.h> +#include <asm/arch/sandybridge.h> + +struct gt_powermeter { + u16 reg; + u32 value; +}; + +/* These are magic values - unfortunately the meaning is unknown */ +static const struct gt_powermeter snb_pm_gt1[] = { + { 0xa200, 0xcc000000 }, + { 0xa204, 0x07000040 }, + { 0xa208, 0x0000fe00 }, + { 0xa20c, 0x00000000 }, + { 0xa210, 0x17000000 }, + { 0xa214, 0x00000021 }, + { 0xa218, 0x0817fe19 }, + { 0xa21c, 0x00000000 }, + { 0xa220, 0x00000000 }, + { 0xa224, 0xcc000000 }, + { 0xa228, 0x07000040 }, + { 0xa22c, 0x0000fe00 }, + { 0xa230, 0x00000000 }, + { 0xa234, 0x17000000 }, + { 0xa238, 0x00000021 }, + { 0xa23c, 0x0817fe19 }, + { 0xa240, 0x00000000 }, + { 0xa244, 0x00000000 }, + { 0xa248, 0x8000421e }, + { 0 } +}; + +static const struct gt_powermeter snb_pm_gt2[] = { + { 0xa200, 0x330000a6 }, + { 0xa204, 0x402d0031 }, + { 0xa208, 0x00165f83 }, + { 0xa20c, 0xf1000000 }, + { 0xa210, 0x00000000 }, + { 0xa214, 0x00160016 }, + { 0xa218, 0x002a002b }, + { 0xa21c, 0x00000000 }, + { 0xa220, 0x00000000 }, + { 0xa224, 0x330000a6 }, + { 0xa228, 0x402d0031 }, + { 0xa22c, 0x00165f83 }, + { 0xa230, 0xf1000000 }, + { 0xa234, 0x00000000 }, + { 0xa238, 0x00160016 }, + { 0xa23c, 0x002a002b }, + { 0xa240, 0x00000000 }, + { 0xa244, 0x00000000 }, + { 0xa248, 0x8000421e }, + { 0 } +}; + +static const struct gt_powermeter ivb_pm_gt1[] = { + { 0xa800, 0x00000000 }, + { 0xa804, 0x00021c00 }, + { 0xa808, 0x00000403 }, + { 0xa80c, 0x02001700 }, + { 0xa810, 0x05000200 }, + { 0xa814, 0x00000000 }, + { 0xa818, 0x00690500 }, + { 0xa81c, 0x0000007f }, + { 0xa820, 0x01002501 }, + { 0xa824, 0x00000300 }, + { 0xa828, 0x01000331 }, + { 0xa82c, 0x0000000c }, + { 0xa830, 0x00010016 }, + { 0xa834, 0x01100101 }, + { 0xa838, 0x00010103 }, + { 0xa83c, 0x00041300 }, + { 0xa840, 0x00000b30 }, + { 0xa844, 0x00000000 }, + { 0xa848, 0x7f000000 }, + { 0xa84c, 0x05000008 }, + { 0xa850, 0x00000001 }, + { 0xa854, 0x00000004 }, + { 0xa858, 0x00000007 }, + { 0xa85c, 0x00000000 }, + { 0xa860, 0x00010000 }, + { 0xa248, 0x0000221e }, + { 0xa900, 0x00000000 }, + { 0xa904, 0x00001c00 }, + { 0xa908, 0x00000000 }, + { 0xa90c, 0x06000000 }, + { 0xa910, 0x09000200 }, + { 0xa914, 0x00000000 }, + { 0xa918, 0x00590000 }, + { 0xa91c, 0x00000000 }, + { 0xa920, 0x04002501 }, + { 0xa924, 0x00000100 }, + { 0xa928, 0x03000410 }, + { 0xa92c, 0x00000000 }, + { 0xa930, 0x00020000 }, + { 0xa934, 0x02070106 }, + { 0xa938, 0x00010100 }, + { 0xa93c, 0x00401c00 }, + { 0xa940, 0x00000000 }, + { 0xa944, 0x00000000 }, + { 0xa948, 0x10000e00 }, + { 0xa94c, 0x02000004 }, + { 0xa950, 0x00000001 }, + { 0xa954, 0x00000004 }, + { 0xa960, 0x00060000 }, + { 0xaa3c, 0x00001c00 }, + { 0xaa54, 0x00000004 }, + { 0xaa60, 0x00060000 }, + { 0 } +}; + +static const struct gt_powermeter ivb_pm_gt2[] = { + { 0xa800, 0x10000000 }, + { 0xa804, 0x00033800 }, + { 0xa808, 0x00000902 }, + { 0xa80c, 0x0c002f00 }, + { 0xa810, 0x12000400 }, + { 0xa814, 0x00000000 }, + { 0xa818, 0x00d20800 }, + { 0xa81c, 0x00000002 }, + { 0xa820, 0x03004b02 }, + { 0xa824, 0x00000600 }, + { 0xa828, 0x07000773 }, + { 0xa82c, 0x00000000 }, + { 0xa830, 0x00010032 }, + { 0xa834, 0x1520040d }, + { 0xa838, 0x00020105 }, + { 0xa83c, 0x00083700 }, + { 0xa840, 0x0000151d }, + { 0xa844, 0x00000000 }, + { 0xa848, 0x20001b00 }, + { 0xa84c, 0x0a000010 }, + { 0xa850, 0x00000000 }, + { 0xa854, 0x00000008 }, + { 0xa858, 0x00000008 }, + { 0xa85c, 0x00000000 }, + { 0xa860, 0x00020000 }, + { 0xa248, 0x0000221e }, + { 0xa900, 0x00000000 }, + { 0xa904, 0x00003500 }, + { 0xa908, 0x00000000 }, + { 0xa90c, 0x0c000000 }, + { 0xa910, 0x12000500 }, + { 0xa914, 0x00000000 }, + { 0xa918, 0x00b20000 }, + { 0xa91c, 0x00000000 }, + { 0xa920, 0x08004b02 }, + { 0xa924, 0x00000200 }, + { 0xa928, 0x07000820 }, + { 0xa92c, 0x00000000 }, + { 0xa930, 0x00030000 }, + { 0xa934, 0x050f020d }, + { 0xa938, 0x00020300 }, + { 0xa93c, 0x00903900 }, + { 0xa940, 0x00000000 }, + { 0xa944, 0x00000000 }, + { 0xa948, 0x20001b00 }, + { 0xa94c, 0x0a000010 }, + { 0xa950, 0x00000000 }, + { 0xa954, 0x00000008 }, + { 0xa960, 0x00110000 }, + { 0xaa3c, 0x00003900 }, + { 0xaa54, 0x00000008 }, + { 0xaa60, 0x00110000 }, + { 0 } +}; + +static const struct gt_powermeter ivb_pm_gt2_17w[] = { + { 0xa800, 0x20000000 }, + { 0xa804, 0x000e3800 }, + { 0xa808, 0x00000806 }, + { 0xa80c, 0x0c002f00 }, + { 0xa810, 0x0c000800 }, + { 0xa814, 0x00000000 }, + { 0xa818, 0x00d20d00 }, + { 0xa81c, 0x000000ff }, + { 0xa820, 0x03004b02 }, + { 0xa824, 0x00000600 }, + { 0xa828, 0x07000773 }, + { 0xa82c, 0x00000000 }, + { 0xa830, 0x00020032 }, + { 0xa834, 0x1520040d }, + { 0xa838, 0x00020105 }, + { 0xa83c, 0x00083700 }, + { 0xa840, 0x000016ff }, + { 0xa844, 0x00000000 }, + { 0xa848, 0xff000000 }, + { 0xa84c, 0x0a000010 }, + { 0xa850, 0x00000002 }, + { 0xa854, 0x00000008 }, + { 0xa858, 0x0000000f }, + { 0xa85c, 0x00000000 }, + { 0xa860, 0x00020000 }, + { 0xa248, 0x0000221e }, + { 0xa900, 0x00000000 }, + { 0xa904, 0x00003800 }, + { 0xa908, 0x00000000 }, + { 0xa90c, 0x0c000000 }, + { 0xa910, 0x12000800 }, + { 0xa914, 0x00000000 }, + { 0xa918, 0x00b20000 }, + { 0xa91c, 0x00000000 }, + { 0xa920, 0x08004b02 }, + { 0xa924, 0x00000300 }, + { 0xa928, 0x01000820 }, + { 0xa92c, 0x00000000 }, + { 0xa930, 0x00030000 }, + { 0xa934, 0x15150406 }, + { 0xa938, 0x00020300 }, + { 0xa93c, 0x00903900 }, + { 0xa940, 0x00000000 }, + { 0xa944, 0x00000000 }, + { 0xa948, 0x20001b00 }, + { 0xa94c, 0x0a000010 }, + { 0xa950, 0x00000000 }, + { 0xa954, 0x00000008 }, + { 0xa960, 0x00110000 }, + { 0xaa3c, 0x00003900 }, + { 0xaa54, 0x00000008 }, + { 0xaa60, 0x00110000 }, + { 0 } +}; + +static const struct gt_powermeter ivb_pm_gt2_35w[] = { + { 0xa800, 0x00000000 }, + { 0xa804, 0x00030400 }, + { 0xa808, 0x00000806 }, + { 0xa80c, 0x0c002f00 }, + { 0xa810, 0x0c000300 }, + { 0xa814, 0x00000000 }, + { 0xa818, 0x00d20d00 }, + { 0xa81c, 0x000000ff }, + { 0xa820, 0x03004b02 }, + { 0xa824, 0x00000600 }, + { 0xa828, 0x07000773 }, + { 0xa82c, 0x00000000 }, + { 0xa830, 0x00020032 }, + { 0xa834, 0x1520040d }, + { 0xa838, 0x00020105 }, + { 0xa83c, 0x00083700 }, + { 0xa840, 0x000016ff }, + { 0xa844, 0x00000000 }, + { 0xa848, 0xff000000 }, + { 0xa84c, 0x0a000010 }, + { 0xa850, 0x00000001 }, + { 0xa854, 0x00000008 }, + { 0xa858, 0x00000008 }, + { 0xa85c, 0x00000000 }, + { 0xa860, 0x00020000 }, + { 0xa248, 0x0000221e }, + { 0xa900, 0x00000000 }, + { 0xa904, 0x00003800 }, + { 0xa908, 0x00000000 }, + { 0xa90c, 0x0c000000 }, + { 0xa910, 0x12000800 }, + { 0xa914, 0x00000000 }, + { 0xa918, 0x00b20000 }, + { 0xa91c, 0x00000000 }, + { 0xa920, 0x08004b02 }, + { 0xa924, 0x00000300 }, + { 0xa928, 0x01000820 }, + { 0xa92c, 0x00000000 }, + { 0xa930, 0x00030000 }, + { 0xa934, 0x15150406 }, + { 0xa938, 0x00020300 }, + { 0xa93c, 0x00903900 }, + { 0xa940, 0x00000000 }, + { 0xa944, 0x00000000 }, + { 0xa948, 0x20001b00 }, + { 0xa94c, 0x0a000010 }, + { 0xa950, 0x00000000 }, + { 0xa954, 0x00000008 }, + { 0xa960, 0x00110000 }, + { 0xaa3c, 0x00003900 }, + { 0xaa54, 0x00000008 }, + { 0xaa60, 0x00110000 }, + { 0 } +}; + +static inline u32 gtt_read(void *bar, u32 reg) +{ + return readl(bar + reg); +} + +static inline void gtt_write(void *bar, u32 reg, u32 data) +{ + writel(data, bar + reg); +} + +static void gtt_write_powermeter(void *bar, const struct gt_powermeter *pm) +{ + for (; pm && pm->reg; pm++) + gtt_write(bar, pm->reg, pm->value); +} + +#define GTT_RETRY 1000 +static int gtt_poll(void *bar, u32 reg, u32 mask, u32 value) +{ + unsigned try = GTT_RETRY; + u32 data; + + while (try--) { + data = gtt_read(bar, reg); + if ((data & mask) == value) + return 1; + udelay(10); + } + + printf("GT init timeout\n"); + return 0; +} + +static int gma_pm_init_pre_vbios(void *gtt_bar, int rev) +{ + u32 reg32; + + debug("GT Power Management Init, silicon = %#x\n", rev); + + if (rev < IVB_STEP_C0) { + /* 1: Enable force wake */ + gtt_write(gtt_bar, 0xa18c, 0x00000001); + gtt_poll(gtt_bar, 0x130090, (1 << 0), (1 << 0)); + } else { + gtt_write(gtt_bar, 0xa180, 1 << 5); + gtt_write(gtt_bar, 0xa188, 0xffff0001); + gtt_poll(gtt_bar, 0x130040, (1 << 0), (1 << 0)); + } + + if ((rev & BASE_REV_MASK) == BASE_REV_SNB) { + /* 1d: Set GTT+0x42004 [15:14]=11 (SnB C1+) */ + reg32 = gtt_read(gtt_bar, 0x42004); + reg32 |= (1 << 14) | (1 << 15); + gtt_write(gtt_bar, 0x42004, reg32); + } + + if (rev >= IVB_STEP_A0) { + /* Display Reset Acknowledge Settings */ + reg32 = gtt_read(gtt_bar, 0x45010); + reg32 |= (1 << 1) | (1 << 0); + gtt_write(gtt_bar, 0x45010, reg32); + } + + /* 2: Get GT SKU from GTT+0x911c[13] */ + reg32 = gtt_read(gtt_bar, 0x911c); + if ((rev & BASE_REV_MASK) == BASE_REV_SNB) { + if (reg32 & (1 << 13)) { + debug("SNB GT1 Power Meter Weights\n"); + gtt_write_powermeter(gtt_bar, snb_pm_gt1); + } else { + debug("SNB GT2 Power Meter Weights\n"); + gtt_write_powermeter(gtt_bar, snb_pm_gt2); + } + } else { + u32 unit = readl(MCHBAR_REG(0x5938)) & 0xf; + + if (reg32 & (1 << 13)) { + /* GT1 SKU */ + debug("IVB GT1 Power Meter Weights\n"); + gtt_write_powermeter(gtt_bar, ivb_pm_gt1); + } else { + /* GT2 SKU */ + u32 tdp = readl(MCHBAR_REG(0x5930)) & 0x7fff; + tdp /= (1 << unit); + + if (tdp <= 17) { + /* <=17W ULV */ + debug("IVB GT2 17W Power Meter Weights\n"); + gtt_write_powermeter(gtt_bar, ivb_pm_gt2_17w); + } else if ((tdp >= 25) && (tdp <= 35)) { + /* 25W-35W */ + debug("IVB GT2 25W-35W Power Meter Weights\n"); + gtt_write_powermeter(gtt_bar, ivb_pm_gt2_35w); + } else { + /* All others */ + debug("IVB GT2 35W Power Meter Weights\n"); + gtt_write_powermeter(gtt_bar, ivb_pm_gt2_35w); + } + } + } + + /* 3: Gear ratio map */ + gtt_write(gtt_bar, 0xa004, 0x00000010); + + /* 4: GFXPAUSE */ + gtt_write(gtt_bar, 0xa000, 0x00070020); + + /* 5: Dynamic EU trip control */ + gtt_write(gtt_bar, 0xa080, 0x00000004); + + /* 6: ECO bits */ + reg32 = gtt_read(gtt_bar, 0xa180); + reg32 |= (1 << 26) | (1 << 31); + /* (bit 20=1 for SNB step D1+ / IVB A0+) */ + if (rev >= SNB_STEP_D1) + reg32 |= (1 << 20); + gtt_write(gtt_bar, 0xa180, reg32); + + /* 6a: for SnB step D2+ only */ + if (((rev & BASE_REV_MASK) == BASE_REV_SNB) && + (rev >= SNB_STEP_D2)) { + reg32 = gtt_read(gtt_bar, 0x9400); + reg32 |= (1 << 7); + gtt_write(gtt_bar, 0x9400, reg32); + + reg32 = gtt_read(gtt_bar, 0x941c); + reg32 &= 0xf; + reg32 |= (1 << 1); + gtt_write(gtt_bar, 0x941c, reg32); + gtt_poll(gtt_bar, 0x941c, (1 << 1), (0 << 1)); + } + + if ((rev & BASE_REV_MASK) == BASE_REV_IVB) { + reg32 = gtt_read(gtt_bar, 0x907c); + reg32 |= (1 << 16); + gtt_write(gtt_bar, 0x907c, reg32); + + /* 6b: Clocking reset controls */ + gtt_write(gtt_bar, 0x9424, 0x00000001); + } else { + /* 6b: Clocking reset controls */ + gtt_write(gtt_bar, 0x9424, 0x00000000); + } + + /* 7 */ + if (gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31))) { + gtt_write(gtt_bar, 0x138128, 0x00000029); /* Mailbox Data */ + /* Mailbox Cmd for RC6 VID */ + gtt_write(gtt_bar, 0x138124, 0x80000004); + if (gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31))) + gtt_write(gtt_bar, 0x138124, 0x8000000a); + gtt_poll(gtt_bar, 0x138124, (1 << 31), (0 << 31)); + } + + /* 8 */ + gtt_write(gtt_bar, 0xa090, 0x00000000); /* RC Control */ + gtt_write(gtt_bar, 0xa098, 0x03e80000); /* RC1e Wake Rate Limit */ + gtt_write(gtt_bar, 0xa09c, 0x0028001e); /* RC6/6p Wake Rate Limit */ + gtt_write(gtt_bar, 0xa0a0, 0x0000001e); /* RC6pp Wake Rate Limit */ + gtt_write(gtt_bar, 0xa0a8, 0x0001e848); /* RC Evaluation Interval */ + gtt_write(gtt_bar, 0xa0ac, 0x00000019); /* RC Idle Hysteresis */ + + /* 9 */ + gtt_write(gtt_bar, 0x2054, 0x0000000a); /* Render Idle Max Count */ + gtt_write(gtt_bar, 0x12054, 0x0000000a); /* Video Idle Max Count */ + gtt_write(gtt_bar, 0x22054, 0x0000000a); /* Blitter Idle Max Count */ + + /* 10 */ + gtt_write(gtt_bar, 0xa0b0, 0x00000000); /* Unblock Ack to Busy */ + gtt_write(gtt_bar, 0xa0b4, 0x000003e8); /* RC1e Threshold */ + gtt_write(gtt_bar, 0xa0b8, 0x0000c350); /* RC6 Threshold */ + gtt_write(gtt_bar, 0xa0bc, 0x000186a0); /* RC6p Threshold */ + gtt_write(gtt_bar, 0xa0c0, 0x0000fa00); /* RC6pp Threshold */ + + /* 11 */ + gtt_write(gtt_bar, 0xa010, 0x000f4240); /* RP Down Timeout */ + gtt_write(gtt_bar, 0xa014, 0x12060000); /* RP Interrupt Limits */ + gtt_write(gtt_bar, 0xa02c, 0x00015f90); /* RP Up Threshold */ + gtt_write(gtt_bar, 0xa030, 0x000186a0); /* RP Down Threshold */ + gtt_write(gtt_bar, 0xa068, 0x000186a0); /* RP Up EI */ + gtt_write(gtt_bar, 0xa06c, 0x000493e0); /* RP Down EI */ + gtt_write(gtt_bar, 0xa070, 0x0000000a); /* RP Idle Hysteresis */ + + /* 11a: Enable Render Standby (RC6) */ + if ((rev & BASE_REV_MASK) == BASE_REV_IVB) { + /* + * IvyBridge should also support DeepRenderStandby. + * + * Unfortunately it does not work reliably on all SKUs so + * disable it here and it can be enabled by the kernel. + */ + gtt_write(gtt_bar, 0xa090, 0x88040000); /* HW RC Control */ + } else { + gtt_write(gtt_bar, 0xa090, 0x88040000); /* HW RC Control */ + } + + /* 12: Normal Frequency Request */ + /* RPNFREQ_VAL comes from MCHBAR 0x5998 23:16 (8 bits!? use 7) */ + reg32 = readl(MCHBAR_REG(0x5998)); + reg32 >>= 16; + reg32 &= 0xef; + reg32 <<= 25; + gtt_write(gtt_bar, 0xa008, reg32); + + /* 13: RP Control */ + gtt_write(gtt_bar, 0xa024, 0x00000592); + + /* 14: Enable PM Interrupts */ + gtt_write(gtt_bar, 0x4402c, 0x03000076); + + /* Clear 0x6c024 [8:6] */ + reg32 = gtt_read(gtt_bar, 0x6c024); + reg32 &= ~0x000001c0; + gtt_write(gtt_bar, 0x6c024, reg32); + + return 0; +} + +static int gma_pm_init_post_vbios(struct udevice *dev, int rev, void *gtt_bar) +{ + const void *blob = gd->fdt_blob; + int node = dev->of_offset; + u32 reg32, cycle_delay; + + debug("GT Power Management Init (post VBIOS)\n"); + + /* 15: Deassert Force Wake */ + if (rev < IVB_STEP_C0) { + gtt_write(gtt_bar, 0xa18c, gtt_read(gtt_bar, 0xa18c) & ~1); + gtt_poll(gtt_bar, 0x130090, (1 << 0), (0 << 0)); + } else { + gtt_write(gtt_bar, 0xa188, 0x1fffe); + if (gtt_poll(gtt_bar, 0x130040, (1 << 0), (0 << 0))) { + gtt_write(gtt_bar, 0xa188, + gtt_read(gtt_bar, 0xa188) | 1); + } + } + + /* 16: SW RC Control */ + gtt_write(gtt_bar, 0xa094, 0x00060000); + + /* Setup Digital Port Hotplug */ + reg32 = gtt_read(gtt_bar, 0xc4030); + if (!reg32) { + u32 dp_hotplug[3]; + + if (fdtdec_get_int_array(blob, node, "intel,dp_hotplug", + dp_hotplug, ARRAY_SIZE(dp_hotplug))) + return -EINVAL; + + reg32 = (dp_hotplug[0] & 0x7) << 2; + reg32 |= (dp_hotplug[0] & 0x7) << 10; + reg32 |= (dp_hotplug[0] & 0x7) << 18; + gtt_write(gtt_bar, 0xc4030, reg32); + } + + /* Setup Panel Power On Delays */ + reg32 = gtt_read(gtt_bar, 0xc7208); + if (!reg32) { + reg32 = (unsigned)fdtdec_get_int(blob, node, + "panel-port-select", 0) << 30; + reg32 |= fdtdec_get_int(blob, node, "panel-power-up-delay", 0) + << 16; + reg32 |= fdtdec_get_int(blob, node, + "panel-power-backlight-on-delay", 0); + gtt_write(gtt_bar, 0xc7208, reg32); + } + + /* Setup Panel Power Off Delays */ + reg32 = gtt_read(gtt_bar, 0xc720c); + if (!reg32) { + reg32 = fdtdec_get_int(blob, node, "panel-power-down-delay", 0) + << 16; + reg32 |= fdtdec_get_int(blob, node, + "panel-power-backlight-off-delay", 0); + gtt_write(gtt_bar, 0xc720c, reg32); + } + + /* Setup Panel Power Cycle Delay */ + cycle_delay = fdtdec_get_int(blob, node, + "intel,panel-power-cycle-delay", 0); + if (cycle_delay) { + reg32 = gtt_read(gtt_bar, 0xc7210); + reg32 &= ~0xff; + reg32 |= cycle_delay; + gtt_write(gtt_bar, 0xc7210, reg32); + } + + /* Enable Backlight if needed */ + reg32 = fdtdec_get_int(blob, node, "intel,cpu-backlight", 0); + if (reg32) { + gtt_write(gtt_bar, 0x48250, (1 << 31)); + gtt_write(gtt_bar, 0x48254, reg32); + } + reg32 = fdtdec_get_int(blob, node, "intel,pch-backlight", 0); + if (reg32) { + gtt_write(gtt_bar, 0xc8250, (1 << 31)); + gtt_write(gtt_bar, 0xc8254, reg32); + } + + return 0; +} + +/* + * Some vga option roms are used for several chipsets but they only have one + * PCI ID in their header. If we encounter such an option rom, we need to do + * the mapping ourselves. + */ + +uint32_t board_map_oprom_vendev(uint32_t vendev) +{ + switch (vendev) { + case 0x80860102: /* GT1 Desktop */ + case 0x8086010a: /* GT1 Server */ + case 0x80860112: /* GT2 Desktop */ + case 0x80860116: /* GT2 Mobile */ + case 0x80860122: /* GT2 Desktop >=1.3GHz */ + case 0x80860126: /* GT2 Mobile >=1.3GHz */ + case 0x80860156: /* IVB */ + case 0x80860166: /* IVB */ + return 0x80860106; /* GT1 Mobile */ + } + + return vendev; +} + +static int int15_handler(void) +{ + int res = 0; + + debug("%s: INT15 function %04x!\n", __func__, M.x86.R_AX); + + switch (M.x86.R_AX) { + case 0x5f34: + /* + * Set Panel Fitting Hook: + * bit 2 = Graphics Stretching + * bit 1 = Text Stretching + * bit 0 = Centering (do not set with bit1 or bit2) + * 0 = video bios default + */ + M.x86.R_AX = 0x005f; + M.x86.R_CL = 0x00; /* Use video bios default */ + res = 1; + break; + case 0x5f35: + /* + * Boot Display Device Hook: + * bit 0 = CRT + * bit 1 = TV (eDP) + * bit 2 = EFP + * bit 3 = LFP + * bit 4 = CRT2 + * bit 5 = TV2 (eDP) + * bit 6 = EFP2 + * bit 7 = LFP2 + */ + M.x86.R_AX = 0x005f; + M.x86.R_CX = 0x0000; /* Use video bios default */ + res = 1; + break; + case 0x5f51: + /* + * Hook to select active LFP configuration: + * 00h = No LVDS, VBIOS does not enable LVDS + * 01h = Int-LVDS, LFP driven by integrated LVDS decoder + * 02h = SVDO-LVDS, LFP driven by SVDO decoder + * 03h = eDP, LFP Driven by Int-DisplayPort encoder + */ + M.x86.R_AX = 0x005f; + M.x86.R_CX = 0x0003; /* eDP */ + res = 1; + break; + case 0x5f70: + switch (M.x86.R_CH) { + case 0: + /* Get Mux */ + M.x86.R_AX = 0x005f; + M.x86.R_CX = 0x0000; + res = 1; + break; + case 1: + /* Set Mux */ + M.x86.R_AX = 0x005f; + M.x86.R_CX = 0x0000; + res = 1; + break; + case 2: + /* Get SG/Non-SG mode */ + M.x86.R_AX = 0x005f; + M.x86.R_CX = 0x0000; + res = 1; + break; + default: + /* Interrupt was not handled */ + debug("Unknown INT15 5f70 function: 0x%02x\n", + M.x86.R_CH); + break; + } + break; + case 0x5fac: + res = 1; + break; + default: + debug("Unknown INT15 function %04x!\n", M.x86.R_AX); + break; + } + return res; +} + +static void sandybridge_setup_graphics(struct udevice *dev, + struct udevice *video_dev) +{ + u32 reg32; + u16 reg16; + u8 reg8; + + dm_pci_read_config16(video_dev, PCI_DEVICE_ID, ®16); + switch (reg16) { + case 0x0102: /* GT1 Desktop */ + case 0x0106: /* GT1 Mobile */ + case 0x010a: /* GT1 Server */ + case 0x0112: /* GT2 Desktop */ + case 0x0116: /* GT2 Mobile */ + case 0x0122: /* GT2 Desktop >=1.3GHz */ + case 0x0126: /* GT2 Mobile >=1.3GHz */ + case 0x0156: /* IvyBridge */ + case 0x0166: /* IvyBridge */ + break; + default: + debug("Graphics not supported by this CPU/chipset\n"); + return; + } + + debug("Initialising Graphics\n"); + + /* Setup IGD memory by setting GGC[7:3] = 1 for 32MB */ + dm_pci_read_config16(dev, GGC, ®16); + reg16 &= ~0x00f8; + reg16 |= 1 << 3; + /* Program GTT memory by setting GGC[9:8] = 2MB */ + reg16 &= ~0x0300; + reg16 |= 2 << 8; + /* Enable VGA decode */ + reg16 &= ~0x0002; + dm_pci_write_config16(dev, GGC, reg16); + + /* Enable 256MB aperture */ + dm_pci_read_config8(video_dev, MSAC, ®8); + reg8 &= ~0x06; + reg8 |= 0x02; + dm_pci_write_config8(video_dev, MSAC, reg8); + + /* Erratum workarounds */ + reg32 = readl(MCHBAR_REG(0x5f00)); + reg32 |= (1 << 9) | (1 << 10); + writel(reg32, MCHBAR_REG(0x5f00)); + + /* Enable SA Clock Gating */ + reg32 = readl(MCHBAR_REG(0x5f00)); + writel(reg32 | 1, MCHBAR_REG(0x5f00)); + + /* GPU RC6 workaround for sighting 366252 */ + reg32 = readl(MCHBAR_REG(0x5d14)); + reg32 |= (1 << 31); + writel(reg32, MCHBAR_REG(0x5d14)); + + /* VLW */ + reg32 = readl(MCHBAR_REG(0x6120)); + reg32 &= ~(1 << 0); + writel(reg32, MCHBAR_REG(0x6120)); + + reg32 = readl(MCHBAR_REG(0x5418)); + reg32 |= (1 << 4) | (1 << 5); + writel(reg32, MCHBAR_REG(0x5418)); +} + +static int gma_func0_init(struct udevice *dev) +{ + struct udevice *nbridge; + void *gtt_bar; + ulong base; + u32 reg32; + int ret; + int rev; + + /* Enable PCH Display Port */ + writew(0x0010, RCB_REG(DISPBDF)); + setbits_le32(RCB_REG(FD2), PCH_ENABLE_DBDF); + + ret = uclass_first_device_err(UCLASS_NORTHBRIDGE, &nbridge); + if (ret) + return ret; + rev = bridge_silicon_revision(nbridge); + sandybridge_setup_graphics(nbridge, dev); + + /* IGD needs to be Bus Master */ + dm_pci_read_config32(dev, PCI_COMMAND, ®32); + reg32 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + dm_pci_write_config32(dev, PCI_COMMAND, reg32); + + /* Use write-combining for the graphics memory, 256MB */ + base = dm_pci_read_bar32(dev, 2); + mtrr_add_request(MTRR_TYPE_WRCOMB, base, 256 << 20); + mtrr_commit(true); + + gtt_bar = (void *)dm_pci_read_bar32(dev, 0); + debug("GT bar %p\n", gtt_bar); + ret = gma_pm_init_pre_vbios(gtt_bar, rev); + if (ret) + return ret; + + return rev; +} + +static int bd82x6x_video_probe(struct udevice *dev) +{ + void *gtt_bar; + int ret, rev; + + rev = gma_func0_init(dev); + if (rev < 0) + return rev; + ret = vbe_setup_video(dev, int15_handler); + if (ret) + return ret; + + /* Post VBIOS init */ + gtt_bar = (void *)dm_pci_read_bar32(dev, 0); + ret = gma_pm_init_post_vbios(dev, rev, gtt_bar); + if (ret) + return ret; + + return 0; +} + +static const struct udevice_id bd82x6x_video_ids[] = { + { .compatible = "intel,gma" }, + { } +}; + +U_BOOT_DRIVER(bd82x6x_video) = { + .name = "bd82x6x_video", + .id = UCLASS_VIDEO, + .of_match = bd82x6x_video_ids, + .probe = bd82x6x_video_probe, +}; diff --git a/drivers/video/simple_panel.c b/drivers/video/simple_panel.c index b2fe345ce3d..baa95f6a120 100644 --- a/drivers/video/simple_panel.c +++ b/drivers/video/simple_panel.c @@ -42,7 +42,7 @@ static int simple_panel_ofdata_to_platdata(struct udevice *dev) ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, "power-supply", &priv->reg); if (ret) { - debug("%s: Warning: cnnot get power supply: ret=%d\n", + debug("%s: Warning: cannot get power supply: ret=%d\n", __func__, ret); if (ret != -ENOENT) return ret; diff --git a/drivers/video/vesa.c b/drivers/video/vesa.c new file mode 100644 index 00000000000..ddf8df89930 --- /dev/null +++ b/drivers/video/vesa.c @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2016, Bin Meng <bmeng.cn@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <pci.h> +#include <vbe.h> + +static int vesa_video_probe(struct udevice *dev) +{ + return vbe_setup_video(dev, NULL); +} + +static const struct udevice_id vesa_video_ids[] = { + { .compatible = "vesa-fb" }, + { } +}; + +U_BOOT_DRIVER(vesa_video) = { + .name = "vesa_video", + .id = UCLASS_VIDEO, + .of_match = vesa_video_ids, + .probe = vesa_video_probe, +}; + +static struct pci_device_id vesa_video_supported[] = { + { PCI_DEVICE_CLASS(PCI_CLASS_DISPLAY_VGA << 8, ~0) }, + { }, +}; + +U_BOOT_PCI_DEVICE(vesa_video, vesa_video_supported); diff --git a/drivers/video/vesa_fb.c b/drivers/video/vesa_fb.c deleted file mode 100644 index 021c1d68edf..00000000000 --- a/drivers/video/vesa_fb.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * VESA frame buffer driver - * - * Copyright (C) 2014 Google, Inc - * - * SPDX-License-Identifier: GPL-2.0+ - */ - -#include <common.h> -#include <pci_rom.h> -#include <video_fb.h> -#include <vbe.h> - -/* - * The Graphic Device - */ -GraphicDevice ctfb; - -void *video_hw_init(void) -{ - GraphicDevice *gdev = &ctfb; - struct udevice *dev; - int bits_per_pixel; - int ret; - - printf("Video: "); - if (!ll_boot_init()) { - /* - * If we are running from EFI or coreboot, this driver can't - * work. - */ - printf("Not available (previous bootloader prevents it)\n"); - return NULL; - } - if (vbe_get_video_info(gdev)) { - ret = dm_pci_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0, &dev); - if (ret) { - printf("no card detected\n"); - return NULL; - } - bootstage_start(BOOTSTAGE_ID_ACCUM_LCD, "vesa display"); - ret = dm_pci_run_vga_bios(dev, NULL, PCI_ROM_USE_NATIVE | - PCI_ROM_ALLOW_FALLBACK); - bootstage_accum(BOOTSTAGE_ID_ACCUM_LCD); - if (ret) { - printf("failed to run video BIOS: %d\n", ret); - return NULL; - } - } - - if (vbe_get_video_info(gdev)) { - printf("No video mode configured\n"); - return NULL; - } - - bits_per_pixel = gdev->gdfBytesPP * 8; - sprintf(gdev->modeIdent, "%dx%dx%d", gdev->winSizeX, gdev->winSizeY, - bits_per_pixel); - printf("%s\n", gdev->modeIdent); - debug("Frame buffer at %x\n", gdev->pciBase); - - return (void *)gdev; -} diff --git a/drivers/video/video-uclass.c b/drivers/video/video-uclass.c index b6dd0f5a583..11ca7937dc8 100644 --- a/drivers/video/video-uclass.c +++ b/drivers/video/video-uclass.c @@ -54,6 +54,9 @@ static ulong alloc_fb(struct udevice *dev, ulong *addrp) struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); ulong base, align, size; + if (!plat->size) + return 0; + align = plat->align ? plat->align : 1 << 20; base = *addrp - plat->size; base &= ~(align - 1); |