181afac12SSimon Glass /* 281afac12SSimon Glass * Copyright (C) 2014 Google, Inc 381afac12SSimon Glass * 481afac12SSimon Glass * SPDX-License-Identifier: GPL-2.0+ 581afac12SSimon Glass */ 681afac12SSimon Glass 781afac12SSimon Glass #include <common.h> 881afac12SSimon Glass #include <dm.h> 981afac12SSimon Glass #include <pch.h> 1081afac12SSimon Glass 11*ec2af6f8SBin Meng #define GPIO_BASE 0x48 1281afac12SSimon Glass #define SBASE_ADDR 0x54 1381afac12SSimon Glass 143e389d8bSBin Meng static int pch9_get_spi_base(struct udevice *dev, ulong *sbasep) 1581afac12SSimon Glass { 1681afac12SSimon Glass uint32_t sbase_addr; 1781afac12SSimon Glass 1881afac12SSimon Glass dm_pci_read_config32(dev, SBASE_ADDR, &sbase_addr); 1981afac12SSimon Glass *sbasep = sbase_addr & 0xfffffe00; 2081afac12SSimon Glass 2181afac12SSimon Glass return 0; 2281afac12SSimon Glass } 2381afac12SSimon Glass 24*ec2af6f8SBin Meng static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep) 25*ec2af6f8SBin Meng { 26*ec2af6f8SBin Meng u32 base; 27*ec2af6f8SBin Meng 28*ec2af6f8SBin Meng /* 29*ec2af6f8SBin Meng * GPIO_BASE moved to its current offset with ICH6, but prior to 30*ec2af6f8SBin Meng * that it was unused (or undocumented). Check that it looks 31*ec2af6f8SBin Meng * okay: not all ones or zeros. 32*ec2af6f8SBin Meng * 33*ec2af6f8SBin Meng * Note we don't need check bit0 here, because the Tunnel Creek 34*ec2af6f8SBin Meng * GPIO base address register bit0 is reserved (read returns 0), 35*ec2af6f8SBin Meng * while on the Ivybridge the bit0 is used to indicate it is an 36*ec2af6f8SBin Meng * I/O space. 37*ec2af6f8SBin Meng */ 38*ec2af6f8SBin Meng dm_pci_read_config32(dev, GPIO_BASE, &base); 39*ec2af6f8SBin Meng if (base == 0x00000000 || base == 0xffffffff) { 40*ec2af6f8SBin Meng debug("%s: unexpected BASE value\n", __func__); 41*ec2af6f8SBin Meng return -ENODEV; 42*ec2af6f8SBin Meng } 43*ec2af6f8SBin Meng 44*ec2af6f8SBin Meng /* 45*ec2af6f8SBin Meng * Okay, I guess we're looking at the right device. The actual 46*ec2af6f8SBin Meng * GPIO registers are in the PCI device's I/O space, starting 47*ec2af6f8SBin Meng * at the offset that we just read. Bit 0 indicates that it's 48*ec2af6f8SBin Meng * an I/O address, not a memory address, so mask that off. 49*ec2af6f8SBin Meng */ 50*ec2af6f8SBin Meng *gbasep = base & 1 ? base & ~3 : base & ~15; 51*ec2af6f8SBin Meng 52*ec2af6f8SBin Meng return 0; 53*ec2af6f8SBin Meng } 54*ec2af6f8SBin Meng 5581afac12SSimon Glass static const struct pch_ops pch9_ops = { 563e389d8bSBin Meng .get_spi_base = pch9_get_spi_base, 57*ec2af6f8SBin Meng .get_gpio_base = pch9_get_gpio_base, 5881afac12SSimon Glass }; 5981afac12SSimon Glass 6081afac12SSimon Glass static const struct udevice_id pch9_ids[] = { 6181afac12SSimon Glass { .compatible = "intel,pch9" }, 6281afac12SSimon Glass { } 6381afac12SSimon Glass }; 6481afac12SSimon Glass 6581afac12SSimon Glass U_BOOT_DRIVER(pch9_drv) = { 6681afac12SSimon Glass .name = "intel-pch9", 6781afac12SSimon Glass .id = UCLASS_PCH, 6881afac12SSimon Glass .of_match = pch9_ids, 6981afac12SSimon Glass .ops = &pch9_ops, 7081afac12SSimon Glass }; 71