diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/core/device-remove.c | 16 | ||||
-rw-r--r-- | drivers/gpio/intel_ich6_gpio.c | 30 | ||||
-rw-r--r-- | drivers/mmc/pci_mmc.c | 86 | ||||
-rw-r--r-- | drivers/pci/pci_rom.c | 14 | ||||
-rw-r--r-- | drivers/serial/serial-uclass.c | 2 | ||||
-rw-r--r-- | drivers/spi/ich.c | 18 | ||||
-rw-r--r-- | drivers/spi/ich.h | 54 |
7 files changed, 176 insertions, 44 deletions
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c index cc0043b990..3c6ab42f7d 100644 --- a/drivers/core/device-remove.c +++ b/drivers/core/device-remove.c @@ -152,6 +152,15 @@ void device_free(struct udevice *dev) devres_release_probe(dev); } +static bool flags_remove(uint flags, uint drv_flags) +{ + if ((flags & DM_REMOVE_NORMAL) || + (flags & (drv_flags & (DM_FLAG_ACTIVE_DMA | DM_FLAG_OS_PREPARE)))) + return true; + + return false; +} + int device_remove(struct udevice *dev, uint flags) { const struct driver *drv; @@ -178,9 +187,7 @@ int device_remove(struct udevice *dev, uint flags) * Remove the device if called with the "normal" remove flag set, * or if the remove flag matches any of the drivers remove flags */ - if (drv->remove && - ((flags & DM_REMOVE_NORMAL) || - (flags & (drv->flags & DM_FLAG_ACTIVE_DMA)))) { + if (drv->remove && flags_remove(flags, drv->flags)) { ret = drv->remove(dev); if (ret) goto err_remove; @@ -194,8 +201,7 @@ int device_remove(struct udevice *dev, uint flags) } } - if ((flags & DM_REMOVE_NORMAL) || - (flags & (drv->flags & DM_FLAG_ACTIVE_DMA))) { + if (flags_remove(flags, drv->flags)) { device_free(dev); dev->seq = -1; diff --git a/drivers/gpio/intel_ich6_gpio.c b/drivers/gpio/intel_ich6_gpio.c index 8b782260bc..0a9eb03fd0 100644 --- a/drivers/gpio/intel_ich6_gpio.c +++ b/drivers/gpio/intel_ich6_gpio.c @@ -46,22 +46,31 @@ struct ich6_bank_priv { uint16_t use_sel; uint16_t io_sel; uint16_t lvl; + u32 lvl_write_cache; + bool use_lvl_write_cache; }; #define GPIO_USESEL_OFFSET(x) (x) #define GPIO_IOSEL_OFFSET(x) (x + 4) #define GPIO_LVL_OFFSET(x) (x + 8) -static int _ich6_gpio_set_value(uint16_t base, unsigned offset, int value) +static int _ich6_gpio_set_value(struct ich6_bank_priv *bank, unsigned offset, + int value) { u32 val; - val = inl(base); + if (bank->use_lvl_write_cache) + val = bank->lvl_write_cache; + else + val = inl(bank->lvl); + if (value) val |= (1UL << offset); else val &= ~(1UL << offset); - outl(val, base); + outl(val, bank->lvl); + if (bank->use_lvl_write_cache) + bank->lvl_write_cache = val; return 0; } @@ -112,6 +121,7 @@ static int ich6_gpio_probe(struct udevice *dev) struct ich6_bank_platdata *plat = dev_get_platdata(dev); struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); struct ich6_bank_priv *bank = dev_get_priv(dev); + const void *prop; uc_priv->gpio_count = GPIO_PER_BANK; uc_priv->bank_name = plat->bank_name; @@ -119,6 +129,14 @@ static int ich6_gpio_probe(struct udevice *dev) bank->io_sel = plat->base_addr + 4; bank->lvl = plat->base_addr + 8; + prop = fdt_getprop(gd->fdt_blob, dev->of_offset, + "use-lvl-write-cache", NULL); + if (prop) + bank->use_lvl_write_cache = true; + else + bank->use_lvl_write_cache = false; + bank->lvl_write_cache = 0; + return 0; } @@ -160,7 +178,7 @@ static int ich6_gpio_direction_output(struct udevice *dev, unsigned offset, if (ret) return ret; - return _ich6_gpio_set_value(bank->lvl, offset, value); + return _ich6_gpio_set_value(bank, offset, value); } static int ich6_gpio_get_value(struct udevice *dev, unsigned offset) @@ -170,6 +188,8 @@ static int ich6_gpio_get_value(struct udevice *dev, unsigned offset) int r; tmplong = inl(bank->lvl); + if (bank->use_lvl_write_cache) + tmplong |= bank->lvl_write_cache; r = (tmplong & (1UL << offset)) ? 1 : 0; return r; } @@ -178,7 +198,7 @@ static int ich6_gpio_set_value(struct udevice *dev, unsigned offset, int value) { struct ich6_bank_priv *bank = dev_get_priv(dev); - return _ich6_gpio_set_value(bank->lvl, offset, value); + return _ich6_gpio_set_value(bank, offset, value); } static int ich6_gpio_get_function(struct udevice *dev, unsigned offset) diff --git a/drivers/mmc/pci_mmc.c b/drivers/mmc/pci_mmc.c index e39b476834..6db89779ba 100644 --- a/drivers/mmc/pci_mmc.c +++ b/drivers/mmc/pci_mmc.c @@ -6,37 +6,71 @@ */ #include <common.h> +#include <dm.h> #include <errno.h> #include <malloc.h> +#include <mapmem.h> #include <sdhci.h> #include <asm/pci.h> -int pci_mmc_init(const char *name, struct pci_device_id *mmc_supported) +struct pci_mmc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + +struct pci_mmc_priv { + struct sdhci_host host; + void *base; +}; + +static int pci_mmc_probe(struct udevice *dev) { - struct sdhci_host *mmc_host; - u32 iobase; + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct pci_mmc_plat *plat = dev_get_platdata(dev); + struct pci_mmc_priv *priv = dev_get_priv(dev); + struct sdhci_host *host = &priv->host; + u32 ioaddr; int ret; - int i; - - for (i = 0; ; i++) { - struct udevice *dev; - - ret = pci_find_device_id(mmc_supported, i, &dev); - if (ret) - return ret; - mmc_host = malloc(sizeof(struct sdhci_host)); - if (!mmc_host) - return -ENOMEM; - - mmc_host->name = name; - dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &iobase); - mmc_host->ioaddr = (void *)(ulong)iobase; - mmc_host->quirks = 0; - mmc_host->max_clk = 0; - ret = add_sdhci(mmc_host, 0, 0); - if (ret) - return ret; - } - - return 0; + + dm_pci_read_config32(dev, PCI_BASE_ADDRESS_0, &ioaddr); + host->ioaddr = map_sysmem(ioaddr, 0); + host->name = dev->name; + ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0); + if (ret) + return ret; + host->mmc = &plat->mmc; + host->mmc->priv = &priv->host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + return sdhci_probe(dev); } + +static int pci_mmc_bind(struct udevice *dev) +{ + struct pci_mmc_plat *plat = dev_get_platdata(dev); + + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +U_BOOT_DRIVER(pci_mmc) = { + .name = "pci_mmc", + .id = UCLASS_MMC, + .bind = pci_mmc_bind, + .probe = pci_mmc_probe, + .ops = &sdhci_ops, + .priv_auto_alloc_size = sizeof(struct pci_mmc_priv), + .platdata_auto_alloc_size = sizeof(struct pci_mmc_plat), +}; + +static struct pci_device_id mmc_supported[] = { + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SDIO) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_SD) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BYT_EMMC2) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_QRK_SDIO) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_0) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TCF_SDIO_1) }, + {}, +}; + +U_BOOT_PCI_DEVICE(pci_mmc, mmc_supported); diff --git a/drivers/pci/pci_rom.c b/drivers/pci/pci_rom.c index 57204c4f3f..75fb093337 100644 --- a/drivers/pci/pci_rom.c +++ b/drivers/pci/pci_rom.c @@ -35,8 +35,22 @@ #include <video_fb.h> #include <linux/screen_info.h> +#ifdef CONFIG_X86 +#include <asm/acpi_s3.h> +DECLARE_GLOBAL_DATA_PTR; +#endif + __weak bool board_should_run_oprom(struct udevice *dev) { +#if defined(CONFIG_X86) && defined(CONFIG_HAVE_ACPI_RESUME) + if (gd->arch.prev_sleep_state == ACPI_S3) { + if (IS_ENABLED(CONFIG_S3_VGA_ROM_RUN)) + return true; + else + return false; + } +#endif + return true; } diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index 43c028ebe6..c2b9c5f12f 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -349,7 +349,7 @@ static int serial_pre_remove(struct udevice *dev) #if CONFIG_IS_ENABLED(SYS_STDIO_DEREGISTER) struct serial_dev_priv *upriv = dev_get_uclass_priv(dev); - if (stdio_deregister_dev(upriv->sdev, 0)) + if (stdio_deregister_dev(upriv->sdev, true)) return -EPERM; #endif diff --git a/drivers/spi/ich.c b/drivers/spi/ich.c index 893fe33b66..bf2e99b5cc 100644 --- a/drivers/spi/ich.c +++ b/drivers/spi/ich.c @@ -617,6 +617,22 @@ static int ich_spi_probe(struct udevice *dev) return 0; } +static int ich_spi_remove(struct udevice *bus) +{ + struct ich_spi_priv *ctlr = dev_get_priv(bus); + + /* + * Configure SPI controller so that the Linux MTD driver can fully + * access the SPI NOR chip + */ + ich_writew(ctlr, SPI_OPPREFIX, ctlr->preop); + ich_writew(ctlr, SPI_OPTYPE, ctlr->optype); + ich_writel(ctlr, SPI_OPMENU_LOWER, ctlr->opmenu); + ich_writel(ctlr, SPI_OPMENU_UPPER, ctlr->opmenu + sizeof(u32)); + + return 0; +} + static int ich_spi_set_speed(struct udevice *bus, uint speed) { struct ich_spi_priv *priv = dev_get_priv(bus); @@ -700,4 +716,6 @@ U_BOOT_DRIVER(ich_spi) = { .priv_auto_alloc_size = sizeof(struct ich_spi_priv), .child_pre_probe = ich_spi_child_pre_probe, .probe = ich_spi_probe, + .remove = ich_spi_remove, + .flags = DM_FLAG_OS_PREPARE, }; diff --git a/drivers/spi/ich.h b/drivers/spi/ich.h index bd0a820809..dcb8a9048f 100644 --- a/drivers/spi/ich.h +++ b/drivers/spi/ich.h @@ -102,13 +102,6 @@ enum { }; enum { - SPI_OPCODE_TYPE_READ_NO_ADDRESS = 0, - SPI_OPCODE_TYPE_WRITE_NO_ADDRESS = 1, - SPI_OPCODE_TYPE_READ_WITH_ADDRESS = 2, - SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS = 3 -}; - -enum { ICH_MAX_CMD_LEN = 5, }; @@ -124,8 +117,55 @@ struct spi_trans { uint32_t offset; }; +#define SPI_OPCODE_WRSR 0x01 +#define SPI_OPCODE_PAGE_PROGRAM 0x02 +#define SPI_OPCODE_READ 0x03 +#define SPI_OPCODE_WRDIS 0x04 +#define SPI_OPCODE_RDSR 0x05 #define SPI_OPCODE_WREN 0x06 #define SPI_OPCODE_FAST_READ 0x0b +#define SPI_OPCODE_ERASE_SECT 0x20 +#define SPI_OPCODE_READ_ID 0x9f +#define SPI_OPCODE_ERASE_BLOCK 0xd8 + +#define SPI_OPCODE_TYPE_READ_NO_ADDRESS 0 +#define SPI_OPCODE_TYPE_WRITE_NO_ADDRESS 1 +#define SPI_OPCODE_TYPE_READ_WITH_ADDRESS 2 +#define SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS 3 + +#define SPI_OPMENU_0 SPI_OPCODE_WRSR +#define SPI_OPTYPE_0 SPI_OPCODE_TYPE_WRITE_NO_ADDRESS + +#define SPI_OPMENU_1 SPI_OPCODE_PAGE_PROGRAM +#define SPI_OPTYPE_1 SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS + +#define SPI_OPMENU_2 SPI_OPCODE_READ +#define SPI_OPTYPE_2 SPI_OPCODE_TYPE_READ_WITH_ADDRESS + +#define SPI_OPMENU_3 SPI_OPCODE_RDSR +#define SPI_OPTYPE_3 SPI_OPCODE_TYPE_READ_NO_ADDRESS + +#define SPI_OPMENU_4 SPI_OPCODE_ERASE_SECT +#define SPI_OPTYPE_4 SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS + +#define SPI_OPMENU_5 SPI_OPCODE_READ_ID +#define SPI_OPTYPE_5 SPI_OPCODE_TYPE_READ_NO_ADDRESS + +#define SPI_OPMENU_6 SPI_OPCODE_ERASE_BLOCK +#define SPI_OPTYPE_6 SPI_OPCODE_TYPE_WRITE_WITH_ADDRESS + +#define SPI_OPMENU_7 SPI_OPCODE_FAST_READ +#define SPI_OPTYPE_7 SPI_OPCODE_TYPE_READ_WITH_ADDRESS + +#define SPI_OPPREFIX ((SPI_OPCODE_WREN << 8) | SPI_OPCODE_WREN) +#define SPI_OPTYPE ((SPI_OPTYPE_7 << 14) | (SPI_OPTYPE_6 << 12) | \ + (SPI_OPTYPE_5 << 10) | (SPI_OPTYPE_4 << 8) | \ + (SPI_OPTYPE_3 << 6) | (SPI_OPTYPE_2 << 4) | \ + (SPI_OPTYPE_1 << 2) | (SPI_OPTYPE_0 << 0)) +#define SPI_OPMENU_UPPER ((SPI_OPMENU_7 << 24) | (SPI_OPMENU_6 << 16) | \ + (SPI_OPMENU_5 << 8) | (SPI_OPMENU_4 << 0)) +#define SPI_OPMENU_LOWER ((SPI_OPMENU_3 << 24) | (SPI_OPMENU_2 << 16) | \ + (SPI_OPMENU_1 << 8) | (SPI_OPMENU_0 << 0)) enum ich_version { ICHV_7, |