1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (C) 2014 Google, Inc 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <pch.h> 9 10 #define GPIO_BASE 0x44 11 #define BIOS_CTRL 0xd8 12 13 static int pch7_get_spi_base(struct udevice *dev, ulong *sbasep) 14 { 15 u32 rcba; 16 17 dm_pci_read_config32(dev, PCH_RCBA, &rcba); 18 /* Bits 31-14 are the base address, 13-1 are reserved, 0 is enable */ 19 rcba = rcba & 0xffffc000; 20 *sbasep = rcba + 0x3020; 21 22 return 0; 23 } 24 25 static int pch7_set_spi_protect(struct udevice *dev, bool protect) 26 { 27 uint8_t bios_cntl; 28 29 /* Adjust the BIOS write protect to dis/allow write commands */ 30 dm_pci_read_config8(dev, BIOS_CTRL, &bios_cntl); 31 if (protect) 32 bios_cntl &= ~BIOS_CTRL_BIOSWE; 33 else 34 bios_cntl |= BIOS_CTRL_BIOSWE; 35 dm_pci_write_config8(dev, BIOS_CTRL, bios_cntl); 36 37 return 0; 38 } 39 40 static int pch7_get_gpio_base(struct udevice *dev, u32 *gbasep) 41 { 42 u32 base; 43 44 /* 45 * GPIO_BASE moved to its current offset with ICH6, but prior to 46 * that it was unused (or undocumented). Check that it looks 47 * okay: not all ones or zeros. 48 * 49 * Note we don't need check bit0 here, because the Tunnel Creek 50 * GPIO base address register bit0 is reserved (read returns 0), 51 * while on the Ivybridge the bit0 is used to indicate it is an 52 * I/O space. 53 */ 54 dm_pci_read_config32(dev, GPIO_BASE, &base); 55 if (base == 0x00000000 || base == 0xffffffff) { 56 debug("%s: unexpected BASE value\n", __func__); 57 return -ENODEV; 58 } 59 60 /* 61 * Okay, I guess we're looking at the right device. The actual 62 * GPIO registers are in the PCI device's I/O space, starting 63 * at the offset that we just read. Bit 0 indicates that it's 64 * an I/O address, not a memory address, so mask that off. 65 */ 66 *gbasep = base & 1 ? base & ~3 : base & ~15; 67 68 return 0; 69 } 70 71 static const struct pch_ops pch7_ops = { 72 .get_spi_base = pch7_get_spi_base, 73 .set_spi_protect = pch7_set_spi_protect, 74 .get_gpio_base = pch7_get_gpio_base, 75 }; 76 77 static const struct udevice_id pch7_ids[] = { 78 { .compatible = "intel,pch7" }, 79 { } 80 }; 81 82 U_BOOT_DRIVER(pch7_drv) = { 83 .name = "intel-pch7", 84 .id = UCLASS_PCH, 85 .of_match = pch7_ids, 86 .ops = &pch7_ops, 87 }; 88