1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2014 Google, Inc 4 */ 5 #include <common.h> 6 #include <dm.h> 7 #include <errno.h> 8 #include <fdtdec.h> 9 #include <log.h> 10 #include <malloc.h> 11 #include <pch.h> 12 #include <asm/cpu.h> 13 #include <asm/global_data.h> 14 #include <asm/intel_regs.h> 15 #include <asm/io.h> 16 #include <asm/lapic.h> 17 #include <asm/lpc_common.h> 18 #include <asm/pci.h> 19 #include <asm/arch/model_206ax.h> 20 #include <asm/arch/pch.h> 21 #include <asm/arch/sandybridge.h> 22 #include <linux/bitops.h> 23 #include <linux/delay.h> 24 25 DECLARE_GLOBAL_DATA_PTR; 26 27 #define GPIO_BASE 0x48 28 #define BIOS_CTRL 0xdc 29 30 #define RCBA_AUDIO_CONFIG 0x2030 31 #define RCBA_AUDIO_CONFIG_HDA BIT(31) 32 #define RCBA_AUDIO_CONFIG_MASK 0xfe 33 34 #ifndef CONFIG_HAVE_FSP 35 static int pch_revision_id = -1; 36 static int pch_type = -1; 37 38 /** 39 * pch_silicon_revision() - Read silicon revision ID from the PCH 40 * 41 * @dev: PCH device 42 * @return silicon revision ID 43 */ 44 static int pch_silicon_revision(struct udevice *dev) 45 { 46 u8 val; 47 48 if (pch_revision_id < 0) { 49 dm_pci_read_config8(dev, PCI_REVISION_ID, &val); 50 pch_revision_id = val; 51 } 52 53 return pch_revision_id; 54 } 55 56 int pch_silicon_type(struct udevice *dev) 57 { 58 u8 val; 59 60 if (pch_type < 0) { 61 dm_pci_read_config8(dev, PCI_DEVICE_ID + 1, &val); 62 pch_type = val; 63 } 64 65 return pch_type; 66 } 67 68 /** 69 * pch_silicon_supported() - Check if a certain revision is supported 70 * 71 * @dev: PCH device 72 * @type: PCH type 73 * @rev: Minimum required resion 74 * @return 0 if not supported, 1 if supported 75 */ 76 static int pch_silicon_supported(struct udevice *dev, int type, int rev) 77 { 78 int cur_type = pch_silicon_type(dev); 79 int cur_rev = pch_silicon_revision(dev); 80 81 switch (type) { 82 case PCH_TYPE_CPT: 83 /* CougarPoint minimum revision */ 84 if (cur_type == PCH_TYPE_CPT && cur_rev >= rev) 85 return 1; 86 /* PantherPoint any revision */ 87 if (cur_type == PCH_TYPE_PPT) 88 return 1; 89 break; 90 91 case PCH_TYPE_PPT: 92 /* PantherPoint minimum revision */ 93 if (cur_type == PCH_TYPE_PPT && cur_rev >= rev) 94 return 1; 95 break; 96 } 97 98 return 0; 99 } 100 101 #define IOBP_RETRY 1000 102 static inline int iobp_poll(void) 103 { 104 unsigned try = IOBP_RETRY; 105 u32 data; 106 107 while (try--) { 108 data = readl(RCB_REG(IOBPS)); 109 if ((data & 1) == 0) 110 return 1; 111 udelay(10); 112 } 113 114 printf("IOBP timeout\n"); 115 return 0; 116 } 117 118 void pch_iobp_update(struct udevice *dev, u32 address, u32 andvalue, 119 u32 orvalue) 120 { 121 u32 data; 122 123 /* Set the address */ 124 writel(address, RCB_REG(IOBPIRI)); 125 126 /* READ OPCODE */ 127 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0)) 128 writel(IOBPS_RW_BX, RCB_REG(IOBPS)); 129 else 130 writel(IOBPS_READ_AX, RCB_REG(IOBPS)); 131 if (!iobp_poll()) 132 return; 133 134 /* Read IOBP data */ 135 data = readl(RCB_REG(IOBPD)); 136 if (!iobp_poll()) 137 return; 138 139 /* Check for successful transaction */ 140 if ((readl(RCB_REG(IOBPS)) & 0x6) != 0) { 141 printf("IOBP read 0x%08x failed\n", address); 142 return; 143 } 144 145 /* Update the data */ 146 data &= andvalue; 147 data |= orvalue; 148 149 /* WRITE OPCODE */ 150 if (pch_silicon_supported(dev, PCH_TYPE_CPT, PCH_STEP_B0)) 151 writel(IOBPS_RW_BX, RCB_REG(IOBPS)); 152 else 153 writel(IOBPS_WRITE_AX, RCB_REG(IOBPS)); 154 if (!iobp_poll()) 155 return; 156 157 /* Write IOBP data */ 158 writel(data, RCB_REG(IOBPD)); 159 if (!iobp_poll()) 160 return; 161 } 162 163 static int bd82x6x_probe(struct udevice *dev) 164 { 165 if (!(gd->flags & GD_FLG_RELOC)) 166 return 0; 167 168 /* Cause the SATA device to do its init */ 169 uclass_first_device(UCLASS_AHCI, &dev); 170 171 return 0; 172 } 173 #endif /* CONFIG_HAVE_FSP */ 174 175 static int bd82x6x_pch_get_spi_base(struct udevice *dev, ulong *sbasep) 176 { 177 u32 rcba; 178 179 dm_pci_read_config32(dev, PCH_RCBA, &rcba); 180 /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */ 181 rcba = rcba & 0xffffc000; 182 *sbasep = rcba + 0x3800; 183 184 return 0; 185 } 186 187 static int bd82x6x_set_spi_protect(struct udevice *dev, bool protect) 188 { 189 return lpc_set_spi_protect(dev, BIOS_CTRL, protect); 190 } 191 192 static int bd82x6x_get_gpio_base(struct udevice *dev, u32 *gbasep) 193 { 194 u32 base; 195 196 /* 197 * GPIO_BASE moved to its current offset with ICH6, but prior to 198 * that it was unused (or undocumented). Check that it looks 199 * okay: not all ones or zeros. 200 * 201 * Note we don't need check bit0 here, because the Tunnel Creek 202 * GPIO base address register bit0 is reserved (read returns 0), 203 * while on the Ivybridge the bit0 is used to indicate it is an 204 * I/O space. 205 */ 206 dm_pci_read_config32(dev, GPIO_BASE, &base); 207 if (base == 0x00000000 || base == 0xffffffff) { 208 debug("%s: unexpected BASE value\n", __func__); 209 return -ENODEV; 210 } 211 212 /* 213 * Okay, I guess we're looking at the right device. The actual 214 * GPIO registers are in the PCI device's I/O space, starting 215 * at the offset that we just read. Bit 0 indicates that it's 216 * an I/O address, not a memory address, so mask that off. 217 */ 218 *gbasep = base & 1 ? base & ~3 : base & ~15; 219 220 return 0; 221 } 222 223 static int bd82x6x_ioctl(struct udevice *dev, enum pch_req_t req, void *data, 224 int size) 225 { 226 u32 rcba, val; 227 228 switch (req) { 229 case PCH_REQ_HDA_CONFIG: 230 dm_pci_read_config32(dev, PCH_RCBA, &rcba); 231 val = readl(rcba + RCBA_AUDIO_CONFIG); 232 if (!(val & RCBA_AUDIO_CONFIG_HDA)) 233 return -ENOENT; 234 235 return val & RCBA_AUDIO_CONFIG_MASK; 236 case PCH_REQ_PMBASE_INFO: { 237 struct pch_pmbase_info *pm = data; 238 int ret; 239 240 /* Find the base address of the powermanagement registers */ 241 ret = dm_pci_read_config16(dev, 0x40, &pm->base); 242 if (ret) 243 return ret; 244 pm->base &= 0xfffe; 245 pm->gpio0_en_ofs = GPE0_EN; 246 pm->pm1_sts_ofs = PM1_STS; 247 pm->pm1_cnt_ofs = PM1_CNT; 248 249 return 0; 250 } 251 default: 252 return -ENOSYS; 253 } 254 } 255 256 static const struct pch_ops bd82x6x_pch_ops = { 257 .get_spi_base = bd82x6x_pch_get_spi_base, 258 .set_spi_protect = bd82x6x_set_spi_protect, 259 .get_gpio_base = bd82x6x_get_gpio_base, 260 .ioctl = bd82x6x_ioctl, 261 }; 262 263 static const struct udevice_id bd82x6x_ids[] = { 264 { .compatible = "intel,bd82x6x" }, 265 { } 266 }; 267 268 U_BOOT_DRIVER(bd82x6x_drv) = { 269 .name = "bd82x6x", 270 .id = UCLASS_PCH, 271 .of_match = bd82x6x_ids, 272 #ifndef CONFIG_HAVE_FSP 273 .probe = bd82x6x_probe, 274 #endif 275 .ops = &bd82x6x_pch_ops, 276 }; 277