diff options
Diffstat (limited to 'drivers')
77 files changed, 1447 insertions, 160 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 5a9d01b508..350acf81f3 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -70,8 +70,6 @@ source "drivers/pci_endpoint/Kconfig" source "drivers/pch/Kconfig" -source "drivers/pcmcia/Kconfig" - source "drivers/phy/Kconfig" source "drivers/phy/allwinner/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 41933605ce..a4bb5e4975 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -88,7 +88,6 @@ obj-y += misc/ obj-$(CONFIG_MMC) += mmc/ obj-$(CONFIG_NVME) += nvme/ obj-$(CONFIG_PCI_ENDPOINT) += pci_endpoint/ -obj-y += pcmcia/ obj-y += dfu/ obj-$(CONFIG_PCH) += pch/ obj-y += phy/allwinner/ diff --git a/drivers/bootcount/bootcount_env.c b/drivers/bootcount/bootcount_env.c index 9084ca8a6e..b75c9002b2 100644 --- a/drivers/bootcount/bootcount_env.c +++ b/drivers/bootcount/bootcount_env.c @@ -5,7 +5,7 @@ */ #include <common.h> -#include <environment.h> +#include <env.h> void bootcount_store(ulong a) { diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c index cee4d912b0..c66b6f3c4e 100644 --- a/drivers/clk/clk-uclass.c +++ b/drivers/clk/clk-uclass.c @@ -518,6 +518,19 @@ int clk_get_by_id(ulong id, struct clk **clkp) return -ENOENT; } +bool clk_is_match(const struct clk *p, const struct clk *q) +{ + /* trivial case: identical struct clk's or both NULL */ + if (p == q) + return true; + + /* same device, id and data */ + if (p->dev == q->dev && p->id == q->id && p->data == q->data) + return true; + + return false; +} + UCLASS_DRIVER(clk) = { .id = UCLASS_CLK, .name = "clk", diff --git a/drivers/core/fdtaddr.c b/drivers/core/fdtaddr.c index c2873861da..6850003a28 100644 --- a/drivers/core/fdtaddr.c +++ b/drivers/core/fdtaddr.c @@ -129,6 +129,23 @@ fdt_addr_t devfdt_get_addr_name(struct udevice *dev, const char *name) #endif } +fdt_addr_t devfdt_get_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size) +{ +#if CONFIG_IS_ENABLED(OF_CONTROL) + int index; + + index = fdt_stringlist_search(gd->fdt_blob, dev_of_offset(dev), + "reg-names", name); + if (index < 0) + return index; + + return devfdt_get_addr_size_index(dev, index, size); +#else + return FDT_ADDR_T_NONE; +#endif +} + fdt_addr_t devfdt_get_addr(struct udevice *dev) { return devfdt_get_addr_index(dev, 0); diff --git a/drivers/core/read.c b/drivers/core/read.c index 1a044b05e8..8b5502de11 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -82,6 +82,15 @@ fdt_addr_t dev_read_addr_index(struct udevice *dev, int index) return devfdt_get_addr_index(dev, index); } +fdt_addr_t dev_read_addr_size_index(struct udevice *dev, int index, + fdt_size_t *size) +{ + if (ofnode_is_np(dev_ofnode(dev))) + return ofnode_get_addr_size_index(dev_ofnode(dev), index, size); + else + return devfdt_get_addr_size_index(dev, index, size); +} + void *dev_remap_addr_index(struct udevice *dev, int index) { fdt_addr_t addr = dev_read_addr_index(dev, index); @@ -102,6 +111,17 @@ fdt_addr_t dev_read_addr_name(struct udevice *dev, const char *name) return dev_read_addr_index(dev, index); } +fdt_addr_t dev_read_addr_size_name(struct udevice *dev, const char *name, + fdt_size_t *size) +{ + int index = dev_read_stringlist_search(dev, "reg-names", name); + + if (index < 0) + return FDT_ADDR_T_NONE; + else + return dev_read_addr_size_index(dev, index, size); +} + void *dev_remap_addr_name(struct udevice *dev, const char *name) { fdt_addr_t addr = dev_read_addr_name(dev, name); diff --git a/drivers/ddr/fsl/fsl_ddr_gen4.c b/drivers/ddr/fsl/fsl_ddr_gen4.c index 30f7863b39..17a4a8282b 100644 --- a/drivers/ddr/fsl/fsl_ddr_gen4.c +++ b/drivers/ddr/fsl/fsl_ddr_gen4.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <env.h> #include <asm/io.h> #include <fsl_ddr_sdram.h> #include <asm/processor.h> diff --git a/drivers/ddr/fsl/interactive.c b/drivers/ddr/fsl/interactive.c index 4de0eae5f2..8e171e67fe 100644 --- a/drivers/ddr/fsl/interactive.c +++ b/drivers/ddr/fsl/interactive.c @@ -13,6 +13,7 @@ #include <common.h> #include <cli.h> +#include <env.h> #include <linux/ctype.h> #include <asm/types.h> #include <asm/io.h> diff --git a/drivers/ddr/fsl/options.c b/drivers/ddr/fsl/options.c index 4573ffa115..b9179315f2 100644 --- a/drivers/ddr/fsl/options.c +++ b/drivers/ddr/fsl/options.c @@ -5,6 +5,7 @@ */ #include <common.h> +#include <env.h> #include <hwconfig.h> #include <fsl_ddr_sdram.h> diff --git a/drivers/dfu/dfu.c b/drivers/dfu/dfu.c index 318949529b..d2b67b18cf 100644 --- a/drivers/dfu/dfu.c +++ b/drivers/dfu/dfu.c @@ -7,6 +7,7 @@ */ #include <common.h> +#include <env.h> #include <errno.h> #include <malloc.h> #include <mmc.h> diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index 200f9910c5..4864344853 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <env.h> #include <fastboot.h> #include <fastboot-internal.h> #include <fb_mmc.h> diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index 17eca73be0..e76af8ecc3 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -11,6 +11,7 @@ */ #include <common.h> +#include <env.h> #include <fastboot.h> #include <net/fastboot.h> diff --git a/drivers/fastboot/fb_getvar.c b/drivers/fastboot/fb_getvar.c index ebe5c8a104..95cb434189 100644 --- a/drivers/fastboot/fb_getvar.c +++ b/drivers/fastboot/fb_getvar.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <env.h> #include <fastboot.h> #include <fastboot-internal.h> #include <fb_mmc.h> diff --git a/drivers/fastboot/fb_mmc.c b/drivers/fastboot/fb_mmc.c index 0a335db3a6..b0b19c5762 100644 --- a/drivers/fastboot/fb_mmc.c +++ b/drivers/fastboot/fb_mmc.c @@ -6,6 +6,7 @@ #include <config.h> #include <common.h> #include <blk.h> +#include <env.h> #include <fastboot.h> #include <fastboot-internal.h> #include <fb_mmc.h> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c index 1fd29f2cdf..62b1dc2006 100644 --- a/drivers/firmware/ti_sci.c +++ b/drivers/firmware/ti_sci.c @@ -3170,6 +3170,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, u32 resource_subtype; u16 resource_type; struct ti_sci_resource *res; + bool valid_set = false; int sets, i, ret; u32 *temp; @@ -3209,12 +3210,15 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, &res->desc[i].start, &res->desc[i].num); if (ret) { - dev_err(dev, "type %d subtype %d not allocated for host %d\n", + dev_dbg(dev, "type %d subtype %d not allocated for host %d\n", resource_type, resource_subtype, handle_to_ti_sci_info(handle)->host_id); - return ERR_PTR(ret); + res->desc[i].start = 0; + res->desc[i].num = 0; + continue; } + valid_set = true; dev_dbg(dev, "res type = %d, subtype = %d, start = %d, num = %d\n", resource_type, resource_subtype, res->desc[i].start, res->desc[i].num); @@ -3226,7 +3230,10 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, return ERR_PTR(-ENOMEM); } - return res; + if (valid_set) + return res; + + return ERR_PTR(-EINVAL); } /* Description for K2G */ diff --git a/drivers/input/i8042.c b/drivers/input/i8042.c index 9a5dc46207..98015899f2 100644 --- a/drivers/input/i8042.c +++ b/drivers/input/i8042.c @@ -8,6 +8,7 @@ #include <common.h> #include <dm.h> +#include <env.h> #include <errno.h> #include <i8042.h> #include <input.h> diff --git a/drivers/input/input.c b/drivers/input/input.c index 4f514dba56..6ab378b979 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -9,6 +9,7 @@ #include <common.h> #include <console.h> #include <dm.h> +#include <env.h> #include <errno.h> #include <stdio_dev.h> #include <input.h> diff --git a/drivers/misc/fs_loader.c b/drivers/misc/fs_loader.c index f42eeff8f6..88e486e9d5 100644 --- a/drivers/misc/fs_loader.c +++ b/drivers/misc/fs_loader.c @@ -5,6 +5,7 @@ */ #include <common.h> #include <dm.h> +#include <env.h> #include <errno.h> #include <blk.h> #include <fs.h> diff --git a/drivers/mmc/hi6220_dw_mmc.c b/drivers/mmc/hi6220_dw_mmc.c index effd1e4c7c..6de7924383 100644 --- a/drivers/mmc/hi6220_dw_mmc.c +++ b/drivers/mmc/hi6220_dw_mmc.c @@ -22,6 +22,11 @@ struct hi6220_dwmmc_priv_data { struct dwmci_host host; }; +struct hisi_mmc_data { + unsigned int clock; + bool use_fifo; +}; + static int hi6220_dwmmc_ofdata_to_platdata(struct udevice *dev) { struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); @@ -49,13 +54,17 @@ static int hi6220_dwmmc_probe(struct udevice *dev) struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct hi6220_dwmmc_priv_data *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; + struct hisi_mmc_data *mmc_data; + + mmc_data = (struct hisi_mmc_data *)dev_get_driver_data(dev); /* Use default bus speed due to absence of clk driver */ - host->bus_hz = 50000000; + host->bus_hz = mmc_data->clock; dwmci_setup_cfg(&plat->cfg, host, host->bus_hz, 400000); host->mmc = &plat->mmc; + host->fifo_mode = mmc_data->use_fifo; host->mmc->priv = &priv->host; upriv->mmc = host->mmc; host->mmc->dev = dev; @@ -75,9 +84,23 @@ static int hi6220_dwmmc_bind(struct udevice *dev) return 0; } +static const struct hisi_mmc_data hi3660_mmc_data = { + .clock = 3200000, + .use_fifo = true, +}; + +static const struct hisi_mmc_data hi6220_mmc_data = { + .clock = 50000000, + .use_fifo = false, +}; + static const struct udevice_id hi6220_dwmmc_ids[] = { - { .compatible = "hisilicon,hi6220-dw-mshc" }, - { .compatible = "hisilicon,hi3798cv200-dw-mshc" }, + { .compatible = "hisilicon,hi6220-dw-mshc", + .data = (ulong)&hi6220_mmc_data }, + { .compatible = "hisilicon,hi3798cv200-dw-mshc", + .data = (ulong)&hi6220_mmc_data }, + { .compatible = "hisilicon,hi3660-dw-mshc", + .data = (ulong)&hi3660_mmc_data }, { } }; diff --git a/drivers/mtd/cfi_flash.c b/drivers/mtd/cfi_flash.c index 6b97e145e9..c59254c76e 100644 --- a/drivers/mtd/cfi_flash.c +++ b/drivers/mtd/cfi_flash.c @@ -19,13 +19,14 @@ #include <common.h> #include <console.h> #include <dm.h> +#include <env.h> #include <errno.h> #include <fdt_support.h> #include <asm/processor.h> #include <asm/io.h> #include <asm/byteorder.h> #include <asm/unaligned.h> -#include <environment.h> +#include <env_internal.h> #include <mtd/cfi_flash.h> #include <watchdog.h> diff --git a/drivers/mtd/jedec_flash.c b/drivers/mtd/jedec_flash.c index a3540c1115..f59b2bc62f 100644 --- a/drivers/mtd/jedec_flash.c +++ b/drivers/mtd/jedec_flash.c @@ -15,7 +15,6 @@ #include <asm/processor.h> #include <asm/io.h> #include <asm/byteorder.h> -#include <environment.h> #define P_ID_AMD_STD CFI_CMDSET_AMD_LEGACY diff --git a/drivers/mtd/mtd_uboot.c b/drivers/mtd/mtd_uboot.c index 0a41ed477c..5574227598 100644 --- a/drivers/mtd/mtd_uboot.c +++ b/drivers/mtd/mtd_uboot.c @@ -4,6 +4,7 @@ * Heiko Schocher, DENX Software Engineering, hs@denx.de. */ #include <common.h> +#include <env.h> #include <dm/device.h> #include <dm/uclass-internal.h> #include <jffs2/jffs2.h> /* LEGACY */ diff --git a/drivers/net/dc2114x.c b/drivers/net/dc2114x.c index e3c403c13f..43c2253f10 100644 --- a/drivers/net/dc2114x.c +++ b/drivers/net/dc2114x.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ #include <common.h> +#include <env.h> #include <malloc.h> #include <net.h> #include <netdev.h> diff --git a/drivers/net/fec_mxc.c b/drivers/net/fec_mxc.c index 96e3ad9a1a..080dbcf7db 100644 --- a/drivers/net/fec_mxc.c +++ b/drivers/net/fec_mxc.c @@ -9,7 +9,7 @@ #include <common.h> #include <dm.h> -#include <environment.h> +#include <env.h> #include <malloc.h> #include <memalign.h> #include <miiphy.h> diff --git a/drivers/net/fm/b4860.c b/drivers/net/fm/b4860.c index 1e20685803..5be0ad2ab3 100644 --- a/drivers/net/fm/b4860.c +++ b/drivers/net/fm/b4860.c @@ -4,6 +4,7 @@ * Roy Zang <tie-fei.zang@freescale.com> */ #include <common.h> +#include <env.h> #include <phy.h> #include <fm_eth.h> #include <asm/io.h> diff --git a/drivers/net/fm/fdt.c b/drivers/net/fm/fdt.c index 6125797125..72d1294751 100644 --- a/drivers/net/fm/fdt.c +++ b/drivers/net/fm/fdt.c @@ -3,6 +3,7 @@ * Copyright 2016 Freescale Semiconductor, Inc. */ #include <asm/io.h> +#include <env.h> #include <fsl_qe.h> /* For struct qe_firmware */ #ifdef CONFIG_SYS_DPAA_FMAN diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 0a43dfe74e..4c9dce8dc5 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -4,6 +4,7 @@ * Dave Liu <daveliu@freescale.com> */ #include <common.h> +#include <env.h> #include <malloc.h> #include <asm/io.h> #include <linux/errno.h> @@ -14,7 +15,6 @@ #include <nand.h> #include <spi_flash.h> #include <mmc.h> -#include <environment.h> #ifdef CONFIG_ARM64 #include <asm/armv8/mmu.h> diff --git a/drivers/net/fsl-mc/mc.c b/drivers/net/fsl-mc/mc.c index cc59b21f9f..1d96e4bdc2 100644 --- a/drivers/net/fsl-mc/mc.c +++ b/drivers/net/fsl-mc/mc.c @@ -5,6 +5,7 @@ * Copyright 2017-2018 NXP */ #include <common.h> +#include <env.h> #include <errno.h> #include <linux/bug.h> #include <asm/io.h> diff --git a/drivers/net/fsl_mcdmafec.c b/drivers/net/fsl_mcdmafec.c index 88309b186c..e66fb16de8 100644 --- a/drivers/net/fsl_mcdmafec.c +++ b/drivers/net/fsl_mcdmafec.c @@ -8,7 +8,7 @@ */ #include <common.h> -#include <environment.h> +#include <env.h> #include <malloc.h> #include <command.h> #include <config.h> diff --git a/drivers/net/ftmac100.c b/drivers/net/ftmac100.c index c08889c4b1..d8f1dde657 100644 --- a/drivers/net/ftmac100.c +++ b/drivers/net/ftmac100.c @@ -8,6 +8,7 @@ #include <config.h> #include <common.h> +#include <env.h> #include <malloc.h> #include <net.h> #include <linux/io.h> diff --git a/drivers/net/lan91c96.c b/drivers/net/lan91c96.c index f2489aaf82..c08bd21f95 100644 --- a/drivers/net/lan91c96.c +++ b/drivers/net/lan91c96.c @@ -46,6 +46,7 @@ #include <common.h> #include <command.h> +#include <env.h> #include <malloc.h> #include "lan91c96.h" #include <net.h> diff --git a/drivers/net/mcffec.c b/drivers/net/mcffec.c index 2b54e3a549..fb93041256 100644 --- a/drivers/net/mcffec.c +++ b/drivers/net/mcffec.c @@ -8,7 +8,7 @@ */ #include <common.h> -#include <environment.h> +#include <env.h> #include <malloc.h> #include <command.h> diff --git a/drivers/net/ne2000_base.c b/drivers/net/ne2000_base.c index 421aa20ea6..a240d06ad4 100644 --- a/drivers/net/ne2000_base.c +++ b/drivers/net/ne2000_base.c @@ -74,7 +74,7 @@ Add SNMP #include <common.h> #include <command.h> -#include <environment.h> +#include <env.h> #include <net.h> #include <malloc.h> #include <linux/compiler.h> @@ -693,16 +693,6 @@ static int ne2k_setup_driver(struct eth_device *dev) } } -#ifdef CONFIG_DRIVER_NE2000_CCR - { - vu_char *p = (vu_char *) CONFIG_DRIVER_NE2000_CCR; - - PRINTK("CCR before is %x\n", *p); - *p = CONFIG_DRIVER_NE2000_VAL; - PRINTK("CCR after is %x\n", *p); - } -#endif - nic.base = (u8 *) CONFIG_DRIVER_NE2000_BASE; nic.data = nic.base + DP_DATA; diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index ce5a15ef57..73005ff94d 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -6,6 +6,7 @@ #include <common.h> #include <command.h> +#include <env.h> #include <stdio_dev.h> #include <net.h> @@ -55,7 +56,7 @@ static int is_broadcast(struct in_addr ip) static struct in_addr netmask; static struct in_addr our_ip; static int env_changed_id; - int env_id = get_env_id(); + int env_id = env_get_id(); /* update only when the environment has changed */ if (env_changed_id != env_id) { @@ -75,7 +76,7 @@ static int refresh_settings_from_env(void) { const char *p; static int env_changed_id; - int env_id = get_env_id(); + int env_id = env_get_id(); /* update only when the environment has changed */ if (env_changed_id != env_id) { diff --git a/drivers/net/phy/micrel_ksz90x1.c b/drivers/net/phy/micrel_ksz90x1.c index f18e40a2fe..0105fc5af1 100644 --- a/drivers/net/phy/micrel_ksz90x1.c +++ b/drivers/net/phy/micrel_ksz90x1.c @@ -10,6 +10,7 @@ */ #include <common.h> #include <dm.h> +#include <env.h> #include <errno.h> #include <micrel.h> #include <phy.h> diff --git a/drivers/net/sandbox-raw.c b/drivers/net/sandbox-raw.c index 7e6625d020..3707ee35eb 100644 --- a/drivers/net/sandbox-raw.c +++ b/drivers/net/sandbox-raw.c @@ -9,6 +9,7 @@ #include <asm/eth-raw-os.h> #include <common.h> #include <dm.h> +#include <env.h> #include <malloc.h> #include <net.h> diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 2d5c97062f..749f651920 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -10,7 +10,7 @@ #include <config.h> #include <common.h> -#include <environment.h> +#include <env.h> #include <malloc.h> #include <net.h> #include <netdev.h> diff --git a/drivers/net/ti/cpsw-common.c b/drivers/net/ti/cpsw-common.c index ac12cfe9b8..21b8bbda3d 100644 --- a/drivers/net/ti/cpsw-common.c +++ b/drivers/net/ti/cpsw-common.c @@ -7,7 +7,6 @@ #include <common.h> #include <dm.h> -#include <environment.h> #include <fdt_support.h> #include <asm/io.h> #include <cpsw.h> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 3fe38f7315..bdfc0c1796 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -145,4 +145,10 @@ config PCI_MVEBU Say Y here if you want to enable PCIe controller support on Armada XP/38x SoCs. +config PCI_KEYSTONE + bool "TI Keystone PCIe controller" + depends on DM_PCI + help + Say Y here if you want to enable PCI controller support on AM654 SoC. + endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index b5ebd50c85..e54a98b8c9 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -38,3 +38,4 @@ obj-$(CONFIG_PCIE_LAYERSCAPE_GEN4) += pcie_layerscape_gen4.o \ pcie_layerscape_gen4_fixup.o obj-$(CONFIG_PCI_XILINX) += pcie_xilinx.o obj-$(CONFIG_PCIE_INTEL_FPGA) += pcie_intel_fpga.o +obj-$(CONFIG_PCI_KEYSTONE) += pcie_dw_ti.o diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index b4c8556686..ab5e49941f 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -4,6 +4,7 @@ */ #include <common.h> +#include <env.h> #include <malloc.h> #include <asm/fsl_serdes.h> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e2195726c8..5db24f1c51 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -17,6 +17,7 @@ #include <common.h> #include <command.h> +#include <env.h> #include <errno.h> #include <asm/processor.h> #include <asm/io.h> diff --git a/drivers/pci/pci_common.c b/drivers/pci/pci_common.c index 9f2d2678e3..5231b69dc9 100644 --- a/drivers/pci/pci_common.c +++ b/drivers/pci/pci_common.c @@ -11,6 +11,7 @@ #include <common.h> #include <dm.h> +#include <env.h> #include <errno.h> #include <pci.h> #include <asm/io.h> diff --git a/drivers/pci/pcie_dw_ti.c b/drivers/pci/pcie_dw_ti.c new file mode 100644 index 0000000000..b37fc2de7f --- /dev/null +++ b/drivers/pci/pcie_dw_ti.c @@ -0,0 +1,725 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Texas Instruments, Inc + */ + +#include <common.h> +#include <dm.h> +#include <pci.h> +#include <generic-phy.h> +#include <power-domain.h> +#include <regmap.h> +#include <syscon.h> +#include <asm/io.h> +#include <asm-generic/gpio.h> + +DECLARE_GLOBAL_DATA_PTR; + +#define PCIE_VENDORID_MASK GENMASK(15, 0) +#define PCIE_DEVICEID_SHIFT 16 + +/* PCI DBICS registers */ +#define PCIE_CONFIG_BAR0 0x10 +#define PCIE_LINK_STATUS_REG 0x80 +#define PCIE_LINK_STATUS_SPEED_OFF 16 +#define PCIE_LINK_STATUS_SPEED_MASK (0xf << PCIE_LINK_STATUS_SPEED_OFF) +#define PCIE_LINK_STATUS_WIDTH_OFF 20 +#define PCIE_LINK_STATUS_WIDTH_MASK (0xf << PCIE_LINK_STATUS_WIDTH_OFF) + +#define PCIE_LINK_CAPABILITY 0x7c +#define PCIE_LINK_CTL_2 0xa0 +#define TARGET_LINK_SPEED_MASK 0xf +#define LINK_SPEED_GEN_1 0x1 +#define LINK_SPEED_GEN_2 0x2 +#define LINK_SPEED_GEN_3 0x3 + +#define PCIE_MISC_CONTROL_1_OFF 0x8bc +#define PCIE_DBI_RO_WR_EN BIT(0) + +#define PLR_OFFSET 0x700 +#define PCIE_PORT_DEBUG0 (PLR_OFFSET + 0x28) +#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f +#define PORT_LOGIC_LTSSM_STATE_L0 0x11 + +#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80c +#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) + +#define PCIE_LINK_UP_TIMEOUT_MS 100 + +/* + * iATU Unroll-specific register definitions + * From 4.80 core version the address translation will be made by unroll. + * The registers are offset from atu_base + */ +#define PCIE_ATU_UNR_REGION_CTRL1 0x00 +#define PCIE_ATU_UNR_REGION_CTRL2 0x04 +#define PCIE_ATU_UNR_LOWER_BASE 0x08 +#define PCIE_ATU_UNR_UPPER_BASE 0x0c +#define PCIE_ATU_UNR_LIMIT 0x10 +#define PCIE_ATU_UNR_LOWER_TARGET 0x14 +#define PCIE_ATU_UNR_UPPER_TARGET 0x18 + +#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) +#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) +#define PCIE_ATU_TYPE_MEM (0x0 << 0) +#define PCIE_ATU_TYPE_IO (0x2 << 0) +#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) +#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) +#define PCIE_ATU_ENABLE (0x1 << 31) +#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) +#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) +#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) +#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) + +/* Register address builder */ +#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((region) << 9) + +/* Offsets from App base */ +#define PCIE_CMD_STATUS 0x04 +#define LTSSM_EN_VAL BIT(0) + +/* Parameters for the waiting for iATU enabled routine */ +#define LINK_WAIT_MAX_IATU_RETRIES 5 +#define LINK_WAIT_IATU 10000 + +#define AM654_PCIE_DEV_TYPE_MASK 0x3 +#define EP 0x0 +#define LEG_EP 0x1 +#define RC 0x2 + +/** + * struct pcie_dw_ti - TI DW PCIe controller state + * + * @app_base: The base address of application register space + * @dbics_base: The base address of dbics register space + * @cfg_base: The base address of configuration space + * @atu_base: The base address of ATU space + * @cfg_size: The size of the configuration space which is needed + * as it gets written into the PCIE_ATU_LIMIT register + * @first_busno: This driver supports multiple PCIe controllers. + * first_busno stores the bus number of the PCIe root-port + * number which may vary depending on the PCIe setup + * (PEX switches etc). + */ +struct pcie_dw_ti { + void *app_base; + void *dbi_base; + void *cfg_base; + void *atu_base; + fdt_size_t cfg_size; + int first_busno; + struct udevice *dev; + + /* IO and MEM PCI regions */ + struct pci_region io; + struct pci_region mem; +}; + +enum dw_pcie_device_mode { + DW_PCIE_UNKNOWN_TYPE, + DW_PCIE_EP_TYPE, + DW_PCIE_LEG_EP_TYPE, + DW_PCIE_RC_TYPE, +}; + +static int pcie_dw_get_link_speed(struct pcie_dw_ti *pci) +{ + return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) & + PCIE_LINK_STATUS_SPEED_MASK) >> PCIE_LINK_STATUS_SPEED_OFF; +} + +static int pcie_dw_get_link_width(struct pcie_dw_ti *pci) +{ + return (readl(pci->dbi_base + PCIE_LINK_STATUS_REG) & + PCIE_LINK_STATUS_WIDTH_MASK) >> PCIE_LINK_STATUS_WIDTH_OFF; +} + +static void dw_pcie_writel_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg, + u32 val) +{ + u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); + void __iomem *base = pci->atu_base; + + writel(val, base + offset + reg); +} + +static u32 dw_pcie_readl_ob_unroll(struct pcie_dw_ti *pci, u32 index, u32 reg) +{ + u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); + void __iomem *base = pci->atu_base; + + return readl(base + offset + reg); +} + +/** + * pcie_dw_prog_outbound_atu_unroll() - Configure ATU for outbound accesses + * + * @pcie: Pointer to the PCI controller state + * @index: ATU region index + * @type: ATU accsess type + * @cpu_addr: the physical address for the translation entry + * @pci_addr: the pcie bus address for the translation entry + * @size: the size of the translation entry + */ +static void pcie_dw_prog_outbound_atu_unroll(struct pcie_dw_ti *pci, int index, + int type, u64 cpu_addr, + u64 pci_addr, u32 size) +{ + u32 retries, val; + + debug("ATU programmed with: index: %d, type: %d, cpu addr: %8llx, pci addr: %8llx, size: %8x\n", + index, type, cpu_addr, pci_addr, size); + + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE, + lower_32_bits(cpu_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE, + upper_32_bits(cpu_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT, + lower_32_bits(cpu_addr + size - 1)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET, + lower_32_bits(pci_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET, + upper_32_bits(pci_addr)); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, + type); + dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2, + PCIE_ATU_ENABLE); + + /* + * Make sure ATU enable takes effect before any subsequent config + * and I/O accesses. + */ + for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) { + val = dw_pcie_readl_ob_unroll(pci, index, + PCIE_ATU_UNR_REGION_CTRL2); + if (val & PCIE_ATU_ENABLE) + return; + + udelay(LINK_WAIT_IATU); + } + dev_err(pci->dev, "outbound iATU is not being enabled\n"); +} + +/** + * set_cfg_address() - Configure the PCIe controller config space access + * + * @pcie: Pointer to the PCI controller state + * @d: PCI device to access + * @where: Offset in the configuration space + * + * Configures the PCIe controller to access the configuration space of + * a specific PCIe device and returns the address to use for this + * access. + * + * Return: Address that can be used to access the configation space + * of the requested device / offset + */ +static uintptr_t set_cfg_address(struct pcie_dw_ti *pcie, + pci_dev_t d, uint where) +{ + int bus = PCI_BUS(d) - pcie->first_busno; + uintptr_t va_address; + u32 atu_type; + + /* Use dbi_base for own configuration read and write */ + if (!bus) { + va_address = (uintptr_t)pcie->dbi_base; + goto out; + } + + if (bus == 1) + /* For local bus, change TLP Type field to 4. */ + atu_type = PCIE_ATU_TYPE_CFG0; + else + /* Otherwise, change TLP Type field to 5. */ + atu_type = PCIE_ATU_TYPE_CFG1; + + /* + * Not accessing root port configuration space? + * Region #0 is used for Outbound CFG space access. + * Direction = Outbound + * Region Index = 0 + */ + d = PCI_MASK_BUS(d); + d = PCI_ADD_BUS(bus, d); + pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1, + atu_type, (u64)pcie->cfg_base, + d << 8, pcie->cfg_size); + + va_address = (uintptr_t)pcie->cfg_base; + +out: + va_address += where & ~0x3; + + return va_address; +} + +/** + * pcie_dw_addr_valid() - Check for valid bus address + * + * @d: The PCI device to access + * @first_busno: Bus number of the PCIe controller root complex + * + * Return 1 (true) if the PCI device can be accessed by this controller. + * + * Return: 1 on valid, 0 on invalid + */ +static int pcie_dw_addr_valid(pci_dev_t d, int first_busno) +{ + if ((PCI_BUS(d) == first_busno) && (PCI_DEV(d) > 0)) + return 0; + if ((PCI_BUS(d) == first_busno + 1) && (PCI_DEV(d) > 0)) + return 0; + + return 1; +} + +/** + * pcie_dw_ti_read_config() - Read from configuration space + * + * @bus: Pointer to the PCI bus + * @bdf: Identifies the PCIe device to access + * @offset: The offset into the device's configuration space + * @valuep: A pointer at which to store the read value + * @size: Indicates the size of access to perform + * + * Read a value of size @size from offset @offset within the configuration + * space of the device identified by the bus, device & function numbers in @bdf + * on the PCI bus @bus. + * + * Return: 0 on success + */ +static int pcie_dw_ti_read_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong *valuep, + enum pci_size_t size) +{ + struct pcie_dw_ti *pcie = dev_get_priv(bus); + uintptr_t va_address; + ulong value; + + debug("PCIE CFG read: bdf=%2x:%2x:%2x ", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); + + if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { + debug("- out of range\n"); + *valuep = pci_get_ff(size); + return 0; + } + + va_address = set_cfg_address(pcie, bdf, offset); + + value = readl(va_address); + + debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); + *valuep = pci_conv_32_to_size(value, offset, size); + + pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1, + PCIE_ATU_TYPE_IO, pcie->io.phys_start, + pcie->io.bus_start, pcie->io.size); + + return 0; +} + +/** + * pcie_dw_ti_write_config() - Write to configuration space + * + * @bus: Pointer to the PCI bus + * @bdf: Identifies the PCIe device to access + * @offset: The offset into the device's configuration space + * @value: The value to write + * @size: Indicates the size of access to perform + * + * Write the value @value of size @size from offset @offset within the + * configuration space of the device identified by the bus, device & function + * numbers in @bdf on the PCI bus @bus. + * + * Return: 0 on success + */ +static int pcie_dw_ti_write_config(struct udevice *bus, pci_dev_t bdf, + uint offset, ulong value, + enum pci_size_t size) +{ + struct pcie_dw_ti *pcie = dev_get_priv(bus); + uintptr_t va_address; + ulong old; + + debug("PCIE CFG write: (b,d,f)=(%2d,%2d,%2d) ", + PCI_BUS(bdf), PCI_DEV(bdf), PCI_FUNC(bdf)); + debug("(addr,val)=(0x%04x, 0x%08lx)\n", offset, value); + + if (!pcie_dw_addr_valid(bdf, pcie->first_busno)) { + debug("- out of range\n"); + return 0; + } + + va_address = set_cfg_address(pcie, bdf, offset); + + old = readl(va_address); + value = pci_conv_size_to_32(old, value, offset, size); + writel(value, va_address); + + pcie_dw_prog_outbound_atu_unroll(pcie, PCIE_ATU_REGION_INDEX1, + PCIE_ATU_TYPE_IO, pcie->io.phys_start, + pcie->io.bus_start, pcie->io.size); + + return 0; +} + +static inline void dw_pcie_dbi_write_enable(struct pcie_dw_ti *pci, bool en) +{ + u32 val; + + val = readl(pci->dbi_base + PCIE_MISC_CONTROL_1_OFF); + if (en) + val |= PCIE_DBI_RO_WR_EN; + else + val &= ~PCIE_DBI_RO_WR_EN; + writel(val, pci->dbi_base + PCIE_MISC_CONTROL_1_OFF); +} + +/** + * pcie_dw_configure() - Configure link capabilities and speed + * + * @regs_base: A pointer to the PCIe controller registers + * @cap_speed: The capabilities and speed to configure + * + * Configure the link capabilities and speed in the PCIe root complex. + */ +static void pcie_dw_configure(struct pcie_dw_ti *pci, u32 cap_speed) +{ + u32 val; + + dw_pcie_dbi_write_enable(pci, true); + + val = readl(pci->dbi_base + PCIE_LINK_CAPABILITY); + val &= ~TARGET_LINK_SPEED_MASK; + val |= cap_speed; + writel(val, pci->dbi_base + PCIE_LINK_CAPABILITY); + + val = readl(pci->dbi_base + PCIE_LINK_CTL_2); + val &= ~TARGET_LINK_SPEED_MASK; + val |= cap_speed; + writel(val, pci->dbi_base + PCIE_LINK_CTL_2); + + dw_pcie_dbi_write_enable(pci, false); +} + +/** + * is_link_up() - Return the link state + * + * @regs_base: A pointer to the PCIe DBICS registers + * + * Return: 1 (true) for active line and 0 (false) for no link + */ +static int is_link_up(struct pcie_dw_ti *pci) +{ + u32 val; + + val = readl(pci->dbi_base + PCIE_PORT_DEBUG0); + val &= PORT_LOGIC_LTSSM_STATE_MASK; + + return (val == PORT_LOGIC_LTSSM_STATE_L0); +} + +/** + * wait_link_up() - Wait for the link to come up + * + * @regs_base: A pointer to the PCIe controller registers + * + * Return: 1 (true) for active line and 0 (false) for no link (timeout) + */ +static int wait_link_up(struct pcie_dw_ti *pci) +{ + unsigned long timeout; + + timeout = get_timer(0) + PCIE_LINK_UP_TIMEOUT_MS; + while (!is_link_up(pci)) { + if (get_timer(0) > timeout) + return 0; + }; + + return 1; +} + +static int pcie_dw_ti_pcie_link_up(struct pcie_dw_ti *pci, u32 cap_speed) +{ + u32 val; + + if (is_link_up(pci)) { + printf("PCI Link already up before configuration!\n"); + return 1; + } + + /* DW pre link configurations */ + pcie_dw_configure(pci, cap_speed); + + /* Initiate link training */ + val = readl(pci->app_base + PCIE_CMD_STATUS); + val |= LTSSM_EN_VAL; + writel(val, pci->app_base + PCIE_CMD_STATUS); + + /* Check that link was established */ + if (!wait_link_up(pci)) + return 0; + + /* + * Link can be established in Gen 1. still need to wait + * till MAC nagaotiation is completed + */ + udelay(100); + + return 1; +} + +/** + * pcie_dw_setup_host() - Setup the PCIe controller for RC opertaion + * + * @pcie: Pointer to the PCI controller state + * + * Configure the host BARs of the PCIe controller root port so that + * PCI(e) devices may access the system memory. + */ +static void pcie_dw_setup_host(struct pcie_dw_ti *pci) +{ + u32 val; + + /* setup RC BARs */ + writel(PCI_BASE_ADDRESS_MEM_TYPE_64, + pci->dbi_base + PCI_BASE_ADDRESS_0); + writel(0x0, pci->dbi_base + PCI_BASE_ADDRESS_1); + + /* setup interrupt pins */ + dw_pcie_dbi_write_enable(pci, true); + val = readl(pci->dbi_base + PCI_INTERRUPT_LINE); + val &= 0xffff00ff; + val |= 0x00000100; + writel(val, pci->dbi_base + PCI_INTERRUPT_LINE); + dw_pcie_dbi_write_enable(pci, false); + + /* setup bus numbers */ + val = readl(pci->dbi_base + PCI_PRIMARY_BUS); + val &= 0xff000000; + val |= 0x00ff0100; + writel(val, pci->dbi_base + PCI_PRIMARY_BUS); + + /* setup command register */ + val = readl(pci->dbi_base + PCI_COMMAND); + val &= 0xffff0000; + val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_SERR; + writel(val, pci->dbi_base + PCI_COMMAND); + + /* Enable write permission for the DBI read-only register */ + dw_pcie_dbi_write_enable(pci, true); + /* program correct class for RC */ + writew(PCI_CLASS_BRIDGE_PCI, pci->dbi_base + PCI_CLASS_DEVICE); + /* Better disable write permission right after the update */ + dw_pcie_dbi_write_enable(pci, false); + + val = readl(pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); + val |= PORT_LOGIC_SPEED_CHANGE; + writel(val, pci->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); +} + +static int pcie_am654_set_mode(struct pcie_dw_ti *pci, + enum dw_pcie_device_mode mode) +{ + struct regmap *syscon; + u32 val; + u32 mask; + int ret; + + syscon = syscon_regmap_lookup_by_phandle(pci->dev, + "ti,syscon-pcie-mode"); + if (IS_ERR(syscon)) + return 0; + + mask = AM654_PCIE_DEV_TYPE_MASK; + + switch (mode) { + case DW_PCIE_RC_TYPE: + val = RC; + break; + case DW_PCIE_EP_TYPE: + val = EP; + break; + default: + dev_err(pci->dev, "INVALID device type %d\n", mode); + return -EINVAL; + } + + ret = regmap_update_bits(syscon, 0, mask, val); + if (ret) { + dev_err(pci->dev, "failed to set pcie mode\n"); + return ret; + } + + return 0; +} + +static int pcie_dw_init_id(struct pcie_dw_ti *pci) +{ + struct regmap *devctrl_regs; + unsigned int id; + int ret; + + devctrl_regs = syscon_regmap_lookup_by_phandle(pci->dev, + "ti,syscon-pcie-id"); + if (IS_ERR(devctrl_regs)) + return PTR_ERR(devctrl_regs); + + ret = regmap_read(devctrl_regs, 0, &id); + if (ret) + return ret; + + dw_pcie_dbi_write_enable(pci, true); + writew(id & PCIE_VENDORID_MASK, pci->dbi_base + PCI_VENDOR_ID); + writew(id >> PCIE_DEVICEID_SHIFT, pci->dbi_base + PCI_DEVICE_ID); + dw_pcie_dbi_write_enable(pci, false); + + return 0; +} + +/** + * pcie_dw_ti_probe() - Probe the PCIe bus for active link + * + * @dev: A pointer to the device being operated on + * + * Probe for an active link on the PCIe bus and configure the controller + * to enable this port. + * + * Return: 0 on success, else -ENODEV + */ +static int pcie_dw_ti_probe(struct udevice *dev) +{ + struct pcie_dw_ti *pci = dev_get_priv(dev); + struct udevice *ctlr = pci_get_controller(dev); + struct pci_controller *hose = dev_get_uclass_priv(ctlr); + struct power_domain pci_pwrdmn; + struct phy phy0, phy1; + int ret; + + ret = power_domain_get_by_index(dev, &pci_pwrdmn, 0); + if (ret) { + dev_err(dev, "failed to get power domain\n"); + return ret; + } + + ret = power_domain_on(&pci_pwrdmn); + if (ret) { + dev_err(dev, "Power domain on failed\n"); + return ret; + } + + ret = generic_phy_get_by_name(dev, "pcie-phy0", &phy0); + if (ret) { + dev_err(dev, "Unable to get phy0"); + return ret; + } + generic_phy_reset(&phy0); + generic_phy_init(&phy0); + generic_phy_power_on(&phy0); + + ret = generic_phy_get_by_name(dev, "pcie-phy1", &phy1); + if (ret) { + dev_err(dev, "Unable to get phy1"); + return ret; + } + generic_phy_reset(&phy1); + generic_phy_init(&phy1); + generic_phy_power_on(&phy1); + + pci->first_busno = dev->seq; + pci->dev = dev; + + pcie_dw_setup_host(pci); + pcie_dw_init_id(pci); + + if (device_is_compatible(dev, "ti,am654-pcie-rc")) + pcie_am654_set_mode(pci, DW_PCIE_RC_TYPE); + + if (!pcie_dw_ti_pcie_link_up(pci, LINK_SPEED_GEN_2)) { + printf("PCIE-%d: Link down\n", dev->seq); + return -ENODEV; + } + + printf("PCIE-%d: Link up (Gen%d-x%d, Bus%d)\n", dev->seq, + pcie_dw_get_link_speed(pci), + pcie_dw_get_link_width(pci), + hose->first_busno); + + /* Store the IO and MEM windows settings for future use by the ATU */ + pci->io.phys_start = hose->regions[0].phys_start; /* IO base */ + pci->io.bus_start = hose->regions[0].bus_start; /* IO_bus_addr */ + pci->io.size = hose->regions[0].size; /* IO size */ + + pci->mem.phys_start = hose->regions[1].phys_start; /* MEM base */ + pci->mem.bus_start = hose->regions[1].bus_start; /* MEM_bus_addr */ + pci->mem.size = hose->regions[1].size; /* MEM size */ + + pcie_dw_prog_outbound_atu_unroll(pci, PCIE_ATU_REGION_INDEX0, + PCIE_ATU_TYPE_MEM, + pci->mem.phys_start, + pci->mem.bus_start, pci->mem.size); + + return 0; +} + +/** + * pcie_dw_ti_ofdata_to_platdata() - Translate from DT to device state + * + * @dev: A pointer to the device being operated on + * + * Translate relevant data from the device tree pertaining to device @dev into + * state that the driver will later make use of. This state is stored in the + * device's private data structure. + * + * Return: 0 on success, else -EINVAL + */ +static int pcie_dw_ti_ofdata_to_platdata(struct udevice *dev) +{ + struct pcie_dw_ti *pcie = dev_get_priv(dev); + + /* Get the controller base address */ + pcie->dbi_base = (void *)dev_read_addr_name(dev, "dbics"); + if ((fdt_addr_t)pcie->dbi_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the config space base address and size */ + pcie->cfg_base = (void *)dev_read_addr_size_name(dev, "config", + &pcie->cfg_size); + if ((fdt_addr_t)pcie->cfg_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the iATU base address and size */ + pcie->atu_base = (void *)dev_read_addr_name(dev, "atu"); + if ((fdt_addr_t)pcie->atu_base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Get the app base address and size */ + pcie->app_base = (void *)dev_read_addr_name(dev, "app"); + if ((fdt_addr_t)pcie->app_base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +static const struct dm_pci_ops pcie_dw_ti_ops = { + .read_config = pcie_dw_ti_read_config, + .write_config = pcie_dw_ti_write_config, +}; + +static const struct udevice_id pcie_dw_ti_ids[] = { + { .compatible = "ti,am654-pcie-rc" }, + { } +}; + +U_BOOT_DRIVER(pcie_dw_ti) = { + .name = "pcie_dw_ti", + .id = UCLASS_PCI, + .of_match = pcie_dw_ti_ids, + .ops = &pcie_dw_ti_ops, + .ofdata_to_platdata = pcie_dw_ti_ofdata_to_platdata, + .probe = pcie_dw_ti_probe, + .priv_auto_alloc_size = sizeof(struct pcie_dw_ti), +}; diff --git a/drivers/pci/pcie_intel_fpga.c b/drivers/pci/pcie_intel_fpga.c index 3cdf05b314..a5ea4888f3 100644 --- a/drivers/pci/pcie_intel_fpga.c +++ b/drivers/pci/pcie_intel_fpga.c @@ -36,16 +36,18 @@ #define RP_CFG_ADDR(pcie, reg) \ ((pcie->hip_base) + (reg) + (1 << 20)) +#define RP_SECONDARY(pcie) \ + readb(RP_CFG_ADDR(pcie, PCI_SECONDARY_BUS)) #define TLP_REQ_ID(bus, devfn) (((bus) << 8) | (devfn)) #define TLP_CFGRD_DW0(pcie, bus) \ - ((((bus != pcie->first_busno) ? TLP_FMTTYPE_CFGRD0 \ - : TLP_FMTTYPE_CFGRD1) << 24) | \ + ((((bus > RP_SECONDARY(pcie)) ? TLP_FMTTYPE_CFGRD1 \ + : TLP_FMTTYPE_CFGRD0) << 24) | \ TLP_PAYLOAD_SIZE) #define TLP_CFGWR_DW0(pcie, bus) \ - ((((bus != pcie->first_busno) ? TLP_FMTTYPE_CFGWR0 \ - : TLP_FMTTYPE_CFGWR1) << 24) | \ + ((((bus > RP_SECONDARY(pcie)) ? TLP_FMTTYPE_CFGWR1 \ + : TLP_FMTTYPE_CFGWR0) << 24) | \ TLP_PAYLOAD_SIZE) #define TLP_CFG_DW1(pcie, tag, be) \ @@ -56,7 +58,7 @@ #define TLP_COMP_STATUS(s) (((s) >> 13) & 7) #define TLP_BYTE_COUNT(s) (((s) >> 0) & 0xfff) #define TLP_HDR_SIZE 3 -#define TLP_LOOP 500 +#define TLP_LOOP 20000 #define DWORD_MASK 3 #define IS_ROOT_PORT(pcie, bdf) \ @@ -161,8 +163,10 @@ static int tlp_read_packet(struct intel_fpga_pcie *pcie, u32 *value) dw[count++] = cra_readl(pcie, RP_RXCPL_REG); if (ctrl & RP_RXCPL_EOP) { comp_status = TLP_COMP_STATUS(dw[1]); - if (comp_status) - return -EFAULT; + if (comp_status) { + *value = pci_get_ff(PCI_SIZE_32); + return 0; + } if (value && TLP_BYTE_COUNT(dw[1]) == sizeof(u32) && diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig deleted file mode 100644 index e69de29bb2..0000000000 --- a/drivers/pcmcia/Kconfig +++ /dev/null diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile deleted file mode 100644 index 8374a56c34..0000000000 --- a/drivers/pcmcia/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0+ -# -# (C) Copyright 2000-2007 -# Wolfgang Denk, DENX Software Engineering, wd@denx.de. - -obj-$(CONFIG_MARUBUN_PCCARD) += marubun_pcmcia.o diff --git a/drivers/pcmcia/marubun_pcmcia.c b/drivers/pcmcia/marubun_pcmcia.c deleted file mode 100644 index b2eea6c601..0000000000 --- a/drivers/pcmcia/marubun_pcmcia.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Marubun MR-SHPC-01 PCMCIA controller device driver - * - * (c) 2007 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> - */ - -#include <common.h> -#include <config.h> -#include <pcmcia.h> -#include <asm/io.h> - -#undef CONFIG_PCMCIA - -#if defined(CONFIG_CMD_PCMCIA) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_IDE) -#define CONFIG_PCMCIA -#endif - -#if defined(CONFIG_PCMCIA) - -/* MR-SHPC-01 register */ -#define MRSHPC_MODE (CONFIG_SYS_MARUBUN_MRSHPC + 4) -#define MRSHPC_OPTION (CONFIG_SYS_MARUBUN_MRSHPC + 6) -#define MRSHPC_CSR (CONFIG_SYS_MARUBUN_MRSHPC + 8) -#define MRSHPC_ISR (CONFIG_SYS_MARUBUN_MRSHPC + 10) -#define MRSHPC_ICR (CONFIG_SYS_MARUBUN_MRSHPC + 12) -#define MRSHPC_CPWCR (CONFIG_SYS_MARUBUN_MRSHPC + 14) -#define MRSHPC_MW0CR1 (CONFIG_SYS_MARUBUN_MRSHPC + 16) -#define MRSHPC_MW1CR1 (CONFIG_SYS_MARUBUN_MRSHPC + 18) -#define MRSHPC_IOWCR1 (CONFIG_SYS_MARUBUN_MRSHPC + 20) -#define MRSHPC_MW0CR2 (CONFIG_SYS_MARUBUN_MRSHPC + 22) -#define MRSHPC_MW1CR2 (CONFIG_SYS_MARUBUN_MRSHPC + 24) -#define MRSHPC_IOWCR2 (CONFIG_SYS_MARUBUN_MRSHPC + 26) -#define MRSHPC_CDCR (CONFIG_SYS_MARUBUN_MRSHPC + 28) -#define MRSHPC_PCIC_INFO (CONFIG_SYS_MARUBUN_MRSHPC + 30) - -int pcmcia_on (void) -{ - printf("Enable PCMCIA " PCMCIA_SLOT_MSG "\n"); - - /* Init */ - outw( 0x0000 , MRSHPC_MODE ); - - if ((inw(MRSHPC_CSR) & 0x000c) == 0){ /* if card detect is true */ - if ((inw(MRSHPC_CSR) & 0x0080) == 0){ - outw(0x0674 ,MRSHPC_CPWCR); /* Card Vcc is 3.3v? */ - }else{ - outw(0x0678 ,MRSHPC_CPWCR); /* Card Vcc is 5V */ - } - udelay( 100000 ); /* wait for power on */ - }else{ - return 1; - } - /* - * PC-Card window open - * flag == COMMON/ATTRIBUTE/IO - */ - /* common window open */ - outw(0x8a84,MRSHPC_MW0CR1); /* window 0xb8400000 */ - if ((inw(MRSHPC_CSR) & 0x4000) != 0) - outw(0x0b00,MRSHPC_MW0CR2); /* common mode & bus width 16bit SWAP = 1 */ - else - outw(0x0300,MRSHPC_MW0CR2); /* common mode & bus width 16bit SWAP = 0 */ - - /* attribute window open */ - outw(0x8a85,MRSHPC_MW1CR1); /* window 0xb8500000 */ - if ((inw(MRSHPC_CSR) & 0x4000) != 0) - outw(0x0a00,MRSHPC_MW1CR2); /* attribute mode & bus width 16bit SWAP = 1 */ - else - outw(0x0200,MRSHPC_MW1CR2); /* attribute mode & bus width 16bit SWAP = 0 */ - - /* I/O window open */ - outw(0x8a86,MRSHPC_IOWCR1); /* I/O window 0xb8600000 */ - outw(0x0008,MRSHPC_CDCR); /* I/O card mode */ - if ((inw(MRSHPC_CSR) & 0x4000) != 0) - outw(0x0a00,MRSHPC_IOWCR2); /* bus width 16bit SWAP = 1 */ - else - outw(0x0200,MRSHPC_IOWCR2); /* bus width 16bit SWAP = 0 */ - - outw(0x0000,MRSHPC_ISR); - outw(0x2000,MRSHPC_ICR); - outb(0x00,(CONFIG_SYS_MARUBUN_MW2 + 0x206)); - outb(0x42,(CONFIG_SYS_MARUBUN_MW2 + 0x200)); - - return 0; -} - -int pcmcia_off (void) -{ - printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n"); - - return 0; -} - -#endif /* CONFIG_PCMCIA */ diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index 8209ca7323..3942f035eb 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -108,6 +108,15 @@ config SPL_PIPE3_PHY This PHY is found on omap devices supporting SATA such as dra7, am57x and omap5 +config AM654_PHY + tristate "TI AM654 SERDES support" + depends on PHY && ARCH_K3 + select REGMAP + select SYSCON + help + This option enables support for TI AM654 SerDes PHY used for + PCIe. + config STI_USB_PHY bool "STMicroelectronics USB2 picoPHY driver for STiH407 family" depends on PHY && ARCH_STI diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index b9f5195e1c..3157f1b7ee 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_BCM6358_USBH_PHY) += bcm6358-usbh-phy.o obj-$(CONFIG_BCM6368_USBH_PHY) += bcm6368-usbh-phy.o obj-$(CONFIG_PHY_SANDBOX) += sandbox-phy.o obj-$(CONFIG_$(SPL_)PIPE3_PHY) += ti-pipe3-phy.o +obj-$(CONFIG_AM654_PHY) += phy-ti-am654.o obj-$(CONFIG_STI_USB_PHY) += sti_usb_phy.o obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_PHY_RCAR_GEN3) += phy-rcar-gen3.o diff --git a/drivers/phy/phy-ti-am654.c b/drivers/phy/phy-ti-am654.c new file mode 100644 index 0000000000..39490124ea --- /dev/null +++ b/drivers/phy/phy-ti-am654.c @@ -0,0 +1,411 @@ +// SPDX-License-Identifier: GPL-2.0+ +/** + * PCIe SERDES driver for AM654x SoC + * + * Copyright (C) 2018 Texas Instruments + * Author: Kishon Vijay Abraham I <kishon@ti.com> + */ + +#include <common.h> +#include <clk-uclass.h> +#include <dm.h> +#include <dm/device.h> +#include <dm/lists.h> +#include <dt-bindings/phy/phy.h> +#include <generic-phy.h> +#include <asm/io.h> +#include <asm/arch/sys_proto.h> +#include <power-domain.h> +#include <regmap.h> +#include <syscon.h> + +#define CMU_R07C 0x7c +#define CMU_MASTER_CDN_O BIT(24) + +#define COMLANE_R138 0xb38 +#define CONFIG_VERSION_REG_MASK GENMASK(23, 16) +#define CONFIG_VERSION_REG_SHIFT 16 +#define VERSION 0x70 + +#define COMLANE_R190 0xb90 +#define L1_MASTER_CDN_O BIT(9) + +#define COMLANE_R194 0xb94 +#define CMU_OK_I_0 BIT(19) + +#define SERDES_CTRL 0x1fd0 +#define POR_EN BIT(29) + +#define WIZ_LANEXCTL_STS 0x1fe0 +#define TX0_ENABLE_OVL BIT(31) +#define TX0_ENABLE_MASK GENMASK(30, 29) +#define TX0_ENABLE_SHIFT 29 +#define TX0_DISABLE_STATE 0x0 +#define TX0_SLEEP_STATE 0x1 +#define TX0_SNOOZE_STATE 0x2 +#define TX0_ENABLE_STATE 0x3 +#define RX0_ENABLE_OVL BIT(15) +#define RX0_ENABLE_MASK GENMASK(14, 13) +#define RX0_ENABLE_SHIFT 13 +#define RX0_DISABLE_STATE 0x0 +#define RX0_SLEEP_STATE 0x1 +#define RX0_SNOOZE_STATE 0x2 +#define RX0_ENABLE_STATE 0x3 + +#define WIZ_PLL_CTRL 0x1ff4 +#define PLL_ENABLE_OVL BIT(31) +#define PLL_ENABLE_MASK GENMASK(30, 29) +#define PLL_ENABLE_SHIFT 29 +#define PLL_DISABLE_STATE 0x0 +#define PLL_SLEEP_STATE 0x1 +#define PLL_SNOOZE_STATE 0x2 +#define PLL_ENABLE_STATE 0x3 +#define PLL_OK BIT(28) + +#define PLL_LOCK_TIME 1000 /* in milliseconds */ +#define SLEEP_TIME 100 /* in microseconds */ + +#define LANE_USB3 0x0 +#define LANE_PCIE0_LANE0 0x1 + +#define LANE_PCIE1_LANE0 0x0 +#define LANE_PCIE0_LANE1 0x1 + +#define SERDES_NUM_CLOCKS 3 + +/* SERDES control MMR bit offsets */ +#define SERDES_CTL_LANE_FUNC_SEL_SHIFT 0 +#define SERDES_CTL_LANE_FUNC_SEL_MASK GENMASK(1, 0) +#define SERDES_CTL_CLK_SEL_SHIFT 4 +#define SERDES_CTL_CLK_SEL_MASK GENMASK(7, 4) + +/** + * struct serdes_am654_mux_clk_data - clock controller information structure + */ +struct serdes_am654_mux_clk_data { + struct regmap *regmap; + struct clk_bulk parents; +}; + +static int serdes_am654_mux_clk_probe(struct udevice *dev) +{ + struct serdes_am654_mux_clk_data *data = dev_get_priv(dev); + struct udevice *syscon; + struct regmap *regmap; + int ret; + + debug("%s(dev=%s)\n", __func__, dev->name); + + if (!data) + return -ENOMEM; + + ret = uclass_get_device_by_phandle(UCLASS_SYSCON, dev, + "ti,serdes-clk", &syscon); + if (ret) { + dev_err(dev, "unable to find syscon device\n"); + return ret; + } + + regmap = syscon_get_regmap(syscon); + if (IS_ERR(regmap)) { + dev_err(dev, "Fail to get Syscon regmap\n"); + return PTR_ERR(regmap); + } + + data->regmap = regmap; + + ret = clk_get_bulk(dev, &data->parents); + if (ret) { + dev_err(dev, "Failed to obtain parent clocks\n"); + return ret; + } + + return 0; +} + +static int mux_table[SERDES_NUM_CLOCKS][3] = { + /* + * The entries represent values for selecting between + * {left input, external reference clock, right input} + * Only one of Left Output or Right Output should be used since + * both left and right output clock uses the same bits and modifying + * one clock will impact the other. + */ + { BIT(2), 0, BIT(0) }, /* Mux of CMU refclk */ + { -1, BIT(3), BIT(1) }, /* Mux of Left Output */ + { BIT(1), BIT(3) | BIT(1), -1 }, /* Mux of Right Output */ +}; + +static int serdes_am654_mux_clk_set_parent(struct clk *clk, struct clk *parent) +{ + struct serdes_am654_mux_clk_data *data = dev_get_priv(clk->dev); + u32 val; + int i; + + debug("%s(clk=%s, parent=%s)\n", __func__, clk->dev->name, + parent->dev->name); + + /* + * Since we have the same device-tree node represent both the + * clock and serdes device, we have two devices associated with + * the serdes node. assigned-clocks for this node is processed twice, + * once for the clock device and another time for the serdes + * device. When it is processed for the clock device, it is before + * the probe for clock device has been called. We ignore this case + * and rely on assigned-clocks to be processed correctly for the + * serdes case. + */ + if (!data->regmap) + return 0; + + for (i = 0; i < data->parents.count; i++) { + if (clk_is_match(&data->parents.clks[i], parent)) + break; + } + + if (i >= data->parents.count) + return -EINVAL; + + val = mux_table[clk->id][i]; + val <<= SERDES_CTL_CLK_SEL_SHIFT; + + regmap_update_bits(data->regmap, 0, SERDES_CTL_CLK_SEL_MASK, val); + + return 0; +} + +static struct clk_ops serdes_am654_mux_clk_ops = { + .set_parent = serdes_am654_mux_clk_set_parent, +}; + +U_BOOT_DRIVER(serdes_am654_mux_clk) = { + .name = "ti-serdes-am654-mux-clk", + .id = UCLASS_CLK, + .probe = serdes_am654_mux_clk_probe, + .priv_auto_alloc_size = sizeof(struct serdes_am654_mux_clk_data), + .ops = &serdes_am654_mux_clk_ops, +}; + +struct serdes_am654 { + struct regmap *regmap; + struct regmap *serdes_ctl; +}; + +static int serdes_am654_enable_pll(struct serdes_am654 *phy) +{ + u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK; + u32 val = PLL_ENABLE_OVL | (PLL_ENABLE_STATE << PLL_ENABLE_SHIFT); + + regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, val); + + return regmap_read_poll_timeout(phy->regmap, WIZ_PLL_CTRL, val, + val & PLL_OK, 1000, PLL_LOCK_TIME); +} + +static void serdes_am654_disable_pll(struct serdes_am654 *phy) +{ + u32 mask = PLL_ENABLE_OVL | PLL_ENABLE_MASK; + + regmap_update_bits(phy->regmap, WIZ_PLL_CTRL, mask, 0); +} + +static int serdes_am654_enable_txrx(struct serdes_am654 *phy) +{ + u32 mask; + u32 val; + + /* Enable TX */ + mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK; + val = TX0_ENABLE_OVL | (TX0_ENABLE_STATE << TX0_ENABLE_SHIFT); + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val); + + /* Enable RX */ + mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK; + val = RX0_ENABLE_OVL | (RX0_ENABLE_STATE << RX0_ENABLE_SHIFT); + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, val); + + return 0; +} + +static int serdes_am654_disable_txrx(struct serdes_am654 *phy) +{ + u32 mask; + + /* Disable TX */ + mask = TX0_ENABLE_OVL | TX0_ENABLE_MASK; + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0); + + /* Disable RX */ + mask = RX0_ENABLE_OVL | RX0_ENABLE_MASK; + regmap_update_bits(phy->regmap, WIZ_LANEXCTL_STS, mask, 0); + + return 0; +} + +static int serdes_am654_power_on(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + int ret; + u32 val; + + ret = serdes_am654_enable_pll(phy); + if (ret) { + dev_err(x->dev, "Failed to enable PLL\n"); + return ret; + } + + ret = serdes_am654_enable_txrx(phy); + if (ret) { + dev_err(x->dev, "Failed to enable TX RX\n"); + return ret; + } + + return regmap_read_poll_timeout(phy->regmap, COMLANE_R194, val, + val & CMU_OK_I_0, SLEEP_TIME, + PLL_LOCK_TIME); +} + +static int serdes_am654_power_off(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + + serdes_am654_disable_txrx(phy); + serdes_am654_disable_pll(phy); + + return 0; +} + +static int serdes_am654_init(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + u32 mask; + u32 val; + + mask = CONFIG_VERSION_REG_MASK; + val = VERSION << CONFIG_VERSION_REG_SHIFT; + regmap_update_bits(phy->regmap, COMLANE_R138, mask, val); + + val = CMU_MASTER_CDN_O; + regmap_update_bits(phy->regmap, CMU_R07C, val, val); + + val = L1_MASTER_CDN_O; + regmap_update_bits(phy->regmap, COMLANE_R190, val, val); + + return 0; +} + +static int serdes_am654_reset(struct phy *x) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + u32 val; + + val = POR_EN; + regmap_update_bits(phy->regmap, SERDES_CTRL, val, val); + mdelay(1); + regmap_update_bits(phy->regmap, SERDES_CTRL, val, 0); + + return 0; +} + +static int serdes_am654_of_xlate(struct phy *x, + struct ofnode_phandle_args *args) +{ + struct serdes_am654 *phy = dev_get_priv(x->dev); + + if (args->args_count != 2) { + dev_err(phy->dev, "Invalid DT PHY argument count: %d\n", + args->args_count); + return -EINVAL; + } + + if (args->args[0] != PHY_TYPE_PCIE) { + dev_err(phy->dev, "Unrecognized PHY type: %d\n", + args->args[0]); + return -EINVAL; + } + + x->id = args->args[0] | (args->args[1] << 16); + + /* Setup mux mode using second argument */ + regmap_update_bits(phy->serdes_ctl, 0, SERDES_CTL_LANE_FUNC_SEL_MASK, + args->args[1]); + + return 0; +} + +static int serdes_am654_bind(struct udevice *dev) +{ + int ret; + + ret = device_bind_driver_to_node(dev->parent, + "ti-serdes-am654-mux-clk", + dev_read_name(dev), dev->node, + NULL); + if (ret) { + dev_err(dev, "%s: not able to bind clock driver\n", __func__); + return ret; + } + + return 0; +} + +static int serdes_am654_probe(struct udevice *dev) +{ + struct serdes_am654 *phy = dev_get_priv(dev); + struct power_domain serdes_pwrdmn; + struct regmap *serdes_ctl; + struct regmap *map; + int ret; + + ret = regmap_init_mem(dev_ofnode(dev), &map); + if (ret) + return ret; + + phy->regmap = map; + + serdes_ctl = syscon_regmap_lookup_by_phandle(dev, "ti,serdes-clk"); + if (IS_ERR(serdes_ctl)) { + dev_err(dev, "unable to find syscon device\n"); + return PTR_ERR(serdes_ctl); + } + + phy->serdes_ctl = serdes_ctl; + + ret = power_domain_get_by_index(dev, &serdes_pwrdmn, 0); + if (ret) { + dev_err(dev, "failed to get power domain\n"); + return ret; + } + + ret = power_domain_on(&serdes_pwrdmn); + if (ret) { + dev_err(dev, "Power domain on failed\n"); + return ret; + } + + return 0; +} + +static const struct udevice_id serdes_am654_phy_ids[] = { + { + .compatible = "ti,phy-am654-serdes", + }, +}; + +static const struct phy_ops serdes_am654_phy_ops = { + .reset = serdes_am654_reset, + .init = serdes_am654_init, + .power_on = serdes_am654_power_on, + .power_off = serdes_am654_power_off, + .of_xlate = serdes_am654_of_xlate, +}; + +U_BOOT_DRIVER(am654_serdes_phy) = { + .name = "am654_serdes_phy", + .id = UCLASS_PHY, + .of_match = serdes_am654_phy_ids, + .bind = serdes_am654_bind, + .ops = &serdes_am654_phy_ops, + .probe = serdes_am654_probe, + .priv_auto_alloc_size = sizeof(struct serdes_am654), +}; diff --git a/drivers/power/domain/ti-sci-power-domain.c b/drivers/power/domain/ti-sci-power-domain.c index b9cd37b612..4c4351d2d9 100644 --- a/drivers/power/domain/ti-sci-power-domain.c +++ b/drivers/power/domain/ti-sci-power-domain.c @@ -68,8 +68,8 @@ static int ti_sci_power_domain_on(struct power_domain *pd) ret = dops->get_device(sci, pd->id); if (ret) - dev_err(power_domain->dev, "%s: get_device failed (%d)\n", - __func__, ret); + dev_err(pd->dev, "%s: get_device(%lu) failed (%d)\n", + __func__, pd->id, ret); return ret; } @@ -85,8 +85,8 @@ static int ti_sci_power_domain_off(struct power_domain *pd) ret = dops->put_device(sci, pd->id); if (ret) - dev_err(power_domain->dev, "%s: put_device failed (%d)\n", - __func__, ret); + dev_err(pd->dev, "%s: put_device(%lu) failed (%d)\n", + __func__, pd->id, ret); return ret; } diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 505ae9b45f..6e4d732a07 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -14,7 +14,6 @@ #include <linux/immap_qe.h> #include <fsl_qe.h> #include <mmc.h> -#include <environment.h> #ifdef CONFIG_ARCH_LS1021A #include <asm/arch/immap_ls102xa.h> diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index 822a3fe265..93ec9cfdb6 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -16,6 +16,7 @@ #include <dm.h> #include <dm/lists.h> #include <dm/of_access.h> +#include <env.h> #include <reset-uclass.h> #include <linux/bitops.h> #include <linux/io.h> diff --git a/drivers/rtc/m41t60.c b/drivers/rtc/m41t60.c index c84c8e11b3..532d2105e1 100644 --- a/drivers/rtc/m41t60.c +++ b/drivers/rtc/m41t60.c @@ -17,6 +17,7 @@ #include <common.h> #include <command.h> +#include <env.h> #include <rtc.h> #include <i2c.h> diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 75900d8228..48cb2a2818 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> +#include <env.h> #include <pci.h> #include <scsi.h> #include <dm/device-internal.h> diff --git a/drivers/serial/serial-uclass.c b/drivers/serial/serial-uclass.c index d4488a2cc2..dcdaedefe7 100644 --- a/drivers/serial/serial-uclass.c +++ b/drivers/serial/serial-uclass.c @@ -5,7 +5,7 @@ #include <common.h> #include <dm.h> -#include <environment.h> +#include <env_internal.h> #include <errno.h> #include <os.h> #include <serial.h> diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index 09365ba6a1..b907508dbe 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -5,7 +5,7 @@ */ #include <common.h> -#include <environment.h> +#include <env_internal.h> #include <serial.h> #include <stdio_dev.h> #include <post.h> diff --git a/drivers/serial/serial_lpuart.c b/drivers/serial/serial_lpuart.c index 57dd4a72c6..4b0a964d1b 100644 --- a/drivers/serial/serial_lpuart.c +++ b/drivers/serial/serial_lpuart.c @@ -106,7 +106,7 @@ u32 __weak get_lpuart_clk(void) return CONFIG_SYS_CLK_FREQ; } -#if IS_ENABLED(CONFIG_CLK) +#if CONFIG_IS_ENABLED(CLK) static int get_lpuart_clk_rate(struct udevice *dev, u32 *clk) { struct clk per_clk; @@ -148,7 +148,7 @@ static void _lpuart_serial_setbrg(struct udevice *dev, u16 sbr; int ret; - if (IS_ENABLED(CONFIG_CLK)) { + if (CONFIG_IS_ENABLED(CLK)) { ret = get_lpuart_clk_rate(dev, &clk); if (ret) return; @@ -237,7 +237,7 @@ static void _lpuart32_serial_setbrg_7ulp(struct udevice *dev, u32 clk; int ret; - if (IS_ENABLED(CONFIG_CLK)) { + if (CONFIG_IS_ENABLED(CLK)) { ret = get_lpuart_clk_rate(dev, &clk); if (ret) return; @@ -306,7 +306,7 @@ static void _lpuart32_serial_setbrg(struct udevice *dev, u32 sbr; int ret; - if (IS_ENABLED(CONFIG_CLK)) { + if (CONFIG_IS_ENABLED(CLK)) { ret = get_lpuart_clk_rate(dev, &clk); if (ret) return; diff --git a/drivers/serial/usbtty.c b/drivers/serial/usbtty.c index d0465b844e..76d9c8a3a6 100644 --- a/drivers/serial/usbtty.c +++ b/drivers/serial/usbtty.c @@ -10,6 +10,7 @@ #include <common.h> #include <config.h> #include <circbuf.h> +#include <env.h> #include <stdio_dev.h> #include <asm/unaligned.h> #include "usbtty.h" diff --git a/drivers/tee/sandbox.c b/drivers/tee/sandbox.c index 2f3355c7b7..4b91e7db1b 100644 --- a/drivers/tee/sandbox.c +++ b/drivers/tee/sandbox.c @@ -79,7 +79,7 @@ static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params, struct tee_param *params) { struct sandbox_tee_state *state = dev_get_priv(dev); - ENTRY e, *ep; + struct env_entry e, *ep; char *name; u32 res; uint slot; @@ -174,7 +174,7 @@ static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params, e.key = name; e.data = NULL; - hsearch_r(e, FIND, &ep, &state->pstorage_htab, 0); + hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0); if (!ep) return TEE_ERROR_ITEM_NOT_FOUND; @@ -198,13 +198,13 @@ static u32 ta_avb_invoke_func(struct udevice *dev, u32 func, uint num_params, e.key = name; e.data = NULL; - hsearch_r(e, FIND, &ep, &state->pstorage_htab, 0); + hsearch_r(e, ENV_FIND, &ep, &state->pstorage_htab, 0); if (ep) hdelete_r(e.key, &state->pstorage_htab, 0); e.key = name; e.data = value; - hsearch_r(e, ENTER, &ep, &state->pstorage_htab, 0); + hsearch_r(e, ENV_ENTER, &ep, &state->pstorage_htab, 0); if (!ep) return TEE_ERROR_OUT_OF_MEMORY; diff --git a/drivers/usb/gadget/designware_udc.c b/drivers/usb/gadget/designware_udc.c index fa947dade6..432f312cee 100644 --- a/drivers/usb/gadget/designware_udc.c +++ b/drivers/usb/gadget/designware_udc.c @@ -10,6 +10,7 @@ #include <common.h> #include <asm/io.h> +#include <env.h> #include <usbdevice.h> #include "ep0.h" #include <usb/designware_udc.h> diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 0b5a1a4796..a118283984 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -9,7 +9,7 @@ #include <common.h> #include <console.h> -#include <environment.h> +#include <env.h> #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/usb/ch9.h> diff --git a/drivers/usb/gadget/f_dfu.c b/drivers/usb/gadget/f_dfu.c index e27f146605..6756155133 100644 --- a/drivers/usb/gadget/f_dfu.c +++ b/drivers/usb/gadget/f_dfu.c @@ -14,6 +14,7 @@ * (C) Copyright 2006 by Harald Welte <hwelte at hmw-consulting.de> */ +#include <env.h> #include <errno.h> #include <common.h> #include <malloc.h> diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 3ad4346f2d..fc27dbe8de 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -11,6 +11,7 @@ */ #include <config.h> #include <common.h> +#include <env.h> #include <errno.h> #include <fastboot.h> #include <malloc.h> diff --git a/drivers/usb/gadget/f_rockusb.c b/drivers/usb/gadget/f_rockusb.c index f3d24772cd..1cfeabcd31 100644 --- a/drivers/usb/gadget/f_rockusb.c +++ b/drivers/usb/gadget/f_rockusb.c @@ -6,6 +6,7 @@ */ #include <config.h> #include <common.h> +#include <env.h> #include <errno.h> #include <malloc.h> #include <memalign.h> diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index fab7ce6f97..bcd1c5d47c 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -19,6 +19,7 @@ #include <errno.h> #include <common.h> #include <console.h> +#include <env.h> #include <malloc.h> #include <linux/usb/ch9.h> diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b8f8e7a794..ced295ef0f 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -8,6 +8,7 @@ */ #include <common.h> +#include <env.h> #include <pci.h> #include <usb.h> #include <asm/io.h> diff --git a/drivers/video/ati_radeon_fb.c b/drivers/video/ati_radeon_fb.c index 87557e52c0..6fce033636 100644 --- a/drivers/video/ati_radeon_fb.c +++ b/drivers/video/ati_radeon_fb.c @@ -19,6 +19,7 @@ #include <command.h> #include <bios_emul.h> +#include <env.h> #include <pci.h> #include <asm/processor.h> #include <linux/errno.h> diff --git a/drivers/video/cfb_console.c b/drivers/video/cfb_console.c index 636c3e8c18..e5c077e4f5 100644 --- a/drivers/video/cfb_console.c +++ b/drivers/video/cfb_console.c @@ -65,7 +65,9 @@ */ #include <common.h> +#include <env.h> #include <fdtdec.h> +#include <gzip.h> #include <version.h> #include <malloc.h> #include <video.h> diff --git a/drivers/video/mb862xx.c b/drivers/video/mb862xx.c index 1a3c970b3d..301c1f0df1 100644 --- a/drivers/video/mb862xx.c +++ b/drivers/video/mb862xx.c @@ -12,6 +12,7 @@ #include <common.h> #include <asm/io.h> +#include <env.h> #include <pci.h> #include <video_fb.h> #include "videomodes.h" diff --git a/drivers/video/mx3fb.c b/drivers/video/mx3fb.c index 176ae70b7c..a984443ef9 100644 --- a/drivers/video/mx3fb.c +++ b/drivers/video/mx3fb.c @@ -6,6 +6,7 @@ * HALE electronic GmbH, <helmut.raiger@hale.at> */ #include <common.h> +#include <env.h> #include <malloc.h> #include <video_fb.h> diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 6c9a7c05e8..6922a130c6 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -6,6 +6,7 @@ */ #include <common.h> #include <dm.h> +#include <env.h> #include <linux/errno.h> #include <malloc.h> #include <video.h> diff --git a/drivers/video/videomodes.c b/drivers/video/videomodes.c index d7614329ff..ac25b45f81 100644 --- a/drivers/video/videomodes.c +++ b/drivers/video/videomodes.c @@ -58,6 +58,7 @@ #include <common.h> #include <edid.h> +#include <env.h> #include <errno.h> #include <linux/ctype.h> diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 1e5d14c4ff..a66a9bcbe2 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -28,7 +28,6 @@ config OMAP_WATCHDOG bool "TI OMAP watchdog driver" depends on ARCH_OMAP2PLUS select HW_WATCHDOG - default y if AM33XX help Say Y here to enable the OMAP3+ watchdog driver. @@ -113,6 +112,14 @@ config WDT_MTK The watchdog timer is stopped when initialized. It performs full SoC reset. +config WDT_OMAP3 + bool "TI OMAP watchdog timer support" + depends on WDT && ARCH_OMAP2PLUS + default y if AM33XX + help + This enables OMAP3+ watchdog timer driver, which can be + found on some TI chipsets and inline with driver model. + config WDT_ORION bool "Orion watchdog timer support" depends on WDT diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 414ba2430a..955caef815 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_WDT_CDNS) += cdns_wdt.o obj-$(CONFIG_WDT_MPC8xx) += mpc8xx_wdt.o obj-$(CONFIG_WDT_MT7621) += mt7621_wdt.o obj-$(CONFIG_WDT_MTK) += mtk_wdt.o +obj-$(CONFIG_WDT_OMAP3) += omap_wdt.o obj-$(CONFIG_WDT_SP805) += sp805_wdt.o obj-$(CONFIG_WDT_STM32MP) += stm32mp_wdt.o obj-$(CONFIG_WDT_TANGIER) += tangier_wdt.o diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 343adb00c7..d5857be867 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c @@ -42,10 +42,14 @@ #include <asm/io.h> #include <asm/processor.h> #include <asm/arch/cpu.h> +#include <wdt.h> +#include <dm.h> +#include <errno.h> /* Hardware timeout in seconds */ #define WDT_HW_TIMEOUT 60 +#if !CONFIG_IS_ENABLED(WDT) static unsigned int wdt_trgr_pattern = 0x1234; void hw_watchdog_reset(void) @@ -134,3 +138,120 @@ void hw_watchdog_init(void) while ((readl(&wdt->wdtwwps)) & WDT_WWPS_PEND_WSPR) ; } + +void watchdog_reset(void) +{ + hw_watchdog_reset(); +} + +#else + +static int omap3_wdt_reset(struct udevice *dev) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + + priv->wdt_trgr_pattern = 0x1234; +/* + * Somebody just triggered watchdog reset and write to WTGR register + * is in progress. It is resetting right now, no need to trigger it + * again + */ + if ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WTGR) + return 0; + + priv->wdt_trgr_pattern = ~(priv->wdt_trgr_pattern); + writel(priv->wdt_trgr_pattern, &priv->regs->wdtwtgr); +/* + * Don't wait for posted write to complete, i.e. don't check + * WDT_WWPS_PEND_WTGR bit in WWPS register. There is no writes to + * WTGR register outside of this func, and if entering it + * we see WDT_WWPS_PEND_WTGR bit set, it means watchdog reset + * was just triggered. This prevents us from wasting time in busy + * polling of WDT_WWPS_PEND_WTGR bit. + */ + return 0; +} + +static int omap3_wdt_stop(struct udevice *dev) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + +/* disable watchdog */ + writel(0xAAAA, &priv->regs->wdtwspr); + while (readl(&priv->regs->wdtwwps) != 0x0) + ; + writel(0x5555, &priv->regs->wdtwspr); + while (readl(&priv->regs->wdtwwps) != 0x0) + ; + return 0; +} + +static int omap3_wdt_start(struct udevice *dev, u64 timeout_ms, ulong flags) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + u32 pre_margin = GET_WLDR_VAL(timeout_ms); +/* + * Make sure the watchdog is disabled. This is unfortunately required + * because writing to various registers with the watchdog running has no + * effect. + */ + omap3_wdt_stop(dev); + +/* initialize prescaler */ + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR) + ; + + writel(WDT_WCLR_PRE | (PTV << WDT_WCLR_PTV_OFF), &priv->regs->wdtwclr); + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WCLR) + ; +/* just count up at 32 KHz */ + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR) + ; + + writel(pre_margin, &priv->regs->wdtwldr); + while (readl(&priv->regs->wdtwwps) & WDT_WWPS_PEND_WLDR) + ; +/* Sequence to enable the watchdog */ + writel(0xBBBB, &priv->regs->wdtwspr); + while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR) + ; + + writel(0x4444, &priv->regs->wdtwspr); + while ((readl(&priv->regs->wdtwwps)) & WDT_WWPS_PEND_WSPR) + ; + + return 0; +} + +static int omap3_wdt_probe(struct udevice *dev) +{ + struct omap3_wdt_priv *priv = dev_get_priv(dev); + + priv->regs = (struct wd_timer *)devfdt_get_addr(dev); + if (!priv->regs) + return -EINVAL; + + debug("%s: Probing wdt%u\n", __func__, dev->seq); + return 0; +} + +static const struct wdt_ops omap3_wdt_ops = { + .start = omap3_wdt_start, + .stop = omap3_wdt_stop, + .reset = omap3_wdt_reset, +}; + +static const struct udevice_id omap3_wdt_ids[] = { + { .compatible = "ti,omap3-wdt" }, + { } +}; + +U_BOOT_DRIVER(omap3_wdt) = { + .name = "omap3_wdt", + .id = UCLASS_WDT, + .of_match = omap3_wdt_ids, + .ops = &omap3_wdt_ops, + .probe = omap3_wdt_probe, + .priv_auto_alloc_size = sizeof(struct omap3_wdt_priv), +}; +#endif /* !CONFIG_IS_ENABLED(WDT) */ |