1 /* 2 * Copyright (C) 2014 Google, Inc 3 * 4 * SPDX-License-Identifier: GPL-2.0+ 5 */ 6 #include <common.h> 7 #include <dm.h> 8 #include <errno.h> 9 #include <fdtdec.h> 10 #include <malloc.h> 11 #include <pch.h> 12 #include <syscon.h> 13 #include <asm/cpu.h> 14 #include <asm/io.h> 15 #include <asm/lapic.h> 16 #include <asm/pci.h> 17 #include <asm/arch/bd82x6x.h> 18 #include <asm/arch/model_206ax.h> 19 #include <asm/arch/pch.h> 20 #include <asm/arch/sandybridge.h> 21 22 #define BIOS_CTRL 0xdc 23 24 static int pch_revision_id = -1; 25 static int pch_type = -1; 26 27 /** 28 * pch_silicon_revision() - Read silicon revision ID from the PCH 29 * 30 * @dev: PCH device 31 * @return silicon revision ID 32 */ 33 static int pch_silicon_revision(struct udevice *dev) 34 { 35 u8 val; 36 37 if (pch_revision_id < 0) { 38 dm_pci_read_config8(dev, PCI_REVISION_ID, &val); 39 pch_revision_id = val; 40 } 41 42 return pch_revision_id; 43 } 44 45 int pch_silicon_type(struct udevice *dev) 46 { 47 u8 val; 48 49 if (pch_type < 0) { 50 dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val); 51 pch_type = val; 52 } 53 54 return pch_type; 55 } 56 57 /** 58 * pch_silicon_supported() - Check if a certain revision is supported 59 * 60 * @dev: PCH device 61 * @type: PCH type 62 * @rev: Minimum required resion 63 * @return 0 if not supported, 1 if supported 64 */ 65 static int pch_silicon_supported(struct udevice *dev, int type, int rev) 66 { 67 int cur_type = pch_silicon_type(dev); 68 int cur_rev = pch_silicon_revision(dev); 69 70 switch (type) { 71 case PCH_TYPE_CPT: 72 /* CougarPoint minimum revision */ 73 if (cur_type == PCH_TYPE_CPT && cur_rev >= rev) 74 return 1; 75 /* PantherPoint any revision */ 76 if (cur_type == PCH_TYPE_PPT) 77 return 1; 78 break; 79 80 case PCH_TYPE_PPT: 81 /* PantherPoint minimum revision */ 82 if (cur_type == PCH_TYPE_PPT && cur_rev >= rev) 83 return 1; 84 break; 85 } 86 87 return 0; 88 } 89 90 #define IOBP_RETRY 1000 91 static inline int iobp_poll(void) 92 { 93 unsigned try = IOBP_RETRY; 94 u32 data; 95 96 while (try--) { 97 data = readl(RCB_REG(IOBPS)); 98 if ((data & 1) == 0) 99 return 1; 100 udelay(10); 101 } 102 103 printf("IOBP timeout\n"); 104 return 0; 105 } 106 107 void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue, 108 u32 orvalue) 109 { 110 u32 data; 111 112 /* Set the address */ 113 writel(address, RCB_REG(IOBPIRI)); 114 115 /* READ OPCODE */ 116 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0)) 117 writel(IOBPS_RW_BX, RCB_REG(IOBPS)); 118 else 119 writel(IOBPS_READ_AX, RCB_REG(IOBPS)); 120 if (!iobp_poll()) 121 return; 122 123 /* Read IOBP data */ 124 data = readl(RCB_REG(IOBPD)); 125 if (!iobp_poll()) 126 return; 127 128 /* Check for successful transaction */ 129 if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) { 130 printf("IOBP read 0x%08x failed\n", address); 131 return; 132 } 133 134 /* Update the data */ 135 data &= andvalue; 136 data |= orvalue; 137 138 /* WRITE OPCODE */ 139 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0)) 140 writel(IOBPS_RW_BX, RCB_REG(IOBPS)); 141 else 142 writel(IOBPS_WRITE_AX, RCB_REG(IOBPS)); 143 if (!iobp_poll()) 144 return; 145 146 /* Write IOBP data */ 147 writel(data, RCB_REG(IOBPD)); 148 if (!iobp_poll()) 149 return; 150 } 151 152 static int bd82x6x_probe(struct udevice *dev) 153 { 154 struct udevice *gma_dev; 155 int ret; 156 157 if (!(gd->flags & GD_FLG_RELOC)) 158 return 0; 159 160 /* Cause the SATA device to do its init */ 161 uclass_first_device(UCLASS_DISK, &dev); 162 163 ret = syscon_get_by_driver_data(X86_SYSCON_GMA, &gma_dev); 164 if (ret) 165 return ret; 166 ret = gma_func0_init(gma_dev); 167 if (ret) 168 return ret; 169 170 return 0; 171 } 172 173 static int bd82x6x_pch_get_sbase(struct udevice *dev, ulong *sbasep) 174 { 175 u32 rcba; 176 177 dm_pci_read_config32(dev, PCH_RCBA, &rcba); 178 /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */ 179 rcba = rcba & 0xffffc000; 180 *sbasep = rcba + 0x3800; 181 182 return 0; 183 } 184 185 static enum pch_version bd82x6x_pch_get_version(struct udevice *dev) 186 { 187 return PCHV_9; 188 } 189 190 static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect) 191 { 192 uint8_t bios_cntl; 193 194 /* Adjust the BIOS write protect and SMM BIOS Write Protect Disable */ 195 dm_pci_read_config8(dev, BIOS_CTRL, &bios_cntl); 196 if (protect) { 197 bios_cntl &= ~BIOS_CTRL_BIOSWE; 198 bios_cntl |= BIT(5); 199 } else { 200 bios_cntl |= BIOS_CTRL_BIOSWE; 201 bios_cntl &= ~BIT(5); 202 } 203 dm_pci_write_config8(dev, BIOS_CTRL, bios_cntl); 204 205 return 0; 206 } 207 208 static const struct pch_ops bd82x6x_pch_ops = { 209 .get_sbase = bd82x6x_pch_get_sbase, 210 .get_version = bd82x6x_pch_get_version, 211 .set_spi_protect = bd82x6x_set_spi_protect, 212 }; 213 214 static const struct udevice_id bd82x6x_ids[] = { 215 { .compatible = "intel,bd82x6x" }, 216 { } 217 }; 218 219 U_BOOT_DRIVER(bd82x6x_drv) = { 220 .name = "bd82x6x", 221 .id = UCLASS_PCH, 222 .of_match = bd82x6x_ids, 223 .probe = bd82x6x_probe, 224 .ops = &bd82x6x_pch_ops, 225 }; 226