1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2016 Google, Inc 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <fdtdec.h> 10 #include <pch.h> 11 #include <pci.h> 12 #include <asm/intel_regs.h> 13 #include <asm/io.h> 14 #include <asm/lpc_common.h> 15 16 DECLARE_GLOBAL_DATA_PTR; 17 18 /* Enable Prefetching and Caching */ 19 static void enable_spi_prefetch(struct udevice *pch) 20 { 21 u8 reg8; 22 23 dm_pci_read_config8(pch, 0xdc, ®8); 24 reg8 &= ~(3 << 2); 25 reg8 |= (2 << 2); /* Prefetching and Caching Enabled */ 26 dm_pci_write_config8(pch, 0xdc, reg8); 27 } 28 29 static void enable_port80_on_lpc(struct udevice *pch) 30 { 31 /* Enable port 80 POST on LPC */ 32 dm_pci_write_config32(pch, PCH_RCBA_BASE, RCB_BASE_ADDRESS | 1); 33 clrbits_le32(RCB_REG(GCS), 4); 34 } 35 36 /** 37 * lpc_early_init() - set up LPC serial ports and other early things 38 * 39 * @dev: LPC device 40 * @return 0 if OK, -ve on error 41 */ 42 int lpc_common_early_init(struct udevice *dev) 43 { 44 struct udevice *pch = dev->parent; 45 struct reg_info { 46 u32 base; 47 u32 size; 48 } values[4], *ptr; 49 int count; 50 int i; 51 52 count = fdtdec_get_int_array_count(gd->fdt_blob, dev_of_offset(dev), 53 "intel,gen-dec", (u32 *)values, 54 sizeof(values) / sizeof(u32)); 55 if (count < 0) 56 return -EINVAL; 57 58 /* Set COM1/COM2 decode range */ 59 dm_pci_write_config16(pch, LPC_IO_DEC, 0x0010); 60 61 /* Enable PS/2 Keyboard/Mouse, EC areas and COM1 */ 62 dm_pci_write_config16(pch, LPC_EN, KBC_LPC_EN | MC_LPC_EN | 63 GAMEL_LPC_EN | COMA_LPC_EN); 64 65 /* Write all registers but use 0 if we run out of data */ 66 count = count * sizeof(u32) / sizeof(values[0]); 67 for (i = 0, ptr = values; i < ARRAY_SIZE(values); i++, ptr++) { 68 u32 reg = 0; 69 70 if (i < count) 71 reg = ptr->base | PCI_COMMAND_IO | (ptr->size << 16); 72 dm_pci_write_config32(pch, LPC_GENX_DEC(i), reg); 73 } 74 75 enable_spi_prefetch(pch); 76 77 /* This is already done in start.S, but let's do it in C */ 78 enable_port80_on_lpc(pch); 79 80 return 0; 81 } 82 83 int lpc_set_spi_protect(struct udevice *dev, int bios_ctrl, bool protect) 84 { 85 uint8_t bios_cntl; 86 87 /* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */ 88 dm_pci_read_config8(dev, bios_ctrl, &bios_cntl); 89 if (protect) { 90 bios_cntl &= ~BIOS_CTRL_BIOSWE; 91 bios_cntl |= BIT(5); 92 } else { 93 bios_cntl |= BIOS_CTRL_BIOSWE; 94 bios_cntl &= ~BIT(5); 95 } 96 dm_pci_write_config8(dev, bios_ctrl, bios_cntl); 97 98 return 0; 99 } 100