diff options
Diffstat (limited to 'drivers')
216 files changed, 7907 insertions, 5390 deletions
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 049f7ef..9bc5283 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -20,14 +20,6 @@ config SATA See also CMD_SATA which provides command-line support. -config SYS_SATA_MAX_PORTS - int "Maximum supported SATA ports" - depends on SCSI_AHCI && !DM_SCSI - default 1 - help - Sets the maximum number of ports to scan when looking for devices. - Ports from 0 to (this value - 1) are scanned. - config LIBATA bool help @@ -44,7 +36,7 @@ menu "SATA/SCSI device support" config AHCI_PCI bool "Support for PCI-based AHCI controller" depends on PCI - depends on DM_SCSI + depends on SCSI depends on SCSI_AHCI help Enables support for the PCI-based AHCI controller. @@ -55,13 +47,13 @@ config SPL_AHCI_PCI bool "Support for PCI-based AHCI controller for SPL" depends on SPL depends on SPL_PCI - depends on SPL_SATA && DM_SCSI + depends on SPL_SATA && SCSI config DWC_AHCI bool "Enable Synopsys DWC AHCI driver support" select SCSI_AHCI select PHY - depends on DM_SCSI + depends on SCSI help Enable this driver to support Sata devices through Synopsys DWC AHCI module. @@ -91,7 +83,7 @@ config AHCI_MVEBU bool "Marvell EBU AHCI SATA support" depends on ARCH_MVEBU || ARCH_OCTEON select SCSI_AHCI - select DM_SCSI + select SCSI help This option enables support for the Marvell EBU SoC's onboard AHCI SATA. @@ -112,7 +104,7 @@ if SATA config SATA_CEVA bool "Ceva Sata controller" depends on AHCI - depends on DM_SCSI + depends on SCSI help This option enables Ceva Sata controller hard IP available on Xilinx ZynqMP. Support up to 2 external devices. Compliant with SATA 3.1 and diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 0b6f910..af6f0bf 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -14,7 +14,6 @@ obj-$(CONFIG_SATA) += sata.o sata_bootdev.o obj-$(CONFIG_SATA_CEVA) += sata_ceva.o obj-$(CONFIG_SATA_MV) += sata_mv.o obj-$(CONFIG_SATA_SIL) += sata_sil.o -obj-$(CONFIG_SANDBOX) += sata_sandbox.o obj-$(CONFIG_AHCI_MVEBU) += ahci_mvebu.o obj-$(CONFIG_SUNXI_AHCI) += ahci_sunxi.o obj-$(CONFIG_MTK_AHCI) += mtk_ahci.o diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index cb2c648..04ddc33 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -33,10 +33,6 @@ static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port); -#ifndef CONFIG_DM_SCSI -struct ahci_uc_priv *probe_ent = NULL; -#endif - #define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0) /* @@ -169,11 +165,6 @@ int ahci_reset(void __iomem *base) static int ahci_host_init(struct ahci_uc_priv *uc_priv) { -#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) - struct udevice *dev = uc_priv->dev; - struct pci_child_plat *pplat = dev_get_parent_plat(dev); - u16 tmp16; -#endif void __iomem *mmio = uc_priv->mmio_base; u32 tmp, cap_save, cmd; int i, j, ret; @@ -194,14 +185,6 @@ static int ahci_host_init(struct ahci_uc_priv *uc_priv) writel(cap_save, mmio + HOST_CAP); writel_with_flush(0xf, mmio + HOST_PORTS_IMPL); -#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) - if (pplat->vendor == PCI_VENDOR_ID_INTEL) { - u16 tmp16; - - dm_pci_read_config16(dev, 0x92, &tmp16); - dm_pci_write_config16(dev, 0x92, tmp16 | 0xf); - } -#endif uc_priv->cap = readl(mmio + HOST_CAP); uc_priv->port_map = readl(mmio + HOST_PORTS_IMPL); port_map = uc_priv->port_map; @@ -210,11 +193,6 @@ static int ahci_host_init(struct ahci_uc_priv *uc_priv) debug("cap 0x%x port_map 0x%x n_ports %d\n", uc_priv->cap, uc_priv->port_map, uc_priv->n_ports); -#if !defined(CONFIG_DM_SCSI) - if (uc_priv->n_ports > CONFIG_SYS_SATA_MAX_PORTS) - uc_priv->n_ports = CONFIG_SYS_SATA_MAX_PORTS; -#endif - for (i = 0; i < uc_priv->n_ports; i++) { if (!(port_map & (1 << i))) continue; @@ -313,23 +291,12 @@ static int ahci_host_init(struct ahci_uc_priv *uc_priv) writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL); tmp = readl(mmio + HOST_CTL); debug("HOST_CTL 0x%x\n", tmp); -#if !defined(CONFIG_DM_SCSI) -#ifndef CONFIG_SCSI_AHCI_PLAT - dm_pci_read_config16(dev, PCI_COMMAND, &tmp16); - tmp |= PCI_COMMAND_MASTER; - dm_pci_write_config16(dev, PCI_COMMAND, tmp16); -#endif -#endif return 0; } static void ahci_print_info(struct ahci_uc_priv *uc_priv) { -#if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI) - struct udevice *dev = uc_priv->dev; - u16 cc; -#endif void __iomem *mmio = uc_priv->mmio_base; u32 vers, cap, cap2, impl, speed; const char *speed_s; @@ -350,19 +317,7 @@ static void ahci_print_info(struct ahci_uc_priv *uc_priv) else speed_s = "?"; -#if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI) scc_s = "SATA"; -#else - dm_pci_read_config16(dev, 0x0a, &cc); - if (cc == 0x0101) - scc_s = "IDE"; - else if (cc == 0x0106) - scc_s = "SATA"; - else if (cc == 0x0104) - scc_s = "RAID"; - else - scc_s = "unknown"; -#endif printf("AHCI %02x%02x.%02x%02x " "%u slots %u ports %s Gbps 0x%x impl %s mode\n", (vers >> 24) & 0xff, @@ -397,12 +352,8 @@ static void ahci_print_info(struct ahci_uc_priv *uc_priv) cap2 & (1 << 0) ? "boh " : ""); } -#if defined(CONFIG_DM_SCSI) || !defined(CONFIG_SCSI_AHCI_PLAT) static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev) { -#if !defined(CONFIG_DM_SCSI) - u16 vendor; -#endif int rc; uc_priv->dev = dev; @@ -415,21 +366,8 @@ static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev) uc_priv->pio_mask = 0x1f; uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ -#if !defined(CONFIG_DM_SCSI) - uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5, 0, 0, - PCI_REGION_TYPE, PCI_REGION_MEM); - - /* Take from kernel: - * JMicron-specific fixup: - * make sure we're in AHCI mode - */ - dm_pci_read_config16(dev, PCI_VENDOR_ID, &vendor); - if (vendor == 0x197b) - dm_pci_write_config8(dev, 0x41, 0xa1); -#else struct scsi_plat *plat = dev_get_uclass_plat(dev); uc_priv->mmio_base = (void *)plat->base; -#endif debug("ahci mmio_base=0x%p\n", uc_priv->mmio_base); /* initialize adapter */ @@ -444,7 +382,6 @@ static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev) err_out: return rc; } -#endif #define MAX_DATA_BYTE_COUNT (4*1024*1024) @@ -893,12 +830,7 @@ static int ata_scsiop_test_unit_ready(struct ahci_uc_priv *uc_priv, static int ahci_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) { - struct ahci_uc_priv *uc_priv; -#ifdef CONFIG_DM_SCSI - uc_priv = dev_get_uclass_priv(dev->parent); -#else - uc_priv = probe_ent; -#endif + struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev->parent); int ret; switch (pccb->cmd[0]) { @@ -953,41 +885,12 @@ static int ahci_start_ports(struct ahci_uc_priv *uc_priv) return 0; } -#ifndef CONFIG_DM_SCSI -void scsi_low_level_init(int busdevfunc) -{ - struct ahci_uc_priv *uc_priv; - -#ifndef CONFIG_SCSI_AHCI_PLAT - probe_ent = calloc(1, sizeof(struct ahci_uc_priv)); - if (!probe_ent) { - printf("%s: No memory for uc_priv\n", __func__); - return; - } - uc_priv = probe_ent; - struct udevice *dev; - int ret; - - ret = dm_pci_bus_find_bdf(busdevfunc, &dev); - if (ret) - return; - ahci_init_one(uc_priv, dev); -#else - uc_priv = probe_ent; -#endif - - ahci_start_ports(uc_priv); -} -#endif - -#ifndef CONFIG_SCSI_AHCI_PLAT int ahci_init_one_dm(struct udevice *dev) { struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); return ahci_init_one(uc_priv, dev); } -#endif int ahci_start_ports_dm(struct udevice *dev) { @@ -996,65 +899,6 @@ int ahci_start_ports_dm(struct udevice *dev) return ahci_start_ports(uc_priv); } -#ifdef CONFIG_SCSI_AHCI_PLAT -static int ahci_init_common(struct ahci_uc_priv *uc_priv, void __iomem *base) -{ - int rc; - - uc_priv->host_flags = ATA_FLAG_SATA - | ATA_FLAG_NO_LEGACY - | ATA_FLAG_MMIO - | ATA_FLAG_PIO_DMA - | ATA_FLAG_NO_ATAPI; - uc_priv->pio_mask = 0x1f; - uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */ - - uc_priv->mmio_base = base; - - /* initialize adapter */ - rc = ahci_host_init(uc_priv); - if (rc) - goto err_out; - - ahci_print_info(uc_priv); - - rc = ahci_start_ports(uc_priv); - -err_out: - return rc; -} - -#ifndef CONFIG_DM_SCSI -int ahci_init(void __iomem *base) -{ - struct ahci_uc_priv *uc_priv; - - probe_ent = malloc(sizeof(struct ahci_uc_priv)); - if (!probe_ent) { - printf("%s: No memory for uc_priv\n", __func__); - return -ENOMEM; - } - - uc_priv = probe_ent; - memset(uc_priv, 0, sizeof(struct ahci_uc_priv)); - - return ahci_init_common(uc_priv, base); -} -#endif - -int ahci_init_dm(struct udevice *dev, void __iomem *base) -{ - struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev); - - return ahci_init_common(uc_priv, base); -} - -void __weak scsi_init(void) -{ -} - -#endif /* CONFIG_SCSI_AHCI_PLAT */ - /* * In the general case of generic rotating media it makes sense to have a * flush capability. It probably even makes sense in the case of SSDs because @@ -1098,7 +942,6 @@ static int ahci_scsi_bus_reset(struct udevice *dev) return 0; } -#ifdef CONFIG_DM_SCSI int ahci_bind_scsi(struct udevice *ahci_dev, struct udevice **devp) { struct udevice *dev; @@ -1190,16 +1033,3 @@ U_BOOT_DRIVER(ahci_scsi) = { .id = UCLASS_SCSI, .ops = &scsi_ops, }; -#else -int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) -{ - return ahci_scsi_exec(dev, pccb); -} - -__weak int scsi_bus_reset(struct udevice *dev) -{ - return ahci_scsi_bus_reset(dev); - - return 0; -} -#endif diff --git a/drivers/ata/sata.c b/drivers/ata/sata.c index 64fc078..784d9bbe 100644 --- a/drivers/ata/sata.c +++ b/drivers/ata/sata.c @@ -18,10 +18,6 @@ #include <dm/device-internal.h> #include <dm/uclass-internal.h> -#ifndef CONFIG_AHCI -struct blk_desc sata_dev_desc[CONFIG_SYS_SATA_MAX_DEVICE]; -#endif - int sata_reset(struct udevice *dev) { struct ahci_ops *ops = ahci_get_ops(dev); @@ -88,15 +84,6 @@ int sata_rescan(bool verbose) return ret; } -#ifndef CONFIG_AHCI -#ifdef CONFIG_PARTITIONS -struct blk_desc *sata_get_dev(int dev) -{ - return (dev < CONFIG_SYS_SATA_MAX_DEVICE) ? &sata_dev_desc[dev] : NULL; -} -#endif -#endif - static unsigned long sata_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst) { @@ -109,51 +96,6 @@ static unsigned long sata_bwrite(struct udevice *dev, lbaint_t start, return -ENOSYS; } -#ifndef CONFIG_AHCI -int __sata_initialize(void) -{ - int rc, ret = -1; - int i; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) { - memset(&sata_dev_desc[i], 0, sizeof(struct blk_desc)); - sata_dev_desc[i].uclass_id = UCLASS_AHCI; - sata_dev_desc[i].devnum = i; - sata_dev_desc[i].part_type = PART_TYPE_UNKNOWN; - sata_dev_desc[i].type = DEV_TYPE_HARDDISK; - sata_dev_desc[i].lba = 0; - sata_dev_desc[i].blksz = 512; - sata_dev_desc[i].log2blksz = LOG2(sata_dev_desc[i].blksz); - rc = init_sata(i); - if (!rc) { - rc = scan_sata(i); - if (!rc && sata_dev_desc[i].lba > 0 && - sata_dev_desc[i].blksz > 0) { - part_init(&sata_dev_desc[i]); - ret = i; - } - } - } - - return ret; -} -int sata_initialize(void) __attribute__((weak, alias("__sata_initialize"))); - -__weak int __sata_stop(void) -{ - int i, err = 0; - - for (i = 0; i < CONFIG_SYS_SATA_MAX_DEVICE; i++) - err |= reset_sata(i); - - if (err) - printf("Could not reset some SATA devices\n"); - - return err; -} -int sata_stop(void) __attribute__((weak, alias("__sata_stop"))); -#endif - static const struct blk_ops sata_blk_ops = { .read = sata_bread, .write = sata_bwrite, diff --git a/drivers/ata/sata_sandbox.c b/drivers/ata/sata_sandbox.c deleted file mode 100644 index e64cc4a..0000000 --- a/drivers/ata/sata_sandbox.c +++ /dev/null @@ -1,33 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2015 Google, Inc - * Written by Simon Glass <sjg@chromium.org> - */ - -#include <common.h> -#include <blk.h> - -int init_sata(int dev) -{ - return 0; -} - -int reset_sata(int dev) -{ - return 0; -} - -int scan_sata(int dev) -{ - return 0; -} - -ulong sata_read(int dev, ulong blknr, lbaint_t blkcnt, void *buffer) -{ - return 0; -} - -ulong sata_write(int dev, ulong blknr, lbaint_t blkcnt, const void *buffer) -{ - return 0; -} diff --git a/drivers/bios_emulator/include/x86emu.h b/drivers/bios_emulator/include/x86emu.h index b28cdc6..d2650a8 100644 --- a/drivers/bios_emulator/include/x86emu.h +++ b/drivers/bios_emulator/include/x86emu.h @@ -42,7 +42,6 @@ #define __X86EMU_X86EMU_H #include <asm/types.h> -#include <common.h> #include <pci.h> #include <asm/io.h> #define X86API diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 048a6ca..6ad1888 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -13,7 +13,7 @@ config BLK config SPL_LEGACY_BLOCK bool # "Enable Legacy Block Device" - depends on SPL && !DM_SPL + depends on SPL default y if SPL_MMC || SPL_USB_STORAGE || SCSI || NVME || IDE default y if SPL_AHCI_PCI help @@ -265,6 +265,7 @@ config SYS_64BIT_LBA config RKMTD bool "Rockchip rkmtd virtual block device" + select RANDOM_UUID help Enable "rkmtd" class and driver to create a virtual block device to transfer Rockchip boot block data to and from NAND with block diff --git a/drivers/block/Makefile b/drivers/block/Makefile index fdcba5c..fe6a1fc 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -15,7 +15,8 @@ obj-$(CONFIG_RKMTD) += rkmtd.o endif obj-$(CONFIG_SANDBOX) += sandbox.o host-uclass.o host_dev.o obj-$(CONFIG_$(SPL_TPL_)BLOCK_CACHE) += blkcache.o -obj-$(CONFIG_BLKMAP) += blkmap.o +obj-$(CONFIG_$(SPL_TPL_)BLKMAP) += blkmap.o +obj-$(CONFIG_$(SPL_TPL_)BLKMAP) += blkmap_helper.o obj-$(CONFIG_EFI_MEDIA) += efi-media-uclass.o obj-$(CONFIG_EFI_MEDIA_SANDBOX) += sb_efi_media.o diff --git a/drivers/block/blkmap.c b/drivers/block/blkmap.c index 149a4ca..2120140 100644 --- a/drivers/block/blkmap.c +++ b/drivers/block/blkmap.c @@ -66,21 +66,6 @@ struct blkmap_slice { void (*destroy)(struct blkmap *bm, struct blkmap_slice *bms); }; -/** - * struct blkmap - Block map - * - * Data associated with a blkmap. - * - * @label: Human readable name of this blkmap - * @blk: Underlying block device - * @slices: List of slices associated with this blkmap - */ -struct blkmap { - char *label; - struct udevice *blk; - struct list_head slices; -}; - static bool blkmap_slice_contains(struct blkmap_slice *bms, lbaint_t blknr) { return (blknr >= bms->blknr) && (blknr < (bms->blknr + bms->blkcnt)); diff --git a/drivers/block/blkmap_helper.c b/drivers/block/blkmap_helper.c new file mode 100644 index 0000000..bfba141 --- /dev/null +++ b/drivers/block/blkmap_helper.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * blkmap helper function + * + * Copyright (c) 2023, Linaro Limited + */ + +#include <blk.h> +#include <blkmap.h> +#include <dm/device.h> +#include <dm/device-internal.h> + +int blkmap_create_ramdisk(const char *label, ulong image_addr, ulong image_size, + struct udevice **devp) +{ + int ret; + lbaint_t blknum; + struct blkmap *bm; + struct blk_desc *desc; + struct udevice *bm_dev; + + ret = blkmap_create(label, &bm_dev); + if (ret) { + log_err("failed to create blkmap\n"); + return ret; + } + + bm = dev_get_plat(bm_dev); + desc = dev_get_uclass_plat(bm->blk); + blknum = image_size >> desc->log2blksz; + ret = blkmap_map_pmem(bm_dev, 0, blknum, image_addr); + if (ret) { + log_err("Unable to map %#llx at block %d : %d\n", + (unsigned long long)image_addr, 0, ret); + goto err; + } + log_info("Block %d+0x" LBAF " mapped to %#llx\n", 0, blknum, + (unsigned long long)image_addr); + + ret = device_probe(bm->blk); + if (ret) + goto err; + + if (devp) + *devp = bm_dev; + + return 0; + +err: + blkmap_destroy(bm_dev); + + return ret; +} diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig index 6cb8c3e..26c2d80 100644 --- a/drivers/cache/Kconfig +++ b/drivers/cache/Kconfig @@ -45,4 +45,11 @@ config SIFIVE_CCACHE This driver is for SiFive Composable L2/L3 cache. It enables cache ways of composable cache. +config SIFIVE_PL2 + bool "SiFive private L2 cache" + select CACHE + help + This driver is for SiFive Private L2 cache. It configures registers + to enable the clock gating feature. + endmenu diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile index ad76577..78e673d 100644 --- a/drivers/cache/Makefile +++ b/drivers/cache/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_L2X0_CACHE) += cache-l2x0.o obj-$(CONFIG_NCORE_CACHE) += cache-ncore.o obj-$(CONFIG_V5L2_CACHE) += cache-v5l2.o obj-$(CONFIG_SIFIVE_CCACHE) += cache-sifive-ccache.o +obj-$(CONFIG_SIFIVE_PL2) += cache-sifive-pl2.o diff --git a/drivers/cache/cache-sifive-pl2.c b/drivers/cache/cache-sifive-pl2.c new file mode 100644 index 0000000..ae689e1 --- /dev/null +++ b/drivers/cache/cache-sifive-pl2.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2023 SiFive + */ + +#include <cache.h> +#include <dm.h> +#include <malloc.h> +#include <asm/io.h> +#include <dm/device.h> +#include <dm/device-internal.h> + +#define SIFIVE_PL2CHICKENBIT_OFFSET 0x1000 +#define SIFIVE_PL2CHICKENBIT_REGIONCLOCKDISABLE_MASK BIT(3) + +static int sifive_pl2_probe(struct udevice *dev) +{ + fdt_addr_t base; + u32 val; + + base = dev_read_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + /* Enable regionClockDisable bit */ + val = readl((void __iomem *)(base + SIFIVE_PL2CHICKENBIT_OFFSET)); + writel(val & ~SIFIVE_PL2CHICKENBIT_REGIONCLOCKDISABLE_MASK, + (void __iomem *)(base + SIFIVE_PL2CHICKENBIT_OFFSET)); + + return 0; +} + +static const struct udevice_id sifive_pl2_ids[] = { + { .compatible = "sifive,pl2cache0" }, + { .compatible = "sifive,pl2cache1" }, + {} +}; + +U_BOOT_DRIVER(sifive_pl2) = { + .name = "sifive_pl2", + .id = UCLASS_CACHE, + .of_match = sifive_pl2_ids, + .probe = sifive_pl2_probe, +}; diff --git a/drivers/clk/aspeed/clk_ast2600.c b/drivers/clk/aspeed/clk_ast2600.c index e5ada5b..eecfacd 100644 --- a/drivers/clk/aspeed/clk_ast2600.c +++ b/drivers/clk/aspeed/clk_ast2600.c @@ -1104,46 +1104,12 @@ static int ast2600_clk_enable(struct clk *clk) return 0; } -struct clk_ops ast2600_clk_ops = { - .get_rate = ast2600_clk_get_rate, - .set_rate = ast2600_clk_set_rate, - .enable = ast2600_clk_enable, -}; - -static int ast2600_clk_probe(struct udevice *dev) -{ - struct ast2600_clk_priv *priv = dev_get_priv(dev); - - priv->scu = devfdt_get_addr_ptr(dev); - if (IS_ERR(priv->scu)) - return PTR_ERR(priv->scu); - - ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig); - ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig); - ast2600_configure_mac12_clk(priv->scu); - ast2600_configure_mac34_clk(priv->scu); - ast2600_configure_rsa_ecc_clk(priv->scu); - - return 0; -} - -static int ast2600_clk_bind(struct udevice *dev) -{ - int ret; - - /* The reset driver does not have a device node, so bind it here */ - ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); - if (ret) - debug("Warning: No reset driver: ret=%d\n", ret); - - return 0; -} - struct aspeed_clks { ulong id; const char *name; }; +#if IS_ENABLED(CONFIG_CMD_CLK) static struct aspeed_clks aspeed_clk_names[] = { { ASPEED_CLK_HPLL, "hpll" }, { ASPEED_CLK_MPLL, "mpll" }, @@ -1158,18 +1124,12 @@ static struct aspeed_clks aspeed_clk_names[] = { { ASPEED_CLK_HUARTX, "huxclk" }, }; -int soc_clk_dump(void) +static void ast2600_clk_dump(struct udevice *dev) { - struct udevice *dev; struct clk clk; unsigned long rate; int i, ret; - ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(aspeed_scu), - &dev); - if (ret) - return ret; - printf("Clk\t\tHz\n"); for (i = 0; i < ARRAY_SIZE(aspeed_clk_names); i++) { @@ -1202,6 +1162,45 @@ int soc_clk_dump(void) return 0; } +#endif + +struct clk_ops ast2600_clk_ops = { + .get_rate = ast2600_clk_get_rate, + .set_rate = ast2600_clk_set_rate, + .enable = ast2600_clk_enable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = ast2600_clk_dump, +#endif +}; + +static int ast2600_clk_probe(struct udevice *dev) +{ + struct ast2600_clk_priv *priv = dev_get_priv(dev); + + priv->scu = devfdt_get_addr_ptr(dev); + if (IS_ERR(priv->scu)) + return PTR_ERR(priv->scu); + + ast2600_init_rgmii_clk(priv->scu, &rgmii_clk_defconfig); + ast2600_init_rmii_clk(priv->scu, &rmii_clk_defconfig); + ast2600_configure_mac12_clk(priv->scu); + ast2600_configure_mac34_clk(priv->scu); + ast2600_configure_rsa_ecc_clk(priv->scu); + + return 0; +} + +static int ast2600_clk_bind(struct udevice *dev) +{ + int ret; + + /* The reset driver does not have a device node, so bind it here */ + ret = device_bind_driver(gd->dm_root, "ast_sysreset", "reset", &dev); + if (ret) + debug("Warning: No reset driver: ret=%d\n", ret); + + return 0; +} static const struct udevice_id ast2600_clk_ids[] = { { .compatible = "aspeed,ast2600-scu", }, diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index b52d926..025c7a7 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -17,6 +17,7 @@ #include <linux/clk/at91_pmc.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/time.h> #include "pmc.h" #define UBOOT_DM_CLK_AT91_MAIN_RC "at91-main-rc-clk" @@ -25,7 +26,6 @@ #define UBOOT_DM_CLK_AT91_SAM9X5_MAIN "at91-sam9x5-main-clk" #define MOR_KEY_MASK GENMASK(23, 16) -#define USEC_PER_SEC 1000000UL #define SLOW_CLOCK_FREQ 32768 #define clk_main_parent_select(s) (((s) & \ diff --git a/drivers/clk/clk_k210.c b/drivers/clk/clk_k210.c index c534cc0..7432ae8 100644 --- a/drivers/clk/clk_k210.c +++ b/drivers/clk/clk_k210.c @@ -16,6 +16,7 @@ #include <dt-bindings/mfd/k210-sysctl.h> #include <k210/pll.h> #include <linux/bitfield.h> +#include <asm/barrier.h> DECLARE_GLOBAL_DATA_PTR; @@ -1238,52 +1239,6 @@ static int k210_clk_request(struct clk *clk) return 0; } -static const struct clk_ops k210_clk_ops = { - .request = k210_clk_request, - .set_rate = k210_clk_set_rate, - .get_rate = k210_clk_get_rate, - .set_parent = k210_clk_set_parent, - .enable = k210_clk_enable, - .disable = k210_clk_disable, -}; - -static int k210_clk_probe(struct udevice *dev) -{ - int ret; - struct k210_clk_priv *priv = dev_get_priv(dev); - - priv->base = dev_read_addr_ptr(dev_get_parent(dev)); - if (!priv->base) - return -EINVAL; - - ret = clk_get_by_index(dev, 0, &priv->in0); - if (ret) - return ret; - - /* - * Force setting defaults, even before relocation. This is so we can - * set the clock rate for PLL1 before we relocate into aisram. - */ - if (!(gd->flags & GD_FLG_RELOC)) - clk_set_defaults(dev, CLK_DEFAULTS_POST_FORCE); - - return 0; -} - -static const struct udevice_id k210_clk_ids[] = { - { .compatible = "canaan,k210-clk" }, - { }, -}; - -U_BOOT_DRIVER(k210_clk) = { - .name = "k210_clk", - .id = UCLASS_CLK, - .of_match = k210_clk_ids, - .ops = &k210_clk_ops, - .probe = k210_clk_probe, - .priv_auto = sizeof(struct k210_clk_priv), -}; - #if IS_ENABLED(CONFIG_CMD_CLK) static char show_enabled(struct k210_clk_priv *priv, int id) { @@ -1322,16 +1277,10 @@ static void show_clks(struct k210_clk_priv *priv, int id, int depth) } } -int soc_clk_dump(void) +static void k210_clk_dump(struct udevice *dev) { - int ret; - struct udevice *dev; struct k210_clk_priv *priv; - ret = uclass_get_device_by_driver(UCLASS_CLK, DM_DRIVER_GET(k210_clk), - &dev); - if (ret) - return ret; priv = dev_get_priv(dev); puts(" Rate Enabled Name\n"); @@ -1339,6 +1288,54 @@ int soc_clk_dump(void) printf(" %-9lu %-7c %*s%s\n", clk_get_rate(&priv->in0), 'y', 0, "", priv->in0.dev->name); show_clks(priv, K210_CLK_IN0, 1); - return 0; } #endif + +static const struct clk_ops k210_clk_ops = { + .request = k210_clk_request, + .set_rate = k210_clk_set_rate, + .get_rate = k210_clk_get_rate, + .set_parent = k210_clk_set_parent, + .enable = k210_clk_enable, + .disable = k210_clk_disable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = k210_clk_dump, +#endif +}; + +static int k210_clk_probe(struct udevice *dev) +{ + int ret; + struct k210_clk_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr_ptr(dev_get_parent(dev)); + if (!priv->base) + return -EINVAL; + + ret = clk_get_by_index(dev, 0, &priv->in0); + if (ret) + return ret; + + /* + * Force setting defaults, even before relocation. This is so we can + * set the clock rate for PLL1 before we relocate into aisram. + */ + if (!(gd->flags & GD_FLG_RELOC)) + clk_set_defaults(dev, CLK_DEFAULTS_POST_FORCE); + + return 0; +} + +static const struct udevice_id k210_clk_ids[] = { + { .compatible = "canaan,k210-clk" }, + { }, +}; + +U_BOOT_DRIVER(k210_clk) = { + .name = "k210_clk", + .id = UCLASS_CLK, + .of_match = k210_clk_ids, + .ops = &k210_clk_ops, + .probe = k210_clk_probe, + .priv_auto = sizeof(struct k210_clk_priv), +}; diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c index ef06a7f..a77d0e7 100644 --- a/drivers/clk/clk_pic32.c +++ b/drivers/clk/clk_pic32.c @@ -20,6 +20,8 @@ DECLARE_GLOBAL_DATA_PTR; +#define CLK_MHZ(x) ((x) / 1000000) + /* Primary oscillator */ #define SYS_POSC_CLK_HZ 24000000 @@ -385,9 +387,44 @@ static ulong pic32_set_rate(struct clk *clk, ulong rate) return rate; } +#if IS_ENABLED(CONFIG_CMD_CLK) +static void pic32_dump(struct udevice *dev) +{ + int i; + struct clk clk; + + clk.dev = dev; + + clk.id = PLLCLK; + printf("PLL Speed: %lu MHz\n", + CLK_MHZ(pic32_get_rate(&clk))); + + clk.id = PB7CLK; + printf("CPU Speed: %lu MHz\n", CLK_MHZ(pic32_get_rate(&clk))); + + clk.id = MPLL; + printf("MPLL Speed: %lu MHz\n", CLK_MHZ(pic32_get_rate(&clk))); + + for (i = PB1CLK; i <= PB7CLK; i++) { + clk.id = i; + printf("PB%d Clock Speed: %lu MHz\n", i - PB1CLK + 1, + CLK_MHZ(pic32_get_rate(&clk))); + } + + for (i = REF1CLK; i <= REF5CLK; i++) { + clk.id = i; + printf("REFO%d Clock Speed: %lu MHz\n", i - REF1CLK + 1, + CLK_MHZ(pic32_get_rate(&clk))); + } +} +#endif + static struct clk_ops pic32_pic32_clk_ops = { .set_rate = pic32_set_rate, .get_rate = pic32_get_rate, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = pic32_dump, +#endif }; static int pic32_clk_probe(struct udevice *dev) diff --git a/drivers/clk/clk_versal.c b/drivers/clk/clk_versal.c index c473643..42ab032 100644 --- a/drivers/clk/clk_versal.c +++ b/drivers/clk/clk_versal.c @@ -555,7 +555,8 @@ static int versal_clock_get_rate(u32 clk_id, u64 *clk_rate) return 0; } -int soc_clk_dump(void) +#if IS_ENABLED(CONFIG_CMD_CLK) +static void versal_clk_dump(struct udevice __always_unused *dev) { u64 clk_rate = 0; u32 type, ret, i = 0; @@ -575,9 +576,8 @@ int soc_clk_dump(void) printf("clk: %s freq:%lld\n", clock[i].clk_name, clk_rate); } - - return 0; } +#endif static void versal_get_clock_info(void) { @@ -769,6 +769,9 @@ static struct clk_ops versal_clk_ops = { .set_rate = versal_clk_set_rate, .get_rate = versal_clk_get_rate, .enable = versal_clk_enable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = versal_clk_dump, +#endif }; static const struct udevice_id versal_clk_ids[] = { diff --git a/drivers/clk/clk_zynq.c b/drivers/clk/clk_zynq.c index e80500e..34f964d 100644 --- a/drivers/clk/clk_zynq.c +++ b/drivers/clk/clk_zynq.c @@ -454,12 +454,64 @@ static int dummy_enable(struct clk *clk) return 0; } +#if IS_ENABLED(CONFIG_CMD_CLK) +static const char * const clk_names[clk_max] = { + "armpll", "ddrpll", "iopll", + "cpu_6or4x", "cpu_3or2x", "cpu_2x", "cpu_1x", + "ddr2x", "ddr3x", "dci", + "lqspi", "smc", "pcap", "gem0", "gem1", + "fclk0", "fclk1", "fclk2", "fclk3", "can0", "can1", + "sdio0", "sdio1", "uart0", "uart1", "spi0", "spi1", "dma", + "usb0_aper", "usb1_aper", "gem0_aper", "gem1_aper", + "sdio0_aper", "sdio1_aper", "spi0_aper", "spi1_aper", + "can0_aper", "can1_aper", "i2c0_aper", "i2c1_aper", + "uart0_aper", "uart1_aper", "gpio_aper", "lqspi_aper", + "smc_aper", "swdt", "dbg_trc", "dbg_apb" +}; + +static void zynq_clk_dump(struct udevice *dev) +{ + int i, ret; + + printf("clk\t\tfrequency\n"); + for (i = 0; i < clk_max; i++) { + const char *name = clk_names[i]; + + if (name) { + struct clk clk; + unsigned long rate; + + clk.id = i; + ret = clk_request(dev, &clk); + if (ret < 0) { + printf("%s clk_request() failed: %d\n", + __func__, ret); + break; + } + + rate = clk_get_rate(&clk); + + clk_free(&clk); + + if ((rate == (unsigned long)-ENOSYS) || + (rate == (unsigned long)-ENXIO)) + printf("%10s%20s\n", name, "unknown"); + else + printf("%10s%20lu\n", name, rate); + } + } +} +#endif + static struct clk_ops zynq_clk_ops = { .get_rate = zynq_clk_get_rate, #ifndef CONFIG_SPL_BUILD .set_rate = zynq_clk_set_rate, #endif .enable = dummy_enable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = zynq_clk_dump, +#endif }; static int zynq_clk_probe(struct udevice *dev) diff --git a/drivers/clk/clk_zynqmp.c b/drivers/clk/clk_zynqmp.c index 1cfe0e2..0ffac19 100644 --- a/drivers/clk/clk_zynqmp.c +++ b/drivers/clk/clk_zynqmp.c @@ -735,16 +735,11 @@ static ulong zynqmp_clk_set_rate(struct clk *clk, ulong rate) } } -int soc_clk_dump(void) +#if IS_ENABLED(CONFIG_CMD_CLK) +static void zynqmp_clk_dump(struct udevice *dev) { - struct udevice *dev; int i, ret; - ret = uclass_get_device_by_driver(UCLASS_CLK, - DM_DRIVER_GET(zynqmp_clk), &dev); - if (ret) - return ret; - printf("clk\t\tfrequency\n"); for (i = 0; i < clk_max; i++) { const char *name = clk_names[i]; @@ -754,8 +749,11 @@ int soc_clk_dump(void) clk.id = i; ret = clk_request(dev, &clk); - if (ret < 0) - return ret; + if (ret < 0) { + printf("%s clk_request() failed: %d\n", + __func__, ret); + break; + } rate = clk_get_rate(&clk); @@ -769,9 +767,8 @@ int soc_clk_dump(void) printf("%10s%20lu\n", name, rate); } } - - return 0; } +#endif static int zynqmp_get_freq_by_name(char *name, struct udevice *dev, ulong *freq) { @@ -844,6 +841,7 @@ static int zynqmp_clk_enable(struct clk *clk) break; case qspi_ref ... can1_ref: case lpd_lsbus: + case topsw_lsbus: clkact_shift = 24; mask = 0x1; break; @@ -871,6 +869,9 @@ static struct clk_ops zynqmp_clk_ops = { .set_rate = zynqmp_clk_set_rate, .get_rate = zynqmp_clk_get_rate, .enable = zynqmp_clk_enable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = zynqmp_clk_dump, +#endif }; static const struct udevice_id zynqmp_clk_ids[] = { diff --git a/drivers/clk/imx/clk-imx8.c b/drivers/clk/imx/clk-imx8.c index ceeead3..9600672 100644 --- a/drivers/clk/imx/clk-imx8.c +++ b/drivers/clk/imx/clk-imx8.c @@ -43,18 +43,12 @@ static int imx8_clk_enable(struct clk *clk) } #if IS_ENABLED(CONFIG_CMD_CLK) -int soc_clk_dump(void) +static void imx8_clk_dump(struct udevice *dev) { - struct udevice *dev; struct clk clk; unsigned long rate; int i, ret; - ret = uclass_get_device_by_driver(UCLASS_CLK, - DM_DRIVER_GET(imx8_clk), &dev); - if (ret) - return ret; - printf("Clk\t\tHz\n"); for (i = 0; i < num_clks; i++) { @@ -84,8 +78,6 @@ int soc_clk_dump(void) printf("%s(%3lu):\t%lu\n", imx8_clk_names[i].name, imx8_clk_names[i].id, rate); } - - return 0; } #endif @@ -94,6 +86,9 @@ static struct clk_ops imx8_clk_ops = { .get_rate = imx8_clk_get_rate, .enable = imx8_clk_enable, .disable = imx8_clk_disable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = imx8_clk_dump, +#endif }; static int imx8_clk_probe(struct udevice *dev) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 692823e..457acb8 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -83,6 +83,20 @@ static const char *imx8mn_i2c3_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_ static const char *imx8mn_i2c4_sels[] = {"clock-osc-24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out", "video_pll_out", "audio_pll2_out", "sys_pll1_133m", }; +#ifndef CONFIG_SPL_BUILD +static const char *imx8mn_pwm1_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m", + "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll_out", }; + +static const char *imx8mn_pwm2_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m", + "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll_out", }; + +static const char *imx8mn_pwm3_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m", + "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll_out", }; + +static const char *imx8mn_pwm4_sels[] = {"clock-osc-24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m", + "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll_out", }; +#endif + static const char *imx8mn_wdog_sels[] = {"clock-osc-24m", "sys_pll1_133m", "sys_pll1_160m", "m7_alt_pll", "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", }; @@ -330,6 +344,22 @@ static int imx8mn_clk_probe(struct udevice *dev) clk_dm(IMX8MN_CLK_ENET1_ROOT, imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0)); + clk_dm(IMX8MN_CLK_PWM1, + imx8m_clk_composite("pwm1", imx8mn_pwm1_sels, base + 0xb380)); + clk_dm(IMX8MN_CLK_PWM2, + imx8m_clk_composite("pwm2", imx8mn_pwm2_sels, base + 0xb400)); + clk_dm(IMX8MN_CLK_PWM3, + imx8m_clk_composite("pwm3", imx8mn_pwm3_sels, base + 0xb480)); + clk_dm(IMX8MN_CLK_PWM4, + imx8m_clk_composite("pwm4", imx8mn_pwm4_sels, base + 0xb500)); + clk_dm(IMX8MN_CLK_PWM1_ROOT, + imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0)); + clk_dm(IMX8MN_CLK_PWM2_ROOT, + imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0)); + clk_dm(IMX8MN_CLK_PWM3_ROOT, + imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0)); + clk_dm(IMX8MN_CLK_PWM4_ROOT, + imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0)); #endif #if CONFIG_IS_ENABLED(DM_SPI) diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index e74c6f9..e631f79 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -11,5 +11,6 @@ obj-$(CONFIG_TARGET_MT7986) += clk-mt7986.o obj-$(CONFIG_TARGET_MT7981) += clk-mt7981.o obj-$(CONFIG_TARGET_MT7988) += clk-mt7988.o obj-$(CONFIG_TARGET_MT8183) += clk-mt8183.o +obj-$(CONFIG_TARGET_MT8365) += clk-mt8365.o obj-$(CONFIG_TARGET_MT8516) += clk-mt8516.o obj-$(CONFIG_TARGET_MT8518) += clk-mt8518.o diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c new file mode 100644 index 0000000..61ccd4a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365.c @@ -0,0 +1,766 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * MediaTek clock driver for MT8365 SoC + * + * Copyright (C) 2023 BayLibre, SAS + * Copyright (c) 2023 MediaTek Inc. + * Author: Julien Masson <jmasson@baylibre.com> + * Author: Fabien Parent <fparent@baylibre.com> + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <dm.h> +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include "clk-mtk.h" + +/* apmixedsys */ +#define MT8365_PLL_FMAX (3800UL * MHZ) +#define MT8365_PLL_FMIN (1500UL * MHZ) +#define CON0_MT8365_RST_BAR BIT(23) +#define PLL_AO BIT(1) + +#define PLL(_id, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ + _pd_shift, _pcw_reg, _pcw_shift, _rst_bar_mask, _pcw_chg_reg) { \ + .id = _id, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8365_PLL_FMAX, \ + .fmin = MT8365_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = 8, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + } + +static const struct mtk_pll_data apmixed_plls[] = { + PLL(CLK_APMIXED_ARMPLL, 0x030C, 0x0318, 0x00000001, PLL_AO, 22, 0x0310, + 24, 0x0310, 0, 0, 0), + PLL(CLK_APMIXED_MAINPLL, 0x0228, 0x0234, 0xFF000001, HAVE_RST_BAR, 22, + 0x022C, 24, 0x022C, 0, CON0_MT8365_RST_BAR, 0), + PLL(CLK_APMIXED_UNIVPLL, 0x0208, 0x0214, 0xFF000001, HAVE_RST_BAR, 22, + 0x020C, 24, 0x020C, 0, CON0_MT8365_RST_BAR, 0), + PLL(CLK_APMIXED_MFGPLL, 0x0218, 0x0224, 0x00000001, 0, 22, 0x021C, 24, + 0x021C, 0, 0, 0), + PLL(CLK_APMIXED_MSDCPLL, 0x0350, 0x035C, 0x00000001, 0, 22, 0x0354, 24, + 0x0354, 0, 0, 0), + PLL(CLK_APMIXED_MMPLL, 0x0330, 0x033C, 0x00000001, 0, 22, 0x0334, 24, + 0x0334, 0, 0, 0), + PLL(CLK_APMIXED_APLL1, 0x031C, 0x032C, 0x00000001, 0, 32, 0x0320, 24, + 0x0324, 0, 0, 0x0320), + PLL(CLK_APMIXED_APLL2, 0x0360, 0x0370, 0x00000001, 0, 32, 0x0364, 24, + 0x0368, 0, 0, 0x0364), + PLL(CLK_APMIXED_LVDSPLL, 0x0374, 0x0380, 0x00000001, 0, 22, 0x0378, 24, + 0x0378, 0, 0, 0), + PLL(CLK_APMIXED_DSPPLL, 0x0390, 0x039C, 0x00000001, 0, 22, 0x0394, 24, + 0x0394, 0, 0, 0), + PLL(CLK_APMIXED_APUPLL, 0x03A0, 0x03AC, 0x00000001, 0, 22, 0x03A4, 24, + 0x03A4, 0, 0, 0), +}; + +/* topckgen */ +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_CLK_NULL, CLK_XTAL, 0), + FIXED_CLK(CLK_TOP_I2S0_BCK, CLK_XTAL, 26000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC_DSICK, CLK_TOP_CLK26M, 75000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, CLK_TOP_CLK26M, 75000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, CLK_TOP_CLK26M, 52500000), +}; + +#define PLL_FACTOR(_id, _name, _parent, _mult, _div) \ + FACTOR(_id, _parent, _mult, _div, CLK_PARENT_APMIXED) + +static const struct mtk_fixed_factor top_divs[] = { + PLL_FACTOR(CLK_TOP_SYS_26M_D2, "sys_26m_d2", CLK_XTAL, 1, 2), + PLL_FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", CLK_APMIXED_MAINPLL, 1, 2), + PLL_FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", CLK_APMIXED_MAINPLL, 1, 4), + PLL_FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", CLK_APMIXED_MAINPLL, 1, 8), + PLL_FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", CLK_APMIXED_MAINPLL, 1, 16), + PLL_FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", CLK_APMIXED_MAINPLL, 1, 32), + PLL_FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", CLK_APMIXED_MAINPLL, 1, 3), + PLL_FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", CLK_APMIXED_MAINPLL, 1, 6), + PLL_FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", CLK_APMIXED_MAINPLL, 1, 12), + PLL_FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", CLK_APMIXED_MAINPLL, 1, 24), + PLL_FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", CLK_APMIXED_MAINPLL, 1, 5), + PLL_FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", CLK_APMIXED_MAINPLL, 1, 10), + PLL_FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", CLK_APMIXED_MAINPLL, 1, 20), + PLL_FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", CLK_APMIXED_MAINPLL, 1, 7), + PLL_FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", CLK_APMIXED_MAINPLL, 1, 14), + PLL_FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", CLK_APMIXED_MAINPLL, 1, 28), + PLL_FACTOR(CLK_TOP_UNIVPLL, "univpll", CLK_APMIXED_UNIV_EN, 1, 2), + PLL_FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", CLK_APMIXED_UNIVPLL, 1, 2), + PLL_FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", CLK_APMIXED_UNIVPLL, 1, 4), + PLL_FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", CLK_APMIXED_UNIVPLL, 1, 8), + PLL_FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", CLK_APMIXED_UNIVPLL, 1, 3), + PLL_FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", CLK_APMIXED_UNIVPLL, 1, 6), + PLL_FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", CLK_APMIXED_UNIVPLL, 1, 12), + PLL_FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", CLK_APMIXED_UNIVPLL, 1, 24), + PLL_FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", CLK_APMIXED_UNIVPLL, 1, 96), + PLL_FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", CLK_APMIXED_UNIVPLL, 1, 5), + PLL_FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", CLK_APMIXED_UNIVPLL, 1, 10), + PLL_FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", CLK_APMIXED_UNIVPLL, 1, 20), + PLL_FACTOR(CLK_TOP_MMPLL, "mmpll_ck", CLK_APMIXED_MMPLL, 1, 1), + PLL_FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", CLK_APMIXED_MMPLL, 1, 2), + PLL_FACTOR(CLK_TOP_MFGPLL, "mfgpll_ck", CLK_APMIXED_MFGPLL, 1, 1), + PLL_FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", CLK_APMIXED_LVDSPLL, 1, 2), + PLL_FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", CLK_APMIXED_LVDSPLL, 1, 4), + PLL_FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", CLK_APMIXED_LVDSPLL, 1, 8), + PLL_FACTOR(CLK_TOP_LVDSPLL_D16, "lvdspll_d16", CLK_APMIXED_LVDSPLL, 1, 16), + PLL_FACTOR(CLK_TOP_USB20_192M, "usb20_192m_ck", CLK_APMIXED_USB20_EN, 1, 13), + PLL_FACTOR(CLK_TOP_USB20_192M_D4, "usb20_192m_d4", CLK_TOP_USB20_192M, 1, 4), + PLL_FACTOR(CLK_TOP_USB20_192M_D8, "usb20_192m_d8", CLK_TOP_USB20_192M, 1, 8), + PLL_FACTOR(CLK_TOP_USB20_192M_D16, "usb20_192m_d16", CLK_TOP_USB20_192M, 1, 16), + PLL_FACTOR(CLK_TOP_USB20_192M_D32, "usb20_192m_d32", CLK_TOP_USB20_192M, 1, 32), + PLL_FACTOR(CLK_TOP_APLL1, "apll1_ck", CLK_APMIXED_APLL1, 1, 1), + PLL_FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", CLK_APMIXED_APLL1, 1, 2), + PLL_FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", CLK_APMIXED_APLL1, 1, 4), + PLL_FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", CLK_APMIXED_APLL1, 1, 8), + PLL_FACTOR(CLK_TOP_APLL2, "apll2_ck", CLK_APMIXED_APLL2, 1, 1), + PLL_FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", CLK_APMIXED_APLL2, 1, 2), + PLL_FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", CLK_APMIXED_APLL2, 1, 4), + PLL_FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", CLK_APMIXED_APLL2, 1, 8), + PLL_FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", CLK_APMIXED_MSDCPLL, 1, 1), + PLL_FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", CLK_APMIXED_MSDCPLL, 1, 2), + PLL_FACTOR(CLK_TOP_DSPPLL, "dsppll_ck", CLK_APMIXED_DSPPLL, 1, 1), + PLL_FACTOR(CLK_TOP_DSPPLL_D2, "dsppll_d2", CLK_APMIXED_DSPPLL, 1, 2), + PLL_FACTOR(CLK_TOP_DSPPLL_D4, "dsppll_d4", CLK_APMIXED_DSPPLL, 1, 4), + PLL_FACTOR(CLK_TOP_DSPPLL_D8, "dsppll_d8", CLK_APMIXED_DSPPLL, 1, 8), + PLL_FACTOR(CLK_TOP_APUPLL, "apupll_ck", CLK_APMIXED_APUPLL, 1, 1), + PLL_FACTOR(CLK_TOP_CLK26M_D52, "clk26m_d52", CLK_XTAL, 1, 52), +}; + +static const int axi_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL_D7, + CLK_TOP_SYSPLL1_D4, + CLK_TOP_SYSPLL3_D2 +}; + +static const int mem_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MMPLL, + CLK_TOP_SYSPLL_D3, + CLK_TOP_SYSPLL1_D2 +}; + +static const int mm_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MMPLL, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_SYSPLL_D5, + CLK_TOP_SYSPLL1_D4, + CLK_TOP_UNIVPLL_D5, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_MMPLL_D2, +}; + +static const int scp_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL4_D2, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_SYSPLL_D3, + CLK_TOP_UNIVPLL_D3 +}; + +static const int mfg_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MFGPLL, + CLK_TOP_SYSPLL_D3, + CLK_TOP_UNIVPLL_D3 +}; + +static const int atb_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL1_D4, + CLK_TOP_SYSPLL1_D2 +}; + +static const int camtg_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_USB20_192M_D8, + CLK_TOP_UNIVPLL2_D8, + CLK_TOP_USB20_192M_D4, + CLK_TOP_UNIVPLL2_D32, + CLK_TOP_USB20_192M_D16, + CLK_TOP_USB20_192M_D32, +}; + +static const int uart_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL2_D8 +}; + +static const int spi_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_UNIVPLL2_D4, + CLK_TOP_UNIVPLL2_D8 +}; + +static const int msdc50_0_hc_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_UNIVPLL1_D4, + CLK_TOP_SYSPLL2_D2 +}; + +static const int msdc50_0_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MSDCPLL, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_UNIVPLL_D5, + CLK_TOP_SYSPLL2_D2, + CLK_TOP_UNIVPLL1_D4, + CLK_TOP_SYSPLL4_D2 +}; + +static const int msdc50_2_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MSDCPLL, + CLK_TOP_UNIVPLL_D3, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_SYSPLL2_D2, + CLK_TOP_UNIVPLL1_D4 +}; + +static const int msdc30_1_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MSDCPLL_D2, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_SYSPLL2_D2, + CLK_TOP_UNIVPLL1_D4, + CLK_TOP_SYSPLL1_D4, + CLK_TOP_SYSPLL2_D4, + CLK_TOP_UNIVPLL2_D8 +}; + +static const int audio_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL3_D4, + CLK_TOP_SYSPLL4_D4, + CLK_TOP_SYSPLL1_D16 +}; + +static const int aud_intbus_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL1_D4, + CLK_TOP_SYSPLL4_D2 +}; + +static const int aud_1_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_APLL1 +}; + +static const int aud_2_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_APLL2 +}; + +static const int aud_engen1_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_APLL1_D2, + CLK_TOP_APLL1_D4, + CLK_TOP_APLL1_D8 +}; + +static const int aud_engen2_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_APLL2_D2, + CLK_TOP_APLL2_D4, + CLK_TOP_APLL2_D8, +}; + +static const int aud_spdif_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL_D2 +}; + +static const int disp_pwm_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL2_D4 +}; + +static const int dxcc_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_SYSPLL1_D4, + CLK_TOP_SYSPLL1_D8 +}; + +static const int ssusb_sys_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL3_D4, + CLK_TOP_UNIVPLL2_D4, + CLK_TOP_UNIVPLL3_D2 +}; + +static const int spm_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL1_D8 +}; + +static const int i2c_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL3_D4, + CLK_TOP_UNIVPLL3_D2, + CLK_TOP_SYSPLL1_D8, + CLK_TOP_SYSPLL2_D8 +}; + +static const int pwm_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL3_D4, + CLK_TOP_SYSPLL1_D8 +}; + +static const int senif_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL1_D4, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_UNIVPLL2_D2 +}; + +static const int aes_fde_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_MSDCPLL, + CLK_TOP_UNIVPLL_D3, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_SYSPLL1_D2 +}; + +static const int dpi0_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_LVDSPLL_D2, + CLK_TOP_LVDSPLL_D4, + CLK_TOP_LVDSPLL_D8, + CLK_TOP_LVDSPLL_D16 +}; + +static const int dsp_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYS_26M_D2, + CLK_TOP_DSPPLL, + CLK_TOP_DSPPLL_D2, + CLK_TOP_DSPPLL_D4, + CLK_TOP_DSPPLL_D8 +}; + +static const int nfi2x_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL2_D2, + CLK_TOP_SYSPLL_D7, + CLK_TOP_SYSPLL_D3, + CLK_TOP_SYSPLL2_D4, + CLK_TOP_MSDCPLL_D2, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_UNIVPLL_D5 +}; + +static const int nfiecc_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_SYSPLL4_D2, + CLK_TOP_UNIVPLL2_D4, + CLK_TOP_SYSPLL_D7, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_SYSPLL_D5 +}; + +static const int ecc_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_UNIVPLL_D3, + CLK_TOP_SYSPLL_D2 +}; + +static const int eth_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL2_D8, + CLK_TOP_SYSPLL4_D4, + CLK_TOP_SYSPLL1_D8, + CLK_TOP_SYSPLL4_D2 +}; + +static const int gcpu_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL_D3, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_SYSPLL_D3, + CLK_TOP_SYSPLL2_D2 +}; + +static const int gcpu_cpm_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL2_D2, + CLK_TOP_SYSPLL2_D2 +}; + +static const int apu_parents[] = { + CLK_TOP_CLK26M, + CLK_TOP_UNIVPLL_D2, + CLK_APMIXED_APUPLL, + CLK_TOP_MMPLL, + CLK_TOP_SYSPLL_D3, + CLK_TOP_UNIVPLL1_D2, + CLK_TOP_SYSPLL1_D2, + CLK_TOP_SYSPLL1_D4 +}; + +static const struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE(CLK_TOP_AXI_SEL, axi_parents, 0x040, 0, 2, 7), + MUX_GATE(CLK_TOP_MEM_SEL, mem_parents, 0x040, 8, 2, 15), + MUX_GATE(CLK_TOP_MM_SEL, mm_parents, 0x040, 16, 3, 23), + MUX_GATE(CLK_TOP_SCP_SEL, scp_parents, 0x040, 24, 3, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_MFG_SEL, mfg_parents, 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_ATB_SEL, atb_parents, 0x050, 8, 2, 15), + MUX_GATE(CLK_TOP_CAMTG_SEL, camtg_parents, 0x050, 16, 3, 23), + MUX_GATE(CLK_TOP_CAMTG1_SEL, camtg_parents, 0x050, 24, 3, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_UART_SEL, uart_parents, 0x060, 0, 1, 7), + MUX_GATE(CLK_TOP_SPI_SEL, spi_parents, 0x060, 8, 2, 15), + MUX_GATE(CLK_TOP_MSDC50_0_HC_SEL, msdc50_0_hc_parents, 0x060, 16, 2, 23), + MUX_GATE(CLK_TOP_MSDC2_2_HC_SEL, msdc50_0_hc_parents, 0x060, 24, 2, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_MSDC50_0_SEL, msdc50_0_parents, 0x070, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC50_2_SEL, msdc50_2_parents, 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, msdc30_1_parents, 0x070, 16, 3, 23), + MUX_GATE(CLK_TOP_AUDIO_SEL, audio_parents, 0x070, 24, 2, 31), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, aud_intbus_parents, 0x080, 0, 2, 7), + MUX_GATE(CLK_TOP_AUD_1_SEL, aud_1_parents, 0x080, 8, 1, 15), + MUX_GATE(CLK_TOP_AUD_2_SEL, aud_2_parents, 0x080, 16, 1, 23), + MUX_GATE(CLK_TOP_AUD_ENGEN1_SEL, aud_engen1_parents, 0x080, 24, 2, 31), + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_AUD_ENGEN2_SEL, aud_engen2_parents, 0x090, 0, 2, 7), + MUX_GATE(CLK_TOP_AUD_SPDIF_SEL, aud_spdif_parents, 0x090, 8, 1, 15), + MUX_GATE(CLK_TOP_DISP_PWM_SEL, disp_pwm_parents, 0x090, 16, 2, 23), + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_DXCC_SEL, dxcc_parents, 0x0a0, 0, 2, 7), + MUX_GATE(CLK_TOP_SSUSB_SYS_SEL, ssusb_sys_parents, 0x0a0, 8, 2, 15), + MUX_GATE(CLK_TOP_SSUSB_XHCI_SEL, ssusb_sys_parents, 0x0a0, 16, 2, 23), + MUX_GATE(CLK_TOP_SPM_SEL, spm_parents, 0x0a0, 24, 1, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_I2C_SEL, i2c_parents, 0x0b0, 0, 3, 7), + MUX_GATE(CLK_TOP_PWM_SEL, pwm_parents, 0x0b0, 8, 2, 15), + MUX_GATE(CLK_TOP_SENIF_SEL, senif_parents, 0x0b0, 16, 2, 23), + MUX_GATE(CLK_TOP_AES_FDE_SEL, aes_fde_parents, 0x0b0, 24, 3, 31), + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_CAMTM_SEL, senif_parents, 0x0c0, 0, 2, 7), + MUX_GATE(CLK_TOP_DPI0_SEL, dpi0_parents, 0x0c0, 8, 3, 15), + MUX_GATE(CLK_TOP_DPI1_SEL, dpi0_parents, 0x0c0, 16, 3, 23), + MUX_GATE(CLK_TOP_DSP_SEL, dsp_parents, 0x0c0, 24, 3, 31), + /* CLK_CFG_9 */ + MUX_GATE(CLK_TOP_NFI2X_SEL, nfi2x_parents, 0x0d0, 0, 3, 7), + MUX_GATE(CLK_TOP_NFIECC_SEL, nfiecc_parents, 0x0d0, 8, 3, 15), + MUX_GATE(CLK_TOP_ECC_SEL, ecc_parents, 0x0d0, 16, 3, 23), + MUX_GATE(CLK_TOP_ETH_SEL, eth_parents, 0x0d0, 24, 3, 31), + /* CLK_CFG_10 */ + MUX_GATE(CLK_TOP_GCPU_SEL, gcpu_parents, 0x0e0, 0, 3, 7), + MUX_GATE(CLK_TOP_GCPU_CPM_SEL, gcpu_cpm_parents, 0x0e0, 8, 2, 15), + MUX_GATE(CLK_TOP_APU_SEL, apu_parents, 0x0e0, 16, 3, 23), + MUX_GATE(CLK_TOP_APU_IF_SEL, apu_parents, 0x0e0, 24, 3, 31), +}; + +static const struct mtk_clk_tree mt8365_clk_tree = { + .xtal_rate = 26 * MHZ, + .xtal2_rate = 26 * MHZ, + .fdivs_offs = CLK_TOP_SYSPLL_D2, + .muxes_offs = CLK_TOP_AXI_SEL, + .plls = apmixed_plls, + .fclks = top_fixed_clks, + .fdivs = top_divs, + .muxes = top_muxes, +}; + +/* topckgen cg */ +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0, + .clr_ofs = 0, + .sta_ofs = 0, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x104, + .sta_ofs = 0x104, +}; + +static const struct mtk_gate_regs top2_cg_regs = { + .set_ofs = 0x320, + .clr_ofs = 0x320, + .sta_ofs = 0x320, +}; + +#define GATE_TOP0(_id, _parent, _shift) { \ + .id = _id, \ + .parent = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .flags = CLK_GATE_NO_SETCLR | CLK_PARENT_TOPCKGEN, \ + } + +#define GATE_TOP1(_id, _parent, _shift) { \ + .id = _id, \ + .parent = _parent, \ + .regs = &top1_cg_regs, \ + .shift = _shift, \ + .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN, \ + } + +#define GATE_TOP2(_id, _parent, _shift) { \ + .id = _id, \ + .parent = _parent, \ + .regs = &top2_cg_regs, \ + .shift = _shift, \ + .flags = CLK_GATE_NO_SETCLR_INV | CLK_PARENT_TOPCKGEN, \ + } + +static const struct mtk_gate top_clk_gates[] = { + GATE_TOP0(CLK_TOP_CONN_32K, CLK_TOP_CLK32K, 10), + GATE_TOP0(CLK_TOP_CONN_26M, CLK_TOP_CLK26M, 11), + GATE_TOP0(CLK_TOP_DSP_32K, CLK_TOP_CLK32K, 16), + GATE_TOP0(CLK_TOP_DSP_26M, CLK_TOP_CLK26M, 17), + GATE_TOP1(CLK_TOP_USB20_48M_EN, CLK_TOP_USB20_192M_D4, 8), + GATE_TOP1(CLK_TOP_UNIVPLL_48M_EN, CLK_TOP_USB20_192M_D4, 9), + GATE_TOP1(CLK_TOP_LVDSTX_CLKDIG_EN, CLK_TOP_LVDSTX_CLKDIG_CTS, 20), + GATE_TOP1(CLK_TOP_VPLL_DPIX_EN, CLK_TOP_VPLL_DPIX, 21), + GATE_TOP1(CLK_TOP_SSUSB_TOP_CK_EN, CLK_TOP_CLK_NULL, 22), + GATE_TOP1(CLK_TOP_SSUSB_PHY_CK_EN, CLK_TOP_CLK_NULL, 23), + GATE_TOP2(CLK_TOP_AUD_I2S0_M, CLK_TOP_APLL12_CK_DIV0, 0), + GATE_TOP2(CLK_TOP_AUD_I2S1_M, CLK_TOP_APLL12_CK_DIV1, 1), + GATE_TOP2(CLK_TOP_AUD_I2S2_M, CLK_TOP_APLL12_CK_DIV2, 2), + GATE_TOP2(CLK_TOP_AUD_I2S3_M, CLK_TOP_APLL12_CK_DIV3, 3), + GATE_TOP2(CLK_TOP_AUD_TDMOUT_M, CLK_TOP_APLL12_CK_DIV4, 4), + GATE_TOP2(CLK_TOP_AUD_TDMOUT_B, CLK_TOP_APLL12_CK_DIV4B, 5), + GATE_TOP2(CLK_TOP_AUD_TDMIN_M, CLK_TOP_APLL12_CK_DIV5, 6), + GATE_TOP2(CLK_TOP_AUD_TDMIN_B, CLK_TOP_APLL12_CK_DIV5B, 7), + GATE_TOP2(CLK_TOP_AUD_SPDIF_M, CLK_TOP_APLL12_CK_DIV6, 8), +}; + +/* infracfg */ +static const struct mtk_gate_regs ifr2_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs ifr3_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs ifr4_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs ifr5_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +static const struct mtk_gate_regs ifr6_cg_regs = { + .set_ofs = 0xd0, + .clr_ofs = 0xd4, + .sta_ofs = 0xd8, +}; + +#define GATE_IFRX(_id, _parent, _shift, _regs) \ + { \ + .id = _id, \ + .parent = _parent, \ + .regs = _regs, \ + .shift = _shift, \ + .flags = CLK_GATE_SETCLR | CLK_PARENT_TOPCKGEN, \ + } + +#define GATE_IFR2(_id, _parent, _shift) \ + GATE_IFRX(_id, _parent, _shift, &ifr2_cg_regs) + +#define GATE_IFR3(_id, _parent, _shift) \ + GATE_IFRX(_id, _parent, _shift, &ifr3_cg_regs) + +#define GATE_IFR4(_id, _parent, _shift) \ + GATE_IFRX(_id, _parent, _shift, &ifr4_cg_regs) + +#define GATE_IFR5(_id, _parent, _shift) \ + GATE_IFRX(_id, _parent, _shift, &ifr5_cg_regs) + +#define GATE_IFR6(_id, _parent, _shift) \ + GATE_IFRX(_id, _parent, _shift, &ifr6_cg_regs) + +static const struct mtk_gate ifr_clks[] = { + /* IFR2 */ + GATE_IFR2(CLK_IFR_PMIC_TMR, CLK_TOP_CLK26M, 0), + GATE_IFR2(CLK_IFR_PMIC_AP, CLK_TOP_CLK26M, 1), + GATE_IFR2(CLK_IFR_PMIC_MD, CLK_TOP_CLK26M, 2), + GATE_IFR2(CLK_IFR_PMIC_CONN, CLK_TOP_CLK26M, 3), + GATE_IFR2(CLK_IFR_ICUSB, CLK_TOP_AXI_SEL, 8), + GATE_IFR2(CLK_IFR_GCE, CLK_TOP_AXI_SEL, 9), + GATE_IFR2(CLK_IFR_THERM, CLK_TOP_AXI_SEL, 10), + GATE_IFR2(CLK_IFR_PWM_HCLK, CLK_TOP_AXI_SEL, 15), + GATE_IFR2(CLK_IFR_PWM1, CLK_TOP_PWM_SEL, 16), + GATE_IFR2(CLK_IFR_PWM2, CLK_TOP_PWM_SEL, 17), + GATE_IFR2(CLK_IFR_PWM3, CLK_TOP_PWM_SEL, 18), + GATE_IFR2(CLK_IFR_PWM4, CLK_TOP_PWM_SEL, 19), + GATE_IFR2(CLK_IFR_PWM5, CLK_TOP_PWM_SEL, 20), + GATE_IFR2(CLK_IFR_PWM, CLK_TOP_PWM_SEL, 21), + GATE_IFR2(CLK_IFR_UART0, CLK_TOP_UART_SEL, 22), + GATE_IFR2(CLK_IFR_UART1, CLK_TOP_UART_SEL, 23), + GATE_IFR2(CLK_IFR_UART2, CLK_TOP_UART_SEL, 24), + GATE_IFR2(CLK_IFR_DSP_UART, CLK_TOP_UART_SEL, 26), + GATE_IFR2(CLK_IFR_GCE_26M, CLK_TOP_CLK26M, 27), + GATE_IFR2(CLK_IFR_CQ_DMA_FPC, CLK_TOP_AXI_SEL, 28), + GATE_IFR2(CLK_IFR_BTIF, CLK_TOP_AXI_SEL, 31), + /* IFR3 */ + GATE_IFR3(CLK_IFR_SPI0, CLK_TOP_SPI_SEL, 1), + GATE_IFR3(CLK_IFR_MSDC0_HCLK, CLK_TOP_MSDC50_0_HC_SEL, 2), + GATE_IFR3(CLK_IFR_MSDC2_HCLK, CLK_TOP_MSDC2_2_HC_SEL, 3), + GATE_IFR3(CLK_IFR_MSDC1_HCLK, CLK_TOP_AXI_SEL, 4), + GATE_IFR3(CLK_IFR_DVFSRC, CLK_TOP_CLK26M, 7), + GATE_IFR3(CLK_IFR_GCPU, CLK_TOP_AXI_SEL, 8), + GATE_IFR3(CLK_IFR_TRNG, CLK_TOP_AXI_SEL, 9), + GATE_IFR3(CLK_IFR_AUXADC, CLK_TOP_CLK26M, 10), + GATE_IFR3(CLK_IFR_AUXADC_MD, CLK_TOP_CLK26M, 14), + GATE_IFR3(CLK_IFR_AP_DMA, CLK_TOP_AXI_SEL, 18), + GATE_IFR3(CLK_IFR_DEBUGSYS, CLK_TOP_AXI_SEL, 24), + GATE_IFR3(CLK_IFR_AUDIO, CLK_TOP_AXI_SEL, 25), + /* IFR4 */ + GATE_IFR4(CLK_IFR_PWM_FBCLK6, CLK_TOP_PWM_SEL, 0), + GATE_IFR4(CLK_IFR_DISP_PWM, CLK_TOP_DISP_PWM_SEL, 2), + GATE_IFR4(CLK_IFR_AUD_26M_BK, CLK_TOP_CLK26M, 4), + GATE_IFR4(CLK_IFR_CQ_DMA, CLK_TOP_AXI_SEL, 27), + /* IFR5 */ + GATE_IFR5(CLK_IFR_MSDC0_SF, CLK_TOP_MSDC50_0_SEL, 0), + GATE_IFR5(CLK_IFR_MSDC1_SF, CLK_TOP_MSDC50_0_SEL, 1), + GATE_IFR5(CLK_IFR_MSDC2_SF, CLK_TOP_MSDC50_0_SEL, 2), + GATE_IFR5(CLK_IFR_AP_MSDC0, CLK_TOP_MSDC50_0_SEL, 7), + GATE_IFR5(CLK_IFR_MD_MSDC0, CLK_TOP_MSDC50_0_SEL, 8), + GATE_IFR5(CLK_IFR_MSDC0_SRC, CLK_TOP_MSDC50_0_SEL, 9), + GATE_IFR5(CLK_IFR_MSDC1_SRC, CLK_TOP_MSDC30_1_SEL, 10), + GATE_IFR5(CLK_IFR_MSDC2_SRC, CLK_TOP_MSDC50_2_SEL, 11), + GATE_IFR5(CLK_IFR_PWRAP_TMR, CLK_TOP_CLK26M, 12), + GATE_IFR5(CLK_IFR_PWRAP_SPI, CLK_TOP_CLK26M, 13), + GATE_IFR5(CLK_IFR_PWRAP_SYS, CLK_TOP_CLK26M, 14), + GATE_IFR5(CLK_IFR_IRRX_26M, CLK_TOP_CLK26M, 22), + GATE_IFR5(CLK_IFR_IRRX_32K, CLK_TOP_CLK32K, 23), + GATE_IFR5(CLK_IFR_I2C0_AXI, CLK_TOP_I2C_SEL, 24), + GATE_IFR5(CLK_IFR_I2C1_AXI, CLK_TOP_I2C_SEL, 25), + GATE_IFR5(CLK_IFR_I2C2_AXI, CLK_TOP_I2C_SEL, 26), + GATE_IFR5(CLK_IFR_I2C3_AXI, CLK_TOP_I2C_SEL, 27), + GATE_IFR5(CLK_IFR_NIC_AXI, CLK_TOP_AXI_SEL, 28), + GATE_IFR5(CLK_IFR_NIC_SLV_AXI, CLK_TOP_AXI_SEL, 29), + GATE_IFR5(CLK_IFR_APU_AXI, CLK_TOP_AXI_SEL, 30), + /* IFR6 */ + GATE_IFR6(CLK_IFR_NFIECC, CLK_TOP_NFIECC_SEL, 0), + GATE_IFR6(CLK_IFR_NFI1X_BK, CLK_TOP_NFI2X_SEL, 1), + GATE_IFR6(CLK_IFR_NFIECC_BK, CLK_TOP_NFI2X_SEL, 2), + GATE_IFR6(CLK_IFR_NFI_BK, CLK_TOP_AXI_SEL, 3), + GATE_IFR6(CLK_IFR_MSDC2_AP_BK, CLK_TOP_AXI_SEL, 4), + GATE_IFR6(CLK_IFR_MSDC2_MD_BK, CLK_TOP_AXI_SEL, 5), + GATE_IFR6(CLK_IFR_MSDC2_BK, CLK_TOP_AXI_SEL, 6), + GATE_IFR6(CLK_IFR_SUSB_133_BK, CLK_TOP_AXI_SEL, 7), + GATE_IFR6(CLK_IFR_SUSB_66_BK, CLK_TOP_AXI_SEL, 8), + GATE_IFR6(CLK_IFR_SSUSB_SYS, CLK_TOP_SSUSB_SYS_SEL, 9), + GATE_IFR6(CLK_IFR_SSUSB_REF, CLK_TOP_SSUSB_SYS_SEL, 10), + GATE_IFR6(CLK_IFR_SSUSB_XHCI, CLK_TOP_SSUSB_XHCI_SEL, 11), +}; + +static int mt8365_apmixedsys_probe(struct udevice *dev) +{ + return mtk_common_clk_init(dev, &mt8365_clk_tree); +} + +static int mt8365_topckgen_probe(struct udevice *dev) +{ + return mtk_common_clk_init(dev, &mt8365_clk_tree); +} + +static int mt8365_topckgen_cg_probe(struct udevice *dev) +{ + return mtk_common_clk_gate_init(dev, &mt8365_clk_tree, top_clk_gates); +} + +static int mt8365_infracfg_probe(struct udevice *dev) +{ + return mtk_common_clk_gate_init(dev, &mt8365_clk_tree, ifr_clks); +} + +static const struct udevice_id mt8365_apmixed_compat[] = { + { .compatible = "mediatek,mt8365-apmixedsys", }, + { } +}; + +static const struct udevice_id mt8365_topckgen_compat[] = { + { .compatible = "mediatek,mt8365-topckgen", }, + { } +}; + +static const struct udevice_id mt8365_topckgen_cg_compat[] = { + { .compatible = "mediatek,mt8365-topckgen-cg", }, + { } +}; + +static const struct udevice_id mt8365_infracfg_compat[] = { + { .compatible = "mediatek,mt8365-infracfg", }, + { } +}; + +U_BOOT_DRIVER(mtk_clk_apmixedsys) = { + .name = "mt8365-apmixedsys", + .id = UCLASS_CLK, + .of_match = mt8365_apmixed_compat, + .probe = mt8365_apmixedsys_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_apmixedsys_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRIVER(mtk_clk_topckgen) = { + .name = "mt8365-topckgen", + .id = UCLASS_CLK, + .of_match = mt8365_topckgen_compat, + .probe = mt8365_topckgen_probe, + .priv_auto = sizeof(struct mtk_clk_priv), + .ops = &mtk_clk_topckgen_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRIVER(mtk_clk_topckgen_cg) = { + .name = "mt8365-topckgen-cg", + .id = UCLASS_CLK, + .of_match = mt8365_topckgen_cg_compat, + .probe = mt8365_topckgen_cg_probe, + .priv_auto = sizeof(struct mtk_cg_priv), + .ops = &mtk_clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; + +U_BOOT_DRIVER(mtk_clk_infracfg) = { + .name = "mt8365-infracfg", + .id = UCLASS_CLK, + .of_match = mt8365_infracfg_compat, + .probe = mt8365_infracfg_probe, + .priv_auto = sizeof(struct mtk_cg_priv), + .ops = &mtk_clk_gate_ops, + .flags = DM_FLAG_PRE_RELOC, +}; diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c index d0f5bb3..5220a33 100644 --- a/drivers/clk/meson/a1.c +++ b/drivers/clk/meson/a1.c @@ -607,14 +607,6 @@ static int meson_clk_set_parent(struct clk *clk, struct clk *parent_clk) return meson_mux_set_parent_by_id(clk, parent_clk->id); } -static struct clk_ops meson_clk_ops = { - .disable = meson_clk_disable, - .enable = meson_clk_enable, - .get_rate = meson_clk_get_rate, - .set_rate = meson_clk_set_rate, - .set_parent = meson_clk_set_parent, -}; - static int meson_clk_probe(struct udevice *dev) { struct meson_clk *priv = dev_get_priv(dev); @@ -644,15 +636,7 @@ static const struct udevice_id meson_clk_ids[] = { { } }; -U_BOOT_DRIVER(meson_clk) = { - .name = "meson-clk-a1", - .id = UCLASS_CLK, - .of_match = meson_clk_ids, - .priv_auto = sizeof(struct meson_clk), - .ops = &meson_clk_ops, - .probe = meson_clk_probe, -}; - +#if IS_ENABLED(CONFIG_CMD_CLK) static const char *meson_clk_get_name(struct clk *clk, int id) { const struct meson_clk_info *info; @@ -662,7 +646,7 @@ static const char *meson_clk_get_name(struct clk *clk, int id) return IS_ERR(info) ? "unknown" : info->name; } -static int meson_clk_dump(struct clk *clk) +static int meson_clk_dump_single(struct clk *clk) { const struct meson_clk_info *info; struct meson_clk *priv; @@ -697,7 +681,7 @@ static int meson_clk_dump(struct clk *clk) return 0; } -static int meson_clk_dump_dev(struct udevice *dev) +static void meson_clk_dump(struct udevice *dev) { int i; struct meson_clk_data *data; @@ -710,26 +694,30 @@ static int meson_clk_dump_dev(struct udevice *dev) data = (struct meson_clk_data *)dev_get_driver_data(dev); for (i = 0; i < data->num_clocks; i++) { - meson_clk_dump(&(struct clk){ + meson_clk_dump_single(&(struct clk){ .dev = dev, .id = i }); } - - return 0; } +#endif -int soc_clk_dump(void) -{ - struct udevice *dev; - int i = 0; - - while (!uclass_get_device(UCLASS_CLK, i++, &dev)) { - if (dev->driver == DM_DRIVER_GET(meson_clk)) { - meson_clk_dump_dev(dev); - printf("\n"); - } - } +static struct clk_ops meson_clk_ops = { + .disable = meson_clk_disable, + .enable = meson_clk_enable, + .get_rate = meson_clk_get_rate, + .set_rate = meson_clk_set_rate, + .set_parent = meson_clk_set_parent, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = meson_clk_dump, +#endif +}; - return 0; -} +U_BOOT_DRIVER(meson_clk) = { + .name = "meson-clk-a1", + .id = UCLASS_CLK, + .of_match = meson_clk_ids, + .priv_auto = sizeof(struct meson_clk), + .ops = &meson_clk_ops, + .probe = meson_clk_probe, +}; diff --git a/drivers/clk/mvebu/armada-37xx-periph.c b/drivers/clk/mvebu/armada-37xx-periph.c index e75052f..1a70970 100644 --- a/drivers/clk/mvebu/armada-37xx-periph.c +++ b/drivers/clk/mvebu/armada-37xx-periph.c @@ -488,33 +488,36 @@ static int armada_37xx_periph_clk_dump(struct udevice *dev) static int clk_dump(const char *name, int (*func)(struct udevice *)) { struct udevice *dev; + int ret; if (uclass_get_device_by_name(UCLASS_CLK, name, &dev)) { printf("Cannot find device %s\n", name); return -ENODEV; } - return func(dev); + ret = func(dev); + if (ret) + printf("Dump failed for %s: %d\n", name, ret); + + return ret; } int armada_37xx_tbg_clk_dump(struct udevice *); -int soc_clk_dump(void) +static void armada37xx_clk_dump(struct udevice __always_unused *dev) { printf(" xtal at %u000000 Hz\n\n", get_ref_clk()); if (clk_dump("tbg@13200", armada_37xx_tbg_clk_dump)) - return 1; + return; if (clk_dump("nb-periph-clk@13000", armada_37xx_periph_clk_dump)) - return 1; + return; if (clk_dump("sb-periph-clk@18000", armada_37xx_periph_clk_dump)) - return 1; - - return 0; + return; } #endif @@ -605,6 +608,9 @@ static const struct clk_ops armada_37xx_periph_clk_ops = { .set_parent = armada_37xx_periph_clk_set_parent, .enable = armada_37xx_periph_clk_enable, .disable = armada_37xx_periph_clk_disable, +#if IS_ENABLED(CONFIG_CMD_CLK) + .dump = armada37xx_clk_dump, +#endif }; static const struct udevice_id armada_37xx_periph_clk_ids[] = { diff --git a/drivers/clk/nuvoton/clk_npcm.c b/drivers/clk/nuvoton/clk_npcm.c index 8d71f2a..18cb9cd 100644 --- a/drivers/clk/nuvoton/clk_npcm.c +++ b/drivers/clk/nuvoton/clk_npcm.c @@ -135,7 +135,7 @@ static u32 npcm_clk_get_div(struct clk *clk) return div; } -static u32 npcm_clk_set_div(struct clk *clk, u32 div) +static int npcm_clk_set_div(struct clk *clk, u32 div) { struct npcm_clk_priv *priv = dev_get_priv(clk->dev); struct npcm_clk_div *divider; @@ -145,6 +145,9 @@ static u32 npcm_clk_set_div(struct clk *clk, u32 div) if (!divider) return -EINVAL; + if (divider->flags & DIV_RO) + return 0; + if (divider->flags & PRE_DIV2) div = div >> 1; @@ -153,6 +156,12 @@ static u32 npcm_clk_set_div(struct clk *clk, u32 div) else clkdiv = ilog2(div); + if (clkdiv > (divider->mask >> (ffs(divider->mask) - 1))) { + printf("clkdiv(%d) for clk(%ld) is over limit\n", + clkdiv, clk->id); + return -EINVAL; + } + val = readl(priv->base + divider->reg); val &= ~divider->mask; val |= (clkdiv << (ffs(divider->mask) - 1)) & divider->mask; @@ -253,8 +262,8 @@ static ulong npcm_clk_set_rate(struct clk *clk, ulong rate) if (ret) return ret; - debug("%s: rate %lu, new rate (%lu / %u)\n", __func__, rate, parent_rate, div); - return (parent_rate / div); + debug("%s: rate %lu, new rate %lu\n", __func__, rate, npcm_clk_get_rate(clk)); + return npcm_clk_get_rate(clk); } static int npcm_clk_set_parent(struct clk *clk, struct clk *parent) diff --git a/drivers/clk/nuvoton/clk_npcm.h b/drivers/clk/nuvoton/clk_npcm.h index 06b60dc..b4726d8 100644 --- a/drivers/clk/nuvoton/clk_npcm.h +++ b/drivers/clk/nuvoton/clk_npcm.h @@ -50,6 +50,7 @@ #define PRE_DIV2 BIT(2) /* Pre divisor = 2 */ #define POST_DIV2 BIT(3) /* Post divisor = 2 */ #define FIXED_PARENT BIT(4) /* clock source is fixed */ +#define DIV_RO BIT(5) /* divider is read-only */ /* Parameters of PLL configuration */ struct npcm_clk_pll { diff --git a/drivers/clk/nuvoton/clk_npcm8xx.c b/drivers/clk/nuvoton/clk_npcm8xx.c index 27e3cfc..d1b32e3 100644 --- a/drivers/clk/nuvoton/clk_npcm8xx.c +++ b/drivers/clk/nuvoton/clk_npcm8xx.c @@ -45,12 +45,12 @@ static struct npcm_clk_select npcm8xx_clk_selectors[] = { }; static struct npcm_clk_div npcm8xx_clk_dividers[] = { - {NPCM8XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2}, - {NPCM8XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2}, - {NPCM8XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2}, - {NPCM8XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1}, - {NPCM8XX_CLK_SPI1, CLKDIV3, SPI1CKDIV, DIV_TYPE1}, - {NPCM8XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1}, + {NPCM8XX_CLK_AHB, CLKDIV1, CLK4DIV, DIV_TYPE1 | PRE_DIV2 | DIV_RO}, + {NPCM8XX_CLK_APB2, CLKDIV2, APB2CKDIV, DIV_TYPE2 | DIV_RO}, + {NPCM8XX_CLK_APB5, CLKDIV2, APB5CKDIV, DIV_TYPE2 | DIV_RO}, + {NPCM8XX_CLK_SPI0, CLKDIV3, SPI0CKDIV, DIV_TYPE1 | DIV_RO}, + {NPCM8XX_CLK_SPI1, CLKDIV3, SPI1CKDIV, DIV_TYPE1 | DIV_RO}, + {NPCM8XX_CLK_SPI3, CLKDIV1, SPI3CKDIV, DIV_TYPE1 | DIV_RO}, {NPCM8XX_CLK_SPIX, CLKDIV3, SPIXCKDIV, DIV_TYPE1}, {NPCM8XX_CLK_UART, CLKDIV1, UARTDIV1, DIV_TYPE1}, {NPCM8XX_CLK_UART2, CLKDIV3, UARTDIV2, DIV_TYPE1}, diff --git a/drivers/clk/stm32/clk-stm32f.c b/drivers/clk/stm32/clk-stm32f.c index ed76601..d68c75e 100644 --- a/drivers/clk/stm32/clk-stm32f.c +++ b/drivers/clk/stm32/clk-stm32f.c @@ -522,17 +522,20 @@ static ulong stm32_set_rate(struct clk *clk, ulong rate) /* get the current PLLSAIR output freq */ pllsair_rate = stm32_clk_get_pllsai_rate(priv, PLLSAIR); - best_div = pllsair_rate / rate; - - /* look into pllsaidivr_table if this divider is available*/ - for (i = 0 ; i < sizeof(pllsaidivr_table); i++) - if (best_div == pllsaidivr_table[i]) { - /* set pll_saidivr with found value */ - clrsetbits_le32(®s->dckcfgr, - RCC_DCKCFGR_PLLSAIDIVR_MASK, - pllsaidivr_table[i]); - return rate; - } + if ((pllsair_rate % rate) == 0) { + best_div = pllsair_rate / rate; + + /* look into pllsaidivr_table if this divider is available */ + for (i = 0 ; i < sizeof(pllsaidivr_table); i++) + if (best_div == pllsaidivr_table[i]) { + /* set pll_saidivr with found value */ + clrsetbits_le32(®s->dckcfgr, + RCC_DCKCFGR_PLLSAIDIVR_MASK, + pllsaidivr_table[i] << + RCC_DCKCFGR_PLLSAIDIVR_SHIFT); + return rate; + } + } /* * As no pllsaidivr value is suitable to obtain requested freq, diff --git a/drivers/clk/stm32/clk-stm32mp1.c b/drivers/clk/stm32/clk-stm32mp1.c index f3ac8c7..6f000c8 100644 --- a/drivers/clk/stm32/clk-stm32mp1.c +++ b/drivers/clk/stm32/clk-stm32mp1.c @@ -2225,10 +2225,13 @@ static void stm32mp1_osc_init(struct udevice *dev) } } -static void __maybe_unused stm32mp1_clk_dump(struct stm32mp1_clk_priv *priv) +static void __maybe_unused stm32mp1_clk_dump(struct udevice *dev) { char buf[32]; int i, s, p; + struct stm32mp1_clk_priv *priv; + + priv = dev_get_priv(dev); printf("Clocks:\n"); for (i = 0; i < _PARENT_NB; i++) { @@ -2252,27 +2255,6 @@ static void __maybe_unused stm32mp1_clk_dump(struct stm32mp1_clk_priv *priv) } } -#ifdef CONFIG_CMD_CLK -int soc_clk_dump(void) -{ - struct udevice *dev; - struct stm32mp1_clk_priv *priv; - int ret; - - ret = uclass_get_device_by_driver(UCLASS_CLK, - DM_DRIVER_GET(stm32mp1_clock), - &dev); - if (ret) - return ret; - - priv = dev_get_priv(dev); - - stm32mp1_clk_dump(priv); - - return 0; -} -#endif - static int stm32mp1_clk_probe(struct udevice *dev) { int result = 0; @@ -2302,7 +2284,7 @@ static int stm32mp1_clk_probe(struct udevice *dev) #if defined(VERBOSE_DEBUG) /* display debug information for probe after relocation */ if (gd->flags & GD_FLG_RELOC) - stm32mp1_clk_dump(priv); + stm32mp1_clk_dump(dev); #endif gd->cpu_clk = stm32mp1_clk_get(priv, _CK_MPU); @@ -2333,6 +2315,9 @@ static const struct clk_ops stm32mp1_clk_ops = { .disable = stm32mp1_clk_disable, .get_rate = stm32mp1_clk_get_rate, .set_rate = stm32mp1_clk_set_rate, +#if IS_ENABLED(CONFIG_CMD_CLK) && !IS_ENABLED(CONFIG_SPL_BUILD) + .dump = stm32mp1_clk_dump, +#endif }; U_BOOT_DRIVER(stm32mp1_clock) = { diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig index 737d459..1081d61 100644 --- a/drivers/core/Kconfig +++ b/drivers/core/Kconfig @@ -87,7 +87,7 @@ config DM_STATS config SPL_DM_STATS bool "Collect and show driver model stats in SPL" - depends on DM_SPL + depends on SPL_DM help Enable this to collect and display memory statistics about driver model. This can help to figure out where all the memory is going and diff --git a/drivers/core/ofnode.c b/drivers/core/ofnode.c index f72ea41..21a233f 100644 --- a/drivers/core/ofnode.c +++ b/drivers/core/ofnode.c @@ -83,6 +83,11 @@ static oftree oftree_ensure(void *fdt) if (check_tree_count()) return oftree_null(); + if (fdt_check_header(fdt)) { + log_err("Invalid device tree blob header\n"); + return oftree_null(); + } + /* register the new tree */ i = oftree_count++; oftree_list[i] = fdt; diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h index c4501ab..69adfdc 100644 --- a/drivers/crypto/fsl/jobdesc.h +++ b/drivers/crypto/fsl/jobdesc.h @@ -7,7 +7,6 @@ #ifndef __JOBDESC_H #define __JOBDESC_H -#include <common.h> #include <asm/io.h> #include "rsa_caam.h" diff --git a/drivers/crypto/fsl/rsa_caam.h b/drivers/crypto/fsl/rsa_caam.h index 9a6a8af..fb132a3 100644 --- a/drivers/crypto/fsl/rsa_caam.h +++ b/drivers/crypto/fsl/rsa_caam.h @@ -6,8 +6,6 @@ #ifndef __RSA_CAAM_H #define __RSA_CAAM_H -#include <common.h> - /** * struct pk_in_params - holder for input to PKHA block in CAAM * These parameters are required to perform Modular Exponentiation diff --git a/drivers/ddr/altera/sdram_soc64.h b/drivers/ddr/altera/sdram_soc64.h index 07a0f9f..87a70a8 100644 --- a/drivers/ddr/altera/sdram_soc64.h +++ b/drivers/ddr/altera/sdram_soc64.h @@ -6,7 +6,6 @@ #ifndef _SDRAM_SOC64_H_ #define _SDRAM_SOC64_H_ -#include <common.h> #include <linux/sizes.h> struct altera_sdram_priv { diff --git a/drivers/ddr/imx/phy/helper.c b/drivers/ddr/imx/phy/helper.c index 855a874..b9b2403 100644 --- a/drivers/ddr/imx/phy/helper.c +++ b/drivers/ddr/imx/phy/helper.c @@ -49,6 +49,13 @@ void ddr_load_train_firmware(enum fw_type type) unsigned long imem_start = (unsigned long)_end + fw_offset; unsigned long dmem_start; unsigned long imem_len = IMEM_LEN, dmem_len = DMEM_LEN; + static enum fw_type last_type = -1; + + /* If FW doesn't change, we can save the loading. */ + if (last_type == type) + return; + + last_type = type; #ifdef CONFIG_SPL_OF_CONTROL if (gd->fdt_blob && !fdt_check_header(gd->fdt_blob)) { diff --git a/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h b/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h index 7357311..dff5633 100644 --- a/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h +++ b/drivers/ddr/marvell/a38x/ddr_ml_wrapper.h @@ -6,7 +6,6 @@ #ifndef _DDR_ML_WRAPPER_H #define _DDR_ML_WRAPPER_H -#include <common.h> #include <i2c.h> #include <spl.h> #include <asm/io.h> diff --git a/drivers/ddr/marvell/axp/ddr3_axp.h b/drivers/ddr/marvell/axp/ddr3_axp.h index c40cd76..c3d2824 100644 --- a/drivers/ddr/marvell/axp/ddr3_axp.h +++ b/drivers/ddr/marvell/axp/ddr3_axp.h @@ -6,6 +6,8 @@ #ifndef __DDR3_AXP_H #define __DDR3_AXP_H +#include <config.h> + #define MV_78XX0_Z1_REV 0x0 #define MV_78XX0_A0_REV 0x1 #define MV_78XX0_B0_REV 0x2 diff --git a/drivers/dfu/Kconfig b/drivers/dfu/Kconfig index 4e80e85..0360d9d 100644 --- a/drivers/dfu/Kconfig +++ b/drivers/dfu/Kconfig @@ -19,6 +19,7 @@ config DFU_WRITE_ALT config DFU_TFTP bool "DFU via TFTP" + depends on NETDEVICES select UPDATE_COMMON select DFU_OVER_TFTP help @@ -111,5 +112,14 @@ config SYS_DFU_MAX_FILE_SIZE the buffer once we've been given the whole file. Define this to the maximum filesize (in bytes) for the buffer. If undefined it defaults to the CONFIG_SYS_DFU_DATA_BUF_SIZE. + +config DFU_NAME_MAX_SIZE + int "Size of the name to be added in dfu entity" + default 32 + depends on DFU + help + This value is used to maximum size. If name is longer than default size, + we need to change the proper maximum size. + endif endmenu diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 0af5460..3c64e89 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -87,7 +87,6 @@ endif config DMA_LEGACY bool "Legacy DMA support" - default y if FSLDMAFEC help Enable legacy DMA support. This does not use driver model and should be migrated to the new API. diff --git a/drivers/dma/MCD_dmaApi.c b/drivers/dma/MCD_dmaApi.c deleted file mode 100644 index af0e134..0000000 --- a/drivers/dma/MCD_dmaApi.c +++ /dev/null @@ -1,1010 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. - */ - -/*Main C file for multi-channel DMA API. */ - -#include <common.h> - -#include <MCD_dma.h> -#include <MCD_tasksInit.h> -#include <MCD_progCheck.h> - -/********************************************************************/ -/* This is an API-internal pointer to the DMA's registers */ -dmaRegs *MCD_dmaBar; - -/* - * These are the real and model task tables as generated by the - * build process - */ -extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS]; -extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS]; - -/* - * However, this (usually) gets relocated to on-chip SRAM, at which - * point we access them as these tables - */ -volatile TaskTableEntry *MCD_taskTable; -TaskTableEntry *MCD_modelTaskTable; - -/* - * MCD_chStatus[] is an array of status indicators for remembering - * whether a DMA has ever been attempted on each channel, pausing - * status, etc. - */ -static int MCD_chStatus[NCHANNELS] = { - MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, - MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, - MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, - MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA -}; - -/* Prototypes for local functions */ -static void MCD_memcpy(int *dest, int *src, u32 size); -static void MCD_resmActions(int channel); - -/* - * Buffer descriptors used for storage of progress info for single Dmas - * Also used as storage for the DMA for CRCs for single DMAs - * Otherwise, the DMA does not parse these buffer descriptors - */ -#ifdef MCD_INCLUDE_EU -extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; -#else -MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; -#endif -MCD_bufDesc *MCD_relocBuffDesc; - -/* Defines for the debug control register's functions */ -#define DBG_CTL_COMP1_TASK (0x00002000) -#define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \ - DBG_CTL_BREAK | \ - DBG_CTL_INT_BREAK | \ - DBG_CTL_COMP1_TASK) -#define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \ - DBG_CTL_INT_BREAK | \ - DBG_CTL_COMP1_TASK) -#define DBG_KILL_ALL_STAT (0xFFFFFFFF) - -/* Offset to context save area where progress info is stored */ -#define CSAVE_OFFSET 10 - -/* Defines for Byte Swapping */ -#define MCD_BYTE_SWAP_KILLER 0xFFF8888F -#define MCD_NO_BYTE_SWAP_ATALL 0x00040000 - -/* Execution Unit Identifiers */ -#define MAC 0 /* legacy - not used */ -#define LUAC 1 /* legacy - not used */ -#define CRC 2 /* legacy - not used */ -#define LURC 3 /* Logic Unit with CRC */ - -/* Task Identifiers */ -#define TASK_CHAINNOEU 0 -#define TASK_SINGLENOEU 1 -#ifdef MCD_INCLUDE_EU -#define TASK_CHAINEU 2 -#define TASK_SINGLEEU 3 -#define TASK_FECRX 4 -#define TASK_FECTX 5 -#else -#define TASK_CHAINEU 0 -#define TASK_SINGLEEU 1 -#define TASK_FECRX 2 -#define TASK_FECTX 3 -#endif - -/* - * Structure to remember which variant is on which channel - * TBD- need this? - */ -typedef struct MCD_remVariants_struct MCD_remVariant; -struct MCD_remVariants_struct { - int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */ - int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */ - s16 remDestIncr[NCHANNELS]; /* DestIncr */ - s16 remSrcIncr[NCHANNELS]; /* srcIncr */ - u32 remXferSize[NCHANNELS]; /* xferSize */ -}; - -/* Structure to remember the startDma parameters for each channel */ -MCD_remVariant MCD_remVariants; -/********************************************************************/ -/* Function: MCD_initDma - * Purpose: Initializes the DMA API by setting up a pointer to the DMA - * registers, relocating and creating the appropriate task - * structures, and setting up some global settings - * Arguments: - * dmaBarAddr - pointer to the multichannel DMA registers - * taskTableDest - location to move DMA task code and structs to - * flags - operational parameters - * Return Value: - * MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned - * MCD_OK otherwise - */ -extern u32 MCD_funcDescTab0[]; - -int MCD_initDma(dmaRegs * dmaBarAddr, void *taskTableDest, u32 flags) -{ - int i; - TaskTableEntry *entryPtr; - - /* setup the local pointer to register set */ - MCD_dmaBar = dmaBarAddr; - - /* do we need to move/create a task table */ - if ((flags & MCD_RELOC_TASKS) != 0) { - int fixedSize; - u32 *fixedPtr; - /*int *tablePtr = taskTableDest;TBD */ - int varTabsOffset, funcDescTabsOffset, contextSavesOffset; - int taskDescTabsOffset; - int taskTableSize, varTabsSize, funcDescTabsSize, - contextSavesSize; - int taskDescTabSize; - - int i; - - /* check if physical address is aligned on 512 byte boundary */ - if (((u32) taskTableDest & 0x000001ff) != 0) - return (MCD_TABLE_UNALIGNED); - - /* set up local pointer to task Table */ - MCD_taskTable = taskTableDest; - - /* - * Create a task table: - * - compute aligned base offsets for variable tables and - * function descriptor tables, then - * - loop through the task table and setup the pointers - * - copy over model task table with the the actual task - * descriptor tables - */ - - taskTableSize = NCHANNELS * sizeof(TaskTableEntry); - /* align variable tables to size */ - varTabsOffset = taskTableSize + (u32) taskTableDest; - if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0) - varTabsOffset = - (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE); - /* align function descriptor tables */ - varTabsSize = NCHANNELS * VAR_TAB_SIZE; - funcDescTabsOffset = varTabsOffset + varTabsSize; - - if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0) - funcDescTabsOffset = - (funcDescTabsOffset + - FUNCDESC_TAB_SIZE) & (~FUNCDESC_TAB_SIZE); - - funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE; - contextSavesOffset = funcDescTabsOffset + funcDescTabsSize; - contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE); - fixedSize = - taskTableSize + varTabsSize + funcDescTabsSize + - contextSavesSize; - - /* zero the thing out */ - fixedPtr = (u32 *) taskTableDest; - for (i = 0; i < (fixedSize / 4); i++) - fixedPtr[i] = 0; - - entryPtr = (TaskTableEntry *) MCD_taskTable; - /* set up fixed pointers */ - for (i = 0; i < NCHANNELS; i++) { - /* update ptr to local value */ - entryPtr[i].varTab = (u32) varTabsOffset; - entryPtr[i].FDTandFlags = - (u32) funcDescTabsOffset | MCD_TT_FLAGS_DEF; - entryPtr[i].contextSaveSpace = (u32) contextSavesOffset; - varTabsOffset += VAR_TAB_SIZE; -#ifdef MCD_INCLUDE_EU - /* if not there is only one, just point to the - same one */ - funcDescTabsOffset += FUNCDESC_TAB_SIZE; -#endif - contextSavesOffset += CONTEXT_SAVE_SIZE; - } - /* copy over the function descriptor table */ - for (i = 0; i < FUNCDESC_TAB_NUM; i++) { - MCD_memcpy((void *)(entryPtr[i]. - FDTandFlags & ~MCD_TT_FLAGS_MASK), - (void *)MCD_funcDescTab0, FUNCDESC_TAB_SIZE); - } - - /* copy model task table to where the context saves stuff - leaves off */ - MCD_modelTaskTable = (TaskTableEntry *) contextSavesOffset; - - MCD_memcpy((void *)MCD_modelTaskTable, - (void *)MCD_modelTaskTableSrc, - NUMOFVARIANTS * sizeof(TaskTableEntry)); - - /* point to local version of model task table */ - entryPtr = MCD_modelTaskTable; - taskDescTabsOffset = (u32) MCD_modelTaskTable + - (NUMOFVARIANTS * sizeof(TaskTableEntry)); - - /* copy actual task code and update TDT ptrs in local - model task table */ - for (i = 0; i < NUMOFVARIANTS; i++) { - taskDescTabSize = - entryPtr[i].TDTend - entryPtr[i].TDTstart + 4; - MCD_memcpy((void *)taskDescTabsOffset, - (void *)entryPtr[i].TDTstart, - taskDescTabSize); - entryPtr[i].TDTstart = (u32) taskDescTabsOffset; - taskDescTabsOffset += taskDescTabSize; - entryPtr[i].TDTend = (u32) taskDescTabsOffset - 4; - } -#ifdef MCD_INCLUDE_EU - /* Tack single DMA BDs onto end of code so API controls - where they are since DMA might write to them */ - MCD_relocBuffDesc = - (MCD_bufDesc *) (entryPtr[NUMOFVARIANTS - 1].TDTend + 4); -#else - /* DMA does not touch them so they can be wherever and we - don't need to waste SRAM on them */ - MCD_relocBuffDesc = MCD_singleBufDescs; -#endif - } else { - /* point the would-be relocated task tables and the - buffer descriptors to the ones the linker generated */ - - if (((u32) MCD_realTaskTableSrc & 0x000001ff) != 0) - return (MCD_TABLE_UNALIGNED); - - /* need to add code to make sure that every thing else is - aligned properly TBD. this is problematic if we init - more than once or after running tasks, need to add - variable to see if we have aleady init'd */ - entryPtr = MCD_realTaskTableSrc; - for (i = 0; i < NCHANNELS; i++) { - if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) || - ((entryPtr[i]. - FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0)) - return (MCD_TABLE_UNALIGNED); - } - - MCD_taskTable = MCD_realTaskTableSrc; - MCD_modelTaskTable = MCD_modelTaskTableSrc; - MCD_relocBuffDesc = MCD_singleBufDescs; - } - - /* Make all channels as totally inactive, and remember them as such: */ - - MCD_dmaBar->taskbar = (u32) MCD_taskTable; - for (i = 0; i < NCHANNELS; i++) { - MCD_dmaBar->taskControl[i] = 0x0; - MCD_chStatus[i] = MCD_NO_DMA; - } - - /* Set up pausing mechanism to inactive state: */ - /* no particular values yet for either comparator registers */ - MCD_dmaBar->debugComp1 = 0; - MCD_dmaBar->debugComp2 = 0; - MCD_dmaBar->debugControl = DBG_CTL_DISABLE; - MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT; - - /* enable or disable commbus prefetch, really need an ifdef or - something to keep from trying to set this in the 8220 */ - if ((flags & MCD_COMM_PREFETCH_EN) != 0) - MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH; - else - MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH; - - return (MCD_OK); -} - -/*********************** End of MCD_initDma() ***********************/ - -/********************************************************************/ -/* Function: MCD_dmaStatus - * Purpose: Returns the status of the DMA on the requested channel - * Arguments: channel - channel number - * Returns: Predefined status indicators - */ -int MCD_dmaStatus(int channel) -{ - u16 tcrValue; - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - tcrValue = MCD_dmaBar->taskControl[channel]; - if ((tcrValue & TASK_CTL_EN) == 0) { /* nothing running */ - /* if last reported with task enabled */ - if (MCD_chStatus[channel] == MCD_RUNNING - || MCD_chStatus[channel] == MCD_IDLE) - MCD_chStatus[channel] = MCD_DONE; - } else { /* something is running */ - - /* There are three possibilities: paused, running or idle. */ - if (MCD_chStatus[channel] == MCD_RUNNING - || MCD_chStatus[channel] == MCD_IDLE) { - MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; - /* This register is selected to know which initiator is - actually asserted. */ - if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) - MCD_chStatus[channel] = MCD_RUNNING; - else - MCD_chStatus[channel] = MCD_IDLE; - /* do not change the status if it is already paused. */ - } - } - return MCD_chStatus[channel]; -} - -/******************** End of MCD_dmaStatus() ************************/ - -/********************************************************************/ -/* Function: MCD_startDma - * Ppurpose: Starts a particular kind of DMA - * Arguments: - * srcAddr - the channel on which to run the DMA - * srcIncr - the address to move data from, or buffer-descriptor address - * destAddr - the amount to increment the source address per transfer - * destIncr - the address to move data to - * dmaSize - the amount to increment the destination address per transfer - * xferSize - the number bytes in of each data movement (1, 2, or 4) - * initiator - what device initiates the DMA - * priority - priority of the DMA - * flags - flags describing the DMA - * funcDesc - description of byte swapping, bit swapping, and CRC actions - * srcAddrVirt - virtual buffer descriptor address TBD - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - */ - -int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr, - s16 destIncr, u32 dmaSize, u32 xferSize, u32 initiator, - int priority, u32 flags, u32 funcDesc -#ifdef MCD_NEED_ADDR_TRANS - s8 * srcAddrVirt -#endif - ) -{ - int srcRsdIncr, destRsdIncr; - int *cSave; - short xferSizeIncr; - int tcrCount = 0; -#ifdef MCD_INCLUDE_EU - u32 *realFuncArray; -#endif - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - /* tbd - need to determine the proper response to a bad funcDesc when - not including EU functions, for now, assign a benign funcDesc, but - maybe should return an error */ -#ifndef MCD_INCLUDE_EU - funcDesc = MCD_FUNC_NOEU1; -#endif - -#ifdef MCD_DEBUG - printf("startDma:Setting up params\n"); -#endif - /* Set us up for task-wise priority. We don't technically need to do - this on every start, but since the register involved is in the same - longword as other registers that users are in control of, setting - it more than once is probably preferable. That since the - documentation doesn't seem to be completely consistent about the - nature of the PTD control register. */ - MCD_dmaBar->ptdControl |= (u16) 0x8000; - - /* Not sure what we need to keep here rtm TBD */ -#if 1 - /* Calculate additional parameters to the regular DMA calls. */ - srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0); - destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0); - - xferSizeIncr = (xferSize & 0xffff) | 0x20000000; - - /* Remember for each channel which variant is running. */ - MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr; - MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr; - MCD_remVariants.remDestIncr[channel] = destIncr; - MCD_remVariants.remSrcIncr[channel] = srcIncr; - MCD_remVariants.remXferSize[channel] = xferSize; -#endif - - cSave = - (int *)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + - CURRBD; - -#ifdef MCD_INCLUDE_EU - /* may move this to EU specific calls */ - realFuncArray = - (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00); - /* Modify the LURC's normal and byte-residue-loop functions according - to parameter. */ - realFuncArray[(LURC * 16)] = xferSize == 4 ? - funcDesc : xferSize == 2 ? - funcDesc & 0xfffff00f : funcDesc & 0xffff000f; - realFuncArray[(LURC * 16 + 1)] = - (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL; -#endif - /* Write the initiator field in the TCR, and also set the - initiator-hold bit. Note that,due to a hardware quirk, this could - collide with an MDE access to the initiator-register file, so we - have to verify that the write reads back correctly. */ - - MCD_dmaBar->taskControl[channel] = - (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM; - - while (((MCD_dmaBar->taskControl[channel] & 0x1fff) != - ((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) - && (tcrCount < 1000)) { - tcrCount++; - /*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020; */ - MCD_dmaBar->taskControl[channel] = - (initiator << 8) | TASK_CTL_HIPRITSKEN | - TASK_CTL_HLDINITNUM; - } - - MCD_dmaBar->priority[channel] = (u8) priority & PRIORITY_PRI_MASK; - /* should be albe to handle this stuff with only one write to ts reg - - tbd */ - if (channel < 8 && channel >= 0) { - MCD_dmaBar->taskSize0 &= ~(0xf << (7 - channel) * 4); - MCD_dmaBar->taskSize0 |= - (xferSize & 3) << (((7 - channel) * 4) + 2); - MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel) * 4); - } else { - MCD_dmaBar->taskSize1 &= ~(0xf << (15 - channel) * 4); - MCD_dmaBar->taskSize1 |= - (xferSize & 3) << (((15 - channel) * 4) + 2); - MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel) * 4); - } - - /* setup task table flags/options which mostly control the line - buffers */ - MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK; - MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags); - - if (flags & MCD_FECTX_DMA) { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_FECTX].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_FECTX].TDTend; - MCD_startDmaENetXmit((char *)srcAddr, (char *)srcAddr, - (char *)destAddr, MCD_taskTable, - channel); - } else if (flags & MCD_FECRX_DMA) { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_FECRX].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_FECRX].TDTend; - MCD_startDmaENetRcv((char *)srcAddr, (char *)srcAddr, - (char *)destAddr, MCD_taskTable, - channel); - } else if (flags & MCD_SINGLE_DMA) { - /* this buffer descriptor is used for storing off initial - parameters for later progress query calculation and for the - DMA to write the resulting checksum. The DMA does not use - this to determine how to operate, that info is passed with - the init routine */ - MCD_relocBuffDesc[channel].srcAddr = srcAddr; - MCD_relocBuffDesc[channel].destAddr = destAddr; - - /* definitely not its final value */ - MCD_relocBuffDesc[channel].lastDestAddr = destAddr; - - MCD_relocBuffDesc[channel].dmaSize = dmaSize; - MCD_relocBuffDesc[channel].flags = 0; /* not used */ - MCD_relocBuffDesc[channel].csumResult = 0; /* not used */ - MCD_relocBuffDesc[channel].next = 0; /* not used */ - - /* Initialize the progress-querying stuff to show no - progress: */ - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET] = -(u32) & (MCD_relocBuffDesc[channel]); - /* tbd - need to keep the user from trying to call the EU - routine when MCD_INCLUDE_EU is not defined */ - if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_SINGLENOEU].TDTend; - MCD_startDmaSingleNoEu((char *)srcAddr, srcIncr, - (char *)destAddr, destIncr, - (int)dmaSize, xferSizeIncr, - flags, (int *) - &(MCD_relocBuffDesc[channel]), - cSave, MCD_taskTable, channel); - } else { - /* TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_SINGLEEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_SINGLEEU].TDTend; - MCD_startDmaSingleEu((char *)srcAddr, srcIncr, - (char *)destAddr, destIncr, - (int)dmaSize, xferSizeIncr, - flags, (int *) - &(MCD_relocBuffDesc[channel]), - cSave, MCD_taskTable, channel); - } - } else { /* chained DMAS */ - /* Initialize the progress-querying stuff to show no - progress: */ -#if 1 - /* (!defined(MCD_NEED_ADDR_TRANS)) */ - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddr)->srcAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddr)->destAddr; -#else - /* if using address translation, need the virtual addr of the - first buffdesc */ - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddrVirt)->srcAddr; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET] - = (int)((MCD_bufDesc *) srcAddrVirt)->destAddr; -#endif - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr; - - if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { - /*TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_CHAINNOEU].TDTend; - MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, - destIncr, xferSize, - xferSizeIncr, cSave, - MCD_taskTable, channel); - } else { - /*TDTStart and TDTEnd */ - MCD_taskTable[channel].TDTstart = - MCD_modelTaskTable[TASK_CHAINEU].TDTstart; - MCD_taskTable[channel].TDTend = - MCD_modelTaskTable[TASK_CHAINEU].TDTend; - MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, - xferSize, xferSizeIncr, cSave, - MCD_taskTable, channel); - } - } - MCD_chStatus[channel] = MCD_IDLE; - return (MCD_OK); -} - -/************************ End of MCD_startDma() *********************/ - -/********************************************************************/ -/* Function: MCD_XferProgrQuery - * Purpose: Returns progress of DMA on requested channel - * Arguments: channel - channel to retrieve progress for - * progRep - pointer to user supplied MCD_XferProg struct - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - * - * Notes: - * MCD_XferProgrQuery() upon completing or after aborting a DMA, or - * while the DMA is in progress, this function returns the first - * DMA-destination address not (or not yet) used in the DMA. When - * encountering a non-ready buffer descriptor, the information for - * the last completed descriptor is returned. - * - * MCD_XferProgQuery() has to avoid the possibility of getting - * partially-updated information in the event that we should happen - * to query DMA progress just as the DMA is updating it. It does that - * by taking advantage of the fact context is not saved frequently for - * the most part. We therefore read it at least twice until we get the - * same information twice in a row. - * - * Because a small, but not insignificant, amount of time is required - * to write out the progress-query information, especially upon - * completion of the DMA, it would be wise to guarantee some time lag - * between successive readings of the progress-query information. - */ - -/* How many iterations of the loop below to execute to stabilize values */ -#define STABTIME 0 - -int MCD_XferProgrQuery(int channel, MCD_XferProg * progRep) -{ - MCD_XferProg prevRep; - int again; /* true if we are to try again to ge - consistent results */ - int i; /* used as a time-waste counter */ - int destDiffBytes; /* Total no of bytes that we think actually - got xfered. */ - int numIterations; /* number of iterations */ - int bytesNotXfered; /* bytes that did not get xfered. */ - s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr; - int subModVal, addModVal; /* Mode values to added and subtracted - from the final destAddr */ - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - /* Read a trial value for the progress-reporting values */ - prevRep.lastSrcAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; - prevRep.lastDestAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; - prevRep.dmaSize = - ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + - CSAVE_OFFSET]; - prevRep.currBufDesc = - (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET]; - /* Repeatedly reread those values until they match previous values: */ - do { - /* Waste a little bit of time to ensure stability: */ - for (i = 0; i < STABTIME; i++) { - /* make sure this loop does something so that it - doesn't get optimized out */ - i += i >> 2; - } - /* Check them again: */ - progRep->lastSrcAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; - progRep->lastDestAddr = - (s8 *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; - progRep->dmaSize = - ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[DCOUNT + CSAVE_OFFSET]; - progRep->currBufDesc = - (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. - contextSaveSpace)[CURRBD + CSAVE_OFFSET]; - /* See if they match: */ - if (prevRep.lastSrcAddr != progRep->lastSrcAddr - || prevRep.lastDestAddr != progRep->lastDestAddr - || prevRep.dmaSize != progRep->dmaSize - || prevRep.currBufDesc != progRep->currBufDesc) { - /* If they don't match, remember previous values and - try again: */ - prevRep.lastSrcAddr = progRep->lastSrcAddr; - prevRep.lastDestAddr = progRep->lastDestAddr; - prevRep.dmaSize = progRep->dmaSize; - prevRep.currBufDesc = progRep->currBufDesc; - again = MCD_TRUE; - } else - again = MCD_FALSE; - } while (again == MCD_TRUE); - - /* Update the dCount, srcAddr and destAddr */ - /* To calculate dmaCount, we consider destination address. C - overs M1,P1,Z for destination */ - switch (MCD_remVariants.remDestRsdIncr[channel]) { - case MINUS1: - subModVal = - ((int)progRep-> - lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - - 1); - addModVal = - ((int)progRep->currBufDesc-> - destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); - LWAlignedInitDestAddr = - (progRep->currBufDesc->destAddr) - addModVal; - LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal; - destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr; - bytesNotXfered = - (destDiffBytes / MCD_remVariants.remDestIncr[channel]) * - (MCD_remVariants.remDestIncr[channel] - + MCD_remVariants.remXferSize[channel]); - progRep->dmaSize = - destDiffBytes - bytesNotXfered + addModVal - subModVal; - break; - case ZERO: - progRep->lastDestAddr = progRep->currBufDesc->destAddr; - break; - case PLUS1: - /* This value has to be subtracted from the final - calculated dCount. */ - subModVal = - ((int)progRep->currBufDesc-> - destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); - /* These bytes are already in lastDestAddr. */ - addModVal = - ((int)progRep-> - lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - - 1); - LWAlignedInitDestAddr = - (progRep->currBufDesc->destAddr) - subModVal; - LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal; - destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr); - numIterations = - (LWAlignedCurrDestAddr - - LWAlignedInitDestAddr) / - MCD_remVariants.remDestIncr[channel]; - bytesNotXfered = - numIterations * (MCD_remVariants.remDestIncr[channel] - - MCD_remVariants.remXferSize[channel]); - progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal; - break; - default: - break; - } - - /* This covers M1,P1,Z for source */ - switch (MCD_remVariants.remSrcRsdIncr[channel]) { - case MINUS1: - progRep->lastSrcAddr = - progRep->currBufDesc->srcAddr + - (MCD_remVariants.remSrcIncr[channel] * - (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); - break; - case ZERO: - progRep->lastSrcAddr = progRep->currBufDesc->srcAddr; - break; - case PLUS1: - progRep->lastSrcAddr = - progRep->currBufDesc->srcAddr + - (MCD_remVariants.remSrcIncr[channel] * - (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); - break; - default: - break; - } - - return (MCD_OK); -} - -/******************* End of MCD_XferProgrQuery() ********************/ - -/********************************************************************/ -/* MCD_resmActions() does the majority of the actions of a DMA resume. - * It is called from MCD_killDma() and MCD_resumeDma(). It has to be - * a separate function because the kill function has to negate the task - * enable before resuming it, but the resume function has to do nothing - * if there is no DMA on that channel (i.e., if the enable bit is 0). - */ -static void MCD_resmActions(int channel) -{ - MCD_dmaBar->debugControl = DBG_CTL_DISABLE; - MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus; - /* This register is selected to know which initiator is - actually asserted. */ - MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; - - if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) - MCD_chStatus[channel] = MCD_RUNNING; - else - MCD_chStatus[channel] = MCD_IDLE; -} - -/********************* End of MCD_resmActions() *********************/ - -/********************************************************************/ -/* Function: MCD_killDma - * Purpose: Halt the DMA on the requested channel, without any - * intention of resuming the DMA. - * Arguments: channel - requested channel - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - * - * Notes: - * A DMA may be killed from any state, including paused state, and it - * always goes to the MCD_HALTED state even if it is killed while in - * the MCD_NO_DMA or MCD_IDLE states. - */ -int MCD_killDma(int channel) -{ - /* MCD_XferProg progRep; */ - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - MCD_dmaBar->taskControl[channel] = 0x0; - MCD_resumeDma(channel); - /* - * This must be after the write to the TCR so that the task doesn't - * start up again momentarily, and before the status assignment so - * as to override whatever MCD_resumeDma() may do to the channel - * status. - */ - MCD_chStatus[channel] = MCD_HALTED; - - /* - * Update the current buffer descriptor's lastDestAddr field - * - * MCD_XferProgrQuery (channel, &progRep); - * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; - */ - return (MCD_OK); -} - -/************************ End of MCD_killDma() **********************/ - -/********************************************************************/ -/* Function: MCD_continDma - * Purpose: Continue a DMA which as stopped due to encountering an - * unready buffer descriptor. - * Arguments: channel - channel to continue the DMA on - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - * - * Notes: - * This routine does not check to see if there is a task which can - * be continued. Also this routine should not be used with single DMAs. - */ -int MCD_continDma(int channel) -{ - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN; - MCD_chStatus[channel] = MCD_RUNNING; - - return (MCD_OK); -} - -/********************** End of MCD_continDma() **********************/ - -/********************************************************************* - * MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit - * to freeze a task and resume it. We freeze a task by breakpointing - * on the stated task. That is, not any specific place in the task, - * but any time that task executes. In particular, when that task - * executes, we want to freeze that task and only that task. - * - * The bits of the debug control register influence interrupts vs. - * breakpoints as follows: - * - Bits 14 and 0 enable or disable debug functions. If enabled, you - * will get the interrupt but you may or may not get a breakpoint. - * - Bits 2 and 1 decide whether you also get a breakpoint in addition - * to an interrupt. - * - * The debug unit can do these actions in response to either internally - * detected breakpoint conditions from the comparators, or in response - * to the external breakpoint pin, or both. - * - Bits 14 and 1 perform the above-described functions for - * internally-generated conditions, i.e., the debug comparators. - * - Bits 0 and 2 perform the above-described functions for external - * conditions, i.e., the breakpoint external pin. - * - * Note that, although you "always" get the interrupt when you turn - * the debug functions, the interrupt can nevertheless, if desired, be - * masked by the corresponding bit in the PTD's IMR. Note also that - * this means that bits 14 and 0 must enable debug functions before - * bits 1 and 2, respectively, have any effect. - * - * NOTE: It's extremely important to not pause more than one DMA channel - * at a time. - ********************************************************************/ - -/********************************************************************/ -/* Function: MCD_pauseDma - * Purpose: Pauses the DMA on a given channel (if any DMA is running - * on that channel). - * Arguments: channel - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - */ -int MCD_pauseDma(int channel) -{ - /* MCD_XferProg progRep; */ - - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) { - MCD_dmaBar->debugComp1 = channel; - MCD_dmaBar->debugControl = - DBG_CTL_ENABLE | (1 << (channel + 16)); - MCD_chStatus[channel] = MCD_PAUSED; - - /* - * Update the current buffer descriptor's lastDestAddr field - * - * MCD_XferProgrQuery (channel, &progRep); - * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; - */ - } - return (MCD_OK); -} - -/************************* End of MCD_pauseDma() ********************/ - -/********************************************************************/ -/* Function: MCD_resumeDma - * Purpose: Resumes the DMA on a given channel (if any DMA is - * running on that channel). - * Arguments: channel - channel on which to resume DMA - * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK - */ -int MCD_resumeDma(int channel) -{ - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) - MCD_resmActions(channel); - - return (MCD_OK); -} - -/************************ End of MCD_resumeDma() ********************/ - -/********************************************************************/ -/* Function: MCD_csumQuery - * Purpose: Provide the checksum after performing a non-chained DMA - * Arguments: channel - channel to report on - * csum - pointer to where to write the checksum/CRC - * Returns: MCD_ERROR if the channel is invalid, else MCD_OK - * - * Notes: - * - */ -int MCD_csumQuery(int channel, u32 * csum) -{ -#ifdef MCD_INCLUDE_EU - if ((channel < 0) || (channel >= NCHANNELS)) - return (MCD_CHANNEL_INVALID); - - *csum = MCD_relocBuffDesc[channel].csumResult; - return (MCD_OK); -#else - return (MCD_ERROR); -#endif -} - -/*********************** End of MCD_resumeDma() *********************/ - -/********************************************************************/ -/* Function: MCD_getCodeSize - * Purpose: Provide the size requirements of the microcoded tasks - * Returns: Size in bytes - */ -int MCD_getCodeSize(void) -{ -#ifdef MCD_INCLUDE_EU - return (0x2b5c); -#else - return (0x173c); -#endif -} - -/********************** End of MCD_getCodeSize() ********************/ - -/********************************************************************/ -/* Function: MCD_getVersion - * Purpose: Provide the version string and number - * Arguments: longVersion - user supplied pointer to a pointer to a char - * which points to the version string - * Returns: Version number and version string (by reference) - */ -char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)"; -#define MCD_REV_MAJOR 0x00 -#define MCD_REV_MINOR 0x03 - -int MCD_getVersion(char **longVersion) -{ - *longVersion = MCD_versionString; - return ((MCD_REV_MAJOR << 8) | MCD_REV_MINOR); -} - -/********************** End of MCD_getVersion() *********************/ - -/********************************************************************/ -/* Private version of memcpy() - * Note that everything this is used for is longword-aligned. - */ -static void MCD_memcpy(int *dest, int *src, u32 size) -{ - u32 i; - - for (i = 0; i < size; i += sizeof(int), dest++, src++) - *dest = *src; -} diff --git a/drivers/dma/MCD_tasks.c b/drivers/dma/MCD_tasks.c deleted file mode 100644 index 453d954..0000000 --- a/drivers/dma/MCD_tasks.c +++ /dev/null @@ -1,2413 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. - */ - -/* Contains task code and structures for Multi-channel DMA */ - -#include <common.h> - -#include <MCD_dma.h> - -u32 MCD_varTab0[]; -u32 MCD_varTab1[]; -u32 MCD_varTab2[]; -u32 MCD_varTab3[]; -u32 MCD_varTab4[]; -u32 MCD_varTab5[]; -u32 MCD_varTab6[]; -u32 MCD_varTab7[]; -u32 MCD_varTab8[]; -u32 MCD_varTab9[]; -u32 MCD_varTab10[]; -u32 MCD_varTab11[]; -u32 MCD_varTab12[]; -u32 MCD_varTab13[]; -u32 MCD_varTab14[]; -u32 MCD_varTab15[]; - -u32 MCD_funcDescTab0[]; -#ifdef MCD_INCLUDE_EU -u32 MCD_funcDescTab1[]; -u32 MCD_funcDescTab2[]; -u32 MCD_funcDescTab3[]; -u32 MCD_funcDescTab4[]; -u32 MCD_funcDescTab5[]; -u32 MCD_funcDescTab6[]; -u32 MCD_funcDescTab7[]; -u32 MCD_funcDescTab8[]; -u32 MCD_funcDescTab9[]; -u32 MCD_funcDescTab10[]; -u32 MCD_funcDescTab11[]; -u32 MCD_funcDescTab12[]; -u32 MCD_funcDescTab13[]; -u32 MCD_funcDescTab14[]; -u32 MCD_funcDescTab15[]; -#endif - -u32 MCD_contextSave0[]; -u32 MCD_contextSave1[]; -u32 MCD_contextSave2[]; -u32 MCD_contextSave3[]; -u32 MCD_contextSave4[]; -u32 MCD_contextSave5[]; -u32 MCD_contextSave6[]; -u32 MCD_contextSave7[]; -u32 MCD_contextSave8[]; -u32 MCD_contextSave9[]; -u32 MCD_contextSave10[]; -u32 MCD_contextSave11[]; -u32 MCD_contextSave12[]; -u32 MCD_contextSave13[]; -u32 MCD_contextSave14[]; -u32 MCD_contextSave15[]; - -u32 MCD_realTaskTableSrc[] = { - 0x00000000, - 0x00000000, - (u32) MCD_varTab0, /* Task 0 Variable Table */ - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ - 0x00000000, - 0x00000000, - (u32) MCD_contextSave0, /* Task 0 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab1, /* Task 1 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab1, /* Task 1 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave1, /* Task 1 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab2, /* Task 2 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab2, /* Task 2 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave2, /* Task 2 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab3, /* Task 3 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab3, /* Task 3 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave3, /* Task 3 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab4, /* Task 4 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab4, /* Task 4 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave4, /* Task 4 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab5, /* Task 5 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab5, /* Task 5 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave5, /* Task 5 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab6, /* Task 6 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab6, /* Task 6 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave6, /* Task 6 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab7, /* Task 7 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab7, /* Task 7 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave7, /* Task 7 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab8, /* Task 8 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab8, /* Task 8 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave8, /* Task 8 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab9, /* Task 9 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab9, /* Task 9 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave9, /* Task 9 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab10, /* Task 10 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab10, /* Task 10 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave10, /* Task 10 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab11, /* Task 11 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab11, /* Task 11 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave11, /* Task 11 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab12, /* Task 12 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab12, /* Task 12 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave12, /* Task 12 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab13, /* Task 13 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab13, /* Task 13 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave13, /* Task 13 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab14, /* Task 14 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab14, /* Task 14 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave14, /* Task 14 context save space */ - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_varTab15, /* Task 15 Variable Table */ -#ifdef MCD_INCLUDE_EU - (u32) MCD_funcDescTab15, /* Task 15 Fn Desc. Table & Flags */ -#else - (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ -#endif - 0x00000000, - 0x00000000, - (u32) MCD_contextSave15, /* Task 15 context save space */ - 0x00000000, -}; - -u32 MCD_varTab0[] = { /* Task 0 Variable Table */ - 0x00000000, /* var[0] */ - 0x00000000, /* var[1] */ - 0x00000000, /* var[2] */ - 0x00000000, /* var[3] */ - 0x00000000, /* var[4] */ - 0x00000000, /* var[5] */ - 0x00000000, /* var[6] */ - 0x00000000, /* var[7] */ - 0x00000000, /* var[8] */ - 0x00000000, /* var[9] */ - 0x00000000, /* var[10] */ - 0x00000000, /* var[11] */ - 0x00000000, /* var[12] */ - 0x00000000, /* var[13] */ - 0x00000000, /* var[14] */ - 0x00000000, /* var[15] */ - 0x00000000, /* var[16] */ - 0x00000000, /* var[17] */ - 0x00000000, /* var[18] */ - 0x00000000, /* var[19] */ - 0x00000000, /* var[20] */ - 0x00000000, /* var[21] */ - 0x00000000, /* var[22] */ - 0x00000000, /* var[23] */ - 0xe0000000, /* inc[0] */ - 0x20000000, /* inc[1] */ - 0x2000ffff, /* inc[2] */ - 0x00000000, /* inc[3] */ - 0x00000000, /* inc[4] */ - 0x00000000, /* inc[5] */ - 0x00000000, /* inc[6] */ - 0x00000000, /* inc[7] */ -}; - -u32 MCD_varTab1[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab2[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab3[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab4[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab5[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab6[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab7[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab8[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab9[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab10[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab11[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab12[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab13[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab14[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_varTab15[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xe0000000, - 0x20000000, - 0x2000ffff, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_funcDescTab0[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -#ifdef MCD_INCLUDE_EU -u32 MCD_funcDescTab1[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab2[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab3[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab4[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab5[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab6[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab7[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab8[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab9[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab10[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab11[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab12[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab13[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab14[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; - -u32 MCD_funcDescTab15[] = { - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0xa0045670, - 0xa0000000, - 0xa0000000, - 0x20000000, - 0x21800000, - 0x21e00000, - 0x20400000, - 0x20500000, - 0x205a0000, - 0x20a00000, - 0x202fa000, - 0x202f9000, - 0x202ea000, - 0x202da000, - 0x202e2000, - 0x202f2000, -}; -#endif /*MCD_INCLUDE_EU */ - -u32 MCD_contextSave0[128]; /* Task 0 context save space */ -u32 MCD_contextSave1[128]; /* Task 1 context save space */ -u32 MCD_contextSave2[128]; /* Task 2 context save space */ -u32 MCD_contextSave3[128]; /* Task 3 context save space */ -u32 MCD_contextSave4[128]; /* Task 4 context save space */ -u32 MCD_contextSave5[128]; /* Task 5 context save space */ -u32 MCD_contextSave6[128]; /* Task 6 context save space */ -u32 MCD_contextSave7[128]; /* Task 7 context save space */ -u32 MCD_contextSave8[128]; /* Task 8 context save space */ -u32 MCD_contextSave9[128]; /* Task 9 context save space */ -u32 MCD_contextSave10[128]; /* Task 10 context save space */ -u32 MCD_contextSave11[128]; /* Task 11 context save space */ -u32 MCD_contextSave12[128]; /* Task 12 context save space */ -u32 MCD_contextSave13[128]; /* Task 13 context save space */ -u32 MCD_contextSave14[128]; /* Task 14 context save space */ -u32 MCD_contextSave15[128]; /* Task 15 context save space */ - -u32 MCD_ChainNoEu_TDT[]; -u32 MCD_SingleNoEu_TDT[]; -#ifdef MCD_INCLUDE_EU -u32 MCD_ChainEu_TDT[]; -u32 MCD_SingleEu_TDT[]; -#endif -u32 MCD_ENetRcv_TDT[]; -u32 MCD_ENetXmit_TDT[]; - -u32 MCD_modelTaskTableSrc[] = { - (u32) MCD_ChainNoEu_TDT, - (u32) & ((u8 *) MCD_ChainNoEu_TDT)[0x0000016c], - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_SingleNoEu_TDT, - (u32) & ((u8 *) MCD_SingleNoEu_TDT)[0x000000d4], - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -#ifdef MCD_INCLUDE_EU - (u32) MCD_ChainEu_TDT, - (u32) & ((u8 *) MCD_ChainEu_TDT)[0x000001b4], - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_SingleEu_TDT, - (u32) & ((u8 *) MCD_SingleEu_TDT)[0x00000124], - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -#endif - (u32) MCD_ENetRcv_TDT, - (u32) & ((u8 *) MCD_ENetRcv_TDT)[0x0000009c], - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - (u32) MCD_ENetXmit_TDT, - (u32) & ((u8 *) MCD_ENetXmit_TDT)[0x000000d0], - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, - 0x00000000, -}; - -u32 MCD_ChainNoEu_TDT[] = { - 0x80004000, - 0x8118801b, - 0xb8c60018, - 0x10002b10, - 0x7000000d, - 0x018cf89f, - 0x6000000a, - 0x080cf89f, - 0x000001f8, - 0x98180364, - 0x8118801b, - 0xf8c6001a, - 0xb8c6601b, - 0x10002710, - 0x00000f18, - 0xb8c6001d, - 0x10001310, - 0x60000007, - 0x014cf88b, - 0x98c6001c, - 0x00000710, - 0x98c70018, - 0x10001f10, - 0x0000c818, - 0x000001f8, - 0xc1476018, - 0xc003231d, - 0x811a601b, - 0xc1862102, - 0x849be009, - 0x03fed7b8, - 0xda9b001b, - 0x9b9be01b, - 0x1000cb20, - 0x70000006, - 0x088cf88f, - 0x1000cb28, - 0x70000006, - 0x088cf88f, - 0x1000cb30, - 0x70000006, - 0x088cf88f, - 0x1000cb38, - 0x0000c728, - 0x000001f8, - 0xc1476018, - 0xc003241d, - 0x811a601b, - 0xda9b001b, - 0x9b9be01b, - 0x0000d3a0, - 0xc1862102, - 0x849be009, - 0x0bfed7b8, - 0xda9b001b, - 0x9b9be01b, - 0x1000cb20, - 0x70000006, - 0x088cf88f, - 0x1000cb28, - 0x70000006, - 0x088cf88f, - 0x1000cb30, - 0x70000006, - 0x088cf88f, - 0x1000cb38, - 0x0000c728, - 0x000001f8, - 0x8118801b, - 0xd8c60018, - 0x98c6601c, - 0x6000000b, - 0x0c8cfc9f, - 0x000001f8, - 0xa146001e, - 0x10000b08, - 0x10002050, - 0xb8c60018, - 0x10002b10, - 0x7000000a, - 0x080cf89f, - 0x6000000d, - 0x018cf89f, - 0x000001f8, - 0x8618801b, - 0x7000000e, - 0x084cf21f, - 0xd8990336, - 0x8019801b, - 0x040001f8, - 0x000001f8, - 0x000001f8, -}; - -u32 MCD_SingleNoEu_TDT[] = { - 0x8198001b, - 0x7000000d, - 0x080cf81f, - 0x8198801b, - 0x6000000e, - 0x084cf85f, - 0x000001f8, - 0x8298001b, - 0x7000000d, - 0x010cf81f, - 0x6000000e, - 0x018cf81f, - 0xc202601b, - 0xc002221c, - 0x809a601b, - 0xc10420c2, - 0x839be009, - 0x03fed7b8, - 0xda9b001b, - 0x9b9be01b, - 0x70000006, - 0x088cf889, - 0x1000cb28, - 0x70000006, - 0x088cf889, - 0x1000cb30, - 0x70000006, - 0x088cf889, - 0x0000cb38, - 0x000001f8, - 0xc202601b, - 0xc002229c, - 0x809a601b, - 0xda9b001b, - 0x9b9be01b, - 0x0000d3a0, - 0xc10420c2, - 0x839be009, - 0x0bfed7b8, - 0xda9b001b, - 0x9b9be01b, - 0x70000006, - 0x088cf889, - 0x1000cb28, - 0x70000006, - 0x088cf889, - 0x1000cb30, - 0x70000006, - 0x088cf889, - 0x0000cb38, - 0x000001f8, - 0xc318022d, - 0x8018801b, - 0x040001f8, -}; - -#ifdef MCD_INCLUDE_EU -u32 MCD_ChainEu_TDT[] = { - 0x80004000, - 0x8198801b, - 0xb8c68018, - 0x10002f10, - 0x7000000d, - 0x01ccf89f, - 0x6000000a, - 0x080cf89f, - 0x000001f8, - 0x981803a4, - 0x8198801b, - 0xf8c6801a, - 0xb8c6e01b, - 0x10002b10, - 0x00001318, - 0xb8c6801d, - 0x10001710, - 0x60000007, - 0x018cf88c, - 0x98c6801c, - 0x00000b10, - 0x98c78018, - 0x10002310, - 0x0000c820, - 0x000001f8, - 0x8698801b, - 0x7000000f, - 0x084cf2df, - 0xd899042d, - 0x8019801b, - 0x60000003, - 0x2cd7c7df, - 0xd8990364, - 0x8019801b, - 0x60000003, - 0x2c17c7df, - 0x000001f8, - 0xc1c7e018, - 0xc003a35e, - 0x819a601b, - 0xc206a142, - 0x851be009, - 0x63fe0000, - 0x0d4cfddf, - 0xda9b001b, - 0x9b9be01b, - 0x70000002, - 0x004cf81f, - 0x1000cb20, - 0x70000006, - 0x088cf891, - 0x1000cb28, - 0x70000006, - 0x088cf891, - 0x1000cb30, - 0x70000006, - 0x088cf891, - 0x1000cb38, - 0x0000c728, - 0x000001f8, - 0xc1c7e018, - 0xc003a49e, - 0x819a601b, - 0xda9b001b, - 0x9b9be01b, - 0x0000d3a0, - 0xc206a142, - 0x851be009, - 0x6bfe0000, - 0x0d4cfddf, - 0xda9b001b, - 0x9b9be01b, - 0x70000002, - 0x004cf81f, - 0x1000cb20, - 0x70000006, - 0x088cf891, - 0x1000cb28, - 0x70000006, - 0x088cf891, - 0x1000cb30, - 0x70000006, - 0x088cf891, - 0x1000cb38, - 0x0000c728, - 0x000001f8, - 0x8198801b, - 0xd8c68018, - 0x98c6e01c, - 0x6000000b, - 0x0c8cfc9f, - 0x0000cc08, - 0xa1c6801e, - 0x10000f08, - 0x10002458, - 0xb8c68018, - 0x10002f10, - 0x7000000a, - 0x080cf89f, - 0x6000000d, - 0x01ccf89f, - 0x000001f8, - 0x8698801b, - 0x7000000e, - 0x084cf25f, - 0xd899037f, - 0x8019801b, - 0x040001f8, - 0x000001f8, - 0x000001f8, -}; - -u32 MCD_SingleEu_TDT[] = { - 0x8218001b, - 0x7000000d, - 0x080cf81f, - 0x8218801b, - 0x6000000e, - 0x084cf85f, - 0x000001f8, - 0x8318001b, - 0x7000000d, - 0x014cf81f, - 0x6000000e, - 0x01ccf81f, - 0x8498001b, - 0x7000000f, - 0x080cf19f, - 0xd81882a4, - 0x8019001b, - 0x60000003, - 0x2c97c7df, - 0xd818826d, - 0x8019001b, - 0x60000003, - 0x2c17c7df, - 0x000001f8, - 0xc282e01b, - 0xc002a25e, - 0x811a601b, - 0xc184a102, - 0x841be009, - 0x63fe0000, - 0x0d4cfddf, - 0xda9b001b, - 0x9b9be01b, - 0x70000002, - 0x004cf99f, - 0x70000006, - 0x088cf88b, - 0x1000cb28, - 0x70000006, - 0x088cf88b, - 0x1000cb30, - 0x70000006, - 0x088cf88b, - 0x0000cb38, - 0x000001f8, - 0xc282e01b, - 0xc002a31e, - 0x811a601b, - 0xda9b001b, - 0x9b9be01b, - 0x0000d3a0, - 0xc184a102, - 0x841be009, - 0x6bfe0000, - 0x0d4cfddf, - 0xda9b001b, - 0x9b9be01b, - 0x70000002, - 0x004cf99f, - 0x70000006, - 0x088cf88b, - 0x1000cb28, - 0x70000006, - 0x088cf88b, - 0x1000cb30, - 0x70000006, - 0x088cf88b, - 0x0000cb38, - 0x000001f8, - 0x8144801c, - 0x0000c008, - 0xc398027f, - 0x8018801b, - 0x040001f8, -}; -#endif -u32 MCD_ENetRcv_TDT[] = { - 0x80004000, - 0x81988000, - 0x10000788, - 0x6000000a, - 0x080cf05f, - 0x98180209, - 0x81c40004, - 0x7000000e, - 0x010cf05f, - 0x7000000c, - 0x01ccf05f, - 0x70000004, - 0x014cf049, - 0x70000004, - 0x004cf04a, - 0x00000b88, - 0xc4030150, - 0x8119e012, - 0x03e0cf90, - 0x81188000, - 0x000ac788, - 0xc4030000, - 0x8199e000, - 0x70000004, - 0x084cfc8b, - 0x60000005, - 0x0cccf841, - 0x81c60000, - 0xc399021b, - 0x80198000, - 0x00008400, - 0x00000f08, - 0x81988000, - 0x10000788, - 0x6000000a, - 0x080cf05f, - 0xc2188209, - 0x80190000, - 0x040001f8, - 0x000001f8, -}; - -u32 MCD_ENetXmit_TDT[] = { - 0x80004000, - 0x81988000, - 0x10000788, - 0x6000000a, - 0x080cf05f, - 0x98180309, - 0x80004003, - 0x81c60004, - 0x7000000e, - 0x014cf05f, - 0x7000000c, - 0x028cf05f, - 0x7000000d, - 0x018cf05f, - 0x70000004, - 0x01ccf04d, - 0x10000b90, - 0x60000004, - 0x020cf0a1, - 0xc3188312, - 0x83c70000, - 0x00001f10, - 0xc583a3c3, - 0x81042325, - 0x03e0c798, - 0xd8990000, - 0x9999e000, - 0x000acf98, - 0xd8992306, - 0x9999e03f, - 0x03eac798, - 0xd8990000, - 0x9999e000, - 0x000acf98, - 0xd8990000, - 0x99832302, - 0x0beac798, - 0x81988000, - 0x6000000b, - 0x0c4cfc5f, - 0x81c80000, - 0xc5190312, - 0x80198000, - 0x00008400, - 0x00000f08, - 0x81988000, - 0x10000788, - 0x6000000a, - 0x080cf05f, - 0xc2988309, - 0x80190000, - 0x040001f8, - 0x000001f8, -}; - -#ifdef MCD_INCLUDE_EU -MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; -#endif diff --git a/drivers/dma/MCD_tasksInit.c b/drivers/dma/MCD_tasksInit.c deleted file mode 100644 index 079cd0a..0000000 --- a/drivers/dma/MCD_tasksInit.c +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. - */ - -#include <common.h> - -/* Functions for initializing variable tables of different types of tasks. */ - -/* - * Do not edit! - */ - -#include <MCD_dma.h> - -extern dmaRegs *MCD_dmaBar; - -/* Task 0 */ - -void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, - int xferSize, short xferSizeIncr, int *cSave, - volatile TaskTableEntry * taskTable, int channel) -{ - volatile TaskTableEntry *taskChan = taskTable + channel; - - MCD_SET_VAR(taskChan, 2, (u32) currBD); /* var[2] */ - MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ - MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ - MCD_SET_VAR(taskChan, 11, (u32) xferSize); /* var[11] */ - MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ - MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ - MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ - MCD_SET_VAR(taskChan, 3, (u32) 0x00000000); /* var[3] */ - MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ - MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ - MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ - MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ - MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ - MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ - MCD_SET_VAR(taskChan, 10, (u32) 0x00000000); /* var[10] */ - MCD_SET_VAR(taskChan, 12, (u32) 0x00000000); /* var[12] */ - MCD_SET_VAR(taskChan, 13, (u32) 0x80000000); /* var[13] */ - MCD_SET_VAR(taskChan, 14, (u32) 0x00000010); /* var[14] */ - MCD_SET_VAR(taskChan, 15, (u32) 0x00000004); /* var[15] */ - MCD_SET_VAR(taskChan, 16, (u32) 0x08000000); /* var[16] */ - MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ - MCD_SET_VAR(taskChan, 28, (u32) 0x80000000); /* inc[4] */ - MCD_SET_VAR(taskChan, 29, (u32) 0x80000001); /* inc[5] */ - MCD_SET_VAR(taskChan, 30, (u32) 0x40000000); /* inc[6] */ - - /* Set the task's Enable bit in its Task Control Register */ - MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; -} - -/* Task 1 */ - -void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, - short destIncr, int dmaSize, short xferSizeIncr, - int flags, int *currBD, int *cSave, - volatile TaskTableEntry * taskTable, int channel) -{ - volatile TaskTableEntry *taskChan = taskTable + channel; - - MCD_SET_VAR(taskChan, 7, (u32) srcAddr); /* var[7] */ - MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ - MCD_SET_VAR(taskChan, 2, (u32) destAddr); /* var[2] */ - MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ - MCD_SET_VAR(taskChan, 3, (u32) dmaSize); /* var[3] */ - MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ - MCD_SET_VAR(taskChan, 5, (u32) flags); /* var[5] */ - MCD_SET_VAR(taskChan, 1, (u32) currBD); /* var[1] */ - MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ - MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ - MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ - MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ - MCD_SET_VAR(taskChan, 9, (u32) 0x00000004); /* var[9] */ - MCD_SET_VAR(taskChan, 10, (u32) 0x08000000); /* var[10] */ - MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ - MCD_SET_VAR(taskChan, 28, (u32) 0x80000001); /* inc[4] */ - MCD_SET_VAR(taskChan, 29, (u32) 0x40000000); /* inc[5] */ - - /* Set the task's Enable bit in its Task Control Register */ - MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; -} - -/* Task 2 */ - -void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, - int xferSize, short xferSizeIncr, int *cSave, - volatile TaskTableEntry * taskTable, int channel) -{ - volatile TaskTableEntry *taskChan = taskTable + channel; - - MCD_SET_VAR(taskChan, 3, (u32) currBD); /* var[3] */ - MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ - MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ - MCD_SET_VAR(taskChan, 12, (u32) xferSize); /* var[12] */ - MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ - MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ - MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ - MCD_SET_VAR(taskChan, 2, (u32) 0x00000000); /* var[2] */ - MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ - MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ - MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ - MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ - MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ - MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ - MCD_SET_VAR(taskChan, 10, (u32) 0x00000000); /* var[10] */ - MCD_SET_VAR(taskChan, 11, (u32) 0x00000000); /* var[11] */ - MCD_SET_VAR(taskChan, 13, (u32) 0x00000000); /* var[13] */ - MCD_SET_VAR(taskChan, 14, (u32) 0x80000000); /* var[14] */ - MCD_SET_VAR(taskChan, 15, (u32) 0x00000010); /* var[15] */ - MCD_SET_VAR(taskChan, 16, (u32) 0x00000001); /* var[16] */ - MCD_SET_VAR(taskChan, 17, (u32) 0x00000004); /* var[17] */ - MCD_SET_VAR(taskChan, 18, (u32) 0x08000000); /* var[18] */ - MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ - MCD_SET_VAR(taskChan, 28, (u32) 0x80000000); /* inc[4] */ - MCD_SET_VAR(taskChan, 29, (u32) 0xc0000000); /* inc[5] */ - MCD_SET_VAR(taskChan, 30, (u32) 0x80000001); /* inc[6] */ - MCD_SET_VAR(taskChan, 31, (u32) 0x40000000); /* inc[7] */ - - /* Set the task's Enable bit in its Task Control Register */ - MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; -} - -/* Task 3 */ - -void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, - short destIncr, int dmaSize, short xferSizeIncr, - int flags, int *currBD, int *cSave, - volatile TaskTableEntry * taskTable, int channel) -{ - volatile TaskTableEntry *taskChan = taskTable + channel; - - MCD_SET_VAR(taskChan, 8, (u32) srcAddr); /* var[8] */ - MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ - MCD_SET_VAR(taskChan, 3, (u32) destAddr); /* var[3] */ - MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ - MCD_SET_VAR(taskChan, 4, (u32) dmaSize); /* var[4] */ - MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ - MCD_SET_VAR(taskChan, 6, (u32) flags); /* var[6] */ - MCD_SET_VAR(taskChan, 2, (u32) currBD); /* var[2] */ - MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ - MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ - MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ - MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ - MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ - MCD_SET_VAR(taskChan, 10, (u32) 0x00000001); /* var[10] */ - MCD_SET_VAR(taskChan, 11, (u32) 0x00000004); /* var[11] */ - MCD_SET_VAR(taskChan, 12, (u32) 0x08000000); /* var[12] */ - MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ - MCD_SET_VAR(taskChan, 28, (u32) 0xc0000000); /* inc[4] */ - MCD_SET_VAR(taskChan, 29, (u32) 0x80000000); /* inc[5] */ - MCD_SET_VAR(taskChan, 30, (u32) 0x80000001); /* inc[6] */ - MCD_SET_VAR(taskChan, 31, (u32) 0x40000000); /* inc[7] */ - - /* Set the task's Enable bit in its Task Control Register */ - MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; -} - -/* Task 4 */ - -void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, - volatile TaskTableEntry * taskTable, int channel) -{ - volatile TaskTableEntry *taskChan = taskTable + channel; - - MCD_SET_VAR(taskChan, 0, (u32) bDBase); /* var[0] */ - MCD_SET_VAR(taskChan, 3, (u32) currBD); /* var[3] */ - MCD_SET_VAR(taskChan, 6, (u32) rcvFifoPtr); /* var[6] */ - MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ - MCD_SET_VAR(taskChan, 2, (u32) 0x00000000); /* var[2] */ - MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ - MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ - MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ - MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ - MCD_SET_VAR(taskChan, 9, (u32) 0x0000ffff); /* var[9] */ - MCD_SET_VAR(taskChan, 10, (u32) 0x30000000); /* var[10] */ - MCD_SET_VAR(taskChan, 11, (u32) 0x0fffffff); /* var[11] */ - MCD_SET_VAR(taskChan, 12, (u32) 0x00000008); /* var[12] */ - MCD_SET_VAR(taskChan, 24, (u32) 0x00000000); /* inc[0] */ - MCD_SET_VAR(taskChan, 25, (u32) 0x60000000); /* inc[1] */ - MCD_SET_VAR(taskChan, 26, (u32) 0x20000004); /* inc[2] */ - MCD_SET_VAR(taskChan, 27, (u32) 0x40000000); /* inc[3] */ - - /* Set the task's Enable bit in its Task Control Register */ - MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; -} - -/* Task 5 */ - -void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, - volatile TaskTableEntry * taskTable, int channel) -{ - volatile TaskTableEntry *taskChan = taskTable + channel; - - MCD_SET_VAR(taskChan, 0, (u32) bDBase); /* var[0] */ - MCD_SET_VAR(taskChan, 3, (u32) currBD); /* var[3] */ - MCD_SET_VAR(taskChan, 11, (u32) xmitFifoPtr); /* var[11] */ - MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ - MCD_SET_VAR(taskChan, 2, (u32) 0x00000000); /* var[2] */ - MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ - MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ - MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ - MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ - MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ - MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ - MCD_SET_VAR(taskChan, 10, (u32) 0x00000000); /* var[10] */ - MCD_SET_VAR(taskChan, 12, (u32) 0x00000000); /* var[12] */ - MCD_SET_VAR(taskChan, 13, (u32) 0x0000ffff); /* var[13] */ - MCD_SET_VAR(taskChan, 14, (u32) 0xffffffff); /* var[14] */ - MCD_SET_VAR(taskChan, 15, (u32) 0x00000004); /* var[15] */ - MCD_SET_VAR(taskChan, 16, (u32) 0x00000008); /* var[16] */ - MCD_SET_VAR(taskChan, 24, (u32) 0x00000000); /* inc[0] */ - MCD_SET_VAR(taskChan, 25, (u32) 0x60000000); /* inc[1] */ - MCD_SET_VAR(taskChan, 26, (u32) 0x40000000); /* inc[2] */ - MCD_SET_VAR(taskChan, 27, (u32) 0xc000fffc); /* inc[3] */ - MCD_SET_VAR(taskChan, 28, (u32) 0xe0000004); /* inc[4] */ - MCD_SET_VAR(taskChan, 29, (u32) 0x80000000); /* inc[5] */ - MCD_SET_VAR(taskChan, 30, (u32) 0x4000ffff); /* inc[6] */ - MCD_SET_VAR(taskChan, 31, (u32) 0xe0000001); /* inc[7] */ - - /* Set the task's Enable bit in its Task Control Register */ - MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; -} diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index a75572f..48811ea 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_DMA) += dma-uclass.o -obj-$(CONFIG_FSLDMAFEC) += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o obj-$(CONFIG_APBH_DMA) += apbh_dma.o obj-$(CONFIG_BCM6348_IUDMA) += bcm6348-iudma.o obj-$(CONFIG_FSL_DMA) += fsl_dma.o diff --git a/drivers/dma/ti/Makefile b/drivers/dma/ti/Makefile index 6807eb8..f4e0271 100644 --- a/drivers/dma/ti/Makefile +++ b/drivers/dma/ti/Makefile @@ -8,3 +8,4 @@ k3-psil-data-$(CONFIG_SOC_K3_J721E) += k3-psil-j721e.o k3-psil-data-$(CONFIG_SOC_K3_J721S2) += k3-psil-j721s2.o k3-psil-data-$(CONFIG_SOC_K3_AM642) += k3-psil-am64.o k3-psil-data-$(CONFIG_SOC_K3_AM625) += k3-psil-am62.o +k3-psil-data-$(CONFIG_SOC_K3_AM62A7) += k3-psil-am62a.o diff --git a/drivers/dma/ti/k3-psil-am62a.c b/drivers/dma/ti/k3-psil-am62a.c new file mode 100644 index 0000000..ca9d71f --- /dev/null +++ b/drivers/dma/ti/k3-psil-am62a.c @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 Texas Instruments Incorporated - https://www.ti.com + */ + +#include <linux/kernel.h> + +#include "k3-psil-priv.h" + +#define PSIL_PDMA_XY_TR(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .mapped_channel_id = -1, \ + .default_flow_id = -1, \ + }, \ + } + +#define PSIL_PDMA_XY_PKT(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .mapped_channel_id = -1, \ + .default_flow_id = -1, \ + .pkt_mode = 1, \ + }, \ + } + +#define PSIL_ETHERNET(x, ch, flow_base, flow_cnt) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 16, \ + .mapped_channel_id = ch, \ + .flow_start = flow_base, \ + .flow_num = flow_cnt, \ + .default_flow_id = flow_base, \ + }, \ + } + +#define PSIL_SAUL(x, ch, flow_base, flow_cnt, default_flow, tx) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + .pkt_mode = 1, \ + .needs_epib = 1, \ + .psd_size = 64, \ + .mapped_channel_id = ch, \ + .flow_start = flow_base, \ + .flow_num = flow_cnt, \ + .default_flow_id = default_flow, \ + .notdpkt = tx, \ + }, \ + } + +#define PSIL_PDMA_MCASP(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_PDMA_XY, \ + .pdma_acc32 = 1, \ + .pdma_burst = 1, \ + }, \ + } + +#define PSIL_CSI2RX(x) \ + { \ + .thread_id = x, \ + .ep_config = { \ + .ep_type = PSIL_EP_NATIVE, \ + }, \ + } + +/* PSI-L source thread IDs, used for RX (DMA_DEV_TO_MEM) */ +static struct psil_ep am62a_src_ep_map[] = { + /* SAUL */ + PSIL_SAUL(0x7504, 20, 35, 8, 35, 0), + PSIL_SAUL(0x7505, 21, 35, 8, 36, 0), + PSIL_SAUL(0x7506, 22, 43, 8, 43, 0), + PSIL_SAUL(0x7507, 23, 43, 8, 44, 0), + /* PDMA_MAIN0 - SPI0-3 */ + PSIL_PDMA_XY_PKT(0x4302), + PSIL_PDMA_XY_PKT(0x4303), + PSIL_PDMA_XY_PKT(0x4304), + PSIL_PDMA_XY_PKT(0x4305), + PSIL_PDMA_XY_PKT(0x4306), + PSIL_PDMA_XY_PKT(0x4307), + PSIL_PDMA_XY_PKT(0x4308), + PSIL_PDMA_XY_PKT(0x4309), + PSIL_PDMA_XY_PKT(0x430a), + PSIL_PDMA_XY_PKT(0x430b), + PSIL_PDMA_XY_PKT(0x430c), + PSIL_PDMA_XY_PKT(0x430d), + /* PDMA_MAIN1 - UART0-6 */ + PSIL_PDMA_XY_PKT(0x4400), + PSIL_PDMA_XY_PKT(0x4401), + PSIL_PDMA_XY_PKT(0x4402), + PSIL_PDMA_XY_PKT(0x4403), + PSIL_PDMA_XY_PKT(0x4404), + PSIL_PDMA_XY_PKT(0x4405), + PSIL_PDMA_XY_PKT(0x4406), + /* PDMA_MAIN2 - MCASP0-2 */ + PSIL_PDMA_MCASP(0x4500), + PSIL_PDMA_MCASP(0x4501), + PSIL_PDMA_MCASP(0x4502), + /* CPSW3G */ + PSIL_ETHERNET(0x4600, 19, 19, 16), + /* CSI2RX */ + PSIL_CSI2RX(0x5000), + PSIL_CSI2RX(0x5001), + PSIL_CSI2RX(0x5002), + PSIL_CSI2RX(0x5003), + PSIL_CSI2RX(0x5004), + PSIL_CSI2RX(0x5005), + PSIL_CSI2RX(0x5006), + PSIL_CSI2RX(0x5007), + PSIL_CSI2RX(0x5008), + PSIL_CSI2RX(0x5009), + PSIL_CSI2RX(0x500a), + PSIL_CSI2RX(0x500b), + PSIL_CSI2RX(0x500c), + PSIL_CSI2RX(0x500d), + PSIL_CSI2RX(0x500e), + PSIL_CSI2RX(0x500f), + PSIL_CSI2RX(0x5010), + PSIL_CSI2RX(0x5011), + PSIL_CSI2RX(0x5012), + PSIL_CSI2RX(0x5013), + PSIL_CSI2RX(0x5014), + PSIL_CSI2RX(0x5015), + PSIL_CSI2RX(0x5016), + PSIL_CSI2RX(0x5017), + PSIL_CSI2RX(0x5018), + PSIL_CSI2RX(0x5019), + PSIL_CSI2RX(0x501a), + PSIL_CSI2RX(0x501b), + PSIL_CSI2RX(0x501c), + PSIL_CSI2RX(0x501d), + PSIL_CSI2RX(0x501e), + PSIL_CSI2RX(0x501f), +}; + +/* PSI-L destination thread IDs, used for TX (DMA_MEM_TO_DEV) */ +static struct psil_ep am62a_dst_ep_map[] = { + /* SAUL */ + PSIL_SAUL(0xf500, 27, 83, 8, 83, 1), + PSIL_SAUL(0xf501, 28, 91, 8, 91, 1), + /* PDMA_MAIN0 - SPI0-3 */ + PSIL_PDMA_XY_PKT(0xc302), + PSIL_PDMA_XY_PKT(0xc303), + PSIL_PDMA_XY_PKT(0xc304), + PSIL_PDMA_XY_PKT(0xc305), + PSIL_PDMA_XY_PKT(0xc306), + PSIL_PDMA_XY_PKT(0xc307), + PSIL_PDMA_XY_PKT(0xc308), + PSIL_PDMA_XY_PKT(0xc309), + PSIL_PDMA_XY_PKT(0xc30a), + PSIL_PDMA_XY_PKT(0xc30b), + PSIL_PDMA_XY_PKT(0xc30c), + PSIL_PDMA_XY_PKT(0xc30d), + /* PDMA_MAIN1 - UART0-6 */ + PSIL_PDMA_XY_PKT(0xc400), + PSIL_PDMA_XY_PKT(0xc401), + PSIL_PDMA_XY_PKT(0xc402), + PSIL_PDMA_XY_PKT(0xc403), + PSIL_PDMA_XY_PKT(0xc404), + PSIL_PDMA_XY_PKT(0xc405), + PSIL_PDMA_XY_PKT(0xc406), + /* PDMA_MAIN2 - MCASP0-2 */ + PSIL_PDMA_MCASP(0xc500), + PSIL_PDMA_MCASP(0xc501), + PSIL_PDMA_MCASP(0xc502), + /* CPSW3G */ + PSIL_ETHERNET(0xc600, 19, 19, 8), + PSIL_ETHERNET(0xc601, 20, 27, 8), + PSIL_ETHERNET(0xc602, 21, 35, 8), + PSIL_ETHERNET(0xc603, 22, 43, 8), + PSIL_ETHERNET(0xc604, 23, 51, 8), + PSIL_ETHERNET(0xc605, 24, 59, 8), + PSIL_ETHERNET(0xc606, 25, 67, 8), + PSIL_ETHERNET(0xc607, 26, 75, 8), +}; + +struct psil_ep_map am62a_ep_map = { + .name = "am62a", + .src = am62a_src_ep_map, + .src_count = ARRAY_SIZE(am62a_src_ep_map), + .dst = am62a_dst_ep_map, + .dst_count = ARRAY_SIZE(am62a_dst_ep_map), +}; diff --git a/drivers/dma/ti/k3-psil-priv.h b/drivers/dma/ti/k3-psil-priv.h index 563bc57..83f873b 100644 --- a/drivers/dma/ti/k3-psil-priv.h +++ b/drivers/dma/ti/k3-psil-priv.h @@ -42,5 +42,6 @@ extern struct psil_ep_map j721e_ep_map; extern struct psil_ep_map j721s2_ep_map; extern struct psil_ep_map am64_ep_map; extern struct psil_ep_map am62_ep_map; +extern struct psil_ep_map am62a_ep_map; #endif /* K3_PSIL_PRIV_H_ */ diff --git a/drivers/dma/ti/k3-psil.c b/drivers/dma/ti/k3-psil.c index 963321a..d4d4fed 100644 --- a/drivers/dma/ti/k3-psil.c +++ b/drivers/dma/ti/k3-psil.c @@ -26,6 +26,8 @@ struct psil_endpoint_config *psil_get_ep_config(u32 thread_id) soc_ep_map = &am64_ep_map; else if (IS_ENABLED(CONFIG_SOC_K3_AM625)) soc_ep_map = &am62_ep_map; + else if (IS_ENABLED(CONFIG_SOC_K3_AM62A7)) + soc_ep_map = &am62a_ep_map; } if (thread_id & K3_PSIL_DST_THREAD_ID_OFFSET && soc_ep_map->dst) { diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index 837c6f1..11fc0fe 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -1,4 +1,5 @@ menu "Fastboot support" + depends on CMDLINE config FASTBOOT bool diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index 4e9d9b7..3576b06 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -91,6 +91,7 @@ void fastboot_okay(const char *reason, char *response) */ int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + int ret; static const char * const boot_cmds[] = { [FASTBOOT_REBOOT_REASON_BOOTLOADER] = "bootonce-bootloader", [FASTBOOT_REBOOT_REASON_FASTBOOTD] = "boot-fastboot", @@ -105,7 +106,18 @@ int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) if (reason >= FASTBOOT_REBOOT_REASONS_COUNT) return -EINVAL; - return bcb_write_reboot_reason(mmc_dev, "misc", boot_cmds[reason]); + ret = bcb_find_partition_and_load("mmc", mmc_dev, "misc"); + if (ret) + goto out; + + ret = bcb_set(BCB_FIELD_COMMAND, boot_cmds[reason]); + if (ret) + goto out; + + ret = bcb_store(); +out: + bcb_reset(); + return ret; } /** diff --git a/drivers/firmware/firmware-zynqmp.c b/drivers/firmware/firmware-zynqmp.c index 8ea15c7..dfad798 100644 --- a/drivers/firmware/firmware-zynqmp.c +++ b/drivers/firmware/firmware-zynqmp.c @@ -8,6 +8,7 @@ #include <common.h> #include <cpu_func.h> #include <dm.h> +#include <dm/device_compat.h> #include <dm/lists.h> #include <log.h> #include <zynqmp_firmware.h> @@ -290,10 +291,31 @@ int zynqmp_pmufw_load_config_object(const void *cfg_obj, size_t size) static int zynqmp_power_probe(struct udevice *dev) { + struct udevice *ipi_dev; + ofnode ipi_node; int ret; debug("%s, (dev=%p)\n", __func__, dev); + /* + * Probe all IPI parent node driver. It is important to have IPI + * devices available when requested by mbox_get_by* API. + * If IPI device isn't available, then mailbox request fails and + * that causes system boot failure. + * To avoid this make sure all IPI parent drivers are probed here, + * and IPI parent driver binds each child node to mailbox driver. + * This way mbox_get_by_* API will have correct mailbox device + * driver probed. + */ + ofnode_for_each_compatible_node(ipi_node, "xlnx,zynqmp-ipi-mailbox") { + ret = uclass_get_device_by_ofnode(UCLASS_NOP, ipi_node, &ipi_dev); + if (ret) { + dev_err(dev, "failed to get IPI device from node %s\n", + ofnode_get_name(ipi_node)); + return ret; + } + } + ret = mbox_get_by_name(dev, "tx", &zynqmp_power.tx_chan); if (ret) { debug("%s: Cannot find tx mailbox\n", __func__); diff --git a/drivers/firmware/scmi/sandbox-scmi_agent.c b/drivers/firmware/scmi/sandbox-scmi_agent.c index d131809..cc9011c 100644 --- a/drivers/firmware/scmi/sandbox-scmi_agent.c +++ b/drivers/firmware/scmi/sandbox-scmi_agent.c @@ -66,10 +66,10 @@ struct scmi_channel { }; static u8 protocols[] = { - SCMI_PROTOCOL_ID_POWER_DOMAIN, - SCMI_PROTOCOL_ID_CLOCK, - SCMI_PROTOCOL_ID_RESET_DOMAIN, - SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN, + CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN, (SCMI_PROTOCOL_ID_POWER_DOMAIN,)) + CONFIG_IS_ENABLED(CLK_SCMI, (SCMI_PROTOCOL_ID_CLOCK,)) + CONFIG_IS_ENABLED(RESET_SCMI, (SCMI_PROTOCOL_ID_RESET_DOMAIN,)) + CONFIG_IS_ENABLED(DM_REGULATOR_SCMI, (SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN,)) }; #define NUM_PROTOCOLS ARRAY_SIZE(protocols) @@ -1124,6 +1124,13 @@ unsigned int sandbox_scmi_channel_id(struct udevice *dev) return chan->channel_id; } +static int sandbox_proto_not_supported(struct scmi_msg *msg) +{ + *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; + + return 0; +} + static int sandbox_scmi_test_process_msg(struct udevice *dev, struct scmi_channel *channel, struct scmi_msg *msg) @@ -1160,6 +1167,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_POWER_DOMAIN: + if (!CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN)) + return sandbox_proto_not_supported(msg); + switch (msg->message_id) { case SCMI_PROTOCOL_VERSION: return sandbox_scmi_pwd_protocol_version(dev, msg); @@ -1180,6 +1190,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_CLOCK: + if (!CONFIG_IS_ENABLED(CLK_SCMI)) + return sandbox_proto_not_supported(msg); + switch (msg->message_id) { case SCMI_PROTOCOL_ATTRIBUTES: return sandbox_scmi_clock_protocol_attribs(dev, msg); @@ -1196,6 +1209,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_RESET_DOMAIN: + if (!CONFIG_IS_ENABLED(RESET_SCMI)) + return sandbox_proto_not_supported(msg); + switch (msg->message_id) { case SCMI_RESET_DOMAIN_ATTRIBUTES: return sandbox_scmi_rd_attribs(dev, msg); @@ -1206,6 +1222,9 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, } break; case SCMI_PROTOCOL_ID_VOLTAGE_DOMAIN: + if (!CONFIG_IS_ENABLED(DM_REGULATOR_SCMI)) + return sandbox_proto_not_supported(msg); + switch (msg->message_id) { case SCMI_VOLTAGE_DOMAIN_ATTRIBUTES: return sandbox_scmi_voltd_attribs(dev, msg); @@ -1224,8 +1243,7 @@ static int sandbox_scmi_test_process_msg(struct udevice *dev, case SCMI_PROTOCOL_ID_SYSTEM: case SCMI_PROTOCOL_ID_PERF: case SCMI_PROTOCOL_ID_SENSOR: - *(u32 *)msg->out_msg = SCMI_NOT_SUPPORTED; - return 0; + return sandbox_proto_not_supported(msg); default: break; } diff --git a/drivers/firmware/scmi/sandbox-scmi_devices.c b/drivers/firmware/scmi/sandbox-scmi_devices.c index facb5b0..603e2bb 100644 --- a/drivers/firmware/scmi/sandbox-scmi_devices.c +++ b/drivers/firmware/scmi/sandbox-scmi_devices.c @@ -62,12 +62,13 @@ static int sandbox_scmi_devices_remove(struct udevice *dev) if (!devices) return 0; - for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) { - int ret2 = reset_free(devices->reset + n); + if (CONFIG_IS_ENABLED(RESET_SCMI)) + for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) { + int ret2 = reset_free(devices->reset + n); - if (ret2 && !ret) - ret = ret2; - } + if (ret2 && !ret) + ret = ret2; + } return ret; } @@ -89,39 +90,53 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) .regul_count = SCMI_TEST_DEVICES_VOLTD_COUNT, }; - ret = power_domain_get_by_index(dev, priv->devices.pwdom, 0); - if (ret) { - dev_err(dev, "%s: Failed on power domain\n", __func__); - return ret; - } - - for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { - ret = clk_get_by_index(dev, n, priv->devices.clk + n); + if (CONFIG_IS_ENABLED(SCMI_POWER_DOMAIN)) { + ret = power_domain_get_by_index(dev, priv->devices.pwdom, 0); if (ret) { - dev_err(dev, "%s: Failed on clk %zu\n", __func__, n); + dev_err(dev, "%s: Failed on power domain\n", __func__); return ret; } } - for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) { - ret = reset_get_by_index(dev, n, priv->devices.reset + n); - if (ret) { - dev_err(dev, "%s: Failed on reset %zu\n", __func__, n); - goto err_reset; + if (CONFIG_IS_ENABLED(CLK_SCMI)) { + for (n = 0; n < SCMI_TEST_DEVICES_CLK_COUNT; n++) { + ret = clk_get_by_index(dev, n, priv->devices.clk + n); + if (ret) { + dev_err(dev, "%s: Failed on clk %zu\n", + __func__, n); + return ret; + } } } - for (n = 0; n < SCMI_TEST_DEVICES_VOLTD_COUNT; n++) { - char name[32]; - - ret = snprintf(name, sizeof(name), "regul%zu-supply", n); - assert(ret >= 0 && ret < sizeof(name)); + if (CONFIG_IS_ENABLED(RESET_SCMI)) { + for (n = 0; n < SCMI_TEST_DEVICES_RD_COUNT; n++) { + ret = reset_get_by_index(dev, n, + priv->devices.reset + n); + if (ret) { + dev_err(dev, "%s: Failed on reset %zu\n", + __func__, n); + goto err_reset; + } + } + } - ret = device_get_supply_regulator(dev, name, - priv->devices.regul + n); - if (ret) { - dev_err(dev, "%s: Failed on voltd %zu\n", __func__, n); - goto err_regul; + if (CONFIG_IS_ENABLED(DM_REGULATOR_SCMI)) { + for (n = 0; n < SCMI_TEST_DEVICES_VOLTD_COUNT; n++) { + char name[32]; + + ret = snprintf(name, sizeof(name), "regul%zu-supply", + n); + assert(ret >= 0 && ret < sizeof(name)); + + ret = device_get_supply_regulator(dev, name, + priv->devices.regul + + n); + if (ret) { + dev_err(dev, "%s: Failed on voltd %zu\n", + __func__, n); + goto err_regul; + } } } @@ -130,8 +145,9 @@ static int sandbox_scmi_devices_probe(struct udevice *dev) err_regul: n = SCMI_TEST_DEVICES_RD_COUNT; err_reset: - for (; n > 0; n--) - reset_free(priv->devices.reset + n - 1); + if (CONFIG_IS_ENABLED(RESET_SCMI)) + for (; n > 0; n--) + reset_free(priv->devices.reset + n - 1); return ret; } diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ba42b07..63e62e1 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -238,6 +238,15 @@ config MAX7320_GPIO original maxim device has 8 push/pull outputs, some clones offers 16bit. +config MAX77663_GPIO + bool "MAX77663 GPIO cell of PMIC driver" + depends on DM_GPIO && DM_PMIC_MAX77663 + help + GPIO driver for MAX77663 PMIC from Maxim Semiconductor. + MAX77663 PMIC has 8 pins that can be configured as GPIOs + and 3 GPIO-like pins dedicated for power/reset buttons + and LID sensor. + config MCP230XX_GPIO bool "MCP230XX GPIO driver" depends on DM @@ -426,6 +435,13 @@ config VYBRID_GPIO help Say yes here to support Vybrid vf610 GPIOs. +config PALMAS_GPIO + bool "TI PALMAS series PMICs GPIO" + depends on DM_GPIO && PMIC_PALMAS + help + Select this option to enable GPIO driver for the TI PALMAS + series chip family. + config PIC32_GPIO bool "Microchip PIC32 GPIO driver" depends on DM_GPIO && MACH_PIC32 diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index c8b3fd7..da3da5d 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_VYBRID_GPIO) += vybrid_gpio.o obj-$(CONFIG_HIKEY_GPIO) += hi6220_gpio.o obj-$(CONFIG_HSDK_CREG_GPIO) += hsdk-creg-gpio.o obj-$(CONFIG_IMX_RGPIO2P) += imx_rgpio2p.o +obj-$(CONFIG_$(SPL_)PALMAS_GPIO) += palmas_gpio.o obj-$(CONFIG_PIC32_GPIO) += pic32_gpio.o obj-$(CONFIG_OCTEON_GPIO) += octeon_gpio.o obj-$(CONFIG_MVEBU_GPIO) += mvebu_gpio.o @@ -68,6 +69,7 @@ obj-$(CONFIG_NX_GPIO) += nx_gpio.o obj-$(CONFIG_SIFIVE_GPIO) += sifive-gpio.o obj-$(CONFIG_NOMADIK_GPIO) += nmk_gpio.o obj-$(CONFIG_MAX7320_GPIO) += max7320_gpio.o +obj-$(CONFIG_$(SPL_)MAX77663_GPIO) += max77663_gpio.o obj-$(CONFIG_SL28CPLD_GPIO) += sl28cpld-gpio.o obj-$(CONFIG_ZYNQMP_GPIO_MODEPIN) += zynqmp_gpio_modepin.o obj-$(CONFIG_SLG7XL45106_I2C_GPO) += gpio_slg7xl45106.o diff --git a/drivers/gpio/dwapb_gpio.c b/drivers/gpio/dwapb_gpio.c index e6e9194..7a6eae9 100644 --- a/drivers/gpio/dwapb_gpio.c +++ b/drivers/gpio/dwapb_gpio.c @@ -5,21 +5,15 @@ * DesignWare APB GPIO driver */ -#include <common.h> -#include <log.h> -#include <malloc.h> -#include <asm/arch/gpio.h> #include <asm/gpio.h> #include <asm/io.h> -#include <dm.h> +#include <dm/device.h> #include <dm/device-internal.h> #include <dm/device_compat.h> #include <dm/devres.h> -#include <dm/lists.h> -#include <dm/root.h> +#include <dm/read.h> #include <errno.h> #include <reset.h> -#include <linux/bitops.h> #define GPIO_SWPORT_DR(p) (0x00 + (p) * 0xc) #define GPIO_SWPORT_DDR(p) (0x04 + (p) * 0xc) diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c index 2c5415c..1c3d187 100644 --- a/drivers/gpio/gpio-aspeed.c +++ b/drivers/gpio/gpio-aspeed.c @@ -11,7 +11,6 @@ #include <asm/gpio.h> #include <config.h> -#include <common.h> #include <clk.h> #include <dm.h> #include <asm/io.h> diff --git a/drivers/gpio/gpio-uclass.c b/drivers/gpio/gpio-uclass.c index 7aece85..4234cd9 100644 --- a/drivers/gpio/gpio-uclass.c +++ b/drivers/gpio/gpio-uclass.c @@ -1143,9 +1143,29 @@ static int gpio_request_tail(int ret, const char *nodename, ret = uclass_get_device_by_ofnode(UCLASS_GPIO, args->node, &desc->dev); if (ret) { +#if CONFIG_IS_ENABLED(MAX77663_GPIO) || CONFIG_IS_ENABLED(PALMAS_GPIO) + struct udevice *pmic; + ret = uclass_get_device_by_ofnode(UCLASS_PMIC, args->node, + &pmic); + if (ret) { + log_debug("%s: PMIC device get failed, err %d\n", + __func__, ret); + goto err; + } + + device_foreach_child(desc->dev, pmic) { + if (device_get_uclass_id(desc->dev) == UCLASS_GPIO) + break; + } + + /* if loop exits without GPIO device return error */ + if (device_get_uclass_id(desc->dev) != UCLASS_GPIO) + goto err; +#else debug("%s: uclass_get_device_by_ofnode failed\n", __func__); goto err; +#endif } } ret = gpio_find_and_xlate(desc, args); diff --git a/drivers/gpio/max77663_gpio.c b/drivers/gpio/max77663_gpio.c new file mode 100644 index 0000000..ecb6047 --- /dev/null +++ b/drivers/gpio/max77663_gpio.c @@ -0,0 +1,178 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <dm.h> +#include <asm/gpio.h> +#include <power/max77663.h> +#include <power/pmic.h> + +#define NUM_ENTRIES 11 /* 8 GPIOs + 3 KEYs */ +#define NUM_GPIOS 8 + +#define MAX77663_CNFG1_GPIO 0x36 +#define GPIO_REG_ADDR(offset) (MAX77663_CNFG1_GPIO + (offset)) + +#define MAX77663_CNFG_GPIO_DIR_MASK BIT(1) +#define MAX77663_CNFG_GPIO_DIR_INPUT BIT(1) +#define MAX77663_CNFG_GPIO_DIR_OUTPUT 0 +#define MAX77663_CNFG_GPIO_INPUT_VAL_MASK BIT(2) +#define MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK BIT(3) +#define MAX77663_CNFG_GPIO_OUTPUT_VAL_HIGH BIT(3) +#define MAX77663_CNFG_GPIO_OUTPUT_VAL_LOW 0 +#define MAX77663_CNFG_IRQ GENMASK(5, 4) + +#define MAX77663_ONOFFSTAT_REG 0x15 +#define EN0 BIT(2) /* KEY 2 */ +#define ACOK BIT(1) /* KEY 1 */ +#define LID BIT(0) /* KEY 0 */ + +static int max77663_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + int ret; + + if (offset >= NUM_GPIOS) + return 0; + + ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset), + MAX77663_CNFG_GPIO_DIR_MASK, + MAX77663_CNFG_GPIO_DIR_INPUT); + if (ret < 0) + log_debug("%s: CNFG_GPIOx dir update failed: %d\n", __func__, ret); + + return ret; +} + +static int max77663_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + u8 val; + int ret; + + if (offset >= NUM_GPIOS) + return -EINVAL; + + val = (value) ? MAX77663_CNFG_GPIO_OUTPUT_VAL_HIGH : + MAX77663_CNFG_GPIO_OUTPUT_VAL_LOW; + + ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset), + MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK, val); + if (ret < 0) { + log_debug("%s: CNFG_GPIOx val update failed: %d\n", __func__, ret); + return ret; + } + + ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset), + MAX77663_CNFG_GPIO_DIR_MASK, + MAX77663_CNFG_GPIO_DIR_OUTPUT); + if (ret < 0) + log_debug("%s: CNFG_GPIOx dir update failed: %d\n", __func__, ret); + + return ret; +} + +static int max77663_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + int ret; + + if (offset >= NUM_GPIOS) { + ret = pmic_reg_read(dev->parent, MAX77663_ONOFFSTAT_REG); + if (ret < 0) { + log_debug("%s: ONOFFSTAT_REG read failed: %d\n", __func__, ret); + return ret; + } + + return !!(ret & BIT(offset - NUM_GPIOS)); + } + + ret = pmic_reg_read(dev->parent, GPIO_REG_ADDR(offset)); + if (ret < 0) { + log_debug("%s: CNFG_GPIOx read failed: %d\n", __func__, ret); + return ret; + } + + if (ret & MAX77663_CNFG_GPIO_DIR_MASK) + return !!(ret & MAX77663_CNFG_GPIO_INPUT_VAL_MASK); + else + return !!(ret & MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK); +} + +static int max77663_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + u8 val; + int ret; + + if (offset >= NUM_GPIOS) + return -EINVAL; + + val = (value) ? MAX77663_CNFG_GPIO_OUTPUT_VAL_HIGH : + MAX77663_CNFG_GPIO_OUTPUT_VAL_LOW; + + ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(offset), + MAX77663_CNFG_GPIO_OUTPUT_VAL_MASK, val); + if (ret < 0) + log_debug("%s: CNFG_GPIO_OUT update failed: %d\n", __func__, ret); + + return ret; +} + +static int max77663_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + int ret; + + if (offset >= NUM_GPIOS) + return GPIOF_INPUT; + + ret = pmic_reg_read(dev->parent, GPIO_REG_ADDR(offset)); + if (ret < 0) { + log_debug("%s: CNFG_GPIOx read failed: %d\n", __func__, ret); + return ret; + } + + if (ret & MAX77663_CNFG_GPIO_DIR_MASK) + return GPIOF_INPUT; + else + return GPIOF_OUTPUT; +} + +static const struct dm_gpio_ops max77663_gpio_ops = { + .direction_input = max77663_gpio_direction_input, + .direction_output = max77663_gpio_direction_output, + .get_value = max77663_gpio_get_value, + .set_value = max77663_gpio_set_value, + .get_function = max77663_gpio_get_function, +}; + +static int max77663_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + int i, ret; + + uc_priv->gpio_count = NUM_ENTRIES; + uc_priv->bank_name = "GPIO"; + + /* + * GPIO interrupts may be left ON after bootloader, hence let's + * pre-initialize hardware to the expected state by disabling all + * the interrupts. + */ + for (i = 0; i < NUM_GPIOS; i++) { + ret = pmic_clrsetbits(dev->parent, GPIO_REG_ADDR(i), + MAX77663_CNFG_IRQ, 0); + if (ret < 0) { + log_debug("%s: failed to disable interrupt: %d\n", __func__, ret); + return ret; + } + } + + return 0; +} + +U_BOOT_DRIVER(max77663_gpio) = { + .name = MAX77663_GPIO_DRIVER, + .id = UCLASS_GPIO, + .probe = max77663_gpio_probe, + .ops = &max77663_gpio_ops, +}; diff --git a/drivers/gpio/palmas_gpio.c b/drivers/gpio/palmas_gpio.c new file mode 100644 index 0000000..1503935 --- /dev/null +++ b/drivers/gpio/palmas_gpio.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Based on mainline Linux palmas GPIO driver + * Copyright(C) 2023 Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <dm.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <power/palmas.h> + +#define NUM_GPIOS 8 + +static int palmas_gpio_set_value(struct udevice *dev, unsigned int offset, + int value) +{ + struct palmas_priv *priv = dev_get_priv(dev->parent); + u32 reg; + int ret; + + reg = (value) ? PALMAS_GPIO_SET_DATA_OUT : PALMAS_GPIO_CLEAR_DATA_OUT; + + ret = dm_i2c_reg_write(priv->chip2, reg, BIT(offset)); + if (ret < 0) + log_debug("%s: Reg 0x%02x write failed, %d\n", __func__, reg, ret); + + return ret; +} + +static int palmas_gpio_get_value(struct udevice *dev, unsigned int offset) +{ + struct palmas_priv *priv = dev_get_priv(dev->parent); + u32 reg; + int ret; + + ret = dm_i2c_reg_read(priv->chip2, PALMAS_GPIO_DATA_DIR); + if (ret < 0) { + log_debug("%s: GPIO_DATA_DIR read failed, %d\n", __func__, ret); + return ret; + } + + if (ret & BIT(offset)) + reg = PALMAS_GPIO_DATA_OUT; + else + reg = PALMAS_GPIO_DATA_IN; + + ret = dm_i2c_reg_read(priv->chip2, reg); + if (ret < 0) { + log_debug("%s: Reg 0x%02x read failed, %d\n", __func__, reg, ret); + return ret; + } + + return !!(ret & BIT(offset)); +} + +static int palmas_gpio_direction_input(struct udevice *dev, unsigned int offset) +{ + struct palmas_priv *priv = dev_get_priv(dev->parent); + int ret; + + ret = dm_i2c_reg_clrset(priv->chip2, PALMAS_GPIO_DATA_DIR, + BIT(offset), 0); + if (ret < 0) + log_debug("%s: GPIO_DATA_DIR val update failed: %d\n", __func__, ret); + + return ret; +} + +static int palmas_gpio_direction_output(struct udevice *dev, unsigned int offset, + int value) +{ + struct palmas_priv *priv = dev_get_priv(dev->parent); + int ret; + + /* Set the initial value */ + palmas_gpio_set_value(dev, offset, value); + + ret = dm_i2c_reg_clrset(priv->chip2, PALMAS_GPIO_DATA_DIR, + BIT(offset), BIT(offset)); + if (ret < 0) + log_debug("%s: GPIO_DATA_DIR val update failed: %d\n", __func__, ret); + + return ret; +} + +static int palmas_gpio_get_function(struct udevice *dev, unsigned int offset) +{ + struct palmas_priv *priv = dev_get_priv(dev->parent); + int ret; + + ret = dm_i2c_reg_read(priv->chip2, PALMAS_GPIO_DATA_DIR); + if (ret < 0) { + log_debug("%s: GPIO_DATA_DIR read failed, %d\n", __func__, ret); + return ret; + } + + if (ret & BIT(offset)) + return GPIOF_OUTPUT; + else + return GPIOF_INPUT; +} + +static const struct dm_gpio_ops palmas_gpio_ops = { + .direction_input = palmas_gpio_direction_input, + .direction_output = palmas_gpio_direction_output, + .get_value = palmas_gpio_get_value, + .set_value = palmas_gpio_set_value, + .get_function = palmas_gpio_get_function, +}; + +static int palmas_gpio_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + uc_priv->gpio_count = NUM_GPIOS; + uc_priv->bank_name = "GPIO"; + + return 0; +} + +static const struct udevice_id palmas_ids[] = { + { .compatible = "ti,palmas-gpio" }, + { } +}; + +U_BOOT_DRIVER(palmas_gpio) = { + .name = PALMAS_GPIO_DRIVER, + .id = UCLASS_GPIO, + .of_match = palmas_ids, + .probe = palmas_gpio_probe, + .ops = &palmas_gpio_ops, +}; diff --git a/drivers/i2c/stm32f7_i2c.c b/drivers/i2c/stm32f7_i2c.c index b6c7178..eaa1d69 100644 --- a/drivers/i2c/stm32f7_i2c.c +++ b/drivers/i2c/stm32f7_i2c.c @@ -20,6 +20,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/printk.h> +#include <linux/time.h> /* STM32 I2C registers */ struct stm32_i2c_regs { @@ -121,8 +122,6 @@ struct stm32_i2c_regs { #define STM32_SCLH_MAX BIT(8) #define STM32_SCLL_MAX BIT(8) -#define STM32_NSEC_PER_SEC 1000000000L - /** * struct stm32_i2c_spec - private i2c specification timing * @rate: I2C bus speed (Hz) @@ -591,7 +590,7 @@ static int stm32_i2c_choose_solution(u32 i2cclk, struct stm32_i2c_timings *s) { struct stm32_i2c_timings *v; - u32 i2cbus = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, + u32 i2cbus = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->speed_freq); u32 clk_error_prev = i2cbus; u32 clk_min, clk_max; @@ -607,8 +606,8 @@ static int stm32_i2c_choose_solution(u32 i2cclk, dnf_delay = setup->dnf * i2cclk; tsync = af_delay_min + dnf_delay + (2 * i2cclk); - clk_max = STM32_NSEC_PER_SEC / specs->rate_min; - clk_min = STM32_NSEC_PER_SEC / specs->rate_max; + clk_max = NSEC_PER_SEC / specs->rate_min; + clk_min = NSEC_PER_SEC / specs->rate_max; /* * Among Prescaler possibilities discovered above figures out SCL Low @@ -686,7 +685,7 @@ static int stm32_i2c_compute_timing(struct stm32_i2c_priv *i2c_priv, const struct stm32_i2c_spec *specs; struct stm32_i2c_timings *v, *_v; struct list_head solutions; - u32 i2cclk = DIV_ROUND_CLOSEST(STM32_NSEC_PER_SEC, setup->clock_src); + u32 i2cclk = DIV_ROUND_CLOSEST(NSEC_PER_SEC, setup->clock_src); int ret; specs = get_specs(setup->speed_freq); diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index dabc1f9..2ba6d9c 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -24,4 +24,20 @@ config APPLE_DART configuration to put the DART into bypass mode such that it can be used transparently by U-Boot. +config QCOM_HYP_SMMU + bool "Qualcomm quirky SMMU support" + depends on IOMMU && ARCH_SNAPDRAGON + help + Enable support for the Qualcomm variant of the Arm System MMU-500. + Qualcomm boards have a non-standard SMMU where some registers are + emulated by the hypervisor. It is initialised early in the boot + process and can't be turned off. + + The main caveat with this hardware is that it doesn't support BYPASS + streams, attempting to configure once will instead wind up with a + FAULT stream, and the device will crash when DMA is attempted. + + Say Y here to enable support for non-boot peripherals like USB by + configuring identity mapped streams for them. + endmenu diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index e3e0900..438cab8 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_IOMMU) += iommu-uclass.o obj-$(CONFIG_APPLE_DART) += apple_dart.o obj-$(CONFIG_SANDBOX) += sandbox_iommu.o +obj-$(CONFIG_QCOM_HYP_SMMU) += qcom-hyp-smmu.o diff --git a/drivers/iommu/iommu-uclass.c b/drivers/iommu/iommu-uclass.c index 72f123d..6babc0e3 100644 --- a/drivers/iommu/iommu-uclass.c +++ b/drivers/iommu/iommu-uclass.c @@ -77,6 +77,7 @@ int dev_iommu_enable(struct udevice *dev) { struct ofnode_phandle_args args; struct udevice *dev_iommu; + const struct iommu_ops *ops; int i, count, ret = 0; count = dev_count_phandle_with_args(dev, "iommus", @@ -98,11 +99,22 @@ int dev_iommu_enable(struct udevice *dev) return ret; } dev->iommu = dev_iommu; + + if (dev->parent && dev->parent->iommu == dev_iommu) + continue; + + ops = device_get_ops(dev->iommu); + if (ops && ops->connect) { + ret = ops->connect(dev); + if (ret) + return ret; + } } - if (CONFIG_IS_ENABLED(PCI) && count < 0 && - device_is_on_pci_bus(dev)) +#if CONFIG_IS_ENABLED(PCI) + if (count < 0 && device_is_on_pci_bus(dev)) return dev_pci_iommu_enable(dev); +#endif return 0; } diff --git a/drivers/iommu/qcom-hyp-smmu.c b/drivers/iommu/qcom-hyp-smmu.c new file mode 100644 index 0000000..8e5cdb5 --- /dev/null +++ b/drivers/iommu/qcom-hyp-smmu.c @@ -0,0 +1,396 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 Linaro Ltd. + * Basic ARM SMMU-500 driver, assuming a pre-initialised SMMU and only IDENTITY domains + * this driver only implements the bare minimum to configure stream mappings for periphals + * used by u-boot on platforms where the SMMU can't be disabled. + */ + +#include <log.h> +#include <cpu_func.h> +#include <dm.h> +#include <iommu.h> +#include <linux/bitfield.h> +#include <linux/list.h> +#include <linux/err.h> +#include <lmb.h> +#include <memalign.h> +#include <asm/io.h> + +#define ARM_SMMU_GR0 0 +#define ARM_SMMU_GR1 1 + +#define ARM_SMMU_GR0_ID0 0x20 +#define ARM_SMMU_ID0_NUMSMRG GENMASK(7, 0) /* Number of stream mapping groups */ +#define ARM_SMMU_GR0_ID1 0x24 +#define ARM_SMMU_ID1_PAGESIZE \ + BIT(31) /* Page shift is 16 bits when set, otherwise 23 */ +#define ARM_SMMU_ID1_NUMPAGENDXB \ + GENMASK(30, 28) /* Number of pages before context banks */ +#define ARM_SMMU_ID1_NUMCB GENMASK(7, 0) /* Number of context banks supported */ + +#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2)) +#define ARM_SMMU_CBAR_TYPE GENMASK(17, 16) +#define ARM_SMMU_CBAR_VMID GENMASK(7, 0) +enum arm_smmu_cbar_type { + CBAR_TYPE_S2_TRANS, + CBAR_TYPE_S1_TRANS_S2_BYPASS, + CBAR_TYPE_S1_TRANS_S2_FAULT, + CBAR_TYPE_S1_TRANS_S2_TRANS, +}; + +#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2)) +#define ARM_SMMU_CBA2R_VA64 BIT(0) + +/* Per-CB system control register */ +#define ARM_SMMU_CB_SCTLR 0x0 +#define ARM_SMMU_SCTLR_CFCFG BIT(7) /* Stall on context fault */ +#define ARM_SMMU_SCTLR_CFIE BIT(6) /* Context fault interrupt enable */ +#define ARM_SMMU_SCTLR_CFRE BIT(5) /* Abort on context fault */ + +/* Translation Table Base, holds address of translation table in memory to be used + * for this context bank. Or 0 for bypass + */ +#define ARM_SMMU_CB_TTBR0 0x20 +#define ARM_SMMU_CB_TTBR1 0x28 +/* Translation Control Register, configured TTBR/TLB behaviour (0 for bypass) */ +#define ARM_SMMU_CB_TCR 0x30 +/* Memory Attribute Indirection, also 0 for bypass */ +#define ARM_SMMU_CB_S1_MAIR0 0x38 +#define ARM_SMMU_CB_S1_MAIR1 0x3c + +#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2)) +#define ARM_SMMU_SMR_VALID BIT(31) +#define ARM_SMMU_SMR_MASK GENMASK(31, 16) // Always 0 for now?? +#define ARM_SMMU_SMR_ID GENMASK(15, 0) + +#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2)) +#define ARM_SMMU_S2CR_PRIVCFG GENMASK(25, 24) + +enum arm_smmu_s2cr_privcfg { + S2CR_PRIVCFG_DEFAULT, + S2CR_PRIVCFG_DIPAN, + S2CR_PRIVCFG_UNPRIV, + S2CR_PRIVCFG_PRIV, +}; + +#define ARM_SMMU_S2CR_TYPE GENMASK(17, 16) + +enum arm_smmu_s2cr_type { + S2CR_TYPE_TRANS, + S2CR_TYPE_BYPASS, + S2CR_TYPE_FAULT, +}; + +#define ARM_SMMU_S2CR_EXIDVALID BIT(10) +#define ARM_SMMU_S2CR_CBNDX GENMASK(7, 0) + +#define VMID_UNUSED 0xff + +struct qcom_smmu_priv { + phys_addr_t base; + struct list_head devices; + struct udevice *dev; + + /* Read-once config */ + int num_cb; + int num_smr; + u32 pgshift; + u32 cb_pg_offset; +}; + +struct mmu_dev { + struct list_head li; + struct udevice *dev; + u16 sid; + u16 cbx; + u16 smr; +}; + +#define page_addr(priv, page) ((priv)->base + ((page) << (priv)->pgshift)) + +#define smmu_readl(priv, page, offset) readl(page_addr(priv, page) + offset) +#define gr0_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR0, offset) +#define gr1_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR1, offset) +#define cbx_readl(priv, cbx, offset) \ + smmu_readl(priv, (priv->cb_pg_offset) + cbx, offset) + +#define smmu_writel(priv, page, offset, value) \ + writel((value), page_addr(priv, page) + offset) +#define gr0_writel(priv, offset, value) \ + smmu_writel(priv, ARM_SMMU_GR0, offset, (value)) +#define gr1_writel(priv, offset, value) \ + smmu_writel(priv, ARM_SMMU_GR1, offset, (value)) +#define cbx_writel(priv, cbx, offset, value) \ + smmu_writel(priv, (priv->cb_pg_offset) + cbx, offset, value) + +#define gr1_setbits(priv, offset, value) \ + gr1_writel(priv, offset, gr1_readl(priv, offset) | (value)) + +static int get_stream_id(struct udevice *dev) +{ + ofnode node = dev_ofnode(dev); + struct ofnode_phandle_args args; + int count = ofnode_parse_phandle_with_args(node, "iommus", + "#iommu-cells", 0, 0, &args); + + if (count < 0 || args.args[0] == 0) { + printf("Error: %s: iommus property not found or wrong number of cells\n", + __func__); + return -EINVAL; + } + + return args.args[0]; // Some mask from bit 16 onward? +} + +static struct mmu_dev *alloc_dev(struct udevice *dev) +{ + struct qcom_smmu_priv *priv = dev_get_priv(dev->iommu); + struct mmu_dev *mmu_dev; + int sid; + + sid = get_stream_id(dev); + debug("%s %s has SID %#x\n", dev->iommu->name, dev->name, sid); + if (sid < 0 || sid > 0xffff) { + printf("\tSMMU: Invalid stream ID for %s\n", dev->name); + return ERR_PTR(-EINVAL); + } + + /* We only support a single SID per device for now */ + list_for_each_entry(mmu_dev, &priv->devices, li) { + if (mmu_dev->sid == sid) + return ERR_PTR(-EEXIST); + } + + mmu_dev = calloc(sizeof(*mmu_dev), 1); + if (!mmu_dev) + return ERR_PTR(-ENOMEM); + + mmu_dev->dev = dev; + mmu_dev->sid = sid; + + list_add_tail(&mmu_dev->li, &priv->devices); + + return mmu_dev; +} + +/* Find and init the first free context bank */ +static int alloc_cb(struct qcom_smmu_priv *priv) +{ + u32 cbar, type, vmid, val; + + for (int i = 0; i < priv->num_cb; i++) { + cbar = gr1_readl(priv, ARM_SMMU_GR1_CBAR(i)); + type = FIELD_GET(ARM_SMMU_CBAR_TYPE, cbar); + vmid = FIELD_GET(ARM_SMMU_CBAR_VMID, cbar); + + /* Check that the context bank is available. We haven't reset the SMMU so + * we just make a best guess. + */ + if (type != CBAR_TYPE_S2_TRANS && + (type != CBAR_TYPE_S1_TRANS_S2_BYPASS || + vmid != VMID_UNUSED)) + continue; + + debug("%s: Found free context bank %d (cbar %#x)\n", + priv->dev->name, i, cbar); + type = CBAR_TYPE_S1_TRANS_S2_BYPASS; + vmid = 0; + cbar &= ~ARM_SMMU_CBAR_TYPE & ~ARM_SMMU_CBAR_VMID; + cbar |= FIELD_PREP(ARM_SMMU_CBAR_TYPE, type) | + FIELD_PREP(ARM_SMMU_CBAR_VMID, vmid); + gr1_writel(priv, ARM_SMMU_GR1_CBAR(i), cbar); + + val = IS_ENABLED(CONFIG_ARM64) == 1 ? ARM_SMMU_CBA2R_VA64 : 0; + gr1_setbits(priv, ARM_SMMU_GR1_CBA2R(i), val); + return i; + } + + return -1; +} + +/* Search for a context bank that is already configured for this stream + * returns the context bank index or -ENOENT + */ +static int find_smr(struct qcom_smmu_priv *priv, u16 stream_id) +{ + u32 val; + int i; + + for (i = 0; i < priv->num_smr; i++) { + val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i)); + if (!(val & ARM_SMMU_SMR_VALID) || + FIELD_GET(ARM_SMMU_SMR_ID, val) != stream_id) + continue; + + return i; + } + + return -ENOENT; +} + +static int configure_smr_s2cr(struct qcom_smmu_priv *priv, struct mmu_dev *mdev) +{ + u32 val; + int i; + + for (i = 0; i < priv->num_smr; i++) { + /* Configure SMR */ + val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i)); + if (val & ARM_SMMU_SMR_VALID) + continue; + + val = mdev->sid | ARM_SMMU_SMR_VALID; + gr0_writel(priv, ARM_SMMU_GR0_SMR(i), val); + + /* + * WARNING: Don't change this to use S2CR_TYPE_BYPASS! + * Some Qualcomm boards have angry hypervisor firmware + * that converts S2CR type BYPASS to type FAULT on write. + * We don't use virtual addressing for these boards in + * u-boot so we can get away with using S2CR_TYPE_TRANS + * instead + */ + val = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_TRANS) | + FIELD_PREP(ARM_SMMU_S2CR_CBNDX, mdev->cbx); + gr0_writel(priv, ARM_SMMU_GR0_S2CR(i), val); + + mdev->smr = i; + break; + } + + /* Make sure our writes went through */ + mb(); + + return 0; +} + +static int qcom_smmu_connect(struct udevice *dev) +{ + struct mmu_dev *mdev; + struct qcom_smmu_priv *priv; + int ret; + + debug("%s: %s -> %s\n", __func__, dev->name, dev->iommu->name); + + priv = dev_get_priv(dev->iommu); + if (WARN_ON(!priv)) + return -EINVAL; + + mdev = alloc_dev(dev); + if (IS_ERR(mdev) && PTR_ERR(mdev) != -EEXIST) { + printf("%s: %s Couldn't create mmu context\n", __func__, + dev->name); + return PTR_ERR(mdev); + } else if (IS_ERR(mdev)) { // -EEXIST + return 0; + } + + if (find_smr(priv, mdev->sid) >= 0) { + debug("Found existing context bank for %s, skipping init\n", + dev->name); + return 0; + } + + ret = alloc_cb(priv); + if (ret < 0 || ret > 0xff) { + printf("Error: %s: failed to allocate context bank for %s\n", + __func__, dev->name); + return 0; + } + mdev->cbx = ret; + + /* Configure context bank registers */ + cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR0, 0x0); + cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR1, 0x0); + cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR0, 0x0); + cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR1, 0x0); + cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_SCTLR, + ARM_SMMU_SCTLR_CFIE | ARM_SMMU_SCTLR_CFRE | + ARM_SMMU_SCTLR_CFCFG); + cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TCR, 0x0); + + /* Ensure that our writes went through */ + mb(); + + configure_smr_s2cr(priv, mdev); + + return 0; +} + +#ifdef DEBUG +static inline void dump_boot_mappings(struct arm_smmu_priv *priv) +{ + u32 val; + int i; + + debug(" SMMU dump boot mappings:\n"); + for (i = 0; i < priv->num_smr; i++) { + val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i)); + if (val & ARM_SMMU_SMR_VALID) + debug("\tSMR %3d: SID: %#lx\n", i, + FIELD_GET(ARM_SMMU_SMR_ID, val)); + } +} +#else +#define dump_boot_mappings(priv) \ + do { \ + } while (0) +#endif + +static int qcom_smmu_probe(struct udevice *dev) +{ + struct qcom_smmu_priv *priv; + u32 val; + + priv = dev_get_priv(dev); + priv->dev = dev; + priv->base = dev_read_addr(dev); + INIT_LIST_HEAD(&priv->devices); + + /* Read SMMU config */ + val = gr0_readl(priv, ARM_SMMU_GR0_ID0); + priv->num_smr = FIELD_GET(ARM_SMMU_ID0_NUMSMRG, val); + + val = gr0_readl(priv, ARM_SMMU_GR0_ID1); + priv->num_cb = FIELD_GET(ARM_SMMU_ID1_NUMCB, val); + priv->pgshift = FIELD_GET(ARM_SMMU_ID1_PAGESIZE, val) ? 16 : 12; + priv->cb_pg_offset = 1 + << (FIELD_GET(ARM_SMMU_ID1_NUMPAGENDXB, val) + 1); + + dump_boot_mappings(priv); + + return 0; +} + +static int qcom_smmu_remove(struct udevice *dev) +{ + (void)dev; + /* + * We should probably try and de-configure things here, + * however I'm yet to find a way to do it without crashing + * and it seems like Linux doesn't care at all anyway. + */ + + return 0; +} + +static struct iommu_ops qcom_smmu_ops = { + .connect = qcom_smmu_connect, +}; + +static const struct udevice_id qcom_smmu500_ids[] = { + { .compatible = "qcom,sdm845-smmu-500" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(qcom_smmu500) = { + .name = "qcom_smmu500", + .id = UCLASS_IOMMU, + .of_match = qcom_smmu500_ids, + .priv_auto = sizeof(struct qcom_smmu_priv), + .ops = &qcom_smmu_ops, + .probe = qcom_smmu_probe, + .remove = qcom_smmu_remove, + .flags = DM_FLAG_OS_PREPARE, +}; diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 996b757..9837960 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -49,6 +49,14 @@ config LED_CORTINA This option enables support for LEDs connected to the Cortina Access CAxxxx SOCs. +config LED_LP5562 + bool "LED Support for LP5562" + depends on LED && DM_I2C + help + This option enables support for LEDs connected to the TI LP5562 + 4 channel I2C LED controller. Driver fully supports blink on the + B/G/R LEDs. White LED can blink, but re-uses the period from blue. + config LED_PWM bool "LED PWM" depends on LED && DM_PWM diff --git a/drivers/led/Makefile b/drivers/led/Makefile index 49ae919..2bcb858 100644 --- a/drivers/led/Makefile +++ b/drivers/led/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_LED_BCM6858) += led_bcm6858.o obj-$(CONFIG_LED_PWM) += led_pwm.o obj-$(CONFIG_$(SPL_)LED_GPIO) += led_gpio.o obj-$(CONFIG_LED_CORTINA) += led_cortina.o +obj-$(CONFIG_LED_LP5562) += led_lp5562.o diff --git a/drivers/led/led-uclass.c b/drivers/led/led-uclass.c index 68ca3c2..a4be56f 100644 --- a/drivers/led/led-uclass.c +++ b/drivers/led/led-uclass.c @@ -11,9 +11,27 @@ #include <errno.h> #include <led.h> #include <dm/device-internal.h> +#include <dm/lists.h> #include <dm/root.h> #include <dm/uclass-internal.h> +int led_bind_generic(struct udevice *parent, const char *driver_name) +{ + struct udevice *dev; + ofnode node; + int ret; + + dev_for_each_subnode(node, parent) { + ret = device_bind_driver_to_node(parent, driver_name, + ofnode_get_name(node), + node, &dev); + if (ret) + return ret; + } + + return 0; +} + int led_get_by_label(const char *label, struct udevice **devp) { struct udevice *dev; @@ -71,8 +89,10 @@ static int led_post_bind(struct udevice *dev) struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev); const char *default_state; - uc_plat->label = dev_read_string(dev, "label"); if (!uc_plat->label) + uc_plat->label = dev_read_string(dev, "label"); + + if (!uc_plat->label && !dev_read_string(dev, "compatible")) uc_plat->label = ofnode_get_name(dev_ofnode(dev)); uc_plat->default_state = LEDST_COUNT; diff --git a/drivers/led/led_gpio.c b/drivers/led/led_gpio.c index fbed151..71421de 100644 --- a/drivers/led/led_gpio.c +++ b/drivers/led/led_gpio.c @@ -11,7 +11,6 @@ #include <log.h> #include <malloc.h> #include <asm/gpio.h> -#include <dm/lists.h> struct led_gpio_priv { struct gpio_desc gpio; @@ -80,19 +79,7 @@ static int led_gpio_remove(struct udevice *dev) static int led_gpio_bind(struct udevice *parent) { - struct udevice *dev; - ofnode node; - int ret; - - dev_for_each_subnode(node, parent) { - ret = device_bind_driver_to_node(parent, "gpio_led", - ofnode_get_name(node), - node, &dev); - if (ret) - return ret; - } - - return 0; + return led_bind_generic(parent, "gpio_led"); } static const struct led_ops gpio_led_ops = { diff --git a/drivers/led/led_lp5562.c b/drivers/led/led_lp5562.c new file mode 100644 index 0000000..431d7e1 --- /dev/null +++ b/drivers/led/led_lp5562.c @@ -0,0 +1,577 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Doug Zobel <douglas.zobel@climate.com> + * + * Driver for TI lp5562 4 channel LED driver. There are only 3 + * engines available for the 4 LEDs, so white and blue LEDs share + * the same engine. This means that the blink period is shared + * between them. Changing the period of blue blink will affect + * the white period (and vice-versa). Blue and white On/Off + * states remain independent (as would PWM brightness if that's + * ever added to the LED core). + */ + +#include <dm.h> +#include <errno.h> +#include <led.h> +#include <i2c.h> +#include <asm/gpio.h> +#include <linux/delay.h> + +#define DEFAULT_CURRENT 100 /* 10 mA */ +#define MIN_BLINK_PERIOD 32 /* ms */ +#define MAX_BLINK_PERIOD 2248 /* ms */ + +/* Register Map */ +#define REG_ENABLE 0x00 +#define REG_OP_MODE 0x01 +#define REG_B_PWM 0x02 +#define REG_G_PWM 0x03 +#define REG_R_PWM 0x04 +#define REG_B_CUR 0x05 +#define REG_G_CUR 0x06 +#define REG_R_CUR 0x07 +#define REG_CONFIG 0x08 +#define REG_ENG1_PC 0x09 +#define REG_ENG2_PC 0x0A +#define REG_ENG3_PC 0x0B +#define REG_STATUS 0x0C +#define REG_RESET 0x0D +#define REG_W_PWM 0x0E +#define REG_W_CUR 0x0F +#define REG_ENG1_MEM_BEGIN 0x10 +#define REG_ENG2_MEM_BEGIN 0x30 +#define REG_ENG3_MEM_BEGIN 0x50 +#define REG_LED_MAP 0x70 + +/* LED Register Values */ +/* 0x00 ENABLE */ +#define REG_ENABLE_CHIP_ENABLE (0x1 << 6) +#define REG_ENABLE_ENG_EXEC_HOLD 0x0 +#define REG_ENABLE_ENG_EXEC_RUN 0x2 +#define REG_ENABLE_ENG_EXEC_MASK 0x3 + +/* 0x01 OP MODE */ +#define REG_OP_MODE_DISABLED 0x0 +#define REG_OP_MODE_LOAD_SRAM 0x1 +#define REG_OP_MODE_RUN 0x2 +#define REG_OP_MODE_MASK 0x3 + +/* 0x02, 0x03, 0x04, 0x0E PWM */ +#define REG_PWM_MIN_VALUE 0 +#define REG_PWM_MAX_VALUE 0xFF + +/* 0x08 CONFIG */ +#define REG_CONFIG_EXT_CLK 0x0 +#define REG_CONFIG_INT_CLK 0x1 +#define REG_CONFIG_AUTO_CLK 0x2 +#define REG_CONFIG_CLK_MASK 0x3 + +/* 0x0D RESET */ +#define REG_RESET_RESET 0xFF + +/* 0x70 LED MAP */ +#define REG_LED_MAP_ENG_MASK 0x03 +#define REG_LED_MAP_W_ENG_SHIFT 6 +#define REG_LED_MAP_R_ENG_SHIFT 4 +#define REG_LED_MAP_G_ENG_SHIFT 2 +#define REG_LED_MAP_B_ENG_SHIFT 0 + +/* Engine program related */ +#define REG_ENGINE_MEM_SIZE 0x20 +#define LED_PGRM_RAMP_INCREMENT_SHIFT 0 +#define LED_PGRM_RAMP_SIGN_SHIFT 7 +#define LED_PGRM_RAMP_STEP_SHIFT 8 +#define LED_PGRM_RAMP_PRESCALE_SHIFT 14 + +struct lp5562_led_wrap_priv { + struct gpio_desc enable_gpio; +}; + +struct lp5562_led_priv { + u8 reg_pwm; + u8 reg_current; + u8 map_shift; + u8 enginenum; +}; + +/* enum values map to LED_MAP (0x70) values */ +enum lp5562_led_ctl_mode { + I2C = 0x0, +#ifdef CONFIG_LED_BLINK + ENGINE1 = 0x1, + ENGINE2 = 0x2, + ENGINE3 = 0x3 +#endif +}; + +/* + * Update a register value + * dev - I2C udevice (parent of led) + * regnum - register number to update + * value - value to write to register + * mask - mask of bits that should be changed + */ +static int lp5562_led_reg_update(struct udevice *dev, int regnum, + u8 value, u8 mask) +{ + int ret; + + if (mask == 0xFF) + ret = dm_i2c_reg_write(dev, regnum, value); + else + ret = dm_i2c_reg_clrset(dev, regnum, mask, value); + + + /* + * Data sheet says "Delay between consecutive I2C writes to + * ENABLE register (00h) need to be longer than 488 μs + * (typical)." and "Delay between consecutive I2C writes to + * OP_MODE register need to be longer than 153 μs (typ)." + * + * The linux driver does usleep_range(500, 600) and + * usleep_range(200, 300), respectively. + */ + switch (regnum) { + case REG_ENABLE: + udelay(600); + break; + case REG_OP_MODE: + udelay(300); + break; + } + + return ret; +} + +#ifdef CONFIG_LED_BLINK +/* + * Program the lp5562 engine + * dev - I2C udevice (parent of led) + * program - array of commands + * size - number of commands in program array (1-16) + * engine - engine number (1-3) + */ +static int lp5562_led_program_engine(struct udevice *dev, u16 *program, + u8 size, u8 engine) +{ + int ret, cmd; + u8 engine_reg = REG_ENG1_MEM_BEGIN + + ((engine - 1) * REG_ENGINE_MEM_SIZE); + u8 shift = (3 - engine) * 2; + __be16 prog_be[16]; + + if (size < 1 || size > 16 || engine < 1 || engine > 3) + return -EINVAL; + + for (cmd = 0; cmd < size; cmd++) + prog_be[cmd] = cpu_to_be16(program[cmd]); + + /* set engine mode to 'disabled' */ + ret = lp5562_led_reg_update(dev, REG_OP_MODE, + REG_OP_MODE_DISABLED << shift, + REG_OP_MODE_MASK << shift); + if (ret != 0) + goto done; + + /* set exec mode to 'hold' */ + ret = lp5562_led_reg_update(dev, REG_ENABLE, + REG_ENABLE_ENG_EXEC_HOLD << shift, + REG_ENABLE_ENG_EXEC_MASK << shift); + if (ret != 0) + goto done; + + /* set engine mode to 'load SRAM' */ + ret = lp5562_led_reg_update(dev, REG_OP_MODE, + REG_OP_MODE_LOAD_SRAM << shift, + REG_OP_MODE_MASK << shift); + if (ret != 0) + goto done; + + /* send the re-ordered program sequence */ + ret = dm_i2c_write(dev, engine_reg, (uchar *)prog_be, sizeof(u16) * size); + if (ret != 0) + goto done; + + /* set engine mode to 'run' */ + ret = lp5562_led_reg_update(dev, REG_OP_MODE, + REG_OP_MODE_RUN << shift, + REG_OP_MODE_MASK << shift); + if (ret != 0) + goto done; + + /* set engine exec to 'run' */ + ret = lp5562_led_reg_update(dev, REG_ENABLE, + REG_ENABLE_ENG_EXEC_RUN << shift, + REG_ENABLE_ENG_EXEC_MASK << shift); + +done: + return ret; +} + +/* + * Get the LED's current control mode (I2C or ENGINE[1-3]) + * dev - led udevice (child udevice) + */ +static enum lp5562_led_ctl_mode lp5562_led_get_control_mode(struct udevice *dev) +{ + struct lp5562_led_priv *priv = dev_get_priv(dev); + u8 data; + enum lp5562_led_ctl_mode mode = I2C; + + if (dm_i2c_read(dev_get_parent(dev), REG_LED_MAP, &data, 1) == 0) + mode = (data & (REG_LED_MAP_ENG_MASK << priv->map_shift)) + >> priv->map_shift; + + return mode; +} +#endif + +/* + * Set the LED's control mode to I2C or ENGINE[1-3] + * dev - led udevice (child udevice) + * mode - mode to change to + */ +static int lp5562_led_set_control_mode(struct udevice *dev, + enum lp5562_led_ctl_mode mode) +{ + struct lp5562_led_priv *priv = dev_get_priv(dev); + + return (lp5562_led_reg_update(dev_get_parent(dev), REG_LED_MAP, + mode << priv->map_shift, + REG_LED_MAP_ENG_MASK << priv->map_shift)); +} + +/* + * Return the LED's PWM value; If LED is in BLINK state, then it is + * under engine control mode which doesn't use this PWM value. + * dev - led udevice (child udevice) + */ +static int lp5562_led_get_pwm(struct udevice *dev) +{ + struct lp5562_led_priv *priv = dev_get_priv(dev); + u8 data; + + if (dm_i2c_read(dev_get_parent(dev), priv->reg_pwm, &data, 1) != 0) + return -EINVAL; + + return data; +} + +/* + * Set the LED's PWM value and configure it to use this (I2C mode). + * dev - led udevice (child udevice) + * value - PWM value (0 - 255) + */ +static int lp5562_led_set_pwm(struct udevice *dev, u8 value) +{ + struct lp5562_led_priv *priv = dev_get_priv(dev); + + if (lp5562_led_reg_update(dev_get_parent(dev), priv->reg_pwm, + value, 0xff) != 0) + return -EINVAL; + + /* set LED to I2C register mode */ + return lp5562_led_set_control_mode(dev, I2C); +} + +/* + * Return the led's current state + * dev - led udevice (child udevice) + * + */ +static enum led_state_t lp5562_led_get_state(struct udevice *dev) +{ + enum led_state_t state = LEDST_ON; + + if (lp5562_led_get_pwm(dev) == REG_PWM_MIN_VALUE) + state = LEDST_OFF; + +#ifdef CONFIG_LED_BLINK + if (lp5562_led_get_control_mode(dev) != I2C) + state = LEDST_BLINK; +#endif + + return state; +} + +/* + * Set the led state + * dev - led udevice (child udevice) + * state - State to set the LED to + */ +static int lp5562_led_set_state(struct udevice *dev, enum led_state_t state) +{ +#ifdef CONFIG_LED_BLINK + struct lp5562_led_priv *priv = dev_get_priv(dev); +#endif + + switch (state) { + case LEDST_OFF: + return lp5562_led_set_pwm(dev, REG_PWM_MIN_VALUE); + case LEDST_ON: + return lp5562_led_set_pwm(dev, REG_PWM_MAX_VALUE); +#ifdef CONFIG_LED_BLINK + case LEDST_BLINK: + return lp5562_led_set_control_mode(dev, priv->enginenum); +#endif + case LEDST_TOGGLE: + if (lp5562_led_get_state(dev) == LEDST_OFF) + return lp5562_led_set_state(dev, LEDST_ON); + else + return lp5562_led_set_state(dev, LEDST_OFF); + break; + default: + return -EINVAL; + } + + return 0; +} + +#ifdef CONFIG_LED_BLINK +/* + * Set the blink period of an LED; note blue and white share the same + * engine so changing the period of one affects the other. + * dev - led udevice (child udevice) + * period_ms - blink period in ms + */ +static int lp5562_led_set_period(struct udevice *dev, int period_ms) +{ + struct lp5562_led_priv *priv = dev_get_priv(dev); + u8 opcode = 0; + u16 program[7]; + u16 wait_time; + + /* Blink is implemented as an engine program. Simple on/off + * for short periods, or fade in/fade out for longer periods: + * + * if (period_ms < 500): + * set PWM to 100% + * pause for period / 2 + * set PWM to 0% + * pause for period / 2 + * goto start + * + * else + * raise PWM 0% -> 50% in 62.7 ms + * raise PWM 50% -> 100% in 62.7 ms + * pause for (period - 4 * 62.7) / 2 + * lower PWM 100% -> 50% in 62.7 ms + * lower PWM 50% -> 0% in 62.7 ms + * pause for (period - 4 * 62.7) / 2 + * goto start + */ + + if (period_ms < MIN_BLINK_PERIOD) + period_ms = MIN_BLINK_PERIOD; + else if (period_ms > MAX_BLINK_PERIOD) + period_ms = MAX_BLINK_PERIOD; + + if (period_ms < 500) { + /* Simple on/off blink */ + wait_time = period_ms / 2; + + /* 1st command is full brightness */ + program[opcode++] = + (1 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + REG_PWM_MAX_VALUE; + + /* 2nd command is wait (period / 2) using 15.6ms steps */ + program[opcode++] = + (1 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (((wait_time * 10) / 156) << LED_PGRM_RAMP_STEP_SHIFT) | + (0 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 3rd command is 0% brightness */ + program[opcode++] = + (1 << LED_PGRM_RAMP_PRESCALE_SHIFT); + + /* 4th command is wait (period / 2) using 15.6ms steps */ + program[opcode++] = + (1 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (((wait_time * 10) / 156) << LED_PGRM_RAMP_STEP_SHIFT) | + (0 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 5th command: repeat */ + program[opcode++] = 0x00; + } else { + /* fade-in / fade-out blink */ + wait_time = ((period_ms - 251) / 2); + + /* ramp up time is 256 * 0.49ms (125.4ms) done in 2 steps */ + /* 1st command is ramp up 1/2 way */ + program[opcode++] = + (0 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (1 << LED_PGRM_RAMP_STEP_SHIFT) | + (127 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 2nd command is ramp up rest of the way */ + program[opcode++] = + (0 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (1 << LED_PGRM_RAMP_STEP_SHIFT) | + (127 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 3rd: wait ((period - 2 * ramp_time) / 2) (15.6ms steps) */ + program[opcode++] = + (1 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (((wait_time * 10) / 156) << LED_PGRM_RAMP_STEP_SHIFT) | + (0 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* ramp down is same as ramp up with sign bit set */ + /* 4th command is ramp down 1/2 way */ + program[opcode++] = + (0 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (1 << LED_PGRM_RAMP_STEP_SHIFT) | + (1 << LED_PGRM_RAMP_SIGN_SHIFT) | + (127 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 5th command is ramp down rest of the way */ + program[opcode++] = + (0 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (1 << LED_PGRM_RAMP_STEP_SHIFT) | + (1 << LED_PGRM_RAMP_SIGN_SHIFT) | + (127 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 6th: wait ((period - 2 * ramp_time) / 2) (15.6ms steps) */ + program[opcode++] = + (1 << LED_PGRM_RAMP_PRESCALE_SHIFT) | + (((wait_time * 10) / 156) << LED_PGRM_RAMP_STEP_SHIFT) | + (0 << LED_PGRM_RAMP_INCREMENT_SHIFT); + + /* 7th command: repeat */ + program[opcode++] = 0x00; + } + + return lp5562_led_program_engine(dev_get_parent(dev), program, + opcode, priv->enginenum); +} +#endif + +static const struct led_ops lp5562_led_ops = { + .get_state = lp5562_led_get_state, + .set_state = lp5562_led_set_state, +#ifdef CONFIG_LED_BLINK + .set_period = lp5562_led_set_period, +#endif +}; + +static int lp5562_led_probe(struct udevice *dev) +{ + struct lp5562_led_priv *priv = dev_get_priv(dev); + u8 current; + int ret = 0; + + /* Child LED nodes */ + switch (dev_read_addr(dev)) { + case 0: + priv->reg_current = REG_R_CUR; + priv->reg_pwm = REG_R_PWM; + priv->map_shift = REG_LED_MAP_R_ENG_SHIFT; + priv->enginenum = 1; + break; + case 1: + priv->reg_current = REG_G_CUR; + priv->reg_pwm = REG_G_PWM; + priv->map_shift = REG_LED_MAP_G_ENG_SHIFT; + priv->enginenum = 2; + break; + case 2: + priv->reg_current = REG_B_CUR; + priv->reg_pwm = REG_B_PWM; + priv->map_shift = REG_LED_MAP_B_ENG_SHIFT; + priv->enginenum = 3; /* shared with white */ + break; + case 3: + priv->reg_current = REG_W_CUR; + priv->map_shift = REG_LED_MAP_W_ENG_SHIFT; + priv->enginenum = 3; /* shared with blue */ + break; + default: + return -EINVAL; + } + + current = dev_read_u8_default(dev, "max-cur", DEFAULT_CURRENT); + + ret = lp5562_led_reg_update(dev_get_parent(dev), priv->reg_current, + current, 0xff); + + return ret; +} + +static int lp5562_led_bind(struct udevice *dev) +{ + struct led_uc_plat *uc_plat = dev_get_uclass_plat(dev); + + /* + * For the child nodes, parse a "chan-name" property, since + * the DT bindings for this device use that instead of + * "label". + */ + uc_plat->label = dev_read_string(dev, "chan-name"); + + return 0; +} + +U_BOOT_DRIVER(lp5562_led) = { + .name = "lp5562-led", + .id = UCLASS_LED, + .bind = lp5562_led_bind, + .probe = lp5562_led_probe, + .priv_auto = sizeof(struct lp5562_led_priv), + .ops = &lp5562_led_ops, +}; + + +static int lp5562_led_wrap_probe(struct udevice *dev) +{ + struct lp5562_led_wrap_priv *priv = dev_get_priv(dev); + u8 clock_mode; + int ret; + + /* Enable gpio if needed */ + if (gpio_request_by_name(dev, "enabled-gpios", 0, + &priv->enable_gpio, GPIOD_IS_OUT) == 0) { + dm_gpio_set_value(&priv->enable_gpio, 1); + udelay(1000); + } + + /* Ensure all registers have default values. */ + ret = lp5562_led_reg_update(dev, REG_RESET, REG_RESET_RESET, 0xff); + if (ret) + return ret; + udelay(10000); + + /* Enable the chip */ + ret = lp5562_led_reg_update(dev, REG_ENABLE, REG_ENABLE_CHIP_ENABLE, 0xff); + if (ret) + return ret; + + /* + * The DT bindings say 0=auto, 1=internal, 2=external, while + * the register[0:1] values are 0=external, 1=internal, + * 2=auto. + */ + clock_mode = dev_read_u8_default(dev, "clock-mode", 0); + ret = lp5562_led_reg_update(dev, REG_CONFIG, 2 - clock_mode, REG_CONFIG_CLK_MASK); + + return ret; +} + +static int lp5562_led_wrap_bind(struct udevice *dev) +{ + return led_bind_generic(dev, "lp5562-led"); +} + +static const struct udevice_id lp5562_led_ids[] = { + { .compatible = "ti,lp5562" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(lp5562_led_wrap) = { + .name = "lp5562-led-wrap", + .id = UCLASS_NOP, + .of_match = lp5562_led_ids, + .bind = lp5562_led_wrap_bind, + .probe = lp5562_led_wrap_probe, + .priv_auto = sizeof(struct lp5562_led_wrap_priv), +}; diff --git a/drivers/led/led_pwm.c b/drivers/led/led_pwm.c index 7c8eae9..ae6de30 100644 --- a/drivers/led/led_pwm.c +++ b/drivers/led/led_pwm.c @@ -9,7 +9,6 @@ #include <errno.h> #include <led.h> #include <malloc.h> -#include <dm/lists.h> #include <pwm.h> #define LEDS_PWM_DRIVER_NAME "led_pwm" @@ -136,18 +135,7 @@ static int led_pwm_of_to_plat(struct udevice *dev) static int led_pwm_bind(struct udevice *parent) { - struct udevice *dev; - ofnode node; - int ret; - - dev_for_each_subnode(node, parent) { - ret = device_bind_driver_to_node(parent, LEDS_PWM_DRIVER_NAME, - ofnode_get_name(node), - node, &dev); - if (ret) - return ret; - } - return 0; + return led_bind_generic(parent, LEDS_PWM_DRIVER_NAME); } static const struct led_ops led_pwm_ops = { diff --git a/drivers/mailbox/zynqmp-ipi.c b/drivers/mailbox/zynqmp-ipi.c index 3e4ec47..eb86847 100644 --- a/drivers/mailbox/zynqmp-ipi.c +++ b/drivers/mailbox/zynqmp-ipi.c @@ -8,9 +8,13 @@ #include <common.h> #include <log.h> #include <asm/io.h> +#include <asm/system.h> #include <dm.h> #include <mailbox-uclass.h> #include <dm/device_compat.h> +#include <dm/lists.h> +#include <dm/of_access.h> +#include <linux/arm-smccc.h> #include <linux/ioport.h> #include <linux/io.h> #include <wait_bit.h> @@ -21,6 +25,43 @@ #define IPI_BIT_MASK_PMU0 0x10000 #define IPI_INT_REG_BASE_APU 0xFF300000 +/* IPI agent ID any */ +#define IPI_ID_ANY 0xFFUL + +/* indicate if ZynqMP IPI mailbox driver uses SMC calls or HVC calls */ +#define USE_SMC 0 + +/* Default IPI SMC function IDs */ +#define SMC_IPI_MAILBOX_OPEN 0x82001000U +#define SMC_IPI_MAILBOX_RELEASE 0x82001001U +#define SMC_IPI_MAILBOX_STATUS_ENQUIRY 0x82001002U +#define SMC_IPI_MAILBOX_NOTIFY 0x82001003U +#define SMC_IPI_MAILBOX_ACK 0x82001004U +#define SMC_IPI_MAILBOX_ENABLE_IRQ 0x82001005U +#define SMC_IPI_MAILBOX_DISABLE_IRQ 0x82001006U + +/* IPI SMC Macros */ + +/* + * Flag to indicate if notification interrupt + * to be disabled. + */ +#define IPI_SMC_ENQUIRY_DIRQ_MASK BIT(0) + +/* + * Flag to indicate if notification interrupt + * to be enabled. + */ +#define IPI_SMC_ACK_EIRQ_MASK BIT(0) + +/* IPI mailbox status */ +#define IPI_MB_STATUS_IDLE 0 +#define IPI_MB_STATUS_SEND_PENDING 1 +#define IPI_MB_STATUS_RECV_PENDING 2 + +#define IPI_MB_CHNL_TX 0 /* IPI mailbox TX channel */ +#define IPI_MB_CHNL_RX 1 /* IPI mailbox RX channel */ + struct ipi_int_regs { u32 trig; /* 0x0 */ u32 obs; /* 0x4 */ @@ -39,8 +80,24 @@ struct zynqmp_ipi { void __iomem *local_res_regs; void __iomem *remote_req_regs; void __iomem *remote_res_regs; + u32 remote_id; + u32 local_id; + bool el3_supported; }; +static int zynqmp_ipi_fw_call(struct zynqmp_ipi *ipi_mbox, + unsigned long a0, unsigned long a3) +{ + struct arm_smccc_res res = {0}; + unsigned long a1, a2; + + a1 = ipi_mbox->local_id; + a2 = ipi_mbox->remote_id; + arm_smccc_smc(a0, a1, a2, a3, 0, 0, 0, 0, &res); + + return (int)res.a0; +} + static int zynqmp_ipi_send(struct mbox_chan *chan, const void *data) { const struct zynqmp_ipi_msg *msg = (struct zynqmp_ipi_msg *)data; @@ -51,6 +108,21 @@ static int zynqmp_ipi_send(struct mbox_chan *chan, const void *data) for (size_t i = 0; i < msg->len; i++) writel(msg->buf[i], &mbx[i]); + /* Use SMC calls for Exception Level less than 3 where TF-A is available */ + if (!IS_ENABLED(CONFIG_SPL_BUILD) && current_el() < 3) { + ret = zynqmp_ipi_fw_call(zynqmp, SMC_IPI_MAILBOX_NOTIFY, 0); + + debug("%s, send %ld bytes\n", __func__, msg->len); + + return ret; + } + + /* Return if EL3 is not supported */ + if (!zynqmp->el3_supported) { + dev_err(chan->dev, "mailbox in EL3 only supported for zynqmp"); + return -EOPNOTSUPP; + } + /* Write trigger interrupt */ writel(IPI_BIT_MASK_PMU0, &ipi_int_apu->trig); @@ -67,29 +139,50 @@ static int zynqmp_ipi_recv(struct mbox_chan *chan, void *data) struct zynqmp_ipi_msg *msg = (struct zynqmp_ipi_msg *)data; struct zynqmp_ipi *zynqmp = dev_get_priv(chan->dev); u32 *mbx = (u32 *)zynqmp->local_res_regs; + int ret = 0; /* * PMU Firmware does not trigger IPI interrupt for API call responses so - * there is no need to check ISR flags + * there is no need to check ISR flags for EL3. */ for (size_t i = 0; i < msg->len; i++) msg->buf[i] = readl(&mbx[i]); + /* Ack to remote if EL is not 3 */ + if (!IS_ENABLED(CONFIG_SPL_BUILD) && current_el() < 3) { + ret = zynqmp_ipi_fw_call(zynqmp, SMC_IPI_MAILBOX_ACK, + IPI_SMC_ACK_EIRQ_MASK); + } + debug("%s, recv %ld bytes\n", __func__, msg->len); - return 0; + return ret; }; -static int zynqmp_ipi_probe(struct udevice *dev) +static int zynqmp_ipi_dest_probe(struct udevice *dev) { struct zynqmp_ipi *zynqmp = dev_get_priv(dev); struct resource res; ofnode node; + int ret; debug("%s(dev=%p)\n", __func__, dev); - /* Get subnode where the regs are defined */ - /* Note IPI mailbox node needs to be the first one in DT */ - node = ofnode_first_subnode(dev_ofnode(dev)); + node = dev_ofnode(dev); + + if (IS_ENABLED(CONFIG_SPL_BUILD) || of_machine_is_compatible("xlnx,zynqmp")) + zynqmp->el3_supported = true; + + ret = dev_read_u32(dev->parent, "xlnx,ipi-id", &zynqmp->local_id); + if (ret) { + dev_err(dev, "can't get local ipi id\n"); + return ret; + } + + ret = ofnode_read_u32(node, "xlnx,ipi-id", &zynqmp->remote_id); + if (ret) { + dev_err(dev, "can't get remote ipi id\n"); + return ret; + } if (ofnode_read_resource_byname(node, "local_request_region", &res)) { dev_err(dev, "No reg property for local_request_region\n"); @@ -97,6 +190,8 @@ static int zynqmp_ipi_probe(struct udevice *dev) }; zynqmp->local_req_regs = devm_ioremap(dev, res.start, (res.start - res.end)); + if (!zynqmp->local_req_regs) + return -EINVAL; if (ofnode_read_resource_byname(node, "local_response_region", &res)) { dev_err(dev, "No reg property for local_response_region\n"); @@ -104,6 +199,8 @@ static int zynqmp_ipi_probe(struct udevice *dev) }; zynqmp->local_res_regs = devm_ioremap(dev, res.start, (res.start - res.end)); + if (!zynqmp->local_res_regs) + return -EINVAL; if (ofnode_read_resource_byname(node, "remote_request_region", &res)) { dev_err(dev, "No reg property for remote_request_region\n"); @@ -111,6 +208,8 @@ static int zynqmp_ipi_probe(struct udevice *dev) }; zynqmp->remote_req_regs = devm_ioremap(dev, res.start, (res.start - res.end)); + if (!zynqmp->remote_req_regs) + return -EINVAL; if (ofnode_read_resource_byname(node, "remote_response_region", &res)) { dev_err(dev, "No reg property for remote_response_region\n"); @@ -118,25 +217,59 @@ static int zynqmp_ipi_probe(struct udevice *dev) }; zynqmp->remote_res_regs = devm_ioremap(dev, res.start, (res.start - res.end)); + if (!zynqmp->remote_res_regs) + return -EINVAL; return 0; }; -static const struct udevice_id zynqmp_ipi_ids[] = { - { .compatible = "xlnx,zynqmp-ipi-mailbox" }, - { } +static int zynqmp_ipi_probe(struct udevice *dev) +{ + struct udevice *cdev; + ofnode cnode; + int ret; + + debug("%s(dev=%p)\n", __func__, dev); + + dev_for_each_subnode(cnode, dev) { + ret = device_bind_driver_to_node(dev, "zynqmp_ipi_dest", + ofnode_get_name(cnode), + cnode, &cdev); + if (ret) + return ret; + } + + return 0; }; -struct mbox_ops zynqmp_ipi_mbox_ops = { +struct mbox_ops zynqmp_ipi_dest_mbox_ops = { .send = zynqmp_ipi_send, .recv = zynqmp_ipi_recv, }; +static const struct udevice_id zynqmp_ipi_dest_ids[] = { + { .compatible = "xlnx,zynqmp-ipi-dest-mailbox" }, + { } +}; + +U_BOOT_DRIVER(zynqmp_ipi_dest) = { + .name = "zynqmp_ipi_dest", + .id = UCLASS_MAILBOX, + .of_match = zynqmp_ipi_dest_ids, + .probe = zynqmp_ipi_dest_probe, + .priv_auto = sizeof(struct zynqmp_ipi), + .ops = &zynqmp_ipi_dest_mbox_ops, +}; + +static const struct udevice_id zynqmp_ipi_ids[] = { + { .compatible = "xlnx,zynqmp-ipi-mailbox" }, + { } +}; + U_BOOT_DRIVER(zynqmp_ipi) = { .name = "zynqmp_ipi", - .id = UCLASS_MAILBOX, + .id = UCLASS_NOP, .of_match = zynqmp_ipi_ids, .probe = zynqmp_ipi_probe, - .priv_auto = sizeof(struct zynqmp_ipi), - .ops = &zynqmp_ipi_mbox_ops, + .flags = DM_FLAG_PROBE_AFTER_BIND, }; diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c index 212bb4f..a722a38 100644 --- a/drivers/memory/stm32-fmc2-ebi.c +++ b/drivers/memory/stm32-fmc2-ebi.c @@ -14,6 +14,7 @@ #include <linux/err.h> #include <linux/iopoll.h> #include <linux/ioport.h> +#include <linux/time.h> /* FMC2 Controller Registers */ #define FMC2_BCR1 0x0 @@ -90,8 +91,6 @@ #define FMC2_BTR_DATLAT_MAX 0xf #define FMC2_PCSCNTR_CSCOUNT_MAX 0xff -#define FMC2_NSEC_PER_SEC 1000000000L - enum stm32_fmc2_ebi_bank { FMC2_EBI1 = 0, FMC2_EBI2, @@ -279,7 +278,7 @@ static u32 stm32_fmc2_ebi_ns_to_clock_cycles(struct stm32_fmc2_ebi *ebi, int cs, u32 setup) { unsigned long hclk = clk_get_rate(&ebi->clk); - unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000); + unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); return DIV_ROUND_UP(setup * 1000, hclkp); } diff --git a/drivers/memory/ti-aemif.c b/drivers/memory/ti-aemif.c index c4bc88c..41325eb 100644 --- a/drivers/memory/ti-aemif.c +++ b/drivers/memory/ti-aemif.c @@ -7,6 +7,7 @@ */ #include <common.h> +#include <asm/arch/hardware.h> #include <asm/ti-common/ti-aemif.h> #define AEMIF_WAITCYCLE_CONFIG (KS2_AEMIF_CNTRL_BASE + 0x4) diff --git a/drivers/misc/gsc.c b/drivers/misc/gsc.c index 65c9c2c..feb02f9 100644 --- a/drivers/misc/gsc.c +++ b/drivers/misc/gsc.c @@ -531,10 +531,10 @@ static int do_gsc(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[] if (!gsc_wd_disable(dev)) return CMD_RET_SUCCESS; } else if (strcasecmp(argv[1], "thermal") == 0) { - char *cmd, *val; + const char *cmd, *val; - cmd = (argc > 2) ? argv[2] : NULL; - val = (argc > 3) ? argv[3] : NULL; + cmd = cmd_arg2(argc, argv); + val = cmd_arg3(argc, argv); if (!gsc_thermal(dev, cmd, val)) return CMD_RET_SUCCESS; } diff --git a/drivers/misc/qfw.c b/drivers/misc/qfw.c index 7c01bf2..e3b6b4c 100644 --- a/drivers/misc/qfw.c +++ b/drivers/misc/qfw.c @@ -7,6 +7,7 @@ #define LOG_CATEGORY UCLASS_QFW #include <common.h> +#include <acpi/acpi_table.h> #include <bootdev.h> #include <bootflow.h> #include <bootmeth.h> diff --git a/drivers/mmc/mtk-sd.c b/drivers/mmc/mtk-sd.c index d21a30c..5a0c61d 100644 --- a/drivers/mmc/mtk-sd.c +++ b/drivers/mmc/mtk-sd.c @@ -1665,7 +1665,7 @@ static int msdc_drv_probe(struct udevice *dev) if (cfg->f_max < cfg->f_min || cfg->f_max > host->src_clk_freq) cfg->f_max = host->src_clk_freq; - cfg->b_max = 1024; + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; cfg->voltages = MMC_VDD_32_33 | MMC_VDD_33_34; host->mmc = &plat->mmc; diff --git a/drivers/mmc/octeontx_hsmmc.h b/drivers/mmc/octeontx_hsmmc.h index 70844b1..9849121 100644 --- a/drivers/mmc/octeontx_hsmmc.h +++ b/drivers/mmc/octeontx_hsmmc.h @@ -32,8 +32,6 @@ */ #define MMC_TIMEOUT_SHORT 20 -#define NSEC_PER_SEC 1000000000L - #define MAX_NO_OF_TAPS 64 #define EXT_CSD_POWER_CLASS 187 /* R/W */ diff --git a/drivers/mmc/tegra_mmc.c b/drivers/mmc/tegra_mmc.c index d507adb..c01fb3d 100644 --- a/drivers/mmc/tegra_mmc.c +++ b/drivers/mmc/tegra_mmc.c @@ -698,7 +698,7 @@ static int tegra_mmc_probe(struct udevice *dev) * (actually 52MHz) */ cfg->f_min = 375000; - cfg->f_max = 48000000; + cfg->f_max = dev_read_u32_default(dev, "max-frequency", 48000000); cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index c638980..c2fc80b 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -31,7 +31,7 @@ obj-$(CONFIG_NVMXIP) += nvmxip/ else ifneq ($(mtd-y),) -obj-$(CONFIG_SPL_MTD_SUPPORT) += mtd.o +obj-$(CONFIG_SPL_MTD) += mtd.o endif obj-$(CONFIG_$(SPL_TPL_)NAND_SUPPORT) += nand/ obj-$(CONFIG_SPL_ONENAND_SUPPORT) += onenand/ diff --git a/drivers/mtd/nand/raw/Kconfig b/drivers/mtd/nand/raw/Kconfig index a13e6f5..bb9994b 100644 --- a/drivers/mtd/nand/raw/Kconfig +++ b/drivers/mtd/nand/raw/Kconfig @@ -447,6 +447,22 @@ config NAND_PXA3XX This enables the driver for the NAND flash device found on PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2). +config NAND_SANDBOX + bool "Support for NAND in sandbox" + depends on SANDBOX + select SYS_NAND_SELF_INIT + select SPL_SYS_NAND_SELF_INIT + select SPL_NAND_INIT + select SYS_NAND_SOFT_ECC + select BCH + select NAND_ECC_BCH + imply CMD_NAND + help + Enable a dummy NAND driver for sandbox. It simulates any number of + arbitrary NAND chips with a RAM buffer. It will also inject errors to + test ECC. At the moment, only 8-bit busses and single-chip devices are + supported. + config NAND_SUNXI bool "Support for NAND on Allwinner SoCs" default ARCH_SUNXI @@ -659,20 +675,13 @@ config SYS_NAND_ONFI_DETECTION And fetching device parameters flashed on device, by parsing ONFI parameter page. -config SYS_NAND_PAGE_COUNT - hex "NAND chip page count" - depends on SPL_NAND_SUPPORT && (NAND_ATMEL || NAND_MXC || \ - SPL_NAND_AM33XX_BCH || SPL_NAND_LOAD || SPL_NAND_SIMPLE || \ - NAND_OMAP_GPMC) - help - Number of pages in the NAND chip. - config SYS_NAND_PAGE_SIZE hex "NAND chip page size" depends on ARCH_SUNXI || NAND_OMAP_GPMC || NAND_LPC32XX_SLC || \ SPL_NAND_SIMPLE || (NAND_MXC && SPL_NAND_SUPPORT) || \ MVEBU_SPL_BOOT_DEVICE_NAND || \ - (NAND_ATMEL && SPL_NAND_SUPPORT) || SPL_GENERATE_ATMEL_PMECC_HEADER + (NAND_ATMEL && SPL_NAND_SUPPORT) || \ + SPL_GENERATE_ATMEL_PMECC_HEADER || NAND_SANDBOX depends on !NAND_MXS && !NAND_DENALI_DT && !NAND_LPC32XX_MLC && !NAND_MT7621 help Number of data bytes in one page for the NAND chip on the diff --git a/drivers/mtd/nand/raw/Makefile b/drivers/mtd/nand/raw/Makefile index add2b4c..ddbba89 100644 --- a/drivers/mtd/nand/raw/Makefile +++ b/drivers/mtd/nand/raw/Makefile @@ -70,6 +70,7 @@ obj-$(CONFIG_NAND_PXA3XX) += pxa3xx_nand.o obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o +obj-$(CONFIG_NAND_SANDBOX) += sand_nand.o obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o obj-$(CONFIG_NAND_MXIC) += mxic_nand.o obj-$(CONFIG_NAND_ZYNQ) += zynq_nand.o diff --git a/drivers/mtd/nand/raw/am335x_spl_bch.c b/drivers/mtd/nand/raw/am335x_spl_bch.c index 6ab3f1f..6831af9 100644 --- a/drivers/mtd/nand/raw/am335x_spl_bch.c +++ b/drivers/mtd/nand/raw/am335x_spl_bch.c @@ -11,6 +11,7 @@ #include <common.h> #include <nand.h> +#include <system-constants.h> #include <asm/io.h> #include <linux/delay.h> #include <linux/mtd/nand_ecc.h> @@ -32,7 +33,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd) { struct nand_chip *this = mtd_to_nand(mtd); - int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; + int page_addr = page + block * SYS_NAND_BLOCK_PAGES; void (*hwctrl)(struct mtd_info *mtd, int cmd, unsigned int ctrl) = this->cmd_ctrl; @@ -217,6 +218,11 @@ void nand_init(void) nand_command(0, 0, 0, NAND_CMD_RESET); } +unsigned int nand_page_size(void) +{ + return nand_to_mtd(&nand_chip)->writesize; +} + /* Unselect after operation */ void nand_deselect(void) { diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index fa962ba..a2151f9 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -64,6 +64,7 @@ #include <linux/mfd/syscon/atmel-smc.h> #include <linux/mtd/rawnand.h> #include <linux/mtd/mtd.h> +#include <linux/time.h> #include <mach/at91_sfr.h> #include <nand.h> #include <regmap.h> @@ -71,8 +72,6 @@ #include "pmecc.h" -#define NSEC_PER_SEC 1000000000L - #define ATMEL_HSMC_NFC_CFG 0x0 #define ATMEL_HSMC_NFC_CFG_SPARESIZE(x) (((x) / 4) << 24) #define ATMEL_HSMC_NFC_CFG_SPARESIZE_MASK GENMASK(30, 24) @@ -352,40 +351,6 @@ static int atmel_nfc_wait(struct atmel_hsmc_nand_controller *nc, bool poll, return ret; } -static void iowrite8_rep(void *addr, const uint8_t *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - writeb(buf[i], addr); -} - -static void ioread8_rep(void *addr, uint8_t *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - buf[i] = readb(addr); -} - -static void ioread16_rep(void *addr, void *buf, int len) -{ - int i; - u16 *p = (u16 *)buf; - - for (i = 0; i < len; i++) - p[i] = readw(addr); -} - -static void iowrite16_rep(void *addr, const void *buf, int len) -{ - int i; - u16 *p = (u16 *)buf; - - for (i = 0; i < len; i++) - writew(p[i], addr); -} - static u8 atmel_nand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd_to_nand(mtd); diff --git a/drivers/mtd/nand/raw/atmel_nand.c b/drivers/mtd/nand/raw/atmel_nand.c index 6b17e74..6d94e7a 100644 --- a/drivers/mtd/nand/raw/atmel_nand.c +++ b/drivers/mtd/nand/raw/atmel_nand.c @@ -12,6 +12,7 @@ #include <common.h> #include <log.h> +#include <system-constants.h> #include <asm/gpio.h> #include <asm/arch/gpio.h> #include <dm/device_compat.h> @@ -1258,7 +1259,7 @@ static struct nand_chip nand_chip; static int nand_command(int block, int page, uint32_t offs, u8 cmd) { struct nand_chip *this = mtd_to_nand(mtd); - int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; + int page_addr = page + block * SYS_NAND_BLOCK_PAGES; void (*hwctrl)(struct mtd_info *mtd, int cmd, unsigned int ctrl) = this->cmd_ctrl; @@ -1359,7 +1360,7 @@ int spl_nand_erase_one(int block, int page) if (nand_chip.select_chip) nand_chip.select_chip(mtd, 0); - page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; + page_addr = page + block * SYS_NAND_BLOCK_PAGES; hwctrl(mtd, NAND_CMD_ERASE1, NAND_CTRL_CLE | NAND_CTRL_CHANGE); /* Row address */ hwctrl(mtd, (page_addr & 0xff), NAND_CTRL_ALE | NAND_CTRL_CHANGE); @@ -1451,6 +1452,11 @@ void nand_init(void) nand_chip.select_chip(mtd, 0); } +unsigned int nand_page_size(void) +{ + return nand_to_mtd(&nand_chip)->writesize; +} + void nand_deselect(void) { if (nand_chip.select_chip) diff --git a/drivers/mtd/nand/raw/denali_spl.c b/drivers/mtd/nand/raw/denali_spl.c index 690279c..165a233 100644 --- a/drivers/mtd/nand/raw/denali_spl.c +++ b/drivers/mtd/nand/raw/denali_spl.c @@ -234,4 +234,9 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) return 0; } +unsigned int nand_page_size(void) +{ + return page_size; +} + void nand_deselect(void) {} diff --git a/drivers/mtd/nand/raw/fsl_ifc_spl.c b/drivers/mtd/nand/raw/fsl_ifc_spl.c index c67065e..69d26f1 100644 --- a/drivers/mtd/nand/raw/fsl_ifc_spl.c +++ b/drivers/mtd/nand/raw/fsl_ifc_spl.c @@ -106,6 +106,8 @@ static inline int bad_block(uchar *marker, int port_size) return __raw_readw((u16 *)marker) != 0xffff; } +static int saved_page_size; + int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) { struct fsl_ifc_fcm *gregs = (void *)CFG_SYS_IFC_ADDR; @@ -150,6 +152,7 @@ int nand_spl_load_image(uint32_t offs, unsigned int uboot_size, void *vdst) if (port_size == 8) bad_marker = 5; } + saved_page_size = page_size; ver = ifc_in32(&gregs->ifc_rev); if (ver >= FSL_IFC_V2_0_0) @@ -302,6 +305,11 @@ void nand_init(void) { } +unsigned int nand_page_size(void) +{ + return saved_page_size; +} + void nand_deselect(void) { } diff --git a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c index ac2e669..f8ae216 100644 --- a/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_nand_mlc.c @@ -765,4 +765,9 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) return 0; } +unsigned int nand_page_size(void) +{ + return BYTES_PER_PAGE; +} + #endif /* CONFIG_SPL_BUILD */ diff --git a/drivers/mtd/nand/raw/mt7621_nand_spl.c b/drivers/mtd/nand/raw/mt7621_nand_spl.c index 114fc8b..a2be9ba 100644 --- a/drivers/mtd/nand/raw/mt7621_nand_spl.c +++ b/drivers/mtd/nand/raw/mt7621_nand_spl.c @@ -203,6 +203,11 @@ unsigned long nand_size(void) return SZ_2G; } +unsigned int nand_page_size(void) +{ + return nfc_dev.nand.mtd.writesize; +} + void nand_deselect(void) { } diff --git a/drivers/mtd/nand/raw/mxc_nand_spl.c b/drivers/mtd/nand/raw/mxc_nand_spl.c index 309e75d..a855c99 100644 --- a/drivers/mtd/nand/raw/mxc_nand_spl.c +++ b/drivers/mtd/nand/raw/mxc_nand_spl.c @@ -13,6 +13,7 @@ #include <common.h> #include <hang.h> #include <nand.h> +#include <system-constants.h> #include <linux/mtd/rawnand.h> #include <asm/arch/imx-regs.h> #include <asm/io.h> @@ -304,13 +305,13 @@ int nand_spl_load_image(uint32_t from, unsigned int size, void *buf) * Check if we have crossed a block boundary, and if so * check for bad block. */ - if (!(page % CONFIG_SYS_NAND_PAGE_COUNT)) { + if (!(page % SYS_NAND_BLOCK_PAGES)) { /* * Yes, new block. See if this block is good. If not, * loop until we find a good block. */ while (is_badblock(page)) { - page = page + CONFIG_SYS_NAND_PAGE_COUNT; + page = page + SYS_NAND_BLOCK_PAGES; /* Check i we've reached the end of flash. */ if (page >= maxpages) return -1; @@ -350,3 +351,8 @@ __used void nand_boot(void) void nand_init(void) {} void nand_deselect(void) {} + +unsigned int nand_page_size(void) +{ + return CONFIG_SYS_NAND_PAGE_SIZE; +} diff --git a/drivers/mtd/nand/raw/mxs_nand.c b/drivers/mtd/nand/raw/mxs_nand.c index 65eab4c8..fd65772 100644 --- a/drivers/mtd/nand/raw/mxs_nand.c +++ b/drivers/mtd/nand/raw/mxs_nand.c @@ -31,6 +31,7 @@ #include <linux/errno.h> #include <linux/mtd/rawnand.h> #include <linux/sizes.h> +#include <linux/time.h> #include <linux/types.h> #include <linux/math64.h> @@ -52,8 +53,6 @@ #endif #define MXS_NAND_BCH_TIMEOUT 10000 -#define USEC_PER_SEC 1000000 -#define NSEC_PER_SEC 1000000000L #define TO_CYCLES(duration, period) DIV_ROUND_UP_ULL(duration, period) diff --git a/drivers/mtd/nand/raw/mxs_nand_spl.c b/drivers/mtd/nand/raw/mxs_nand_spl.c index 3006629..f7d3f02 100644 --- a/drivers/mtd/nand/raw/mxs_nand_spl.c +++ b/drivers/mtd/nand/raw/mxs_nand_spl.c @@ -295,6 +295,11 @@ int nand_default_bbt(struct mtd_info *mtd) return 0; } +unsigned int nand_page_size(void) +{ + return nand_to_mtd(&nand_chip)->writesize; +} + void nand_deselect(void) { } diff --git a/drivers/mtd/nand/raw/nand.c b/drivers/mtd/nand/raw/nand.c index eacd99c..4c18861 100644 --- a/drivers/mtd/nand/raw/nand.c +++ b/drivers/mtd/nand/raw/nand.c @@ -60,13 +60,11 @@ int nand_register(int devnum, struct mtd_info *mtd) sprintf(dev_name[devnum], "nand%d", devnum); mtd->name = dev_name[devnum]; -#ifdef CONFIG_MTD /* * Add MTD device so that we can reference it later * via the mtdcore infrastructure (e.g. ubi). */ add_mtd_device(mtd); -#endif total_nand_size += mtd->size / 1024; @@ -76,6 +74,23 @@ int nand_register(int devnum, struct mtd_info *mtd) return 0; } +void nand_unregister(struct mtd_info *mtd) +{ + int devnum = nand_mtd_to_devnum(mtd); + + if (devnum < 0) + return; + + if (nand_curr_device == devnum) + nand_curr_device = -1; + + total_nand_size -= mtd->size / 1024; + + del_mtd_device(nand_info[devnum]); + + nand_info[devnum] = NULL; +} + #if !CONFIG_IS_ENABLED(SYS_NAND_SELF_INIT) static void nand_init_chip(int i) { @@ -100,6 +115,8 @@ static void nand_init_chip(int i) #endif #ifdef CONFIG_MTD_CONCAT +struct mtd_info *concat_mtd; + static void create_mtd_concat(void) { struct mtd_info *nand_info_list[CONFIG_SYS_MAX_NAND_DEVICE]; @@ -114,28 +131,40 @@ static void create_mtd_concat(void) } } if (nand_devices_found > 1) { - struct mtd_info *mtd; char c_mtd_name[16]; /* * We detected multiple devices. Concatenate them together. */ sprintf(c_mtd_name, "nand%d", nand_devices_found); - mtd = mtd_concat_create(nand_info_list, nand_devices_found, - c_mtd_name); + concat_mtd = mtd_concat_create(nand_info_list, + nand_devices_found, c_mtd_name); - if (mtd == NULL) + if (!concat_mtd) return; - nand_register(nand_devices_found, mtd); + nand_register(nand_devices_found, concat_mtd); } return; } + +static void destroy_mtd_concat(void) +{ + if (!concat_mtd) + return; + + mtd_concat_destroy(concat_mtd); + concat_mtd = NULL; +} #else static void create_mtd_concat(void) { } + +static void destroy_mtd_concat(void) +{ +} #endif unsigned long nand_size(void) @@ -143,10 +172,10 @@ unsigned long nand_size(void) return total_nand_size; } +static int initialized; + void nand_init(void) { - static int initialized; - /* * Avoid initializing NAND Flash multiple times, * otherwise it will calculate a wrong total size. @@ -174,3 +203,22 @@ void nand_init(void) create_mtd_concat(); } + +void nand_reinit(void) +{ + int i; + + destroy_mtd_concat(); + for (i = 0; i < CONFIG_SYS_MAX_NAND_DEVICE; i++) + assert(!nand_info[i]); + + initialized = 0; + nand_init(); +} + +unsigned int nand_page_size(void) +{ + struct mtd_info *mtd = get_nand_dev_by_index(nand_curr_device); + + return mtd ? mtd->writesize : 1; +} diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 6b4adcf..c40a0f2 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -245,39 +245,6 @@ static void nand_write_byte16(struct mtd_info *mtd, uint8_t byte) chip->write_buf(mtd, (uint8_t *)&word, 2); } -static void iowrite8_rep(void *addr, const uint8_t *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - writeb(buf[i], addr); -} -static void ioread8_rep(void *addr, uint8_t *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) - buf[i] = readb(addr); -} - -static void ioread16_rep(void *addr, void *buf, int len) -{ - int i; - u16 *p = (u16 *) buf; - - for (i = 0; i < len; i++) - p[i] = readw(addr); -} - -static void iowrite16_rep(void *addr, void *buf, int len) -{ - int i; - u16 *p = (u16 *) buf; - - for (i = 0; i < len; i++) - writew(p[i], addr); -} - /** * nand_write_buf - [DEFAULT] write buffer to chip * @mtd: MTD device structure @@ -4462,17 +4429,14 @@ ident_done: else if (chip->jedec_version) pr_info("%s %s\n", manufacturer_desc->name, chip->jedec_params.model); - else + else if (manufacturer_desc) pr_info("%s %s\n", manufacturer_desc->name, type->name); #else if (chip->jedec_version) pr_info("%s %s\n", manufacturer_desc->name, chip->jedec_params.model); - else + else if (manufacturer_desc) pr_info("%s %s\n", manufacturer_desc->name, type->name); - - pr_info("%s %s\n", manufacturer_desc->name, - type->name); #endif pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n", diff --git a/drivers/mtd/nand/raw/nand_spl_loaders.c b/drivers/mtd/nand/raw/nand_spl_loaders.c index 156b44d..db4213e 100644 --- a/drivers/mtd/nand/raw/nand_spl_loaders.c +++ b/drivers/mtd/nand/raw/nand_spl_loaders.c @@ -12,8 +12,11 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dst) while (block <= lastblock) { if (!nand_is_bad_block(block)) { /* Skip bad blocks */ - while (page < CONFIG_SYS_NAND_PAGE_COUNT) { + while (size && page < SYS_NAND_BLOCK_PAGES) { nand_read_page(block, page, dst); + + size -= min(size, CONFIG_SYS_NAND_PAGE_SIZE - + page_offset); /* * When offs is not aligned to page address the * extra offset is copied to dst as well. Copy diff --git a/drivers/mtd/nand/raw/nand_spl_simple.c b/drivers/mtd/nand/raw/nand_spl_simple.c index 2f3af9e..80d6e0e 100644 --- a/drivers/mtd/nand/raw/nand_spl_simple.c +++ b/drivers/mtd/nand/raw/nand_spl_simple.c @@ -6,6 +6,7 @@ #include <common.h> #include <nand.h> +#include <system-constants.h> #include <asm/io.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/rawnand.h> @@ -27,7 +28,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd) { struct nand_chip *this = mtd_to_nand(mtd); - int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; + int page_addr = page + block * SYS_NAND_BLOCK_PAGES; while (!this->dev_ready(mtd)) ; @@ -59,7 +60,7 @@ static int nand_command(int block, int page, uint32_t offs, u8 cmd) { struct nand_chip *this = mtd_to_nand(mtd); - int page_addr = page + block * CONFIG_SYS_NAND_PAGE_COUNT; + int page_addr = page + block * SYS_NAND_BLOCK_PAGES; void (*hwctrl)(struct mtd_info *mtd, int cmd, unsigned int ctrl) = this->cmd_ctrl; @@ -226,6 +227,11 @@ void nand_init(void) nand_chip.select_chip(mtd, 0); } +unsigned int nand_page_size(void) +{ + return nand_to_mtd(&nand_chip)->writesize; +} + /* Unselect after operation */ void nand_deselect(void) { diff --git a/drivers/mtd/nand/raw/octeontx_nand.c b/drivers/mtd/nand/raw/octeontx_nand.c index 65a03d2..3b20685 100644 --- a/drivers/mtd/nand/raw/octeontx_nand.c +++ b/drivers/mtd/nand/raw/octeontx_nand.c @@ -24,6 +24,7 @@ #include <linux/mtd/nand_bch.h> #include <linux/mtd/nand_ecc.h> #include <linux/mtd/rawnand.h> +#include <linux/time.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/types.h> @@ -291,7 +292,6 @@ union ndf_cmd { #define OCTEONTX_NAND_DRIVER_NAME "octeontx_nand" #define NDF_TIMEOUT 1000 /** Timeout in ms */ -#define USEC_PER_SEC 1000000 /** Linux compatibility */ #ifndef NAND_MAX_CHIPS # define NAND_MAX_CHIPS 8 /** Linux compatibility */ #endif diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 1a5ed0d..0e25bd5 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -6,6 +6,7 @@ #include <common.h> #include <log.h> +#include <system-constants.h> #include <asm/io.h> #include <dm/uclass.h> #include <linux/errno.h> @@ -1298,7 +1299,7 @@ static int nand_is_bad_block(int block) static int nand_read_page(int block, int page, uchar *dst) { - int page_addr = block * CONFIG_SYS_NAND_PAGE_COUNT + page; + int page_addr = block * SYS_NAND_BLOCK_PAGES + page; loff_t ofs = page_addr * CONFIG_SYS_NAND_PAGE_SIZE; int ret; size_t len = CONFIG_SYS_NAND_PAGE_SIZE; diff --git a/drivers/mtd/nand/raw/sand_nand.c b/drivers/mtd/nand/raw/sand_nand.c new file mode 100644 index 0000000..229d7b5 --- /dev/null +++ b/drivers/mtd/nand/raw/sand_nand.c @@ -0,0 +1,707 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) Sean Anderson <seanga2@gmail.com> + */ + +#define LOG_CATEGORY UCLASS_MTD +#include <errno.h> +#include <hexdump.h> +#include <log.h> +#include <nand.h> +#include <os.h> +#include <rand.h> +#include <spl.h> +#include <system-constants.h> +#include <dm/device_compat.h> +#include <dm/read.h> +#include <dm/uclass.h> +#include <asm/bitops.h> +#include <linux/bitmap.h> +#include <linux/mtd/rawnand.h> +#include <linux/sizes.h> + +enum sand_nand_state { + STATE_READY, + STATE_IDLE, + STATE_READ, + STATE_READ_ID, + STATE_READ_ONFI, + STATE_PARAM_ONFI, + STATE_STATUS, + STATE_PROG, + STATE_ERASE, +}; + +static const char *const state_name[] = { + [STATE_READY] = "READY", + [STATE_IDLE] = "IDLE", + [STATE_READ] = "READ", + [STATE_READ_ID] = "READ_ID", + [STATE_READ_ONFI] = "READ_ONFI", + [STATE_PARAM_ONFI] = "PARAM_ONFI", + [STATE_STATUS] = "STATUS", + [STATE_PROG] = "PROG", + [STATE_ERASE] = "ERASE", +}; + +/** + * struct sand_nand_chip - Per-device private data + * @nand: The nand chip + * @node: The next device in this controller + * @programmed: Bitmap of whether sectors are programmed + * @id: ID to report for NAND_CMD_READID + * @id_len: Length of @id + * @onfi: Three copies of ONFI parameter page + * @status: Status to report for NAND_CMD_STATUS + * @chunksize: Size of one "chunk" (page + oob) in bytes + * @pageize: Size of one page in bytes + * @pages: Total number of pages + * @pages_per_erase: Number of pages per eraseblock + * @err_count: Number of errors to inject per @err_step_bits of data + * @err_step_bits: Number of data bits per error "step" + * @err_steps: Number of err steps in a page + * @cs: Chip select for this device + * @state: Current state of the device + * @column: Column of the most-recent command + * @page_addr: Page address of the most-recent command + * @fd: File descriptor for the backing data + * @fd_page_addr: Page address that @fd is seek'd to + * @selected: Whether this device is selected + * @tmp: "Cache" buffer used to store transferred data before committing it + * @tmp_dirty: Whether @tmp is dirty (modified) or clean (all ones) + * + * Data is stored with the OOB area in-line. For example, with 512-byte pages + * and and 16-byte OOB areas, the first page would start at offset 0, the second + * at offset 528, the third at offset 1056, and so on + */ +struct sand_nand_chip { + struct nand_chip nand; + struct list_head node; + long *programmed; + const u8 *id; + u32 chunksize, pagesize, pages, pages_per_erase; + u32 err_count, err_step_bits, err_steps, ecc_bits; + unsigned int cs; + enum sand_nand_state state; + int column, page_addr, fd, fd_page_addr; + bool selected, tmp_dirty; + u8 status; + u8 id_len; + u8 tmp[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE]; + u8 onfi[sizeof(struct nand_onfi_params) * 3]; +}; + +#define SAND_DEBUG(chip, fmt, ...) \ + dev_dbg((chip)->nand.mtd.dev, "%u (%s): " fmt, (chip)->cs, \ + state_name[(chip)->state], ##__VA_ARGS__) + +static inline void to_state(struct sand_nand_chip *chip, + enum sand_nand_state new_state) +{ + if (new_state != chip->state) + SAND_DEBUG(chip, "to state %s\n", state_name[new_state]); + chip->state = new_state; +} + +static inline struct sand_nand_chip *to_sand_nand(struct nand_chip *nand) +{ + return container_of(nand, struct sand_nand_chip, nand); +} + +struct sand_nand_priv { + struct list_head chips; +}; + +static int sand_nand_dev_ready(struct mtd_info *mtd) +{ + return 1; +} + +static int sand_nand_wait(struct mtd_info *mtd, struct nand_chip *chip) +{ + u8 status; + + return nand_status_op(chip, &status) ?: status; +} + +static int sand_nand_seek(struct sand_nand_chip *chip) +{ + if (chip->fd_page_addr == chip->page_addr) + return 0; + + if (os_lseek(chip->fd, (off_t)chip->page_addr * chip->chunksize, + OS_SEEK_SET) < 0) { + SAND_DEBUG(chip, "could not seek: %d\n", errno); + return -EIO; + } + + chip->fd_page_addr = chip->page_addr; + return 0; +} + +static void sand_nand_inject_error(struct sand_nand_chip *chip, + unsigned int step, unsigned int pos) +{ + int byte, index; + + if (pos < chip->err_step_bits) { + __change_bit(step * chip->err_step_bits + pos, chip->tmp); + return; + } + + /* + * Only ECC bytes are covered in the OOB area, so + * pretend that those are the only bytes which can have + * errors. + */ + byte = (pos - chip->err_step_bits + step * chip->ecc_bits) / 8; + index = chip->nand.ecc.layout->eccpos[byte]; + /* Avoid endianness issues by working with bytes */ + chip->tmp[chip->pagesize + index] ^= BIT(pos & 0x7); +} + +static int sand_nand_read(struct sand_nand_chip *chip) +{ + unsigned int i, stop = 0; + + if (chip->column == chip->pagesize) + stop = chip->err_step_bits; + + if (test_bit(chip->page_addr, chip->programmed)) { + if (sand_nand_seek(chip)) + return -EIO; + + if (os_read(chip->fd, chip->tmp, chip->chunksize) != + chip->chunksize) { + SAND_DEBUG(chip, "could not read: %d\n", errno); + return -EIO; + } + chip->fd_page_addr++; + } else if (chip->tmp_dirty) { + memset(chip->tmp + chip->column, 0xff, + chip->chunksize - chip->column); + } + + /* + * Inject some errors; this is Method A from "An Efficient Algorithm for + * Sequential Random Sampling" (Vitter 87). This is still slow when + * generating a lot (dozens) of ECC errors. + * + * To avoid generating too many errors in any one ECC step, we separate + * our error generation by ECC step. + */ + chip->tmp_dirty = true; + for (i = 0; i < chip->err_steps; i++) { + u32 bit_errors = chip->err_count; + unsigned int j = chip->err_step_bits + chip->ecc_bits; + + while (bit_errors) { + unsigned int u = rand(); + float quot = 1ULL << 32; + + do { + quot *= j - bit_errors; + quot /= j; + j--; + + if (j < stop) + goto next; + } while (u < quot); + + sand_nand_inject_error(chip, i, j); + bit_errors--; + } +next: + ; + } + + return 0; +} + +static void sand_nand_command(struct mtd_info *mtd, unsigned int command, + int column, int page_addr) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sand_nand_chip *chip = to_sand_nand(nand); + enum sand_nand_state new_state = chip->state; + + SAND_DEBUG(chip, "command=%02x column=%d page_addr=%d\n", command, + column, page_addr); + + if (!chip->selected) + return; + + switch (chip->state) { + case STATE_READY: + if (command == NAND_CMD_RESET) + goto reset; + break; + case STATE_PROG: + new_state = STATE_IDLE; + if (command != NAND_CMD_PAGEPROG || + test_and_set_bit(chip->page_addr, chip->programmed)) { + chip->status |= NAND_STATUS_FAIL; + break; + } + + if (sand_nand_seek(chip)) { + chip->status |= NAND_STATUS_FAIL; + break; + } + + if (os_write(chip->fd, chip->tmp, chip->chunksize) != + chip->chunksize) { + SAND_DEBUG(chip, "could not write: %d\n", errno); + chip->status |= NAND_STATUS_FAIL; + break; + } + + chip->fd_page_addr++; + break; + case STATE_ERASE: + new_state = STATE_IDLE; + if (command != NAND_CMD_ERASE2) { + chip->status |= NAND_STATUS_FAIL; + break; + } + + if (chip->page_addr < 0 || + chip->page_addr >= chip->pages || + chip->page_addr % chip->pages_per_erase) + chip->status |= NAND_STATUS_FAIL; + else + bitmap_clear(chip->programmed, chip->page_addr, + chip->pages_per_erase); + break; + default: + chip->column = column; + chip->page_addr = page_addr; + switch (command) { + case NAND_CMD_READOOB: + if (column >= 0) + chip->column += chip->pagesize; + fallthrough; + case NAND_CMD_READ0: + new_state = STATE_IDLE; + if (page_addr < 0 || page_addr >= chip->pages) + break; + + if (chip->column < 0 || chip->column >= chip->chunksize) + break; + + if (sand_nand_read(chip)) + break; + + chip->page_addr = page_addr; + new_state = STATE_READ; + break; + case NAND_CMD_ERASE1: + new_state = STATE_ERASE; + chip->status = ~NAND_STATUS_FAIL; + break; + case NAND_CMD_STATUS: + new_state = STATE_STATUS; + chip->column = 0; + break; + case NAND_CMD_SEQIN: + new_state = STATE_PROG; + chip->status = ~NAND_STATUS_FAIL; + if (page_addr < 0 || page_addr >= chip->pages || + chip->column < 0 || + chip->column >= chip->chunksize) { + chip->status |= NAND_STATUS_FAIL; + } else if (chip->tmp_dirty) { + memset(chip->tmp, 0xff, chip->chunksize); + chip->tmp_dirty = false; + } + break; + case NAND_CMD_READID: + if (chip->onfi[0] && column == 0x20) + new_state = STATE_READ_ONFI; + else + new_state = STATE_READ_ID; + chip->column = 0; + break; + case NAND_CMD_PARAM: + if (chip->onfi[0] && !column) + new_state = STATE_PARAM_ONFI; + else + new_state = STATE_IDLE; + break; + case NAND_CMD_RESET: +reset: + new_state = STATE_IDLE; + chip->column = -1; + chip->page_addr = -1; + chip->status = ~NAND_STATUS_FAIL; + break; + default: + new_state = STATE_IDLE; + SAND_DEBUG(chip, "Unsupported command %02x\n", command); + } + } + + to_state(chip, new_state); +} + +static void sand_nand_select_chip(struct mtd_info *mtd, int n) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sand_nand_chip *chip = to_sand_nand(nand); + + chip->selected = !n; +} + +static void sand_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sand_nand_chip *chip = to_sand_nand(nand); + unsigned int to_copy; + int src_len = 0; + const u8 *src = NULL; + + if (!chip->selected) + goto copy; + + switch (chip->state) { + case STATE_READ: + src = chip->tmp; + src_len = chip->chunksize; + break; + case STATE_READ_ID: + src = chip->id; + src_len = chip->id_len; + break; + case STATE_READ_ONFI: + src = "ONFI"; + src_len = 4; + break; + case STATE_PARAM_ONFI: + src = chip->onfi; + src_len = sizeof(chip->onfi); + break; + case STATE_STATUS: + src = &chip->status; + src_len = 1; + break; + default: + break; + } + +copy: + if (chip->column >= 0) + to_copy = max(min(len, src_len - chip->column), 0); + else + to_copy = 0; + memcpy(buf, src + chip->column, to_copy); + memset(buf + to_copy, 0xff, len - to_copy); + chip->column += to_copy; + + if (len == 1) { + SAND_DEBUG(chip, "read [ %02x ]\n", buf[0]); + } else if (src_len) { + SAND_DEBUG(chip, "read %d bytes\n", len); +#ifdef VERBOSE_DEBUG + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); +#endif + } + + if (src_len && chip->column == src_len) + to_state(chip, STATE_IDLE); +} + +static u8 sand_nand_read_byte(struct mtd_info *mtd) +{ + u8 ret; + + sand_nand_read_buf(mtd, &ret, 1); + return ret; +} + +static u16 sand_nand_read_word(struct mtd_info *mtd) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sand_nand_chip *chip = to_sand_nand(nand); + + SAND_DEBUG(chip, "16-bit access unsupported\n"); + return sand_nand_read_byte(mtd) | 0xff00; +} + +static void sand_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len) +{ + struct nand_chip *nand = mtd_to_nand(mtd); + struct sand_nand_chip *chip = to_sand_nand(nand); + + SAND_DEBUG(chip, "write %d bytes\n", len); +#ifdef VERBOSE_DEBUG + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len); +#endif + + if (chip->state != STATE_PROG || chip->status & NAND_STATUS_FAIL) + return; + + chip->tmp_dirty = true; + len = min((unsigned int)len, chip->chunksize - chip->column); + memcpy(chip->tmp + chip->column, buf, len); + chip->column += len; +} + +static struct nand_chip *nand_chip; + +int sand_nand_remove(struct udevice *dev) +{ + struct sand_nand_priv *priv = dev_get_priv(dev); + struct sand_nand_chip *chip; + + list_for_each_entry(chip, &priv->chips, node) { + struct nand_chip *nand = &chip->nand; + + if (nand_chip == nand) + nand_chip = NULL; + + nand_unregister(nand_to_mtd(nand)); + free(chip->programmed); + os_close(chip->fd); + free(chip); + } + + return 0; +} + +static int sand_nand_probe(struct udevice *dev) +{ + struct sand_nand_priv *priv = dev_get_priv(dev); + struct sand_nand_chip *chip; + int ret, devnum = 0; + ofnode np; + + INIT_LIST_HEAD(&priv->chips); + + dev_for_each_subnode(np, dev) { + struct nand_chip *nand; + struct mtd_info *mtd; + u32 erasesize, oobsize, pagesize, pages; + u32 err_count, err_step_size; + off_t expected_size; + char filename[30]; + fdt_addr_t cs; + const u8 *id, *onfi; + int id_len, onfi_len; + + cs = ofnode_get_addr_size_index_notrans(np, 0, NULL); + if (cs == FDT_ADDR_T_NONE) { + dev_dbg(dev, "Invalid cs for chip %s\n", + ofnode_get_name(np)); + ret = -ENOENT; + goto err; + } + + id = ofnode_read_prop(np, "sandbox,id", &id_len); + if (!id) { + dev_dbg(dev, "No sandbox,id property for chip %s\n", + ofnode_get_name(np)); + ret = -EINVAL; + goto err; + } + + onfi = ofnode_read_prop(np, "sandbox,onfi", &onfi_len); + if (onfi && onfi_len != sizeof(struct nand_onfi_params)) { + dev_dbg(dev, "Invalid length %d for onfi params\n", + onfi_len); + ret = -EINVAL; + goto err; + } + + ret = ofnode_read_u32(np, "sandbox,erasesize", &erasesize); + if (ret) { + dev_dbg(dev, "No sandbox,erasesize property for chip %s", + ofnode_get_name(np)); + goto err; + } + + ret = ofnode_read_u32(np, "sandbox,oobsize", &oobsize); + if (ret) { + dev_dbg(dev, "No sandbox,oobsize property for chip %s", + ofnode_get_name(np)); + goto err; + } + + ret = ofnode_read_u32(np, "sandbox,pagesize", &pagesize); + if (ret) { + dev_dbg(dev, "No sandbox,pagesize property for chip %s", + ofnode_get_name(np)); + goto err; + } + + ret = ofnode_read_u32(np, "sandbox,pages", &pages); + if (ret) { + dev_dbg(dev, "No sandbox,pages property for chip %s", + ofnode_get_name(np)); + goto err; + } + + ret = ofnode_read_u32(np, "sandbox,err-count", &err_count); + if (ret) { + dev_dbg(dev, + "No sandbox,err-count property for chip %s", + ofnode_get_name(np)); + goto err; + } + + ret = ofnode_read_u32(np, "sandbox,err-step-size", + &err_step_size); + if (ret) { + dev_dbg(dev, + "No sandbox,err-step-size property for chip %s", + ofnode_get_name(np)); + goto err; + } + + chip = calloc(sizeof(*chip), 1); + if (!chip) { + ret = -ENOMEM; + goto err; + } + + chip->cs = cs; + chip->id = id; + chip->id_len = id_len; + chip->chunksize = pagesize + oobsize; + chip->pagesize = pagesize; + chip->pages = pages; + chip->pages_per_erase = erasesize / pagesize; + memset(chip->tmp, 0xff, chip->chunksize); + + chip->err_count = err_count; + chip->err_step_bits = err_step_size * 8; + chip->err_steps = pagesize / err_step_size; + + expected_size = (off_t)pages * chip->chunksize; + snprintf(filename, sizeof(filename), + "/tmp/u-boot.nand%d.XXXXXX", devnum); + chip->fd = os_mktemp(filename, expected_size); + if (chip->fd < 0) { + dev_dbg(dev, "Could not create temp file %s\n", + filename); + ret = chip->fd; + goto err_chip; + } + + chip->programmed = calloc(sizeof(long), + BITS_TO_LONGS(pages)); + if (!chip->programmed) { + ret = -ENOMEM; + goto err_fd; + } + + if (onfi) { + memcpy(chip->onfi, onfi, onfi_len); + memcpy(chip->onfi + onfi_len, onfi, onfi_len); + memcpy(chip->onfi + 2 * onfi_len, onfi, onfi_len); + } + + nand = &chip->nand; + nand->options = spl_in_proper() ? 0 : NAND_SKIP_BBTSCAN; + nand->flash_node = np; + nand->dev_ready = sand_nand_dev_ready; + nand->cmdfunc = sand_nand_command; + nand->waitfunc = sand_nand_wait; + nand->select_chip = sand_nand_select_chip; + nand->read_byte = sand_nand_read_byte; + nand->read_word = sand_nand_read_word; + nand->read_buf = sand_nand_read_buf; + nand->write_buf = sand_nand_write_buf; + nand->ecc.options = NAND_ECC_GENERIC_ERASED_CHECK; + + mtd = nand_to_mtd(nand); + mtd->dev = dev; + + ret = nand_scan(mtd, CONFIG_SYS_NAND_MAX_CHIPS); + if (ret) { + dev_dbg(dev, "Could not scan chip %s: %d\n", + ofnode_get_name(np), ret); + goto err_prog; + } + chip->ecc_bits = nand->ecc.layout->eccbytes * 8 / + chip->err_steps; + + ret = nand_register(devnum, mtd); + if (ret) { + dev_dbg(dev, "Could not register nand %d: %d\n", devnum, + ret); + goto err_prog; + } + + if (!nand_chip) + nand_chip = nand; + + list_add_tail(&chip->node, &priv->chips); + devnum++; + continue; + +err_prog: + free(chip->programmed); +err_fd: + os_close(chip->fd); +err_chip: + free(chip); + goto err; + } + + return 0; + +err: + sand_nand_remove(dev); + return ret; +} + +static const struct udevice_id sand_nand_ids[] = { + { .compatible = "sandbox,nand" }, + { } +}; + +U_BOOT_DRIVER(sand_nand) = { + .name = "sand-nand", + .id = UCLASS_MTD, + .of_match = sand_nand_ids, + .probe = sand_nand_probe, + .remove = sand_nand_remove, + .priv_auto = sizeof(struct sand_nand_priv), +}; + +void board_nand_init(void) +{ + struct udevice *dev; + int err; + + err = uclass_get_device_by_driver(UCLASS_MTD, DM_DRIVER_REF(sand_nand), + &dev); + if (err && err != -ENODEV) + log_info("Failed to get sandbox NAND: %d\n", err); +} + +#if IS_ENABLED(CONFIG_SPL_BUILD) && IS_ENABLED(CONFIG_SPL_NAND_INIT) +void nand_deselect(void) +{ + nand_chip->select_chip(nand_to_mtd(nand_chip), -1); +} + +static int nand_is_bad_block(int block) +{ + struct mtd_info *mtd = nand_to_mtd(nand_chip); + + return mtd_block_isbad(mtd, block << mtd->erasesize_shift); +} + +static int nand_read_page(int block, int page, uchar *dst) +{ + struct mtd_info *mtd = nand_to_mtd(nand_chip); + loff_t ofs = ((loff_t)block << mtd->erasesize_shift) + + ((loff_t)page << mtd->writesize_shift); + size_t len = mtd->writesize; + + return nand_read(mtd, ofs, &len, dst); +} + +#include "nand_spl_loaders.c" +#endif /* CONFIG_SPL_NAND_INIT */ diff --git a/drivers/mtd/nand/raw/stm32_fmc2_nand.c b/drivers/mtd/nand/raw/stm32_fmc2_nand.c index 64be648..3528824 100644 --- a/drivers/mtd/nand/raw/stm32_fmc2_nand.c +++ b/drivers/mtd/nand/raw/stm32_fmc2_nand.c @@ -22,6 +22,7 @@ #include <linux/ioport.h> #include <linux/mtd/rawnand.h> #include <linux/printk.h> +#include <linux/time.h> /* Bad block marker length */ #define FMC2_BBM_LEN 2 @@ -127,8 +128,6 @@ #define FMC2_BCHDSR4_EBP7 GENMASK(12, 0) #define FMC2_BCHDSR4_EBP8 GENMASK(28, 16) -#define FMC2_NSEC_PER_SEC 1000000000L - #define FMC2_TIMEOUT_5S 5000000 enum stm32_fmc2_ecc { @@ -603,7 +602,7 @@ static void stm32_fmc2_nfc_calc_timings(struct nand_chip *chip, struct stm32_fmc2_nand *nand = to_fmc2_nand(chip); struct stm32_fmc2_timings *tims = &nand->timings; unsigned long hclk = clk_get_rate(&nfc->clk); - unsigned long hclkp = FMC2_NSEC_PER_SEC / (hclk / 1000); + unsigned long hclkp = NSEC_PER_SEC / (hclk / 1000); unsigned long timing, tar, tclr, thiz, twait; unsigned long tset_mem, tset_att, thold_mem, thold_att; diff --git a/drivers/mtd/nand/raw/sunxi_nand_spl.c b/drivers/mtd/nand/raw/sunxi_nand_spl.c index 6de0b0a..c9b8c78 100644 --- a/drivers/mtd/nand/raw/sunxi_nand_spl.c +++ b/drivers/mtd/nand/raw/sunxi_nand_spl.c @@ -524,9 +524,10 @@ static int nand_read_buffer(struct nfc_config *conf, uint32_t offs, return 0; } +static struct nfc_config conf; + int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest) { - static struct nfc_config conf = { }; int ret; ret = nand_detect_config(&conf, offs, dest); @@ -536,6 +537,11 @@ int nand_spl_load_image(uint32_t offs, unsigned int size, void *dest) return nand_read_buffer(&conf, offs, size, dest); } +unsigned int nand_page_size(void) +{ + return conf.page_size; +} + void nand_deselect(void) { struct sunxi_ccm_reg *const ccm = diff --git a/drivers/mtd/nand/spi/Makefile b/drivers/mtd/nand/spi/Makefile index 3051de4..f172f47 100644 --- a/drivers/mtd/nand/spi/Makefile +++ b/drivers/mtd/nand/spi/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -spinand-objs := core.o gigadevice.o macronix.o micron.o paragon.o toshiba.o winbond.o +spinand-objs := core.o esmt.o gigadevice.o macronix.o micron.o paragon.o +spinand-objs += toshiba.o winbond.o obj-$(CONFIG_MTD_SPI_NAND) += spinand.o diff --git a/drivers/mtd/nand/spi/core.c b/drivers/mtd/nand/spi/core.c index 597b088..8ca3345 100644 --- a/drivers/mtd/nand/spi/core.c +++ b/drivers/mtd/nand/spi/core.c @@ -828,6 +828,7 @@ static const struct spinand_manufacturer *spinand_manufacturers[] = { ¶gon_spinand_manufacturer, &toshiba_spinand_manufacturer, &winbond_spinand_manufacturer, + &esmt_c8_spinand_manufacturer, }; static int spinand_manufacturer_match(struct spinand_device *spinand, diff --git a/drivers/mtd/nand/spi/esmt.c b/drivers/mtd/nand/spi/esmt.c new file mode 100644 index 0000000..7e07b26 --- /dev/null +++ b/drivers/mtd/nand/spi/esmt.c @@ -0,0 +1,137 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Author: + * Chuanhong Guo <gch981213@gmail.com> - the main driver logic + * Martin Kurbanov <mmkurbanov@sberdevices.ru> - OOB layout + */ + +#ifndef __UBOOT__ +#include <linux/device.h> +#include <linux/kernel.h> +#endif +#include <linux/mtd/spinand.h> + +/* ESMT uses GigaDevice 0xc8 JECDEC ID on some SPI NANDs */ +#define SPINAND_MFR_ESMT_C8 0xc8 + +static SPINAND_OP_VARIANTS(read_cache_variants, + SPINAND_PAGE_READ_FROM_CACHE_X4_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_X2_OP(0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(true, 0, 1, NULL, 0), + SPINAND_PAGE_READ_FROM_CACHE_OP(false, 0, 1, NULL, 0)); + +static SPINAND_OP_VARIANTS(write_cache_variants, + SPINAND_PROG_LOAD_X4(true, 0, NULL, 0), + SPINAND_PROG_LOAD(true, 0, NULL, 0)); + +static SPINAND_OP_VARIANTS(update_cache_variants, + SPINAND_PROG_LOAD_X4(false, 0, NULL, 0), + SPINAND_PROG_LOAD(false, 0, NULL, 0)); + +/* + * OOB spare area map (64 bytes) + * + * Bad Block Markers + * filled by HW and kernel Reserved + * | +-----------------------+-----------------------+ + * | | | | + * | | OOB free data Area |non ECC protected | + * | +-------------|-----+-----------------|-----+-----------------|-----+ + * | | | | | | | | + * +-|---|----------+--|-----|--------------+--|-----|--------------+--|-----|--------------+ + * | | | section0 | | | section1 | | | section2 | | | section3 | + * +-v-+-v-+---+----+--v--+--v--+-----+-----+--v--+--v--+-----+-----+--v--+--v--+-----+-----+ + * | | | | | | | | | | | | | | | | | + * |0:1|2:3|4:7|8:15|16:17|18:19|20:23|24:31|32:33|34:35|36:39|40:47|48:49|50:51|52:55|56:63| + * | | | | | | | | | | | | | | | | | + * +---+---+-^-+--^-+-----+-----+--^--+--^--+-----+-----+--^--+--^--+-----+-----+--^--+--^--+ + * | | | | | | | | + * | +----------------|-----+-----------------|-----+-----------------|-----+ + * | ECC Area|(Main + Spare) - filled|by ESMT NAND HW | + * | | | | + * +---------------------+-----------------------+-----------------------+ + * OOB ECC protected Area - not used due to + * partial programming from some filesystems + * (like JFFS2 with cleanmarkers) + */ + +#define ESMT_OOB_SECTION_COUNT 4 +#define ESMT_OOB_SECTION_SIZE(nand) \ + (nanddev_per_page_oobsize(nand) / ESMT_OOB_SECTION_COUNT) +#define ESMT_OOB_FREE_SIZE(nand) \ + (ESMT_OOB_SECTION_SIZE(nand) / 2) +#define ESMT_OOB_ECC_SIZE(nand) \ + (ESMT_OOB_SECTION_SIZE(nand) - ESMT_OOB_FREE_SIZE(nand)) +#define ESMT_OOB_BBM_SIZE 2 + +static int f50l1g41lb_ooblayout_ecc(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + struct nand_device *nand = mtd_to_nanddev(mtd); + + if (section >= ESMT_OOB_SECTION_COUNT) + return -ERANGE; + + region->offset = section * ESMT_OOB_SECTION_SIZE(nand) + + ESMT_OOB_FREE_SIZE(nand); + region->length = ESMT_OOB_ECC_SIZE(nand); + + return 0; +} + +static int f50l1g41lb_ooblayout_free(struct mtd_info *mtd, int section, + struct mtd_oob_region *region) +{ + struct nand_device *nand = mtd_to_nanddev(mtd); + + if (section >= ESMT_OOB_SECTION_COUNT) + return -ERANGE; + + /* + * Reserve space for bad blocks markers (section0) and + * reserved bytes (sections 1-3) + */ + region->offset = section * ESMT_OOB_SECTION_SIZE(nand) + 2; + + /* Use only 2 non-protected ECC bytes per each OOB section */ + region->length = 2; + + return 0; +} + +static const struct mtd_ooblayout_ops f50l1g41lb_ooblayout = { + .ecc = f50l1g41lb_ooblayout_ecc, + .rfree = f50l1g41lb_ooblayout_free, +}; + +static const struct spinand_info esmt_c8_spinand_table[] = { + SPINAND_INFO("F50L1G41LB", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x01), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), + SPINAND_INFO("F50D1G41LB", + SPINAND_ID(SPINAND_READID_METHOD_OPCODE_ADDR, 0x11), + NAND_MEMORG(1, 2048, 64, 64, 1024, 20, 1, 1, 1), + NAND_ECCREQ(1, 512), + SPINAND_INFO_OP_VARIANTS(&read_cache_variants, + &write_cache_variants, + &update_cache_variants), + 0, + SPINAND_ECCINFO(&f50l1g41lb_ooblayout, NULL)), +}; + +static const struct spinand_manufacturer_ops esmt_spinand_manuf_ops = { +}; + +const struct spinand_manufacturer esmt_c8_spinand_manufacturer = { + .id = SPINAND_MFR_ESMT_C8, + .name = "ESMT", + .chips = esmt_c8_spinand_table, + .nchips = ARRAY_SIZE(esmt_c8_spinand_table), + .ops = &esmt_spinand_manuf_ops, +}; diff --git a/drivers/mtd/onenand/onenand_uboot.c b/drivers/mtd/onenand/onenand_uboot.c index 04791df..ecacabe 100644 --- a/drivers/mtd/onenand/onenand_uboot.c +++ b/drivers/mtd/onenand/onenand_uboot.c @@ -44,14 +44,12 @@ void onenand_init(void) puts("Flex-"); puts("OneNAND: "); -#ifdef CONFIG_MTD /* * Add MTD device so that we can reference it later * via the mtdcore infrastructure (e.g. ubi). */ onenand_mtd.name = dev_name; add_mtd_device(&onenand_mtd); -#endif } print_size(onenand_chip.chipsize, "\n"); } diff --git a/drivers/mtd/spi/Kconfig b/drivers/mtd/spi/Kconfig index abed392..d068b78 100644 --- a/drivers/mtd/spi/Kconfig +++ b/drivers/mtd/spi/Kconfig @@ -176,6 +176,11 @@ config SPI_FLASH_MACRONIX help Add support for various Macronix SPI flash chips (MX25Lxxx) +config SPI_FLASH_SILICONKAISER + bool "Silicon Kaiser SPI flash support" + help + Add support for various Silicon Kaiser SPI flash chips (SK25Lxxx) + config SPI_FLASH_SPANSION bool "Spansion SPI flash support" help diff --git a/drivers/mtd/spi/spi-nor-core.c b/drivers/mtd/spi/spi-nor-core.c index 9a1801b..3f5f3c8 100644 --- a/drivers/mtd/spi/spi-nor-core.c +++ b/drivers/mtd/spi/spi-nor-core.c @@ -2089,6 +2089,36 @@ read_err: return ret; } +/** + * spi_nor_read_sfdp_dma_unsafe() - read Serial Flash Discoverable Parameters. + * @nor: pointer to a 'struct spi_nor' + * @addr: offset in the SFDP area to start reading data from + * @len: number of bytes to read + * @buf: buffer where the SFDP data are copied into + * + * Wrap spi_nor_read_sfdp() using a kmalloc'ed bounce buffer as @buf is now not + * guaranteed to be dma-safe. + * + * Return: -ENOMEM if kmalloc() fails, the return code of spi_nor_read_sfdp() + * otherwise. + */ +static int spi_nor_read_sfdp_dma_unsafe(struct spi_nor *nor, u32 addr, + size_t len, void *buf) +{ + void *dma_safe_buf; + int ret; + + dma_safe_buf = kmalloc(len, GFP_KERNEL); + if (!dma_safe_buf) + return -ENOMEM; + + ret = spi_nor_read_sfdp(nor, addr, len, dma_safe_buf); + memcpy(buf, dma_safe_buf, len); + kfree(dma_safe_buf); + + return ret; +} + /* Fast Read settings. */ static void @@ -2262,7 +2292,7 @@ static int spi_nor_parse_bfpt(struct spi_nor *nor, bfpt_header->length * sizeof(u32)); addr = SFDP_PARAM_HEADER_PTP(bfpt_header); memset(&bfpt, 0, sizeof(bfpt)); - err = spi_nor_read_sfdp(nor, addr, len, &bfpt); + err = spi_nor_read_sfdp_dma_unsafe(nor, addr, len, &bfpt); if (err < 0) return err; @@ -2588,7 +2618,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor, int i, err; /* Get the SFDP header. */ - err = spi_nor_read_sfdp(nor, 0, sizeof(header), &header); + err = spi_nor_read_sfdp_dma_unsafe(nor, 0, sizeof(header), &header); if (err < 0) return err; diff --git a/drivers/mtd/spi/spi-nor-ids.c b/drivers/mtd/spi/spi-nor-ids.c index f86e7ff..8db522f 100644 --- a/drivers/mtd/spi/spi-nor-ids.c +++ b/drivers/mtd/spi/spi-nor-ids.c @@ -200,6 +200,11 @@ const struct flash_info spi_nor_ids[] = { SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES)}, {INFO("gd55lx02g", 0xc8681C, 0, 64 * 1024, 4096, SECT_4K | SPI_NOR_OCTAL_READ | SPI_NOR_4B_OPCODES)}, + { + INFO("gd55lb02ge", 0xc8671c, 0, 64 * 1024, 4096, + SECT_4K | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, #endif #ifdef CONFIG_SPI_FLASH_ISSI /* ISSI */ /* ISSI */ @@ -287,6 +292,10 @@ const struct flash_info spi_nor_ids[] = { { INFO("mx25uw6345g", 0xc28437, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_OCTAL_DTR_READ | SPI_NOR_4B_OPCODES) }, #endif +#ifdef CONFIG_SPI_FLASH_SILICONKAISER + { INFO("sk25lp128", 0x257018, 0, 64 * 1024, 256, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, +#endif + #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */ /* Micron */ { INFO("n25q016a", 0x20bb15, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_QUAD_READ) }, @@ -300,6 +309,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("n25q256a", 0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | USE_FSR) }, { INFO6("mt25qu256a", 0x20bb19, 0x104400, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | USE_FSR) }, { INFO("n25q256ax1", 0x20bb19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ | USE_FSR) }, + { INFO("mt25qu128ab", 0x20bb18, 0, 64 * 1024, 256, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, { INFO6("mt25qu512a", 0x20bb20, 0x104400, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES | USE_FSR) }, @@ -309,6 +319,7 @@ const struct flash_info spi_nor_ids[] = { { INFO("n25q00", 0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { INFO("n25q00a", 0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { INFO("mt25ql01g", 0x21ba20, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, + { INFO6("mt25qu01g", 0x20bb21, 0x104400, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) }, { INFO("mt25qu02g", 0x20bb22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) }, { INFO("mt25ql02g", 0x20ba22, 0, 64 * 1024, 4096, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE | SPI_NOR_4B_OPCODES) }, #ifdef CONFIG_SPI_FLASH_MT35XU @@ -513,6 +524,16 @@ const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) }, + { + INFO("w25q01jvfim", 0xef7021, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, + { + INFO("w25q02jv", 0xef7022, 0, 64 * 1024, 4096, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | + SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB) + }, { INFO("w25q80", 0xef5014, 0, 64 * 1024, 16, SECT_4K) }, { INFO("w25q80bl", 0xef4014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { INFO("w25q16cl", 0xef4015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, @@ -566,6 +587,8 @@ const struct flash_info spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, { INFO("xt25q01g", 0x0b601B, 0, 64 * 1024, 2048, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, + { INFO("xt55q02g", 0x0b601C, 0, 64 * 1024, 4096, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, /* adding these wide voltage QSPI flash parts */ { INFO("xt25w512", 0x0b651A, 0, 64 * 1024, 1024, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_4B_OPCODES) }, diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ebab4d9..b2d7b49 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -471,14 +471,6 @@ config SYS_UNIFY_CACHE depends on MCFFEC bool "Invalidate icache during ethernet operations" -config FSLDMAFEC - bool "ColdFire DMA Ethernet Support" - select PHYLIB - select SYS_DISCOVER_PHY - help - This driver supports the network interface units in the - ColdFire family. - config KS8851_MLL bool "Microchip KS8851-MLL controller driver" help @@ -988,4 +980,11 @@ config MDIO_MUX_MESON_G12A This driver is used for the MDIO mux found on the Amlogic G12A & compatible SoCs. +config MDIO_MUX_MESON_GXL + bool "MDIO MUX for Amlogic Meson GXL SoCs" + depends on DM_MDIO_MUX + help + This driver is used for the MDIO mux found on the Amlogic GXL & compatible + SoCs. + endif # NETDEVICES diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 1ce6fea..6677366 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -37,7 +37,6 @@ obj-$(CONFIG_ETH_SANDBOX_RAW) += sandbox-raw.o obj-$(CONFIG_FEC_MXC) += fec_mxc.o obj-$(CONFIG_FMAN_ENET) += fm/ obj-$(CONFIG_FMAN_ENET) += fsl_mdio.o -obj-$(CONFIG_FSLDMAFEC) += fsl_mcdmafec.o mcfmii.o obj-$(CONFIG_FSL_ENETC) += fsl_enetc.o fsl_enetc_mdio.o obj-$(CONFIG_FSL_LS_MDIO) += fsl_ls_mdio.o obj-$(CONFIG_FSL_MC_ENET) += fsl-mc/ @@ -58,6 +57,7 @@ obj-$(CONFIG_MCFFEC) += mcffec.o mcfmii.o obj-$(CONFIG_MDIO_IPQ4019) += mdio-ipq4019.o obj-$(CONFIG_MDIO_MUX_I2CREG) += mdio_mux_i2creg.o obj-$(CONFIG_MDIO_MUX_MESON_G12A) += mdio_mux_meson_g12a.o +obj-$(CONFIG_MDIO_MUX_MESON_GXL) += mdio_mux_meson_gxl.o obj-$(CONFIG_MDIO_MUX_MMIOREG) += mdio_mux_mmioreg.o obj-$(CONFIG_MDIO_MUX_SANDBOX) += mdio_mux_sandbox.o obj-$(CONFIG_MDIO_SANDBOX) += mdio_sandbox.o diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index a4e3698..e40e399 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1711,6 +1711,10 @@ static const struct udevice_id eqos_ids[] = { .compatible = "nxp,imx8mp-dwmac-eqos", .data = (ulong)&eqos_imx_config }, + { + .compatible = "nxp,imx93-dwmac-eqos", + .data = (ulong)&eqos_imx_config + }, #endif #if IS_ENABLED(CONFIG_DWC_ETH_QOS_ROCKCHIP) { diff --git a/drivers/net/dwc_eth_qos_imx.c b/drivers/net/dwc_eth_qos_imx.c index 60f3f3f..e3f55dd 100644 --- a/drivers/net/dwc_eth_qos_imx.c +++ b/drivers/net/dwc_eth_qos_imx.c @@ -181,6 +181,9 @@ static int eqos_set_tx_clk_speed_imx(struct udevice *dev) ulong rate; int ret; + if (device_is_compatible(dev, "nxp,imx93-dwmac-eqos")) + return 0; + debug("%s(dev=%p):\n", __func__, dev); if (eqos->phy->interface == PHY_INTERFACE_MODE_RMII) diff --git a/drivers/net/fm/fm.c b/drivers/net/fm/fm.c index 7dfa821..a8caa0f 100644 --- a/drivers/net/fm/fm.c +++ b/drivers/net/fm/fm.c @@ -3,7 +3,6 @@ * Copyright 2009-2011 Freescale Semiconductor, Inc. * Dave Liu <daveliu@freescale.com> */ -#include <common.h> #include <env.h> #include <fs_loader.h> #include <image.h> diff --git a/drivers/net/fm/fm.h b/drivers/net/fm/fm.h index a2d5b03..5c45ad5 100644 --- a/drivers/net/fm/fm.h +++ b/drivers/net/fm/fm.h @@ -6,7 +6,6 @@ #ifndef __FM_H__ #define __FM_H__ -#include <common.h> #include <phy.h> #include <fm_eth.h> #include <fsl_fman.h> diff --git a/drivers/net/fsl-mc/dpio/qbman_private.h b/drivers/net/fsl-mc/dpio/qbman_private.h index 53f1300..f9dad17 100644 --- a/drivers/net/fsl-mc/dpio/qbman_private.h +++ b/drivers/net/fsl-mc/dpio/qbman_private.h @@ -4,7 +4,6 @@ */ /* Perform extra checking */ -#include <common.h> #include <errno.h> #include <asm/io.h> #include <linux/bug.h> diff --git a/drivers/net/fsl-mc/dpio/qbman_sys.h b/drivers/net/fsl-mc/dpio/qbman_sys.h index 1c6e489..cac70a1 100644 --- a/drivers/net/fsl-mc/dpio/qbman_sys.h +++ b/drivers/net/fsl-mc/dpio/qbman_sys.h @@ -20,6 +20,7 @@ /* Trace the 3 different classes of read/write access to QBMan. #undef as * required. */ +#include <config.h> #include <linux/bug.h> #include <linux/printk.h> #undef QBMAN_CCSR_TRACE diff --git a/drivers/net/fsl_mcdmafec.c b/drivers/net/fsl_mcdmafec.c deleted file mode 100644 index cc61a10..0000000 --- a/drivers/net/fsl_mcdmafec.c +++ /dev/null @@ -1,592 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * (C) Copyright 2000-2004 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * (C) Copyright 2007 Freescale Semiconductor, Inc. - * TsiChung Liew (Tsi-Chung.Liew@freescale.com) - * - * Conversion to DM - * (C) 2019 Angelo Dureghello <angelo.dureghello@timesys.com> - */ - -#include <common.h> -#include <env.h> -#include <hang.h> -#include <malloc.h> -#include <command.h> -#include <config.h> -#include <net.h> -#include <miiphy.h> -#include <asm/global_data.h> -#include <linux/delay.h> -#include <linux/mii.h> -#include <asm/immap.h> -#include <asm/fsl_mcdmafec.h> - -#include "MCD_dma.h" - -#undef ET_DEBUG -#undef MII_DEBUG - -/* Ethernet Transmit and Receive Buffers */ -#define DBUF_LENGTH 1520 -#define PKT_MAXBUF_SIZE 1518 -#define FIFO_ERRSTAT (FIFO_STAT_RXW | FIFO_STAT_UF | FIFO_STAT_OF) - -/* RxBD bits definitions */ -#define BD_ENET_RX_ERR (BD_ENET_RX_LG | BD_ENET_RX_NO | BD_ENET_RX_CR | \ - BD_ENET_RX_OV | BD_ENET_RX_TR) - -DECLARE_GLOBAL_DATA_PTR; - -static void init_eth_info(struct fec_info_dma *info) -{ - /* setup Receive and Transmit buffer descriptor */ -#ifdef CFG_SYS_FEC_BUF_USE_SRAM - static u32 tmp; - - if (info->index == 0) - tmp = CFG_SYS_INIT_RAM_ADDR + 0x1000; - else - info->rxbd = (cbd_t *)DBUF_LENGTH; - - info->rxbd = (cbd_t *)((u32)info->rxbd + tmp); - tmp = (u32)info->rxbd; - info->txbd = - (cbd_t *)((u32)info->txbd + tmp + - (PKTBUFSRX * sizeof(cbd_t))); - tmp = (u32)info->txbd; - info->txbuf = - (char *)((u32)info->txbuf + tmp + - (CFG_SYS_TX_ETH_BUFFER * sizeof(cbd_t))); - tmp = (u32)info->txbuf; -#else - info->rxbd = - (cbd_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, - (PKTBUFSRX * sizeof(cbd_t))); - info->txbd = - (cbd_t *)memalign(CONFIG_SYS_CACHELINE_SIZE, - (CFG_SYS_TX_ETH_BUFFER * sizeof(cbd_t))); - info->txbuf = - (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, DBUF_LENGTH); -#endif - -#ifdef ET_DEBUG - printf("rxbd %x txbd %x\n", (int)info->rxbd, (int)info->txbd); -#endif - info->phy_name = (char *)memalign(CONFIG_SYS_CACHELINE_SIZE, 32); -} - -static void fec_halt(struct udevice *dev) -{ - struct fec_info_dma *info = dev_get_priv(dev); - volatile fecdma_t *fecp = (fecdma_t *)info->iobase; - int counter = 0xffff; - - /* issue graceful stop command to the FEC transmitter if necessary */ - fecp->tcr |= FEC_TCR_GTS; - - /* wait for graceful stop to register */ - while ((counter--) && (!(fecp->eir & FEC_EIR_GRA))) - ; - - /* Disable DMA tasks */ - MCD_killDma(info->tx_task); - MCD_killDma(info->rx_task); - - /* Disable the Ethernet Controller */ - fecp->ecr &= ~FEC_ECR_ETHER_EN; - - /* Clear FIFO status registers */ - fecp->rfsr &= FIFO_ERRSTAT; - fecp->tfsr &= FIFO_ERRSTAT; - - fecp->frst = 0x01000000; - - /* Issue a reset command to the FEC chip */ - fecp->ecr |= FEC_ECR_RESET; - - /* wait at least 20 clock cycles */ - mdelay(10); - -#ifdef ET_DEBUG - printf("Ethernet task stopped\n"); -#endif -} - -#ifdef ET_DEBUG -static void dbg_fec_regs(struct eth_device *dev) -{ - struct fec_info_dma *info = dev->priv; - volatile fecdma_t *fecp = (fecdma_t *)info->iobase; - - printf("=====\n"); - printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir); - printf("imask %x - %x\n", (int)&fecp->eimr, fecp->eimr); - printf("ecntrl %x - %x\n", (int)&fecp->ecr, fecp->ecr); - printf("mii_mframe %x - %x\n", (int)&fecp->mmfr, fecp->mmfr); - printf("mii_speed %x - %x\n", (int)&fecp->mscr, fecp->mscr); - printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc); - printf("r_cntrl %x - %x\n", (int)&fecp->rcr, fecp->rcr); - printf("r hash %x - %x\n", (int)&fecp->rhr, fecp->rhr); - printf("x_cntrl %x - %x\n", (int)&fecp->tcr, fecp->tcr); - printf("padr_l %x - %x\n", (int)&fecp->palr, fecp->palr); - printf("padr_u %x - %x\n", (int)&fecp->paur, fecp->paur); - printf("op_pause %x - %x\n", (int)&fecp->opd, fecp->opd); - printf("iadr_u %x - %x\n", (int)&fecp->iaur, fecp->iaur); - printf("iadr_l %x - %x\n", (int)&fecp->ialr, fecp->ialr); - printf("gadr_u %x - %x\n", (int)&fecp->gaur, fecp->gaur); - printf("gadr_l %x - %x\n", (int)&fecp->galr, fecp->galr); - printf("x_wmrk %x - %x\n", (int)&fecp->tfwr, fecp->tfwr); - printf("r_fdata %x - %x\n", (int)&fecp->rfdr, fecp->rfdr); - printf("r_fstat %x - %x\n", (int)&fecp->rfsr, fecp->rfsr); - printf("r_fctrl %x - %x\n", (int)&fecp->rfcr, fecp->rfcr); - printf("r_flrfp %x - %x\n", (int)&fecp->rlrfp, fecp->rlrfp); - printf("r_flwfp %x - %x\n", (int)&fecp->rlwfp, fecp->rlwfp); - printf("r_frfar %x - %x\n", (int)&fecp->rfar, fecp->rfar); - printf("r_frfrp %x - %x\n", (int)&fecp->rfrp, fecp->rfrp); - printf("r_frfwp %x - %x\n", (int)&fecp->rfwp, fecp->rfwp); - printf("t_fdata %x - %x\n", (int)&fecp->tfdr, fecp->tfdr); - printf("t_fstat %x - %x\n", (int)&fecp->tfsr, fecp->tfsr); - printf("t_fctrl %x - %x\n", (int)&fecp->tfcr, fecp->tfcr); - printf("t_flrfp %x - %x\n", (int)&fecp->tlrfp, fecp->tlrfp); - printf("t_flwfp %x - %x\n", (int)&fecp->tlwfp, fecp->tlwfp); - printf("t_ftfar %x - %x\n", (int)&fecp->tfar, fecp->tfar); - printf("t_ftfrp %x - %x\n", (int)&fecp->tfrp, fecp->tfrp); - printf("t_ftfwp %x - %x\n", (int)&fecp->tfwp, fecp->tfwp); - printf("frst %x - %x\n", (int)&fecp->frst, fecp->frst); - printf("ctcwr %x - %x\n", (int)&fecp->ctcwr, fecp->ctcwr); -} -#endif - -static void set_fec_duplex_speed(volatile fecdma_t *fecp, int dup_spd) -{ - struct bd_info *bd = gd->bd; - - if ((dup_spd >> 16) == FULL) { - /* Set maximum frame length */ - fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE | - FEC_RCR_PROM | 0x100; - fecp->tcr = FEC_TCR_FDEN; - } else { - /* Half duplex mode */ - fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | - FEC_RCR_MII_MODE | FEC_RCR_DRT; - fecp->tcr &= ~FEC_TCR_FDEN; - } - - if ((dup_spd & 0xFFFF) == _100BASET) { -#ifdef MII_DEBUG - printf("100Mbps\n"); -#endif - bd->bi_ethspeed = 100; - } else { -#ifdef MII_DEBUG - printf("10Mbps\n"); -#endif - bd->bi_ethspeed = 10; - } -} - -static void fec_set_hwaddr(volatile fecdma_t *fecp, u8 *mac) -{ - u8 curr_byte; /* byte for which to compute the CRC */ - int byte; /* loop - counter */ - int bit; /* loop - counter */ - u32 crc = 0xffffffff; /* initial value */ - - for (byte = 0; byte < 6; byte++) { - curr_byte = mac[byte]; - for (bit = 0; bit < 8; bit++) { - if ((curr_byte & 0x01) ^ (crc & 0x01)) { - crc >>= 1; - crc = crc ^ 0xedb88320; - } else { - crc >>= 1; - } - curr_byte >>= 1; - } - } - - crc = crc >> 26; - - /* Set individual hash table register */ - if (crc >= 32) { - fecp->ialr = (1 << (crc - 32)); - fecp->iaur = 0; - } else { - fecp->ialr = 0; - fecp->iaur = (1 << crc); - } - - /* Set physical address */ - fecp->palr = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3]; - fecp->paur = (mac[4] << 24) + (mac[5] << 16) + 0x8808; - - /* Clear multicast address hash table */ - fecp->gaur = 0; - fecp->galr = 0; -} - -static int fec_init(struct udevice *dev) -{ - struct fec_info_dma *info = dev_get_priv(dev); - volatile fecdma_t *fecp = (fecdma_t *)info->iobase; - int rval, i; - uchar enetaddr[6]; - -#ifdef ET_DEBUG - printf("fec_init: iobase 0x%08x ...\n", info->iobase); -#endif - - fecpin_setclear(info, 1); - fec_halt(dev); - - mii_init(); - set_fec_duplex_speed(fecp, info->dup_spd); - - /* We use strictly polling mode only */ - fecp->eimr = 0; - - /* Clear any pending interrupt */ - fecp->eir = 0xffffffff; - - /* Set station address */ - if (info->index == 0) - rval = eth_env_get_enetaddr("ethaddr", enetaddr); - else - rval = eth_env_get_enetaddr("eth1addr", enetaddr); - - if (!rval) { - puts("Please set a valid MAC address\n"); - return -EINVAL; - } - - fec_set_hwaddr(fecp, enetaddr); - - /* Set Opcode/Pause Duration Register */ - fecp->opd = 0x00010020; - - /* Setup Buffers and Buffer Descriptors */ - info->rx_idx = 0; - info->tx_idx = 0; - - /* Setup Receiver Buffer Descriptors (13.14.24.18) - * Settings: Empty, Wrap */ - for (i = 0; i < PKTBUFSRX; i++) { - info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; - info->rxbd[i].cbd_datlen = PKTSIZE_ALIGN; - info->rxbd[i].cbd_bufaddr = (uint) net_rx_packets[i]; - } - info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; - - /* Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) - * Settings: Last, Tx CRC */ - for (i = 0; i < CFG_SYS_TX_ETH_BUFFER; i++) { - info->txbd[i].cbd_sc = 0; - info->txbd[i].cbd_datlen = 0; - info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]); - } - info->txbd[CFG_SYS_TX_ETH_BUFFER - 1].cbd_sc |= BD_ENET_TX_WRAP; - - info->used_tbd_idx = 0; - info->clean_tbd_num = CFG_SYS_TX_ETH_BUFFER; - - /* Set Rx FIFO alarm and granularity value */ - fecp->rfcr = 0x0c000000; - fecp->rfar = 0x0000030c; - - /* Set Tx FIFO granularity value */ - fecp->tfcr = FIFO_CTRL_FRAME | FIFO_CTRL_GR(6) | 0x00040000; - fecp->tfar = 0x00000080; - - fecp->tfwr = 0x2; - fecp->ctcwr = 0x03000000; - - /* Enable DMA receive task */ - MCD_startDma(info->rx_task, - (s8 *)info->rxbd, - 0, - (s8 *)&fecp->rfdr, - 4, - 0, - 4, - info->rx_init, - info->rx_pri, - (MCD_FECRX_DMA | MCD_TT_FLAGS_DEF), - (MCD_NO_CSUM | MCD_NO_BYTE_SWAP) - ); - - /* Enable DMA tx task with no ready buffer descriptors */ - MCD_startDma(info->tx_task, - (s8 *)info->txbd, - 0, - (s8 *)&fecp->tfdr, - 4, - 0, - 4, - info->tx_init, - info->tx_pri, - (MCD_FECTX_DMA | MCD_TT_FLAGS_DEF), - (MCD_NO_CSUM | MCD_NO_BYTE_SWAP) - ); - - /* Now enable the transmit and receive processing */ - fecp->ecr |= FEC_ECR_ETHER_EN; - - return 0; -} - -static int mcdmafec_init(struct udevice *dev) -{ - return fec_init(dev); -} - -static int mcdmafec_send(struct udevice *dev, void *packet, int length) -{ - struct fec_info_dma *info = dev_get_priv(dev); - cbd_t *p_tbd, *p_used_tbd; - u16 phy_status; - - miiphy_read(dev->name, info->phy_addr, MII_BMSR, &phy_status); - - /* process all the consumed TBDs */ - while (info->clean_tbd_num < CFG_SYS_TX_ETH_BUFFER) { - p_used_tbd = &info->txbd[info->used_tbd_idx]; - if (p_used_tbd->cbd_sc & BD_ENET_TX_READY) { -#ifdef ET_DEBUG - printf("Cannot clean TBD %d, in use\n", - info->clean_tbd_num); -#endif - return 0; - } - - /* clean this buffer descriptor */ - if (info->used_tbd_idx == (CFG_SYS_TX_ETH_BUFFER - 1)) - p_used_tbd->cbd_sc = BD_ENET_TX_WRAP; - else - p_used_tbd->cbd_sc = 0; - - /* update some indeces for a correct handling of TBD ring */ - info->clean_tbd_num++; - info->used_tbd_idx = (info->used_tbd_idx + 1) - % CFG_SYS_TX_ETH_BUFFER; - } - - /* Check for valid length of data. */ - if (length > 1500 || length <= 0) - return -1; - - /* Check the number of vacant TxBDs. */ - if (info->clean_tbd_num < 1) { - printf("No available TxBDs ...\n"); - return -1; - } - - /* Get the first TxBD to send the mac header */ - p_tbd = &info->txbd[info->tx_idx]; - p_tbd->cbd_datlen = length; - p_tbd->cbd_bufaddr = (u32)packet; - p_tbd->cbd_sc |= BD_ENET_TX_LAST | BD_ENET_TX_TC | BD_ENET_TX_READY; - info->tx_idx = (info->tx_idx + 1) % CFG_SYS_TX_ETH_BUFFER; - - /* Enable DMA transmit task */ - MCD_continDma(info->tx_task); - - info->clean_tbd_num -= 1; - - /* wait until frame is sent . */ - while (p_tbd->cbd_sc & BD_ENET_TX_READY) - udelay(10); - - return (int)(info->txbd[info->tx_idx].cbd_sc & BD_ENET_TX_STATS); -} - -static int mcdmafec_recv(struct udevice *dev, int flags, uchar **packetp) -{ - struct fec_info_dma *info = dev_get_priv(dev); - volatile fecdma_t *fecp = (fecdma_t *)info->iobase; - - cbd_t *prbd = &info->rxbd[info->rx_idx]; - u32 ievent; - int frame_length, len = 0; - - /* Check if any critical events have happened */ - ievent = fecp->eir; - if (ievent != 0) { - fecp->eir = ievent; - - if (ievent & (FEC_EIR_BABT | FEC_EIR_TXERR | FEC_EIR_RXERR)) { - printf("fec_recv: error\n"); - fec_halt(dev); - fec_init(dev); - return 0; - } - - if (ievent & FEC_EIR_HBERR) { - /* Heartbeat error */ - fecp->tcr |= FEC_TCR_GTS; - } - - if (ievent & FEC_EIR_GRA) { - /* Graceful stop complete */ - if (fecp->tcr & FEC_TCR_GTS) { - printf("fec_recv: tcr_gts\n"); - fec_halt(dev); - fecp->tcr &= ~FEC_TCR_GTS; - fec_init(dev); - } - } - } - - if (!(prbd->cbd_sc & BD_ENET_RX_EMPTY)) { - if ((prbd->cbd_sc & BD_ENET_RX_LAST) && - !(prbd->cbd_sc & BD_ENET_RX_ERR) && - ((prbd->cbd_datlen - 4) > 14)) { - /* Get buffer address and size */ - frame_length = prbd->cbd_datlen - 4; - - /* Fill the buffer and pass it to upper layers */ - net_process_received_packet((uchar *)prbd->cbd_bufaddr, - frame_length); - len = frame_length; - } - - /* Reset buffer descriptor as empty */ - if (info->rx_idx == (PKTBUFSRX - 1)) - prbd->cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); - else - prbd->cbd_sc = BD_ENET_RX_EMPTY; - - prbd->cbd_datlen = PKTSIZE_ALIGN; - - /* Now, we have an empty RxBD, restart the DMA receive task */ - MCD_continDma(info->rx_task); - - /* Increment BD count */ - info->rx_idx = (info->rx_idx + 1) % PKTBUFSRX; - } - - return len; -} - -static void mcdmafec_halt(struct udevice *dev) -{ - fec_halt(dev); -} - -static const struct eth_ops mcdmafec_ops = { - .start = mcdmafec_init, - .send = mcdmafec_send, - .recv = mcdmafec_recv, - .stop = mcdmafec_halt, -}; - -/* - * Boot sequence, called just after mcffec_of_to_plat, - * as DM way, it replaces old mcffec_initialize. - */ -static int mcdmafec_probe(struct udevice *dev) -{ - struct fec_info_dma *info = dev_get_priv(dev); - struct eth_pdata *pdata = dev_get_plat(dev); - int node = dev_of_offset(dev); - int retval; - const u32 *val; - - info->index = dev_seq(dev); - info->iobase = pdata->iobase; - info->miibase = pdata->iobase; - info->phy_addr = -1; - - val = fdt_getprop(gd->fdt_blob, node, "rx-task", NULL); - if (val) - info->rx_task = fdt32_to_cpu(*val); - - val = fdt_getprop(gd->fdt_blob, node, "tx-task", NULL); - if (val) - info->tx_task = fdt32_to_cpu(*val); - - val = fdt_getprop(gd->fdt_blob, node, "rx-prioprity", NULL); - if (val) - info->rx_pri = fdt32_to_cpu(*val); - - val = fdt_getprop(gd->fdt_blob, node, "tx-prioprity", NULL); - if (val) - info->tx_pri = fdt32_to_cpu(*val); - - val = fdt_getprop(gd->fdt_blob, node, "rx-init", NULL); - if (val) - info->rx_init = fdt32_to_cpu(*val); - - val = fdt_getprop(gd->fdt_blob, node, "tx-init", NULL); - if (val) - info->tx_init = fdt32_to_cpu(*val); - -#ifdef CFG_SYS_FEC_BUF_USE_SRAM - u32 tmp = CFG_SYS_INIT_RAM_ADDR + 0x1000; -#endif - init_eth_info(info); - -#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) - info->bus = mdio_alloc(); - if (!info->bus) - return -ENOMEM; - strlcpy(info->bus->name, dev->name, MDIO_NAME_LEN); - info->bus->read = mcffec_miiphy_read; - info->bus->write = mcffec_miiphy_write; - - retval = mdio_register(info->bus); - if (retval < 0) - return retval; -#endif - - return 0; -} - -static int mcdmafec_remove(struct udevice *dev) -{ - struct fec_info_dma *priv = dev_get_priv(dev); - - mdio_unregister(priv->bus); - mdio_free(priv->bus); - - return 0; -} - -/* - * Boot sequence, called 1st - */ -static int mcdmafec_of_to_plat(struct udevice *dev) -{ - struct eth_pdata *pdata = dev_get_plat(dev); - const u32 *val; - - pdata->iobase = dev_read_addr(dev); - /* Default to 10Mbit/s */ - pdata->max_speed = 10; - - val = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "max-speed", NULL); - if (val) - pdata->max_speed = fdt32_to_cpu(*val); - - return 0; -} - -static const struct udevice_id mcdmafec_ids[] = { - { .compatible = "fsl,mcf-dma-fec" }, - { } -}; - -U_BOOT_DRIVER(mcffec) = { - .name = "mcdmafec", - .id = UCLASS_ETH, - .of_match = mcdmafec_ids, - .of_to_plat = mcdmafec_of_to_plat, - .probe = mcdmafec_probe, - .remove = mcdmafec_remove, - .ops = &mcdmafec_ops, - .priv_auto = sizeof(struct fec_info_dma), - .plat_auto = sizeof(struct eth_pdata), -}; diff --git a/drivers/net/mdio_mux_meson_gxl.c b/drivers/net/mdio_mux_meson_gxl.c new file mode 100644 index 0000000..8ef3ae5 --- /dev/null +++ b/drivers/net/mdio_mux_meson_gxl.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2022 Baylibre, SAS. + * Author: Jerome Brunet <jbrunet@baylibre.com> + * Copyright (c) 2023 Neil Armstrong <neil.armstrong@linaro.org> + */ + +#include <dm.h> +#include <errno.h> +#include <log.h> +#include <miiphy.h> +#include <asm/io.h> +#include <linux/bitfield.h> +#include <linux/delay.h> + +#define ETH_REG2 0x0 +#define REG2_PHYID GENMASK(21, 0) +#define EPHY_GXL_ID 0x110181 +#define REG2_LEDACT GENMASK(23, 22) +#define REG2_LEDLINK GENMASK(25, 24) +#define REG2_DIV4SEL BIT(27) +#define REG2_ADCBYPASS BIT(30) +#define REG2_CLKINSEL BIT(31) +#define ETH_REG3 0x4 +#define REG3_ENH BIT(3) +#define REG3_CFGMODE GENMASK(6, 4) +#define REG3_AUTOMDIX BIT(7) +#define REG3_PHYADDR GENMASK(12, 8) +#define REG3_PWRUPRST BIT(21) +#define REG3_PWRDOWN BIT(22) +#define REG3_LEDPOL BIT(23) +#define REG3_PHYMDI BIT(26) +#define REG3_CLKINEN BIT(29) +#define REG3_PHYIP BIT(30) +#define REG3_PHYEN BIT(31) +#define ETH_REG4 0x8 +#define REG4_PWRUPRSTSIG BIT(0) + +#define MESON_GXL_MDIO_EXTERNAL_ID 0 +#define MESON_GXL_MDIO_INTERNAL_ID 1 + +struct mdio_mux_meson_gxl_priv { + phys_addr_t regs; +}; + +static int meson_gxl_enable_internal_mdio(struct mdio_mux_meson_gxl_priv *priv) +{ + u32 val; + + /* Setup the internal phy */ + val = (REG3_ENH | + FIELD_PREP(REG3_CFGMODE, 0x7) | + REG3_AUTOMDIX | + FIELD_PREP(REG3_PHYADDR, 8) | + REG3_LEDPOL | + REG3_PHYMDI | + REG3_CLKINEN | + REG3_PHYIP); + + writel(REG4_PWRUPRSTSIG, priv->regs + ETH_REG4); + writel(val, priv->regs + ETH_REG3); + mdelay(10); + + /* NOTE: The HW kept the phy id configurable at runtime. + * The id below is arbitrary. It is the one used in the vendor code. + * The only constraint is that it must match the one in + * drivers/net/phy/meson-gxl.c to properly match the PHY. + */ + writel(FIELD_PREP(REG2_PHYID, EPHY_GXL_ID), + priv->regs + ETH_REG2); + + /* Enable the internal phy */ + val |= REG3_PHYEN; + writel(val, priv->regs + ETH_REG3); + writel(0, priv->regs + ETH_REG4); + + /* The phy needs a bit of time to power up */ + mdelay(10); + + return 0; +} + +static int meson_gxl_enable_external_mdio(struct mdio_mux_meson_gxl_priv *priv) +{ + /* Reset the mdio bus mux to the external phy */ + writel(0, priv->regs + ETH_REG3); + + return 0; +} + +static int mdio_mux_meson_gxl_select(struct udevice *mux, int cur, int sel) +{ + struct mdio_mux_meson_gxl_priv *priv = dev_get_priv(mux); + + debug("%s: %x -> %x\n", __func__, (u32)cur, (u32)sel); + + /* if last selection didn't change we're good to go */ + if (cur == sel) + return 0; + + switch (sel) { + case MESON_GXL_MDIO_EXTERNAL_ID: + return meson_gxl_enable_external_mdio(priv); + case MESON_GXL_MDIO_INTERNAL_ID: + return meson_gxl_enable_internal_mdio(priv); + default: + return -EINVAL; + } + + return 0; +} + +static const struct mdio_mux_ops mdio_mux_meson_gxl_ops = { + .select = mdio_mux_meson_gxl_select, +}; + +static int mdio_mux_meson_gxl_probe(struct udevice *dev) +{ + struct mdio_mux_meson_gxl_priv *priv = dev_get_priv(dev); + + priv->regs = dev_read_addr(dev); + + return 0; +} + +static const struct udevice_id mdio_mux_meson_gxl_ids[] = { + { .compatible = "amlogic,gxl-mdio-mux" }, + { } +}; + +U_BOOT_DRIVER(mdio_mux_meson_gxl) = { + .name = "mdio_mux_meson_gxl", + .id = UCLASS_MDIO_MUX, + .of_match = mdio_mux_meson_gxl_ids, + .probe = mdio_mux_meson_gxl_probe, + .ops = &mdio_mux_meson_gxl_ops, + .priv_auto = sizeof(struct mdio_mux_meson_gxl_priv), +}; diff --git a/drivers/net/mscc_eswitch/mscc_mac_table.c b/drivers/net/mscc_eswitch/mscc_mac_table.c index 25b9cad..06e1f62 100644 --- a/drivers/net/mscc_eswitch/mscc_mac_table.c +++ b/drivers/net/mscc_eswitch/mscc_mac_table.c @@ -3,6 +3,7 @@ * Copyright (c) 2018 Microsemi Corporation */ +#include <errno.h> #include <linux/bitops.h> #include <linux/io.h> #include "mscc_mac_table.h" diff --git a/drivers/net/mscc_eswitch/mscc_mac_table.h b/drivers/net/mscc_eswitch/mscc_mac_table.h index 17fed2e..5ec8db2 100644 --- a/drivers/net/mscc_eswitch/mscc_mac_table.h +++ b/drivers/net/mscc_eswitch/mscc_mac_table.h @@ -3,8 +3,6 @@ * Copyright (c) 2018 Microsemi Corporation */ -#include <common.h> - #define ETH_LEN 6 #define MAC_VID 1 diff --git a/drivers/net/mscc_eswitch/mscc_xfer.c b/drivers/net/mscc_eswitch/mscc_xfer.c index 6f74746..ee6bf06 100644 --- a/drivers/net/mscc_eswitch/mscc_xfer.c +++ b/drivers/net/mscc_eswitch/mscc_xfer.c @@ -3,6 +3,7 @@ * Copyright (c) 2018 Microsemi Corporation */ +#include <errno.h> #include <log.h> #include <linux/bitops.h> #include <linux/delay.h> diff --git a/drivers/net/mscc_eswitch/mscc_xfer.h b/drivers/net/mscc_eswitch/mscc_xfer.h index c880a4e..70f2794 100644 --- a/drivers/net/mscc_eswitch/mscc_xfer.h +++ b/drivers/net/mscc_eswitch/mscc_xfer.h @@ -3,8 +3,6 @@ * Copyright (c) 2018 Microsemi Corporation */ -#include <common.h> - enum mscc_regs_qs { MSCC_QS_XTR_RD, MSCC_QS_XTR_FLUSH, diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 396cac7..7e1036b 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -446,6 +446,20 @@ U_BOOT_PHY_DRIVER(rtl8211f) = { .writeext = &rtl8211f_phy_extwrite, }; +/* Support for RTL8211F-VD PHY */ +U_BOOT_PHY_DRIVER(rtl8211fvd) = { + .name = "RealTek RTL8211F-VD", + .uid = 0x1cc878, + .mask = 0xffffff, + .features = PHY_GBIT_FEATURES, + .probe = &rtl8211f_probe, + .config = &rtl8211f_config, + .startup = &rtl8211f_startup, + .shutdown = &genphy_shutdown, + .readext = &rtl8211f_phy_extread, + .writeext = &rtl8211f_phy_extwrite, +}; + /* Support for RTL8201F PHY */ U_BOOT_PHY_DRIVER(rtl8201f) = { .name = "RealTek RTL8201F 10/100Mbps Ethernet", diff --git a/drivers/net/qe/uccf.c b/drivers/net/qe/uccf.c index 306f1ea..00848a1 100644 --- a/drivers/net/qe/uccf.c +++ b/drivers/net/qe/uccf.c @@ -6,7 +6,6 @@ * based on source code of Shlomi Gridish */ -#include <common.h> #include <malloc.h> #include <linux/errno.h> #include <asm/io.h> diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 54f2232..ef151ee 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -903,12 +903,11 @@ static int axi_emac_of_to_plat(struct udevice *dev) ret = dev_read_phandle_with_args(dev, "axistream-connected", NULL, 0, 0, &axistream_node); - if (ret) { - printf("%s: axistream is not found\n", __func__); - return -EINVAL; - } + if (!ret) + plat->dmatx = (struct axidma_reg *)ofnode_get_addr(axistream_node.node); + else + plat->dmatx = (struct axidma_reg *)dev_read_addr_index(dev, 1); - plat->dmatx = (struct axidma_reg *)ofnode_get_addr(axistream_node.node); if (!plat->dmatx) { printf("%s: axi_dma register space not found\n", __func__); return -EINVAL; diff --git a/drivers/pci/pcie_layerscape_fixup_common.h b/drivers/pci/pcie_layerscape_fixup_common.h index 70bd3f0..3255b76 100644 --- a/drivers/pci/pcie_layerscape_fixup_common.h +++ b/drivers/pci/pcie_layerscape_fixup_common.h @@ -9,8 +9,6 @@ #ifndef _PCIE_LAYERSCAPE_FIXUP_COMMON_H_ #define _PCIE_LAYERSCAPE_FIXUP_COMMON_H_ -#include <common.h> - void ft_pci_setup_ls(void *blob, struct bd_info *bd); #ifdef CONFIG_PCIE_LAYERSCAPE_GEN4 diff --git a/drivers/pci/pcie_xilinx.c b/drivers/pci/pcie_xilinx.c index 53fd121..3db460b 100644 --- a/drivers/pci/pcie_xilinx.c +++ b/drivers/pci/pcie_xilinx.c @@ -8,11 +8,10 @@ #include <common.h> #include <dm.h> #include <pci.h> -#include <asm/global_data.h> #include <linux/bitops.h> #include <linux/printk.h> - -#include <asm/io.h> +#include <linux/io.h> +#include <linux/err.h> /** * struct xilinx_pcie - Xilinx PCIe controller state @@ -25,6 +24,8 @@ struct xilinx_pcie { /* Register definitions */ #define XILINX_PCIE_REG_PSCR 0x144 #define XILINX_PCIE_REG_PSCR_LNKUP BIT(11) +#define XILINX_PCIE_REG_RPSC 0x148 +#define XILINX_PCIE_REG_RPSC_BEN BIT(0) /** * pcie_xilinx_link_up() - Check whether the PCIe link is up @@ -140,20 +141,22 @@ static int pcie_xilinx_write_config(struct udevice *bus, pci_dev_t bdf, static int pcie_xilinx_of_to_plat(struct udevice *dev) { struct xilinx_pcie *pcie = dev_get_priv(dev); - struct fdt_resource reg_res; - DECLARE_GLOBAL_DATA_PTR; - int err; - - err = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev), "reg", - 0, ®_res); - if (err < 0) { - pr_err("\"reg\" resource not found\n"); - return err; - } - - pcie->cfg_base = map_physmem(reg_res.start, - fdt_resource_size(®_res), - MAP_NOCACHE); + fdt_addr_t addr; + fdt_size_t size; + u32 rpsc; + + addr = dev_read_addr_size(dev, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + pcie->cfg_base = devm_ioremap(dev, addr, size); + if (IS_ERR(pcie->cfg_base)) + return PTR_ERR(pcie->cfg_base); + + /* Enable the Bridge enable bit */ + rpsc = __raw_readl(pcie->cfg_base + XILINX_PCIE_REG_RPSC); + rpsc |= XILINX_PCIE_REG_RPSC_BEN; + __raw_writel(rpsc, pcie->cfg_base + XILINX_PCIE_REG_RPSC); return 0; } diff --git a/drivers/pci_endpoint/pcie-cadence.h b/drivers/pci_endpoint/pcie-cadence.h index 8a659c3..dd0101a 100644 --- a/drivers/pci_endpoint/pcie-cadence.h +++ b/drivers/pci_endpoint/pcie-cadence.h @@ -11,7 +11,6 @@ #ifndef PCIE_CADENCE_H #define PCIE_CADENCE_H -#include <common.h> #include <pci_ep.h> #include <asm/io.h> #include <linux/bitops.h> diff --git a/drivers/phy/meson-axg-mipi-dphy.c b/drivers/phy/meson-axg-mipi-dphy.c index cf2a1cd..a69b6c9 100644 --- a/drivers/phy/meson-axg-mipi-dphy.c +++ b/drivers/phy/meson-axg-mipi-dphy.c @@ -25,6 +25,7 @@ #include <linux/bitops.h> #include <linux/compat.h> #include <linux/bitfield.h> +#include <linux/time.h> /* [31] soft reset for the phy. * 1: reset. 0: dessert the reset. @@ -170,8 +171,6 @@ #define MIPI_DSI_TEST_CTRL0 0x3c #define MIPI_DSI_TEST_CTRL1 0x40 -#define NSEC_PER_MSEC 1000000L - struct phy_meson_axg_mipi_dphy_priv { struct regmap *regmap; #if CONFIG_IS_ENABLED(CLK) diff --git a/drivers/phy/phy-core-mipi-dphy.c b/drivers/phy/phy-core-mipi-dphy.c index ba5f648..bb61816 100644 --- a/drivers/phy/phy-core-mipi-dphy.c +++ b/drivers/phy/phy-core-mipi-dphy.c @@ -6,11 +6,10 @@ #include <common.h> #include <div64.h> +#include <linux/time.h> #include <phy-mipi-dphy.h> -#define PSEC_PER_SEC 1000000000000LL - /* * Minimum D-PHY timings based on MIPI D-PHY specification. Derived * from the valid ranges specified in Section 6.9, Table 14, Page 41 diff --git a/drivers/phy/phy-imx8mq-usb.c b/drivers/phy/phy-imx8mq-usb.c index b660ead..e5e96e7 100644 --- a/drivers/phy/phy-imx8mq-usb.c +++ b/drivers/phy/phy-imx8mq-usb.c @@ -231,16 +231,10 @@ static int imx8mq_usb_phy_power_off(struct phy *usb_phy) return 0; } -static int imx8mq_usb_phy_exit(struct phy *usb_phy) -{ - return imx8mq_usb_phy_power_off(usb_phy); -} - struct phy_ops imx8mq_usb_phy_ops = { .init = imx8mpq_usb_phy_init, .power_on = imx8mq_usb_phy_power_on, .power_off = imx8mq_usb_phy_power_off, - .exit = imx8mq_usb_phy_exit, }; int imx8mq_usb_phy_probe(struct udevice *dev) diff --git a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c index 9ed7af0..5be76e0 100644 --- a/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c +++ b/drivers/phy/rockchip/phy-rockchip-inno-dsidphy.c @@ -15,6 +15,7 @@ #include <linux/clk-provider.h> #include <linux/delay.h> #include <linux/math64.h> +#include <linux/time.h> #include <phy-mipi-dphy.h> #include <reset.h> @@ -186,8 +187,6 @@ #define DSI_PHY_STATUS 0xb0 #define PHY_LOCK BIT(0) -#define PSEC_PER_SEC 1000000000000LL - #define msleep(a) udelay(a * 1000) enum phy_max_rate { diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 75b3ff4..fceafea 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -358,6 +358,7 @@ source "drivers/pinctrl/nxp/Kconfig" source "drivers/pinctrl/renesas/Kconfig" source "drivers/pinctrl/rockchip/Kconfig" source "drivers/pinctrl/sunxi/Kconfig" +source "drivers/pinctrl/tegra/Kconfig" source "drivers/pinctrl/uniphier/Kconfig" source "drivers/pinctrl/starfive/Kconfig" diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index fc1f01a..96a0516 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_ARCH_RMOBILE) += renesas/ obj-$(CONFIG_ARCH_RZN1) += renesas/ obj-$(CONFIG_PINCTRL_SANDBOX) += pinctrl-sandbox.o obj-$(CONFIG_PINCTRL_SUNXI) += sunxi/ +obj-$(CONFIG_$(SPL_)PINCTRL_TEGRA) += tegra/ obj-$(CONFIG_PINCTRL_UNIPHIER) += uniphier/ obj-$(CONFIG_PINCTRL_PIC32) += pinctrl_pic32.o obj-$(CONFIG_PINCTRL_EXYNOS) += exynos/ diff --git a/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h b/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h index 1f1023e..7a38f8d 100644 --- a/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h +++ b/drivers/pinctrl/mtmips/pinctrl-mtmips-common.h @@ -8,8 +8,6 @@ #ifndef _PINCTRL_MTMIPS_COMMON_H_ #define _PINCTRL_MTMIPS_COMMON_H_ -#include <common.h> - struct mtmips_pmx_func { const char *name; int value; diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index 8bb7588..7120b8e 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -505,6 +505,8 @@ static const struct udevice_id stm32_pinctrl_ids[] = { { .compatible = "st,stm32mp157-pinctrl" }, { .compatible = "st,stm32mp157-z-pinctrl" }, { .compatible = "st,stm32mp135-pinctrl" }, + { .compatible = "st,stm32mp257-pinctrl" }, + { .compatible = "st,stm32mp257-z-pinctrl" }, { } }; diff --git a/drivers/pinctrl/tegra/Kconfig b/drivers/pinctrl/tegra/Kconfig new file mode 100644 index 0000000..669d8e2 --- /dev/null +++ b/drivers/pinctrl/tegra/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0 + +config PINCTRL_TEGRA + bool "Nvidia Tegra pinctrl driver" + depends on DM + help + Support pin multiplexing control on Nvidia Tegra SoCs. + The driver is an overlay to existing driver and allows + the usage of dedicated device tree node which contains + full description of each pin. + +config SPL_PINCTRL_TEGRA + bool "Nvidia Tegra SPL pinctrl driver" + depends on SPL_PINCTRL + help + Enables support of pre-DM version of pin multiplexing + control driver used on SPL stage for board setup and + available for backwards compatibility purpose. diff --git a/drivers/pinctrl/tegra/Makefile b/drivers/pinctrl/tegra/Makefile new file mode 100644 index 0000000..75d3cab --- /dev/null +++ b/drivers/pinctrl/tegra/Makefile @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +ifndef CONFIG_SPL_BUILD +ifdef CONFIG_TEGRA20 +obj-y += pinctrl-tegra20.o +else +obj-y += pinctrl-tegra.o +endif +endif + +obj-y += pinmux-common.o + +obj-$(CONFIG_TEGRA20) += pinmux-tegra20.o funcmux-tegra20.o +obj-$(CONFIG_TEGRA30) += pinmux-tegra30.o funcmux-tegra30.o +obj-$(CONFIG_TEGRA114) += pinmux-tegra114.o funcmux-tegra114.o +obj-$(CONFIG_TEGRA124) += pinmux-tegra124.o funcmux-tegra124.o +obj-$(CONFIG_TEGRA210) += pinmux-tegra210.o funcmux-tegra210.o diff --git a/drivers/pinctrl/tegra/funcmux-tegra114.c b/drivers/pinctrl/tegra/funcmux-tegra114.c new file mode 100644 index 0000000..23a27c8 --- /dev/null +++ b/drivers/pinctrl/tegra/funcmux-tegra114.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + */ + +/* Tegra114 high-level function multiplexing */ + +#include <common.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART4: + switch (config) { + case FUNCMUX_UART4_GMI: + pinmux_set_func(PMUX_PINGRP_GMI_A16_PJ7, + PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_GMI_A17_PB0, + PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_GMI_A18_PB1, + PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_GMI_A19_PK7, + PMUX_FUNC_UARTD); + + pinmux_set_io(PMUX_PINGRP_GMI_A16_PJ7, PMUX_PIN_OUTPUT); + pinmux_set_io(PMUX_PINGRP_GMI_A17_PB0, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_GMI_A18_PB1, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_GMI_A19_PK7, PMUX_PIN_OUTPUT); + + pinmux_tristate_disable(PMUX_PINGRP_GMI_A16_PJ7); + pinmux_tristate_disable(PMUX_PINGRP_GMI_A17_PB0); + pinmux_tristate_disable(PMUX_PINGRP_GMI_A18_PB1); + pinmux_tristate_disable(PMUX_PINGRP_GMI_A19_PK7); + break; + } + break; + + /* Add other periph IDs here as needed */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/drivers/pinctrl/tegra/funcmux-tegra124.c b/drivers/pinctrl/tegra/funcmux-tegra124.c new file mode 100644 index 0000000..e7ad85f --- /dev/null +++ b/drivers/pinctrl/tegra/funcmux-tegra124.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013 + * NVIDIA Corporation <www.nvidia.com> + */ + +/* Tegra124 high-level function multiplexing */ + +#include <common.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART4: + switch (config) { + case FUNCMUX_UART4_GPIO: /* TXD,RXD,CTS,RTS */ + pinmux_set_func(PMUX_PINGRP_PJ7, PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_PB0, PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_PB1, PMUX_FUNC_UARTD); + pinmux_set_func(PMUX_PINGRP_PK7, PMUX_FUNC_UARTD); + + pinmux_set_io(PMUX_PINGRP_PJ7, PMUX_PIN_OUTPUT); + pinmux_set_io(PMUX_PINGRP_PB0, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_PB1, PMUX_PIN_INPUT); + pinmux_set_io(PMUX_PINGRP_PK7, PMUX_PIN_OUTPUT); + + pinmux_tristate_disable(PMUX_PINGRP_PJ7); + pinmux_tristate_disable(PMUX_PINGRP_PB0); + pinmux_tristate_disable(PMUX_PINGRP_PB1); + pinmux_tristate_disable(PMUX_PINGRP_PK7); + break; + } + break; + + case PERIPH_ID_UART1: + switch (config) { + case FUNCMUX_UART1_KBC: + pinmux_set_func(PMUX_PINGRP_KB_ROW9_PS1, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_KB_ROW10_PS2, + PMUX_FUNC_UARTA); + + pinmux_set_io(PMUX_PINGRP_KB_ROW9_PS1, PMUX_PIN_OUTPUT); + pinmux_set_io(PMUX_PINGRP_KB_ROW10_PS2, PMUX_PIN_INPUT); + + pinmux_tristate_disable(PMUX_PINGRP_KB_ROW9_PS1); + pinmux_tristate_disable(PMUX_PINGRP_KB_ROW10_PS2); + break; + } + break; + + /* Add other periph IDs here as needed */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/drivers/pinctrl/tegra/funcmux-tegra20.c b/drivers/pinctrl/tegra/funcmux-tegra20.c new file mode 100644 index 0000000..90fe0cb --- /dev/null +++ b/drivers/pinctrl/tegra/funcmux-tegra20.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2011 The Chromium OS Authors. + */ + +/* Tegra20 high-level function multiplexing */ +#include <common.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +/* + * The PINMUX macro is used to set up pinmux tables. + */ +#define PINMUX(grp, mux, pupd, tri) \ + {PMUX_PINGRP_##grp, PMUX_FUNC_##mux, PMUX_PULL_##pupd, PMUX_TRI_##tri} + +static const struct pmux_pingrp_config disp1_default[] = { + PINMUX(LDI, DISPA, NORMAL, NORMAL), + PINMUX(LHP0, DISPA, NORMAL, NORMAL), + PINMUX(LHP1, DISPA, NORMAL, NORMAL), + PINMUX(LHP2, DISPA, NORMAL, NORMAL), + PINMUX(LHS, DISPA, NORMAL, NORMAL), + PINMUX(LM0, RSVD4, NORMAL, NORMAL), + PINMUX(LPP, DISPA, NORMAL, NORMAL), + PINMUX(LPW0, DISPA, NORMAL, NORMAL), + PINMUX(LPW2, DISPA, NORMAL, NORMAL), + PINMUX(LSC0, DISPA, NORMAL, NORMAL), + PINMUX(LSPI, DISPA, NORMAL, NORMAL), + PINMUX(LVP1, DISPA, NORMAL, NORMAL), + PINMUX(LVS, DISPA, NORMAL, NORMAL), + PINMUX(SLXD, SPDIF, NORMAL, NORMAL), +}; + + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART1: + switch (config) { + case FUNCMUX_UART1_IRRX_IRTX: + pinmux_set_func(PMUX_PINGRP_IRRX, PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_IRTX, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_IRRX); + pinmux_tristate_disable(PMUX_PINGRP_IRTX); + break; + case FUNCMUX_UART1_UAA_UAB: + pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_UAA); + pinmux_tristate_disable(PMUX_PINGRP_UAB); + bad_config = 0; + break; + case FUNCMUX_UART1_GPU: + pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_GPU); + bad_config = 0; + break; + case FUNCMUX_UART1_SDIO1: + pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_SDIO1); + bad_config = 0; + break; + } + if (!bad_config) { + /* + * Tegra appears to boot with function UARTA pre- + * selected on mux group SDB. If two mux groups are + * both set to the same function, it's unclear which + * group's pins drive the RX signals into the HW. + * For UARTA, SDB certainly overrides group IRTX in + * practice. To solve this, configure some alternative + * function on SDB to avoid the conflict. Also, tri- + * state the group to avoid driving any signal onto it + * until we know what's connected. + */ + pinmux_tristate_enable(PMUX_PINGRP_SDB); + pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3); + } + break; + + case PERIPH_ID_UART2: + if (config == FUNCMUX_UART2_UAD) { + pinmux_set_func(PMUX_PINGRP_UAD, PMUX_FUNC_UARTB); + pinmux_tristate_disable(PMUX_PINGRP_UAD); + } + break; + + case PERIPH_ID_UART4: + if (config == FUNCMUX_UART4_GMC) { + pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_UARTD); + pinmux_tristate_disable(PMUX_PINGRP_GMC); + } + break; + + case PERIPH_ID_DVC_I2C: + /* there is only one selection, pinmux_config is ignored */ + if (config == FUNCMUX_DVC_I2CP) { + pinmux_set_func(PMUX_PINGRP_I2CP, PMUX_FUNC_I2C); + pinmux_tristate_disable(PMUX_PINGRP_I2CP); + } + break; + + case PERIPH_ID_I2C1: + /* support pinmux_config of 0 for now, */ + if (config == FUNCMUX_I2C1_RM) { + pinmux_set_func(PMUX_PINGRP_RM, PMUX_FUNC_I2C); + pinmux_tristate_disable(PMUX_PINGRP_RM); + } + break; + case PERIPH_ID_I2C2: /* I2C2 */ + switch (config) { + case FUNCMUX_I2C2_DDC: /* DDC pin group, select I2C2 */ + pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_I2C2); + /* PTA to HDMI */ + pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_HDMI); + pinmux_tristate_disable(PMUX_PINGRP_DDC); + break; + case FUNCMUX_I2C2_PTA: /* PTA pin group, select I2C2 */ + pinmux_set_func(PMUX_PINGRP_PTA, PMUX_FUNC_I2C2); + /* set DDC_SEL to RSVDx (RSVD2 works for now) */ + pinmux_set_func(PMUX_PINGRP_DDC, PMUX_FUNC_RSVD2); + pinmux_tristate_disable(PMUX_PINGRP_PTA); + bad_config = 0; + break; + } + break; + case PERIPH_ID_I2C3: /* I2C3 */ + /* support pinmux_config of 0 for now */ + if (config == FUNCMUX_I2C3_DTF) { + pinmux_set_func(PMUX_PINGRP_DTF, PMUX_FUNC_I2C3); + pinmux_tristate_disable(PMUX_PINGRP_DTF); + } + break; + + case PERIPH_ID_SDMMC1: + if (config == FUNCMUX_SDMMC1_SDIO1_4BIT) { + pinmux_set_func(PMUX_PINGRP_SDIO1, PMUX_FUNC_SDIO1); + pinmux_tristate_disable(PMUX_PINGRP_SDIO1); + } + break; + + case PERIPH_ID_SDMMC2: + if (config == FUNCMUX_SDMMC2_DTA_DTD_8BIT) { + pinmux_set_func(PMUX_PINGRP_DTA, PMUX_FUNC_SDIO2); + pinmux_set_func(PMUX_PINGRP_DTD, PMUX_FUNC_SDIO2); + + pinmux_tristate_disable(PMUX_PINGRP_DTA); + pinmux_tristate_disable(PMUX_PINGRP_DTD); + } + break; + + case PERIPH_ID_SDMMC3: + switch (config) { + case FUNCMUX_SDMMC3_SDB_SLXA_8BIT: + pinmux_set_func(PMUX_PINGRP_SLXA, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SLXC, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SLXD, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SLXK, PMUX_FUNC_SDIO3); + + pinmux_tristate_disable(PMUX_PINGRP_SLXA); + pinmux_tristate_disable(PMUX_PINGRP_SLXC); + pinmux_tristate_disable(PMUX_PINGRP_SLXD); + pinmux_tristate_disable(PMUX_PINGRP_SLXK); + /* fall through */ + + case FUNCMUX_SDMMC3_SDB_4BIT: + pinmux_set_func(PMUX_PINGRP_SDB, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SDC, PMUX_FUNC_SDIO3); + pinmux_set_func(PMUX_PINGRP_SDD, PMUX_FUNC_SDIO3); + + pinmux_tristate_disable(PMUX_PINGRP_SDB); + pinmux_tristate_disable(PMUX_PINGRP_SDC); + pinmux_tristate_disable(PMUX_PINGRP_SDD); + bad_config = 0; + break; + } + break; + + case PERIPH_ID_SDMMC4: + switch (config) { + case FUNCMUX_SDMMC4_ATC_ATD_8BIT: + pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_SDIO4); + pinmux_set_func(PMUX_PINGRP_ATD, PMUX_FUNC_SDIO4); + + pinmux_tristate_disable(PMUX_PINGRP_ATC); + pinmux_tristate_disable(PMUX_PINGRP_ATD); + break; + + case FUNCMUX_SDMMC4_ATB_GMA_GME_8_BIT: + pinmux_set_func(PMUX_PINGRP_GME, PMUX_FUNC_SDIO4); + pinmux_tristate_disable(PMUX_PINGRP_GME); + /* fall through */ + + case FUNCMUX_SDMMC4_ATB_GMA_4_BIT: + pinmux_set_func(PMUX_PINGRP_ATB, PMUX_FUNC_SDIO4); + pinmux_set_func(PMUX_PINGRP_GMA, PMUX_FUNC_SDIO4); + + pinmux_tristate_disable(PMUX_PINGRP_ATB); + pinmux_tristate_disable(PMUX_PINGRP_GMA); + bad_config = 0; + break; + } + break; + + case PERIPH_ID_KBC: + if (config == FUNCMUX_DEFAULT) { + enum pmux_pingrp grp[] = {PMUX_PINGRP_KBCA, + PMUX_PINGRP_KBCB, PMUX_PINGRP_KBCC, + PMUX_PINGRP_KBCD, PMUX_PINGRP_KBCE, + PMUX_PINGRP_KBCF}; + int i; + + for (i = 0; i < ARRAY_SIZE(grp); i++) { + pinmux_tristate_disable(grp[i]); + pinmux_set_func(grp[i], PMUX_FUNC_KBC); + pinmux_set_pullupdown(grp[i], PMUX_PULL_UP); + } + } + break; + + case PERIPH_ID_USB2: + if (config == FUNCMUX_USB2_ULPI) { + pinmux_set_func(PMUX_PINGRP_UAA, PMUX_FUNC_ULPI); + pinmux_set_func(PMUX_PINGRP_UAB, PMUX_FUNC_ULPI); + pinmux_set_func(PMUX_PINGRP_UDA, PMUX_FUNC_ULPI); + + pinmux_tristate_disable(PMUX_PINGRP_UAA); + pinmux_tristate_disable(PMUX_PINGRP_UAB); + pinmux_tristate_disable(PMUX_PINGRP_UDA); + } + break; + + case PERIPH_ID_SPI1: + if (config == FUNCMUX_SPI1_GMC_GMD) { + pinmux_set_func(PMUX_PINGRP_GMC, PMUX_FUNC_SFLASH); + pinmux_set_func(PMUX_PINGRP_GMD, PMUX_FUNC_SFLASH); + + pinmux_tristate_disable(PMUX_PINGRP_GMC); + pinmux_tristate_disable(PMUX_PINGRP_GMD); + } + break; + + case PERIPH_ID_NDFLASH: + switch (config) { + case FUNCMUX_NDFLASH_ATC: + pinmux_set_func(PMUX_PINGRP_ATC, PMUX_FUNC_NAND); + pinmux_tristate_disable(PMUX_PINGRP_ATC); + break; + case FUNCMUX_NDFLASH_KBC_8_BIT: + pinmux_set_func(PMUX_PINGRP_KBCA, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCB, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCC, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCD, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCE, PMUX_FUNC_NAND); + pinmux_set_func(PMUX_PINGRP_KBCF, PMUX_FUNC_NAND); + + pinmux_tristate_disable(PMUX_PINGRP_KBCA); + pinmux_tristate_disable(PMUX_PINGRP_KBCB); + pinmux_tristate_disable(PMUX_PINGRP_KBCC); + pinmux_tristate_disable(PMUX_PINGRP_KBCD); + pinmux_tristate_disable(PMUX_PINGRP_KBCE); + pinmux_tristate_disable(PMUX_PINGRP_KBCF); + + bad_config = 0; + break; + } + break; + case PERIPH_ID_DISP1: + if (config == FUNCMUX_DEFAULT) { + int i; + + for (i = PMUX_PINGRP_LD0; i <= PMUX_PINGRP_LD17; i++) { + pinmux_set_func(i, PMUX_FUNC_DISPA); + pinmux_tristate_disable(i); + pinmux_set_pullupdown(i, PMUX_PULL_NORMAL); + } + pinmux_config_pingrp_table(disp1_default, + ARRAY_SIZE(disp1_default)); + } + break; + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + + return 0; +} diff --git a/drivers/pinctrl/tegra/funcmux-tegra210.c b/drivers/pinctrl/tegra/funcmux-tegra210.c new file mode 100644 index 0000000..30d994a --- /dev/null +++ b/drivers/pinctrl/tegra/funcmux-tegra210.c @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2013-2015 + * NVIDIA Corporation <www.nvidia.com> + */ + +/* Tegra210 high-level function multiplexing */ + +#include <common.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + /* + * Add other periph IDs here as needed. + * Note that all pinmux/pads should have already + * been set up in the board pinmux table in + * pinmux-config-<board>.h for all periphs. + * Leave this in for the odd case where a mux + * needs to be changed on-the-fly. + */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/drivers/pinctrl/tegra/funcmux-tegra30.c b/drivers/pinctrl/tegra/funcmux-tegra30.c new file mode 100644 index 0000000..c3ee787 --- /dev/null +++ b/drivers/pinctrl/tegra/funcmux-tegra30.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2010-2012, NVIDIA CORPORATION. All rights reserved. + */ + +/* Tegra30 high-level function multiplexing */ + +#include <common.h> +#include <log.h> +#include <asm/arch/clock.h> +#include <asm/arch/funcmux.h> +#include <asm/arch/pinmux.h> + +int funcmux_select(enum periph_id id, int config) +{ + int bad_config = config != FUNCMUX_DEFAULT; + + switch (id) { + case PERIPH_ID_UART1: + switch (config) { + case FUNCMUX_UART1_ULPI: + pinmux_set_func(PMUX_PINGRP_ULPI_DATA0_PO1, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_ULPI_DATA1_PO2, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_ULPI_DATA2_PO3, + PMUX_FUNC_UARTA); + pinmux_set_func(PMUX_PINGRP_ULPI_DATA3_PO4, + PMUX_FUNC_UARTA); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA0_PO1); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA1_PO2); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA2_PO3); + pinmux_tristate_disable(PMUX_PINGRP_ULPI_DATA3_PO4); + break; + } + break; + + /* Add other periph IDs here as needed */ + + default: + debug("%s: invalid periph_id %d", __func__, id); + return -1; + } + + if (bad_config) { + debug("%s: invalid config %d for periph_id %d", __func__, + config, id); + return -1; + } + return 0; +} diff --git a/drivers/pinctrl/tegra/pinctrl-tegra.c b/drivers/pinctrl/tegra/pinctrl-tegra.c new file mode 100644 index 0000000..ad7112a --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra.c @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2023 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/pinctrl.h> +#include <stdlib.h> + +#include <asm/arch/pinmux.h> + +static void tegra_pinctrl_set_drive(struct udevice *config, int drvcnt) +{ + struct pmux_drvgrp_config *drive_group; + int i, ret, pad_id; + const char **pads; + + drive_group = kmalloc_array(drvcnt, sizeof(*drive_group), GFP_KERNEL); + if (!drive_group) { + log_debug("%s: cannot allocate drive group array\n", __func__); + return; + } + + drive_group[0].slwf = dev_read_u32_default(config, "nvidia,slew-rate-falling", 0); + drive_group[0].slwr = dev_read_u32_default(config, "nvidia,slew-rate-rising", 0); + drive_group[0].drvup = dev_read_u32_default(config, "nvidia,pull-up-strength", 0); + drive_group[0].drvdn = dev_read_u32_default(config, "nvidia,pull-down-strength", 0); +#ifdef TEGRA_PMX_GRPS_HAVE_LPMD + drive_group[0].lpmd = dev_read_u32_default(config, "nvidia,low-power-mode", 0); +#endif +#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT + drive_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0); +#endif +#ifdef TEGRA_PMX_GRPS_HAVE_HSM + drive_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0); +#endif + + for (i = 1; i < drvcnt; i++) + memcpy(&drive_group[i], &drive_group[0], sizeof(drive_group[0])); + + ret = dev_read_string_list(config, "nvidia,pins", &pads); + if (ret < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + goto exit; + } + + for (i = 0; i < drvcnt; i++) { + for (pad_id = 0; pad_id < PMUX_DRVGRP_COUNT; pad_id++) + if (tegra_pinctrl_to_drvgrp[pad_id]) + if (!strcmp(pads[i], tegra_pinctrl_to_drvgrp[pad_id])) { + drive_group[i].drvgrp = pad_id; + break; + } + + debug("%s drvmap: %d, %d, %d, %d, %d\n", pads[i], + drive_group[i].drvgrp, drive_group[i].slwf, + drive_group[i].slwr, drive_group[i].drvup, + drive_group[i].drvdn); + } + + pinmux_config_drvgrp_table(drive_group, drvcnt); + + free(pads); +exit: + kfree(drive_group); +} + +static void tegra_pinctrl_set_pin(struct udevice *config, int pincnt) +{ + struct pmux_pingrp_config *pinmux_group; + int i, ret, pin_id; + const char *function; + const char **pins; + + pinmux_group = kmalloc_array(pincnt, sizeof(*pinmux_group), GFP_KERNEL); + if (!pinmux_group) { + log_debug("%s: cannot allocate pinmux group array\n", __func__); + return; + } + + /* decode function id and fill the first copy of pmux_pingrp_config */ + function = dev_read_string(config, "nvidia,function"); + if (function) + for (i = 0; i < PMUX_FUNC_COUNT; i++) + if (tegra_pinctrl_to_func[i]) + if (!strcmp(function, tegra_pinctrl_to_func[i])) + break; + + pinmux_group[0].func = i; + + pinmux_group[0].pull = dev_read_u32_default(config, "nvidia,pull", 0); + pinmux_group[0].tristate = dev_read_u32_default(config, "nvidia,tristate", 0); +#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT + pinmux_group[0].io = dev_read_u32_default(config, "nvidia,enable-input", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_LOCK + pinmux_group[0].lock = dev_read_u32_default(config, "nvidia,lock", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_OD + pinmux_group[0].od = dev_read_u32_default(config, "nvidia,open-drain", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET + pinmux_group[0].ioreset = dev_read_u32_default(config, "nvidia,io-reset", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL + pinmux_group[0].rcv_sel = dev_read_u32_default(config, "nvidia,rcv-sel", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV + pinmux_group[0].e_io_hv = dev_read_u32_default(config, "nvidia,io-hv", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_SCHMT + pinmux_group[0].schmt = dev_read_u32_default(config, "nvidia,schmitt", 0); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_HSM + pinmux_group[0].hsm = dev_read_u32_default(config, "nvidia,high-speed-mode", 0); +#endif + + for (i = 1; i < pincnt; i++) + memcpy(&pinmux_group[i], &pinmux_group[0], sizeof(pinmux_group[0])); + + ret = dev_read_string_list(config, "nvidia,pins", &pins); + if (ret < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + goto exit; + } + + for (i = 0; i < pincnt; i++) { + for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++) + if (tegra_pinctrl_to_pingrp[pin_id]) + if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id])) { + pinmux_group[i].pingrp = pin_id; + break; + } + + debug("%s pinmap: %d, %d, %d, %d\n", pins[i], + pinmux_group[i].pingrp, pinmux_group[i].func, + pinmux_group[i].pull, pinmux_group[i].tristate); + } + + pinmux_config_pingrp_table(pinmux_group, pincnt); + + free(pins); +exit: + kfree(pinmux_group); +} + +static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + struct udevice *child; + int ret; + const char *name; + + device_foreach_child(child, config) { + /* Pinmux node can contain pins and drives */ + ret = dev_read_string_index(child, "nvidia,pins", 0, + &name); + if (ret < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + return ret; + } + + ret = dev_read_string_count(child, "nvidia,pins"); + if (ret < 0) { + log_debug("%s: could not count nvidia,pins\n", __func__); + return ret; + } + + if (!strncmp(name, "drive_", 6)) + /* Drive node is detected */ + tegra_pinctrl_set_drive(child, ret); + else + /* Pin node is detected */ + tegra_pinctrl_set_pin(child, ret); + } + + return 0; +} + +static int tegra_pinctrl_get_pins_count(struct udevice *dev) +{ + return PMUX_PINGRP_COUNT; +} + +static const char *tegra_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + return tegra_pinctrl_to_pingrp[selector]; +} + +static int tegra_pinctrl_get_groups_count(struct udevice *dev) +{ + return PMUX_DRVGRP_COUNT; +} + +static const char *tegra_pinctrl_get_group_name(struct udevice *dev, + unsigned int selector) +{ + return tegra_pinctrl_to_drvgrp[selector]; +} + +static int tegra_pinctrl_get_functions_count(struct udevice *dev) +{ + return PMUX_FUNC_COUNT; +} + +static const char *tegra_pinctrl_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return tegra_pinctrl_to_func[selector]; +} + +const struct pinctrl_ops tegra_pinctrl_ops = { + .get_pins_count = tegra_pinctrl_get_pins_count, + .get_pin_name = tegra_pinctrl_get_pin_name, + .get_groups_count = tegra_pinctrl_get_groups_count, + .get_group_name = tegra_pinctrl_get_group_name, + .get_functions_count = tegra_pinctrl_get_functions_count, + .get_function_name = tegra_pinctrl_get_function_name, + .set_state = tegra_pinctrl_set_state, +}; + +static int tegra_pinctrl_bind(struct udevice *dev) +{ + /* + * Make sure that the pinctrl driver gets probed after binding + * to provide initial configuration and assure that further + * probed devices are working correctly. + */ + dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND); + + return 0; +} + +static const struct udevice_id tegra_pinctrl_ids[] = { + { .compatible = "nvidia,tegra30-pinmux" }, + { .compatible = "nvidia,tegra114-pinmux" }, + { }, +}; + +U_BOOT_DRIVER(tegra_pinctrl) = { + .name = "tegra_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = tegra_pinctrl_ids, + .bind = tegra_pinctrl_bind, + .ops = &tegra_pinctrl_ops, +}; diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c new file mode 100644 index 0000000..d5171b8 --- /dev/null +++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2023 + * Svyatoslav Ryhel <clamor95@gmail.com> + */ + +#include <dm.h> +#include <dm/device_compat.h> +#include <dm/pinctrl.h> +#include <stdlib.h> + +#include <asm/arch/pinmux.h> + +static void tegra_pinctrl_set_pin(struct udevice *config) +{ + int i, count, pin_id, ret; + int pull, tristate; + const char **pins; + + ret = dev_read_u32(config, "nvidia,pull", &pull); + if (ret) + pull = ret; + + ret = dev_read_u32(config, "nvidia,tristate", &tristate); + if (ret) + tristate = ret; + + count = dev_read_string_list(config, "nvidia,pins", &pins); + if (count < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + return; + } + + for (i = 0; i < count; i++) { + for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++) + if (tegra_pinctrl_to_pingrp[pin_id]) + if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id])) + break; + + if (pull >= 0) + pinmux_set_pullupdown(pin_id, pull); + + if (tristate >= 0) { + if (!tristate) + pinmux_tristate_disable(pin_id); + else + pinmux_tristate_enable(pin_id); + } + } + + free(pins); +} + +static void tegra_pinctrl_set_func(struct udevice *config) +{ + int i, count, func_id, pin_id; + const char *function; + const char **pins; + + function = dev_read_string(config, "nvidia,function"); + if (function) + for (i = 0; i < PMUX_FUNC_COUNT; i++) + if (tegra_pinctrl_to_func[i]) + if (!strcmp(function, tegra_pinctrl_to_func[i])) + break; + + func_id = i; + + count = dev_read_string_list(config, "nvidia,pins", &pins); + if (count < 0) { + log_debug("%s: could not parse property nvidia,pins\n", __func__); + return; + } + + for (i = 0; i < count; i++) { + for (pin_id = 0; pin_id < PMUX_PINGRP_COUNT; pin_id++) + if (tegra_pinctrl_to_pingrp[pin_id]) + if (!strcmp(pins[i], tegra_pinctrl_to_pingrp[pin_id])) + break; + + debug("%s(%d) muxed to %s(%d)\n", pins[i], pin_id, function, func_id); + + pinmux_set_func(pin_id, func_id); + } + + free(pins); +} + +static int tegra_pinctrl_set_state(struct udevice *dev, struct udevice *config) +{ + struct udevice *child; + + device_foreach_child(child, config) { + /* + * Tegra20 pinmux is set differently then any other + * Tegra SOC. Nodes are arranged by function muxing, + * then actual pins setup (with node name prefix + * conf_*) and then drive setup. + */ + if (!strncmp(child->name, "conf_", 5)) + tegra_pinctrl_set_pin(child); + else if (!strncmp(child->name, "drive_", 6)) + debug("%s: drive configuration is not supported\n", __func__); + else + tegra_pinctrl_set_func(child); + } + + return 0; +} + +static int tegra_pinctrl_get_pins_count(struct udevice *dev) +{ + return PMUX_PINGRP_COUNT; +} + +static const char *tegra_pinctrl_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + return tegra_pinctrl_to_pingrp[selector]; +} + +static int tegra_pinctrl_get_groups_count(struct udevice *dev) +{ + return PMUX_DRVGRP_COUNT; +} + +static const char *tegra_pinctrl_get_group_name(struct udevice *dev, + unsigned int selector) +{ + return tegra_pinctrl_to_drvgrp[selector]; +} + +static int tegra_pinctrl_get_functions_count(struct udevice *dev) +{ + return PMUX_FUNC_COUNT; +} + +static const char *tegra_pinctrl_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return tegra_pinctrl_to_func[selector]; +} + +const struct pinctrl_ops tegra_pinctrl_ops = { + .get_pins_count = tegra_pinctrl_get_pins_count, + .get_pin_name = tegra_pinctrl_get_pin_name, + .get_groups_count = tegra_pinctrl_get_groups_count, + .get_group_name = tegra_pinctrl_get_group_name, + .get_functions_count = tegra_pinctrl_get_functions_count, + .get_function_name = tegra_pinctrl_get_function_name, + .set_state = tegra_pinctrl_set_state, +}; + +static int tegra_pinctrl_bind(struct udevice *dev) +{ + /* + * Make sure that the pinctrl driver gets probed after binding + * to provide initial configuration and assure that further + * probed devices are working correctly. + */ + dev_or_flags(dev, DM_FLAG_PROBE_AFTER_BIND); + + return 0; +} + +static const struct udevice_id tegra_pinctrl_ids[] = { + { .compatible = "nvidia,tegra20-pinmux" }, + { }, +}; + +U_BOOT_DRIVER(tegra_pinctrl) = { + .name = "tegra_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = tegra_pinctrl_ids, + .bind = tegra_pinctrl_bind, + .ops = &tegra_pinctrl_ops, +}; diff --git a/drivers/pinctrl/tegra/pinmux-common.c b/drivers/pinctrl/tegra/pinmux-common.c new file mode 100644 index 0000000..16b03bf --- /dev/null +++ b/drivers/pinctrl/tegra/pinmux-common.c @@ -0,0 +1,755 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2010-2013, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2011 The Chromium OS Authors. + */ + +#include <common.h> +#include <log.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +/* return 1 if a pingrp is in range */ +#define pmux_pingrp_isvalid(pin) (((pin) >= 0) && ((pin) < PMUX_PINGRP_COUNT)) + +/* return 1 if a pmux_func is in range */ +#define pmux_func_isvalid(func) \ + (((func) >= 0) && ((func) < PMUX_FUNC_COUNT)) + +/* return 1 if a pin_pupd_is in range */ +#define pmux_pin_pupd_isvalid(pupd) \ + (((pupd) >= PMUX_PULL_NORMAL) && ((pupd) <= PMUX_PULL_UP)) + +/* return 1 if a pin_tristate_is in range */ +#define pmux_pin_tristate_isvalid(tristate) \ + (((tristate) >= PMUX_TRI_NORMAL) && ((tristate) <= PMUX_TRI_TRISTATE)) + +#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT +/* return 1 if a pin_io_is in range */ +#define pmux_pin_io_isvalid(io) \ + (((io) >= PMUX_PIN_OUTPUT) && ((io) <= PMUX_PIN_INPUT)) +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_LOCK +/* return 1 if a pin_lock is in range */ +#define pmux_pin_lock_isvalid(lock) \ + (((lock) >= PMUX_PIN_LOCK_DISABLE) && ((lock) <= PMUX_PIN_LOCK_ENABLE)) +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_OD +/* return 1 if a pin_od is in range */ +#define pmux_pin_od_isvalid(od) \ + (((od) >= PMUX_PIN_OD_DISABLE) && ((od) <= PMUX_PIN_OD_ENABLE)) +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET +/* return 1 if a pin_ioreset_is in range */ +#define pmux_pin_ioreset_isvalid(ioreset) \ + (((ioreset) >= PMUX_PIN_IO_RESET_DISABLE) && \ + ((ioreset) <= PMUX_PIN_IO_RESET_ENABLE)) +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL +/* return 1 if a pin_rcv_sel_is in range */ +#define pmux_pin_rcv_sel_isvalid(rcv_sel) \ + (((rcv_sel) >= PMUX_PIN_RCV_SEL_NORMAL) && \ + ((rcv_sel) <= PMUX_PIN_RCV_SEL_HIGH)) +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV +/* return 1 if a pin_e_io_hv is in range */ +#define pmux_pin_e_io_hv_isvalid(e_io_hv) \ + (((e_io_hv) >= PMUX_PIN_E_IO_HV_NORMAL) && \ + ((e_io_hv) <= PMUX_PIN_E_IO_HV_HIGH)) +#endif + +#ifdef TEGRA_PMX_GRPS_HAVE_LPMD +#define pmux_lpmd_isvalid(lpm) \ + (((lpm) >= PMUX_LPMD_X8) && ((lpm) <= PMUX_LPMD_X)) +#endif + +#if defined(TEGRA_PMX_PINS_HAVE_SCHMT) || defined(TEGRA_PMX_GRPS_HAVE_SCHMT) +#define pmux_schmt_isvalid(schmt) \ + (((schmt) >= PMUX_SCHMT_DISABLE) && ((schmt) <= PMUX_SCHMT_ENABLE)) +#endif + +#if defined(TEGRA_PMX_PINS_HAVE_HSM) || defined(TEGRA_PMX_GRPS_HAVE_HSM) +#define pmux_hsm_isvalid(hsm) \ + (((hsm) >= PMUX_HSM_DISABLE) && ((hsm) <= PMUX_HSM_ENABLE)) +#endif + +#define _R(offset) (u32 *)((unsigned long)NV_PA_APB_MISC_BASE + (offset)) + +#if defined(CONFIG_TEGRA20) + +#define MUX_REG(grp) _R(0x80 + ((tegra_soc_pingroups[grp].ctl_id / 16) * 4)) +#define MUX_SHIFT(grp) ((tegra_soc_pingroups[grp].ctl_id % 16) * 2) + +#define PULL_REG(grp) _R(0xa0 + ((tegra_soc_pingroups[grp].pull_id / 16) * 4)) +#define PULL_SHIFT(grp) ((tegra_soc_pingroups[grp].pull_id % 16) * 2) + +#define TRI_REG(grp) _R(0x14 + (((grp) / 32) * 4)) +#define TRI_SHIFT(grp) ((grp) % 32) + +#else + +#define REG(pin) _R(0x3000 + ((pin) * 4)) + +#define MUX_REG(pin) REG(pin) +#define MUX_SHIFT(pin) 0 + +#define PULL_REG(pin) REG(pin) +#define PULL_SHIFT(pin) 2 + +#define TRI_REG(pin) REG(pin) +#define TRI_SHIFT(pin) 4 + +#endif /* CONFIG_TEGRA20 */ + +#define DRV_REG(group) _R(TEGRA_PMX_SOC_DRV_GROUP_BASE_REG + ((group) * 4)) + +#define MIPIPADCTRL_REG(group) _R(TEGRA_PMX_SOC_MIPIPADCTRL_BASE_REG + ((group) * 4)) + +/* + * We could force arch-tegraNN/pinmux.h to define all of these. However, + * that's a lot of defines, and for now it's manageable to just put a + * special case here. It's possible this decision will change with future + * SoCs. + */ +#ifdef CONFIG_TEGRA210 +#define IO_SHIFT 6 +#define LOCK_SHIFT 7 +#ifdef TEGRA_PMX_PINS_HAVE_HSM +#define HSM_SHIFT 9 +#endif +#define E_IO_HV_SHIFT 10 +#define OD_SHIFT 11 +#ifdef TEGRA_PMX_PINS_HAVE_SCHMT +#define SCHMT_SHIFT 12 +#endif +#else +#define IO_SHIFT 5 +#define OD_SHIFT 6 +#define LOCK_SHIFT 7 +#define IO_RESET_SHIFT 8 +#define RCV_SEL_SHIFT 9 +#endif + +#ifdef TEGRA_PMX_SOC_HAS_IO_CLAMPING +/* This register/field only exists on Tegra114 and later */ +#define APB_MISC_PP_PINMUX_GLOBAL_0 0x40 +#define CLAMP_INPUTS_WHEN_TRISTATED 1 + +void pinmux_set_tristate_input_clamping(void) +{ + u32 *reg = _R(APB_MISC_PP_PINMUX_GLOBAL_0); + + setbits_le32(reg, CLAMP_INPUTS_WHEN_TRISTATED); +} + +void pinmux_clear_tristate_input_clamping(void) +{ + u32 *reg = _R(APB_MISC_PP_PINMUX_GLOBAL_0); + + clrbits_le32(reg, CLAMP_INPUTS_WHEN_TRISTATED); +} +#endif + +void pinmux_set_func(enum pmux_pingrp pin, enum pmux_func func) +{ + u32 *reg = MUX_REG(pin); + int i, mux = -1; + u32 val; + + if (func == PMUX_FUNC_DEFAULT) + return; + + /* Error check on pin and func */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_func_isvalid(func)); + + if (func >= PMUX_FUNC_RSVD1) { + mux = (func - PMUX_FUNC_RSVD1) & 3; + } else { + /* Search for the appropriate function */ + for (i = 0; i < 4; i++) { + if (tegra_soc_pingroups[pin].funcs[i] == func) { + mux = i; + break; + } + } + } + assert(mux != -1); + + val = readl(reg); + val &= ~(3 << MUX_SHIFT(pin)); + val |= (mux << MUX_SHIFT(pin)); + writel(val, reg); +} + +void pinmux_set_pullupdown(enum pmux_pingrp pin, enum pmux_pull pupd) +{ + u32 *reg = PULL_REG(pin); + u32 val; + + /* Error check on pin and pupd */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_pupd_isvalid(pupd)); + + val = readl(reg); + val &= ~(3 << PULL_SHIFT(pin)); + val |= (pupd << PULL_SHIFT(pin)); + writel(val, reg); +} + +static void pinmux_set_tristate(enum pmux_pingrp pin, int tri) +{ + u32 *reg = TRI_REG(pin); + u32 val; + + /* Error check on pin */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_tristate_isvalid(tri)); + + val = readl(reg); + if (tri == PMUX_TRI_TRISTATE) + val |= (1 << TRI_SHIFT(pin)); + else + val &= ~(1 << TRI_SHIFT(pin)); + writel(val, reg); +} + +void pinmux_tristate_enable(enum pmux_pingrp pin) +{ + pinmux_set_tristate(pin, PMUX_TRI_TRISTATE); +} + +void pinmux_tristate_disable(enum pmux_pingrp pin) +{ + pinmux_set_tristate(pin, PMUX_TRI_NORMAL); +} + +#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT +void pinmux_set_io(enum pmux_pingrp pin, enum pmux_pin_io io) +{ + u32 *reg = REG(pin); + u32 val; + + if (io == PMUX_PIN_NONE) + return; + + /* Error check on pin and io */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_io_isvalid(io)); + + val = readl(reg); + if (io == PMUX_PIN_INPUT) + val |= (io & 1) << IO_SHIFT; + else + val &= ~(1 << IO_SHIFT); + writel(val, reg); +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_LOCK +static void pinmux_set_lock(enum pmux_pingrp pin, enum pmux_pin_lock lock) +{ + u32 *reg = REG(pin); + u32 val; + + if (lock == PMUX_PIN_LOCK_DEFAULT) + return; + + /* Error check on pin and lock */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_lock_isvalid(lock)); + + val = readl(reg); + if (lock == PMUX_PIN_LOCK_ENABLE) { + val |= (1 << LOCK_SHIFT); + } else { + if (val & (1 << LOCK_SHIFT)) + printf("%s: Cannot clear LOCK bit!\n", __func__); + val &= ~(1 << LOCK_SHIFT); + } + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_OD +static void pinmux_set_od(enum pmux_pingrp pin, enum pmux_pin_od od) +{ + u32 *reg = REG(pin); + u32 val; + + if (od == PMUX_PIN_OD_DEFAULT) + return; + + /* Error check on pin and od */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_od_isvalid(od)); + + val = readl(reg); + if (od == PMUX_PIN_OD_ENABLE) + val |= (1 << OD_SHIFT); + else + val &= ~(1 << OD_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET +static void pinmux_set_ioreset(enum pmux_pingrp pin, + enum pmux_pin_ioreset ioreset) +{ + u32 *reg = REG(pin); + u32 val; + + if (ioreset == PMUX_PIN_IO_RESET_DEFAULT) + return; + + /* Error check on pin and ioreset */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_ioreset_isvalid(ioreset)); + + val = readl(reg); + if (ioreset == PMUX_PIN_IO_RESET_ENABLE) + val |= (1 << IO_RESET_SHIFT); + else + val &= ~(1 << IO_RESET_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL +static void pinmux_set_rcv_sel(enum pmux_pingrp pin, + enum pmux_pin_rcv_sel rcv_sel) +{ + u32 *reg = REG(pin); + u32 val; + + if (rcv_sel == PMUX_PIN_RCV_SEL_DEFAULT) + return; + + /* Error check on pin and rcv_sel */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_rcv_sel_isvalid(rcv_sel)); + + val = readl(reg); + if (rcv_sel == PMUX_PIN_RCV_SEL_HIGH) + val |= (1 << RCV_SEL_SHIFT); + else + val &= ~(1 << RCV_SEL_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV +static void pinmux_set_e_io_hv(enum pmux_pingrp pin, + enum pmux_pin_e_io_hv e_io_hv) +{ + u32 *reg = REG(pin); + u32 val; + + if (e_io_hv == PMUX_PIN_E_IO_HV_DEFAULT) + return; + + /* Error check on pin and e_io_hv */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_pin_e_io_hv_isvalid(e_io_hv)); + + val = readl(reg); + if (e_io_hv == PMUX_PIN_E_IO_HV_HIGH) + val |= (1 << E_IO_HV_SHIFT); + else + val &= ~(1 << E_IO_HV_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_SCHMT +static void pinmux_set_schmt(enum pmux_pingrp pin, enum pmux_schmt schmt) +{ + u32 *reg = REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (schmt == PMUX_SCHMT_NONE) + return; + + /* Error check pad */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_schmt_isvalid(schmt)); + + val = readl(reg); + if (schmt == PMUX_SCHMT_ENABLE) + val |= (1 << SCHMT_SHIFT); + else + val &= ~(1 << SCHMT_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_PINS_HAVE_HSM +static void pinmux_set_hsm(enum pmux_pingrp pin, enum pmux_hsm hsm) +{ + u32 *reg = REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (hsm == PMUX_HSM_NONE) + return; + + /* Error check pad */ + assert(pmux_pingrp_isvalid(pin)); + assert(pmux_hsm_isvalid(hsm)); + + val = readl(reg); + if (hsm == PMUX_HSM_ENABLE) + val |= (1 << HSM_SHIFT); + else + val &= ~(1 << HSM_SHIFT); + writel(val, reg); + + return; +} +#endif + +static void pinmux_config_pingrp(const struct pmux_pingrp_config *config) +{ + enum pmux_pingrp pin = config->pingrp; + + pinmux_set_func(pin, config->func); + pinmux_set_pullupdown(pin, config->pull); + pinmux_set_tristate(pin, config->tristate); +#ifdef TEGRA_PMX_PINS_HAVE_E_INPUT + pinmux_set_io(pin, config->io); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_LOCK + pinmux_set_lock(pin, config->lock); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_OD + pinmux_set_od(pin, config->od); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_IO_RESET + pinmux_set_ioreset(pin, config->ioreset); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_RCV_SEL + pinmux_set_rcv_sel(pin, config->rcv_sel); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_E_IO_HV + pinmux_set_e_io_hv(pin, config->e_io_hv); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_SCHMT + pinmux_set_schmt(pin, config->schmt); +#endif +#ifdef TEGRA_PMX_PINS_HAVE_HSM + pinmux_set_hsm(pin, config->hsm); +#endif +} + +void pinmux_config_pingrp_table(const struct pmux_pingrp_config *config, + int len) +{ + int i; + + for (i = 0; i < len; i++) + pinmux_config_pingrp(&config[i]); +} + +#ifdef TEGRA_PMX_SOC_HAS_DRVGRPS + +#define pmux_drvgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_DRVGRP_COUNT)) + +#define pmux_slw_isvalid(slw) \ + (((slw) >= PMUX_SLWF_MIN) && ((slw) <= PMUX_SLWF_MAX)) + +#define pmux_drv_isvalid(drv) \ + (((drv) >= PMUX_DRVUP_MIN) && ((drv) <= PMUX_DRVUP_MAX)) + +#ifdef TEGRA_PMX_GRPS_HAVE_HSM +#define HSM_SHIFT 2 +#endif +#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT +#define SCHMT_SHIFT 3 +#endif +#ifdef TEGRA_PMX_GRPS_HAVE_LPMD +#define LPMD_SHIFT 4 +#define LPMD_MASK (3 << LPMD_SHIFT) +#endif +/* + * Note that the following DRV* and SLW* defines are accurate for many drive + * groups on many SoCs. We really need a per-group data structure to solve + * this, since the fields are in different positions/sizes in different + * registers (for different groups). + * + * On Tegra30/114/124, the DRV*_SHIFT values vary. + * On Tegra30, the SLW*_SHIFT values vary. + * On Tegra30/114/124/210, the DRV*_MASK values vary, although the values + * below are wide enough to cover the widest fields, and hopefully don't + * interfere with any other fields. + * On Tegra30, the SLW*_MASK values vary, but we can't use a value that's + * wide enough to cover all cases, since that would cause the field to + * overlap with other fields in the narrower cases. + */ +#define DRVDN_SHIFT 12 +#define DRVDN_MASK (0x7F << DRVDN_SHIFT) +#define DRVUP_SHIFT 20 +#define DRVUP_MASK (0x7F << DRVUP_SHIFT) +#define SLWR_SHIFT 28 +#define SLWR_MASK (3 << SLWR_SHIFT) +#define SLWF_SHIFT 30 +#define SLWF_MASK (3 << SLWF_SHIFT) + +static void pinmux_set_drvup_slwf(enum pmux_drvgrp grp, int slwf) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (slwf == PMUX_SLWF_NONE) + return; + + /* Error check on pad and slwf */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_slw_isvalid(slwf)); + + val = readl(reg); + val &= ~SLWF_MASK; + val |= (slwf << SLWF_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_drvdn_slwr(enum pmux_drvgrp grp, int slwr) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (slwr == PMUX_SLWR_NONE) + return; + + /* Error check on pad and slwr */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_slw_isvalid(slwr)); + + val = readl(reg); + val &= ~SLWR_MASK; + val |= (slwr << SLWR_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_drvup(enum pmux_drvgrp grp, int drvup) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (drvup == PMUX_DRVUP_NONE) + return; + + /* Error check on pad and drvup */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_drv_isvalid(drvup)); + + val = readl(reg); + val &= ~DRVUP_MASK; + val |= (drvup << DRVUP_SHIFT); + writel(val, reg); + + return; +} + +static void pinmux_set_drvdn(enum pmux_drvgrp grp, int drvdn) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (drvdn == PMUX_DRVDN_NONE) + return; + + /* Error check on pad and drvdn */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_drv_isvalid(drvdn)); + + val = readl(reg); + val &= ~DRVDN_MASK; + val |= (drvdn << DRVDN_SHIFT); + writel(val, reg); + + return; +} + +#ifdef TEGRA_PMX_GRPS_HAVE_LPMD +static void pinmux_set_lpmd(enum pmux_drvgrp grp, enum pmux_lpmd lpmd) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (lpmd == PMUX_LPMD_NONE) + return; + + /* Error check pad and lpmd value */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_lpmd_isvalid(lpmd)); + + val = readl(reg); + val &= ~LPMD_MASK; + val |= (lpmd << LPMD_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT +static void pinmux_set_schmt(enum pmux_drvgrp grp, enum pmux_schmt schmt) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (schmt == PMUX_SCHMT_NONE) + return; + + /* Error check pad */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_schmt_isvalid(schmt)); + + val = readl(reg); + if (schmt == PMUX_SCHMT_ENABLE) + val |= (1 << SCHMT_SHIFT); + else + val &= ~(1 << SCHMT_SHIFT); + writel(val, reg); + + return; +} +#endif + +#ifdef TEGRA_PMX_GRPS_HAVE_HSM +static void pinmux_set_hsm(enum pmux_drvgrp grp, enum pmux_hsm hsm) +{ + u32 *reg = DRV_REG(grp); + u32 val; + + /* NONE means unspecified/do not change/use POR value */ + if (hsm == PMUX_HSM_NONE) + return; + + /* Error check pad */ + assert(pmux_drvgrp_isvalid(grp)); + assert(pmux_hsm_isvalid(hsm)); + + val = readl(reg); + if (hsm == PMUX_HSM_ENABLE) + val |= (1 << HSM_SHIFT); + else + val &= ~(1 << HSM_SHIFT); + writel(val, reg); + + return; +} +#endif + +static void pinmux_config_drvgrp(const struct pmux_drvgrp_config *config) +{ + enum pmux_drvgrp grp = config->drvgrp; + + pinmux_set_drvup_slwf(grp, config->slwf); + pinmux_set_drvdn_slwr(grp, config->slwr); + pinmux_set_drvup(grp, config->drvup); + pinmux_set_drvdn(grp, config->drvdn); +#ifdef TEGRA_PMX_GRPS_HAVE_LPMD + pinmux_set_lpmd(grp, config->lpmd); +#endif +#ifdef TEGRA_PMX_GRPS_HAVE_SCHMT + pinmux_set_schmt(grp, config->schmt); +#endif +#ifdef TEGRA_PMX_GRPS_HAVE_HSM + pinmux_set_hsm(grp, config->hsm); +#endif +} + +void pinmux_config_drvgrp_table(const struct pmux_drvgrp_config *config, + int len) +{ + int i; + + for (i = 0; i < len; i++) + pinmux_config_drvgrp(&config[i]); +} +#endif /* TEGRA_PMX_SOC_HAS_DRVGRPS */ + +#ifdef TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS + +#define pmux_mipipadctrlgrp_isvalid(pd) (((pd) >= 0) && ((pd) < PMUX_MIPIPADCTRLGRP_COUNT)) + +static void pinmux_mipipadctrl_set_func(enum pmux_mipipadctrlgrp grp, + enum pmux_func func) +{ + u32 *reg = MIPIPADCTRL_REG(grp); + int i, mux = -1; + u32 val; + + if (func == PMUX_FUNC_DEFAULT) + return; + + /* Error check grp and func */ + assert(pmux_mipipadctrlgrp_isvalid(grp)); + assert(pmux_func_isvalid(func)); + + if (func >= PMUX_FUNC_RSVD1) { + mux = (func - PMUX_FUNC_RSVD1) & 1; + } else { + /* Search for the appropriate function */ + for (i = 0; i < 2; i++) { + if (tegra_soc_mipipadctrl_groups[grp].funcs[i] + == func) { + mux = i; + break; + } + } + } + assert(mux != -1); + + val = readl(reg); + val &= ~(1 << 1); + val |= (mux << 1); + writel(val, reg); +} + +static void pinmux_config_mipipadctrlgrp(const struct pmux_mipipadctrlgrp_config *config) +{ + enum pmux_mipipadctrlgrp grp = config->grp; + + pinmux_mipipadctrl_set_func(grp, config->func); +} + +void pinmux_config_mipipadctrlgrp_table( + const struct pmux_mipipadctrlgrp_config *config, int len) +{ + int i; + + for (i = 0; i < len; i++) + pinmux_config_mipipadctrlgrp(&config[i]); +} +#endif /* TEGRA_PMX_SOC_HAS_MIPI_PAD_CTRL_GRPS */ diff --git a/drivers/pinctrl/tegra/pinmux-tegra114.c b/drivers/pinctrl/tegra/pinmux-tegra114.c new file mode 100644 index 0000000..1179660 --- /dev/null +++ b/drivers/pinctrl/tegra/pinmux-tegra114.c @@ -0,0 +1,292 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra114_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_CLK_PY0, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_DIR_PY1, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_NXT_PY2, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_STP_PY3, SPI1, SPI5, UARTD, ULPI), + PIN(DAP3_FS_PP0, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DIN_PP1, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DOUT_PP2, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_SCLK_PP3, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(PV0, USB, RSVD2, RSVD3, RSVD4), + PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_CLK_PZ0, SDMMC1, CLK12, RSVD3, RSVD4), + PIN(SDMMC1_CMD_PZ1, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT3_PY4, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT2_PY5, SDMMC1, PWM0, SPI4, UARTA), + PIN(SDMMC1_DAT1_PY6, SDMMC1, PWM1, SPI4, UARTA), + PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, SPI4, UARTA), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3068 */ + PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4), + PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3110 */ + PIN(HDMI_INT_PN7, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4), + PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3164 */ + PIN(UART2_RXD_PC3, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_TXD_PC2, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_RTS_N_PJ6, UARTA, UARTB, RSVD3, SPI4), + PIN(UART2_CTS_N_PJ5, UARTA, UARTB, RSVD3, SPI4), + PIN(UART3_TXD_PW6, UARTC, RSVD2, RSVD3, SPI4), + PIN(UART3_RXD_PW7, UARTC, RSVD2, RSVD3, SPI4), + PIN(UART3_CTS_N_PA1, UARTC, SDMMC1, DTV, SPI4), + PIN(UART3_RTS_N_PC0, UARTC, PWM0, DTV, DISPLAYA), + PIN(PU0, OWR, UARTA, RSVD3, RSVD4), + PIN(PU1, RSVD1, UARTA, RSVD3, RSVD4), + PIN(PU2, RSVD1, UARTA, RSVD3, RSVD4), + PIN(PU3, PWM0, UARTA, DISPLAYA, DISPLAYB), + PIN(PU4, PWM1, UARTA, DISPLAYA, DISPLAYB), + PIN(PU5, PWM2, UARTA, DISPLAYA, DISPLAYB), + PIN(PU6, PWM3, UARTA, USB, DISPLAYB), + PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4), + PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4), + PIN(DAP4_FS_PP4, I2S3, RSVD2, DTV, RSVD4), + PIN(DAP4_DIN_PP5, I2S3, RSVD2, RSVD3, RSVD4), + PIN(DAP4_DOUT_PP6, I2S3, RSVD2, DTV, RSVD4), + PIN(DAP4_SCLK_PP7, I2S3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4), + PIN(GMI_WP_N_PC7, RSVD1, NAND, GMI, GMI_ALT), + PIN(GMI_IORDY_PI5, SDMMC2, RSVD2, GMI, TRACE), + PIN(GMI_WAIT_PI7, SPI4, NAND, GMI, DTV), + PIN(GMI_ADV_N_PK0, RSVD1, NAND, GMI, TRACE), + PIN(GMI_CLK_PK1, SDMMC2, NAND, GMI, TRACE), + PIN(GMI_CS0_N_PJ0, RSVD1, NAND, GMI, USB), + PIN(GMI_CS1_N_PJ2, RSVD1, NAND, GMI, SOC), + PIN(GMI_CS2_N_PK3, SDMMC2, NAND, GMI, TRACE), + PIN(GMI_CS3_N_PK4, SDMMC2, NAND, GMI, GMI_ALT), + PIN(GMI_CS4_N_PK2, USB, NAND, GMI, TRACE), + PIN(GMI_CS6_N_PI3, NAND, NAND_ALT, GMI, SPI4), + PIN(GMI_CS7_N_PI6, NAND, NAND_ALT, GMI, SDMMC2), + PIN(GMI_AD0_PG0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD1_PG1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD2_PG2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD3_PG3, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD4_PG4, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD5_PG5, RSVD1, NAND, GMI, SPI4), + PIN(GMI_AD6_PG6, RSVD1, NAND, GMI, SPI4), + PIN(GMI_AD7_PG7, RSVD1, NAND, GMI, SPI4), + PIN(GMI_AD8_PH0, PWM0, NAND, GMI, DTV), + PIN(GMI_AD9_PH1, PWM1, NAND, GMI, CLDVFS), + PIN(GMI_AD10_PH2, PWM2, NAND, GMI, CLDVFS), + PIN(GMI_AD11_PH3, PWM3, NAND, GMI, USB), + PIN(GMI_AD12_PH4, SDMMC2, NAND, GMI, RSVD4), + PIN(GMI_AD13_PH5, SDMMC2, NAND, GMI, RSVD4), + PIN(GMI_AD14_PH6, SDMMC2, NAND, GMI, DTV), + PIN(GMI_AD15_PH7, SDMMC2, NAND, GMI, DTV), + PIN(GMI_A16_PJ7, UARTD, TRACE, GMI, GMI_ALT), + PIN(GMI_A17_PB0, UARTD, RSVD2, GMI, TRACE), + PIN(GMI_A18_PB1, UARTD, RSVD2, GMI, TRACE), + PIN(GMI_A19_PK7, UARTD, SPI4, GMI, TRACE), + PIN(GMI_WR_N_PI0, RSVD1, NAND, GMI, SPI4), + PIN(GMI_OE_N_PI1, RSVD1, NAND, GMI, SOC), + PIN(GMI_DQS_P_PJ3, SDMMC2, NAND, GMI, TRACE), + PIN(GMI_RST_N_PI4, NAND, NAND_ALT, GMI, RSVD4), + PIN(GEN2_I2C_SCL_PT5, I2C2, RSVD2, GMI, RSVD4), + PIN(GEN2_I2C_SDA_PT6, I2C2, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CLK_PCC4, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CMD_PT7, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_DAT0_PAA0, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT1_PAA1, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT2_PAA2, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT3_PAA3, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT4_PAA4, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT5_PAA5, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT6_PAA6, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT7_PAA7, SDMMC4, RSVD2, GMI, RSVD4), + PIN_RESERVED, + /* Offset 0x3284 */ + PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, RSVD4), + PIN(PCC1, I2S4, RSVD2, RSVD3, RSVD4), + PIN(PBB0, I2S4, VI, VI_ALT1, VI_ALT3), + PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, RSVD4), + PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, RSVD4), + PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB5, VGP5, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB6, VGP6, DISPLAYA, DISPLAYB, RSVD4), + PIN(PBB7, I2S4, RSVD2, RSVD3, RSVD4), + PIN(PCC2, I2S4, RSVD2, RSVD3, RSVD4), + PIN(JTAG_RTCK, RTCK, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW0_PR0, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW1_PR1, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW2_PR2, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW3_PR3, KBC, DISPLAYA, RSVD3, DISPLAYB), + PIN(KB_ROW4_PR4, KBC, DISPLAYA, SPI2, DISPLAYB), + PIN(KB_ROW5_PR5, KBC, DISPLAYA, SPI2, DISPLAYB), + PIN(KB_ROW6_PR6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB), + PIN(KB_ROW7_PR7, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW8_PS0, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW9_PS1, KBC, RSVD2, RSVD3, UARTA), + PIN(KB_ROW10_PS2, KBC, RSVD2, RSVD3, UARTA), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x32fc */ + PIN(KB_COL0_PQ0, KBC, USB, SPI2, EMC_DLL), + PIN(KB_COL1_PQ1, KBC, RSVD2, SPI2, EMC_DLL), + PIN(KB_COL2_PQ2, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL3_PQ3, KBC, DISPLAYA, PWM2, UARTA), + PIN(KB_COL4_PQ4, KBC, OWR, SDMMC3, UARTA), + PIN(KB_COL5_PQ5, KBC, RSVD2, SDMMC1, RSVD4), + PIN(KB_COL6_PQ6, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL7_PQ7, KBC, RSVD2, SPI2, RSVD4), + PIN(CLK_32K_OUT_PA0, BLINK, SOC, RSVD3, RSVD4), + PIN(SYS_CLK_REQ_PZ5, SYSCLK, RSVD2, RSVD3, RSVD4), + PIN(CORE_PWR_REQ, PWRON, RSVD2, RSVD3, RSVD4), + PIN(CPU_PWR_REQ, CPU, RSVD2, RSVD3, RSVD4), + PIN(PWR_INT_N, PMI, RSVD2, RSVD3, RSVD4), + PIN(CLK_32K_IN, CLK, RSVD2, RSVD3, RSVD4), + PIN(OWR, OWR, RSVD2, RSVD3, RSVD4), + PIN(DAP1_FS_PN0, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, RSVD4), + PIN(CLK1_REQ_PEE2, DAP, DAP1, RSVD3, RSVD4), + PIN(CLK1_OUT_PW4, EXTPERIPH1, DAP2, RSVD3, RSVD4), + PIN(SPDIF_IN_PK6, SPDIF, USB, RSVD3, RSVD4), + PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, RSVD3, RSVD4), + PIN(DAP2_FS_PA2, I2S1, HDA, RSVD3, RSVD4), + PIN(DAP2_DIN_PA4, I2S1, HDA, RSVD3, RSVD4), + PIN(DAP2_DOUT_PA5, I2S1, HDA, RSVD3, RSVD4), + PIN(DAP2_SCLK_PA3, I2S1, HDA, RSVD3, RSVD4), + PIN(DVFS_PWM_PX0, SPI6, CLDVFS, RSVD3, RSVD4), + PIN(GPIO_X1_AUD_PX1, SPI6, RSVD2, RSVD3, RSVD4), + PIN(GPIO_X3_AUD_PX3, SPI6, SPI1, RSVD3, RSVD4), + PIN(DVFS_CLK_PX2, SPI6, CLDVFS, RSVD3, RSVD4), + PIN(GPIO_X4_AUD_PX4, RSVD1, SPI1, SPI2, DAP2), + PIN(GPIO_X5_AUD_PX5, RSVD1, SPI1, SPI2, RSVD4), + PIN(GPIO_X6_AUD_PX6, SPI6, SPI1, SPI2, RSVD4), + PIN(GPIO_X7_AUD_PX7, RSVD1, SPI1, SPI2, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3390 */ + PIN(SDMMC3_CLK_PA6, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_CMD_PA7, SDMMC3, PWM3, UARTA, SPI3), + PIN(SDMMC3_DAT0_PB7, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_DAT1_PB6, SDMMC3, PWM2, UARTA, SPI3), + PIN(SDMMC3_DAT2_PB5, SDMMC3, PWM1, DISPLAYA, SPI3), + PIN(SDMMC3_DAT3_PB4, SDMMC3, PWM0, DISPLAYB, SPI3), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x33e0 */ + PIN(HDMI_CEC_PEE3, CEC, SDMMC3, RSVD3, SOC), + PIN(SDMMC1_WP_N_PV3, SDMMC1, CLK12, SPI4, UARTA), + PIN(SDMMC3_CD_N_PV2, SDMMC3, OWR, RSVD3, RSVD4), + PIN(GPIO_W2_AUD_PW2, SPI6, RSVD2, SPI2, I2C1), + PIN(GPIO_W3_AUD_PW3, SPI6, SPI1, SPI2, I2C1), + PIN(USB_VBUS_EN0_PN4, USB, RSVD2, RSVD3, RSVD4), + PIN(USB_VBUS_EN1_PN5, USB, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_IN_PEE5, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_OUT_PEE4, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(GMI_CLK_LB, SDMMC2, NAND, GMI, RSVD4), + PIN(RESET_OUT_N, RSVD1, RSVD2, RSVD3, RESET_OUT_N), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra114_pingroups; diff --git a/drivers/pinctrl/tegra/pinmux-tegra124.c b/drivers/pinctrl/tegra/pinmux-tegra124.c new file mode 100644 index 0000000..261ce64 --- /dev/null +++ b/drivers/pinctrl/tegra/pinmux-tegra124.c @@ -0,0 +1,322 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra124_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_CLK_PY0, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_DIR_PY1, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_NXT_PY2, SPI1, SPI5, UARTD, ULPI), + PIN(ULPI_STP_PY3, SPI1, SPI5, UARTD, ULPI), + PIN(DAP3_FS_PP0, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DIN_PP1, I2S2, SPI5, DISPLAYA, DISPLAYB), + PIN(DAP3_DOUT_PP2, I2S2, SPI5, DISPLAYA, RSVD4), + PIN(DAP3_SCLK_PP3, I2S2, SPI5, RSVD3, DISPLAYB), + PIN(PV0, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_CLK_PZ0, SDMMC1, CLK12, RSVD3, RSVD4), + PIN(SDMMC1_CMD_PZ1, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT3_PY4, SDMMC1, SPDIF, SPI4, UARTA), + PIN(SDMMC1_DAT2_PY5, SDMMC1, PWM0, SPI4, UARTA), + PIN(SDMMC1_DAT1_PY6, SDMMC1, PWM1, SPI4, UARTA), + PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, SPI4, UARTA), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3068 */ + PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4), + PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3110 */ + PIN(HDMI_INT_PN7, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4), + PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3164 */ + PIN(UART2_RXD_PC3, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_TXD_PC2, IRDA, SPDIF, UARTA, SPI4), + PIN(UART2_RTS_N_PJ6, UARTA, UARTB, GMI, SPI4), + PIN(UART2_CTS_N_PJ5, UARTA, UARTB, GMI, SPI4), + PIN(UART3_TXD_PW6, UARTC, RSVD2, GMI, SPI4), + PIN(UART3_RXD_PW7, UARTC, RSVD2, GMI, SPI4), + PIN(UART3_CTS_N_PA1, UARTC, SDMMC1, DTV, GMI), + PIN(UART3_RTS_N_PC0, UARTC, PWM0, DTV, GMI), + PIN(PU0, OWR, UARTA, GMI, RSVD4), + PIN(PU1, RSVD1, UARTA, GMI, RSVD4), + PIN(PU2, RSVD1, UARTA, GMI, RSVD4), + PIN(PU3, PWM0, UARTA, GMI, DISPLAYB), + PIN(PU4, PWM1, UARTA, GMI, DISPLAYB), + PIN(PU5, PWM2, UARTA, GMI, DISPLAYB), + PIN(PU6, PWM3, UARTA, RSVD3, GMI), + PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4), + PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4), + PIN(DAP4_FS_PP4, I2S3, GMI, DTV, RSVD4), + PIN(DAP4_DIN_PP5, I2S3, GMI, RSVD3, RSVD4), + PIN(DAP4_DOUT_PP6, I2S3, GMI, DTV, RSVD4), + PIN(DAP4_SCLK_PP7, I2S3, GMI, RSVD3, RSVD4), + PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4), + PIN(PC7, RSVD1, RSVD2, GMI, GMI_ALT), + PIN(PI5, SDMMC2, RSVD2, GMI, RSVD4), + PIN(PI7, RSVD1, TRACE, GMI, DTV), + PIN(PK0, RSVD1, SDMMC3, GMI, SOC), + PIN(PK1, SDMMC2, TRACE, GMI, RSVD4), + PIN(PJ0, RSVD1, RSVD2, GMI, USB), + PIN(PJ2, RSVD1, RSVD2, GMI, SOC), + PIN(PK3, SDMMC2, TRACE, GMI, CCLA), + PIN(PK4, SDMMC2, RSVD2, GMI, GMI_ALT), + PIN(PK2, RSVD1, RSVD2, GMI, RSVD4), + PIN(PI3, RSVD1, RSVD2, GMI, SPI4), + PIN(PI6, RSVD1, RSVD2, GMI, SDMMC2), + PIN(PG0, RSVD1, RSVD2, GMI, RSVD4), + PIN(PG1, RSVD1, RSVD2, GMI, RSVD4), + PIN(PG2, RSVD1, TRACE, GMI, RSVD4), + PIN(PG3, RSVD1, TRACE, GMI, RSVD4), + PIN(PG4, RSVD1, TMDS, GMI, SPI4), + PIN(PG5, RSVD1, RSVD2, GMI, SPI4), + PIN(PG6, RSVD1, RSVD2, GMI, SPI4), + PIN(PG7, RSVD1, RSVD2, GMI, SPI4), + PIN(PH0, PWM0, TRACE, GMI, DTV), + PIN(PH1, PWM1, TMDS, GMI, DISPLAYA), + PIN(PH2, PWM2, TMDS, GMI, CLDVFS), + PIN(PH3, PWM3, SPI4, GMI, CLDVFS), + PIN(PH4, SDMMC2, RSVD2, GMI, RSVD4), + PIN(PH5, SDMMC2, RSVD2, GMI, RSVD4), + PIN(PH6, SDMMC2, TRACE, GMI, DTV), + PIN(PH7, SDMMC2, TRACE, GMI, DTV), + PIN(PJ7, UARTD, RSVD2, GMI, GMI_ALT), + PIN(PB0, UARTD, RSVD2, GMI, RSVD4), + PIN(PB1, UARTD, RSVD2, GMI, RSVD4), + PIN(PK7, UARTD, RSVD2, GMI, RSVD4), + PIN(PI0, RSVD1, RSVD2, GMI, RSVD4), + PIN(PI1, RSVD1, RSVD2, GMI, RSVD4), + PIN(PI2, SDMMC2, TRACE, GMI, RSVD4), + PIN(PI4, SPI4, TRACE, GMI, DISPLAYA), + PIN(GEN2_I2C_SCL_PT5, I2C2, RSVD2, GMI, RSVD4), + PIN(GEN2_I2C_SDA_PT6, I2C2, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CLK_PCC4, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_CMD_PT7, SDMMC4, RSVD2, GMI, RSVD4), + PIN(SDMMC4_DAT0_PAA0, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT1_PAA1, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT2_PAA2, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT3_PAA3, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT4_PAA4, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT5_PAA5, SDMMC4, SPI3, RSVD3, RSVD4), + PIN(SDMMC4_DAT6_PAA6, SDMMC4, SPI3, GMI, RSVD4), + PIN(SDMMC4_DAT7_PAA7, SDMMC4, RSVD2, GMI, RSVD4), + PIN_RESERVED, + /* Offset 0x3284 */ + PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, SDMMC2), + PIN(PCC1, I2S4, RSVD2, RSVD3, SDMMC2), + PIN(PBB0, VGP6, VIMCLK2, SDMMC2, VIMCLK2_ALT), + PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, SDMMC2), + PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, SDMMC2), + PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, SDMMC2), + PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, SDMMC2), + PIN(PBB5, VGP5, DISPLAYA, RSVD3, SDMMC2), + PIN(PBB6, I2S4, RSVD2, DISPLAYB, SDMMC2), + PIN(PBB7, I2S4, RSVD2, RSVD3, SDMMC2), + PIN(PCC2, I2S4, RSVD2, SDMMC3, SDMMC2), + PIN(JTAG_RTCK, RTCK, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW0_PR0, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW1_PR1, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW2_PR2, KBC, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW3_PR3, KBC, DISPLAYA, SYS, DISPLAYB), + PIN(KB_ROW4_PR4, KBC, DISPLAYA, RSVD3, DISPLAYB), + PIN(KB_ROW5_PR5, KBC, DISPLAYA, RSVD3, DISPLAYB), + PIN(KB_ROW6_PR6, KBC, DISPLAYA, DISPLAYA_ALT, DISPLAYB), + PIN(KB_ROW7_PR7, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW8_PS0, KBC, RSVD2, CLDVFS, UARTA), + PIN(KB_ROW9_PS1, KBC, RSVD2, RSVD3, UARTA), + PIN(KB_ROW10_PS2, KBC, RSVD2, RSVD3, UARTA), + PIN(KB_ROW11_PS3, KBC, RSVD2, RSVD3, IRDA), + PIN(KB_ROW12_PS4, KBC, RSVD2, RSVD3, IRDA), + PIN(KB_ROW13_PS5, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_ROW14_PS6, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_ROW15_PS7, KBC, SOC, RSVD3, RSVD4), + PIN(KB_COL0_PQ0, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL1_PQ1, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL2_PQ2, KBC, RSVD2, SPI2, RSVD4), + PIN(KB_COL3_PQ3, KBC, DISPLAYA, PWM2, UARTA), + PIN(KB_COL4_PQ4, KBC, OWR, SDMMC3, UARTA), + PIN(KB_COL5_PQ5, KBC, RSVD2, SDMMC3, RSVD4), + PIN(KB_COL6_PQ6, KBC, RSVD2, SPI2, UARTD), + PIN(KB_COL7_PQ7, KBC, RSVD2, SPI2, UARTD), + PIN(CLK_32K_OUT_PA0, BLINK, SOC, RSVD3, RSVD4), + PIN_RESERVED, + /* Offset 0x3324 */ + PIN(CORE_PWR_REQ, PWRON, RSVD2, RSVD3, RSVD4), + PIN(CPU_PWR_REQ, CPU, RSVD2, RSVD3, RSVD4), + PIN(PWR_INT_N, PMI, RSVD2, RSVD3, RSVD4), + PIN(CLK_32K_IN, CLK, RSVD2, RSVD3, RSVD4), + PIN(OWR, OWR, RSVD2, RSVD3, RSVD4), + PIN(DAP1_FS_PN0, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, RSVD4), + PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, SATA), + PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, RSVD4), + PIN(DAP_MCLK1_REQ_PEE2, DAP, DAP1, SATA, RSVD4), + PIN(DAP_MCLK1_PW4, EXTPERIPH1, DAP2, RSVD3, RSVD4), + PIN(SPDIF_IN_PK6, SPDIF, RSVD2, RSVD3, I2C3), + PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, RSVD3, I2C3), + PIN(DAP2_FS_PA2, I2S1, HDA, GMI, RSVD4), + PIN(DAP2_DIN_PA4, I2S1, HDA, GMI, RSVD4), + PIN(DAP2_DOUT_PA5, I2S1, HDA, GMI, RSVD4), + PIN(DAP2_SCLK_PA3, I2S1, HDA, GMI, RSVD4), + PIN(DVFS_PWM_PX0, SPI6, CLDVFS, GMI, RSVD4), + PIN(GPIO_X1_AUD_PX1, SPI6, RSVD2, GMI, RSVD4), + PIN(GPIO_X3_AUD_PX3, SPI6, SPI1, GMI, RSVD4), + PIN(DVFS_CLK_PX2, SPI6, CLDVFS, GMI, RSVD4), + PIN(GPIO_X4_AUD_PX4, GMI, SPI1, SPI2, DAP2), + PIN(GPIO_X5_AUD_PX5, GMI, SPI1, SPI2, RSVD4), + PIN(GPIO_X6_AUD_PX6, SPI6, SPI1, SPI2, GMI), + PIN(GPIO_X7_AUD_PX7, RSVD1, SPI1, SPI2, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3390 */ + PIN(SDMMC3_CLK_PA6, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_CMD_PA7, SDMMC3, PWM3, UARTA, SPI3), + PIN(SDMMC3_DAT0_PB7, SDMMC3, RSVD2, RSVD3, SPI3), + PIN(SDMMC3_DAT1_PB6, SDMMC3, PWM2, UARTA, SPI3), + PIN(SDMMC3_DAT2_PB5, SDMMC3, PWM1, DISPLAYA, SPI3), + PIN(SDMMC3_DAT3_PB4, SDMMC3, PWM0, DISPLAYB, SPI3), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x33bc */ + PIN(PEX_L0_RST_N_PDD1, PE0, RSVD2, RSVD3, RSVD4), + PIN(PEX_L0_CLKREQ_N_PDD2, PE0, RSVD2, RSVD3, RSVD4), + PIN(PEX_WAKE_N_PDD3, PE, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + /* Offset 0x33cc */ + PIN(PEX_L1_RST_N_PDD5, PE1, RSVD2, RSVD3, RSVD4), + PIN(PEX_L1_CLKREQ_N_PDD6, PE1, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x33e0 */ + PIN(HDMI_CEC_PEE3, CEC, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_WP_N_PV3, SDMMC1, CLK12, SPI4, UARTA), + PIN(SDMMC3_CD_N_PV2, SDMMC3, OWR, RSVD3, RSVD4), + PIN(GPIO_W2_AUD_PW2, SPI6, RSVD2, SPI2, I2C1), + PIN(GPIO_W3_AUD_PW3, SPI6, SPI1, SPI2, I2C1), + PIN(USB_VBUS_EN0_PN4, USB, RSVD2, RSVD3, RSVD4), + PIN(USB_VBUS_EN1_PN5, USB, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_IN_PEE5, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(SDMMC3_CLK_LB_OUT_PEE4, SDMMC3, RSVD2, RSVD3, RSVD4), + PIN(GMI_CLK_LB, SDMMC2, RSVD2, GMI, RSVD4), + PIN(RESET_OUT_N, RSVD1, RSVD2, RSVD3, RESET_OUT_N), + PIN(KB_ROW16_PT0, KBC, RSVD2, RSVD3, UARTC), + PIN(KB_ROW17_PT1, KBC, RSVD2, RSVD3, UARTC), + PIN(USB_VBUS_EN2_PFF1, USB, RSVD2, RSVD3, RSVD4), + PIN(PFF2, SATA, RSVD2, RSVD3, RSVD4), + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + PIN_RESERVED, + /* Offset 0x3430 */ + PIN(DP_HPD_PFF0, DP, RSVD2, RSVD3, RSVD4), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra124_pingroups; + +#define MIPIPADCTRL_GRP(grp, f0, f1) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + }, \ + } + +#define MIPIPADCTRL_RESERVED {} + +static const struct pmux_mipipadctrlgrp_desc tegra124_mipipadctrl_groups[] = { + /* pin, f0, f1 */ + /* Offset 0x820 */ + MIPIPADCTRL_GRP(DSI_B, CSI, DSI_B), +}; +const struct pmux_mipipadctrlgrp_desc *tegra_soc_mipipadctrl_groups = tegra124_mipipadctrl_groups; diff --git a/drivers/pinctrl/tegra/pinmux-tegra20.c b/drivers/pinctrl/tegra/pinmux-tegra20.c new file mode 100644 index 0000000..0af39e7 --- /dev/null +++ b/drivers/pinctrl/tegra/pinmux-tegra20.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2011 The Chromium OS Authors. + */ + +/* Tegra20 pin multiplexing functions */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +/* + * This defines the order of the pin mux control bits in the registers. For + * some reason there is no correspendence between the tristate, pin mux and + * pullup/pulldown registers. + */ +enum pmux_ctlid { + /* 0: APB_MISC_PP_PIN_MUX_CTL_A_0 */ + MUXCTL_UAA, + MUXCTL_UAB, + MUXCTL_UAC, + MUXCTL_UAD, + MUXCTL_UDA, + MUXCTL_RESERVED5, + MUXCTL_ATE, + MUXCTL_RM, + + MUXCTL_ATB, + MUXCTL_RESERVED9, + MUXCTL_ATD, + MUXCTL_ATC, + MUXCTL_ATA, + MUXCTL_KBCF, + MUXCTL_KBCE, + MUXCTL_SDMMC1, + + /* 16: APB_MISC_PP_PIN_MUX_CTL_B_0 */ + MUXCTL_GMA, + MUXCTL_GMC, + MUXCTL_HDINT, + MUXCTL_SLXA, + MUXCTL_OWC, + MUXCTL_SLXC, + MUXCTL_SLXD, + MUXCTL_SLXK, + + MUXCTL_UCA, + MUXCTL_UCB, + MUXCTL_DTA, + MUXCTL_DTB, + MUXCTL_RESERVED28, + MUXCTL_DTC, + MUXCTL_DTD, + MUXCTL_DTE, + + /* 32: APB_MISC_PP_PIN_MUX_CTL_C_0 */ + MUXCTL_DDC, + MUXCTL_CDEV1, + MUXCTL_CDEV2, + MUXCTL_CSUS, + MUXCTL_I2CP, + MUXCTL_KBCA, + MUXCTL_KBCB, + MUXCTL_KBCC, + + MUXCTL_IRTX, + MUXCTL_IRRX, + MUXCTL_DAP1, + MUXCTL_DAP2, + MUXCTL_DAP3, + MUXCTL_DAP4, + MUXCTL_GMB, + MUXCTL_GMD, + + /* 48: APB_MISC_PP_PIN_MUX_CTL_D_0 */ + MUXCTL_GME, + MUXCTL_GPV, + MUXCTL_GPU, + MUXCTL_SPDO, + MUXCTL_SPDI, + MUXCTL_SDB, + MUXCTL_SDC, + MUXCTL_SDD, + + MUXCTL_SPIH, + MUXCTL_SPIG, + MUXCTL_SPIF, + MUXCTL_SPIE, + MUXCTL_SPID, + MUXCTL_SPIC, + MUXCTL_SPIB, + MUXCTL_SPIA, + + /* 64: APB_MISC_PP_PIN_MUX_CTL_E_0 */ + MUXCTL_LPW0, + MUXCTL_LPW1, + MUXCTL_LPW2, + MUXCTL_LSDI, + MUXCTL_LSDA, + MUXCTL_LSPI, + MUXCTL_LCSN, + MUXCTL_LDC, + + MUXCTL_LSCK, + MUXCTL_LSC0, + MUXCTL_LSC1, + MUXCTL_LHS, + MUXCTL_LVS, + MUXCTL_LM0, + MUXCTL_LM1, + MUXCTL_LVP0, + + /* 80: APB_MISC_PP_PIN_MUX_CTL_F_0 */ + MUXCTL_LD0, + MUXCTL_LD1, + MUXCTL_LD2, + MUXCTL_LD3, + MUXCTL_LD4, + MUXCTL_LD5, + MUXCTL_LD6, + MUXCTL_LD7, + + MUXCTL_LD8, + MUXCTL_LD9, + MUXCTL_LD10, + MUXCTL_LD11, + MUXCTL_LD12, + MUXCTL_LD13, + MUXCTL_LD14, + MUXCTL_LD15, + + /* 96: APB_MISC_PP_PIN_MUX_CTL_G_0 */ + MUXCTL_LD16, + MUXCTL_LD17, + MUXCTL_LHP1, + MUXCTL_LHP2, + MUXCTL_LVP1, + MUXCTL_LHP0, + MUXCTL_RESERVED102, + MUXCTL_LPP, + + MUXCTL_LDI, + MUXCTL_PMC, + MUXCTL_CRTP, + MUXCTL_PTA, + MUXCTL_RESERVED108, + MUXCTL_KBCD, + MUXCTL_GPU7, + MUXCTL_DTF, + + MUXCTL_NONE = -1, +}; + +/* + * And this defines the order of the pullup/pulldown controls which are again + * in a different order + */ +enum pmux_pullid { + /* 0: APB_MISC_PP_PULLUPDOWN_REG_A_0 */ + PUCTL_ATA, + PUCTL_ATB, + PUCTL_ATC, + PUCTL_ATD, + PUCTL_ATE, + PUCTL_DAP1, + PUCTL_DAP2, + PUCTL_DAP3, + + PUCTL_DAP4, + PUCTL_DTA, + PUCTL_DTB, + PUCTL_DTC, + PUCTL_DTD, + PUCTL_DTE, + PUCTL_DTF, + PUCTL_GPV, + + /* 16: APB_MISC_PP_PULLUPDOWN_REG_B_0 */ + PUCTL_RM, + PUCTL_I2CP, + PUCTL_PTA, + PUCTL_GPU7, + PUCTL_KBCA, + PUCTL_KBCB, + PUCTL_KBCC, + PUCTL_KBCD, + + PUCTL_SPDI, + PUCTL_SPDO, + PUCTL_GPSLXAU, + PUCTL_CRTP, + PUCTL_SLXC, + PUCTL_SLXD, + PUCTL_SLXK, + + /* 32: APB_MISC_PP_PULLUPDOWN_REG_C_0 */ + PUCTL_CDEV1, + PUCTL_CDEV2, + PUCTL_SPIA, + PUCTL_SPIB, + PUCTL_SPIC, + PUCTL_SPID, + PUCTL_SPIE, + PUCTL_SPIF, + + PUCTL_SPIG, + PUCTL_SPIH, + PUCTL_IRTX, + PUCTL_IRRX, + PUCTL_GME, + PUCTL_RESERVED45, + PUCTL_XM2D, + PUCTL_XM2C, + + /* 48: APB_MISC_PP_PULLUPDOWN_REG_D_0 */ + PUCTL_UAA, + PUCTL_UAB, + PUCTL_UAC, + PUCTL_UAD, + PUCTL_UCA, + PUCTL_UCB, + PUCTL_LD17, + PUCTL_LD19_18, + + PUCTL_LD21_20, + PUCTL_LD23_22, + PUCTL_LS, + PUCTL_LC, + PUCTL_CSUS, + PUCTL_DDRC, + PUCTL_SDC, + PUCTL_SDD, + + /* 64: APB_MISC_PP_PULLUPDOWN_REG_E_0 */ + PUCTL_KBCF, + PUCTL_KBCE, + PUCTL_PMCA, + PUCTL_PMCB, + PUCTL_PMCC, + PUCTL_PMCD, + PUCTL_PMCE, + PUCTL_CK32, + + PUCTL_UDA, + PUCTL_SDMMC1, + PUCTL_GMA, + PUCTL_GMB, + PUCTL_GMC, + PUCTL_GMD, + PUCTL_DDC, + PUCTL_OWC, + + PUCTL_NONE = -1 +}; + +/* Convenient macro for defining pin group properties */ +#define PINALL(pingrp, f0, f1, f2, f3, mux, pupd) \ + { \ + .funcs = { \ + PMUX_FUNC_ ## f0, \ + PMUX_FUNC_ ## f1, \ + PMUX_FUNC_ ## f2, \ + PMUX_FUNC_ ## f3, \ + }, \ + .ctl_id = mux, \ + .pull_id = pupd \ + } + +/* A normal pin group where the mux name and pull-up name match */ +#define PIN(pingrp, f0, f1, f2, f3) \ + PINALL(pingrp, f0, f1, f2, f3, MUXCTL_##pingrp, PUCTL_##pingrp) + +/* A pin group where the pull-up name doesn't have a 1-1 mapping */ +#define PINP(pingrp, f0, f1, f2, f3, pupd) \ + PINALL(pingrp, f0, f1, f2, f3, MUXCTL_##pingrp, PUCTL_##pupd) + +/* A pin group number which is not used */ +#define PIN_RESERVED \ + PIN(NONE, RSVD1, RSVD2, RSVD3, RSVD4) + +#define DRVGRP(drvgrp) \ + PINALL(drvgrp, RSVD1, RSVD2, RSVD3, RSVD4, MUXCTL_NONE, PUCTL_NONE) + +static const struct pmux_pingrp_desc tegra20_pingroups[] = { + PIN(ATA, IDE, NAND, GMI, RSVD4), + PIN(ATB, IDE, NAND, GMI, SDIO4), + PIN(ATC, IDE, NAND, GMI, SDIO4), + PIN(ATD, IDE, NAND, GMI, SDIO4), + PIN(CDEV1, OSC, PLLA_OUT, PLLM_OUT1, AUDIO_SYNC), + PIN(CDEV2, OSC, AHB_CLK, APB_CLK, PLLP_OUT4), + PIN(CSUS, PLLC_OUT1, PLLP_OUT2, PLLP_OUT3, VI_SENSOR_CLK), + PIN(DAP1, DAP1, RSVD2, GMI, SDIO2), + + PIN(DAP2, DAP2, TWC, RSVD3, GMI), + PIN(DAP3, DAP3, RSVD2, RSVD3, RSVD4), + PIN(DAP4, DAP4, RSVD2, GMI, RSVD4), + PIN(DTA, RSVD1, SDIO2, VI, RSVD4), + PIN(DTB, RSVD1, RSVD2, VI, SPI1), + PIN(DTC, RSVD1, RSVD2, VI, RSVD4), + PIN(DTD, RSVD1, SDIO2, VI, RSVD4), + PIN(DTE, RSVD1, RSVD2, VI, SPI1), + + PINP(GPU, PWM, UARTA, GMI, RSVD4, GPSLXAU), + PIN(GPV, PCIE, RSVD2, RSVD3, RSVD4), + PIN(I2CP, I2C, RSVD2, RSVD3, RSVD4), + PIN(IRTX, UARTA, UARTB, GMI, SPI4), + PIN(IRRX, UARTA, UARTB, GMI, SPI4), + PIN(KBCB, KBC, NAND, SDIO2, MIO), + PIN(KBCA, KBC, NAND, SDIO2, EMC_TEST0_DLL), + PINP(PMC, PWR_ON, PWR_INTR, RSVD3, RSVD4, NONE), + + PIN(PTA, I2C2, HDMI, GMI, RSVD4), + PIN(RM, I2C, RSVD2, RSVD3, RSVD4), + PIN(KBCE, KBC, NAND, OWR, RSVD4), + PIN(KBCF, KBC, NAND, TRACE, MIO), + PIN(GMA, UARTE, SPI3, GMI, SDIO4), + PIN(GMC, UARTD, SPI4, GMI, SFLASH), + PIN(SDMMC1, SDIO1, RSVD2, UARTE, UARTA), + PIN(OWC, OWR, RSVD2, RSVD3, RSVD4), + + PIN(GME, RSVD1, DAP5, GMI, SDIO4), + PIN(SDC, PWM, TWC, SDIO3, SPI3), + PIN(SDD, UARTA, PWM, SDIO3, SPI3), + PIN_RESERVED, + PINP(SLXA, PCIE, SPI4, SDIO3, SPI2, CRTP), + PIN(SLXC, SPDIF, SPI4, SDIO3, SPI2), + PIN(SLXD, SPDIF, SPI4, SDIO3, SPI2), + PIN(SLXK, PCIE, SPI4, SDIO3, SPI2), + + PIN(SPDI, SPDIF, RSVD2, I2C, SDIO2), + PIN(SPDO, SPDIF, RSVD2, I2C, SDIO2), + PIN(SPIA, SPI1, SPI2, SPI3, GMI), + PIN(SPIB, SPI1, SPI2, SPI3, GMI), + PIN(SPIC, SPI1, SPI2, SPI3, GMI), + PIN(SPID, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPIE, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPIF, SPI3, SPI1, SPI2, RSVD4), + + PIN(SPIG, SPI3, SPI2, SPI2_ALT, I2C), + PIN(SPIH, SPI3, SPI2, SPI2_ALT, I2C), + PIN(UAA, SPI3, MIPI_HS, UARTA, ULPI), + PIN(UAB, SPI2, MIPI_HS, UARTA, ULPI), + PIN(UAC, OWR, RSVD2, RSVD3, RSVD4), + PIN(UAD, UARTB, SPDIF, UARTA, SPI4), + PIN(UCA, UARTC, RSVD2, GMI, RSVD4), + PIN(UCB, UARTC, PWM, GMI, RSVD4), + + PIN_RESERVED, + PIN(ATE, IDE, NAND, GMI, RSVD4), + PIN(KBCC, KBC, NAND, TRACE, EMC_TEST1_DLL), + PIN_RESERVED, + PIN_RESERVED, + PIN(GMB, IDE, NAND, GMI, GMI_INT), + PIN(GMD, RSVD1, NAND, GMI, SFLASH), + PIN(DDC, I2C2, RSVD2, RSVD3, RSVD4), + + /* 64 */ + PINP(LD0, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD1, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD2, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD3, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD4, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD5, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD6, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD7, DISPA, DISPB, XIO, RSVD4, LD17), + + PINP(LD8, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD9, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD10, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD11, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD12, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD13, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD14, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD15, DISPA, DISPB, XIO, RSVD4, LD17), + + PINP(LD16, DISPA, DISPB, XIO, RSVD4, LD17), + PINP(LD17, DISPA, DISPB, RSVD3, RSVD4, LD17), + PINP(LHP0, DISPA, DISPB, RSVD3, RSVD4, LD21_20), + PINP(LHP1, DISPA, DISPB, RSVD3, RSVD4, LD19_18), + PINP(LHP2, DISPA, DISPB, RSVD3, RSVD4, LD19_18), + PINP(LVP0, DISPA, DISPB, RSVD3, RSVD4, LC), + PINP(LVP1, DISPA, DISPB, RSVD3, RSVD4, LD21_20), + PINP(HDINT, HDMI, RSVD2, RSVD3, RSVD4, LC), + + PINP(LM0, DISPA, DISPB, SPI3, RSVD4, LC), + PINP(LM1, DISPA, DISPB, RSVD3, CRT, LC), + PINP(LVS, DISPA, DISPB, XIO, RSVD4, LC), + PINP(LSC0, DISPA, DISPB, XIO, RSVD4, LC), + PINP(LSC1, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LSCK, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LDC, DISPA, DISPB, RSVD3, RSVD4, LS), + PINP(LCSN, DISPA, DISPB, SPI3, RSVD4, LS), + + /* 96 */ + PINP(LSPI, DISPA, DISPB, XIO, HDMI, LC), + PINP(LSDA, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LSDI, DISPA, DISPB, SPI3, RSVD4, LS), + PINP(LPW0, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LPW1, DISPA, DISPB, RSVD3, RSVD4, LS), + PINP(LPW2, DISPA, DISPB, SPI3, HDMI, LS), + PINP(LDI, DISPA, DISPB, RSVD3, RSVD4, LD23_22), + PINP(LHS, DISPA, DISPB, XIO, RSVD4, LC), + + PINP(LPP, DISPA, DISPB, RSVD3, RSVD4, LD23_22), + PIN_RESERVED, + PIN(KBCD, KBC, NAND, SDIO2, MIO), + PIN(GPU7, RTCK, RSVD2, RSVD3, RSVD4), + PIN(DTF, I2C3, RSVD2, VI, RSVD4), + PIN(UDA, SPI1, RSVD2, UARTD, ULPI), + PIN(CRTP, CRT, RSVD2, RSVD3, RSVD4), + PINP(SDB, UARTA, PWM, SDIO3, SPI2, NONE), + + /* these pin groups only have pullup and pull down control */ + DRVGRP(CK32), + DRVGRP(DDRC), + DRVGRP(PMCA), + DRVGRP(PMCB), + DRVGRP(PMCC), + DRVGRP(PMCD), + DRVGRP(PMCE), + DRVGRP(XM2C), + DRVGRP(XM2D), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra20_pingroups; diff --git a/drivers/pinctrl/tegra/pinmux-tegra210.c b/drivers/pinctrl/tegra/pinmux-tegra210.c new file mode 100644 index 0000000..27abec2 --- /dev/null +++ b/drivers/pinctrl/tegra/pinmux-tegra210.c @@ -0,0 +1,190 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2013-2014, NVIDIA CORPORATION. All rights reserved. + */ + +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra210_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(SDMMC1_CLK_PM0, SDMMC1, RSVD1, RSVD2, RSVD3), + PIN(SDMMC1_CMD_PM1, SDMMC1, SPI3, RSVD2, RSVD3), + PIN(SDMMC1_DAT3_PM2, SDMMC1, SPI3, RSVD2, RSVD3), + PIN(SDMMC1_DAT2_PM3, SDMMC1, SPI3, RSVD2, RSVD3), + PIN(SDMMC1_DAT1_PM4, SDMMC1, SPI3, RSVD2, RSVD3), + PIN(SDMMC1_DAT0_PM5, SDMMC1, RSVD1, RSVD2, RSVD3), + PIN_RESERVED, + PIN(SDMMC3_CLK_PP0, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN(SDMMC3_CMD_PP1, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN(SDMMC3_DAT0_PP5, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN(SDMMC3_DAT1_PP4, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN(SDMMC3_DAT2_PP3, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN(SDMMC3_DAT3_PP2, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN_RESERVED, + PIN(PEX_L0_RST_N_PA0, PE0, RSVD1, RSVD2, RSVD3), + PIN(PEX_L0_CLKREQ_N_PA1, PE0, RSVD1, RSVD2, RSVD3), + PIN(PEX_WAKE_N_PA2, PE, RSVD1, RSVD2, RSVD3), + PIN(PEX_L1_RST_N_PA3, PE1, RSVD1, RSVD2, RSVD3), + PIN(PEX_L1_CLKREQ_N_PA4, PE1, RSVD1, RSVD2, RSVD3), + PIN(SATA_LED_ACTIVE_PA5, SATA, RSVD1, RSVD2, RSVD3), + PIN(SPI1_MOSI_PC0, SPI1, RSVD1, RSVD2, RSVD3), + PIN(SPI1_MISO_PC1, SPI1, RSVD1, RSVD2, RSVD3), + PIN(SPI1_SCK_PC2, SPI1, RSVD1, RSVD2, RSVD3), + PIN(SPI1_CS0_PC3, SPI1, RSVD1, RSVD2, RSVD3), + PIN(SPI1_CS1_PC4, SPI1, RSVD1, RSVD2, RSVD3), + PIN(SPI2_MOSI_PB4, SPI2, DTV, RSVD2, RSVD3), + PIN(SPI2_MISO_PB5, SPI2, DTV, RSVD2, RSVD3), + PIN(SPI2_SCK_PB6, SPI2, DTV, RSVD2, RSVD3), + PIN(SPI2_CS0_PB7, SPI2, DTV, RSVD2, RSVD3), + PIN(SPI2_CS1_PDD0, SPI2, RSVD1, RSVD2, RSVD3), + PIN(SPI4_MOSI_PC7, SPI4, RSVD1, RSVD2, RSVD3), + PIN(SPI4_MISO_PD0, SPI4, RSVD1, RSVD2, RSVD3), + PIN(SPI4_SCK_PC5, SPI4, RSVD1, RSVD2, RSVD3), + PIN(SPI4_CS0_PC6, SPI4, RSVD1, RSVD2, RSVD3), + PIN(QSPI_SCK_PEE0, QSPI, RSVD1, RSVD2, RSVD3), + PIN(QSPI_CS_N_PEE1, QSPI, RSVD1, RSVD2, RSVD3), + PIN(QSPI_IO0_PEE2, QSPI, RSVD1, RSVD2, RSVD3), + PIN(QSPI_IO1_PEE3, QSPI, RSVD1, RSVD2, RSVD3), + PIN(QSPI_IO2_PEE4, QSPI, RSVD1, RSVD2, RSVD3), + PIN(QSPI_IO3_PEE5, QSPI, RSVD1, RSVD2, RSVD3), + PIN_RESERVED, + PIN(DMIC1_CLK_PE0, DMIC1, I2S3, RSVD2, RSVD3), + PIN(DMIC1_DAT_PE1, DMIC1, I2S3, RSVD2, RSVD3), + PIN(DMIC2_CLK_PE2, DMIC2, I2S3, RSVD2, RSVD3), + PIN(DMIC2_DAT_PE3, DMIC2, I2S3, RSVD2, RSVD3), + PIN(DMIC3_CLK_PE4, DMIC3, I2S5A, RSVD2, RSVD3), + PIN(DMIC3_DAT_PE5, DMIC3, I2S5A, RSVD2, RSVD3), + PIN(GEN1_I2C_SCL_PJ1, I2C1, RSVD1, RSVD2, RSVD3), + PIN(GEN1_I2C_SDA_PJ0, I2C1, RSVD1, RSVD2, RSVD3), + PIN(GEN2_I2C_SCL_PJ2, I2C2, RSVD1, RSVD2, RSVD3), + PIN(GEN2_I2C_SDA_PJ3, I2C2, RSVD1, RSVD2, RSVD3), + PIN(GEN3_I2C_SCL_PF0, I2C3, RSVD1, RSVD2, RSVD3), + PIN(GEN3_I2C_SDA_PF1, I2C3, RSVD1, RSVD2, RSVD3), + PIN(CAM_I2C_SCL_PS2, I2C3, I2CVI, RSVD2, RSVD3), + PIN(CAM_I2C_SDA_PS3, I2C3, I2CVI, RSVD2, RSVD3), + PIN(PWR_I2C_SCL_PY3, I2CPMU, RSVD1, RSVD2, RSVD3), + PIN(PWR_I2C_SDA_PY4, I2CPMU, RSVD1, RSVD2, RSVD3), + PIN(UART1_TX_PU0, UARTA, RSVD1, RSVD2, RSVD3), + PIN(UART1_RX_PU1, UARTA, RSVD1, RSVD2, RSVD3), + PIN(UART1_RTS_PU2, UARTA, RSVD1, RSVD2, RSVD3), + PIN(UART1_CTS_PU3, UARTA, RSVD1, RSVD2, RSVD3), + PIN(UART2_TX_PG0, UARTB, I2S4A, SPDIF, UART), + PIN(UART2_RX_PG1, UARTB, I2S4A, SPDIF, UART), + PIN(UART2_RTS_PG2, UARTB, I2S4A, RSVD2, UART), + PIN(UART2_CTS_PG3, UARTB, I2S4A, RSVD2, UART), + PIN(UART3_TX_PD1, UARTC, SPI4, RSVD2, RSVD3), + PIN(UART3_RX_PD2, UARTC, SPI4, RSVD2, RSVD3), + PIN(UART3_RTS_PD3, UARTC, SPI4, RSVD2, RSVD3), + PIN(UART3_CTS_PD4, UARTC, SPI4, RSVD2, RSVD3), + PIN(UART4_TX_PI4, UARTD, UART, RSVD2, RSVD3), + PIN(UART4_RX_PI5, UARTD, UART, RSVD2, RSVD3), + PIN(UART4_RTS_PI6, UARTD, UART, RSVD2, RSVD3), + PIN(UART4_CTS_PI7, UARTD, UART, RSVD2, RSVD3), + PIN(DAP1_FS_PB0, I2S1, RSVD1, RSVD2, RSVD3), + PIN(DAP1_DIN_PB1, I2S1, RSVD1, RSVD2, RSVD3), + PIN(DAP1_DOUT_PB2, I2S1, RSVD1, RSVD2, RSVD3), + PIN(DAP1_SCLK_PB3, I2S1, RSVD1, RSVD2, RSVD3), + PIN(DAP2_FS_PAA0, I2S2, RSVD1, RSVD2, RSVD3), + PIN(DAP2_DIN_PAA2, I2S2, RSVD1, RSVD2, RSVD3), + PIN(DAP2_DOUT_PAA3, I2S2, RSVD1, RSVD2, RSVD3), + PIN(DAP2_SCLK_PAA1, I2S2, RSVD1, RSVD2, RSVD3), + PIN(DAP4_FS_PJ4, I2S4B, RSVD1, RSVD2, RSVD3), + PIN(DAP4_DIN_PJ5, I2S4B, RSVD1, RSVD2, RSVD3), + PIN(DAP4_DOUT_PJ6, I2S4B, RSVD1, RSVD2, RSVD3), + PIN(DAP4_SCLK_PJ7, I2S4B, RSVD1, RSVD2, RSVD3), + PIN(CAM1_MCLK_PS0, EXTPERIPH3, RSVD1, RSVD2, RSVD3), + PIN(CAM2_MCLK_PS1, EXTPERIPH3, RSVD1, RSVD2, RSVD3), + PIN(JTAG_RTCK, JTAG, RSVD1, RSVD2, RSVD3), + PIN(CLK_32K_IN, CLK, RSVD1, RSVD2, RSVD3), + PIN(CLK_32K_OUT_PY5, SOC, BLINK, RSVD2, RSVD3), + PIN(BATT_BCL, BCL, RSVD1, RSVD2, RSVD3), + PIN(CLK_REQ, SYS, RSVD1, RSVD2, RSVD3), + PIN(CPU_PWR_REQ, CPU, RSVD1, RSVD2, RSVD3), + PIN(PWR_INT_N, PMI, RSVD1, RSVD2, RSVD3), + PIN(SHUTDOWN, SHUTDOWN, RSVD1, RSVD2, RSVD3), + PIN(CORE_PWR_REQ, CORE, RSVD1, RSVD2, RSVD3), + PIN(AUD_MCLK_PBB0, AUD, RSVD1, RSVD2, RSVD3), + PIN(DVFS_PWM_PBB1, RSVD0, CLDVFS, SPI3, RSVD3), + PIN(DVFS_CLK_PBB2, RSVD0, CLDVFS, SPI3, RSVD3), + PIN(GPIO_X1_AUD_PBB3, RSVD0, RSVD1, SPI3, RSVD3), + PIN(GPIO_X3_AUD_PBB4, RSVD0, RSVD1, SPI3, RSVD3), + PIN(PCC7, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(HDMI_CEC_PCC0, CEC, RSVD1, RSVD2, RSVD3), + PIN(HDMI_INT_DP_HPD_PCC1, DP, RSVD1, RSVD2, RSVD3), + PIN(SPDIF_OUT_PCC2, SPDIF, RSVD1, RSVD2, RSVD3), + PIN(SPDIF_IN_PCC3, SPDIF, RSVD1, RSVD2, RSVD3), + PIN(USB_VBUS_EN0_PCC4, USB, RSVD1, RSVD2, RSVD3), + PIN(USB_VBUS_EN1_PCC5, USB, RSVD1, RSVD2, RSVD3), + PIN(DP_HPD0_PCC6, DP, RSVD1, RSVD2, RSVD3), + PIN(WIFI_EN_PH0, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(WIFI_RST_PH1, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(WIFI_WAKE_AP_PH2, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(AP_WAKE_BT_PH3, RSVD0, UARTB, SPDIF, RSVD3), + PIN(BT_RST_PH4, RSVD0, UARTB, SPDIF, RSVD3), + PIN(BT_WAKE_AP_PH5, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(AP_WAKE_NFC_PH7, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(NFC_EN_PI0, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(NFC_INT_PI1, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(GPS_EN_PI2, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(GPS_RST_PI3, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(CAM_RST_PS4, VGP1, RSVD1, RSVD2, RSVD3), + PIN(CAM_AF_EN_PS5, VIMCLK, VGP2, RSVD2, RSVD3), + PIN(CAM_FLASH_EN_PS6, VIMCLK, VGP3, RSVD2, RSVD3), + PIN(CAM1_PWDN_PS7, VGP4, RSVD1, RSVD2, RSVD3), + PIN(CAM2_PWDN_PT0, VGP5, RSVD1, RSVD2, RSVD3), + PIN(CAM1_STROBE_PT1, VGP6, RSVD1, RSVD2, RSVD3), + PIN(LCD_TE_PY2, DISPLAYA, RSVD1, RSVD2, RSVD3), + PIN(LCD_BL_PWM_PV0, DISPLAYA, PWM0, SOR0, RSVD3), + PIN(LCD_BL_EN_PV1, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(LCD_RST_PV2, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(LCD_GPIO1_PV3, DISPLAYB, RSVD1, RSVD2, RSVD3), + PIN(LCD_GPIO2_PV4, DISPLAYB, PWM1, RSVD2, SOR1), + PIN(AP_READY_PV5, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(TOUCH_RST_PV6, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(TOUCH_CLK_PV7, TOUCH, RSVD1, RSVD2, RSVD3), + PIN(MODEM_WAKE_AP_PX0, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(TOUCH_INT_PX1, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(MOTION_INT_PX2, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(ALS_PROX_INT_PX3, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(TEMP_ALERT_PX4, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(BUTTON_POWER_ON_PX5, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(BUTTON_VOL_UP_PX6, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(BUTTON_VOL_DOWN_PX7, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(BUTTON_SLIDE_SW_PY0, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(BUTTON_HOME_PY1, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(PA6, SATA, RSVD1, RSVD2, RSVD3), + PIN(PE6, RSVD0, I2S5A, PWM2, RSVD3), + PIN(PE7, RSVD0, I2S5A, PWM3, RSVD3), + PIN(PH6, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(PK0, IQC0, I2S5B, RSVD2, RSVD3), + PIN(PK1, IQC0, I2S5B, RSVD2, RSVD3), + PIN(PK2, IQC0, I2S5B, RSVD2, RSVD3), + PIN(PK3, IQC0, I2S5B, RSVD2, RSVD3), + PIN(PK4, IQC1, RSVD1, RSVD2, RSVD3), + PIN(PK5, IQC1, RSVD1, RSVD2, RSVD3), + PIN(PK6, IQC1, RSVD1, RSVD2, RSVD3), + PIN(PK7, IQC1, RSVD1, RSVD2, RSVD3), + PIN(PL0, RSVD0, RSVD1, RSVD2, RSVD3), + PIN(PL1, SOC, RSVD1, RSVD2, RSVD3), + PIN(PZ0, VIMCLK2, RSVD1, RSVD2, RSVD3), + PIN(PZ1, VIMCLK2, SDMMC1, RSVD2, RSVD3), + PIN(PZ2, SDMMC3, CCLA, RSVD2, RSVD3), + PIN(PZ3, SDMMC3, RSVD1, RSVD2, RSVD3), + PIN(PZ4, SDMMC1, RSVD1, RSVD2, RSVD3), + PIN(PZ5, SOC, RSVD1, RSVD2, RSVD3), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra210_pingroups; diff --git a/drivers/pinctrl/tegra/pinmux-tegra30.c b/drivers/pinctrl/tegra/pinmux-tegra30.c new file mode 100644 index 0000000..d11b2aa --- /dev/null +++ b/drivers/pinctrl/tegra/pinmux-tegra30.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2010-2014, NVIDIA CORPORATION. All rights reserved. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/arch/pinmux.h> + +#define PIN(pin, f0, f1, f2, f3) \ + { \ + .funcs = { \ + PMUX_FUNC_##f0, \ + PMUX_FUNC_##f1, \ + PMUX_FUNC_##f2, \ + PMUX_FUNC_##f3, \ + }, \ + } + +#define PIN_RESERVED {} + +static const struct pmux_pingrp_desc tegra30_pingroups[] = { + /* pin, f0, f1, f2, f3 */ + /* Offset 0x3000 */ + PIN(ULPI_DATA0_PO1, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA1_PO2, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA2_PO3, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA3_PO4, SPI3, HSI, UARTA, ULPI), + PIN(ULPI_DATA4_PO5, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA5_PO6, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA6_PO7, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_DATA7_PO0, SPI2, HSI, UARTA, ULPI), + PIN(ULPI_CLK_PY0, SPI1, RSVD2, UARTD, ULPI), + PIN(ULPI_DIR_PY1, SPI1, RSVD2, UARTD, ULPI), + PIN(ULPI_NXT_PY2, SPI1, RSVD2, UARTD, ULPI), + PIN(ULPI_STP_PY3, SPI1, RSVD2, UARTD, ULPI), + PIN(DAP3_FS_PP0, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(DAP3_DIN_PP1, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(DAP3_DOUT_PP2, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(DAP3_SCLK_PP3, I2S2, RSVD2, DISPLAYA, DISPLAYB), + PIN(PV0, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(PV1, RSVD1, RSVD2, RSVD3, RSVD4), + PIN(SDMMC1_CLK_PZ0, SDMMC1, RSVD2, RSVD3, UARTA), + PIN(SDMMC1_CMD_PZ1, SDMMC1, RSVD2, RSVD3, UARTA), + PIN(SDMMC1_DAT3_PY4, SDMMC1, RSVD2, UARTE, UARTA), + PIN(SDMMC1_DAT2_PY5, SDMMC1, RSVD2, UARTE, UARTA), + PIN(SDMMC1_DAT1_PY6, SDMMC1, RSVD2, UARTE, UARTA), + PIN(SDMMC1_DAT0_PY7, SDMMC1, RSVD2, UARTE, UARTA), + PIN(PV2, OWR, RSVD2, RSVD3, RSVD4), + PIN(PV3, CLK_12M_OUT, RSVD2, RSVD3, RSVD4), + PIN(CLK2_OUT_PW5, EXTPERIPH2, RSVD2, RSVD3, RSVD4), + PIN(CLK2_REQ_PCC5, DAP, RSVD2, RSVD3, RSVD4), + PIN(LCD_PWR1_PC1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_PWR2_PC6, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_SDIN_PZ2, DISPLAYA, DISPLAYB, SPI5, RSVD4), + PIN(LCD_SDOUT_PN5, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_WR_N_PZ3, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_CS0_N_PN4, DISPLAYA, DISPLAYB, SPI5, RSVD4), + PIN(LCD_DC0_PN6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_SCK_PZ4, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_PWR0_PB2, DISPLAYA, DISPLAYB, SPI5, HDCP), + PIN(LCD_PCLK_PB3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_DE_PJ1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_HSYNC_PJ3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_VSYNC_PJ4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D0_PE0, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D1_PE1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D2_PE2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D3_PE3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D4_PE4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D5_PE5, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D6_PE6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D7_PE7, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D8_PF0, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D9_PF1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D10_PF2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D11_PF3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D12_PF4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D13_PF5, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D14_PF6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D15_PF7, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D16_PM0, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D17_PM1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D18_PM2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D19_PM3, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D20_PM4, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D21_PM5, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D22_PM6, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_D23_PM7, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_CS1_N_PW0, DISPLAYA, DISPLAYB, SPI5, RSVD4), + PIN(LCD_M1_PW1, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(LCD_DC1_PD2, DISPLAYA, DISPLAYB, RSVD3, RSVD4), + PIN(HDMI_INT_PN7, HDMI, RSVD2, RSVD3, RSVD4), + PIN(DDC_SCL_PV4, I2C4, RSVD2, RSVD3, RSVD4), + PIN(DDC_SDA_PV5, I2C4, RSVD2, RSVD3, RSVD4), + PIN(CRT_HSYNC_PV6, CRT, RSVD2, RSVD3, RSVD4), + PIN(CRT_VSYNC_PV7, CRT, RSVD2, RSVD3, RSVD4), + PIN(VI_D0_PT4, DDR, RSVD2, VI, RSVD4), + PIN(VI_D1_PD5, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D2_PL0, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D3_PL1, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D4_PL2, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D5_PL3, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D6_PL4, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D7_PL5, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D8_PL6, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D9_PL7, DDR, SDMMC2, VI, RSVD4), + PIN(VI_D10_PT2, DDR, RSVD2, VI, RSVD4), + PIN(VI_D11_PT3, DDR, RSVD2, VI, RSVD4), + PIN(VI_PCLK_PT0, RSVD1, SDMMC2, VI, RSVD4), + PIN(VI_MCLK_PT1, VI, VI_ALT1, VI_ALT2, VI_ALT3), + PIN(VI_VSYNC_PD6, DDR, RSVD2, VI, RSVD4), + PIN(VI_HSYNC_PD7, DDR, RSVD2, VI, RSVD4), + PIN(UART2_RXD_PC3, UARTB, SPDIF, UARTA, SPI4), + PIN(UART2_TXD_PC2, UARTB, SPDIF, UARTA, SPI4), + PIN(UART2_RTS_N_PJ6, UARTA, UARTB, GMI, SPI4), + PIN(UART2_CTS_N_PJ5, UARTA, UARTB, GMI, SPI4), + PIN(UART3_TXD_PW6, UARTC, RSVD2, GMI, RSVD4), + PIN(UART3_RXD_PW7, UARTC, RSVD2, GMI, RSVD4), + PIN(UART3_CTS_N_PA1, UARTC, RSVD2, GMI, RSVD4), + PIN(UART3_RTS_N_PC0, UARTC, PWM0, GMI, RSVD4), + PIN(PU0, OWR, UARTA, GMI, RSVD4), + PIN(PU1, RSVD1, UARTA, GMI, RSVD4), + PIN(PU2, RSVD1, UARTA, GMI, RSVD4), + PIN(PU3, PWM0, UARTA, GMI, RSVD4), + PIN(PU4, PWM1, UARTA, GMI, RSVD4), + PIN(PU5, PWM2, UARTA, GMI, RSVD4), + PIN(PU6, PWM3, UARTA, GMI, RSVD4), + PIN(GEN1_I2C_SDA_PC5, I2C1, RSVD2, RSVD3, RSVD4), + PIN(GEN1_I2C_SCL_PC4, I2C1, RSVD2, RSVD3, RSVD4), + PIN(DAP4_FS_PP4, I2S3, RSVD2, GMI, RSVD4), + PIN(DAP4_DIN_PP5, I2S3, RSVD2, GMI, RSVD4), + PIN(DAP4_DOUT_PP6, I2S3, RSVD2, GMI, RSVD4), + PIN(DAP4_SCLK_PP7, I2S3, RSVD2, GMI, RSVD4), + PIN(CLK3_OUT_PEE0, EXTPERIPH3, RSVD2, RSVD3, RSVD4), + PIN(CLK3_REQ_PEE1, DEV3, RSVD2, RSVD3, RSVD4), + PIN(GMI_WP_N_PC7, RSVD1, NAND, GMI, GMI_ALT), + PIN(GMI_IORDY_PI5, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_WAIT_PI7, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_ADV_N_PK0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CLK_PK1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CS0_N_PJ0, RSVD1, NAND, GMI, DTV), + PIN(GMI_CS1_N_PJ2, RSVD1, NAND, GMI, DTV), + PIN(GMI_CS2_N_PK3, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CS3_N_PK4, RSVD1, NAND, GMI, GMI_ALT), + PIN(GMI_CS4_N_PK2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_CS6_N_PI3, NAND, NAND_ALT, GMI, SATA), + PIN(GMI_CS7_N_PI6, NAND, NAND_ALT, GMI, GMI_ALT), + PIN(GMI_AD0_PG0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD1_PG1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD2_PG2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD3_PG3, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD4_PG4, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD5_PG5, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD6_PG6, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD7_PG7, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD8_PH0, PWM0, NAND, GMI, RSVD4), + PIN(GMI_AD9_PH1, PWM1, NAND, GMI, RSVD4), + PIN(GMI_AD10_PH2, PWM2, NAND, GMI, RSVD4), + PIN(GMI_AD11_PH3, PWM3, NAND, GMI, RSVD4), + PIN(GMI_AD12_PH4, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD13_PH5, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD14_PH6, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_AD15_PH7, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_A16_PJ7, UARTD, SPI4, GMI, GMI_ALT), + PIN(GMI_A17_PB0, UARTD, SPI4, GMI, DTV), + PIN(GMI_A18_PB1, UARTD, SPI4, GMI, DTV), + PIN(GMI_A19_PK7, UARTD, SPI4, GMI, RSVD4), + PIN(GMI_WR_N_PI0, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_OE_N_PI1, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_DQS_PI2, RSVD1, NAND, GMI, RSVD4), + PIN(GMI_RST_N_PI4, NAND, NAND_ALT, GMI, RSVD4), + PIN(GEN2_I2C_SCL_PT5, I2C2, HDCP, GMI, RSVD4), + PIN(GEN2_I2C_SDA_PT6, I2C2, HDCP, GMI, RSVD4), + PIN(SDMMC4_CLK_PCC4, INVALID, NAND, GMI, SDMMC4), + PIN(SDMMC4_CMD_PT7, I2C3, NAND, GMI, SDMMC4), + PIN(SDMMC4_DAT0_PAA0, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT1_PAA1, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT2_PAA2, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT3_PAA3, UARTE, SPI3, GMI, SDMMC4), + PIN(SDMMC4_DAT4_PAA4, I2C3, I2S4, GMI, SDMMC4), + PIN(SDMMC4_DAT5_PAA5, VGP3, I2S4, GMI, SDMMC4), + PIN(SDMMC4_DAT6_PAA6, VGP4, I2S4, GMI, SDMMC4), + PIN(SDMMC4_DAT7_PAA7, VGP5, I2S4, GMI, SDMMC4), + PIN(SDMMC4_RST_N_PCC3, VGP6, RSVD2, RSVD3, SDMMC4), + PIN(CAM_MCLK_PCC0, VI, VI_ALT1, VI_ALT3, SDMMC4), + PIN(PCC1, I2S4, RSVD2, RSVD3, SDMMC4), + PIN(PBB0, I2S4, RSVD2, RSVD3, SDMMC4), + PIN(CAM_I2C_SCL_PBB1, VGP1, I2C3, RSVD3, SDMMC4), + PIN(CAM_I2C_SDA_PBB2, VGP2, I2C3, RSVD3, SDMMC4), + PIN(PBB3, VGP3, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB4, VGP4, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB5, VGP5, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB6, VGP6, DISPLAYA, DISPLAYB, SDMMC4), + PIN(PBB7, I2S4, RSVD2, RSVD3, SDMMC4), + PIN(PCC2, I2S4, RSVD2, RSVD3, RSVD4), + PIN(JTAG_RTCK_PU7, RTCK, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SCL_PZ6, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(PWR_I2C_SDA_PZ7, I2CPWR, RSVD2, RSVD3, RSVD4), + PIN(KB_ROW0_PR0, KBC, NAND, RSVD3, RSVD4), + PIN(KB_ROW1_PR1, KBC, NAND, RSVD3, RSVD4), + PIN(KB_ROW2_PR2, KBC, NAND, RSVD3, RSVD4), + PIN(KB_ROW3_PR3, KBC, NAND, RSVD3, INVALID), + PIN(KB_ROW4_PR4, KBC, NAND, TRACE, RSVD4), + PIN(KB_ROW5_PR5, KBC, NAND, TRACE, OWR), + PIN(KB_ROW6_PR6, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW7_PR7, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW8_PS0, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW9_PS1, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW10_PS2, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW11_PS3, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW12_PS4, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW13_PS5, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW14_PS6, KBC, NAND, SDMMC2, MIO), + PIN(KB_ROW15_PS7, KBC, NAND, SDMMC2, MIO), + PIN(KB_COL0_PQ0, KBC, NAND, TRACE, TEST), + PIN(KB_COL1_PQ1, KBC, NAND, TRACE, TEST), + PIN(KB_COL2_PQ2, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL3_PQ3, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL4_PQ4, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL5_PQ5, KBC, NAND, TRACE, RSVD4), + PIN(KB_COL6_PQ6, KBC, NAND, TRACE, MIO), + PIN(KB_COL7_PQ7, KBC, NAND, TRACE, MIO), + PIN(CLK_32K_OUT_PA0, BLINK, RSVD2, RSVD3, RSVD4), + PIN(SYS_CLK_REQ_PZ5, SYSCLK, RSVD2, RSVD3, RSVD4), + PIN(CORE_PWR_REQ, CORE_PWR_REQ, RSVD2, RSVD3, RSVD4), + PIN(CPU_PWR_REQ, CPU_PWR_REQ, RSVD2, RSVD3, RSVD4), + PIN(PWR_INT_N, PWR_INT_N, RSVD2, RSVD3, RSVD4), + PIN(CLK_32K_IN, CLK_32K_IN, RSVD2, RSVD3, RSVD4), + PIN(OWR, OWR, CEC, RSVD3, RSVD4), + PIN(DAP1_FS_PN0, I2S0, HDA, GMI, SDMMC2), + PIN(DAP1_DIN_PN1, I2S0, HDA, GMI, SDMMC2), + PIN(DAP1_DOUT_PN2, I2S0, HDA, GMI, SDMMC2), + PIN(DAP1_SCLK_PN3, I2S0, HDA, GMI, SDMMC2), + PIN(CLK1_REQ_PEE2, DAP, HDA, RSVD3, RSVD4), + PIN(CLK1_OUT_PW4, EXTPERIPH1, RSVD2, RSVD3, RSVD4), + PIN(SPDIF_IN_PK6, SPDIF, HDA, I2C1, SDMMC2), + PIN(SPDIF_OUT_PK5, SPDIF, RSVD2, I2C1, SDMMC2), + PIN(DAP2_FS_PA2, I2S1, HDA, RSVD3, GMI), + PIN(DAP2_DIN_PA4, I2S1, HDA, RSVD3, GMI), + PIN(DAP2_DOUT_PA5, I2S1, HDA, RSVD3, GMI), + PIN(DAP2_SCLK_PA3, I2S1, HDA, RSVD3, GMI), + PIN(SPI2_MOSI_PX0, SPI6, SPI2, SPI3, GMI), + PIN(SPI2_MISO_PX1, SPI6, SPI2, SPI3, GMI), + PIN(SPI2_CS0_N_PX3, SPI6, SPI2, SPI3, GMI), + PIN(SPI2_SCK_PX2, SPI6, SPI2, SPI3, GMI), + PIN(SPI1_MOSI_PX4, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPI1_SCK_PX5, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPI1_CS0_N_PX6, SPI2, SPI1, SPI2_ALT, GMI), + PIN(SPI1_MISO_PX7, SPI3, SPI1, SPI2_ALT, RSVD4), + PIN(SPI2_CS1_N_PW2, SPI3, SPI2, SPI2_ALT, I2C1), + PIN(SPI2_CS2_N_PW3, SPI3, SPI2, SPI2_ALT, I2C1), + PIN(SDMMC3_CLK_PA6, UARTA, PWM2, SDMMC3, SPI3), + PIN(SDMMC3_CMD_PA7, UARTA, PWM3, SDMMC3, SPI2), + PIN(SDMMC3_DAT0_PB7, RSVD1, RSVD2, SDMMC3, SPI3), + PIN(SDMMC3_DAT1_PB6, RSVD1, RSVD2, SDMMC3, SPI3), + PIN(SDMMC3_DAT2_PB5, RSVD1, PWM1, SDMMC3, SPI3), + PIN(SDMMC3_DAT3_PB4, RSVD1, PWM0, SDMMC3, SPI3), + PIN(SDMMC3_DAT4_PD1, PWM1, SPI4, SDMMC3, SPI2), + PIN(SDMMC3_DAT5_PD0, PWM0, SPI4, SDMMC3, SPI2), + PIN(SDMMC3_DAT6_PD3, SPDIF, SPI4, SDMMC3, SPI2), + PIN(SDMMC3_DAT7_PD4, SPDIF, SPI4, SDMMC3, SPI2), + PIN(PEX_L0_PRSNT_N_PDD0, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L0_RST_N_PDD1, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L0_CLKREQ_N_PDD2, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_WAKE_N_PDD3, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L1_PRSNT_N_PDD4, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L1_RST_N_PDD5, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L1_CLKREQ_N_PDD6, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L2_PRSNT_N_PDD7, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L2_RST_N_PCC6, PCIE, HDA, RSVD3, RSVD4), + PIN(PEX_L2_CLKREQ_N_PCC7, PCIE, HDA, RSVD3, RSVD4), + PIN(HDMI_CEC_PEE3, CEC, RSVD2, RSVD3, RSVD4), +}; +const struct pmux_pingrp_desc *tegra_soc_pingroups = tegra30_pingroups; diff --git a/drivers/power/pmic/max77663.c b/drivers/power/pmic/max77663.c index 68c3cbb..cf08b6a 100644 --- a/drivers/power/pmic/max77663.c +++ b/drivers/power/pmic/max77663.c @@ -55,6 +55,15 @@ static int max77663_bind(struct udevice *dev) } } + if (IS_ENABLED(CONFIG_MAX77663_GPIO)) { + ret = device_bind_driver(dev, MAX77663_GPIO_DRIVER, + "gpio", NULL); + if (ret) { + log_err("cannot bind GPIOs (ret = %d)\n", ret); + return ret; + } + } + regulators_node = dev_read_subnode(dev, "regulators"); if (!ofnode_valid(regulators_node)) { log_err("%s regulators subnode not found!\n", dev->name); diff --git a/drivers/power/pmic/palmas.c b/drivers/power/pmic/palmas.c index 32f2a93..e340a32 100644 --- a/drivers/power/pmic/palmas.c +++ b/drivers/power/pmic/palmas.c @@ -46,7 +46,7 @@ static int palmas_read(struct udevice *dev, uint reg, uint8_t *buff, int len) static int palmas_bind(struct udevice *dev) { ofnode pmic_node = ofnode_null(), regulators_node; - ofnode subnode; + ofnode subnode, gpio_node; int children, ret; if (IS_ENABLED(CONFIG_SYSRESET_PALMAS)) { @@ -58,6 +58,14 @@ static int palmas_bind(struct udevice *dev) } } + gpio_node = ofnode_find_subnode(dev_ofnode(dev), "gpio"); + if (ofnode_valid(gpio_node)) { + ret = device_bind_driver_to_node(dev, PALMAS_GPIO_DRIVER, + "gpio", gpio_node, NULL); + if (ret) + log_err("cannot bind GPIOs (ret = %d)\n", ret); + } + dev_for_each_subnode(subnode, dev) { const char *name; char *temp; diff --git a/drivers/pwm/pwm-aspeed.c b/drivers/pwm/pwm-aspeed.c index ba98641..b03472d 100644 --- a/drivers/pwm/pwm-aspeed.c +++ b/drivers/pwm/pwm-aspeed.c @@ -49,6 +49,7 @@ #include <dm/device_compat.h> #include <linux/math64.h> #include <linux/bitfield.h> +#include <linux/time.h> #include <asm/io.h> /* The channel number of Aspeed pwm controller */ @@ -77,8 +78,6 @@ /* PWM fixed value */ #define PWM_ASPEED_FIXED_PERIOD 0xff -#define NSEC_PER_SEC 1000000000L - struct aspeed_pwm_priv { struct clk clk; struct regmap *regmap; diff --git a/drivers/pwm/pwm-at91.c b/drivers/pwm/pwm-at91.c index 95597aee..3ff1fb6 100644 --- a/drivers/pwm/pwm-at91.c +++ b/drivers/pwm/pwm-at91.c @@ -14,11 +14,11 @@ #include <dm.h> #include <linux/bitops.h> #include <linux/io.h> +#include <linux/time.h> #include <pwm.h> #define PERIOD_BITS 16 #define PWM_MAX_PRES 10 -#define NSEC_PER_SEC 1000000000L #define PWM_ENA 0x04 #define PWM_CHANNEL_OFFSET 0x20 diff --git a/drivers/pwm/pwm-cadence-ttc.c b/drivers/pwm/pwm-cadence-ttc.c index dc3b314..d9f6736 100644 --- a/drivers/pwm/pwm-cadence-ttc.c +++ b/drivers/pwm/pwm-cadence-ttc.c @@ -17,6 +17,7 @@ #include <linux/bitfield.h> #include <linux/math64.h> #include <linux/log2.h> +#include <linux/time.h> #include <dm/device_compat.h> #define CLOCK_CONTROL 0 @@ -37,8 +38,6 @@ #define COUNTER_INTERVAL_ENABLE BIT(1) #define COUNTER_COUNTING_DISABLE BIT(0) -#define NSEC_PER_SEC 1000000000L - #define TTC_REG(reg, channel) ((reg) + (channel) * sizeof(u32)) #define TTC_CLOCK_CONTROL(reg, channel) \ TTC_REG((reg) + CLOCK_CONTROL, (channel)) diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 2311910..6095972 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -26,8 +26,7 @@ #include <linux/math64.h> #include <linux/bitfield.h> #include <linux/clk-provider.h> - -#define NSEC_PER_SEC 1000000000L +#include <linux/time.h> #define REG_PWM_A 0x0 #define REG_PWM_B 0x4 diff --git a/drivers/pwm/pwm-mtk.c b/drivers/pwm/pwm-mtk.c index 11e7444..ad845ed 100644 --- a/drivers/pwm/pwm-mtk.c +++ b/drivers/pwm/pwm-mtk.c @@ -12,6 +12,7 @@ #include <div64.h> #include <linux/bitops.h> #include <linux/io.h> +#include <linux/time.h> /* PWM registers and bits definitions */ #define PWMCON 0x00 @@ -27,8 +28,6 @@ #define PWM_CLK_DIV_MAX 7 #define MAX_PWM_NUM 8 -#define NSEC_PER_SEC 1000000000L - enum mtk_pwm_reg_ver { PWM_REG_V1, PWM_REG_V2, diff --git a/drivers/pwm/pwm-ti-ehrpwm.c b/drivers/pwm/pwm-ti-ehrpwm.c index f099145..fefa3c6 100644 --- a/drivers/pwm/pwm-ti-ehrpwm.c +++ b/drivers/pwm/pwm-ti-ehrpwm.c @@ -14,8 +14,7 @@ #include <dm/device_compat.h> #include <pwm.h> #include <asm/io.h> - -#define NSEC_PER_SEC 1000000000L +#include <linux/time.h> /* Time base module registers */ #define TI_EHRPWM_TBCTL 0x00 diff --git a/drivers/qe/fdt.c b/drivers/qe/fdt.c index 6195c7c..fa9e406 100644 --- a/drivers/qe/fdt.c +++ b/drivers/qe/fdt.c @@ -6,7 +6,6 @@ * Wolfgang Denk, DENX Software Engineering, wd@denx.de. */ -#include <common.h> #include <asm/global_data.h> #include <linux/libfdt.h> #include <fdt_support.h> diff --git a/drivers/qe/qe.c b/drivers/qe/qe.c index 2825dc6..9631337 100644 --- a/drivers/qe/qe.c +++ b/drivers/qe/qe.c @@ -6,7 +6,6 @@ * based on source code of Shlomi Gridish */ -#include <common.h> #include <malloc.h> #include <command.h> #include <asm/global_data.h> @@ -24,6 +23,9 @@ #include <asm/armv8/mmu.h> #include <asm/arch/cpu.h> #endif +#ifdef CONFIG_PPC +#include <asm/ppc.h> +#endif #define MPC85xx_DEVDISR_QE_DISABLE 0x1 diff --git a/drivers/remoteproc/ti_k3_dsp_rproc.c b/drivers/remoteproc/ti_k3_dsp_rproc.c index 576de4b..1c6515f 100644 --- a/drivers/remoteproc/ti_k3_dsp_rproc.c +++ b/drivers/remoteproc/ti_k3_dsp_rproc.c @@ -56,6 +56,7 @@ struct k3_dsp_boot_data { * @data: Pointer to DSP specific boot data structure * @mem: Array of available memories * @num_mem: Number of available memories + * @in_use: flag to tell if the core is already in use. */ struct k3_dsp_privdata { struct reset_ctl dsp_rst; @@ -63,6 +64,7 @@ struct k3_dsp_privdata { struct k3_dsp_boot_data *data; struct k3_dsp_mem *mem; int num_mems; + bool in_use; }; /* @@ -128,6 +130,13 @@ static int k3_dsp_load(struct udevice *dev, ulong addr, ulong size) u32 boot_vector; int ret; + if (dsp->in_use) { + dev_err(dev, + "Invalid op: Trying to load/start on already running core %d\n", + dsp->tsp.proc_id); + return -EINVAL; + } + dev_dbg(dev, "%s addr = 0x%lx, size = 0x%lx\n", __func__, addr, size); ret = ti_sci_proc_request(&dsp->tsp); if (ret) @@ -195,6 +204,7 @@ static int k3_dsp_start(struct udevice *dev) ti_sci_proc_power_domain_off(&dsp->tsp); } + dsp->in_use = true; proc_release: ti_sci_proc_release(&dsp->tsp); @@ -207,6 +217,7 @@ static int k3_dsp_stop(struct udevice *dev) dev_dbg(dev, "%s\n", __func__); + dsp->in_use = false; ti_sci_proc_request(&dsp->tsp); reset_assert(&dsp->dsp_rst); ti_sci_proc_power_domain_off(&dsp->tsp); diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index a801412..7e21c4a 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1,46 +1,9 @@ config SCSI - bool "Support SCSI controllers" + bool "Support SCSI controllers with driver model" help This enables support for SCSI (Small Computer System Interface), a parallel interface widely used with storage peripherals such as hard drives and optical drives. The SCSI standards define physical interfaces as well as protocols for controlling devices and - tranferring data. - -config DM_SCSI - bool "Support SCSI controllers with driver model" - help - This option enables the SCSI (Small Computer System Interface) uclass - which supports SCSI and SATA HDDs. For every device configuration - (IDs/LUNs) a block device is created with RAW read/write and - filesystem support. - -if SCSI && !DM_SCSI - -config SCSI_AHCI_PLAT - bool "Platform-specific init of AHCI" - help - This enables a way for boards to set up an AHCI device manually, by - called ahci_init() and providing an ahci_reset() mechanism. - - This is deprecated. An AHCI driver should be provided instead. - -config SYS_SCSI_MAX_SCSI_ID - int "Maximum supported SCSI ID" - default 1 - help - Sets the maximum number of SCSI IDs to scan when looking for devices. - IDs from 0 to (this value - 1) are scanned. - - This is deprecated and is not needed when BLK is enabled. - -config SYS_SCSI_MAX_LUN - int "Maximum support SCSI LUN" - default 1 - help - Sets the maximum number of SCSI Logical Unit Numbers (LUNs) to scan on - devices. LUNs from 0 to (this value - 1) are scanned. - - This is deprecated and is not needed when CONFIG_DM_SCSI is enabled. - -endif + tranferring data. For every device configuration (IDs/LUNs) a block + device is created with RAW read/write and filesystem support. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index d8d6de5..628be4c 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -4,25 +4,16 @@ # Wolfgang Denk, DENX Software Engineering, wd@denx.de. ifndef CONFIG_SPL_BUILD -obj-$(CONFIG_DM_SCSI) += scsi-uclass.o -obj-$(CONFIG_SCSI) += scsi.o - +obj-$(CONFIG_SCSI) += scsi.o scsi-uclass.o ifdef CONFIG_SCSI -ifdef CONFIG_DM_SCSI obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += scsi_bootdev.o +obj-$(CONFIG_SANDBOX) += sandbox_scsi.o +obj-$(CONFIG_SANDBOX) += scsi_emul.o endif endif -endif - ifdef CONFIG_SPL_BUILD ifdef CONFIG_SPL_SATA -obj-$(CONFIG_DM_SCSI) += scsi-uclass.o -obj-$(CONFIG_SCSI) += scsi.o +obj-$(CONFIG_SCSI) += scsi.o scsi-uclass.o endif endif - -ifdef CONFIG_SCSI -obj-$(CONFIG_SANDBOX) += sandbox_scsi.o -obj-$(CONFIG_SANDBOX) += scsi_emul.o -endif diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 1330482..79ee400 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -21,38 +21,10 @@ #include <dm/device-internal.h> #include <dm/uclass-internal.h> -#if !defined(CONFIG_DM_SCSI) -# ifdef CFG_SCSI_DEV_LIST -# define SCSI_DEV_LIST CFG_SCSI_DEV_LIST -# else -# ifdef CONFIG_SATA_ULI5288 - -# define SCSI_VEND_ID 0x10b9 -# define SCSI_DEV_ID 0x5288 - -# elif !defined(CONFIG_SCSI_AHCI_PLAT) -# error no scsi device defined -# endif -# define SCSI_DEV_LIST {SCSI_VEND_ID, SCSI_DEV_ID} -# endif -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \ - !defined(CONFIG_DM_SCSI) -const struct pci_device_id scsi_device_list[] = { SCSI_DEV_LIST }; -#endif static struct scsi_cmd tempccb; /* temporary scsi command buffer */ DEFINE_CACHE_ALIGN_BUFFER(u8, tempbuff, 512); /* temporary data buffer */ -#if !defined(CONFIG_DM_SCSI) -static int scsi_max_devs; /* number of highest available scsi device */ - -static int scsi_curr_dev; /* current device */ - -static struct blk_desc scsi_dev_desc[SCSI_MAX_DEVICE]; -#endif - /* almost the maximum amount of the scsi_ext command.. */ #define SCSI_MAX_BLK 0xFFFF #define SCSI_LBA48_READ 0xFFFFFFF @@ -107,7 +79,6 @@ static void scsi_setup_inquiry(struct scsi_cmd *pccb) pccb->msgout[0] = SCSI_IDENTIFY; /* NOT USED */ } -#ifdef CONFIG_BLK static void scsi_setup_read_ext(struct scsi_cmd *pccb, lbaint_t start, unsigned short blocks) { @@ -286,59 +257,6 @@ static int scsi_buffer_aligned(struct udevice *dev, struct bounce_buffer *state) return 1; } #endif /* CONFIG_BOUNCE_BUFFER */ -#endif - -#if defined(CONFIG_PCI) && !defined(CONFIG_SCSI_AHCI_PLAT) && \ - !defined(CONFIG_DM_SCSI) -void scsi_init(void) -{ - int busdevfunc = -1; - int i; - /* - * Find a device from the list, this driver will support a single - * controller. - */ - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - /* get PCI Device ID */ - struct udevice *dev; - int ret; - - ret = dm_pci_find_device(scsi_device_list[i].vendor, - scsi_device_list[i].device, 0, &dev); - if (!ret) { - busdevfunc = dm_pci_get_bdf(dev); - break; - } - if (busdevfunc != -1) - break; - } - - if (busdevfunc == -1) { - printf("Error: SCSI Controller(s) "); - for (i = 0; i < ARRAY_SIZE(scsi_device_list); i++) { - printf("%04X:%04X ", - scsi_device_list[i].vendor, - scsi_device_list[i].device); - } - printf("not found\n"); - return; - } -#ifdef DEBUG - else { - printf("SCSI Controller (%04X,%04X) found (%d:%d:%d)\n", - scsi_device_list[i].vendor, - scsi_device_list[i].device, - (busdevfunc >> 16) & 0xFF, - (busdevfunc >> 11) & 0x1F, - (busdevfunc >> 8) & 0x7); - } -#endif - bootstage_start(BOOTSTAGE_ID_ACCUM_SCSI, "ahci"); - scsi_low_level_init(busdevfunc); - scsi_scan(true); - bootstage_accum(BOOTSTAGE_ID_ACCUM_SCSI); -} -#endif /* copy src to dest, skipping leading and trailing blanks * and null terminate the string @@ -462,25 +380,6 @@ static void scsi_init_dev_desc_priv(struct blk_desc *dev_desc) #endif /* CONFIG_BOUNCE_BUFFER */ } -#if !defined(CONFIG_DM_SCSI) -/** - * scsi_init_dev_desc - initialize all SCSI specific blk_desc properties - * - * @dev_desc: Block device description pointer - * @devnum: Device number - */ -static void scsi_init_dev_desc(struct blk_desc *dev_desc, int devnum) -{ - dev_desc->lba = 0; - dev_desc->blksz = 0; - dev_desc->uclass_id = UCLASS_SCSI; - dev_desc->devnum = devnum; - dev_desc->part_type = PART_TYPE_UNKNOWN; - - scsi_init_dev_desc_priv(dev_desc); -} -#endif - /** * scsi_detect_dev - Detect scsi device * @@ -569,7 +468,6 @@ removable: * (re)-scan the scsi bus and reports scsi device info * to the user if mode = 1 */ -#if defined(CONFIG_DM_SCSI) static int do_scsi_scan_one(struct udevice *dev, int id, int lun, bool verbose) { int ret; @@ -690,48 +588,7 @@ int scsi_scan(bool verbose) return 0; } -#else -int scsi_scan(bool verbose) -{ - unsigned char i, lun; - int ret; - - if (verbose) - printf("scanning bus for devices...\n"); - for (i = 0; i < SCSI_MAX_DEVICE; i++) - scsi_init_dev_desc(&scsi_dev_desc[i], i); - - scsi_max_devs = 0; - for (i = 0; i < CONFIG_SYS_SCSI_MAX_SCSI_ID; i++) { - for (lun = 0; lun < CONFIG_SYS_SCSI_MAX_LUN; lun++) { - struct blk_desc *bdesc = &scsi_dev_desc[scsi_max_devs]; - - ret = scsi_detect_dev(NULL, i, lun, bdesc); - if (ret) - continue; - part_init(bdesc); - - if (verbose) { - printf(" Device %d: ", bdesc->devnum); - dev_print(bdesc); - } - scsi_max_devs++; - } /* next LUN */ - } - if (scsi_max_devs > 0) - scsi_curr_dev = 0; - else - scsi_curr_dev = -1; - - printf("Found %d device(s).\n", scsi_max_devs); -#ifndef CONFIG_SPL_BUILD - env_set_ulong("scsidevs", scsi_max_devs); -#endif - return 0; -} -#endif -#ifdef CONFIG_BLK static const struct blk_ops scsi_blk_ops = { .read = scsi_read, .write = scsi_write, @@ -745,11 +602,3 @@ U_BOOT_DRIVER(scsi_blk) = { .id = UCLASS_BLK, .ops = &scsi_blk_ops, }; -#else -U_BOOT_LEGACY_BLK(scsi) = { - .uclass_idname = "scsi", - .uclass_id = UCLASS_SCSI, - .max_devs = SCSI_MAX_DEVICE, - .desc = scsi_dev_desc, -}; -#endif diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c index 78fd938..b8bc614 100644 --- a/drivers/serial/serial_msm_geni.c +++ b/drivers/serial/serial_msm_geni.c @@ -13,14 +13,13 @@ #include <dm.h> #include <errno.h> #include <linux/delay.h> +#include <linux/time.h> #include <misc.h> #include <serial.h> #define UART_OVERSAMPLING 32 #define STALE_TIMEOUT 160 -#define USEC_PER_SEC 1000000L - /* Registers*/ #define GENI_FORCE_DEFAULT_REG 0x20 #define GENI_SER_M_CLK_CFG 0x48 diff --git a/drivers/serial/serial_npcm.c b/drivers/serial/serial_npcm.c index 76ac7cb..6bf3a94 100644 --- a/drivers/serial/serial_npcm.c +++ b/drivers/serial/serial_npcm.c @@ -83,8 +83,11 @@ static int npcm_serial_setbrg(struct udevice *dev, int baudrate) struct npcm_uart *uart = plat->reg; u16 divisor; + if (IS_ENABLED(CONFIG_SYS_SKIP_UART_INIT)) + return 0; + /* BaudOut = UART Clock / (16 * [Divisor + 2]) */ - divisor = DIV_ROUND_CLOSEST(plat->uart_clk, 16 * baudrate + 2) - 2; + divisor = DIV_ROUND_CLOSEST(plat->uart_clk, 16 * baudrate) - 2; setbits_8(&uart->lcr, LCR_DLAB); writeb(divisor & 0xff, &uart->dll); @@ -97,29 +100,35 @@ static int npcm_serial_setbrg(struct udevice *dev, int baudrate) static int npcm_serial_probe(struct udevice *dev) { struct npcm_serial_plat *plat = dev_get_plat(dev); - struct npcm_uart *uart = plat->reg; + struct npcm_uart *uart; struct clk clk, parent; u32 freq; int ret; plat->reg = dev_read_addr_ptr(dev); - freq = dev_read_u32_default(dev, "clock-frequency", 0); + uart = plat->reg; - ret = clk_get_by_index(dev, 0, &clk); - if (ret < 0) - return ret; + if (!IS_ENABLED(CONFIG_SYS_SKIP_UART_INIT)) { + freq = dev_read_u32_default(dev, "clock-frequency", 24000000); - ret = clk_get_by_index(dev, 1, &parent); - if (!ret) { - ret = clk_set_parent(&clk, &parent); - if (ret) + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) return ret; - } - ret = clk_set_rate(&clk, freq); - if (ret < 0) - return ret; - plat->uart_clk = ret; + ret = clk_get_by_index(dev, 1, &parent); + if (!ret) { + ret = clk_set_parent(&clk, &parent); + if (ret) + return ret; + } + + if (freq) { + ret = clk_set_rate(&clk, freq); + if (ret < 0) + return ret; + } + plat->uart_clk = clk_get_rate(&clk); + } /* Disable all interrupt */ writeb(0, &uart->ier); diff --git a/drivers/serial/serial_stm32.c b/drivers/serial/serial_stm32.c index 23d476f..fb03954 100644 --- a/drivers/serial/serial_stm32.c +++ b/drivers/serial/serial_stm32.c @@ -30,7 +30,7 @@ */ #define ONE_BYTE_B115200_US 87 -static void _stm32_serial_setbrg(fdt_addr_t base, +static void _stm32_serial_setbrg(void __iomem *base, struct stm32_uart_info *uart_info, u32 clock_rate, int baudrate) @@ -75,7 +75,7 @@ static int stm32_serial_setconfig(struct udevice *dev, uint serial_config) struct stm32x7_serial_plat *plat = dev_get_plat(dev); bool stm32f4 = plat->uart_info->stm32f4; u8 uart_enable_bit = plat->uart_info->uart_enable_bit; - u32 cr1 = plat->base + CR1_OFFSET(stm32f4); + void __iomem *cr1 = plat->base + CR1_OFFSET(stm32f4); u32 config = 0; uint parity = SERIAL_GET_PARITY(serial_config); uint bits = SERIAL_GET_BITS(serial_config); @@ -122,7 +122,7 @@ static int stm32_serial_getc(struct udevice *dev) { struct stm32x7_serial_plat *plat = dev_get_plat(dev); bool stm32f4 = plat->uart_info->stm32f4; - fdt_addr_t base = plat->base; + void __iomem *base = plat->base; u32 isr = readl(base + ISR_OFFSET(stm32f4)); if ((isr & USART_ISR_RXNE) == 0) @@ -141,7 +141,7 @@ static int stm32_serial_getc(struct udevice *dev) return readl(base + RDR_OFFSET(stm32f4)); } -static int _stm32_serial_putc(fdt_addr_t base, +static int _stm32_serial_putc(void __iomem *base, struct stm32_uart_info *uart_info, const char c) { @@ -166,7 +166,7 @@ static int stm32_serial_pending(struct udevice *dev, bool input) { struct stm32x7_serial_plat *plat = dev_get_plat(dev); bool stm32f4 = plat->uart_info->stm32f4; - fdt_addr_t base = plat->base; + void __iomem *base = plat->base; if (input) return readl(base + ISR_OFFSET(stm32f4)) & @@ -176,7 +176,7 @@ static int stm32_serial_pending(struct udevice *dev, bool input) USART_ISR_TXE ? 0 : 1; } -static void _stm32_serial_init(fdt_addr_t base, +static void _stm32_serial_init(void __iomem *base, struct stm32_uart_info *uart_info) { bool stm32f4 = uart_info->stm32f4; @@ -250,11 +250,14 @@ static const struct udevice_id stm32_serial_id[] = { static int stm32_serial_of_to_plat(struct udevice *dev) { struct stm32x7_serial_plat *plat = dev_get_plat(dev); + fdt_addr_t addr; - plat->base = dev_read_addr(dev); - if (plat->base == FDT_ADDR_T_NONE) + addr = dev_read_addr(dev); + if (addr == FDT_ADDR_T_NONE) return -EINVAL; + plat->base = (void __iomem *)addr; + return 0; } @@ -297,7 +300,7 @@ static inline struct stm32_uart_info *_debug_uart_info(void) static inline void _debug_uart_init(void) { - fdt_addr_t base = CONFIG_VAL(DEBUG_UART_BASE); + void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE); struct stm32_uart_info *uart_info = _debug_uart_info(); _stm32_serial_init(base, uart_info); @@ -308,7 +311,7 @@ static inline void _debug_uart_init(void) static inline void _debug_uart_putc(int c) { - fdt_addr_t base = CONFIG_VAL(DEBUG_UART_BASE); + void __iomem *base = (void __iomem *)CONFIG_VAL(DEBUG_UART_BASE); struct stm32_uart_info *uart_info = _debug_uart_info(); while (_stm32_serial_putc(base, uart_info, c) == -EAGAIN) diff --git a/drivers/serial/serial_stm32.h b/drivers/serial/serial_stm32.h index b7e7a90..d2c92ba 100644 --- a/drivers/serial/serial_stm32.h +++ b/drivers/serial/serial_stm32.h @@ -49,7 +49,7 @@ struct stm32_uart_info stm32h7_info = { /* Information about a serial port */ struct stm32x7_serial_plat { - fdt_addr_t base; /* address of registers in physical memory */ + void __iomem *base; /* address of registers in physical memory */ struct stm32_uart_info *uart_info; unsigned long int clock_rate; }; diff --git a/drivers/soc/ti/keystone_serdes.c b/drivers/soc/ti/keystone_serdes.c index 2ece1a8..0e1bf8f 100644 --- a/drivers/soc/ti/keystone_serdes.c +++ b/drivers/soc/ti/keystone_serdes.c @@ -8,6 +8,7 @@ #include <errno.h> #include <common.h> +#include <asm/io.h> #include <asm/ti-common/keystone_serdes.h> #include <linux/bitops.h> diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c index a24bb43..19d9a5a 100644 --- a/drivers/spi/bcm63xx_hsspi.c +++ b/drivers/spi/bcm63xx_hsspi.c @@ -295,7 +295,7 @@ static int bcm63xx_hsspi_xfer_dummy_cs(struct udevice *dev, unsigned int data_by /* transfer loop */ while (data_bytes > 0) { - size_t curr_step = min(step_size, data_bytes); + size_t curr_step = min(step_size, (size_t)data_bytes); int ret; /* copy tx data */ diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index cc3a54f..dfc74c8 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -7,7 +7,6 @@ #include <common.h> #include <clk.h> #include <log.h> -#include <asm-generic/io.h> #include <dm.h> #include <fdtdec.h> #include <malloc.h> @@ -17,13 +16,13 @@ #include <dm/device_compat.h> #include <linux/err.h> #include <linux/errno.h> +#include <linux/io.h> #include <linux/sizes.h> +#include <linux/time.h> #include <zynqmp_firmware.h> #include "cadence_qspi.h" #include <dt-bindings/power/xlnx-versal-power.h> -#define NSEC_PER_SEC 1000000000L - #define CQSPI_STIG_READ 0 #define CQSPI_STIG_WRITE 1 #define CQSPI_READ 2 @@ -40,6 +39,11 @@ __weak int cadence_qspi_versal_flash_reset(struct udevice *dev) return 0; } +__weak ofnode cadence_qspi_get_subnode(struct udevice *dev) +{ + return dev_read_first_subnode(dev); +} + static int cadence_spi_write_speed(struct udevice *bus, uint hz) { struct cadence_spi_priv *priv = dev_get_priv(bus); @@ -401,7 +405,7 @@ static int cadence_spi_of_to_plat(struct udevice *bus) plat->is_dma = dev_read_bool(bus, "cdns,is-dma"); /* All other parameters are embedded in the child node */ - subnode = dev_read_first_subnode(bus); + subnode = cadence_qspi_get_subnode(bus); if (!ofnode_valid(subnode)) { printf("Error: subnode with SPI flash config missing!\n"); return -ENODEV; diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index 1c59d1a..12825f8 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -304,6 +304,7 @@ int cadence_qspi_apb_dma_read(struct cadence_spi_priv *priv, int cadence_qspi_apb_wait_for_dma_cmplt(struct cadence_spi_priv *priv); int cadence_qspi_apb_exec_flash_cmd(void *reg_base, unsigned int reg); int cadence_qspi_versal_flash_reset(struct udevice *dev); +ofnode cadence_qspi_get_subnode(struct udevice *dev); void cadence_qspi_apb_enable_linear_mode(bool enable); #endif /* __CADENCE_QSPI_H__ */ diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 9ce2c0f..d033184 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -171,8 +171,7 @@ static unsigned int cadence_qspi_wait_idle(void *reg_base) } /* Timeout, still in busy mode. */ - printf("QSPI: QSPI is still busy after poll for %d times.\n", - CQSPI_REG_RETRY); + printf("QSPI: QSPI is still busy after poll for %d ms.\n", timeout); return 0; } diff --git a/drivers/spi/fsl_dspi.c b/drivers/spi/fsl_dspi.c index f8ec268..9b3d5a9 100644 --- a/drivers/spi/fsl_dspi.c +++ b/drivers/spi/fsl_dspi.c @@ -14,7 +14,6 @@ #include <common.h> #include <dm.h> #include <errno.h> -#include <common.h> #include <log.h> #include <spi.h> #include <malloc.h> @@ -27,9 +26,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/printk.h> - -/* linux/include/time.h */ -#define NSEC_PER_SEC 1000000000L +#include <linux/time.h> DECLARE_GLOBAL_DATA_PTR; diff --git a/drivers/spi/meson_spifc_a1.c b/drivers/spi/meson_spifc_a1.c index 099c4c0..cca4deb 100644 --- a/drivers/spi/meson_spifc_a1.c +++ b/drivers/spi/meson_spifc_a1.c @@ -16,6 +16,7 @@ #include <spi-mem.h> #include <asm/io.h> #include <linux/log2.h> +#include <linux/time.h> #include <linux/iopoll.h> #include <linux/bitfield.h> @@ -117,7 +118,7 @@ static int amlogic_spifc_a1_request(struct amlogic_spifc_a1 *spifc, bool read) return readl_poll_timeout(spifc->base + SPIFC_A1_USER_CTRL0_REG, val, (val & mask) == mask, - 200 * 1000); + 200 * USEC_PER_MSEC); } static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1 *spifc, @@ -129,7 +130,7 @@ static void amlogic_spifc_a1_drain_buffer(struct amlogic_spifc_a1 *spifc, writel(SPIFC_A1_DBUF_AUTO_UPDATE_ADDR, spifc->base + SPIFC_A1_DBUF_CTRL_REG); - readsl(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count); + ioread32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count); if (pad) { data = readl(spifc->base + SPIFC_A1_DBUF_DATA_REG); @@ -146,7 +147,7 @@ static void amlogic_spifc_a1_fill_buffer(struct amlogic_spifc_a1 *spifc, writel(SPIFC_A1_DBUF_DIR | SPIFC_A1_DBUF_AUTO_UPDATE_ADDR, spifc->base + SPIFC_A1_DBUF_CTRL_REG); - writesl(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count); + iowrite32_rep(spifc->base + SPIFC_A1_DBUF_DATA_REG, buf, count); if (pad) { memcpy(&data, buf + len - pad, pad); diff --git a/drivers/spi/spi-mem-nodm.c b/drivers/spi/spi-mem-nodm.c index 6ee8413..6d9ab61 100644 --- a/drivers/spi/spi-mem-nodm.c +++ b/drivers/spi/spi-mem-nodm.c @@ -3,6 +3,7 @@ * Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/ */ +#include <errno.h> #include <log.h> #include <malloc.h> #include <spi.h> diff --git a/drivers/spi/xilinx_spi.c b/drivers/spi/xilinx_spi.c index b58a3f6..94ddf49 100644 --- a/drivers/spi/xilinx_spi.c +++ b/drivers/spi/xilinx_spi.c @@ -67,7 +67,7 @@ /* SPI Slave Select Register (spissr), [1] p13, [2] p13 */ #define SPISSR_MASK(cs) (1 << (cs)) #define SPISSR_ACT(cs) ~SPISSR_MASK(cs) -#define SPISSR_OFF ~0UL +#define SPISSR_OFF (~0U) /* SPI Software Reset Register (ssr) */ #define SPISSR_RESET_VALUE 0x0a @@ -109,6 +109,27 @@ struct xilinx_spi_priv { u8 startup; }; +static int xilinx_spi_find_buffer_size(struct xilinx_spi_regs *regs) +{ + u8 sr; + int n_words = 0; + + /* + * Before the buffer_size detection reset the core + * to make sure to start with a clean state. + */ + writel(SPISSR_RESET_VALUE, ®s->srr); + + /* Fill the Tx FIFO with as many words as possible */ + do { + writel(0, ®s->spidtr); + sr = readl(®s->spisr); + n_words++; + } while (!(sr & SPISR_TX_FULL)); + + return n_words; +} + static int xilinx_spi_probe(struct udevice *bus) { struct xilinx_spi_priv *priv = dev_get_priv(bus); @@ -116,6 +137,8 @@ static int xilinx_spi_probe(struct udevice *bus) regs = priv->regs = dev_read_addr_ptr(bus); priv->fifo_depth = dev_read_u32_default(bus, "fifo-size", 0); + if (!priv->fifo_depth) + priv->fifo_depth = xilinx_spi_find_buffer_size(regs); writel(SPISSR_RESET_VALUE, ®s->srr); @@ -217,9 +240,9 @@ static u32 xilinx_spi_read_rxfifo(struct udevice *bus, u8 *rxp, u32 rxbytes) return i; } -static int start_transfer(struct spi_slave *spi, const void *dout, void *din, u32 len) +static int start_transfer(struct udevice *dev, const void *dout, void *din, u32 len) { - struct udevice *bus = spi->dev->parent; + struct udevice *bus = dev->parent; struct xilinx_spi_priv *priv = dev_get_priv(bus); struct xilinx_spi_regs *regs = priv->regs; u32 count, txbytes, rxbytes; @@ -259,10 +282,9 @@ static int start_transfer(struct spi_slave *spi, const void *dout, void *din, u3 return 0; } -static void xilinx_spi_startup_block(struct spi_slave *spi) +static void xilinx_spi_startup_block(struct udevice *dev) { - struct dm_spi_slave_plat *slave_plat = - dev_get_parent_plat(spi->dev); + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); unsigned char txp; unsigned char rxp[8]; @@ -270,13 +292,25 @@ static void xilinx_spi_startup_block(struct spi_slave *spi) * Perform a dummy read as a work around for * the startup block issue. */ - spi_cs_activate(spi->dev, slave_plat->cs); + spi_cs_activate(dev, slave_plat->cs); txp = 0x9f; - start_transfer(spi, (void *)&txp, NULL, 1); + start_transfer(dev, (void *)&txp, NULL, 1); - start_transfer(spi, NULL, (void *)rxp, 6); + start_transfer(dev, NULL, (void *)rxp, 6); - spi_cs_deactivate(spi->dev); + spi_cs_deactivate(dev); +} + +static int xilinx_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct dm_spi_slave_plat *slave_plat = dev_get_parent_plat(dev); + int ret; + + spi_cs_activate(dev, slave_plat->cs); + ret = start_transfer(dev, dout, din, bitlen / 8); + spi_cs_deactivate(dev); + return ret; } static int xilinx_spi_mem_exec_op(struct spi_slave *spi, @@ -294,14 +328,15 @@ static int xilinx_spi_mem_exec_op(struct spi_slave *spi, * as QSPI provides command. So first command fails. */ if (!startup) { - xilinx_spi_startup_block(spi); + xilinx_spi_startup_block(spi->dev); startup++; } spi_cs_activate(spi->dev, slave_plat->cs); if (op->cmd.opcode) { - ret = start_transfer(spi, (void *)&op->cmd.opcode, NULL, 1); + ret = start_transfer(spi->dev, (void *)&op->cmd.opcode, + NULL, 1); if (ret) goto done; } @@ -313,7 +348,7 @@ static int xilinx_spi_mem_exec_op(struct spi_slave *spi, addr_buf[i] = op->addr.val >> (8 * (op->addr.nbytes - i - 1)); - ret = start_transfer(spi, (void *)addr_buf, NULL, + ret = start_transfer(spi->dev, (void *)addr_buf, NULL, op->addr.nbytes); if (ret) goto done; @@ -322,16 +357,16 @@ static int xilinx_spi_mem_exec_op(struct spi_slave *spi, dummy_len = (op->dummy.nbytes * op->data.buswidth) / op->dummy.buswidth; - ret = start_transfer(spi, NULL, NULL, dummy_len); + ret = start_transfer(spi->dev, NULL, NULL, dummy_len); if (ret) goto done; } if (op->data.nbytes) { if (op->data.dir == SPI_MEM_DATA_IN) { - ret = start_transfer(spi, NULL, + ret = start_transfer(spi->dev, NULL, op->data.buf.in, op->data.nbytes); } else { - ret = start_transfer(spi, op->data.buf.out, + ret = start_transfer(spi->dev, op->data.buf.out, NULL, op->data.nbytes); } if (ret) @@ -427,6 +462,7 @@ static const struct spi_controller_mem_ops xilinx_spi_mem_ops = { static const struct dm_spi_ops xilinx_spi_ops = { .claim_bus = xilinx_spi_claim_bus, .release_bus = xilinx_spi_release_bus, + .xfer = xilinx_spi_xfer, .set_speed = xilinx_spi_set_speed, .set_mode = xilinx_spi_set_mode, .mem_ops = &xilinx_spi_mem_ops, diff --git a/drivers/sysinfo/Kconfig b/drivers/sysinfo/Kconfig index e35f7cb..2030e4b 100644 --- a/drivers/sysinfo/Kconfig +++ b/drivers/sysinfo/Kconfig @@ -8,6 +8,13 @@ menuconfig SYSINFO if SYSINFO +config SYSINFO_EXTRA + bool "Show extra information on startup" + help + Enable this to see extra information on startup. Normally only the + model is shown, but with this option the vendor and any prior-stage + firmware's version and date are shown as well. + config SPL_SYSINFO depends on SPL_DM bool "Enable board driver support in SPL" diff --git a/drivers/sysreset/poweroff_gpio.c b/drivers/sysreset/poweroff_gpio.c index a5c24fd..ad04e4b 100644 --- a/drivers/sysreset/poweroff_gpio.c +++ b/drivers/sysreset/poweroff_gpio.c @@ -33,7 +33,7 @@ static int poweroff_gpio_request(struct udevice *dev, enum sysreset_t type) int r; if (type != SYSRESET_POWER_OFF) - return -ENOSYS; + return -EPROTONOSUPPORT; debug("GPIO poweroff\n"); diff --git a/drivers/sysreset/sysreset_psci.c b/drivers/sysreset/sysreset_psci.c index a8a4152..aa09d0b 100644 --- a/drivers/sysreset/sysreset_psci.c +++ b/drivers/sysreset/sysreset_psci.c @@ -25,7 +25,7 @@ static int psci_sysreset_request(struct udevice *dev, enum sysreset_t type) psci_sys_poweroff(); break; default: - return -ENOSYS; + return -EPROTONOSUPPORT; } return -EINPROGRESS; diff --git a/drivers/sysreset/sysreset_sandbox.c b/drivers/sysreset/sysreset_sandbox.c index f485a13..c12eda8 100644 --- a/drivers/sysreset/sysreset_sandbox.c +++ b/drivers/sysreset/sysreset_sandbox.c @@ -21,7 +21,7 @@ static int sandbox_warm_sysreset_request(struct udevice *dev, state->last_sysreset = type; break; default: - return -ENOSYS; + return -EPROTONOSUPPORT; } if (!state->sysreset_allowed[type]) return -EACCES; @@ -70,7 +70,7 @@ static int sandbox_sysreset_request(struct udevice *dev, enum sysreset_t type) return -EACCES; sandbox_exit(); default: - return -ENOSYS; + return -EPROTONOSUPPORT; } if (!state->sysreset_allowed[type]) return -EACCES; diff --git a/drivers/sysreset/sysreset_watchdog.c b/drivers/sysreset/sysreset_watchdog.c index ceada2e..6db5aa7 100644 --- a/drivers/sysreset/sysreset_watchdog.c +++ b/drivers/sysreset/sysreset_watchdog.c @@ -29,7 +29,7 @@ static int wdt_reboot_request(struct udevice *dev, enum sysreset_t type) return ret; break; default: - return -ENOSYS; + return -EPROTONOSUPPORT; } return -EINPROGRESS; diff --git a/drivers/sysreset/sysreset_x86.c b/drivers/sysreset/sysreset_x86.c index 4936fdb..dc772b5 100644 --- a/drivers/sysreset/sysreset_x86.c +++ b/drivers/sysreset/sysreset_x86.c @@ -87,7 +87,7 @@ static int x86_sysreset_request(struct udevice *dev, enum sysreset_t type) return ret; return -EINPROGRESS; default: - return -ENOSYS; + return -EPROTONOSUPPORT; } outb(value, IO_PORT_RESET); diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 9a9b697..47f845c 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -139,6 +139,11 @@ static int enum_services(struct udevice *dev, struct tee_shm **shm, size_t *coun if (ret) return ret; + if (!shm_size) { + *count = 0; + return 0; + } + ret = tee_shm_alloc(dev, shm_size, 0, shm); if (ret) { dev_err(dev, "Failed to allocated shared memory: %d\n", ret); @@ -185,14 +190,15 @@ static int bind_service_drivers(struct udevice *dev) ret = enum_services(dev, &service_list, &service_count, tee_sess, PTA_CMD_GET_DEVICES); - if (!ret) + if (!ret && service_count) ret = bind_service_list(dev, service_list, service_count); tee_shm_free(service_list); + service_list = NULL; ret2 = enum_services(dev, &service_list, &service_count, tee_sess, PTA_CMD_GET_DEVICES_SUPP); - if (!ret2) + if (!ret2 && service_count) ret2 = bind_service_list(dev, service_list, service_count); tee_shm_free(service_list); @@ -841,7 +847,7 @@ static int optee_probe(struct udevice *dev) if (IS_ENABLED(CONFIG_OPTEE_SERVICE_DISCOVERY)) { ret = bind_service_drivers(dev); if (ret) - return ret; + dev_warn(dev, "optee service enumeration failed: %d\n", ret); } else if (IS_ENABLED(CONFIG_RNG_OPTEE)) { /* * Discovery of TAs on the TEE bus is not supported in U-Boot: diff --git a/drivers/timer/dw-apb-timer.c b/drivers/timer/dw-apb-timer.c index b171232..6cd2525 100644 --- a/drivers/timer/dw-apb-timer.c +++ b/drivers/timer/dw-apb-timer.c @@ -13,7 +13,6 @@ #include <reset.h> #include <timer.h> #include <dm/device_compat.h> -#include <linux/kconfig.h> #include <asm/io.h> #include <asm/arch/timer.h> diff --git a/drivers/timer/starfive-timer.c b/drivers/timer/starfive-timer.c index 816402f..6ac7d7f 100644 --- a/drivers/timer/starfive-timer.c +++ b/drivers/timer/starfive-timer.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2022 StarFive, Inc. All rights reserved. - * Author: Lee Kuan Lim <kuanlim.lee@starfivetech.com> + * Author: Kuan Lim Lee <kuanlim.lee@starfivetech.com> */ #include <common.h> @@ -48,8 +48,8 @@ static int starfive_probe(struct udevice *dev) int ret; priv->base = dev_read_addr_ptr(dev); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); + if (!priv->base) + return -EINVAL; timer_channel = dev_read_u32_default(dev, "channel", 0); priv->base = priv->base + (0x40 * timer_channel); @@ -64,14 +64,16 @@ static int starfive_probe(struct udevice *dev) return ret; uc_priv->clock_rate = clk_get_rate(&clk); - /* Initiate timer, channel 0 */ - /* Unmask Interrupt Mask */ + /* + * Initiate timer, channel 0 + * Unmask Interrupt Mask + */ writel(0, priv->base + STF_TIMER_INT_MASK); /* Single run mode Setting */ if (dev_read_bool(dev, "single-run")) writel(1, priv->base + STF_TIMER_CTL); /* Set Reload value */ - priv->timer_size = dev_read_u32_default(dev, "timer-size", 0xffffffff); + priv->timer_size = dev_read_u32_default(dev, "timer-size", -1U); writel(priv->timer_size, priv->base + STF_TIMER_LOAD); /* Enable to start timer */ writel(1, priv->base + STF_TIMER_ENABLE); @@ -85,7 +87,7 @@ static const struct udevice_id starfive_ids[] = { }; U_BOOT_DRIVER(jh8100_starfive_timer) = { - .name = "jh8100_starfive_timer", + .name = "starfive_timer", .id = UCLASS_TIMER, .of_match = starfive_ids, .probe = starfive_probe, diff --git a/drivers/timer/timer-uclass.c b/drivers/timer/timer-uclass.c index 0c2018b..60ff655 100644 --- a/drivers/timer/timer-uclass.c +++ b/drivers/timer/timer-uclass.c @@ -66,13 +66,13 @@ static int timer_pre_probe(struct udevice *dev) err = clk_get_by_index(dev, 0, &timer_clk); if (!err) { ret = clk_get_rate(&timer_clk); - if (IS_ERR_VALUE(ret)) - return ret; - uc_priv->clock_rate = ret; - } else { - uc_priv->clock_rate = - dev_read_u32_default(dev, "clock-frequency", 0); + if (!IS_ERR_VALUE(ret)) { + uc_priv->clock_rate = ret; + return 0; + } } + + uc_priv->clock_rate = dev_read_u32_default(dev, "clock-frequency", 0); } return 0; diff --git a/drivers/tpm/tpm2_tis_core.c b/drivers/tpm/tpm2_tis_core.c index 985a816..81b9210 100644 --- a/drivers/tpm/tpm2_tis_core.c +++ b/drivers/tpm/tpm2_tis_core.c @@ -224,9 +224,6 @@ int tpm_tis_send(struct udevice *dev, const u8 *buf, size_t len) u8 status; int ret; - if (!chip) - return -ENODEV; - ret = tpm_tis_request_locality(dev, 0); if (ret < 0) return -EBUSY; diff --git a/drivers/ufs/Kconfig b/drivers/ufs/Kconfig index 0e0cc58..7da46fa 100644 --- a/drivers/ufs/Kconfig +++ b/drivers/ufs/Kconfig @@ -2,7 +2,7 @@ menu "UFS Host Controller Support" config UFS bool "Support UFS controllers" - depends on DM_SCSI + depends on SCSI select CHARSET help This selects support for Universal Flash Subsystem (UFS). @@ -15,6 +15,17 @@ config CADENCE_UFS This selects the platform driver for the Cadence UFS host controller present on present TI's J721e devices. +config UFS_PCI + bool "PCI bus based UFS Controller support" + depends on PCI && UFS + help + This selects the PCI UFS Host Controller Interface. Select this if + you have UFS Host Controller with PCI Interface. + + If you have a controller with this interface, say Y here. + + If unsure, say N. + config TI_J721E_UFS bool "Glue Layer driver for UFS on TI J721E devices" help diff --git a/drivers/ufs/Makefile b/drivers/ufs/Makefile index 56a4b07..67c4262 100644 --- a/drivers/ufs/Makefile +++ b/drivers/ufs/Makefile @@ -6,4 +6,5 @@ obj-$(CONFIG_UFS) += ufs.o ufs-uclass.o obj-$(CONFIG_CADENCE_UFS) += cdns-platform.o obj-$(CONFIG_TI_J721E_UFS) += ti-j721e-ufs.o +obj-$(CONFIG_UFS_PCI) += ufs-pci.o obj-$(CONFIG_UFS_RENESAS) += ufs-renesas.o diff --git a/drivers/ufs/cdns-platform.c b/drivers/ufs/cdns-platform.c index 9202b53..d1f3469 100644 --- a/drivers/ufs/cdns-platform.c +++ b/drivers/ufs/cdns-platform.c @@ -13,11 +13,10 @@ #include <dm/device_compat.h> #include <linux/bitops.h> #include <linux/err.h> +#include <linux/time.h> #include "ufs.h" -#define USEC_PER_SEC 1000000L - #define CDNS_UFS_REG_HCLKDIV 0xFC #define CDNS_UFS_REG_PHY_XCFGD1 0x113C diff --git a/drivers/ufs/ufs-pci.c b/drivers/ufs/ufs-pci.c new file mode 100644 index 0000000..ad41358 --- /dev/null +++ b/drivers/ufs/ufs-pci.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2023 tinylab.org + * Author: Bin Meng <bmeng@tinylab.org> + */ + +#include <common.h> +#include <dm.h> +#include <errno.h> +#include <pci.h> +#include <ufs.h> +#include <dm/device_compat.h> +#include "ufs.h" + +static int ufs_pci_bind(struct udevice *dev) +{ + struct udevice *scsi_dev; + + return ufs_scsi_bind(dev, &scsi_dev); +} + +static int ufs_pci_probe(struct udevice *dev) +{ + int err; + + err = ufshcd_probe(dev, NULL); + if (err) + dev_err(dev, "%s failed (ret=%d)\n", __func__, err); + + return err; +} + +U_BOOT_DRIVER(ufs_pci) = { + .name = "ufs_pci", + .id = UCLASS_UFS, + .bind = ufs_pci_bind, + .probe = ufs_pci_probe, +}; + +static struct pci_device_id ufs_supported[] = { + { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_UFS) }, + {}, +}; + +U_BOOT_PCI_DEVICE(ufs_pci, ufs_supported); diff --git a/drivers/ufs/ufs-uclass.c b/drivers/ufs/ufs-uclass.c index e6478a9..92fcdf4 100644 --- a/drivers/ufs/ufs-uclass.c +++ b/drivers/ufs/ufs-uclass.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /** - * ufs-uclass.c - Universal Flash Subsystem (UFS) Uclass driver + * ufs-uclass.c - Universal Flash Storage (UFS) Uclass driver * * Copyright (C) 2019 Texas Instruments Incorporated - https://www.ti.com */ diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 346f0fd..e4400f3 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /** - * ufs.c - Universal Flash Subsystem (UFS) driver + * ufs.c - Universal Flash Storage (UFS) driver * * Taken from Linux Kernel v5.2 (drivers/scsi/ufs/ufshcd.c) and ported * to u-boot. @@ -320,7 +320,7 @@ static int ufshcd_disable_tx_lcc(struct ufs_hba *hba, bool peer) UIC_ARG_MPHY_TX_GEN_SEL_INDEX(i)), 0); if (err) { - dev_err(hba->dev, "%s: TX LCC Disable failed, peer = %d, lane = %d, err = %d", + dev_err(hba->dev, "%s: TX LCC Disable failed, peer = %d, lane = %d, err = %d\n", __func__, peer, i, err); break; } @@ -441,7 +441,7 @@ static int ufshcd_make_hba_operational(struct ufs_hba *hba) ufshcd_enable_run_stop_reg(hba); } else { dev_err(hba->dev, - "Host controller not ready to process requests"); + "Host controller not ready to process requests\n"); err = -EIO; goto out; } @@ -930,7 +930,7 @@ static int ufshcd_copy_query_response(struct ufs_hba *hba) memcpy(hba->dev_cmd.query.descriptor, descp, resp_len); } else { dev_warn(hba->dev, - "%s: Response size is bigger than buffer", + "%s: Response size is bigger than buffer\n", __func__); return -EINVAL; } @@ -1179,11 +1179,11 @@ static int ufshcd_read_desc_length(struct ufs_hba *hba, enum desc_idn desc_id, &header_len); if (ret) { - dev_err(hba->dev, "%s: Failed to get descriptor header id %d", + dev_err(hba->dev, "%s: Failed to get descriptor header id %d\n", __func__, desc_id); return ret; } else if (desc_id != header[QUERY_DESC_DESC_TYPE_OFFSET]) { - dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch", + dev_warn(hba->dev, "%s: descriptor header id %d and desc_id %d mismatch\n", __func__, header[QUERY_DESC_DESC_TYPE_OFFSET], desc_id); ret = -EINVAL; @@ -1302,7 +1302,7 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, /* Sanity checks */ if (ret || !buff_len) { - dev_err(hba->dev, "%s: Failed to get full descriptor length", + dev_err(hba->dev, "%s: Failed to get full descriptor length\n", __func__); return ret; } @@ -1323,14 +1323,14 @@ int ufshcd_read_desc_param(struct ufs_hba *hba, enum desc_idn desc_id, &buff_len); if (ret) { - dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d", + dev_err(hba->dev, "%s: Failed reading descriptor. desc_id %d, desc_index %d, param_offset %d, ret %d\n", __func__, desc_id, desc_index, param_offset, ret); goto out; } /* Sanity check */ if (desc_buf[QUERY_DESC_DESC_TYPE_OFFSET] != desc_id) { - dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header", + dev_err(hba->dev, "%s: invalid desc_id %d in descriptor header\n", __func__, desc_buf[QUERY_DESC_DESC_TYPE_OFFSET]); ret = -EINVAL; goto out; @@ -1914,6 +1914,7 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) struct ufs_hba *hba = dev_get_uclass_priv(ufs_dev); struct scsi_plat *scsi_plat; struct udevice *scsi_dev; + void __iomem *mmio_base; int err; device_find_first_child(ufs_dev, &scsi_dev); @@ -1927,7 +1928,14 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) hba->dev = ufs_dev; hba->ops = hba_ops; - hba->mmio_base = dev_read_addr_ptr(ufs_dev); + + if (device_is_on_pci_bus(ufs_dev)) { + mmio_base = dm_pci_map_bar(ufs_dev, PCI_BASE_ADDRESS_0, 0, 0, + PCI_REGION_TYPE, PCI_REGION_MEM); + } else { + mmio_base = dev_read_addr_ptr(ufs_dev); + } + hba->mmio_base = mmio_base; /* Set descriptor lengths to specification defaults */ ufshcd_def_desc_sizes(hba); @@ -1945,7 +1953,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) hba->version != UFSHCI_VERSION_11 && hba->version != UFSHCI_VERSION_20 && hba->version != UFSHCI_VERSION_21 && - hba->version != UFSHCI_VERSION_30) + hba->version != UFSHCI_VERSION_30 && + hba->version != UFSHCI_VERSION_31) dev_err(hba->dev, "invalid UFS version 0x%x\n", hba->version); diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 9daaf03..816a5ce 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -782,6 +782,7 @@ enum { UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */ UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */ + UFSHCI_VERSION_31 = 0x00000310, /* 3.1 */ }; /* Interrupt disable masks */ diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c index 92a7941..2e44aad 100644 --- a/drivers/usb/cdns3/cdns3-ti.c +++ b/drivers/usb/cdns3/cdns3-ti.c @@ -6,7 +6,6 @@ */ #include <common.h> -#include <asm-generic/io.h> #include <clk.h> #include <dm.h> #include <dm/device_compat.h> diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 3aec8b0..4b4fcd8 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -31,6 +31,7 @@ #include <linux/usb/gadget.h> #include <linux/bitfield.h> #include <linux/math64.h> +#include <linux/time.h> #include "core.h" #include "gadget.h" @@ -38,8 +39,6 @@ #include "linux-compat.h" -#define NSEC_PER_SEC 1000000000L - static LIST_HEAD(dwc3_list); /* -------------------------------------------------------------------------- */ diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c index e0356e6..1960352 100644 --- a/drivers/usb/dwc3/dwc3-meson-g12a.c +++ b/drivers/usb/dwc3/dwc3-meson-g12a.c @@ -8,13 +8,13 @@ #include <common.h> #include <log.h> -#include <asm-generic/io.h> #include <dm.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dwc3-uboot.h> #include <generic-phy.h> #include <linux/delay.h> +#include <linux/io.h> #include <linux/printk.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> diff --git a/drivers/usb/dwc3/dwc3-meson-gxl.c b/drivers/usb/dwc3/dwc3-meson-gxl.c index d56f274..cbe8aaa 100644 --- a/drivers/usb/dwc3/dwc3-meson-gxl.c +++ b/drivers/usb/dwc3/dwc3-meson-gxl.c @@ -8,12 +8,12 @@ #define DEBUG #include <common.h> -#include <asm-generic/io.h> #include <dm.h> #include <dm/device-internal.h> #include <dm/lists.h> #include <dwc3-uboot.h> #include <generic-phy.h> +#include <linux/io.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> #include <malloc.h> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 4eccc5e..c72a804 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -17,6 +17,7 @@ menuconfig USB_GADGET bool "USB Gadget Support" depends on DM select DM_USB + imply CMD_BIND help USB is a master/slave protocol, organized with one master host (such as a PC) controlling up to 127 peripheral devices. diff --git a/drivers/usb/gadget/bcm_udc_otg.h b/drivers/usb/gadget/bcm_udc_otg.h index 24cc936..48370f3 100644 --- a/drivers/usb/gadget/bcm_udc_otg.h +++ b/drivers/usb/gadget/bcm_udc_otg.h @@ -6,8 +6,6 @@ #ifndef __BCM_UDC_OTG_H #define __BCM_UDC_OTG_H -#include <common.h> - static inline void wfld_set(uintptr_t addr, uint32_t fld_val, uint32_t fld_mask) { writel(((readl(addr) & ~(fld_mask)) | (fld_val)), (addr)); diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 1d17331..c725aed 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -327,6 +327,7 @@ struct fsg_common { unsigned int short_packet_received:1; unsigned int bad_lun_okay:1; unsigned int running:1; + unsigned int eject:1; int thread_wakeup_needed; struct completion thread_notifier; @@ -669,6 +670,10 @@ static int sleep_thread(struct fsg_common *common) } if (k == 10) { + /* Handle START-STOP UNIT */ + if (common->eject) + return -EPIPE; + /* Handle CTRL+C */ if (ctrlc()) return -EPIPE; @@ -1325,6 +1330,8 @@ static int do_start_stop(struct fsg_common *common) return -EINVAL; } + common->eject = 1; + return 0; } diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c index ee9384f..ca2760c 100644 --- a/drivers/usb/gadget/f_sdp.c +++ b/drivers/usb/gadget/f_sdp.c @@ -744,7 +744,7 @@ static ulong sdp_load_read(struct spl_load_info *load, ulong sector, { debug("%s: sector %lx, count %lx, buf %lx\n", __func__, sector, count, (ulong)buf); - memcpy(buf, (void *)(load->dev + sector), count); + memcpy(buf, (void *)(load->priv + sector), count); return count; } @@ -844,8 +844,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, struct spl_load_info load; debug("Found FIT\n"); - load.dev = header; - load.bl_len = 1; + load.priv = header; + spl_set_bl_len(&load, 1); load.read = sdp_load_read; spl_load_simple_fit(spl_image, &load, 0, header); @@ -857,8 +857,8 @@ static int sdp_handle_in_ep(struct spl_image_info *spl_image, valid_container_hdr((void *)header)) { struct spl_load_info load; - load.dev = header; - load.bl_len = 1; + load.priv = header; + spl_set_bl_len(&load, 1); load.read = sdp_load_read; spl_load_imx_container(spl_image, &load, 0); return SDP_EXIT; diff --git a/drivers/usb/gadget/udc/udc-core.c b/drivers/usb/gadget/udc/udc-core.c index eb0b359..ba658d9 100644 --- a/drivers/usb/gadget/udc/udc-core.c +++ b/drivers/usb/gadget/udc/udc-core.c @@ -323,6 +323,7 @@ err1: int usb_gadget_probe_driver(struct usb_gadget_driver *driver) { struct usb_udc *udc = NULL; + unsigned int udc_count = 0; int ret; if (!driver || !driver->bind || !driver->setup) @@ -330,12 +331,22 @@ int usb_gadget_probe_driver(struct usb_gadget_driver *driver) mutex_lock(&udc_lock); list_for_each_entry(udc, &udc_list, list) { + udc_count++; + /* For now we take the first one */ if (!udc->driver) goto found; } - printf("couldn't find an available UDC\n"); + if (!udc_count) + printf("No UDC available in the system\n"); + else + /* When this happens, users should 'unbind <class> <index>' + * using the output of 'dm tree' and looking at the line right + * after the USB peripheral/device controller. + */ + printf("All UDCs in use (%d available), use the unbind command\n", + udc_count); mutex_unlock(&udc_lock); return -ENODEV; found: diff --git a/drivers/usb/musb-new/musb_io.h b/drivers/usb/musb-new/musb_io.h index 72a5365..19b12f3 100644 --- a/drivers/usb/musb-new/musb_io.h +++ b/drivers/usb/musb-new/musb_io.h @@ -14,31 +14,7 @@ #ifndef __MUSB_LINUX_PLATFORM_ARCH_H__ #define __MUSB_LINUX_PLATFORM_ARCH_H__ -#ifndef __UBOOT__ #include <linux/io.h> -#else -#include <asm/io.h> -#endif - -#if !defined(CONFIG_ARM) && !defined(CONFIG_SUPERH) \ - && !defined(CONFIG_PPC32) \ - && !defined(CONFIG_PPC64) && !defined(CONFIG_MIPS) \ - && !defined(CONFIG_M68K) -static inline void readsl(const void __iomem *addr, void *buf, int len) - { insl((unsigned long)addr, buf, len); } -static inline void readsw(const void __iomem *addr, void *buf, int len) - { insw((unsigned long)addr, buf, len); } -static inline void readsb(const void __iomem *addr, void *buf, int len) - { insb((unsigned long)addr, buf, len); } - -static inline void writesl(const void __iomem *addr, const void *buf, int len) - { outsl((unsigned long)addr, buf, len); } -static inline void writesw(const void __iomem *addr, const void *buf, int len) - { outsw((unsigned long)addr, buf, len); } -static inline void writesb(const void __iomem *addr, const void *buf, int len) - { outsb((unsigned long)addr, buf, len); } - -#endif /* NOTE: these offsets are all in bytes */ diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index ab92764..6f319ba 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -180,7 +180,6 @@ config CONSOLE_ROTATION config CONSOLE_TRUETYPE bool "Support a console that uses TrueType fonts" - select CMD_SELECT_FONT help TrueTrype fonts can provide outline-drawing capability rather than needing to provide a bitmap for each font and size that is needed. diff --git a/drivers/video/dw_mipi_dsi.c b/drivers/video/dw_mipi_dsi.c index 22fef7e..a7e0784 100644 --- a/drivers/video/dw_mipi_dsi.c +++ b/drivers/video/dw_mipi_dsi.c @@ -22,6 +22,7 @@ #include <linux/bitops.h> #include <linux/delay.h> #include <linux/iopoll.h> +#include <linux/time.h> #include <video_bridge.h> #define HWVER_131 0x31333100 /* IP version 1.31 */ @@ -214,8 +215,6 @@ #define PHY_STATUS_TIMEOUT_US 10000 #define CMD_PKT_STATUS_TIMEOUT_US 20000 -#define MSEC_PER_SEC 1000 - struct dw_mipi_dsi { struct mipi_dsi_host dsi_host; struct mipi_dsi_device *device; diff --git a/drivers/video/exynos/exynos_dp.c b/drivers/video/exynos/exynos_dp.c index a532d5a..59838da 100644 --- a/drivers/video/exynos/exynos_dp.c +++ b/drivers/video/exynos/exynos_dp.c @@ -7,7 +7,6 @@ #include <common.h> #include <dm.h> -#include <common.h> #include <display.h> #include <fdtdec.h> #include <log.h> diff --git a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c index 1a5ab78..5e75b6e 100644 --- a/drivers/video/rockchip/dw_mipi_dsi_rockchip.c +++ b/drivers/video/rockchip/dw_mipi_dsi_rockchip.c @@ -30,12 +30,11 @@ #include <asm/io.h> #include <dm/device-internal.h> #include <linux/bitops.h> +#include <linux/time.h> #include <asm/arch-rockchip/clock.h> #include <asm/arch-rockchip/hardware.h> -#define USEC_PER_SEC 1000000L - /* * DSI wrapper registers & bit definitions * Note: registers are named as in the Reference Manual diff --git a/drivers/video/stm32/stm32_ltdc.c b/drivers/video/stm32/stm32_ltdc.c index 6fd90e3..4f60ba8 100644 --- a/drivers/video/stm32/stm32_ltdc.c +++ b/drivers/video/stm32/stm32_ltdc.c @@ -495,6 +495,33 @@ static void stm32_ltdc_set_layer1(struct stm32_ltdc_priv *priv, ulong fb_addr) setbits_le32(priv->regs + LTDC_L1CR, LXCR_LEN); } +#if IS_ENABLED(CONFIG_TARGET_STM32F469_DISCOVERY) +static int stm32_ltdc_alloc_fb(struct udevice *dev) +{ + u32 sdram_size = gd->ram_size; + struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); + phys_addr_t cpu; + dma_addr_t bus; + u64 dma_size; + int ret; + + ret = dev_get_dma_range(dev, &cpu, &bus, &dma_size); + if (ret) { + dev_err(dev, "failed to get dma address\n"); + return ret; + } + + uc_plat->base = bus + sdram_size - ALIGN(uc_plat->size, uc_plat->align); + return 0; +} +#else +static inline int stm32_ltdc_alloc_fb(struct udevice *dev) +{ + /* Delegate framebuffer allocation to video-uclass */ + return 0; +} +#endif + static int stm32_ltdc_probe(struct udevice *dev) { struct video_uc_plat *uc_plat = dev_get_uclass_plat(dev); @@ -605,6 +632,10 @@ static int stm32_ltdc_probe(struct udevice *dev) priv->crop_h = timings.vactive.typ; priv->alpha = 0xFF; + ret = stm32_ltdc_alloc_fb(dev); + if (ret) + return ret; + dev_dbg(dev, "%dx%d %dbpp frame buffer at 0x%lx\n", timings.hactive.typ, timings.vactive.typ, VNBITS(priv->l2bpp), uc_plat->base); diff --git a/drivers/video/tegra20/tegra-dsi.c b/drivers/video/tegra20/tegra-dsi.c index b4cf4fa..a48f9c8 100644 --- a/drivers/video/tegra20/tegra-dsi.c +++ b/drivers/video/tegra20/tegra-dsi.c @@ -14,6 +14,7 @@ #include <panel.h> #include <linux/delay.h> #include <linux/err.h> +#include <linux/time.h> #include <power/regulator.h> #include <asm/gpio.h> @@ -24,9 +25,6 @@ #include "mipi-phy.h" -#define USEC_PER_SEC 1000000L -#define NSEC_PER_SEC 1000000000L - struct tegra_dsi_priv { struct mipi_dsi_host host; struct mipi_dsi_device device; diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index 852f673..1de6886 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -56,7 +56,7 @@ config VIRTIO_SANDBOX config VIRTIO_NET bool "virtio net driver" - depends on VIRTIO + depends on VIRTIO && NETDEVICES help This is the virtual net driver for virtio. It can be used with QEMU based targets. diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index b40a1d2..8eeac93 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c @@ -9,8 +9,7 @@ #include <wdt.h> #include <asm/io.h> #include <linux/delay.h> - -#define MSEC_PER_SEC 1000 +#include <linux/time.h> #define WDT_MAX_TIMEOUT 16 #define WDT_TIMEOUT_MASK 0xf diff --git a/drivers/xen/pvblock.c b/drivers/xen/pvblock.c index 4ad548d..1df04e2 100644 --- a/drivers/xen/pvblock.c +++ b/drivers/xen/pvblock.c @@ -632,7 +632,8 @@ static ulong pvblock_iop(struct udevice *udev, lbaint_t blknr, memcpy(blk_dev->bounce_buffer, buffer, desc->blksz); aiocb.aio_nbytes = unaligned ? desc->blksz : - min((size_t)(BLKIF_MAX_SEGMENTS_PER_REQUEST * PAGE_SIZE), + min((size_t)((BLKIF_MAX_SEGMENTS_PER_REQUEST - 1) + * PAGE_SIZE), (size_t)(blocks_todo * desc->blksz)); blkfront_io(&aiocb, write); |