diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpio/intel_ich6_gpio.c | 125 | ||||
-rw-r--r-- | drivers/net/designware.c | 4 | ||||
-rw-r--r-- | drivers/net/e1000.c | 75 | ||||
-rw-r--r-- | drivers/net/e1000.h | 4 | ||||
-rw-r--r-- | drivers/net/pch_gbe.c | 27 | ||||
-rw-r--r-- | drivers/net/pch_gbe.h | 2 | ||||
-rw-r--r-- | drivers/pch/pch-uclass.c | 30 | ||||
-rw-r--r-- | drivers/pch/pch7.c | 43 | ||||
-rw-r--r-- | drivers/pch/pch9.c | 54 | ||||
-rw-r--r-- | drivers/spi/ich.c | 76 | ||||
-rw-r--r-- | drivers/spi/ich.h | 61 |
11 files changed, 301 insertions, 200 deletions
diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index 67bf0a2dd3..527ed6d0fa 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -30,6 +30,7 @@ #include <dm.h> #include <errno.h> #include <fdtdec.h> +#include <pch.h> #include <pci.h> #include <asm/gpio.h> #include <asm/io.h> @@ -62,91 +63,6 @@ void ich_gpio_set_gpio_map(const struct pch_gpio_map *map) gd->arch.gpio_map = map; } -static int gpio_ich6_get_base(unsigned long base) -{ - pci_dev_t pci_dev; /* handle for 0:1f:0 */ - u8 tmpbyte; - u16 tmpword; - u32 tmplong; - - /* Where should it be? */ - pci_dev = PCI_BDF(0, 0x1f, 0); - - /* Is the device present? */ - tmpword = x86_pci_read_config16(pci_dev, PCI_VENDOR_ID); - if (tmpword != PCI_VENDOR_ID_INTEL) { - debug("%s: wrong VendorID %x\n", __func__, tmpword); - return -ENODEV; - } - - tmpword = x86_pci_read_config16(pci_dev, PCI_DEVICE_ID); - debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword); - /* - * We'd like to validate the Device ID too, but pretty much any - * value is either a) correct with slight differences, or b) - * correct but undocumented. We'll have to check a bunch of other - * things instead... - */ - - /* I/O should already be enabled (it's a RO bit). */ - tmpword = x86_pci_read_config16(pci_dev, PCI_COMMAND); - if (!(tmpword & PCI_COMMAND_IO)) { - debug("%s: device IO not enabled\n", __func__); - return -ENODEV; - } - - /* Header Type must be normal (bits 6-0 only; see spec.) */ - tmpbyte = x86_pci_read_config8(pci_dev, PCI_HEADER_TYPE); - if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) { - debug("%s: invalid Header type\n", __func__); - return -ENODEV; - } - - /* Base Class must be a bridge device */ - tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_CODE); - if (tmpbyte != PCI_CLASS_CODE_BRIDGE) { - debug("%s: invalid class\n", __func__); - return -ENODEV; - } - /* Sub Class must be ISA */ - tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_SUB_CODE); - if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) { - debug("%s: invalid subclass\n", __func__); - return -ENODEV; - } - - /* Programming Interface must be 0x00 (no others exist) */ - tmpbyte = x86_pci_read_config8(pci_dev, PCI_CLASS_PROG); - if (tmpbyte != 0x00) { - debug("%s: invalid interface type\n", __func__); - return -ENODEV; - } - - /* - * GPIOBASE moved to its current offset with ICH6, but prior to - * that it was unused (or undocumented). Check that it looks - * okay: not all ones or zeros. - * - * Note we don't need check bit0 here, because the Tunnel Creek - * GPIO base address register bit0 is reserved (read returns 0), - * while on the Ivybridge the bit0 is used to indicate it is an - * I/O space. - */ - tmplong = x86_pci_read_config32(pci_dev, base); - if (tmplong == 0x00000000 || tmplong == 0xffffffff) { - debug("%s: unexpected BASE value\n", __func__); - return -ENODEV; - } - - /* - * Okay, I guess we're looking at the right device. The actual - * GPIO registers are in the PCI device's I/O space, starting - * at the offset that we just read. Bit 0 indicates that it's - * an I/O address, not a memory address, so mask that off. - */ - return tmplong & 1 ? tmplong & ~3 : tmplong & ~15; -} - static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value) { u32 val; @@ -288,20 +204,26 @@ static int _gpio_ich6_pinctrl_cfg_pin(s32 gpiobase, s32 iobase, int pin_node) int gpio_ich6_pinctrl_init(void) { + struct udevice *pch; int pin_node; int node; int ret; - int gpiobase; - int iobase_offset; - int iobase = -1; + u32 gpiobase; + u32 iobase = -1; + + ret = uclass_first_device(UCLASS_PCH, &pch); + if (ret) + return ret; + if (!pch) + return -ENODEV; /* * Get the memory/io base address to configure every pins. * IOBASE is used to configure the mode/pads * GPIOBASE is used to configure the direction and default value */ - gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE); - if (gpiobase < 0) { + ret = pch_get_gpio_base(pch, &gpiobase); + if (ret) { debug("%s: invalid GPIOBASE address (%08x)\n", __func__, gpiobase); return -EINVAL; @@ -319,16 +241,11 @@ int gpio_ich6_pinctrl_init(void) * Get the IOBASE, this is not mandatory as this is not * supported by all the CPU */ - iobase_offset = fdtdec_get_int(gd->fdt_blob, node, "io-base", -1); - if (iobase_offset == -1) { - debug("%s: io-base offset not present\n", __func__); - } else { - iobase = gpio_ich6_get_base(iobase_offset); - if (IS_ERR_VALUE(iobase)) { - debug("%s: invalid IOBASE address (%08x)\n", __func__, - iobase); - return -EINVAL; - } + ret = pch_get_io_base(pch, &iobase); + if (ret && ret != -ENOSYS) { + debug("%s: invalid IOBASE address (%08x)\n", __func__, + iobase); + return -EINVAL; } for (pin_node = fdt_first_subnode(gd->fdt_blob, node); @@ -349,10 +266,14 @@ int gpio_ich6_pinctrl_init(void) static int gpio_ich6_ofdata_to_platdata(struct udevice *dev) { struct ich6_bank_platdata *plat = dev_get_platdata(dev); - u16 gpiobase; + u32 gpiobase; int offset; + int ret; + + ret = pch_get_gpio_base(dev->parent, &gpiobase); + if (ret) + return ret; - gpiobase = gpio_ich6_get_base(PCI_CFG_GPIOBASE); offset = fdtdec_get_int(gd->fdt_blob, dev->of_offset, "reg", -1); if (offset == -1) { debug("%s: Invalid register offset %d\n", __func__, offset); diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 77b98c94c0..ca58f34f13 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -591,11 +591,9 @@ static int designware_eth_probe(struct udevice *dev) * or via a PCI bridge, fill in platdata before we probe the hardware. */ if (device_is_on_pci_bus(dev)) { - pci_dev_t bdf = dm_pci_get_bdf(dev); - dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); iobase &= PCI_BASE_ADDRESS_MEM_MASK; - iobase = pci_mem_to_phys(bdf, iobase); + iobase = dm_pci_mem_to_phys(dev, iobase); pdata->iobase = iobase; pdata->phy_interface = PHY_INTERFACE_MODE_RMII; diff --git a/drivers/net/e1000.c b/drivers/net/e1000.c index 70fc02ee5c..2f2185d8f1 100644 --- a/drivers/net/e1000.c +++ b/drivers/net/e1000.c @@ -38,8 +38,13 @@ tested on both gig copper and gig fiber boards #define TOUT_LOOP 100000 +#ifdef CONFIG_DM_ETH +#define virt_to_bus(devno, v) dm_pci_virt_to_mem(devno, (void *) (v)) +#define bus_to_phys(devno, a) dm_pci_mem_to_phys(devno, a) +#else #define virt_to_bus(devno, v) pci_virt_to_mem(devno, (void *) (v)) #define bus_to_phys(devno, a) pci_mem_to_phys(devno, a) +#endif #define E1000_DEFAULT_PCI_PBA 0x00000030 #define E1000_DEFAULT_PCIE_PBA 0x000a0026 @@ -1395,8 +1400,13 @@ e1000_reset_hw(struct e1000_hw *hw) /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ if (hw->mac_type == e1000_82542_rev2_0) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); +#ifdef CONFIG_DM_ETH + dm_pci_write_config16(hw->pdev, PCI_COMMAND, + hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE); +#else pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word & ~PCI_COMMAND_INVALIDATE); +#endif } /* Clear interrupt mask to stop board from generating interrupts */ @@ -1469,7 +1479,11 @@ e1000_reset_hw(struct e1000_hw *hw) /* If MWI was previously enabled, reenable it. */ if (hw->mac_type == e1000_82542_rev2_0) { +#ifdef CONFIG_DM_ETH + dm_pci_write_config16(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); +#else pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); +#endif } if (hw->mac_type != e1000_igb) E1000_WRITE_REG(hw, PBA, pba); @@ -1655,9 +1669,15 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6]) /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ if (hw->mac_type == e1000_82542_rev2_0) { DEBUGOUT("Disabling MWI on 82542 rev 2.0\n"); +#ifdef CONFIG_DM_ETH + dm_pci_write_config16(hw->pdev, PCI_COMMAND, + hw-> + pci_cmd_word & ~PCI_COMMAND_INVALIDATE); +#else pci_write_config_word(hw->pdev, PCI_COMMAND, hw-> pci_cmd_word & ~PCI_COMMAND_INVALIDATE); +#endif E1000_WRITE_REG(hw, RCTL, E1000_RCTL_RST); E1000_WRITE_FLUSH(hw); mdelay(5); @@ -1673,7 +1693,11 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6]) E1000_WRITE_REG(hw, RCTL, 0); E1000_WRITE_FLUSH(hw); mdelay(1); +#ifdef CONFIG_DM_ETH + dm_pci_write_config16(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); +#else pci_write_config_word(hw->pdev, PCI_COMMAND, hw->pci_cmd_word); +#endif } /* Zero out the Multicast HASH table */ @@ -1696,10 +1720,17 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6]) default: /* Workaround for PCI-X problem when BIOS sets MMRBC incorrectly. */ if (hw->bus_type == e1000_bus_type_pcix) { +#ifdef CONFIG_DM_ETH + dm_pci_read_config16(hw->pdev, PCIX_COMMAND_REGISTER, + &pcix_cmd_word); + dm_pci_read_config16(hw->pdev, PCIX_STATUS_REGISTER_HI, + &pcix_stat_hi_word); +#else pci_read_config_word(hw->pdev, PCIX_COMMAND_REGISTER, &pcix_cmd_word); pci_read_config_word(hw->pdev, PCIX_STATUS_REGISTER_HI, &pcix_stat_hi_word); +#endif cmd_mmrbc = (pcix_cmd_word & PCIX_COMMAND_MMRBC_MASK) >> PCIX_COMMAND_MMRBC_SHIFT; @@ -1711,8 +1742,13 @@ e1000_init_hw(struct e1000_hw *hw, unsigned char enetaddr[6]) if (cmd_mmrbc > stat_mmrbc) { pcix_cmd_word &= ~PCIX_COMMAND_MMRBC_MASK; pcix_cmd_word |= stat_mmrbc << PCIX_COMMAND_MMRBC_SHIFT; +#ifdef CONFIG_DM_ETH + dm_pci_write_config16(hw->pdev, PCIX_COMMAND_REGISTER, + pcix_cmd_word); +#else pci_write_config_word(hw->pdev, PCIX_COMMAND_REGISTER, pcix_cmd_word); +#endif } } break; @@ -4809,6 +4845,16 @@ e1000_sw_init(struct e1000_hw *hw) int result; /* PCI config space info */ +#ifdef CONFIG_DM_ETH + dm_pci_read_config16(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id); + dm_pci_read_config16(hw->pdev, PCI_DEVICE_ID, &hw->device_id); + dm_pci_read_config16(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID, + &hw->subsystem_vendor_id); + dm_pci_read_config16(hw->pdev, PCI_SUBSYSTEM_ID, &hw->subsystem_id); + + dm_pci_read_config8(hw->pdev, PCI_REVISION_ID, &hw->revision_id); + dm_pci_read_config16(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word); +#else pci_read_config_word(hw->pdev, PCI_VENDOR_ID, &hw->vendor_id); pci_read_config_word(hw->pdev, PCI_DEVICE_ID, &hw->device_id); pci_read_config_word(hw->pdev, PCI_SUBSYSTEM_VENDOR_ID, @@ -4817,6 +4863,7 @@ e1000_sw_init(struct e1000_hw *hw) pci_read_config_byte(hw->pdev, PCI_REVISION_ID, &hw->revision_id); pci_read_config_word(hw->pdev, PCI_COMMAND, &hw->pci_cmd_word); +#endif /* identify the MAC */ result = e1000_set_mac_type(hw); @@ -5232,25 +5279,46 @@ void e1000_get_bus_type(struct e1000_hw *hw) static LIST_HEAD(e1000_hw_list); #endif +#ifdef CONFIG_DM_ETH +static int e1000_init_one(struct e1000_hw *hw, int cardnum, + struct udevice *devno, unsigned char enetaddr[6]) +#else static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno, unsigned char enetaddr[6]) +#endif { u32 val; /* Assign the passed-in values */ +#ifdef CONFIG_DM_ETH hw->pdev = devno; +#else + hw->pdev = devno; +#endif hw->cardnum = cardnum; /* Print a debug message with the IO base address */ +#ifdef CONFIG_DM_ETH + dm_pci_read_config32(devno, PCI_BASE_ADDRESS_0, &val); +#else pci_read_config_dword(devno, PCI_BASE_ADDRESS_0, &val); +#endif E1000_DBG(hw, "iobase 0x%08x\n", val & 0xfffffff0); /* Try to enable I/O accesses and bus-mastering */ val = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; +#ifdef CONFIG_DM_ETH + dm_pci_write_config32(devno, PCI_COMMAND, val); +#else pci_write_config_dword(devno, PCI_COMMAND, val); +#endif /* Make sure it worked */ +#ifdef CONFIG_DM_ETH + dm_pci_read_config32(devno, PCI_COMMAND, &val); +#else pci_read_config_dword(devno, PCI_COMMAND, &val); +#endif if (!(val & PCI_COMMAND_MEMORY)) { E1000_ERR(hw, "Can't enable I/O memory\n"); return -ENOSPC; @@ -5269,8 +5337,13 @@ static int e1000_init_one(struct e1000_hw *hw, int cardnum, pci_dev_t devno, #ifndef CONFIG_E1000_NO_NVM hw->eeprom_semaphore_present = true; #endif +#ifdef CONFIG_DM_ETH + hw->hw_addr = dm_pci_map_bar(devno, PCI_BASE_ADDRESS_0, + PCI_REGION_MEM); +#else hw->hw_addr = pci_map_bar(devno, PCI_BASE_ADDRESS_0, PCI_REGION_MEM); +#endif hw->mac_type = e1000_undefined; /* MAC and Phy settings */ @@ -5554,7 +5627,7 @@ static int e1000_eth_probe(struct udevice *dev) hw->name = dev->name; ret = e1000_init_one(hw, trailing_strtol(dev->name), - dm_pci_get_bdf(dev), plat->enetaddr); + dev, plat->enetaddr); if (ret < 0) { printf(pr_fmt("failed to initialize card: %d\n"), ret); return ret; diff --git a/drivers/net/e1000.h b/drivers/net/e1000.h index e46edcd4e1..fcb7df0d83 100644 --- a/drivers/net/e1000.h +++ b/drivers/net/e1000.h @@ -1084,7 +1084,11 @@ struct e1000_hw { #endif unsigned int cardnum; +#ifdef CONFIG_DM_ETH + struct udevice *pdev; +#else pci_dev_t pdev; +#endif uint8_t *hw_addr; e1000_mac_type mac_type; e1000_phy_type phy_type; diff --git a/drivers/net/pch_gbe.c b/drivers/net/pch_gbe.c index 56d29d47af..137818b390 100644 --- a/drivers/net/pch_gbe.c +++ b/drivers/net/pch_gbe.c @@ -117,15 +117,15 @@ static void pch_gbe_rx_descs_init(struct udevice *dev) memset(rx_desc, 0, sizeof(struct pch_gbe_rx_desc) * PCH_GBE_DESC_NUM); for (i = 0; i < PCH_GBE_DESC_NUM; i++) - rx_desc->buffer_addr = pci_phys_to_mem(priv->bdf, + rx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (u32)(priv->rx_buff[i])); - writel(pci_phys_to_mem(priv->bdf, (u32)rx_desc), + writel(dm_pci_phys_to_mem(priv->dev, (u32)rx_desc), &mac_regs->rx_dsc_base); writel(sizeof(struct pch_gbe_rx_desc) * (PCH_GBE_DESC_NUM - 1), &mac_regs->rx_dsc_size); - writel(pci_phys_to_mem(priv->bdf, (u32)(rx_desc + 1)), + writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_desc + 1)), &mac_regs->rx_dsc_sw_p); } @@ -137,11 +137,11 @@ static void pch_gbe_tx_descs_init(struct udevice *dev) memset(tx_desc, 0, sizeof(struct pch_gbe_tx_desc) * PCH_GBE_DESC_NUM); - writel(pci_phys_to_mem(priv->bdf, (u32)tx_desc), + writel(dm_pci_phys_to_mem(priv->dev, (u32)tx_desc), &mac_regs->tx_dsc_base); writel(sizeof(struct pch_gbe_tx_desc) * (PCH_GBE_DESC_NUM - 1), &mac_regs->tx_dsc_size); - writel(pci_phys_to_mem(priv->bdf, (u32)(tx_desc + 1)), + writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_desc + 1)), &mac_regs->tx_dsc_sw_p); } @@ -251,7 +251,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) if (length < 64) frame_ctrl |= PCH_GBE_TXD_CTRL_APAD; - tx_desc->buffer_addr = pci_phys_to_mem(priv->bdf, (u32)packet); + tx_desc->buffer_addr = dm_pci_phys_to_mem(priv->dev, (u32)packet); tx_desc->length = length; tx_desc->tx_words_eob = length + 3; tx_desc->tx_frame_ctrl = frame_ctrl; @@ -262,7 +262,7 @@ static int pch_gbe_send(struct udevice *dev, void *packet, int length) if (++priv->tx_idx >= PCH_GBE_DESC_NUM) priv->tx_idx = 0; - writel(pci_phys_to_mem(priv->bdf, (u32)(tx_head + priv->tx_idx)), + writel(dm_pci_phys_to_mem(priv->dev, (u32)(tx_head + priv->tx_idx)), &mac_regs->tx_dsc_sw_p); start = get_timer(0); @@ -294,7 +294,7 @@ static int pch_gbe_recv(struct udevice *dev, int flags, uchar **packetp) if ((u32)rx_desc == hw_desc) return -EAGAIN; - buffer_addr = pci_mem_to_phys(priv->bdf, rx_desc->buffer_addr); + buffer_addr = dm_pci_mem_to_phys(priv->dev, rx_desc->buffer_addr); *packetp = (uchar *)buffer_addr; length = rx_desc->rx_words_eob - 3 - ETH_FCS_LEN; @@ -315,7 +315,7 @@ static int pch_gbe_free_pkt(struct udevice *dev, uchar *packet, int length) if (++rx_swp >= PCH_GBE_DESC_NUM) rx_swp = 0; - writel(pci_phys_to_mem(priv->bdf, (u32)(rx_head + rx_swp)), + writel(dm_pci_phys_to_mem(priv->dev, (u32)(rx_head + rx_swp)), &mac_regs->rx_dsc_sw_p); return 0; @@ -421,11 +421,8 @@ int pch_gbe_probe(struct udevice *dev) { struct pch_gbe_priv *priv; struct eth_pdata *plat = dev_get_platdata(dev); - pci_dev_t devno; u32 iobase; - devno = dm_pci_get_bdf(dev); - /* * The priv structure contains the descriptors and frame buffers which * need a strict buswidth alignment (64 bytes). This is guaranteed by @@ -433,11 +430,11 @@ int pch_gbe_probe(struct udevice *dev) */ priv = dev_get_priv(dev); - priv->bdf = devno; + priv->dev = dev; - pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &iobase); + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_1, &iobase); iobase &= PCI_BASE_ADDRESS_MEM_MASK; - iobase = pci_mem_to_phys(devno, iobase); + iobase = dm_pci_mem_to_phys(dev, iobase); plat->iobase = iobase; priv->mac_regs = (struct pch_gbe_regs *)iobase; diff --git a/drivers/net/pch_gbe.h b/drivers/net/pch_gbe.h index afcb03dd36..0ea0c73a4f 100644 --- a/drivers/net/pch_gbe.h +++ b/drivers/net/pch_gbe.h @@ -290,7 +290,7 @@ struct pch_gbe_priv { struct phy_device *phydev; struct mii_dev *bus; struct pch_gbe_regs *mac_regs; - pci_dev_t bdf; + struct udevice *dev; int rx_idx; int tx_idx; }; diff --git a/drivers/pch/pch-uclass.c b/drivers/pch/pch-uclass.c index 4579ed12f6..7216660a24 100644 --- a/drivers/pch/pch-uclass.c +++ b/drivers/pch/pch-uclass.c @@ -12,35 +12,47 @@ DECLARE_GLOBAL_DATA_PTR; -int pch_get_sbase(struct udevice *dev, ulong *sbasep) +int pch_get_spi_base(struct udevice *dev, ulong *sbasep) { struct pch_ops *ops = pch_get_ops(dev); *sbasep = 0; - if (!ops->get_sbase) + if (!ops->get_spi_base) return -ENOSYS; - return ops->get_sbase(dev, sbasep); + return ops->get_spi_base(dev, sbasep); } -enum pch_version pch_get_version(struct udevice *dev) +int pch_set_spi_protect(struct udevice *dev, bool protect) { struct pch_ops *ops = pch_get_ops(dev); - if (!ops->get_version) + if (!ops->set_spi_protect) return -ENOSYS; - return ops->get_version(dev); + return ops->set_spi_protect(dev, protect); } -int pch_set_spi_protect(struct udevice *dev, bool protect) +int pch_get_gpio_base(struct udevice *dev, u32 *gbasep) { struct pch_ops *ops = pch_get_ops(dev); - if (!ops->set_spi_protect) + *gbasep = 0; + if (!ops->get_gpio_base) return -ENOSYS; - return ops->set_spi_protect(dev, protect); + return ops->get_gpio_base(dev, gbasep); +} + +int pch_get_io_base(struct udevice *dev, u32 *iobasep) +{ + struct pch_ops *ops = pch_get_ops(dev); + + *iobasep = 0; + if (!ops->get_io_base) + return -ENOSYS; + + return ops->get_io_base(dev, iobasep); } static int pch_uclass_post_bind(struct udevice *bus) diff --git a/drivers/pch/pch7.c b/drivers/pch/pch7.c index ef724221c2..302c9299ee 100644 --- a/drivers/pch/pch7.c +++ b/drivers/pch/pch7.c @@ -8,9 +8,10 @@ #include <dm.h> #include <pch.h> +#define GPIO_BASE 0x44 #define BIOS_CTRL 0xd8 -static int pch7_get_sbase(struct udevice *dev, ulong *sbasep) +static int pch7_get_spi_base(struct udevice *dev, ulong *sbasep) { u32 rcba; @@ -22,11 +23,6 @@ static int pch7_get_sbase(struct udevice *dev, ulong *sbasep) return 0; } -static enum pch_version pch7_get_version(struct udevice *dev) -{ - return PCHV_7; -} - static int pch7_set_spi_protect(struct udevice *dev, bool protect) { uint8_t bios_cntl; @@ -42,10 +38,41 @@ static int pch7_set_spi_protect(struct udevice *dev, bool protect) return 0; } +static int pch7_get_gpio_base(struct udevice *dev, u32 *gbasep) +{ + u32 base; + + /* + * GPIO_BASE moved to its current offset with ICH6, but prior to + * that it was unused (or undocumented). Check that it looks + * okay: not all ones or zeros. + * + * Note we don't need check bit0 here, because the Tunnel Creek + * GPIO base address register bit0 is reserved (read returns 0), + * while on the Ivybridge the bit0 is used to indicate it is an + * I/O space. + */ + dm_pci_read_config32(dev, GPIO_BASE, &base); + if (base == 0x00000000 || base == 0xffffffff) { + debug("%s: unexpected BASE value\n", __func__); + return -ENODEV; + } + + /* + * Okay, I guess we're looking at the right device. The actual + * GPIO registers are in the PCI device's I/O space, starting + * at the offset that we just read. Bit 0 indicates that it's + * an I/O address, not a memory address, so mask that off. + */ + *gbasep = base & 1 ? base & ~3 : base & ~15; + + return 0; +} + static const struct pch_ops pch7_ops = { - .get_sbase = pch7_get_sbase, - .get_version = pch7_get_version, + .get_spi_base = pch7_get_spi_base, .set_spi_protect = pch7_set_spi_protect, + .get_gpio_base = pch7_get_gpio_base, }; static const struct udevice_id pch7_ids[] = { diff --git a/drivers/pch/pch9.c b/drivers/pch/pch9.c index 529cb023e2..910eb61f48 100644 --- a/drivers/pch/pch9.c +++ b/drivers/pch/pch9.c @@ -8,9 +8,11 @@ #include <dm.h> #include <pch.h> +#define GPIO_BASE 0x48 +#define IO_BASE 0x4c #define SBASE_ADDR 0x54 -static int pch9_get_sbase(struct udevice *dev, ulong *sbasep) +static int pch9_get_spi_base(struct udevice *dev, ulong *sbasep) { uint32_t sbase_addr; @@ -20,14 +22,56 @@ static int pch9_get_sbase(struct udevice *dev, ulong *sbasep) return 0; } -static enum pch_version pch9_get_version(struct udevice *dev) +static int pch9_get_gpio_base(struct udevice *dev, u32 *gbasep) { - return PCHV_9; + u32 base; + + /* + * GPIO_BASE moved to its current offset with ICH6, but prior to + * that it was unused (or undocumented). Check that it looks + * okay: not all ones or zeros. + * + * Note we don't need check bit0 here, because the Tunnel Creek + * GPIO base address register bit0 is reserved (read returns 0), + * while on the Ivybridge the bit0 is used to indicate it is an + * I/O space. + */ + dm_pci_read_config32(dev, GPIO_BASE, &base); + if (base == 0x00000000 || base == 0xffffffff) { + debug("%s: unexpected BASE value\n", __func__); + return -ENODEV; + } + + /* + * Okay, I guess we're looking at the right device. The actual + * GPIO registers are in the PCI device's I/O space, starting + * at the offset that we just read. Bit 0 indicates that it's + * an I/O address, not a memory address, so mask that off. + */ + *gbasep = base & 1 ? base & ~3 : base & ~15; + + return 0; +} + +static int pch9_get_io_base(struct udevice *dev, u32 *iobasep) +{ + u32 base; + + dm_pci_read_config32(dev, IO_BASE, &base); + if (base == 0x00000000 || base == 0xffffffff) { + debug("%s: unexpected BASE value\n", __func__); + return -ENODEV; + } + + *iobasep = base & 1 ? base & ~3 : base & ~15; + + return 0; } static const struct pch_ops pch9_ops = { - .get_sbase = pch9_get_sbase, - .get_version = pch9_get_version, + .get_spi_base = pch9_get_spi_base, + .get_gpio_base = pch9_get_gpio_base, + .get_io_base = pch9_get_io_base, }; static const struct udevice_id pch9_ids[] = { diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index e543b8f0cf..00b2fed7b7 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -5,6 +5,7 @@ * * This file is derived from the flashrom project. */ + #include <common.h> #include <dm.h> #include <errno.h> @@ -17,8 +18,7 @@ #include "ich.h" -#define SPI_OPCODE_WREN 0x06 -#define SPI_OPCODE_FAST_READ 0x0b +DECLARE_GLOBAL_DATA_PTR; #ifdef DEBUG_TRACE #define debug_trace(fmt, args...) debug(fmt, ##args) @@ -26,32 +26,6 @@ #define debug_trace(x, args...) #endif -struct ich_spi_platdata { - enum pch_version ich_version; /* Controller version, 7 or 9 */ -}; - -struct ich_spi_priv { - int ichspi_lock; - int locked; - int opmenu; - int menubytes; - void *base; /* Base of register set */ - int preop; - int optype; - int addr; - int data; - unsigned databytes; - int status; - int control; - int bbar; - int bcr; - uint32_t *pr; /* only for ich9 */ - int speed; /* pointer to speed control */ - ulong max_speed; /* Maximum bus speed in MHz */ - ulong cur_speed; /* Current bus speed */ - struct spi_trans trans; /* current transaction in progress */ -}; - static u8 ich_readb(struct ich_spi_priv *priv, int reg) { u8 value = readb(priv->base + reg); @@ -145,11 +119,11 @@ static int ich_init_controller(struct udevice *dev, void *sbase; /* SBASE is similar */ - pch_get_sbase(dev->parent, &sbase_addr); + pch_get_spi_base(dev->parent, &sbase_addr); sbase = (void *)sbase_addr; debug("%s: sbase=%p\n", __func__, sbase); - if (plat->ich_version == PCHV_7) { + if (plat->ich_version == ICHV_7) { struct ich7_spi_regs *ich7_spi = sbase; ich7_spi = (struct ich7_spi_regs *)sbase; @@ -165,7 +139,7 @@ static int ich_init_controller(struct udevice *dev, ctlr->bbar = offsetof(struct ich7_spi_regs, bbar); ctlr->preop = offsetof(struct ich7_spi_regs, preop); ctlr->base = ich7_spi; - } else if (plat->ich_version == PCHV_9) { + } else if (plat->ich_version == ICHV_9) { struct ich9_spi_regs *ich9_spi = sbase; ctlr->ichspi_lock = readw(&ich9_spi->hsfs) & HSFS_FLOCKDN; @@ -191,7 +165,7 @@ static int ich_init_controller(struct udevice *dev, /* Work out the maximum speed we can support */ ctlr->max_speed = 20000000; - if (plat->ich_version == PCHV_9 && ich9_can_do_33mhz(dev)) + if (plat->ich_version == ICHV_9 && ich9_can_do_33mhz(dev)) ctlr->max_speed = 33000000; debug("ICH SPI: Version ID %d detected at %p, speed %ld\n", plat->ich_version, ctlr->base, ctlr->max_speed); @@ -217,7 +191,7 @@ static void spi_setup_type(struct spi_trans *trans, int data_bytes) { trans->type = 0xFF; - /* Try to guess spi type from read/write sizes. */ + /* Try to guess spi type from read/write sizes */ if (trans->bytesin == 0) { if (trans->bytesout + data_bytes > 4) /* @@ -301,7 +275,7 @@ static int spi_setup_opcode(struct ich_spi_priv *ctlr, struct spi_trans *trans) static int spi_setup_offset(struct spi_trans *trans) { - /* Separate the SPI address and data. */ + /* Separate the SPI address and data */ switch (trans->type) { case SPI_OPCODE_TYPE_READ_NO_ADDRESS: case SPI_OPCODE_TYPE_WRITE_NO_ADDRESS: @@ -410,7 +384,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, trans->in = din; trans->bytesin = din ? bytes : 0; - /* There has to always at least be an opcode. */ + /* There has to always at least be an opcode */ if (!trans->bytesout) { debug("ICH SPI: No opcode for transfer\n"); return -EPROTO; @@ -420,7 +394,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, if (ret < 0) return ret; - if (plat->ich_version == PCHV_7) + if (plat->ich_version == ICHV_7) ich_writew(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); else ich_writeb(ctlr, SPIS_CDS | SPIS_FCERR, ctlr->status); @@ -541,7 +515,7 @@ static int ich_spi_xfer(struct udevice *dev, unsigned int bitlen, /* write it */ ich_writew(ctlr, control, ctlr->control); - /* Wait for Cycle Done Status or Flash Cycle Error. */ + /* Wait for Cycle Done Status or Flash Cycle Error */ status = ich_status_poll(ctlr, SPIS_CDS | SPIS_FCERR, 1); if (status < 0) return status; @@ -622,9 +596,6 @@ static int ich_spi_probe(struct udevice *dev) uint8_t bios_cntl; int ret; - /* Check the ICH version */ - plat->ich_version = pch_get_version(dev->parent); - ret = ich_init_controller(dev, plat, priv); if (ret) return ret; @@ -678,7 +649,7 @@ static int ich_spi_child_pre_probe(struct udevice *dev) * ICH 7 SPI controller only supports array read command * and byte program command for SST flash */ - if (plat->ich_version == PCHV_7) { + if (plat->ich_version == ICHV_7) { slave->mode_rx = SPI_RX_SLOW; slave->mode = SPI_TX_BYTE; } @@ -686,6 +657,25 @@ static int ich_spi_child_pre_probe(struct udevice *dev) return 0; } +static int ich_spi_ofdata_to_platdata(struct udevice *dev) +{ + struct ich_spi_platdata *plat = dev_get_platdata(dev); + int ret; + + ret = fdt_node_check_compatible(gd->fdt_blob, dev->of_offset, + "intel,ich7-spi"); + if (ret == 0) { + plat->ich_version = ICHV_7; + } else { + ret = fdt_node_check_compatible(gd->fdt_blob, dev->of_offset, + "intel,ich9-spi"); + if (ret == 0) + plat->ich_version = ICHV_9; + } + + return ret; +} + static const struct dm_spi_ops ich_spi_ops = { .xfer = ich_spi_xfer, .set_speed = ich_spi_set_speed, @@ -697,7 +687,8 @@ static const struct dm_spi_ops ich_spi_ops = { }; static const struct udevice_id ich_spi_ids[] = { - { .compatible = "intel,ich-spi" }, + { .compatible = "intel,ich7-spi" }, + { .compatible = "intel,ich9-spi" }, { } }; @@ -706,6 +697,7 @@ U_BOOT_DRIVER(ich_spi) = { .id = UCLASS_SPI, .of_match = ich_spi_ids, .ops = &ich_spi_ops, + .ofdata_to_platdata = ich_spi_ofdata_to_platdata, .platdata_auto_alloc_size = sizeof(struct ich_spi_platdata), .priv_auto_alloc_size = sizeof(struct ich_spi_priv), .child_pre_probe = ich_spi_child_pre_probe, diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h index 1419b23e11..bd0a820809 100644 --- a/drivers/spi/ich.h +++ b/drivers/spi/ich.h @@ -6,6 +6,9 @@ * This file is derived from the flashrom project. */ +#ifndef _ICH_H_ +#define _ICH_H_ + struct ich7_spi_regs { uint16_t spis; uint16_t spic; @@ -19,34 +22,34 @@ struct ich7_spi_regs { } __packed; struct ich9_spi_regs { - uint32_t bfpr; /* 0x00 */ + uint32_t bfpr; /* 0x00 */ uint16_t hsfs; uint16_t hsfc; uint32_t faddr; uint32_t _reserved0; - uint32_t fdata[16]; /* 0x10 */ - uint32_t frap; /* 0x50 */ + uint32_t fdata[16]; /* 0x10 */ + uint32_t frap; /* 0x50 */ uint32_t freg[5]; uint32_t _reserved1[3]; - uint32_t pr[5]; /* 0x74 */ + uint32_t pr[5]; /* 0x74 */ uint32_t _reserved2[2]; - uint8_t ssfs; /* 0x90 */ + uint8_t ssfs; /* 0x90 */ uint8_t ssfc[3]; - uint16_t preop; /* 0x94 */ + uint16_t preop; /* 0x94 */ uint16_t optype; - uint8_t opmenu[8]; /* 0x98 */ + uint8_t opmenu[8]; /* 0x98 */ uint32_t bbar; uint8_t _reserved3[12]; - uint32_t fdoc; /* 0xb0 */ + uint32_t fdoc; /* 0xb0 */ uint32_t fdod; uint8_t _reserved4[8]; - uint32_t afc; /* 0xc0 */ + uint32_t afc; /* 0xc0 */ uint32_t lvscc; uint32_t uvscc; uint8_t _reserved5[4]; - uint32_t fpb; /* 0xd0 */ + uint32_t fpb; /* 0xd0 */ uint8_t _reserved6[28]; - uint32_t srdl; /* 0xf0 */ + uint32_t srdl; /* 0xf0 */ uint32_t srdc; uint32_t scs; uint32_t bcr; @@ -121,8 +124,38 @@ struct spi_trans { uint32_t offset; }; -struct ich_spi_slave { - struct spi_slave slave; +#define SPI_OPCODE_WREN 0x06 +#define SPI_OPCODE_FAST_READ 0x0b + +enum ich_version { + ICHV_7, + ICHV_9, +}; + +struct ich_spi_platdata { + enum ich_version ich_version; /* Controller version, 7 or 9 */ +}; + +struct ich_spi_priv { + int ichspi_lock; + int locked; + int opmenu; + int menubytes; + void *base; /* Base of register set */ + int preop; + int optype; + int addr; + int data; + unsigned databytes; + int status; + int control; + int bbar; + int bcr; + uint32_t *pr; /* only for ich9 */ + int speed; /* pointer to speed control */ + ulong max_speed; /* Maximum bus speed in MHz */ + ulong cur_speed; /* Current bus speed */ struct spi_trans trans; /* current transaction in progress */ - int speed; /* SPI speed in Hz */ }; + +#endif /* _ICH_H_ */ |