diff options
239 files changed, 10282 insertions, 2858 deletions
diff --git a/Documentation/boards/stm32mp.rst b/Documentation/boards/stm32mp.rst index f93ec04eb0..6d97b0d6d4 100644 --- a/Documentation/boards/stm32mp.rst +++ b/Documentation/boards/stm32mp.rst @@ -81,3 +81,13 @@ pulled down and BOOT0 and BOOT2 are connected to a 2P DIP switch:: BOOT2 | O --O | BOOT0 | N --O | <---- DFU on UART and USB OTG +-------+ + +Boot status indicator +--------------------- + +The ROM code on the first Cortex-A7 core pulses the PA13 pad. +An error LED on this pad can be used to indicate boot status: + +* **Boot Failure:** LED lights bright +* **UART/USB Boot:** LED blinks fast +* **Debug access:** LED lights weak diff --git a/Documentation/gen_commands.py b/Documentation/gen_commands.py index 203a39bb11..a55b1acd82 100755 --- a/Documentation/gen_commands.py +++ b/Documentation/gen_commands.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python from __future__ import print_function diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst index 029e463540..4c1b2925f2 100644 --- a/Documentation/user/usb.rst +++ b/Documentation/user/usb.rst @@ -172,7 +172,7 @@ and initrd: .. code-block:: sh - #!/bin/bash + #!/usr/bin/env bash set -e set -v @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Print statistics when we exit trap exit 1 2 3 15 @@ -1,5 +1,5 @@ VERSION = 2019 -PATCHLEVEL = 11 +PATCHLEVEL = 12 SUBLEVEL = 0 EXTRAVERSION = NAME = None @@ -225,6 +225,21 @@ are the release rules: people. +Contributing +------------ + +For any questions regarding Barebox, send a mail to the mailing list at +<barebox@lists.infradead.org>. The archives for this list are available +publicly at <http://lists.infradead.org/pipermail/barebox/> and +<https://www.mail-archive.com/barebox@lists.infradead.org/>. + +The same list should also be used to send patches. Barebox uses a similar +process as the Linux kernel, so most of the Linux guide for submitting patches +<https://www.kernel.org/doc/html/latest/process/submitting-patches.html> also +applies to Barebox (except the step for selecting your recipient - we don't +have a MAINTAINERS file, instead all patches go to the list). + + License ------- diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 6eb117487e..dfb18777b2 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -106,6 +106,9 @@ config ARCH_LAYERSCAPE select COMMON_CLK select CLKDEV_LOOKUP select COMMON_CLK_OF_PROVIDER + select HW_HAS_PCI + select OFTREE + select OFDEVICE config ARCH_MVEBU bool "Marvell EBU platforms" @@ -434,6 +437,7 @@ config ARM_SMCCC This option enables barebox to invoke ARM secure monitor calls. config ARM_SECURE_MONITOR + depends on CPU_32v7 || CPU_64v8 select ARM_SMCCC bool help @@ -453,6 +457,7 @@ config ARM_PSCI config ARM_PSCI_CLIENT bool "Enable barebox PSCI client support" + depends on CPU_32v7 || CPU_64v8 select ARM_SMCCC select ARM_PSCI_OF help diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 13e8cee286..740b0790e7 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -141,6 +141,9 @@ CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) CPPFLAGS += -fdata-sections -ffunction-sections LDFLAGS_barebox += --gc-sections +# early code often runs at addresses we are not linked at +CPPFLAGS += -fPIE + ifdef CONFIG_RELOCATABLE LDFLAGS_barebox += -pie else diff --git a/arch/arm/boards/embedsky-e9/board.c b/arch/arm/boards/embedsky-e9/board.c index 0f47677bb0..e5f92636fb 100644 --- a/arch/arm/boards/embedsky-e9/board.c +++ b/arch/arm/boards/embedsky-e9/board.c @@ -22,7 +22,6 @@ #include <init.h> #include <environment.h> #include <mach/imx6-regs.h> -#include <gpio.h> #include <asm/armlinux.h> #include <generated/mach-types.h> #include <partition.h> @@ -102,8 +101,4 @@ static int e9_coredevices_init(void) return 0; } -/* - * Do this before the fec initializes but after our - * gpios are available. - */ coredevice_initcall(e9_coredevices_init); diff --git a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c index 76d6f5ba86..77d92f0403 100644 --- a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c +++ b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c @@ -145,14 +145,14 @@ static iomux_v3_cfg_t eukrea_cpuimx25_pads[] = { #ifndef CONFIG_USB_GADGET struct imxusb_platformdata otg_pdata = { .flags = MXC_EHCI_INTERFACE_DIFF_UNI, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, .phymode = USBPHY_INTERFACE_MODE_UTMI, }; #endif struct imxusb_platformdata hs_pdata = { .flags = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, }; #endif diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c index a10763780e..220a484bde 100644 --- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c +++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c @@ -95,14 +95,14 @@ static struct imx_ipu_fb_platform_data ipu_fb_data = { #ifndef CONFIG_USB_GADGET struct imxusb_platformdata otg_pdata = { .flags = MXC_EHCI_INTERFACE_DIFF_UNI, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, .phymode = USBPHY_INTERFACE_MODE_UTMI, }; #endif struct imxusb_platformdata hs_pdata = { .flags = MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN, - .mode = IMX_USB_MODE_HOST, + .mode = USB_DR_MODE_HOST, }; #endif diff --git a/arch/arm/boards/freescale-mx6-sabresd/board.c b/arch/arm/boards/freescale-mx6-sabresd/board.c index 595b1eae0b..a5059835df 100644 --- a/arch/arm/boards/freescale-mx6-sabresd/board.c +++ b/arch/arm/boards/freescale-mx6-sabresd/board.c @@ -19,7 +19,6 @@ #include <init.h> #include <environment.h> #include <mach/imx6-regs.h> -#include <gpio.h> #include <asm/armlinux.h> #include <generated/mach-types.h> #include <partition.h> @@ -84,8 +83,4 @@ static int sabresd_coredevices_init(void) return 0; } -/* - * Do this before the fec initializes but after our - * gpios are available. - */ coredevice_initcall(sabresd_coredevices_init); diff --git a/arch/arm/boards/ls1046ardb/board.c b/arch/arm/boards/ls1046ardb/board.c index 0846df9fad..ef68e9c7f9 100644 --- a/arch/arm/boards/ls1046ardb/board.c +++ b/arch/arm/boards/ls1046ardb/board.c @@ -2,13 +2,132 @@ #include <common.h> #include <init.h> +#include <bbu.h> +#include <net.h> +#include <crc.h> +#include <fs.h> #include <envfs.h> +#include <libfile.h> #include <asm/memory.h> #include <linux/sizes.h> #include <linux/clk.h> #include <linux/clkdev.h> #include <asm/system.h> #include <mach/layerscape.h> +#include <mach/bbu.h> + +#define MAX_NUM_PORTS 16 +struct nxid { + u8 id[4]; /* 0x00 - 0x03 EEPROM Tag 'NXID' */ + u8 sn[12]; /* 0x04 - 0x0F Serial Number */ + u8 errata[5]; /* 0x10 - 0x14 Errata Level */ + u8 date[6]; /* 0x15 - 0x1a Build Date */ + u8 res_0; /* 0x1b Reserved */ + u32 version; /* 0x1c - 0x1f NXID Version */ + u8 tempcal[8]; /* 0x20 - 0x27 Temperature Calibration Factors */ + u8 tempcalsys[2]; /* 0x28 - 0x29 System Temperature Calibration Factors */ + u8 tempcalflags; /* 0x2a Temperature Calibration Flags */ + u8 res_1[21]; /* 0x2b - 0x3f Reserved */ + u8 mac_count; /* 0x40 Number of MAC addresses */ + u8 mac_flag; /* 0x41 MAC table flags */ + u8 mac[MAX_NUM_PORTS][6]; /* 0x42 - 0xa1 MAC addresses */ + u8 res_2[90]; /* 0xa2 - 0xfb Reserved */ + u32 crc; /* 0xfc - 0xff CRC32 checksum */ +} __packed; + +static int nxid_is_valid(struct nxid *nxid) +{ + unsigned char id[] = { 'N', 'X', 'I', 'D' }; + int i; + + for (i = 0; i < ARRAY_SIZE(id); i++) + if (nxid->id[i] != id[i]) + return false; + return true; +} + +static struct nxid *nxp_nxid_read(const char *filename, unsigned int offset) +{ + struct nxid *nxid; + int fd, ret, i, n; + struct device_node *root; + u32 crc, crc_expected; + + nxid = xzalloc(sizeof(*nxid)); + + fd = open(filename, O_RDONLY); + if (fd < 0) { + ret = -errno; + goto out; + } + + ret = pread(fd, nxid, sizeof(*nxid), offset); + if (ret < 0) { + close(fd); + goto out; + } + + if (!nxid_is_valid(nxid)) { + ret = -ENODEV; + goto out; + } + + crc = crc32(0, nxid, 256 - 4); + crc_expected = be32_to_cpu(nxid->crc); + if (crc != crc_expected) { + pr_err("CRC mismatch (%08x != %08x)\n", crc, crc_expected); + ret = -EINVAL; + goto out; + } + + root = of_get_root_node(); + + i = n = 0; + + /* + * The MAC addresses in the nxid structure are in the order of enabled + * network interfaces. We have to find the network interfaces by their + * aliases and skip assigning MAC addresses to disabled devices. + */ + while (1) { + struct device_node *np; + char alias[sizeof("ethernetxxx")]; + + sprintf(alias, "ethernet%d", n); + + np = of_find_node_by_alias(root, alias); + if (!np) + goto out; + + n++; + if (!of_device_is_available(np)) + continue; + + of_eth_register_ethaddr(np, (char *)nxid->mac[i]); + + i++; + + if (i == nxid->mac_count) + break; + } + + ret = 0; +out: + if (ret) { + free(nxid); + nxid = ERR_PTR(ret); + } + + return nxid; +} + +static int rdb_late_init(void) +{ + nxp_nxid_read("/dev/eeprom", 256); + + return 0; +} +late_initcall(rdb_late_init); static int rdb_mem_init(void) { @@ -35,6 +154,9 @@ static int rdb_postcore_init(void) defaultenv_append_directory(defaultenv_ls1046ardb); + ls1046a_bbu_mmc_register_handler("sd", "/dev/mmc0.barebox", + BBU_HANDLER_FLAG_DEFAULT); + return 0; } diff --git a/arch/arm/boards/nvidia-beaver/Makefile b/arch/arm/boards/nvidia-beaver/Makefile index 7ade54e854..f0eb7b2de0 100644 --- a/arch/arm/boards/nvidia-beaver/Makefile +++ b/arch/arm/boards/nvidia-beaver/Makefile @@ -1,6 +1,4 @@ -CFLAGS_pbl-entry.o := \ - -mcpu=arm7tdmi -march=armv4t \ - -fno-tree-switch-conversion -fno-jump-tables +CFLAGS_pbl-entry.o := -mcpu=arm7tdmi -march=armv4t soc := tegra30 lwl-y += entry.o obj-y += board.o diff --git a/arch/arm/boards/nvidia-jetson-tk1/Makefile b/arch/arm/boards/nvidia-jetson-tk1/Makefile index 16b203f9f3..5487f0289a 100644 --- a/arch/arm/boards/nvidia-jetson-tk1/Makefile +++ b/arch/arm/boards/nvidia-jetson-tk1/Makefile @@ -1,6 +1,4 @@ -CFLAGS_pbl-entry.o := \ - -mcpu=arm7tdmi -march=armv4t \ - -fno-tree-switch-conversion -fno-jump-tables +CFLAGS_pbl-entry.o := -mcpu=arm7tdmi -march=armv4t soc := tegra124 lwl-y += entry.o obj-y += board.o diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/init/bootsource b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/init/bootsource index 515613b041..fa5f7f26c5 100644 --- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/init/bootsource +++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6-phycore/init/bootsource @@ -12,7 +12,7 @@ if [ $bootsource = mmc ]; then fi elif [ $bootsource = nand ]; then global.boot.default="nand spi emmc mmc net" -elif [ $bootsource = spi ]; then +elif [ $bootsource = spi-nor ]; then global.boot.default="spi nand emmc mmc net" elif [ $bootsource = net ]; then global.boot.default="net nand spi emmc mmc" diff --git a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/bootsource b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/bootsource index 3f2ff4bcc8..9c9f0ec381 100644 --- a/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/bootsource +++ b/arch/arm/boards/phytec-som-imx6/defaultenv-physom-imx6/init/bootsource @@ -8,7 +8,7 @@ if [ $bootsource = mmc ]; then global.boot.default="mmc nand spi net" elif [ $bootsource = nand ]; then global.boot.default="nand spi mmc net" -elif [ $bootsource = spi ]; then +elif [ $bootsource = spi-nor ]; then global.boot.default="spi nand mmc net" elif [ $bootsource = net ]; then global.boot.default="net nand spi mmc" diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib-1bank.imxcfg index 62a24ed0df..bb4fbeb205 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib-1bank.imxcfg @@ -7,3 +7,4 @@ wm 32 0x021b0000 0x831a0000 #include "flash-header-phytec-pcaaxl3.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib.imxcfg index bab726d147..990c34b3af 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib.imxcfg @@ -7,3 +7,4 @@ wm 32 0x021b0000 0xc21a0000 #include "flash-header-phytec-pcaaxl3.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-2gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-2gib.imxcfg index 512f6cbd47..7c56c24ed7 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-2gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcaaxl3-2gib.imxcfg @@ -7,3 +7,4 @@ wm 32 0x021b0000 0xc31a0000 #include "flash-header-phytec-pcaaxl3.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-256mb.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-256mb.imxcfg index 4a827e4dfa..b93e81fb4e 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-256mb.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-256mb.imxcfg @@ -7,3 +7,4 @@ wm 32 0x021B0000 0x83180000 #include "flash-header-phytec-pcl063.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg index c4122d245d..26998c3fd8 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg @@ -7,3 +7,4 @@ wm 32 0x021B0000 0x84180000 #include "flash-header-phytec-pcl063.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg index 5df46b9ff4..0042909c95 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x831A0000 #include "flash-header-phytec-pcm058.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-2gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-2gib.imxcfg index 54c9e41d28..8a09036992 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-2gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058-2gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x841A0000 #include "flash-header-phytec-pcm058.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg index bf95d0f6ae..c949f98503 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x84190000 #include "flash-header-phytec-pcm058dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg index f047253084..3ac7e4e7ff 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x831A0000 #include "flash-header-phytec-pcm058dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-256mb.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-256mb.imxcfg index bf50190c78..bb8cdc9e4d 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-256mb.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058dl-256mb.imxcfg @@ -6,3 +6,5 @@ wm 32 0x021b0000 0x82190000 #include "flash-header-phytec-pcm058dl.h" +#include <mach/habv4-imx6-gencsf.h> + diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg index bf85f0a19c..3ed5b346ae 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x831A0000 #include "flash-header-phytec-pcm058qp.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank.imxcfg index 75dc982432..02f3fa7b33 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x831a0000 #include "flash-header-phytec-pfla02.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib.imxcfg index 1f1fbe542c..dd142a20a9 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-1gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0xc21a0000 #include "flash-header-phytec-pfla02.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-2gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-2gib.imxcfg index aa01c056be..3f9d11dc49 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-2gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-2gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0xC31A0000 #include "flash-header-phytec-pfla02.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-4gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-4gib.imxcfg index c8d33cfacc..fdb1d15538 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-4gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-4gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0xC41A0000 #include "flash-header-phytec-pfla02.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-512mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-512mb-1bank.imxcfg index d6bbe1f1c3..f4f150ee68 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-512mb-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02-512mb-1bank.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x821a0000 #include "flash-header-phytec-pfla02.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg index 7b64e5d2fd..b2a0521bbc 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x831a0000 #include "flash-header-phytec-pfla02dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg index 04c489d7e8..e03e25eae2 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0xc21a0000 #include "flash-header-phytec-pfla02dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg index ebe5a968b1..58c1576219 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x82180000 #include "flash-header-phytec-pfla02dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg index 5f1585a40b..9975e2197b 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x82190000 #include "flash-header-phytec-pfla02dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg index 5ff3ec69d7..edc396bc5d 100644 --- a/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg +++ b/arch/arm/boards/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg @@ -6,3 +6,4 @@ wm 32 0x021b0000 0x83190000 #include "flash-header-phytec-pfla02dl.h" +#include <mach/habv4-imx6-gencsf.h> diff --git a/arch/arm/boards/stm32mp157c-dk2/board.c b/arch/arm/boards/stm32mp157c-dk2/board.c index f15ae0b4af..9cd5b4ee1f 100644 --- a/arch/arm/boards/stm32mp157c-dk2/board.c +++ b/arch/arm/boards/stm32mp157c-dk2/board.c @@ -6,17 +6,6 @@ #include <mach/stm32.h> #include <mach/bbu.h> -static int dk2_mem_init(void) -{ - if (!of_machine_is_compatible("st,stm32mp157c-dk2")) - return 0; - - arm_add_mem_device("ram0", STM32_DDR_BASE, SZ_512M); - - return 0; -} -mem_initcall(dk2_mem_init); - static int dk2_postcore_init(void) { if (!of_machine_is_compatible("st,stm32mp157c-dk2")) diff --git a/arch/arm/boards/stm32mp157c-dk2/lowlevel.c b/arch/arm/boards/stm32mp157c-dk2/lowlevel.c index 566ace79c9..7261d7a8bc 100644 --- a/arch/arm/boards/stm32mp157c-dk2/lowlevel.c +++ b/arch/arm/boards/stm32mp157c-dk2/lowlevel.c @@ -1,19 +1,26 @@ // SPDX-License-Identifier: GPL-2.0+ #include <common.h> -#include <asm/barebox-arm-head.h> -#include <asm/barebox-arm.h> -#include <mach/stm32.h> +#include <mach/entry.h> #include <debug_ll.h> extern char __dtb_z_stm32mp157c_dk2_start[]; +static void setup_uart(void) +{ + /* first stage has set up the UART, so nothing to do here */ + putc_ll('>'); +} + ENTRY_FUNCTION(start_stm32mp157c_dk2, r0, r1, r2) { void *fdt; - arm_cpu_lowlevel_init(); + stm32mp_cpu_lowlevel_init(); + + if (IS_ENABLED(CONFIG_DEBUG_LL)) + setup_uart(); fdt = __dtb_z_stm32mp157c_dk2_start + get_runtime_offset(); - barebox_arm_entry(STM32_DDR_BASE, SZ_512M, fdt); + stm32mp1_barebox_entry(fdt); } diff --git a/arch/arm/boards/toradex-colibri-t20/Makefile b/arch/arm/boards/toradex-colibri-t20/Makefile index d0347f2382..644a8e5269 100644 --- a/arch/arm/boards/toradex-colibri-t20/Makefile +++ b/arch/arm/boards/toradex-colibri-t20/Makefile @@ -1,9 +1,7 @@ -CFLAGS_pbl-entry.o := \ - -mcpu=arm7tdmi -march=armv4t \ - -fno-tree-switch-conversion -fno-jump-tables +CFLAGS_pbl-entry.o := -mcpu=arm7tdmi -march=armv4t soc := tegra20 lwl-y += entry.o obj-y += board.o extra-y += colibri-t20_256_hsmmc.bct colibri-t20_256_v11_nand.bct \ colibri-t20_256_v12_nand.bct colibri-t20_512_hsmmc.bct \ - colibri-t20_512_v11_nand.bct colibri-t20_512_v12_nand.bct
\ No newline at end of file + colibri-t20_512_v11_nand.bct colibri-t20_512_v12_nand.bct diff --git a/arch/arm/boards/toshiba-ac100/Makefile b/arch/arm/boards/toshiba-ac100/Makefile index 2b6c09e279..4ef18c0ce9 100644 --- a/arch/arm/boards/toshiba-ac100/Makefile +++ b/arch/arm/boards/toshiba-ac100/Makefile @@ -1,5 +1,3 @@ -CFLAGS_pbl-entry.o := \ - -mcpu=arm7tdmi -march=armv4t \ - -fno-tree-switch-conversion -fno-jump-tables +CFLAGS_pbl-entry.o := -mcpu=arm7tdmi -march=armv4t lwl-y += entry.o obj-y += board.o diff --git a/arch/arm/boards/wago-pfc-am35xx/board-mlo.c b/arch/arm/boards/wago-pfc-am35xx/board-mlo.c index 7925c71a4b..c940565b4a 100644 --- a/arch/arm/boards/wago-pfc-am35xx/board-mlo.c +++ b/arch/arm/boards/wago-pfc-am35xx/board-mlo.c @@ -48,7 +48,7 @@ static int pfc200_mem_init(void) } mem_initcall(pfc200_mem_init); -static struct gpmc_nand_platform_data nand_plat = { +__maybe_unused static struct gpmc_nand_platform_data nand_plat = { .cs = 0, .device_width = 8, .ecc_mode = OMAP_ECC_BCH8_CODE_HW_ROMCODE, @@ -62,8 +62,8 @@ static int pfc200_init_devices(void) * WP is made high and WAIT1 active Low */ gpmc_generic_init(0x10); -#endif omap_add_gpmc_nand_device(&nand_plat); +#endif omap_set_barebox_part(&pfc200_mlo_part); omap3_add_mmc1(NULL); diff --git a/arch/arm/boards/zii-imx51-rdu1/Makefile b/arch/arm/boards/zii-imx51-rdu1/Makefile index 604b3621be..01c7a259e9 100644 --- a/arch/arm/boards/zii-imx51-rdu1/Makefile +++ b/arch/arm/boards/zii-imx51-rdu1/Makefile @@ -1,3 +1,2 @@ obj-y += board.o -CFLAGS_pbl-lowlevel.o := -fno-tree-switch-conversion -fno-jump-tables lwl-y += lowlevel.o diff --git a/arch/arm/boards/zii-imx7d-dev/Makefile b/arch/arm/boards/zii-imx7d-dev/Makefile index e1baed17ba..01c7a259e9 100644 --- a/arch/arm/boards/zii-imx7d-dev/Makefile +++ b/arch/arm/boards/zii-imx7d-dev/Makefile @@ -1,3 +1,2 @@ -CFLAGS_pbl-lowlevel.o := -fno-tree-switch-conversion -fno-jump-tables obj-y += board.o lwl-y += lowlevel.o diff --git a/arch/arm/boards/zii-vf610-dev/Makefile b/arch/arm/boards/zii-vf610-dev/Makefile index 3c3a3f2387..1297d815e3 100644 --- a/arch/arm/boards/zii-vf610-dev/Makefile +++ b/arch/arm/boards/zii-vf610-dev/Makefile @@ -1,4 +1,3 @@ obj-y += board.o -CFLAGS_pbl-lowlevel.o := -fno-tree-switch-conversion -fno-jump-tables lwl-y += lowlevel.o bbenv-y += defaultenv-zii-vf610-dev diff --git a/arch/arm/cpu/Makefile b/arch/arm/cpu/Makefile index 09b3bc2eea..63cf35c299 100644 --- a/arch/arm/cpu/Makefile +++ b/arch/arm/cpu/Makefile @@ -2,7 +2,7 @@ obj-y += cpu.o obj-$(CONFIG_ARM_EXCEPTIONS) += exceptions$(S64).o interrupts$(S64).o obj-$(CONFIG_MMU) += mmu$(S64).o mmu-common.o -lwl-y += lowlevel$(S64).o +obj-pbl-y += lowlevel$(S64).o obj-pbl-$(CONFIG_MMU) += mmu-early$(S64).o obj-pbl-$(CONFIG_CPU_32v7) += hyp.o AFLAGS_hyp.o :=-Wa,-march=armv7-a -Wa,-mcpu=all @@ -15,7 +15,6 @@ pbl-$(CONFIG_BOARD_ARM_GENERIC_DT_AARCH64) += board-dt-2nd-aarch64.o obj-pbl-y += setupc$(S64).o cache$(S64).o -obj-$(CONFIG_BOOTM_OPTEE) += start-kernel-optee.o obj-$(CONFIG_ARM_PSCI_CLIENT) += psci-client.o # diff --git a/arch/arm/cpu/common.c b/arch/arm/cpu/common.c index c81b2b3791..c7d1709b8b 100644 --- a/arch/arm/cpu/common.c +++ b/arch/arm/cpu/common.c @@ -51,7 +51,11 @@ void pbl_barebox_break(void) { __asm__ __volatile__ ( #ifdef CONFIG_PBL_BREAK +#ifdef CONFIG_CPU_V8 + "brk #17\n" +#else "bkpt #17\n" +#endif "nop\n" #else "nop\n" diff --git a/arch/arm/cpu/dtb.c b/arch/arm/cpu/dtb.c index 1ba5aa415e..c43474e63b 100644 --- a/arch/arm/cpu/dtb.c +++ b/arch/arm/cpu/dtb.c @@ -19,8 +19,6 @@ #include <of.h> #include <asm/barebox-arm.h> -extern char __dtb_start[]; - static int of_arm_init(void) { struct device_node *root; diff --git a/arch/arm/cpu/mmu-early_64.c b/arch/arm/cpu/mmu-early_64.c index f07d107e0d..94e372637a 100644 --- a/arch/arm/cpu/mmu-early_64.c +++ b/arch/arm/cpu/mmu-early_64.c @@ -48,6 +48,8 @@ static void create_sections(void *ttb, uint64_t virt, uint64_t phys, } } +#define EARLY_BITS_PER_VA 39 + void mmu_early_enable(unsigned long membase, unsigned long memsize, unsigned long ttb) { @@ -64,8 +66,8 @@ void mmu_early_enable(unsigned long membase, unsigned long memsize, memset((void *)ttb, 0, GRANULE_SIZE); el = current_el(); - set_ttbr_tcr_mair(el, ttb, calc_tcr(el), MEMORY_ATTRIBUTES); - create_sections((void *)ttb, 0, 0, 1UL << (BITS_PER_VA - 1), UNCACHED_MEM); + set_ttbr_tcr_mair(el, ttb, calc_tcr(el, EARLY_BITS_PER_VA), MEMORY_ATTRIBUTES); + create_sections((void *)ttb, 0, 0, 1UL << (EARLY_BITS_PER_VA - 1), UNCACHED_MEM); create_sections((void *)ttb, membase, membase, memsize, CACHED_MEM); tlb_invalidate(); isb(); diff --git a/arch/arm/cpu/mmu_64.c b/arch/arm/cpu/mmu_64.c index b45a69661e..f7a13014af 100644 --- a/arch/arm/cpu/mmu_64.c +++ b/arch/arm/cpu/mmu_64.c @@ -64,7 +64,7 @@ static __maybe_unused uint64_t *find_pte(uint64_t addr) pte = ttb; - for (i = 1; i < 4; i++) { + for (i = 0; i < 4; i++) { block_shift = level2shift(i); idx = (addr & level2mask(i)) >> block_shift; pte += idx; @@ -129,7 +129,7 @@ static void create_sections(uint64_t virt, uint64_t phys, uint64_t size, while (size) { table = ttb; - for (level = 1; level < 4; level++) { + for (level = 0; level < 4; level++) { block_shift = level2shift(level); idx = (addr & level2mask(level)) >> block_shift; block_size = (1ULL << block_shift); @@ -193,7 +193,8 @@ void __mmu_init(bool mmu_on) ttb = create_table(); el = current_el(); - set_ttbr_tcr_mair(el, (uint64_t)ttb, calc_tcr(el), MEMORY_ATTRIBUTES); + set_ttbr_tcr_mair(el, (uint64_t)ttb, calc_tcr(el, BITS_PER_VA), + MEMORY_ATTRIBUTES); pr_debug("ttb: 0x%p\n", ttb); diff --git a/arch/arm/cpu/mmu_64.h b/arch/arm/cpu/mmu_64.h index e2e125686d..a2a5477569 100644 --- a/arch/arm/cpu/mmu_64.h +++ b/arch/arm/cpu/mmu_64.h @@ -75,7 +75,9 @@ static inline uint64_t level2mask(int level) { uint64_t mask = -EINVAL; - if (level == 1) + if (level == 0) + mask = L0_ADDR_MASK; + else if (level == 1) mask = L1_ADDR_MASK; else if (level == 2) mask = L2_ADDR_MASK; @@ -85,13 +87,12 @@ static inline uint64_t level2mask(int level) return mask; } -static inline uint64_t calc_tcr(int el) +static inline uint64_t calc_tcr(int el, int va_bits) { - u64 ips, va_bits; + u64 ips; u64 tcr; ips = 2; - va_bits = BITS_PER_VA; if (el == 1) tcr = (ips << 32) | TCR_EPD1_DISABLE; diff --git a/arch/arm/cpu/psci.c b/arch/arm/cpu/psci.c index 22ce1dfd0e..5a69aaa810 100644 --- a/arch/arm/cpu/psci.c +++ b/arch/arm/cpu/psci.c @@ -228,107 +228,3 @@ static int armv7_psci_init(void) } device_initcall(armv7_psci_init); -#ifdef CONFIG_ARM_PSCI_DEBUG - -#include <command.h> -#include <getopt.h> -#include "mmu.h" - -void second_entry(void) -{ - struct arm_smccc_res res; - - psci_printf("2nd CPU online, now turn off again\n"); - - arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_OFF, - 0, 0, 0, 0, 0, 0, 0, &res); - - psci_printf("2nd CPU still alive?\n"); - - while (1); -} - -static const char *psci_xlate_str(long err) -{ - static char errno_string[sizeof "error 0x123456789ABCDEF0"]; - - switch(err) - { - case ARM_PSCI_RET_SUCCESS: - return "Success"; - case ARM_PSCI_RET_NOT_SUPPORTED: - return "Operation not supported"; - case ARM_PSCI_RET_INVAL: - return "Invalid argument"; - case ARM_PSCI_RET_DENIED: - return "Operation not permitted"; - case ARM_PSCI_RET_ALREADY_ON: - return "CPU already on"; - case ARM_PSCI_RET_ON_PENDING: - return "CPU_ON in progress"; - case ARM_PSCI_RET_INTERNAL_FAILURE: - return "Internal failure"; - case ARM_PSCI_RET_NOT_PRESENT: - return "Trusted OS not present on core"; - case ARM_PSCI_RET_DISABLED: - return "CPU is disabled"; - case ARM_PSCI_RET_INVALID_ADDRESS: - return "Bad address"; - } - - sprintf(errno_string, "error 0x%lx", err); - return errno_string; -} - -static int do_smc(int argc, char *argv[]) -{ - long ret; - int opt; - struct arm_smccc_res res = { - .a0 = 0xdeadbee0, - .a1 = 0xdeadbee1, - .a2 = 0xdeadbee2, - .a3 = 0xdeadbee3, - }; - - if (argc < 2) - return COMMAND_ERROR_USAGE; - - while ((opt = getopt(argc, argv, "nic")) > 0) { - switch (opt) { - case 'n': - armv7_secure_monitor_install(); - break; - case 'i': - arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, - 0, 0, 0, 0, 0, 0, 0, &res); - printf("found psci version %ld.%ld\n", res.a0 >> 16, res.a0 & 0xffff); - break; - case 'c': - arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_ON, - 1, (unsigned long)second_entry, 0, 0, 0, 0, 0, &res); - ret = (long)res.a0; - printf("CPU_ON returns with: %s\n", psci_xlate_str(ret)); - if (ret) - return COMMAND_ERROR; - } - } - - - return 0; -} -BAREBOX_CMD_HELP_START(smc) -BAREBOX_CMD_HELP_TEXT("Secure monitor code test command") -BAREBOX_CMD_HELP_TEXT("") -BAREBOX_CMD_HELP_TEXT("Options:") -BAREBOX_CMD_HELP_OPT ("-n", "Install secure monitor and switch to nonsecure mode") -BAREBOX_CMD_HELP_OPT ("-i", "Show information about installed PSCI version") -BAREBOX_CMD_HELP_OPT ("-c", "Start secondary CPU core") -BAREBOX_CMD_HELP_END - -BAREBOX_CMD_START(smc) - .cmd = do_smc, - BAREBOX_CMD_DESC("secure monitor test command") - BAREBOX_CMD_GROUP(CMD_GRP_MISC) -BAREBOX_CMD_END -#endif diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index 44d974e40e..d99dd147b0 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -193,7 +193,17 @@ __noreturn void barebox_non_pbl_start(unsigned long membase, uint32_t totalsize = 0; const char *name; - if ((unsigned long)boarddata < 8192) { + if (blob_is_fdt(boarddata)) { + totalsize = get_unaligned_be32(boarddata + 4); + name = "DTB"; + } else if (blob_is_compressed_fdt(boarddata)) { + struct barebox_arm_boarddata_compressed_dtb *bd = boarddata; + totalsize = bd->datalen + sizeof(*bd); + name = "Compressed DTB"; + } else if (blob_is_arm_boarddata(boarddata)) { + totalsize = sizeof(struct barebox_arm_boarddata); + name = "machine type"; + } else if ((unsigned long)boarddata < 8192) { struct barebox_arm_boarddata *bd; uint32_t machine_type = (unsigned long)boarddata; unsigned long mem = arm_mem_boarddata(membase, endmem, @@ -205,16 +215,6 @@ __noreturn void barebox_non_pbl_start(unsigned long membase, bd->magic = BAREBOX_ARM_BOARDDATA_MAGIC; bd->machine = machine_type; malloc_end = mem; - } else if (blob_is_fdt(boarddata)) { - totalsize = get_unaligned_be32(boarddata + 4); - name = "DTB"; - } else if (blob_is_compressed_fdt(boarddata)) { - struct barebox_arm_boarddata_compressed_dtb *bd = boarddata; - totalsize = bd->datalen + sizeof(*bd); - name = "Compressed DTB"; - } else if (blob_is_arm_boarddata(boarddata)) { - totalsize = sizeof(struct barebox_arm_boarddata); - name = "machine type"; } if (totalsize) { diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index c097c10186..5c9a311c5f 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -33,7 +33,8 @@ lwl-dtb-$(CONFIG_MACH_GW_VENTANA) += imx6q-gw54xx.dtb.o lwl-dtb-$(CONFIG_MACH_KONTRON_SAMX6I) += imx6q-samx6i.dtb.o \ imx6dl-samx6i.dtb.o lwl-dtb-$(CONFIG_MACH_LENOVO_IX4_300D) += armada-xp-lenovo-ix4-300d-bb.dtb.o -lwl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o armada-xp-db-bb.dtb.o +lwl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o +lwl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_DB) += armada-xp-db-bb.dtb.o lwl-dtb-$(CONFIG_MACH_MB7707) += module-mb7707.dtb.o lwl-dtb-$(CONFIG_MACH_MX28EVK) += imx28-evk.dtb.o lwl-dtb-$(CONFIG_MACH_NETGEAR_RN104) += armada-370-rn104-bb.dtb.o diff --git a/arch/arm/dts/fsl-ls1046a-rdb.dts b/arch/arm/dts/fsl-ls1046a-rdb.dts index 842d684588..32b3f40769 100644 --- a/arch/arm/dts/fsl-ls1046a-rdb.dts +++ b/arch/arm/dts/fsl-ls1046a-rdb.dts @@ -5,6 +5,10 @@ #include <arm64/freescale/fsl-ls1046a-rdb.dts> / { + aliases { + eeprom = &eeprom; + }; + chosen { stdout-path = &duart0; @@ -23,9 +27,14 @@ #address-cells = <1>; #size-cells = <1>; - environment_sd: partition@200000 { + partition@1000 { + label = "barebox"; + reg = <0x1000 0xdf000>; + }; + + environment_sd: partition@e0000 { label = "barebox-environment"; - reg = <0x200000 0x20000>; + reg = <0xe0000 0x20000>; }; }; @@ -41,6 +50,17 @@ status = "okay"; }; +&i2c0 { + eeprom: eeprom@52 { + compatible = "atmel,24c04"; + }; + + non_existent_eeprom: eeprom@53 { + }; +}; + +/delete-node/ &non_existent_eeprom; + &fman0 { ethernet@e0000 { status = "disabled"; @@ -109,6 +129,14 @@ }; }; +&qflash0 { + compatible = "jedec,spi-nor"; +}; + +&qflash1 { + compatible = "jedec,spi-nor"; +}; + &usb0 { dr_mode = "host"; }; @@ -122,3 +150,17 @@ &usb2 { dr_mode = "host"; }; + +&soc { + pcie1: pcie@3400000 { + status = "okay"; + }; + + pcie2: pcie@3500000 { + status = "okay"; + }; + + pcie3: pcie@3600000 { + status = "okay"; + }; +}; diff --git a/arch/arm/dts/fsl-tqmls1046a-mbls10xxa.dts b/arch/arm/dts/fsl-tqmls1046a-mbls10xxa.dts index f0332e3999..7b17fe2210 100644 --- a/arch/arm/dts/fsl-tqmls1046a-mbls10xxa.dts +++ b/arch/arm/dts/fsl-tqmls1046a-mbls10xxa.dts @@ -84,7 +84,7 @@ compatible = "fixed-partitions"; - partition@0 { + partition@1000 { label = "barebox"; reg = <0x1000 0xdf000>; }; @@ -131,6 +131,22 @@ reg = <0x20>; gpio-controller; #gpio-cells = <2>; + gpio-line-names = "sd1_3_lane_a_mux", + "sd1_2_lane_b_mux", + "sd1_0_lane_d_mux", + "sd2_1_lane_b_mux", + "sd2_3_lane_d_mux1", + "sd2_3_lane_d_mux2", + "sd_mux_shdn", + "sd1_ref_clk2_sel", + "mpcie1_disable_n", + "mpcie1_wake_n", + "mpcie2_disable_n", + "mpcie2_wake_n", + "prsnt_n", + "pcie_pwr_en", + "dcdc_pwr_en", + "dcdc_pgood_1v8"; }; gpioexp2: pca9555@21 { @@ -138,6 +154,22 @@ reg = <0x21>; gpio-controller; #gpio-cells = <2>; + gpio-line-names = "xfi1_tx_dis", + "xfi1_tx_fault", + "xfi1_moddef_det", + "xfi1_rx_loss", + "retimer1_loss", + "xfi1_ensmb", + "qsgmii1_clk_sel0", + "qsgmii_phy1_config3", + "xfi2_tx_fault", + "xfi2_tx_dis", + "xfi2_moddef_det", + "xfi2_rx_loss", + "retimer2_loss", + "xfi2_ensmb", + "qsgmii2_clk_sel0", + "qsgmii_phy2_config3"; }; gpioexp3: pca9555@22 { @@ -145,6 +177,22 @@ reg = <0x22>; gpio-controller; #gpio-cells = <2>; + gpio-line-names = "ec1_phy_pwdn", + "ec2_phy_pwdn", + "usb_c_pwron", + "usb_en_oc_3v3_n", + "usb_h_grst_n", + "gpio_button0", + "gpio_button1", + "sda_pwr_en", + "qsgmii_phy1_int_n", + "qsgmii_phy2_int_n", + "spi_clko_sof", + "spi_int", + "can_sel", + "led_n", + "pcie_rst_3v3_n", + "pcie_wake_3v3_n"; }; }; diff --git a/arch/arm/dts/imx6dl-phytec-pbab01.dts b/arch/arm/dts/imx6dl-phytec-pbab01.dts index d10fbf668f..4fe3c308e7 100644 --- a/arch/arm/dts/imx6dl-phytec-pbab01.dts +++ b/arch/arm/dts/imx6dl-phytec-pbab01.dts @@ -10,7 +10,9 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6dl-phytec-pfla02.dtsi" #include "imx6qdl-phytec-pbab01.dtsi" diff --git a/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts b/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts index 3d1069a965..430745f100 100644 --- a/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts +++ b/arch/arm/dts/imx6dl-phytec-phyboard-subra.dts @@ -10,6 +10,9 @@ */ /dts-v1/; +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6s-phytec-pfla02.dtsi" #include "imx6qdl-phytec-phyboard-subra.dtsi" diff --git a/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts b/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts index 21cbb5f944..03df77f41d 100644 --- a/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts +++ b/arch/arm/dts/imx6dl-phytec-phycore-som-emmc.dts @@ -1,31 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later) /* * Copyright (C) 2015 PHYTEC Messtechnik GmbH, * Author: Stefan Christ <s.christ@phytec.de> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6dl.dtsi> #include "imx6dl.dtsi" #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" #include "imx6qdl-phytec-state.dtsi" / { - model = "Phytec phyCORE-i.MX6 DualLite/SOLO with eMMC"; + model = "PHYTEC phyCORE-i.MX6 DualLite/SOLO with eMMC"; compatible = "phytec,imx6dl-pcm058-emmc", "fsl,imx6dl"; }; -&ecspi1 { - status = "okay"; -}; - &eeprom { status = "okay"; }; @@ -38,7 +31,7 @@ status = "okay"; }; -&flash { +&m25p80 { status = "okay"; }; @@ -52,22 +45,6 @@ &usdhc1 { status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; - }; }; &usdhc4 { diff --git a/arch/arm/dts/imx6dl-phytec-phycore-som-lc-emmc.dts b/arch/arm/dts/imx6dl-phytec-phycore-som-lc-emmc.dts index b8efb95ee0..0ef6f96bbe 100644 --- a/arch/arm/dts/imx6dl-phytec-phycore-som-lc-emmc.dts +++ b/arch/arm/dts/imx6dl-phytec-phycore-som-lc-emmc.dts @@ -5,10 +5,13 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6dl.dtsi> #include "imx6dl.dtsi" #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" #include "imx6qdl-phytec-state.dtsi" / { @@ -16,10 +19,6 @@ compatible = "phytec,imx6dl-pcm058-emmc", "fsl,imx6dl"; }; -&ecspi1 { - status = "okay"; -}; - &eeprom { status = "okay"; }; @@ -32,7 +31,7 @@ status = "okay"; }; -&flash { +&m25p80 { status = "okay"; }; @@ -46,19 +45,6 @@ &usdhc1 { status = "okay"; - - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; }; &usdhc4 { diff --git a/arch/arm/dts/imx6dl-phytec-phycore-som-lc-nand.dts b/arch/arm/dts/imx6dl-phytec-phycore-som-lc-nand.dts index 4d38d1698a..0a4c2e6fb6 100644 --- a/arch/arm/dts/imx6dl-phytec-phycore-som-lc-nand.dts +++ b/arch/arm/dts/imx6dl-phytec-phycore-som-lc-nand.dts @@ -5,10 +5,13 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6dl.dtsi> #include "imx6dl.dtsi" #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" #include "imx6qdl-phytec-state.dtsi" / { @@ -42,17 +45,4 @@ &usdhc1 { status = "okay"; - - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; }; diff --git a/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts index 3ad3723d28..fa518286c3 100644 --- a/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts +++ b/arch/arm/dts/imx6dl-phytec-phycore-som-nand.dts @@ -1,23 +1,21 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later) /* - * Copyright 2015 Christian Hemp, Phytec Messtechnik GmbH - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Author: Christian Hemp <c.hemp@phytec.de> */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6dl.dtsi> #include "imx6dl.dtsi" #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" #include "imx6qdl-phytec-state.dtsi" / { - model = "Phytec phyCORE-i.MX6 Duallite/SOLO with NAND"; + model = "PHYTEC phyCORE-i.MX6 Duallite/SOLO with NAND"; compatible = "phytec,imx6dl-pcm058-nand", "fsl,imx6dl"; }; @@ -47,20 +45,4 @@ &usdhc1 { status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; - }; }; diff --git a/arch/arm/dts/imx6q-phytec-pbaa03.dts b/arch/arm/dts/imx6q-phytec-pbaa03.dts index 4724a02ad7..5216a2dfe3 100644 --- a/arch/arm/dts/imx6q-phytec-pbaa03.dts +++ b/arch/arm/dts/imx6q-phytec-pbaa03.dts @@ -10,6 +10,9 @@ */ /dts-v1/; +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6q-phytec-pcaaxl3.dtsi" / { diff --git a/arch/arm/dts/imx6q-phytec-pbab01.dts b/arch/arm/dts/imx6q-phytec-pbab01.dts index 2f816dd1ac..91562a2ffe 100644 --- a/arch/arm/dts/imx6q-phytec-pbab01.dts +++ b/arch/arm/dts/imx6q-phytec-pbab01.dts @@ -10,6 +10,9 @@ */ /dts-v1/; +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6q-phytec-pfla02.dtsi" #include "imx6qdl-phytec-pbab01.dtsi" diff --git a/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts b/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts index 1c4a78552d..d97c7f15c9 100644 --- a/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts +++ b/arch/arm/dts/imx6q-phytec-phyboard-alcor.dts @@ -10,6 +10,9 @@ */ /dts-v1/; +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6q-phytec-pfla02.dtsi" / { diff --git a/arch/arm/dts/imx6q-phytec-phyboard-subra.dts b/arch/arm/dts/imx6q-phytec-phyboard-subra.dts index 561e985604..4986111036 100644 --- a/arch/arm/dts/imx6q-phytec-phyboard-subra.dts +++ b/arch/arm/dts/imx6q-phytec-phyboard-subra.dts @@ -11,6 +11,9 @@ */ /dts-v1/; +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6q-phytec-pfla02.dtsi" #include "imx6qdl-phytec-phyboard-subra.dtsi" diff --git a/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts b/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts index 7a86d5b94d..2414befd35 100644 --- a/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts +++ b/arch/arm/dts/imx6q-phytec-phycore-som-emmc.dts @@ -1,30 +1,24 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later) /* - * Copyright 2015 Christian Hemp, Phytec Messtechnik GmbH - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Author: Christian Hemp <c.hemp@phytec.de> */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6q.dtsi> #include "imx6q.dtsi" #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" #include "imx6qdl-phytec-state.dtsi" / { - model = "Phytec phyCORE-i.MX6 Quad with eMMC"; + model = "PHYTEC phyCORE-i.MX6 Quad with eMMC"; compatible = "phytec,imx6q-pcm058-emmc", "fsl,imx6q"; }; -&ecspi1 { - status = "okay"; -}; - &eeprom { status = "okay"; }; @@ -37,7 +31,7 @@ status = "okay"; }; -&flash { +&m25p80 { status = "okay"; }; @@ -51,22 +45,6 @@ &usdhc1 { status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; - }; }; &usdhc4 { diff --git a/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts index 96d1de224c..864dc190bc 100644 --- a/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts +++ b/arch/arm/dts/imx6q-phytec-phycore-som-nand.dts @@ -1,31 +1,25 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later) /* - * Copyright 2015 Christian Hemp, Phytec Messtechnik GmbH - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Author: Christian Hemp <c.hemp@phytec.de> */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6q.dtsi> #include "imx6q.dtsi" #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" #include "imx6qdl-phytec-state.dtsi" / { - model = "Phytec phyCORE-i.MX6 Quad with NAND"; + model = "PHYTEC phyCORE-i.MX6 Quad with NAND"; compatible = "phytec,imx6q-pcm058-nand", "fsl,imx6q"; }; -&ecspi1 { - status = "okay"; -}; - &eeprom { status = "okay"; }; @@ -38,7 +32,7 @@ status = "okay"; }; -&flash { +&m25p80 { status = "okay"; }; @@ -56,20 +50,4 @@ &usdhc1 { status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; - }; }; diff --git a/arch/arm/dts/imx6qdl-phytec-mira.dtsi b/arch/arm/dts/imx6qdl-phytec-mira.dtsi new file mode 100644 index 0000000000..49cbd25fc3 --- /dev/null +++ b/arch/arm/dts/imx6qdl-phytec-mira.dtsi @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR MIT) +/* + * Copyright (C) 2019 PHYTEC Messtechnik GmbH + * Author: Stefan Riedmueller <s.riedmueller@phytec.de> + */ + +#include <arm/imx6qdl-phytec-mira.dtsi> +#include <dt-bindings/gpio/gpio.h> + +/ { + chosen { + stdout-path = &uart2; + }; +}; + +&backlight { + status = "disabled"; +}; + +&ldb { + status = "disabled"; +}; + +&pwm1 { + status = "disabled"; +}; + +&usdhc1 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; + + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; + }; +}; diff --git a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi index 1d39368165..69f252b423 100644 --- a/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi +++ b/arch/arm/dts/imx6qdl-phytec-phycore-som.dtsi @@ -1,20 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later) /* - * Copyright 2015 Christian Hemp, Phytec Messtechnik GmbH - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html + * Copyright (C) 2015 PHYTEC Messtechnik GmbH + * Author: Christian Hemp <c.hemp@phytec.de> */ +#include <arm/imx6qdl-phytec-phycore-som.dtsi> #include <dt-bindings/gpio/gpio.h> / { chosen { - stdout-path = &uart2; - environment-sd1 { compatible = "barebox,environment"; device-path = &usdhc1, "partname:barebox-environment"; @@ -35,102 +29,20 @@ environment-spinor { compatible = "barebox,environment"; - device-path = &flash, "partname:barebox-environment"; + device-path = &m25p80, "partname:barebox-environment"; status = "disabled"; }; }; - reg_usbh1_vbus: regulator-usbh1 { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbh1_vbus>; - regulator-name = "usbh1_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio2 18 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; - - reg_usbotg_vbus: regulator-usbotg { - compatible = "regulator-fixed"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbotg_vbus>; - regulator-name = "usbotg_vbus"; - regulator-min-microvolt = <5000000>; - regulator-max-microvolt = <5000000>; - gpio = <&gpio2 19 GPIO_ACTIVE_HIGH>; - enable-active-high; - }; -}; - -&ecspi1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ecspi1>; - fsl,spi-num-chipselects = <1>; - cs-gpios = <&gpio3 19 0>; - status = "disabled"; - - flash: flash@0 { - compatible = "jedec,spi-nor"; - spi-max-frequency = <20000000>; - reg = <0>; - status = "disabled"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0x100000>; - }; - - partition@100000 { - label = "barebox-environment"; - reg = <0x100000 0x20000>; - }; - - partition@120000 { - label = "oftree"; - reg = <0x120000 0x20000>; - }; - - partition@140000 { - label = "kernel"; - reg = <0x140000 0x0>; - }; - }; - }; + /delete-node/ memory@10000000; }; &fec { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_enet>; - phy-handle = <ðphy>; - phy-mode = "rgmii"; - phy-reset-gpios = <&gpio1 14 GPIO_ACTIVE_LOW>; + /delete-property/ phy-supply; phy-reset-duration = <10>; /* in msecs */ - status = "disabled"; - - mdio { - #address-cells = <1>; - #size-cells = <0>; - - ethphy: ethernet-phy@3 { - reg = <3>; - txc-skew-ps = <1680>; - rxc-skew-ps = <1860>; - }; - }; }; &gpmi { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_gpmi_nand>; - nand-on-flash-bbt; - status = "disabled"; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -154,141 +66,44 @@ }; &i2c3 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2c3>; - clock-frequency = <400000>; - status = "okay"; - eeprom: eeprom@50 { status = "disabled"; - compatible = "24c32"; - reg = <0x50>; }; pmic@58 { - compatible = "dlg,da9062"; - reg = <0x58>; - status = "okay"; - watchdog-priority = <500>; restart-priority = <500>; reset-source-priority = <500>; }; }; -&iomuxc { - pinctrl_ecspi1: ecspi1grp { - fsl,pins = < - MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1 - MX6QDL_PAD_EIM_D17__ECSPI1_MISO 0x100b1 - MX6QDL_PAD_EIM_D18__ECSPI1_MOSI 0x100b1 - MX6QDL_PAD_EIM_D19__GPIO3_IO19 0x80000000 - >; - }; - - pinctrl_enet: enetgrp { - fsl,pins = < - MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 - MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 - MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 - MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 - MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 - MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 - MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 - MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 - MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 - MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 - MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 - MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 - MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 - MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 - MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 - MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN 0x1b0b0 - MX6QDL_PAD_SD2_DAT1__GPIO1_IO14 0x80000000 - >; - }; - - pinctrl_gpmi_nand: gpmigrp { - fsl,pins = < - MX6QDL_PAD_NANDF_CLE__NAND_CLE 0xb0b1 - MX6QDL_PAD_NANDF_ALE__NAND_ALE 0xb0b1 - MX6QDL_PAD_NANDF_WP_B__NAND_WP_B 0xb0b1 - MX6QDL_PAD_NANDF_RB0__NAND_READY_B 0xb000 - MX6QDL_PAD_NANDF_CS0__NAND_CE0_B 0xb0b1 - MX6QDL_PAD_NANDF_CS1__NAND_CE1_B 0xb0b1 - MX6QDL_PAD_NANDF_CS2__NAND_CE2_B 0xb0b1 - MX6QDL_PAD_NANDF_CS3__NAND_CE3_B 0xb0b1 - MX6QDL_PAD_SD4_CMD__NAND_RE_B 0xb0b1 - MX6QDL_PAD_SD4_CLK__NAND_WE_B 0xb0b1 - MX6QDL_PAD_NANDF_D0__NAND_DATA00 0xb0b1 - MX6QDL_PAD_NANDF_D1__NAND_DATA01 0xb0b1 - MX6QDL_PAD_NANDF_D2__NAND_DATA02 0xb0b1 - MX6QDL_PAD_NANDF_D3__NAND_DATA03 0xb0b1 - MX6QDL_PAD_NANDF_D4__NAND_DATA04 0xb0b1 - MX6QDL_PAD_NANDF_D5__NAND_DATA05 0xb0b1 - MX6QDL_PAD_NANDF_D6__NAND_DATA06 0xb0b1 - MX6QDL_PAD_NANDF_D7__NAND_DATA07 0xb0b1 - MX6QDL_PAD_SD4_DAT0__NAND_DQS 0x00b1 - >; - }; - - pinctrl_i2c3: i2c3grp { - fsl,pins = < - MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 - MX6QDL_PAD_GPIO_5__I2C3_SCL 0x4001b8b1 - >; - }; - - pinctrl_uart2: uart2grp { - fsl,pins = < - MX6QDL_PAD_EIM_D26__UART2_TX_DATA 0x1b0b1 - MX6QDL_PAD_EIM_D27__UART2_RX_DATA 0x1b0b1 - >; - }; +&m25p80 { + status = "disabled"; - pinctrl_usbh1_vbus: usbh1vbusgrp { - fsl,pins = < - MX6QDL_PAD_EIM_A20__GPIO2_IO18 0xb0b1 - >; - }; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - pinctrl_usbotg: usbotggrp { - fsl,pins = < - MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059 - >; - }; + partition@0 { + label = "barebox"; + reg = <0x0 0x100000>; + }; - pinctrl_usbotg_vbus: usbotgvbusgrp { - fsl,pins = < - MX6QDL_PAD_EIM_A19__GPIO2_IO19 0xb0b1 - >; - }; + partition@100000 { + label = "barebox-environment"; + reg = <0x100000 0x20000>; + }; - pinctrl_usdhc1: usdhc1grp { - fsl,pins = < - MX6QDL_PAD_SD1_CMD__SD1_CMD 0x170f9 - MX6QDL_PAD_SD1_CLK__SD1_CLK 0x100f9 - MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x170f9 - MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x170f9 - MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x170f9 - MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x170f9 - MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000 /* CD */ - >; - }; + partition@120000 { + label = "oftree"; + reg = <0x120000 0x20000>; + }; - pinctrl_usdhc4: usdhc4grp { - fsl,pins = < - MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 - MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 - MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 - MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 - MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 - MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 - MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 - MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 - MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 - MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 - >; + partition@140000 { + label = "kernel"; + reg = <0x140000 0x0>; + }; }; }; @@ -296,50 +111,20 @@ barebox,provide-mac-address = <&fec 0x620>; }; -&uart2 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_uart2>; - status = "okay"; -}; - -&usbh1 { - vbus-supply = <®_usbh1_vbus>; - disable-over-current; - status = "disabled"; -}; - -&usbotg { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usbotg>; - vbus-supply = <®_usbotg_vbus>; - disable-over-current; - status = "disabled"; -}; - -&usdhc1 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc1>; - cd-gpios = <&gpio6 31 0>; - status = "disabled"; -}; - &usdhc4 { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_usdhc4>; - bus-width = <8>; - non-removable; - status = "disabled"; - - #address-cells = <1>; - #size-cells = <1>; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; + partition@0 { + label = "barebox"; + reg = <0x0 0xe0000>; + }; - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; + partition@e0000 { + label = "barebox-environment"; + reg = <0xe0000 0x20000>; + }; }; }; diff --git a/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts index 437457ce75..378806df53 100644 --- a/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts +++ b/arch/arm/dts/imx6qp-phytec-phycore-som-nand.dts @@ -1,28 +1,22 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later) /* - * Copyright (C) 2016 Phytec Messtechnik GmbH + * Copyright (C) 2016 PHYTEC Messtechnik GmbH * Author: Christian Hemp <c.hemp@phytec.de> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html */ /dts-v1/; +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6qp.dtsi> #include "imx6qdl-phytec-phycore-som.dtsi" +#include "imx6qdl-phytec-mira.dtsi" / { - model = "Phytec phyCORE-i.MX6 Quad with NAND"; + model = "PHYTEC phyCORE-i.MX6 QuadPlus with NAND"; compatible = "phytec,imx6qp-pcm058-nand", "fsl,imx6qp"; }; -&ecspi1 { - status = "okay"; -}; - &eeprom { status = "okay"; }; @@ -35,7 +29,7 @@ status = "okay"; }; -&flash { +&m25p80 { status = "okay"; }; @@ -53,20 +47,4 @@ &usdhc1 { status = "okay"; - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - partition@0 { - label = "barebox"; - reg = <0x0 0xe0000>; - }; - - partition@e0000 { - label = "barebox-environment"; - reg = <0xe0000 0x20000>; - }; - }; }; diff --git a/arch/arm/dts/imx6s-phytec-pbab01.dts b/arch/arm/dts/imx6s-phytec-pbab01.dts index 1cb5a237a3..516d20f776 100644 --- a/arch/arm/dts/imx6s-phytec-pbab01.dts +++ b/arch/arm/dts/imx6s-phytec-pbab01.dts @@ -10,7 +10,9 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include "imx6s-phytec-pfla02.dtsi" #include "imx6qdl-phytec-pbab01.dtsi" diff --git a/arch/arm/dts/imx6ul-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6ul-phytec-phycore-som-nand.dts index 67478e26dc..c8d43c5e25 100644 --- a/arch/arm/dts/imx6ul-phytec-phycore-som-nand.dts +++ b/arch/arm/dts/imx6ul-phytec-phycore-som-nand.dts @@ -5,7 +5,9 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6ul.dtsi> #include "imx6ul-phytec-phycore-som.dtsi" #include "imx6ul-phytec-state.dtsi" diff --git a/arch/arm/dts/imx6ull-phytec-phycore-som-emmc.dts b/arch/arm/dts/imx6ull-phytec-phycore-som-emmc.dts index aa162cc42d..2201b4c1b2 100644 --- a/arch/arm/dts/imx6ull-phytec-phycore-som-emmc.dts +++ b/arch/arm/dts/imx6ull-phytec-phycore-som-emmc.dts @@ -5,7 +5,9 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6ull.dtsi> #include "imx6ul-phytec-phycore-som.dtsi" diff --git a/arch/arm/dts/imx6ull-phytec-phycore-som-lc-nand.dts b/arch/arm/dts/imx6ull-phytec-phycore-som-lc-nand.dts index e6c588b449..9c912df4de 100644 --- a/arch/arm/dts/imx6ull-phytec-phycore-som-lc-nand.dts +++ b/arch/arm/dts/imx6ull-phytec-phycore-som-lc-nand.dts @@ -5,7 +5,9 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6ull.dtsi> #include "imx6ul-phytec-phycore-som.dtsi" diff --git a/arch/arm/dts/imx6ull-phytec-phycore-som-nand.dts b/arch/arm/dts/imx6ull-phytec-phycore-som-nand.dts index a5fa3e051c..224e853e1a 100644 --- a/arch/arm/dts/imx6ull-phytec-phycore-som-nand.dts +++ b/arch/arm/dts/imx6ull-phytec-phycore-som-nand.dts @@ -5,7 +5,9 @@ */ /dts-v1/; - +#ifdef CONFIG_BOOTM_FITIMAGE_PUBKEY +#include CONFIG_BOOTM_FITIMAGE_PUBKEY +#endif #include <arm/imx6ull.dtsi> #include "imx6ul-phytec-phycore-som.dtsi" #include "imx6ul-phytec-state.dtsi" diff --git a/arch/arm/dts/stm32mp157a-dk1.dtsi b/arch/arm/dts/stm32mp157a-dk1.dtsi index e9e386a664..6be208f32e 100644 --- a/arch/arm/dts/stm32mp157a-dk1.dtsi +++ b/arch/arm/dts/stm32mp157a-dk1.dtsi @@ -8,10 +8,6 @@ #include <dt-bindings/gpio/gpio.h> / { - aliases { - mmc0 = &sdmmc1; - }; - chosen { environment { compatible = "barebox,environment"; diff --git a/arch/arm/dts/stm32mp157c.dtsi b/arch/arm/dts/stm32mp157c.dtsi index 97c075a020..e416c89856 100644 --- a/arch/arm/dts/stm32mp157c.dtsi +++ b/arch/arm/dts/stm32mp157c.dtsi @@ -18,11 +18,19 @@ gpio9 = &gpioj; gpio10 = &gpiok; gpio25 = &gpioz; + mmc0 = &sdmmc1; }; psci { compatible = "arm,psci-0.2"; }; + + soc { + memory-controller@5a003000 { + compatible = "st,stm32mp1-ddr"; + reg = <0x5a003000 0x1000>; + }; + }; }; &bsec { diff --git a/arch/arm/include/asm/barebox-arm-head.h b/arch/arm/include/asm/barebox-arm-head.h index 83a22c4d94..8409a77d2e 100644 --- a/arch/arm/include/asm/barebox-arm-head.h +++ b/arch/arm/include/asm/barebox-arm-head.h @@ -65,7 +65,11 @@ static inline void __barebox_arm_head(void) ".endr\n" "2:\n" #ifdef CONFIG_PBL_BREAK +#ifdef CONFIG_CPU_V8 + "brk #17\n" +#else "bkpt #17\n" +#endif "nop\n" #else "nop\n" diff --git a/arch/arm/include/asm/pgtable64.h b/arch/arm/include/asm/pgtable64.h index d8382505d0..d142612d0d 100644 --- a/arch/arm/include/asm/pgtable64.h +++ b/arch/arm/include/asm/pgtable64.h @@ -21,7 +21,7 @@ #define UNUSED_DESC 0x6EbAAD0BBADbA6E0 #define VA_START 0x0 -#define BITS_PER_VA 39 +#define BITS_PER_VA 48 /* Granule size of 4KB is being used */ #define GRANULE_SIZE_SHIFT 12 @@ -30,11 +30,13 @@ #define GRANULE_SIZE_MASK ((1 << GRANULE_SIZE_SHIFT) - 1) #define BITS_RESOLVED_PER_LVL (GRANULE_SIZE_SHIFT - 3) +#define L0_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 3) #define L1_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 2) #define L2_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 1) #define L3_ADDR_SHIFT (GRANULE_SIZE_SHIFT + BITS_RESOLVED_PER_LVL * 0) +#define L0_ADDR_MASK (((1UL << BITS_RESOLVED_PER_LVL) - 1) << L0_ADDR_SHIFT) #define L1_ADDR_MASK (((1UL << BITS_RESOLVED_PER_LVL) - 1) << L1_ADDR_SHIFT) #define L2_ADDR_MASK (((1UL << BITS_RESOLVED_PER_LVL) - 1) << L2_ADDR_SHIFT) #define L3_ADDR_MASK (((1UL << BITS_RESOLVED_PER_LVL) - 1) << L3_ADDR_SHIFT) @@ -44,6 +46,7 @@ #define L3_XLAT_SIZE (1UL << L3_ADDR_SHIFT) #define L2_XLAT_SIZE (1UL << L2_ADDR_SHIFT) #define L1_XLAT_SIZE (1UL << L1_ADDR_SHIFT) +#define L0_XLAT_SIZE (1UL << L0_ADDR_SHIFT) #define GRANULE_MASK GRANULE_SIZE diff --git a/arch/arm/lib32/Makefile b/arch/arm/lib32/Makefile index 3c02a0bf96..cd43147e66 100644 --- a/arch/arm/lib32/Makefile +++ b/arch/arm/lib32/Makefile @@ -1,6 +1,7 @@ obj-$(CONFIG_ARM_LINUX) += armlinux.o obj-$(CONFIG_CMD_BOOTZ) += bootz.o obj-$(CONFIG_BOOTM) += bootm.o +obj-$(CONFIG_BOOTM_OPTEE) += start-kernel-optee.o obj-$(CONFIG_CMD_BOOTU) += bootu.o obj-y += div0.o obj-y += findbit.o diff --git a/arch/arm/cpu/start-kernel-optee.S b/arch/arm/lib32/start-kernel-optee.S index 92da4b63c9..92da4b63c9 100644 --- a/arch/arm/cpu/start-kernel-optee.S +++ b/arch/arm/lib32/start-kernel-optee.S diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index 5ad1f62c8d..5267102bf9 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -65,6 +65,7 @@ config SOC_SAMA5D2 select HAVE_AT91_UTMI select HAVE_AT91_USB_CLK select HAVE_AT91_GENERATED_CLK + select PINCTRL select PINCTRL_AT91PIO4 select HAS_MACB select HAVE_MACH_ARM_HEAD diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig index 66d3d7a5f7..c6d4fce603 100644 --- a/arch/arm/mach-davinci/Kconfig +++ b/arch/arm/mach-davinci/Kconfig @@ -9,6 +9,8 @@ choice config MACH_VIRT2REAL bool "Virt2Real" + select OFTREE + select OFDEVICE endchoice diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 6e98e95dbb..f5c8a4242b 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -859,6 +859,28 @@ config HABV4_IMG_CRT_PEM endif +if HABV4 + +config HABV4_IMAGE_SIGNED + bool "build signed images" + help + enable the creation of a signed image, if the habv4-imx6-gencsf.h + included in the flash-header and the NXP cst Tool is available + +config HABV4_IMAGE_SIGNED_USB + bool "build signed USB images" + help + enable the creation of a usb signed image, if the habv4-imx6-gencsf.h + included in the flash-header and the NXP cst Tool is available + +config HABV4_IMAGE_SIGNED_ENCRYPTED + bool "build signed encrypted images" + help + enable the creation of the encrypted image, if the habv4-imx6-gencsf.h + included in the flash-header and the NXP cst Tool is available + +endif + config HABV3 tristate "HABv3 support" select HAB diff --git a/arch/arm/mach-imx/include/mach/vf610.h b/arch/arm/mach-imx/include/mach/vf610.h index 6d00d2e457..7ac10a7b1e 100644 --- a/arch/arm/mach-imx/include/mach/vf610.h +++ b/arch/arm/mach-imx/include/mach/vf610.h @@ -48,4 +48,6 @@ static inline int vf610_cpu_revision(void) return readl(VF610_ROM_VERSION_OFFSET) & 0xff; } +u64 vf610_uid(void); + #endif diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c index b548cbcb5f..2fbd6393ea 100644 --- a/arch/arm/mach-imx/vf610.c +++ b/arch/arm/mach-imx/vf610.c @@ -19,6 +19,7 @@ #include <mach/revision.h> #include <mach/vf610.h> #include <mach/reset-reason.h> +#include <mach/ocotp.h> static const struct imx_reset_reason vf610_reset_reasons[] = { { VF610_SRC_SRSR_POR_RST, RESET_POR, 0 }, @@ -30,6 +31,11 @@ static const struct imx_reset_reason vf610_reset_reasons[] = { { /* sentinel */ } }; +u64 vf610_uid(void) +{ + return imx_ocotp_read_uid(IOMEM(VF610_OCOTP_BASE_ADDR)); +} + int vf610_init(void) { const char *cputypestr; @@ -57,5 +63,7 @@ int vf610_init(void) imx_set_silicon_revision(cputypestr, vf610_cpu_revision()); imx_set_reset_reason(src + IMX_SRC_SRSR, vf610_reset_reasons); + pr_info("%s unique ID: %llx\n", cputypestr, vf610_uid()); + return 0; } diff --git a/arch/arm/mach-layerscape/Kconfig b/arch/arm/mach-layerscape/Kconfig index 139c63f66d..c15d5873a5 100644 --- a/arch/arm/mach-layerscape/Kconfig +++ b/arch/arm/mach-layerscape/Kconfig @@ -30,5 +30,8 @@ config MACH_LS1046ARDB config MACH_TQMLS1046A bool "TQ TQMLS1046A Board" select ARCH_LS1046 + select MCI_IMX_ESDHC_PBL + select DDR_FSL + select DDR_FSL_DDR4 endif diff --git a/arch/arm/mach-layerscape/ppa.c b/arch/arm/mach-layerscape/ppa.c index 6070451020..477e894781 100644 --- a/arch/arm/mach-layerscape/ppa.c +++ b/arch/arm/mach-layerscape/ppa.c @@ -14,18 +14,37 @@ #include <image-fit.h> #include <asm/psci.h> #include <mach/layerscape.h> +#include <asm/cache.h> int ppa_entry(const void *, u32 *, u32 *); -void dma_flush_range(void *ptr, size_t size); + +#define SEC_JR3_OFFSET 0x40000 static int of_psci_do_fixup(struct device_node *root, void *unused) { unsigned long psci_version; + struct device_node *np; struct arm_smccc_res res = {}; arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0, 0, 0, 0, 0, &res); psci_version = res.a0; + for_each_compatible_node_from(np, root, NULL, "fsl,sec-v4.0-job-ring") { + const void *reg; + int na = of_n_addr_cells(np); + u64 offset; + + reg = of_get_property(np, "reg", NULL); + if (!reg) + continue; + + offset = of_read_number(reg, na); + if (offset != SEC_JR3_OFFSET) + continue; + + of_delete_node(np); + } + return of_psci_fixup(root, psci_version); } @@ -73,7 +92,7 @@ static int ppa_init(void *ppa, size_t ppa_size, void *sec_firmware_addr) /* Copy the secure firmware to secure memory */ memcpy(sec_firmware_addr, buf, firmware_size); - dma_flush_range(sec_firmware_addr, ppa_size); + sync_caches_for_execution(); ret = ppa_entry(sec_firmware_addr, boot_loc_ptr_l, boot_loc_ptr_h); if (ret) { diff --git a/arch/arm/mach-mxs/bcb.c b/arch/arm/mach-mxs/bcb.c index fce607f634..860508bde7 100644 --- a/arch/arm/mach-mxs/bcb.c +++ b/arch/arm/mach-mxs/bcb.c @@ -314,7 +314,7 @@ static int write_fcb(struct mtd_info *mtd, void *buf, int block) return ret; } -int update_bcb(int argc, char *argv[]) +static int update_bcb(int argc, char *argv[]) { int ret; int block; diff --git a/arch/arm/mach-omap/am33xx_clock.c b/arch/arm/mach-omap/am33xx_clock.c index e63e93601e..0a49038270 100644 --- a/arch/arm/mach-omap/am33xx_clock.c +++ b/arch/arm/mach-omap/am33xx_clock.c @@ -142,11 +142,13 @@ void am33xx_enable_per_clocks(void) __raw_writel(PRCM_MOD_EN, CM_PER_CPSW_CLKSTCTRL); while ((__raw_readl(CM_PER_CPGMAC0_CLKCTRL) & 0x30000) != 0x0); - /* MMC 0 & 1 */ + /* MMC 0, 1 & 2 */ __raw_writel(PRCM_MOD_EN, CM_PER_MMC0_CLKCTRL); while (__raw_readl(CM_PER_MMC0_CLKCTRL) != PRCM_MOD_EN); __raw_writel(PRCM_MOD_EN, CM_PER_MMC1_CLKCTRL); while (__raw_readl(CM_PER_MMC1_CLKCTRL) != PRCM_MOD_EN); + __raw_writel(PRCM_MOD_EN, CM_PER_MMC2_CLKCTRL); + while (__raw_readl(CM_PER_MMC2_CLKCTRL) != PRCM_MOD_EN); /* Enable the control module though RBL would have done it*/ __raw_writel(PRCM_MOD_EN, CM_WKUP_CONTROL_CLKCTRL); diff --git a/arch/arm/mach-stm32mp/Makefile b/arch/arm/mach-stm32mp/Makefile index 6f49528892..8e14b22535 100644 --- a/arch/arm/mach-stm32mp/Makefile +++ b/arch/arm/mach-stm32mp/Makefile @@ -1,2 +1,3 @@ obj-y := init.o +obj-pbl-y := ddrctrl.o obj-$(CONFIG_BOOTM) += stm32image.o diff --git a/arch/arm/mach-stm32mp/ddrctrl.c b/arch/arm/mach-stm32mp/ddrctrl.c new file mode 100644 index 0000000000..962d4c0d52 --- /dev/null +++ b/arch/arm/mach-stm32mp/ddrctrl.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Ahmad Fatoum <a.fatoum@pengutronix.de> + */ + +#include <common.h> +#include <init.h> +#include <mach/stm32.h> +#include <mach/ddr_regs.h> +#include <mach/entry.h> +#include <mach/stm32.h> +#include <asm/barebox-arm.h> +#include <asm/memory.h> +#include <pbl.h> +#include <io.h> + +#define ADDRMAP1_BANK_B0 GENMASK( 5, 0) +#define ADDRMAP1_BANK_B1 GENMASK(13, 8) +#define ADDRMAP1_BANK_B2 GENMASK(21, 16) + +#define ADDRMAP2_COL_B2 GENMASK( 3, 0) +#define ADDRMAP2_COL_B3 GENMASK(11, 8) +#define ADDRMAP2_COL_B4 GENMASK(19, 16) +#define ADDRMAP2_COL_B5 GENMASK(27, 24) + +#define ADDRMAP3_COL_B6 GENMASK( 3, 0) +#define ADDRMAP3_COL_B7 GENMASK(12, 8) +#define ADDRMAP3_COL_B8 GENMASK(20, 16) +#define ADDRMAP3_COL_B9 GENMASK(28, 24) + +#define ADDRMAP4_COL_B10 GENMASK( 4, 0) +#define ADDRMAP4_COL_B11 GENMASK(12, 8) + +#define ADDRMAP5_ROW_B0 GENMASK( 3, 0) +#define ADDRMAP5_ROW_B1 GENMASK(11, 8) +#define ADDRMAP5_ROW_B2_10 GENMASK(19, 16) +#define ADDRMAP5_ROW_B11 GENMASK(27, 24) + +#define ADDRMAP6_ROW_B12 GENMASK( 3, 0) +#define ADDRMAP6_ROW_B13 GENMASK(11, 8) +#define ADDRMAP6_ROW_B14 GENMASK(19, 16) +#define ADDRMAP6_ROW_B15 GENMASK(27, 24) + +#define ADDRMAP9_ROW_B2 GENMASK( 3, 0) +#define ADDRMAP9_ROW_B3 GENMASK(11, 8) +#define ADDRMAP9_ROW_B4 GENMASK(19, 16) +#define ADDRMAP9_ROW_B5 GENMASK(27, 24) + +#define ADDRMAP10_ROW_B6 GENMASK( 3, 0) +#define ADDRMAP10_ROW_B7 GENMASK(11, 8) +#define ADDRMAP10_ROW_B8 GENMASK(19, 16) +#define ADDRMAP10_ROW_B9 GENMASK(27, 24) + +#define ADDRMAP11_ROW_B10 GENMASK( 3, 0) + +#define LINE_UNUSED(reg, mask) (((reg) & (mask)) == (mask)) + +enum ddrctrl_buswidth { + BUSWIDTH_FULL = 0, + BUSWIDTH_HALF = 1, + BUSWIDTH_QUARTER = 2 +}; + +static unsigned long ddrctrl_addrmap_ramsize(struct stm32mp1_ddrctl __iomem *d, + enum ddrctrl_buswidth buswidth) +{ + unsigned banks = 3, cols = 12, rows = 16; + u32 reg; + + cols += buswidth; + + reg = readl(&d->addrmap1); + if (LINE_UNUSED(reg, ADDRMAP1_BANK_B2)) banks--; + if (LINE_UNUSED(reg, ADDRMAP1_BANK_B1)) banks--; + if (LINE_UNUSED(reg, ADDRMAP1_BANK_B0)) banks--; + + reg = readl(&d->addrmap2); + if (LINE_UNUSED(reg, ADDRMAP2_COL_B5)) cols--; + if (LINE_UNUSED(reg, ADDRMAP2_COL_B4)) cols--; + if (LINE_UNUSED(reg, ADDRMAP2_COL_B3)) cols--; + if (LINE_UNUSED(reg, ADDRMAP2_COL_B2)) cols--; + + reg = readl(&d->addrmap3); + if (LINE_UNUSED(reg, ADDRMAP3_COL_B9)) cols--; + if (LINE_UNUSED(reg, ADDRMAP3_COL_B8)) cols--; + if (LINE_UNUSED(reg, ADDRMAP3_COL_B7)) cols--; + if (LINE_UNUSED(reg, ADDRMAP3_COL_B6)) cols--; + + reg = readl(&d->addrmap4); + if (LINE_UNUSED(reg, ADDRMAP4_COL_B11)) cols--; + if (LINE_UNUSED(reg, ADDRMAP4_COL_B10)) cols--; + + reg = readl(&d->addrmap5); + if (LINE_UNUSED(reg, ADDRMAP5_ROW_B11)) rows--; + + reg = readl(&d->addrmap6); + if (LINE_UNUSED(reg, ADDRMAP6_ROW_B15)) rows--; + if (LINE_UNUSED(reg, ADDRMAP6_ROW_B14)) rows--; + if (LINE_UNUSED(reg, ADDRMAP6_ROW_B13)) rows--; + if (LINE_UNUSED(reg, ADDRMAP6_ROW_B12)) rows--; + + return memory_sdram_size(cols, rows, BIT(banks), 4 / BIT(buswidth)); +} + +static inline unsigned ddrctrl_ramsize(void __iomem *base) +{ + struct stm32mp1_ddrctl __iomem *ddrctl = base; + unsigned buswidth = readl(&ddrctl->mstr) & DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK; + buswidth >>= DDRCTRL_MSTR_DATA_BUS_WIDTH_SHIFT; + + return ddrctrl_addrmap_ramsize(ddrctl, buswidth); +} + +static inline unsigned stm32mp1_ddrctrl_ramsize(void) +{ + return ddrctrl_ramsize(IOMEM(STM32_DDRCTL_BASE)); +} + +void __noreturn stm32mp1_barebox_entry(void *boarddata) +{ + barebox_arm_entry(STM32_DDR_BASE, stm32mp1_ddrctrl_ramsize(), boarddata); +} + + +static int stm32mp1_ddr_probe(struct device_d *dev) +{ + struct resource *iores; + void __iomem *base; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + base = IOMEM(iores->start); + + arm_add_mem_device("ram0", STM32_DDR_BASE, ddrctrl_ramsize(base)); + + return 0; +} + +static __maybe_unused struct of_device_id stm32mp1_ddr_dt_ids[] = { + { .compatible = "st,stm32mp1-ddr" }, + { /* sentinel */ } +}; + +static struct driver_d stm32mp1_ddr_driver = { + .name = "stm32mp1-ddr", + .probe = stm32mp1_ddr_probe, + .of_compatible = DRV_OF_COMPAT(stm32mp1_ddr_dt_ids), +}; + +static int stm32mp1_ddr_init(void) +{ + return platform_driver_register(&stm32mp1_ddr_driver); +} +mem_initcall(stm32mp1_ddr_init); diff --git a/arch/arm/mach-stm32mp/include/mach/ddr_regs.h b/arch/arm/mach-stm32mp/include/mach/ddr_regs.h new file mode 100644 index 0000000000..7d6a5b8be4 --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/ddr_regs.h @@ -0,0 +1,368 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + */ + +#ifndef _STM32MP1_DDR_REGS_H +#define _STM32MP1_DDR_REGS_H + +/* DDR3/LPDDR2/LPDDR3 Controller (DDRCTRL) registers */ +struct stm32mp1_ddrctl { + u32 mstr ; /* 0x0 Master*/ + u32 stat; /* 0x4 Operating Mode Status*/ + u8 reserved008[0x10 - 0x8]; + u32 mrctrl0; /* 0x10 Control 0.*/ + u32 mrctrl1; /* 0x14 Control 1*/ + u32 mrstat; /* 0x18 Status*/ + u32 reserved01c; /* 0x1c */ + u32 derateen; /* 0x20 Temperature Derate Enable*/ + u32 derateint; /* 0x24 Temperature Derate Interval*/ + u8 reserved028[0x30 - 0x28]; + u32 pwrctl; /* 0x30 Low Power Control*/ + u32 pwrtmg; /* 0x34 Low Power Timing*/ + u32 hwlpctl; /* 0x38 Hardware Low Power Control*/ + u8 reserved03c[0x50 - 0x3C]; + u32 rfshctl0; /* 0x50 Refresh Control 0*/ + u32 reserved054; /* 0x54 Refresh Control 1*/ + u32 reserved058; /* 0x58 Refresh Control 2*/ + u32 reserved05C; + u32 rfshctl3; /* 0x60 Refresh Control 0*/ + u32 rfshtmg; /* 0x64 Refresh Timing*/ + u8 reserved068[0xc0 - 0x68]; + u32 crcparctl0; /* 0xc0 CRC Parity Control0*/ + u32 reserved0c4; /* 0xc4 CRC Parity Control1*/ + u32 reserved0c8; /* 0xc8 CRC Parity Control2*/ + u32 crcparstat; /* 0xcc CRC Parity Status*/ + u32 init0; /* 0xd0 SDRAM Initialization 0*/ + u32 init1; /* 0xd4 SDRAM Initialization 1*/ + u32 init2; /* 0xd8 SDRAM Initialization 2*/ + u32 init3; /* 0xdc SDRAM Initialization 3*/ + u32 init4; /* 0xe0 SDRAM Initialization 4*/ + u32 init5; /* 0xe4 SDRAM Initialization 5*/ + u32 reserved0e8; + u32 reserved0ec; + u32 dimmctl; /* 0xf0 DIMM Control*/ + u8 reserved0f4[0x100 - 0xf4]; + u32 dramtmg0; /* 0x100 SDRAM Timing 0*/ + u32 dramtmg1; /* 0x104 SDRAM Timing 1*/ + u32 dramtmg2; /* 0x108 SDRAM Timing 2*/ + u32 dramtmg3; /* 0x10c SDRAM Timing 3*/ + u32 dramtmg4; /* 0x110 SDRAM Timing 4*/ + u32 dramtmg5; /* 0x114 SDRAM Timing 5*/ + u32 dramtmg6; /* 0x118 SDRAM Timing 6*/ + u32 dramtmg7; /* 0x11c SDRAM Timing 7*/ + u32 dramtmg8; /* 0x120 SDRAM Timing 8*/ + u8 reserved124[0x138 - 0x124]; + u32 dramtmg14; /* 0x138 SDRAM Timing 14*/ + u32 dramtmg15; /* 0x13C SDRAM Timing 15*/ + u8 reserved140[0x180 - 0x140]; + u32 zqctl0; /* 0x180 ZQ Control 0*/ + u32 zqctl1; /* 0x184 ZQ Control 1*/ + u32 zqctl2; /* 0x188 ZQ Control 2*/ + u32 zqstat; /* 0x18c ZQ Status*/ + u32 dfitmg0; /* 0x190 DFI Timing 0*/ + u32 dfitmg1; /* 0x194 DFI Timing 1*/ + u32 dfilpcfg0; /* 0x198 DFI Low Power Configuration 0*/ + u32 reserved19c; + u32 dfiupd0; /* 0x1a0 DFI Update 0*/ + u32 dfiupd1; /* 0x1a4 DFI Update 1*/ + u32 dfiupd2; /* 0x1a8 DFI Update 2*/ + u32 reserved1ac; + u32 dfimisc; /* 0x1b0 DFI Miscellaneous Control*/ + u8 reserved1b4[0x1bc - 0x1b4]; + u32 dfistat; /* 0x1bc DFI Miscellaneous Control*/ + u8 reserved1c0[0x1c4 - 0x1c0]; + u32 dfiphymstr; /* 0x1c4 DFI PHY Master interface*/ + u8 reserved1c8[0x204 - 0x1c8]; + u32 addrmap1; /* 0x204 Address Map 1*/ + u32 addrmap2; /* 0x208 Address Map 2*/ + u32 addrmap3; /* 0x20c Address Map 3*/ + u32 addrmap4; /* 0x210 Address Map 4*/ + u32 addrmap5; /* 0x214 Address Map 5*/ + u32 addrmap6; /* 0x218 Address Map 6*/ + u8 reserved21c[0x224 - 0x21c]; + u32 addrmap9; /* 0x224 Address Map 9*/ + u32 addrmap10; /* 0x228 Address Map 10*/ + u32 addrmap11; /* 0x22C Address Map 11*/ + u8 reserved230[0x240 - 0x230]; + u32 odtcfg; /* 0x240 ODT Configuration*/ + u32 odtmap; /* 0x244 ODT/Rank Map*/ + u8 reserved248[0x250 - 0x248]; + u32 sched; /* 0x250 Scheduler Control*/ + u32 sched1; /* 0x254 Scheduler Control 1*/ + u32 reserved258; + u32 perfhpr1; /* 0x25c High Priority Read CAM 1*/ + u32 reserved260; + u32 perflpr1; /* 0x264 Low Priority Read CAM 1*/ + u32 reserved268; + u32 perfwr1; /* 0x26c Write CAM 1*/ + u8 reserved27c[0x300 - 0x270]; + u32 dbg0; /* 0x300 Debug 0*/ + u32 dbg1; /* 0x304 Debug 1*/ + u32 dbgcam; /* 0x308 CAM Debug*/ + u32 dbgcmd; /* 0x30c Command Debug*/ + u32 dbgstat; /* 0x310 Status Debug*/ + u8 reserved314[0x320 - 0x314]; + u32 swctl; /* 0x320 Software Programming Control Enable*/ + u32 swstat; /* 0x324 Software Programming Control Status*/ + u8 reserved328[0x36c - 0x328]; + u32 poisoncfg; /* 0x36c AXI Poison Configuration Register*/ + u32 poisonstat; /* 0x370 AXI Poison Status Register*/ + u8 reserved374[0x3fc - 0x374]; + + /* Multi Port registers */ + u32 pstat; /* 0x3fc Port Status*/ + u32 pccfg; /* 0x400 Port Common Configuration*/ + + /* PORT 0 */ + u32 pcfgr_0; /* 0x404 Configuration Read*/ + u32 pcfgw_0; /* 0x408 Configuration Write*/ + u8 reserved40c[0x490 - 0x40c]; + u32 pctrl_0; /* 0x490 Port Control Register */ + u32 pcfgqos0_0; /* 0x494 Read QoS Configuration 0*/ + u32 pcfgqos1_0; /* 0x498 Read QoS Configuration 1*/ + u32 pcfgwqos0_0; /* 0x49c Write QoS Configuration 0*/ + u32 pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1*/ + u8 reserved4a4[0x4b4 - 0x4a4]; + + /* PORT 1 */ + u32 pcfgr_1; /* 0x4b4 Configuration Read*/ + u32 pcfgw_1; /* 0x4b8 Configuration Write*/ + u8 reserved4bc[0x540 - 0x4bc]; + u32 pctrl_1; /* 0x540 Port 2 Control Register */ + u32 pcfgqos0_1; /* 0x544 Read QoS Configuration 0*/ + u32 pcfgqos1_1; /* 0x548 Read QoS Configuration 1*/ + u32 pcfgwqos0_1; /* 0x54c Write QoS Configuration 0*/ + u32 pcfgwqos1_1; /* 0x550 Write QoS Configuration 1*/ +}; + +/* DDR Physical Interface Control (DDRPHYC) registers*/ +struct stm32mp1_ddrphy { + u32 ridr; /* 0x00 R Revision Identification*/ + u32 pir; /* 0x04 R/W PHY Initialization*/ + u32 pgcr; /* 0x08 R/W PHY General Configuration*/ + u32 pgsr; /* 0x0C PHY General Status*/ + u32 dllgcr; /* 0x10 R/W DLL General Control*/ + u32 acdllcr; /* 0x14 R/W AC DLL Control*/ + u32 ptr0; /* 0x18 R/W PHY Timing 0*/ + u32 ptr1; /* 0x1C R/W PHY Timing 1*/ + u32 ptr2; /* 0x20 R/W PHY Timing 2*/ + u32 aciocr; /* 0x24 AC I/O Configuration*/ + u32 dxccr; /* 0x28 DATX8 Common Configuration*/ + u32 dsgcr; /* 0x2C DDR System General Configuration*/ + u32 dcr; /* 0x30 DRAM Configuration*/ + u32 dtpr0; /* 0x34 DRAM Timing Parameters0*/ + u32 dtpr1; /* 0x38 DRAM Timing Parameters1*/ + u32 dtpr2; /* 0x3C DRAM Timing Parameters2*/ + u32 mr0; /* 0x40 Mode 0*/ + u32 mr1; /* 0x44 Mode 1*/ + u32 mr2; /* 0x48 Mode 2*/ + u32 mr3; /* 0x4C Mode 3*/ + u32 odtcr; /* 0x50 ODT Configuration*/ + u32 dtar; /* 0x54 data training address*/ + u32 dtdr0; /* 0x58 */ + u32 dtdr1; /* 0x5c */ + u8 res1[0x0c0 - 0x060]; /* 0x60 */ + u32 dcuar; /* 0xc0 Address*/ + u32 dcudr; /* 0xc4 DCU Data*/ + u32 dcurr; /* 0xc8 DCU Run*/ + u32 dculr; /* 0xcc DCU Loop*/ + u32 dcugcr; /* 0xd0 DCU General Configuration*/ + u32 dcutpr; /* 0xd4 DCU Timing Parameters */ + u32 dcusr0; /* 0xd8 DCU Status 0*/ + u32 dcusr1; /* 0xdc DCU Status 1*/ + u8 res2[0x100 - 0xe0]; /* 0xe0 */ + u32 bistrr; /* 0x100 BIST Run*/ + u32 bistmskr0; /* 0x104 BIST Mask 0*/ + u32 bistmskr1; /* 0x108 BIST Mask 0*/ + u32 bistwcr; /* 0x10c BIST Word Count*/ + u32 bistlsr; /* 0x110 BIST LFSR Seed*/ + u32 bistar0; /* 0x114 BIST Address 0*/ + u32 bistar1; /* 0x118 BIST Address 1*/ + u32 bistar2; /* 0x11c BIST Address 2*/ + u32 bistupdr; /* 0x120 BIST User Data Pattern*/ + u32 bistgsr; /* 0x124 BIST General Status*/ + u32 bistwer; /* 0x128 BIST Word Error*/ + u32 bistber0; /* 0x12c BIST Bit Error 0*/ + u32 bistber1; /* 0x130 BIST Bit Error 1*/ + u32 bistber2; /* 0x134 BIST Bit Error 2*/ + u32 bistwcsr; /* 0x138 BIST Word Count Status*/ + u32 bistfwr0; /* 0x13c BIST Fail Word 0*/ + u32 bistfwr1; /* 0x140 BIST Fail Word 1*/ + u8 res3[0x178 - 0x144]; /* 0x144 */ + u32 gpr0; /* 0x178 General Purpose 0 (GPR0)*/ + u32 gpr1; /* 0x17C General Purpose 1 (GPR1)*/ + u32 zq0cr0; /* 0x180 zq 0 control 0 */ + u32 zq0cr1; /* 0x184 zq 0 control 1 */ + u32 zq0sr0; /* 0x188 zq 0 status 0 */ + u32 zq0sr1; /* 0x18C zq 0 status 1 */ + u8 res4[0x1C0 - 0x190]; /* 0x190 */ + u32 dx0gcr; /* 0x1c0 Byte lane 0 General Configuration*/ + u32 dx0gsr0; /* 0x1c4 Byte lane 0 General Status 0*/ + u32 dx0gsr1; /* 0x1c8 Byte lane 0 General Status 1*/ + u32 dx0dllcr; /* 0x1cc Byte lane 0 DLL Control*/ + u32 dx0dqtr; /* 0x1d0 Byte lane 0 DQ Timing*/ + u32 dx0dqstr; /* 0x1d4 Byte lane 0 DQS Timing*/ + u8 res5[0x200 - 0x1d8]; /* 0x1d8 */ + u32 dx1gcr; /* 0x200 Byte lane 1 General Configuration*/ + u32 dx1gsr0; /* 0x204 Byte lane 1 General Status 0*/ + u32 dx1gsr1; /* 0x208 Byte lane 1 General Status 1*/ + u32 dx1dllcr; /* 0x20c Byte lane 1 DLL Control*/ + u32 dx1dqtr; /* 0x210 Byte lane 1 DQ Timing*/ + u32 dx1dqstr; /* 0x214 Byte lane 1 QS Timing*/ + u8 res6[0x240 - 0x218]; /* 0x218 */ + u32 dx2gcr; /* 0x240 Byte lane 2 General Configuration*/ + u32 dx2gsr0; /* 0x244 Byte lane 2 General Status 0*/ + u32 dx2gsr1; /* 0x248 Byte lane 2 General Status 1*/ + u32 dx2dllcr; /* 0x24c Byte lane 2 DLL Control*/ + u32 dx2dqtr; /* 0x250 Byte lane 2 DQ Timing*/ + u32 dx2dqstr; /* 0x254 Byte lane 2 QS Timing*/ + u8 res7[0x280 - 0x258]; /* 0x258 */ + u32 dx3gcr; /* 0x280 Byte lane 3 General Configuration*/ + u32 dx3gsr0; /* 0x284 Byte lane 3 General Status 0*/ + u32 dx3gsr1; /* 0x288 Byte lane 3 General Status 1*/ + u32 dx3dllcr; /* 0x28c Byte lane 3 DLL Control*/ + u32 dx3dqtr; /* 0x290 Byte lane 3 DQ Timing*/ + u32 dx3dqstr; /* 0x294 Byte lane 3 QS Timing*/ +}; + +#define DXN(phy, offset, byte) ((u32)(phy) + (offset) + ((u32)(byte) * 0x40)) +#define DXNGCR(phy, byte) DXN(phy, 0x1c0, byte) +#define DXNDLLCR(phy, byte) DXN(phy, 0x1cc, byte) +#define DXNDQTR(phy, byte) DXN(phy, 0x1d0, byte) +#define DXNDQSTR(phy, byte) DXN(phy, 0x1d4, byte) + +/* DDRCTRL REGISTERS */ +#define DDRCTRL_MSTR_DDR3 BIT(0) +#define DDRCTRL_MSTR_LPDDR2 BIT(2) +#define DDRCTRL_MSTR_LPDDR3 BIT(3) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_SHIFT 12 +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL (0 << 12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF (1 << 12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER (2 << 12) +#define DDRCTRL_MSTR_DLL_OFF_MODE BIT(15) + +#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0) +#define DDRCTRL_STAT_OPERATING_MODE_NORMAL 1 +#define DDRCTRL_STAT_OPERATING_MODE_SR 3 +#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4) +#define DDRCTRL_STAT_SELFREF_TYPE_ASR (3 << 4) +#define DDRCTRL_STAT_SELFREF_TYPE_SR (2 << 4) + +#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE 0 +/* only one rank supported */ +#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 +#define DDRCTRL_MRCTRL0_MR_RANK_ALL \ + (0x1 << DDRCTRL_MRCTRL0_MR_RANK_SHIFT) +#define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12 +#define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12) +#define DDRCTRL_MRCTRL0_MR_WR BIT(31) + +#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0) + +#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1) +#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) + +#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) + +#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16) +#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 + +#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK (0xC0000000) +#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL (BIT(30)) + +#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) + +#define DDRCTRL_DBG1_DIS_HIF BIT(1) + +#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) +#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) +#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) +#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) +#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) +#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ + (DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ + DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) +#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ + (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ + DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ + DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) + +#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) + +#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) + +#define DDRCTRL_SWCTL_SW_DONE BIT(0) + +#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) + +#define DDRCTRL_PCTRL_N_PORT_EN BIT(0) + +/* DDRPHYC registers */ +#define DDRPHYC_PIR_INIT BIT(0) +#define DDRPHYC_PIR_DLLSRST BIT(1) +#define DDRPHYC_PIR_DLLLOCK BIT(2) +#define DDRPHYC_PIR_ZCAL BIT(3) +#define DDRPHYC_PIR_ITMSRST BIT(4) +#define DDRPHYC_PIR_DRAMRST BIT(5) +#define DDRPHYC_PIR_DRAMINIT BIT(6) +#define DDRPHYC_PIR_QSTRN BIT(7) +#define DDRPHYC_PIR_ICPC BIT(16) +#define DDRPHYC_PIR_ZCALBYP BIT(30) +#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) + +#define DDRPHYC_PGCR_DFTCMP BIT(2) +#define DDRPHYC_PGCR_PDDISDX BIT(24) +#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK(28, 25) + +#define DDRPHYC_PGSR_IDONE BIT(0) +#define DDRPHYC_PGSR_DTERR BIT(5) +#define DDRPHYC_PGSR_DTIERR BIT(6) +#define DDRPHYC_PGSR_DFTERR BIT(7) +#define DDRPHYC_PGSR_RVERR BIT(8) +#define DDRPHYC_PGSR_RVEIRR BIT(9) + +#define DDRPHYC_DLLGCR_BPS200 BIT(23) + +#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) + +#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) +#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 +#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) + +#define DDRPHYC_DXNGCR_DXEN BIT(0) + +#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) +#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) +#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) +#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 + +#define DDRPHYC_DXNDQTR_DQDLY_SHIFT(bit) (4 * (bit)) +#define DDRPHYC_DXNDQTR_DQDLY_MASK GENMASK(3, 0) +#define DDRPHYC_DXNDQTR_DQDLY_LOW_MASK GENMASK(1, 0) +#define DDRPHYC_DXNDQTR_DQDLY_HIGH_MASK GENMASK(3, 2) + +#define DDRPHYC_DXNDQSTR_DQSDLY_MASK GENMASK(22, 20) +#define DDRPHYC_DXNDQSTR_DQSDLY_SHIFT 20 +#define DDRPHYC_DXNDQSTR_DQSNDLY_MASK GENMASK(25, 23) +#define DDRPHYC_DXNDQSTR_DQSNDLY_SHIFT 23 +#define DDRPHYC_DXNDQSTR_R0DGSL_MASK GENMASK(2, 0) +#define DDRPHYC_DXNDQSTR_R0DGSL_SHIFT 0 +#define DDRPHYC_DXNDQSTR_R0DGPS_MASK GENMASK(13, 12) +#define DDRPHYC_DXNDQSTR_R0DGPS_SHIFT 12 + +#define DDRPHYC_BISTRR_BDXSEL_MASK GENMASK(22, 19) +#define DDRPHYC_BISTRR_BDXSEL_SHIFT 19 + +#define DDRPHYC_BISTGSR_BDDONE BIT(0) +#define DDRPHYC_BISTGSR_BDXERR BIT(2) + +#define DDRPHYC_BISTWCSR_DXWCNT_SHIFT 16 + +/* PWR registers */ +#define PWR_CR3 0x00C +#define PWR_CR3_DDRSRDIS BIT(11) +#define PWR_CR3_DDRRETEN BIT(12) + +#endif diff --git a/arch/arm/mach-stm32mp/include/mach/entry.h b/arch/arm/mach-stm32mp/include/mach/entry.h new file mode 100644 index 0000000000..92e15b5cf4 --- /dev/null +++ b/arch/arm/mach-stm32mp/include/mach/entry.h @@ -0,0 +1,19 @@ +#ifndef _STM32MP_MACH_ENTRY_H_ +#define _STM32MP_MACH_ENTRY_H_ + +#include <linux/kernel.h> +#include <asm/barebox-arm.h> + +static __always_inline void stm32mp_cpu_lowlevel_init(void) +{ + unsigned long stack_top; + arm_cpu_lowlevel_init(); + + stack_top = (unsigned long)__image_end + get_runtime_offset() + 64; + stack_top = ALIGN(stack_top, 16); + arm_setup_stack(stack_top); +} + +void __noreturn stm32mp1_barebox_entry(void *boarddata); + +#endif diff --git a/arch/arm/mach-stm32mp/include/mach/stm32.h b/arch/arm/mach-stm32mp/include/mach/stm32.h index f9bdb788b9..adb898fa26 100644 --- a/arch/arm/mach-stm32mp/include/mach/stm32.h +++ b/arch/arm/mach-stm32mp/include/mach/stm32.h @@ -12,6 +12,8 @@ #define STM32_RCC_BASE 0x50000000 #define STM32_PWR_BASE 0x50001000 #define STM32_DBGMCU_BASE 0x50081000 +#define STM32_DDRCTL_BASE 0x5A003000 +#define STM32_DDRPHY_BASE 0x5A004000 #define STM32_BSEC_BASE 0x5C005000 #define STM32_TZC_BASE 0x5C006000 #define STM32_ETZPC_BASE 0x5C007000 diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index 7c4c1fd137..7547951752 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -1,13 +1,5 @@ -CFLAGS_tegra_avp_init.o := \ - -mcpu=arm7tdmi -march=armv4t \ - -fno-tree-switch-conversion -fno-jump-tables -CFLAGS_pbl-tegra_avp_init.o := \ - -mcpu=arm7tdmi -march=armv4t \ - -fno-tree-switch-conversion -fno-jump-tables -CFLAGS_tegra_maincomplex_init.o := \ - -fno-tree-switch-conversion -fno-jump-tables -CFLAGS_pbl-tegra_maincomplex_init.o := \ - -fno-tree-switch-conversion -fno-jump-tables +CFLAGS_tegra_avp_init.o := -mcpu=arm7tdmi -march=armv4t +CFLAGS_pbl-tegra_avp_init.o := -mcpu=arm7tdmi -march=armv4t lwl-y += tegra_avp_init.o lwl-y += tegra_maincomplex_init.o obj-y += tegra20.o diff --git a/arch/mips/Makefile b/arch/mips/Makefile index ee465dc8e9..1c10db599c 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -52,9 +52,7 @@ cflags-$(CONFIG_CPU_MIPS32_R1) += $(call cc-option,-march=mips32,-mips32 -U_MIPS cflags-$(CONFIG_CPU_MIPS32_R2) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) -Wa,-mips32r2 -Wa,--trap cflags-$(CONFIG_CPU_MIPS64_R1) += $(call cc-option,-march=mips64,-mips64 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) -Wa,-mips64 -Wa,--trap cflags-$(CONFIG_CPU_MIPS64_R2) += $(call cc-option,-march=mips64r2,-mips64r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS64) -Wa,-mips64r2 -Wa,--trap -cflags-$(CONFIG_CPU_LOONGSON1) += \ - $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) \ - -Wa,-mips32r2 -Wa,--trap +cflags-$(CONFIG_CPU_LOONGSON1) += $(call cc-option,-march=mips32r2,-mips32r2 -U_MIPS_ISA -D_MIPS_ISA=_MIPS_ISA_MIPS32) -Wa,-mips32r2 -Wa,--trap CPPFLAGS += -DTEXT_BASE=$(CONFIG_TEXT_BASE) diff --git a/arch/mips/mach-ath79/art.c b/arch/mips/mach-ath79/art.c index 2a2099e9f5..44118c19e9 100644 --- a/arch/mips/mach-ath79/art.c +++ b/arch/mips/mach-ath79/art.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2. +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018 Oleksij Rempel <linux@rempel-privat.de> */ diff --git a/arch/x86/mach-efi/elf_x86_64_efi.lds.S b/arch/x86/mach-efi/elf_x86_64_efi.lds.S index 40a9425034..ed79118a36 100644 --- a/arch/x86/mach-efi/elf_x86_64_efi.lds.S +++ b/arch/x86/mach-efi/elf_x86_64_efi.lds.S @@ -58,12 +58,7 @@ SECTIONS . = ALIGN(4096); .rela : { - *(.rela.data*) - *(.rela.barebox*) - *(.rela.initcall*) - *(.rela.exitcall*) - *(.rela.got) - *(.rela.stab) + *(.rela*) } . = ALIGN(4096); diff --git a/commands/Kconfig b/commands/Kconfig index a6db52ae54..7784966282 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -1867,6 +1867,21 @@ config CMD_POWEROFF help Turn the power off. +config CMD_SMC + bool + depends on ARM_SMCCC + prompt "PSCI test command" + default CONFIG_ARM_PSCI_DEBUG + help + Secure monitor code test command + + Usage: smc [-nic] + + Options: + -n Install secure monitor and switch to nonsecure mode + -i Show information about installed PSCI version + -c Start secondary CPU core + config CMD_SPI bool depends on SPI diff --git a/commands/Makefile b/commands/Makefile index 2f0980185c..01082de44c 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_CMD_MEMSET) += memset.o obj-$(CONFIG_CMD_EDIT) += edit.o obj-$(CONFIG_CMD_EXEC) += exec.o obj-$(CONFIG_CMD_SLEEP) += sleep.o +obj-$(CONFIG_CMD_SMC) += smc.o obj-$(CONFIG_CMD_MSLEEP) += msleep.o obj-$(CONFIG_CMD_RESET) += reset.o obj-$(CONFIG_CMD_POWEROFF) += poweroff.o diff --git a/commands/gpio.c b/commands/gpio.c index 951ad2c285..6d88ab6bbe 100644 --- a/commands/gpio.c +++ b/commands/gpio.c @@ -25,7 +25,9 @@ static int get_gpio_and_value(int argc, char *argv[], if (argc < count) return COMMAND_ERROR_USAGE; - *gpio = gpio_find_by_label(argv[1]); + *gpio = gpio_find_by_name(argv[1]); + if (*gpio < 0) + *gpio = gpio_find_by_label(argv[1]); if (*gpio < 0) { ret = kstrtoint(argv[1], 0, gpio); if (ret < 0) diff --git a/commands/keystore.c b/commands/keystore.c index 52c4be2639..4f6a7ef190 100644 --- a/commands/keystore.c +++ b/commands/keystore.c @@ -15,7 +15,7 @@ static int do_keystore(int argc, char *argv[]) const char *file = NULL; char *secret_str = NULL; void *secret; - int s_len; + size_t s_len; while ((opt = getopt(argc, argv, "rs:f:")) > 0) { switch (opt) { diff --git a/commands/smc.c b/commands/smc.c new file mode 100644 index 0000000000..84102f3249 --- /dev/null +++ b/commands/smc.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <command.h> +#include <getopt.h> +#include <dma.h> +#include <linux/iopoll.h> +#include <asm/barebox-arm-head.h> + +#include <asm/psci.h> +#include <asm/secure.h> +#include <linux/arm-smccc.h> + +#define STACK_SIZE 100 +#define HANDSHAKE_MAGIC 0xBA12EB0C +#define ERROR_MAGIC 0xDEADBEEF + +struct cpu_context { + unsigned long stack[STACK_SIZE]; + long handshake; +}; + +static void noinline cpu_handshake(long *handshake) +{ + struct arm_smccc_res res; + + writel(HANDSHAKE_MAGIC, handshake); + + arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_OFF, + 0, 0, 0, 0, 0, 0, 0, &res); + + writel(ERROR_MAGIC, handshake); + + while (1) + ; +} + +static void __naked second_entry(unsigned long arg0) +{ + struct cpu_context *context = (void*)arg0; + + arm_cpu_lowlevel_init(); + arm_setup_stack((unsigned long)&context->stack[STACK_SIZE]); + barrier(); + + cpu_handshake(&context->handshake); +} + +static const char *psci_xlate_str(long err) +{ + static char errno_string[sizeof "error 0x123456789ABCDEF0"]; + + switch(err) + { + case ARM_PSCI_RET_SUCCESS: + return "Success"; + case ARM_PSCI_RET_NOT_SUPPORTED: + return "Operation not supported"; + case ARM_PSCI_RET_INVAL: + return "Invalid argument"; + case ARM_PSCI_RET_DENIED: + return "Operation not permitted"; + case ARM_PSCI_RET_ALREADY_ON: + return "CPU already on"; + case ARM_PSCI_RET_ON_PENDING: + return "CPU_ON in progress"; + case ARM_PSCI_RET_INTERNAL_FAILURE: + return "Internal failure"; + case ARM_PSCI_RET_NOT_PRESENT: + return "Trusted OS not present on core"; + case ARM_PSCI_RET_DISABLED: + return "CPU is disabled"; + case ARM_PSCI_RET_INVALID_ADDRESS: + return "Bad address"; + } + + sprintf(errno_string, "error 0x%lx", err); + return errno_string; +} + +static struct cpu_context *context; + +static int do_smc(int argc, char *argv[]) +{ + long ret; + int opt; + struct arm_smccc_res res = { + .a0 = 0xdeadbee0, + .a1 = 0xdeadbee1, + .a2 = 0xdeadbee2, + .a3 = 0xdeadbee3, + }; + + if (argc < 2) + return COMMAND_ERROR_USAGE; + + while ((opt = getopt(argc, argv, "nic")) > 0) { + switch (opt) { + case 'n': + if (!IS_ENABLED(CONFIG_ARM_SECURE_MONITOR)) { + printf("secure monitor support not compiled in\n"); + return COMMAND_ERROR; + } + + armv7_secure_monitor_install(); + break; + case 'i': + arm_smccc_smc(ARM_PSCI_0_2_FN_PSCI_VERSION, + 0, 0, 0, 0, 0, 0, 0, &res); + printf("found psci version %ld.%ld\n", res.a0 >> 16, res.a0 & 0xffff); + break; + case 'c': + if (!context) + context = dma_alloc_coherent(sizeof(*context), + DMA_ADDRESS_BROKEN); + + if (!context) { + printf("Out of memory\n"); + return COMMAND_ERROR; + } + + arm_smccc_smc(ARM_PSCI_0_2_FN_CPU_ON, + 1, (unsigned long)second_entry, (unsigned long)context, + 0, 0, 0, 0, &res); + ret = (long)res.a0; + printf("CPU_ON returns with: %s\n", psci_xlate_str(ret)); + if (ret) { + unsigned long magic = readl(&context->handshake); + if (magic == ERROR_MAGIC) + printf("Turning off CPU had failed\n"); + return COMMAND_ERROR; + } + + readl_poll_timeout(&context->handshake, ret, + ret != HANDSHAKE_MAGIC, USEC_PER_SEC); + if (ret == 0) { + printf("Second CPU handshake timed out.\n"); + return COMMAND_ERROR; + } + + printf("Second CPU handshake successful.\n"); + } + } + + + return 0; +} +BAREBOX_CMD_HELP_START(smc) +BAREBOX_CMD_HELP_TEXT("Secure monitor code test command") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("Options:") +BAREBOX_CMD_HELP_OPT ("-n", "Install secure monitor and switch to nonsecure mode") +BAREBOX_CMD_HELP_OPT ("-i", "Show information about installed PSCI version") +BAREBOX_CMD_HELP_OPT ("-c", "Start secondary CPU core") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(smc) + .cmd = do_smc, + BAREBOX_CMD_DESC("secure monitor test command") + BAREBOX_CMD_HELP(cmd_smc_help) + BAREBOX_CMD_GROUP(CMD_GRP_MISC) +BAREBOX_CMD_END diff --git a/common/Kconfig b/common/Kconfig index d397d8bc4d..60237d3056 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1309,7 +1309,7 @@ config DEBUG_INITCALLS config PBL_BREAK bool "Execute software break on pbl start" - depends on ARM + depends on ARM && (!CPU_32v4T && !ARCH_TEGRA) help If this enabled, barebox will be compiled with BKPT instruction on early pbl init. This option should be used only with JTAG debugger! diff --git a/common/console_simple.c b/common/console_simple.c index 6d293b2ba1..42224842c5 100644 --- a/common/console_simple.c +++ b/common/console_simple.c @@ -64,9 +64,6 @@ void console_flush(void) } EXPORT_SYMBOL(console_flush); -void ctrlc_handled(void) -{ -} /* test if ctrl-c was pressed */ int ctrlc (void) { @@ -81,14 +78,6 @@ int ctrlc (void) } EXPORT_SYMBOL(ctrlc); -void console_ctrlc_allow(void) -{ -} - -void console_ctrlc_forbid(void) -{ -} - int console_register(struct console_device *newcdev) { if (console) diff --git a/common/efi/efi.c b/common/efi/efi.c index 73cea37036..ed81583550 100644 --- a/common/efi/efi.c +++ b/common/efi/efi.c @@ -361,7 +361,7 @@ efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table) if (EFI_ERROR(efiret)) panic("failed to allocate malloc pool: %s\n", efi_strerror(efiret)); - mem_malloc_init((void *)mem, (void *)mem + memsize); + mem_malloc_init((void *)mem, (void *)mem + memsize - 1); start_barebox(); diff --git a/common/filetype.c b/common/filetype.c index 4966c5e068..39fea45edf 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -316,19 +316,21 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize) buf8[0] == 0x8b || buf8[0] == 0x9c) && buf8[0x1] == 0 && buf8[0x2] == 0 && buf8[0x3] == 0 && buf8[0x18] == 0 && buf8[0x1b] == 0 && buf8[0x1c] == 0) { - unsigned char sum = 0; - int i; - for (i = 0; i <= 0x1e; ++i) - sum += buf8[i]; + if (buf8[0x8] == 0) { + unsigned char sum = 0; + int i; - if (sum == buf8[0x1f] && buf8[0x8] == 0) - return filetype_kwbimage_v0; + for (i = 0; i <= 0x1e; ++i) + sum += buf8[i]; - if (sum == buf8[0x1f] && - buf8[0x8] == 1 && buf8[0x1d] == 0 && - (buf8[0x1e] == 0 || buf8[0x1e] == 1)) - return filetype_kwbimage_v1; + if (sum == buf8[0x1f]) + return filetype_kwbimage_v0; + } else if (buf8[0x8] == 1) { + if (buf8[0x1d] == 0 && + (buf8[0x1e] == 0 || buf8[0x1e] == 1)) + return filetype_kwbimage_v1; + } } if (is_sparse_image(_buf)) diff --git a/common/ratp/Kconfig b/common/ratp/Kconfig index 30462c6c97..25150addfd 100644 --- a/common/ratp/Kconfig +++ b/common/ratp/Kconfig @@ -6,6 +6,7 @@ config CONSOLE_RATP select POLLER select CMDLINE_EDITING depends on CONSOLE_FULL + depends on !SHELL_NONE prompt "RATP console support" help This option adds support for remote controlling barebox via serial diff --git a/drivers/Makefile b/drivers/Makefile index 5a52225ee0..08a17ff459 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -8,8 +8,8 @@ obj-y += mtd/ obj-y += usb/ obj-$(CONFIG_DISK) += ata/ obj-$(CONFIG_SPI) += spi/ -obj-$(CONFIG_I2C) += i2c/ -obj-$(CONFIG_MCI) += mci/ +obj-y += i2c/ +obj-y += mci/ obj-$(CONFIG_VIDEO) += video/ obj-y += clk/ obj-y += clocksource/ diff --git a/drivers/block/efi-block-io.c b/drivers/block/efi-block-io.c index 39dbfb0f7a..30db486876 100644 --- a/drivers/block/efi-block-io.c +++ b/drivers/block/efi-block-io.c @@ -131,16 +131,9 @@ static void efi_bio_print_info(struct efi_bio_priv *priv) media->optimal_transfer_length_granularity); } -static int is_bio_usbdev(struct efi_device *efidev) +static bool is_bio_usbdev(struct efi_device *efidev) { - int i; - - for (i = 0; i < efidev->num_guids; i++) { - if (!efi_guidcmp(efidev->guids[i], EFI_USB_IO_PROTOCOL_GUID)) - return 1; - } - - return 0; + return efi_device_has_guid(efidev, EFI_USB_IO_PROTOCOL_GUID); } static int efi_bio_probe(struct efi_device *efidev) diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index 219982d878..1a2ff9129e 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -25,4 +25,12 @@ config MVEBU_MBUS Driver needed for the MBus configuration on Marvell EBU SoCs (Kirkwood, Dove, Orion5x, MV78XX0 and Armada 370/XP). +config ACPI + bool "Advanced Configuration and Power Interface (ACPI)" + default y + depends on EFI_BOOTUP + help + Driver needed for supporting drivers probed from ACPI tables. + The root SDT is found via UEFI. + endmenu diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile index ba5cee4063..518689a1ea 100644 --- a/drivers/bus/Makefile +++ b/drivers/bus/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_BUS_OMAP_GPMC) += omap-gpmc.o obj-$(CONFIG_IMX_WEIM) += imx-weim.o obj-$(CONFIG_MVEBU_MBUS) += mvebu-mbus.o obj-$(CONFIG_TI_SYSC) += ti-sysc.o +obj-$(CONFIG_ACPI) += acpi.o diff --git a/drivers/bus/acpi.c b/drivers/bus/acpi.c new file mode 100644 index 0000000000..2515b6633b --- /dev/null +++ b/drivers/bus/acpi.c @@ -0,0 +1,255 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Ahmad Fatoum + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <efi/efi.h> +#include <efi/efi-device.h> +#include <acpi.h> + +static struct sig_desc { + const char sig[4]; + const char *desc; +} signatures[] = { + /* ACPI 6.3 Table 5-29, Defined DESCRIPTION_HEADER Signatures */ + { "APIC", "Multiple APIC Description" }, + { "BERT", "Boot Error Record" }, + { "BGRT", "Boot Graphics Resource" }, + { "CPEP", "Corrected Platform Error Polling" }, + { "DSDT", "Differentiated System Description" }, + { "ECDT", "Embedded Controller Boot Resource" }, + { "EINJ", "Error Injection" }, + { "ERST", "Error Record Serialization" }, + { "FACP", "Fixed ACPI Description" }, + { "FACS", "Firmware ACPI Control Structure" }, + { "FPDT", "Firmware Performance Data" }, + { "GTDT", "Generic Timer Description" }, + { "HEST", "Hardware Error Source" }, + { "MSCT", "Maximum System Characteristics" }, + { "MPST", "Memory Power State" }, + { "NFIT", "NVDIMM Firmware Interface" }, + { "OEM\0", "OEM Specific Information" }, + { "PCCT", "Platform Communications Channel" }, + { "PMTT", "Platform Memory Topology" }, + { "PSDT", "Persistent System Description" }, + { "RASF", "ACPI RAS Feature" }, + { "RSDT", "Root System Description" }, + { "SBST", "Smart Battery Specification" }, + { "SDEV", "Secure Devices" }, + { "SLIT", "System Locality Distance Information" }, + { "SRAT", "System Resource Affinity" }, + { "SSDT", "Secondary System Description" }, + { "XSDT", "Extended System Description" }, + + /* ACPI 6.3 Table 5-30, Reserved DESCRIPTION_HEADER Signatures */ + { "BOOT", "Simple BOOT Flag" }, + { "CSRT", "Core System Resource" }, + { "DBG2", "Microsoft Debug Port 2" }, + { "DBGP", "Debug Port" }, + { "DMAR", "DMA Remapping" }, + { "DPPT", "DMA Protection Policy" }, + { "DRTM", "Dynamic Root of Trust for Measurement" }, + { "ETDT", "(Obsolete) Event Timer Description" }, + { "HPET", "IA-PC High Precision Event Timer" }, + { "IBFT", "iSCSI Boot Firmware" }, + { "IORT", "I/O Remapping" }, + { "IVRS", "I/O Virtualization Reporting Structure" }, + { "LPIT", "Low Power Idle" }, + { "MCFG", "PCI Express memory mapped configuration" }, + { "MCHI", "Management Controller Host Interface" }, + { "MSDM", "Microsoft Data Management" }, + { "SDEI", "Software Delegated Exceptions Interface" }, + { "SLIC", "Microsoft Software Licensing Specification" }, + { "SPCR", "Serial Port Console Redirection" }, + { "SPMI", "Server Platform Management Interface" }, + { "STAO", "_STA Override" }, + { "TCPA", "Trusted Computing Platform Alliance Capabilities" }, + { "TPM2", "Trusted Platform Module 2" }, + { "UEFI", "UEFI ACPI Data" }, + { "WAET", "Windows ACPI Emulated Devices" }, + { "WDAT", "Watch Dog Action" }, + { "WDRT", "Watchdog Resource" }, + { "WPBT", "Platform Binary" }, + { "WSMT", "Windows SMM Security Mitigation" }, + { "XENV", "Xen Project" }, + + /* Others */ + { "NHLT", "Non-HD Audio" }, + { "ASF!", "Alert Standard Format" }, + + { /* sentinel */ } +}; + +static struct acpi_sdt *acpi_get_dev_sdt(struct device_d *dev) +{ + int i; + + for (i = 0; i < dev->num_resources; i++) { + if (!strcmp(dev->resource[i].name, "SDT")) + return (struct acpi_sdt *)dev->resource[i].start; + } + + return NULL; +} + +static void acpi_devinfo(struct device_d *dev) +{ + struct acpi_sdt *sdt = acpi_get_dev_sdt(dev); + struct sig_desc *sig_desc; + + printf("Signature: %.4s", sdt->signature); + + for (sig_desc = signatures; sig_desc->desc; sig_desc++) { + size_t len = strnlen(sig_desc->sig, 4); + + if (!memcmp(sdt->signature, sig_desc->sig, len)) { + printf(" (%s Table)", sig_desc->desc); + break; + } + } + + printf("\nRevision: %u\n", sdt->revision); + printf("OemId: %.6s\n", sdt->oem_id); + printf("OemTableId: %.8s\n", sdt->oem_table_id); + printf("OemRevision: %u\n", sdt->oem_revision); + printf("CreatorId: 0x%08x\n", sdt->creator_id); + printf("CreatorRevision: %u\n", sdt->creator_revision); +} + +static int acpi_register_device(struct device_d *dev, struct acpi_sdt *sdt) +{ + int ret; + + ret = register_device(dev); + if (ret) + return ret; + + device_add_resource(dev, "SDT", (resource_size_t)sdt, sdt->len, + IORESOURCE_MEM | IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY); + + dev_dbg(dev, "registered as ACPI device\n"); + + return 0; +} + +static struct device_d *acpi_add_device(struct bus_type *bus, + acpi_sig_t signature) +{ + struct device_d *dev; + + dev = xzalloc(sizeof(*dev)); + + dev->bus = bus; + dev->parent = bus->dev; + dev->id = DEVICE_ID_DYNAMIC; + dev->info = acpi_devinfo; + + dev_set_name(dev, "acpi-%.4s", signature); + + return dev; +} + +static int acpi_register_devices(struct bus_type *bus) +{ + efi_config_table_t *table = bus->dev->priv; + struct acpi_rsdp *rsdp; + struct acpi_rsdt *root; + size_t entry_count; + const char *sig; + int i; + + rsdp = (struct acpi_rsdp *)table->table; + + if (!rsdp) + return -EFAULT; + + /* ACPI specification v6.3 + * 5.2.5.2 Finding the RSDP on UEFI Enabled Systems + */ + if (memcmp("RSD PTR ", rsdp->signature, sizeof(rsdp->signature))) { + dev_dbg(bus->dev, "unexpected signature at start of config table: '%.8s'\n", + rsdp->signature); + return -ENODEV; + } + + if (rsdp->revision < 0x02) { + sig = "RSDT"; + root = (struct acpi_rsdt *)(unsigned long)rsdp->rsdt_addr; + entry_count = (root->sdt.len - sizeof(struct acpi_rsdt)) / sizeof(u32); + } else { + sig = "XSDT"; + root = (struct acpi_rsdt *)((struct acpi2_rsdp *)rsdp)->xsdt_addr; + entry_count = (root->sdt.len - sizeof(struct acpi_rsdt)) / sizeof(u64); + } + + if (acpi_sigcmp(sig, root->sdt.signature)) { + dev_err(bus->dev, "Expected %s, but found '%.4s'.\n", + sig, root->sdt.signature); + return -EIO; + } + + dev_info(bus->dev, "Found %s (OEM: %.8s) with %lu entries\n", + sig, root->sdt.oem_id, entry_count); + + for (i = 0; i < entry_count; i++) { + struct acpi_sdt *sdt = root->entries[i]; + acpi_register_device(acpi_add_device(bus, sdt->signature), sdt); + } + + return 0; +} + +static int acpi_bus_match(struct device_d *dev, struct driver_d *drv) +{ + struct acpi_driver *acpidrv = to_acpi_driver(drv); + struct acpi_sdt *sdt = acpi_get_dev_sdt(dev); + + return acpi_sigcmp(acpidrv->signature, sdt->signature); +} + +static int acpi_bus_probe(struct device_d *dev) +{ + return dev->driver->probe(dev); +} + +static void acpi_bus_remove(struct device_d *dev) +{ + if (dev->driver->remove) + dev->driver->remove(dev); +} + +struct bus_type acpi_bus = { + .match = acpi_bus_match, + .probe = acpi_bus_probe, + .remove = acpi_bus_remove, +}; + +static int efi_acpi_probe(void) +{ + efi_config_table_t *table = NULL; + int i; + + for (i = 0; i < efi_sys_table->nr_tables; i++) { + efi_config_table_t *ect = &efi_sys_table->tables[i]; + /* take ACPI < 2 table only if no ACPI 2.0 is available */ + if (!efi_guidcmp(ect->guid, EFI_ACPI_20_TABLE_GUID)) { + acpi_bus.name = "acpi2"; + table = ect; + } else if (!table && !efi_guidcmp(ect->guid, EFI_ACPI_TABLE_GUID)) { + acpi_bus.name = "acpi"; + table = ect; + } + } + + if (!table) + return 0; + + bus_register(&acpi_bus); + acpi_bus.dev->priv = table; + + return acpi_register_devices(&acpi_bus); +} +postcore_initcall(efi_acpi_probe); diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c index b0a6bb0e8d..35483efde6 100644 --- a/drivers/clk/imx/clk-imx6ul.c +++ b/drivers/clk/imx/clk-imx6ul.c @@ -450,6 +450,9 @@ static int imx6_ccm_probe(struct device_d *dev) clk_set_parent(clks[IMX6ULL_CLK_EPDC_PRE_SEL], clks[IMX6UL_CLK_PLL3_PFD2]); + /* Disable GPMI_IO clk before reparenting to avoid glitches */ + clks[IMX6UL_CLK_GPMI_IO]->ops->disable(clks[IMX6UL_CLK_GPMI_IO]); + clk_set_parent(clks[IMX6UL_CLK_ENFC_SEL], clks[IMX6UL_CLK_PLL2_PFD2]); return 0; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 43c5bfc973..44a6cef6fb 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -73,7 +73,7 @@ config CLOCKSOURCE_ATMEL_PIT config CLOCKSOURCE_ARMV8_TIMER bool default y - depends on ARM && (CPU_64v8 || CPU_V7) + depends on ARM && CPU_V8 config CLOCKSOURCE_ARM_GLOBAL_TIMER bool diff --git a/drivers/efi/efi-device.c b/drivers/efi/efi-device.c index a1aac2dd31..ac035dcfac 100644 --- a/drivers/efi/efi-device.c +++ b/drivers/efi/efi-device.c @@ -386,16 +386,9 @@ static int efi_is_setup_mode(void) return ret != 1; } -static int is_bio_usbdev(struct efi_device *efidev) +static bool is_bio_usbdev(struct efi_device *efidev) { - int i; - - for (i = 0; i < efidev->num_guids; i++) { - if (!efi_guidcmp(efidev->guids[i], EFI_USB_IO_PROTOCOL_GUID)) - return 1; - } - - return 0; + return efi_device_has_guid(efidev, EFI_USB_IO_PROTOCOL_GUID); } static struct efi_device *bootdev; diff --git a/drivers/firmware/zynqmp-fpga.c b/drivers/firmware/zynqmp-fpga.c index 887865883a..1728e2a954 100644 --- a/drivers/firmware/zynqmp-fpga.c +++ b/drivers/firmware/zynqmp-fpga.c @@ -136,7 +136,7 @@ static int is_bin_header_valid(const u32 *bin_header, size_t size, return 0; for (i = 0; i < ARRAY_SIZE(bin_format); i++) - if (bin_header != (byte_order == XILINX_BYTE_ORDER_BIT) ? + if (bin_header[i] != (byte_order == XILINX_BYTE_ORDER_BIT) ? bin_format[i] : __swab32(bin_format[i])) return 0; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index f96009896a..9764ddf0f0 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -16,6 +16,7 @@ struct gpio_info { bool requested; bool active_low; char *label; + char *name; }; static struct gpio_info *gpio_desc; @@ -108,6 +109,23 @@ int gpio_find_by_label(const char *label) return -ENOENT; } +int gpio_find_by_name(const char *name) +{ + int i; + + for (i = 0; i < ARCH_NR_GPIOS; i++) { + struct gpio_info *info = &gpio_desc[i]; + + if (!info->chip || !info->name) + continue; + + if (!strcmp(info->name, name)) + return i; + } + + return -ENOENT; +} + void gpio_free(unsigned gpio) { struct gpio_info *gi = gpio_to_desc(gpio); @@ -410,11 +428,25 @@ static int of_hog_gpio(struct device_node *np, struct gpio_chip *chip, static int of_gpiochip_scan_hogs(struct gpio_chip *chip) { struct device_node *np; - int ret, i; + int ret, i, count; if (!IS_ENABLED(CONFIG_OFDEVICE) || !chip->dev->device_node) return 0; + count = of_property_count_strings(chip->dev->device_node, "gpio-line-names"); + + if (count > 0) { + const char **arr = xzalloc(count * sizeof(char *)); + + of_property_read_string_array(chip->dev->device_node, + "gpio-line-names", arr, count); + + for (i = 0; i < chip->ngpio && i < count; i++) + gpio_desc[chip->base + i].name = xstrdup(arr[i]); + + free(arr); + } + for_each_available_child_of_node(chip->dev->device_node, np) { if (!of_property_read_bool(np, "gpio-hog")) continue; @@ -500,7 +532,7 @@ static int do_gpiolib(int argc, char *argv[]) gi->chip->base, gi->chip->base + gi->chip->ngpio - 1, gi->chip->dev->name); - printf("%*cdir val requested label\n", 13, ' '); + printf(" %-3s %-3s %-9s %-20s %-20s\n", "dir", "val", "requested", "name", "label"); } if (gi->chip->ops->get_direction) @@ -510,11 +542,12 @@ static int do_gpiolib(int argc, char *argv[]) val = gi->chip->ops->get(gi->chip, i - gi->chip->base); - printf(" GPIO %*d: %*s %*s %*s %s\n", 4, i, - 3, (dir < 0) ? "unk" : ((dir == GPIOF_DIR_IN) ? "in" : "out"), - 3, (val < 0) ? "unk" : ((val == 0) ? "lo" : "hi"), - 12, gi->requested ? (gi->active_low ? "active low" : "true") : "false", - (gi->requested && gi->label) ? gi->label : ""); + printf(" GPIO %4d: %-3s %-3s %-9s %-20s %-20s\n", i, + (dir < 0) ? "unk" : ((dir == GPIOF_DIR_IN) ? "in" : "out"), + (val < 0) ? "unk" : ((val == 0) ? "lo" : "hi"), + gi->requested ? (gi->active_low ? "active low" : "true") : "false", + gi->name ? gi->name : "", + gi->label ? gi->label : ""); } return 0; diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index c93653414e..b887e75573 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -1,2 +1,3 @@ -obj-$(CONFIG_I2C) += i2c.o i2c-smbus.o busses/ algos/ muxes/ +obj-y += busses/ +obj-$(CONFIG_I2C) += i2c.o i2c-smbus.o algos/ muxes/ obj-$(CONFIG_I2C_MUX) += i2c-mux.o diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 5ab43fe935..7ccdb0b222 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -94,8 +94,8 @@ static int of_i2c_gpio_probe(struct device_node *np, if (!IS_ENABLED(CONFIG_OFDEVICE)) return -ENODEV; - pdata->sda_pin = of_get_named_gpio_flags(np, "sda-gpios", 0, NULL); - pdata->scl_pin = of_get_named_gpio_flags(np, "scl-gpios", 0, NULL); + pdata->sda_pin = of_get_named_gpio(np, "sda-gpios", 0); + pdata->scl_pin = of_get_named_gpio(np, "scl-gpios", 0); if ((!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) && (of_gpio_count(np) >= 2)) { diff --git a/drivers/i2c/busses/i2c-stm32.c b/drivers/i2c/busses/i2c-stm32.c index 6af55fb3ff..9f34760e3f 100644 --- a/drivers/i2c/busses/i2c-stm32.c +++ b/drivers/i2c/busses/i2c-stm32.c @@ -785,7 +785,6 @@ static int __init stm32_i2c_probe(struct device_d *dev) struct resource *iores; struct stm32_i2c *stm32_i2c; struct i2c_platform_data *pdata; - struct reset_control *rst; const struct stm32_i2c_setup *setup; struct i2c_timings *timings; int ret; @@ -799,13 +798,9 @@ static int __init stm32_i2c_probe(struct device_d *dev) return PTR_ERR(stm32_i2c->clk); clk_enable(stm32_i2c->clk); - rst = reset_control_get(dev, NULL); - if (IS_ERR(rst)) - return PTR_ERR(rst); - - reset_control_assert(rst); - udelay(2); - reset_control_deassert(rst); + ret = device_reset_us(dev, 2); + if (ret) + return ret; ret = dev_get_drvdata(dev, (const void **)&setup); if (ret) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index be061683fb..e40032d91b 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -66,6 +66,7 @@ config KEYBOARD_USB config INPUT_SPECIALKEYS bool "Special keys handler" + select POLLER select INPUT help Say Y here to handle key events like KEY_RESTART and KEY_POWER. diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig index 4a71a46097..80b3a26002 100644 --- a/drivers/mci/Kconfig +++ b/drivers/mci/Kconfig @@ -1,3 +1,6 @@ +config MCI_SDHCI + bool + menuconfig MCI bool "MCI drivers" select DISK @@ -69,10 +72,12 @@ config MCI_BCM283X config MCI_BCM283X_SDHOST bool "BCM283X sdhost" depends on ARCH_BCM283X + select MCI_SDHCI config MCI_DOVE bool "Marvell Dove SDHCI" depends on ARCH_DOVE + select MCI_SDHCI help Enable this entry to add support to read and write SD cards on a Marvell Dove SoC based system. @@ -87,6 +92,7 @@ config MCI_IMX config MCI_IMX_ESDHC bool "i.MX esdhc" depends on ARCH_IMX || ARCH_LAYERSCAPE + select MCI_SDHCI help Enable this entry to add support to read and write SD cards on a Freescale i.MX25/35/51 based system. @@ -97,9 +103,6 @@ config MCI_IMX_ESDHC_PIO help mostly useful for debugging. Normally you should use DMA. -config MCI_IMX_ESDHC_PBL - bool - config MCI_OMAP_HSMMC bool "OMAP HSMMC" depends on ARCH_OMAP4 || ARCH_OMAP3 || ARCH_AM33XX @@ -131,10 +134,17 @@ config MCI_MMCI config MCI_TEGRA bool "Tegra SD/MMC" depends on ARCH_TEGRA + select MCI_SDHCI help Enable this to support SD and MMC card read/write on a Tegra based systems. +config MCI_ARASAN + bool "Arasan SDHCI Controller" + help + Enable this to support SD and MMC card read/write on systems with + the Arasan SD3.0 / SDIO3.0 / eMMC4.51 host controller. + config MCI_SPI bool "MMC/SD over SPI" select CRC7 @@ -163,3 +173,7 @@ config MCI_STM32_SDMMC2 say Y or M here. endif + +config MCI_IMX_ESDHC_PBL + bool + select MCI_SDHCI diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile index 04c1287fee..54eb65978e 100644 --- a/drivers/mci/Makefile +++ b/drivers/mci/Makefile @@ -1,11 +1,12 @@ obj-$(CONFIG_MCI) += mci-core.o +obj-$(CONFIG_MCI_ARASAN) += arasan-sdhci.o obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o obj-$(CONFIG_MCI_BCM283X) += mci-bcm2835.o obj-$(CONFIG_MCI_BCM283X_SDHOST) += bcm2835-sdhost.o obj-$(CONFIG_MCI_DOVE) += dove-sdhci.o obj-$(CONFIG_MCI_IMX) += imx.o -obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o -pbl-$(CONFIG_MCI_IMX_ESDHC_PBL) += imx-esdhc-pbl.o +obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o imx-esdhc-common.o +pbl-$(CONFIG_MCI_IMX_ESDHC_PBL) += imx-esdhc-pbl.o imx-esdhc-common.o obj-$(CONFIG_MCI_MXS) += mxs.o obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o obj-$(CONFIG_MCI_PXA) += pxamci.o @@ -15,3 +16,4 @@ obj-$(CONFIG_MCI_SPI) += mci_spi.o obj-$(CONFIG_MCI_DW) += dw_mmc.o obj-$(CONFIG_MCI_MMCI) += mmci.o obj-$(CONFIG_MCI_STM32_SDMMC2) += stm32_sdmmc2.o +obj-pbl-$(CONFIG_MCI_SDHCI) += sdhci.o diff --git a/drivers/mci/arasan-sdhci.c b/drivers/mci/arasan-sdhci.c new file mode 100644 index 0000000000..b43a4f8ddf --- /dev/null +++ b/drivers/mci/arasan-sdhci.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <clock.h> +#include <common.h> +#include <driver.h> +#include <init.h> +#include <linux/clk.h> +#include <mci.h> + +#include "sdhci.h" + +#define SDHCI_ARASAN_HCAP_CLK_FREQ_MASK 0xFF00 +#define SDHCI_ARASAN_HCAP_CLK_FREQ_SHIFT 8 +#define SDHCI_INT_ADMAE BIT(29) +#define SDHCI_ARASAN_INT_DATA_MASK SDHCI_INT_XFER_COMPLETE | \ + SDHCI_INT_DMA | \ + SDHCI_INT_SPACE_AVAIL | \ + SDHCI_INT_DATA_AVAIL | \ + SDHCI_INT_DATA_TIMEOUT | \ + SDHCI_INT_DATA_CRC | \ + SDHCI_INT_DATA_END_BIT | \ + SDHCI_INT_ADMAE + +#define SDHCI_ARASAN_INT_CMD_MASK SDHCI_INT_CMD_COMPLETE | \ + SDHCI_INT_TIMEOUT | \ + SDHCI_INT_CRC | \ + SDHCI_INT_END_BIT | \ + SDHCI_INT_INDEX + +#define SDHCI_ARASAN_BUS_WIDTH 4 +#define TIMEOUT_VAL 0xE + +struct arasan_sdhci_host { + struct mci_host mci; + struct sdhci sdhci; + void __iomem *ioaddr; + unsigned int quirks; /* Arasan deviations from spec */ +/* Controller does not have CD wired and will not function normally without */ +#define SDHCI_ARASAN_QUIRK_FORCE_CDTEST BIT(0) +#define SDHCI_ARASAN_QUIRK_NO_1_8_V BIT(1) +}; + + +static inline +struct arasan_sdhci_host *to_arasan_sdhci_host(struct mci_host *mci) +{ + return container_of(mci, struct arasan_sdhci_host, mci); +} + +static inline +struct arasan_sdhci_host *sdhci_to_arasan(struct sdhci *sdhci) +{ + return container_of(sdhci, struct arasan_sdhci_host, sdhci); +} + +static void arasan_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) +{ + struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); + + writel(val, p->ioaddr + reg); +} + +static void arasan_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) +{ + struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); + + writew(val, p->ioaddr + reg); +} + +static void arasan_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) +{ + struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); + + writeb(val, p->ioaddr + reg); +} + +static u32 arasan_sdhci_readl(struct sdhci *sdhci, int reg) +{ + struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); + + return readl(p->ioaddr + reg); +} + +static u16 arasan_sdhci_readw(struct sdhci *sdhci, int reg) +{ + struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); + + return readw(p->ioaddr + reg); +} + +static u8 arasan_sdhci_readb(struct sdhci *sdhci, int reg) +{ + struct arasan_sdhci_host *p = sdhci_to_arasan(sdhci); + + return readb(p->ioaddr + reg); +} + +static int arasan_sdhci_card_present(struct mci_host *mci) +{ + struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + + return !!(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_CARD_DETECT); +} + +static int arasan_sdhci_card_write_protected(struct mci_host *mci) +{ + struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + + return !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); +} + +static int arasan_sdhci_reset(struct arasan_sdhci_host *host, u8 mask) +{ + sdhci_write8(&host->sdhci, SDHCI_SOFTWARE_RESET, mask); + + /* wait for reset completion */ + if (wait_on_timeout(100 * MSECOND, + !(sdhci_read8(&host->sdhci, SDHCI_SOFTWARE_RESET) & mask))){ + dev_err(host->mci.hw_dev, "SDHCI reset timeout\n"); + return -ETIMEDOUT; + } + + if (host->quirks & SDHCI_ARASAN_QUIRK_FORCE_CDTEST) { + u8 ctrl; + + ctrl = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL); + ctrl |= SDHCI_CARD_DETECT_TEST_LEVEL | SDHCI_CARD_DETECT_SIGNAL_SELECTION; + sdhci_write8(&host->sdhci, ctrl, SDHCI_HOST_CONTROL); + } + + return 0; +} + +static int arasan_sdhci_init(struct mci_host *mci, struct device_d *dev) +{ + struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + int ret; + + ret = arasan_sdhci_reset(host, SDHCI_RESET_ALL); + if (ret) + return ret; + + sdhci_write8(&host->sdhci, SDHCI_POWER_CONTROL, + SDHCI_BUS_VOLTAGE_330 | SDHCI_BUS_POWER_EN); + udelay(400); + + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, + SDHCI_ARASAN_INT_DATA_MASK | + SDHCI_ARASAN_INT_CMD_MASK); + sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, 0x00); + + return 0; +} + +#define SDHCI_MAX_DIV_SPEC_300 2046 + +static u16 arasan_sdhci_get_clock_divider(struct arasan_sdhci_host *host, + unsigned int reqclk) +{ + u16 div; + + for (div = 1; div < SDHCI_MAX_DIV_SPEC_300; div += 2) + if ((host->mci.f_max / div) <= reqclk) + break; + div /= 2; + + return div; +} + +#define SDHCI_FREQ_SEL_10_BIT(x) (((x) & 0x300) >> 2) + +static void arasan_sdhci_set_ios(struct mci_host *mci, struct mci_ios *ios) +{ + struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + u16 val; + + /* stop clock */ + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); + + if (ios->clock) { + u64 start; + + /* set & start clock */ + val = arasan_sdhci_get_clock_divider(host, ios->clock); + /* Bit 6 & 7 are upperbits of 10bit divider */ + val = SDHCI_FREQ_SEL(val) | SDHCI_FREQ_SEL_10_BIT(val); + val |= SDHCI_INTCLOCK_EN; + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); + + start = get_time_ns(); + while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & + SDHCI_INTCLOCK_STABLE)) { + if (is_timeout(start, 20 * MSECOND)) { + dev_err(host->mci.hw_dev, + "SDHCI clock stable timeout\n"); + return; + } + } + /* enable bus clock */ + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, + val | SDHCI_SDCLOCK_EN); + } + + val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & + ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); + + switch (ios->bus_width) { + case MMC_BUS_WIDTH_8: + val |= SDHCI_DATA_WIDTH_8BIT; + break; + case MMC_BUS_WIDTH_4: + val |= SDHCI_DATA_WIDTH_4BIT; + break; + } + + if (ios->clock > 26000000) + val |= SDHCI_HIGHSPEED_EN; + else + val &= ~SDHCI_HIGHSPEED_EN; + + sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); +} + +static int arasan_sdhci_wait_for_done(struct arasan_sdhci_host *host, u32 mask) +{ + u64 start = get_time_ns(); + u16 stat; + + do { + stat = sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS); + if (stat & SDHCI_INT_ERROR) { + dev_err(host->mci.hw_dev, "SDHCI_INT_ERROR: 0x%08x\n", + sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); + return -EPERM; + } + + if (is_timeout(start, 1000 * MSECOND)) { + dev_err(host->mci.hw_dev, + "SDHCI timeout while waiting for done\n"); + return -ETIMEDOUT; + } + } while ((stat & mask) != mask); + + return 0; +} + +static void print_error(struct arasan_sdhci_host *host, int cmdidx) +{ + dev_err(host->mci.hw_dev, + "error while transfering data for command %d\n", cmdidx); + dev_err(host->mci.hw_dev, "state = 0x%08x , interrupt = 0x%08x\n", + sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE), + sdhci_read32(&host->sdhci, SDHCI_INT_NORMAL_STATUS)); +} + +static int arasan_sdhci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, + struct mci_data *data) +{ + struct arasan_sdhci_host *host = to_arasan_sdhci_host(mci); + u32 mask, command, xfer; + int ret; + + /* Wait for idle before next command */ + mask = SDHCI_CMD_INHIBIT_CMD; + if (cmd->cmdidx != MMC_CMD_STOP_TRANSMISSION) + mask |= SDHCI_CMD_INHIBIT_DATA; + + ret = wait_on_timeout(10 * MSECOND, + !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & mask)); + + if (ret) { + dev_err(host->mci.hw_dev, + "SDHCI timeout while waiting for idle\n"); + return ret; + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + + mask = SDHCI_INT_CMD_COMPLETE; + if (data) + mask |= SDHCI_INT_XFER_COMPLETE; + + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, false, &command, &xfer); + + sdhci_write8(&host->sdhci, SDHCI_TIMEOUT_CONTROL, TIMEOUT_VAL); + sdhci_write16(&host->sdhci, SDHCI_TRANSFER_MODE, xfer); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_SIZE, SDHCI_DMA_BOUNDARY_512K | + SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_COUNT, data->blocks); + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); + sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); + + ret = arasan_sdhci_wait_for_done(host, mask); + if (ret == -EPERM) + goto error; + else if (ret) + return ret; + + sdhci_read_response(&host->sdhci, cmd); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, mask); + + if (data) + ret = sdhci_transfer_data(&host->sdhci, data); + +error: + if (ret) { + print_error(host, cmd->cmdidx); + arasan_sdhci_reset(host, BIT(1)); // SDHCI_RESET_CMD + arasan_sdhci_reset(host, BIT(2)); // SDHCI_RESET_DATA + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + return ret; +} + + +static void arasan_sdhci_set_mci_caps(struct arasan_sdhci_host *host) +{ + u16 caps = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); + + if ((caps & SDHCI_HOSTCAP_VOLTAGE_180) && + !(host->quirks & SDHCI_ARASAN_QUIRK_NO_1_8_V)) + host->mci.voltages |= MMC_VDD_165_195; + if (caps & SDHCI_HOSTCAP_VOLTAGE_300) + host->mci.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; + if (caps & SDHCI_HOSTCAP_VOLTAGE_330) + host->mci.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + + if (caps & SDHCI_HOSTCAP_HIGHSPEED) + host->mci.host_caps |= (MMC_CAP_MMC_HIGHSPEED_52MHZ | + MMC_CAP_MMC_HIGHSPEED | + MMC_CAP_SD_HIGHSPEED); + + /* parse board supported bus width capabilities */ + mci_of_parse(&host->mci); + + /* limit bus widths to controller capabilities */ + if (!(caps & SDHCI_HOSTCAP_8BIT)) + host->mci.host_caps &= ~MMC_CAP_8_BIT_DATA; +} + +static int arasan_sdhci_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + struct arasan_sdhci_host *arasan_sdhci; + struct clk *clk_xin, *clk_ahb; + struct resource *iores; + struct mci_host *mci; + int ret; + + arasan_sdhci = xzalloc(sizeof(*arasan_sdhci)); + + mci = &arasan_sdhci->mci; + + iores = dev_request_mem_resource(dev, 0); + if (IS_ERR(iores)) + return PTR_ERR(iores); + arasan_sdhci->ioaddr = IOMEM(iores->start); + + clk_ahb = clk_get(dev, "clk_ahb"); + if (IS_ERR(clk_ahb)) { + dev_err(dev, "clk_ahb clock not found.\n"); + return PTR_ERR(clk_ahb); + } + + clk_xin = clk_get(dev, "clk_xin"); + if (IS_ERR(clk_xin)) { + dev_err(dev, "clk_xin clock not found.\n"); + return PTR_ERR(clk_xin); + } + ret = clk_enable(clk_ahb); + if (ret) { + dev_err(dev, "Failed to enable AHB clock: %s\n", + strerror(ret)); + return ret; + } + + ret = clk_enable(clk_xin); + if (ret) { + dev_err(dev, "Failed to enable SD clock: %s\n", strerror(ret)); + return ret; + } + + if (of_property_read_bool(np, "xlnx,fails-without-test-cd")) + arasan_sdhci->quirks |= SDHCI_ARASAN_QUIRK_FORCE_CDTEST; + + if (of_property_read_bool(np, "no-1-8-v")) + arasan_sdhci->quirks |= SDHCI_ARASAN_QUIRK_NO_1_8_V; + + arasan_sdhci->sdhci.read32 = arasan_sdhci_readl; + arasan_sdhci->sdhci.read16 = arasan_sdhci_readw; + arasan_sdhci->sdhci.read8 = arasan_sdhci_readb; + arasan_sdhci->sdhci.write32 = arasan_sdhci_writel; + arasan_sdhci->sdhci.write16 = arasan_sdhci_writew; + arasan_sdhci->sdhci.write8 = arasan_sdhci_writeb; + mci->send_cmd = arasan_sdhci_send_cmd; + mci->set_ios = arasan_sdhci_set_ios; + mci->init = arasan_sdhci_init; + mci->card_present = arasan_sdhci_card_present; + mci->card_write_protected = arasan_sdhci_card_write_protected; + mci->hw_dev = dev; + + mci->f_max = clk_get_rate(clk_xin); + mci->f_min = 50000000 / 256; + + arasan_sdhci_set_mci_caps(arasan_sdhci); + + dev->priv = arasan_sdhci; + + return mci_register(&arasan_sdhci->mci); +} + +static __maybe_unused struct of_device_id arasan_sdhci_compatible[] = { + { .compatible = "arasan,sdhci-8.9a" }, + { /* sentinel */ } +}; + +static struct driver_d arasan_sdhci_driver = { + .name = "arasan-sdhci", + .probe = arasan_sdhci_probe, + .of_compatible = DRV_OF_COMPAT(arasan_sdhci_compatible), +}; +device_platform_driver(arasan_sdhci_driver); diff --git a/drivers/mci/dove-sdhci.c b/drivers/mci/dove-sdhci.c index caee4107eb..bccda53994 100644 --- a/drivers/mci/dove-sdhci.c +++ b/drivers/mci/dove-sdhci.c @@ -33,38 +33,51 @@ struct dove_sdhci { struct mci_host mci; void __iomem *base; + struct sdhci sdhci; }; #define priv_from_mci_host(h) \ container_of(h, struct dove_sdhci, mci); -static inline void dove_sdhci_writel(struct dove_sdhci *p, int reg, u32 val) +static void dove_sdhci_writel(struct sdhci *sdhci, int reg, u32 val) { + struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); + writel(val, p->base + reg); } -static inline void dove_sdhci_writew(struct dove_sdhci *p, int reg, u16 val) +static void dove_sdhci_writew(struct sdhci *sdhci, int reg, u16 val) { + struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); + writew(val, p->base + reg); } -static inline void dove_sdhci_writeb(struct dove_sdhci *p, int reg, u8 val) +static void dove_sdhci_writeb(struct sdhci *sdhci, int reg, u8 val) { + struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); + writeb(val, p->base + reg); } -static inline u32 dove_sdhci_readl(struct dove_sdhci *p, int reg) +static u32 dove_sdhci_readl(struct sdhci *sdhci, int reg) { + struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); + return readl(p->base + reg); } -static inline u16 dove_sdhci_readw(struct dove_sdhci *p, int reg) +static u16 dove_sdhci_readw(struct sdhci *sdhci, int reg) { + struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); + return readw(p->base + reg); } -static inline u8 dove_sdhci_readb(struct dove_sdhci *p, int reg) +static u8 dove_sdhci_readb(struct sdhci *sdhci, int reg) { + struct dove_sdhci *p = container_of(sdhci, struct dove_sdhci, sdhci); + return readb(p->base + reg); } @@ -75,7 +88,7 @@ static int dove_sdhci_wait_for_done(struct dove_sdhci *host, u16 mask) start = get_time_ns(); while (1) { - status = dove_sdhci_readw(host, SDHCI_INT_NORMAL_STATUS); + status = sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS); if (status & SDHCI_INT_ERROR) return -EPERM; /* this special quirk is necessary, as the dma @@ -83,8 +96,8 @@ static int dove_sdhci_wait_for_done(struct dove_sdhci *host, u16 mask) * restart after acknowledging it this way. */ if (status & SDHCI_INT_DMA) { - u32 addr = dove_sdhci_readl(host, SDHCI_DMA_ADDRESS); - dove_sdhci_writel(host, SDHCI_DMA_ADDRESS, addr); + u32 addr = sdhci_read32(&host->sdhci, SDHCI_DMA_ADDRESS); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, addr); } if (status & mask) break; @@ -100,12 +113,13 @@ static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) { u16 val; + u32 command, xfer; u64 start; int ret; - unsigned int num_bytes = data->blocks * data->blocksize; + unsigned int num_bytes = 0; struct dove_sdhci *host = priv_from_mci_host(mci); - dove_sdhci_writel(host, SDHCI_INT_STATUS, ~0); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); /* Do not wait for CMD_INHIBIT_DAT on stop commands */ if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) @@ -116,7 +130,7 @@ static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, /* Wait for bus idle */ start = get_time_ns(); while (1) { - if (!(dove_sdhci_readw(host, SDHCI_PRESENT_STATE) & val)) + if (!(sdhci_read16(&host->sdhci, SDHCI_PRESENT_STATE) & val)) break; if (is_timeout(start, 10 * MSECOND)) { dev_err(host->mci.hw_dev, "SDHCI timeout while waiting for idle\n"); @@ -126,14 +140,15 @@ static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, /* setup transfer data */ if (data) { + num_bytes = data->blocks * data->blocksize; if (data->flags & MMC_DATA_READ) - dove_sdhci_writel(host, SDHCI_DMA_ADDRESS, (u32)data->dest); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, (u32)data->dest); else - dove_sdhci_writel(host, SDHCI_DMA_ADDRESS, (u32)data->src); - dove_sdhci_writew(host, SDHCI_BLOCK_SIZE, SDHCI_DMA_BOUNDARY_512K | + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, (u32)data->src); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_SIZE, SDHCI_DMA_BOUNDARY_512K | SDHCI_TRANSFER_BLOCK_SIZE(data->blocksize)); - dove_sdhci_writew(host, SDHCI_BLOCK_COUNT, data->blocks); - dove_sdhci_writeb(host, SDHCI_TIMEOUT_CONTROL, 0xe); + sdhci_write16(&host->sdhci, SDHCI_BLOCK_COUNT, data->blocks); + sdhci_write8(&host->sdhci, SDHCI_TIMEOUT_CONTROL, 0xe); if (data->flags & MMC_DATA_WRITE) @@ -145,84 +160,48 @@ static int dove_sdhci_mci_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, } /* setup transfer mode */ - val = 0; - if (data) { - val |= SDHCI_DMA_EN | SDHCI_BLOCK_COUNT_EN; - if (data->blocks > 1) - val |= SDHCI_MULTIPLE_BLOCKS; - if (data->flags & MMC_DATA_READ) - val |= SDHCI_DATA_TO_HOST; - } - dove_sdhci_writew(host, SDHCI_TRANSFER_MODE, val); + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, true, &command, &xfer); - dove_sdhci_writel(host, SDHCI_ARGUMENT, cmd->cmdarg); - - if (!(cmd->resp_type & MMC_RSP_PRESENT)) - val = SDHCI_RESP_NONE; - else if (cmd->resp_type & MMC_RSP_136) - val = SDHCI_RESP_TYPE_136; - else if (cmd->resp_type & MMC_RSP_BUSY) - val = SDHCI_RESP_TYPE_48_BUSY; - else - val = SDHCI_RESP_TYPE_48; - - if (cmd->resp_type & MMC_RSP_CRC) - val |= SDHCI_CMD_CRC_CHECK_EN; - if (cmd->resp_type & MMC_RSP_OPCODE) - val |= SDHCI_CMD_INDEX_CHECK_EN; - if (data) - val |= SDHCI_DATA_PRESENT; - val |= SDHCI_CMD_INDEX(cmd->cmdidx); - - dove_sdhci_writew(host, SDHCI_COMMAND, val); + sdhci_write16(&host->sdhci, SDHCI_TRANSFER_MODE, xfer); + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); + sdhci_write16(&host->sdhci, SDHCI_COMMAND, command); ret = dove_sdhci_wait_for_done(host, SDHCI_INT_CMD_COMPLETE); if (ret) { dev_err(host->mci.hw_dev, "error on command %d\n", cmd->cmdidx); dev_err(host->mci.hw_dev, "state = %04x %04x, interrupt = %04x %04x\n", - dove_sdhci_readw(host, SDHCI_PRESENT_STATE), - dove_sdhci_readw(host, SDHCI_PRESENT_STATE1), - dove_sdhci_readw(host, SDHCI_INT_NORMAL_STATUS), - dove_sdhci_readw(host, SDHCI_INT_ERROR_STATUS)); + sdhci_read16(&host->sdhci, SDHCI_PRESENT_STATE), + sdhci_read16(&host->sdhci, SDHCI_PRESENT_STATE1), + sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS), + sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); goto cmd_error; } - /* CRC is stripped so we need to do some shifting. */ - if (cmd->resp_type & MMC_RSP_136) { - int i; - for (i = 0; i < 4; i++) { - cmd->response[i] = dove_sdhci_readl(host, - SDHCI_RESPONSE_0 + 4*(3-i)) << 8; - if (i != 3) - cmd->response[i] |= dove_sdhci_readb(host, - SDHCI_RESPONSE_0 + 4*(3-i) - 1); - } - } else - cmd->response[0] = dove_sdhci_readl(host, SDHCI_RESPONSE_0); + sdhci_read_response(&host->sdhci, cmd); - if (data->flags & MMC_DATA_WRITE) - dma_sync_single_for_cpu((unsigned long)data->src, - num_bytes, DMA_TO_DEVICE); - else - dma_sync_single_for_cpu((unsigned long)data->dest, + if (data) { + if (data->flags & MMC_DATA_WRITE) + dma_sync_single_for_cpu((unsigned long)data->src, + num_bytes, DMA_TO_DEVICE); + else + dma_sync_single_for_cpu((unsigned long)data->dest, num_bytes, DMA_FROM_DEVICE); - if (data) { ret = dove_sdhci_wait_for_done(host, SDHCI_INT_XFER_COMPLETE); if (ret) { dev_err(host->mci.hw_dev, "error while transfering data for command %d\n", cmd->cmdidx); dev_err(host->mci.hw_dev, "state = %04x %04x, interrupt = %04x %04x\n", - dove_sdhci_readw(host, SDHCI_PRESENT_STATE), - dove_sdhci_readw(host, SDHCI_PRESENT_STATE1), - dove_sdhci_readw(host, SDHCI_INT_NORMAL_STATUS), - dove_sdhci_readw(host, SDHCI_INT_ERROR_STATUS)); + sdhci_read16(&host->sdhci, SDHCI_PRESENT_STATE), + sdhci_read16(&host->sdhci, SDHCI_PRESENT_STATE1), + sdhci_read16(&host->sdhci, SDHCI_INT_NORMAL_STATUS), + sdhci_read16(&host->sdhci, SDHCI_INT_ERROR_STATUS)); goto cmd_error; } } cmd_error: - dove_sdhci_writel(host, SDHCI_INT_STATUS, ~0); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); return ret; } @@ -252,11 +231,11 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) /* enable bus power */ val = SDHCI_BUS_VOLTAGE_330; - dove_sdhci_writeb(host, SDHCI_POWER_CONTROL, val | SDHCI_BUS_POWER_EN); + sdhci_write8(&host->sdhci, SDHCI_POWER_CONTROL, val | SDHCI_BUS_POWER_EN); udelay(400); /* set bus width */ - val = dove_sdhci_readb(host, SDHCI_HOST_CONTROL) & + val = sdhci_read8(&host->sdhci, SDHCI_HOST_CONTROL) & ~(SDHCI_DATA_WIDTH_4BIT | SDHCI_DATA_WIDTH_8BIT); switch (ios->bus_width) { case MMC_BUS_WIDTH_8: @@ -272,17 +251,17 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) else val &= ~SDHCI_HIGHSPEED_EN; - dove_sdhci_writeb(host, SDHCI_HOST_CONTROL, val); + sdhci_write8(&host->sdhci, SDHCI_HOST_CONTROL, val); /* set bus clock */ - dove_sdhci_writew(host, SDHCI_CLOCK_CONTROL, 0); + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, 0); val = dove_sdhci_get_clock_divider(host, ios->clock); val = SDHCI_INTCLOCK_EN | SDHCI_FREQ_SEL(val); - dove_sdhci_writew(host, SDHCI_CLOCK_CONTROL, val); + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val); /* wait for internal clock stable */ start = get_time_ns(); - while (!(dove_sdhci_readw(host, SDHCI_CLOCK_CONTROL) & + while (!(sdhci_read16(&host->sdhci, SDHCI_CLOCK_CONTROL) & SDHCI_INTCLOCK_STABLE)) { if (is_timeout(start, 20 * MSECOND)) { dev_err(host->mci.hw_dev, "SDHCI clock stable timeout\n"); @@ -291,7 +270,7 @@ static void dove_sdhci_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) } /* enable bus clock */ - dove_sdhci_writew(host, SDHCI_CLOCK_CONTROL, val | SDHCI_SDCLOCK_EN); + sdhci_write16(&host->sdhci, SDHCI_CLOCK_CONTROL, val | SDHCI_SDCLOCK_EN); } static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) @@ -300,12 +279,12 @@ static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) struct dove_sdhci *host = priv_from_mci_host(mci); /* reset sdhci controller */ - dove_sdhci_writeb(host, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL); + sdhci_write8(&host->sdhci, SDHCI_SOFTWARE_RESET, SDHCI_RESET_ALL); /* wait for reset completion */ start = get_time_ns(); while (1) { - if ((dove_sdhci_readb(host, SDHCI_SOFTWARE_RESET) & + if ((sdhci_read8(&host->sdhci, SDHCI_SOFTWARE_RESET) & SDHCI_RESET_ALL) == 0) break; if (is_timeout(start, 100 * MSECOND)) { @@ -314,9 +293,9 @@ static int dove_sdhci_mci_init(struct mci_host *mci, struct device_d *dev) } } - dove_sdhci_writel(host, SDHCI_INT_STATUS, ~0); - dove_sdhci_writel(host, SDHCI_INT_ENABLE, ~0); - dove_sdhci_writel(host, SDHCI_SIGNAL_ENABLE, ~0); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, ~0); + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, ~0); + sdhci_write32(&host->sdhci, SDHCI_SIGNAL_ENABLE, ~0); return 0; } @@ -325,8 +304,8 @@ static void dove_sdhci_set_mci_caps(struct dove_sdhci *host) { u16 caps[2]; - caps[0] = dove_sdhci_readw(host, SDHCI_CAPABILITIES); - caps[1] = dove_sdhci_readw(host, SDHCI_CAPABILITIES_1); + caps[0] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES); + caps[1] = sdhci_read16(&host->sdhci, SDHCI_CAPABILITIES_1); if (caps[1] & SDHCI_HOSTCAP_VOLTAGE_180) host->mci.voltages |= MMC_VDD_165_195; @@ -368,6 +347,12 @@ static int dove_sdhci_probe(struct device_d *dev) host->mci.init = dove_sdhci_mci_init; host->mci.f_max = 50000000; host->mci.f_min = host->mci.f_max / 256; + host->sdhci.read32 = dove_sdhci_readl; + host->sdhci.read16 = dove_sdhci_readw; + host->sdhci.read8 = dove_sdhci_readb; + host->sdhci.write32 = dove_sdhci_writel; + host->sdhci.write16 = dove_sdhci_writew; + host->sdhci.write8 = dove_sdhci_writeb; dev->priv = host; dev->detect = dove_sdhci_detect; diff --git a/drivers/mci/imx-esdhc-common.c b/drivers/mci/imx-esdhc-common.c new file mode 100644 index 0000000000..d0bef9470c --- /dev/null +++ b/drivers/mci/imx-esdhc-common.c @@ -0,0 +1,275 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <io.h> +#include <mci.h> +#include <pbl.h> + +#include "sdhci.h" +#include "imx-esdhc.h" + +#define PRSSTAT_DAT0 0x01000000 + +struct fsl_esdhc_dma_transfer { + dma_addr_t dma; + unsigned int size; + enum dma_data_direction dir; +}; + +static u32 esdhc_op_read32_le(struct sdhci *sdhci, int reg) +{ + struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); + + return readl(host->regs + reg); +} + +static u32 esdhc_op_read32_be(struct sdhci *sdhci, int reg) +{ + struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); + + return in_be32(host->regs + reg); +} + +static void esdhc_op_write32_le(struct sdhci *sdhci, int reg, u32 val) +{ + struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); + + writel(val, host->regs + reg); +} + +static void esdhc_op_write32_be(struct sdhci *sdhci, int reg, u32 val) +{ + struct fsl_esdhc_host *host = sdhci_to_esdhc(sdhci); + + out_be32(host->regs + reg, val); +} + +void esdhc_populate_sdhci(struct fsl_esdhc_host *host) +{ + if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) { + host->sdhci.read32 = esdhc_op_read32_be; + host->sdhci.write32 = esdhc_op_write32_be; + } else { + host->sdhci.read32 = esdhc_op_read32_le; + host->sdhci.write32 = esdhc_op_write32_le; + } +} + +static bool esdhc_use_pio_mode(void) +{ + return IN_PBL || IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO); +} +static int esdhc_setup_data(struct fsl_esdhc_host *host, struct mci_data *data, + struct fsl_esdhc_dma_transfer *tr) +{ + u32 wml_value; + void *ptr; + + if (!esdhc_use_pio_mode()) { + wml_value = data->blocksize/4; + + if (data->flags & MMC_DATA_READ) { + if (wml_value > 0x10) + wml_value = 0x10; + + esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value); + } else { + if (wml_value > 0x80) + wml_value = 0x80; + + esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_WR_WML_MASK, + wml_value << 16); + } + + tr->size = data->blocks * data->blocksize; + + if (data->flags & MMC_DATA_WRITE) { + ptr = (void *)data->src; + tr->dir = DMA_TO_DEVICE; + } else { + ptr = data->dest; + tr->dir = DMA_FROM_DEVICE; + } + + tr->dma = dma_map_single(host->dev, ptr, tr->size, tr->dir); + if (dma_mapping_error(host->dev, tr->dma)) + return -EFAULT; + + + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, tr->dma); + } + + sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize); + + return 0; +} + +static int esdhc_do_data(struct fsl_esdhc_host *host, struct mci_data *data, + struct fsl_esdhc_dma_transfer *tr) +{ + u32 irqstat; + + if (esdhc_use_pio_mode()) + return sdhci_transfer_data(&host->sdhci, data); + + do { + irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS); + + if (irqstat & DATA_ERR) + return -EIO; + + if (irqstat & SDHCI_INT_DATA_TIMEOUT) + return -ETIMEDOUT; + } while (!(irqstat & SDHCI_INT_XFER_COMPLETE) && + (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_DATA_LINE_ACTIVE)); + + dma_unmap_single(host->dev, tr->dma, tr->size, tr->dir); + + return 0; +} + +static bool esdhc_match32(struct fsl_esdhc_host *host, unsigned int off, + unsigned int mask, unsigned int val) +{ + const unsigned int reg = sdhci_read32(&host->sdhci, off) & mask; + + return reg == val; +} + +#ifdef __PBL__ +/* + * Stubs to make timeout logic below work in PBL + */ + +#define get_time_ns() 0 +/* + * Use time in us (approx) as a busy counter timeout value + */ +#define is_timeout(s, t) ((s)++ > ((t) / 1024)) + +static void __udelay(int us) +{ + volatile int i; + + for (i = 0; i < us * 4; i++); +} + +#define udelay(n) __udelay(n) +#undef dev_err +#define dev_err(d, ...) pr_err(__VA_ARGS__) + +#endif + +int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off, + unsigned int mask, unsigned int val, + uint64_t timeout) +{ + return wait_on_timeout(timeout, + esdhc_match32(host, off, mask, val)); +} + +int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, + struct mci_data *data) +{ + u32 xfertyp, mixctrl, command; + u32 irqstat; + struct fsl_esdhc_dma_transfer tr = { 0 }; + int ret; + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1); + + /* Wait at least 8 SD clock cycles before the next command */ + udelay(1); + + /* Set up for a data transfer if we have one */ + if (data) { + ret = esdhc_setup_data(host, data, &tr); + if (ret) + return ret; + } + + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, + !esdhc_use_pio_mode(), &command, &xfertyp); + + if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) && + (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)) + command |= SDHCI_COMMAND_CMDTYP_ABORT; + + /* Send the command */ + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); + + if (esdhc_is_usdhc(host)) { + /* write lower-half of xfertyp to mixctrl */ + mixctrl = xfertyp; + /* Keep the bits 22-25 of the register as is */ + mixctrl |= (sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL) & (0xF << 22)); + sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, mixctrl); + } + + sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, + command << 16 | xfertyp); + + /* Wait for the command to complete */ + ret = esdhc_poll(host, SDHCI_INT_STATUS, + SDHCI_INT_CMD_COMPLETE, SDHCI_INT_CMD_COMPLETE, + 100 * MSECOND); + if (ret) { + dev_err(host->dev, "timeout 1\n"); + return -ETIMEDOUT; + } + + irqstat = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, irqstat); + + if (irqstat & CMD_ERR) + return -EIO; + + if (irqstat & SDHCI_INT_TIMEOUT) + return -ETIMEDOUT; + + /* Workaround for ESDHC errata ENGcm03648 / ENGcm12360 */ + if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { + /* + * Poll on DATA0 line for cmd with busy signal for + * timout / 10 usec since DLA polling can be insecure. + */ + ret = esdhc_poll(host, SDHCI_PRESENT_STATE, + PRSSTAT_DAT0, PRSSTAT_DAT0, + 2500 * MSECOND); + if (ret) { + dev_err(host->dev, "timeout PRSSTAT_DAT0\n"); + return -ETIMEDOUT; + } + } + + sdhci_read_response(&host->sdhci, cmd); + + /* Wait until all of the blocks are transferred */ + if (data) { + ret = esdhc_do_data(host, data, &tr); + if (ret) + return ret; + } + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, -1); + + /* Wait for the bus to be idle */ + ret = esdhc_poll(host, SDHCI_PRESENT_STATE, + SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA, 0, + SECOND); + if (ret) { + dev_err(host->dev, "timeout 2\n"); + return -ETIMEDOUT; + } + + ret = esdhc_poll(host, SDHCI_PRESENT_STATE, + SDHCI_DATA_LINE_ACTIVE, 0, + 100 * MSECOND); + if (ret) { + dev_err(host->dev, "timeout 3\n"); + return -ETIMEDOUT; + } + + return 0; +} + diff --git a/drivers/mci/imx-esdhc-pbl.c b/drivers/mci/imx-esdhc-pbl.c index f93ddfa0d5..c0d27fb7eb 100644 --- a/drivers/mci/imx-esdhc-pbl.c +++ b/drivers/mci/imx-esdhc-pbl.c @@ -30,206 +30,24 @@ #define SECTOR_SIZE 512 #define SECTOR_WML (SECTOR_SIZE / sizeof(u32)) -struct esdhc { - void __iomem *regs; - bool is_mx6; - bool is_be; - bool wrap_wml; -}; - -static uint32_t esdhc_read32(struct esdhc *esdhc, int reg) -{ - if (esdhc->is_be) - return in_be32(esdhc->regs + reg); - else - return readl(esdhc->regs + reg); -} +#define esdhc_send_cmd __esdhc_send_cmd -static void esdhc_write32(struct esdhc *esdhc, int reg, uint32_t val) -{ - if (esdhc->is_be) - out_be32(esdhc->regs + reg, val); - else - writel(val, esdhc->regs + reg); -} - -static void __udelay(int us) -{ - volatile int i; - - for (i = 0; i < us * 4; i++); -} - -static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) -{ - u32 xfertyp = 0; - - if (data) - xfertyp |= COMMAND_DPSEL | TRANSFER_MODE_MSBSEL | - TRANSFER_MODE_BCEN |TRANSFER_MODE_DTDSEL; - - if (cmd->resp_type & MMC_RSP_CRC) - xfertyp |= COMMAND_CCCEN; - if (cmd->resp_type & MMC_RSP_OPCODE) - xfertyp |= COMMAND_CICEN; - if (cmd->resp_type & MMC_RSP_136) - xfertyp |= COMMAND_RSPTYP_136; - else if (cmd->resp_type & MMC_RSP_BUSY) - xfertyp |= COMMAND_RSPTYP_48_BUSY; - else if (cmd->resp_type & MMC_RSP_PRESENT) - xfertyp |= COMMAND_RSPTYP_48; - - return COMMAND_CMD(cmd->cmdidx) | xfertyp; -} - -static int esdhc_do_data(struct esdhc *esdhc, struct mci_data *data) -{ - char *buffer; - u32 databuf; - u32 size; - u32 irqstat; - u32 present; - - buffer = data->dest; - - size = data->blocksize * data->blocks; - irqstat = esdhc_read32(esdhc, SDHCI_INT_STATUS); - - while (size) { - int i; - int timeout = 1000000; - - while (1) { - present = esdhc_read32(esdhc, SDHCI_PRESENT_STATE) & PRSSTAT_BREN; - if (present) - break; - if (!--timeout) { - pr_err("read time out\n"); - return -ETIMEDOUT; - } - } - - for (i = 0; i < SECTOR_WML; i++) { - databuf = esdhc_read32(esdhc, SDHCI_BUFFER); - *((u32 *)buffer) = databuf; - buffer += 4; - size -= 4; - } - } - - return 0; -} - -static int -esdhc_send_cmd(struct esdhc *esdhc, struct mci_cmd *cmd, struct mci_data *data) -{ - u32 xfertyp, mixctrl; - u32 irqstat; - int ret; - int timeout; - - esdhc_write32(esdhc, SDHCI_INT_STATUS, -1); - - /* Wait at least 8 SD clock cycles before the next command */ - __udelay(1); - - if (data) { - unsigned long dest = (unsigned long)data->dest; - - if (dest > 0xffffffff) - return -EINVAL; - - /* Set up for a data transfer if we have one */ - esdhc_write32(esdhc, SDHCI_DMA_ADDRESS, (u32)dest); - esdhc_write32(esdhc, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | SECTOR_SIZE); - } - - /* Figure out the transfer arguments */ - xfertyp = esdhc_xfertyp(cmd, data); - - /* Send the command */ - esdhc_write32(esdhc, SDHCI_ARGUMENT, cmd->cmdarg); - - if (esdhc->is_mx6) { - /* write lower-half of xfertyp to mixctrl */ - mixctrl = xfertyp & 0xFFFF; - /* Keep the bits 22-25 of the register as is */ - mixctrl |= (esdhc_read32(esdhc, IMX_SDHCI_MIXCTRL) & (0xF << 22)); - esdhc_write32(esdhc, IMX_SDHCI_MIXCTRL, mixctrl); - } - - esdhc_write32(esdhc, SDHCI_TRANSFER_MODE__COMMAND, xfertyp); - - /* Wait for the command to complete */ - timeout = 10000; - while (!(esdhc_read32(esdhc, SDHCI_INT_STATUS) & IRQSTAT_CC)) { - __udelay(1); - if (!timeout--) - return -ETIMEDOUT; - } - - irqstat = esdhc_read32(esdhc, SDHCI_INT_STATUS); - esdhc_write32(esdhc, SDHCI_INT_STATUS, irqstat); - - if (irqstat & CMD_ERR) - return -EIO; - - if (irqstat & IRQSTAT_CTOE) - return -ETIMEDOUT; - - /* Copy the response to the response buffer */ - cmd->response[0] = esdhc_read32(esdhc, SDHCI_RESPONSE_0); - - /* Wait until all of the blocks are transferred */ - if (data) { - ret = esdhc_do_data(esdhc, data); - if (ret) - return ret; - } - - esdhc_write32(esdhc, SDHCI_INT_STATUS, -1); - - /* Wait for the bus to be idle */ - timeout = 10000; - while (esdhc_read32(esdhc, SDHCI_PRESENT_STATE) & - (PRSSTAT_CICHB | PRSSTAT_CIDHB | PRSSTAT_DLA)) { - __udelay(1); - if (!timeout--) - return -ETIMEDOUT; - } - - return 0; -} - -static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) +static int esdhc_read_blocks(struct fsl_esdhc_host *host, void *dst, size_t len) { struct mci_cmd cmd; struct mci_data data; - u32 val, wml; + u32 val; int ret; - esdhc_write32(esdhc, SDHCI_INT_ENABLE, - IRQSTATEN_CC | IRQSTATEN_TC | IRQSTATEN_CINT | IRQSTATEN_CTOE | - IRQSTATEN_CCE | IRQSTATEN_CEBE | IRQSTATEN_CIE | - IRQSTATEN_DTOE | IRQSTATEN_DCE | IRQSTATEN_DEBE | - IRQSTATEN_DINT); - - wml = FIELD_PREP(WML_WR_BRST_LEN, 16) | - FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) | - FIELD_PREP(WML_RD_BRST_LEN, 16) | - FIELD_PREP(WML_RD_WML_MASK, SECTOR_WML); - /* - * Some SoCs intrpret 0 as MAX value so for those cases the - * above value translates to zero - */ - if (esdhc->wrap_wml) - wml = 0; - - esdhc_write32(esdhc, IMX_SDHCI_WML, wml); + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, + SDHCI_INT_CMD_COMPLETE | SDHCI_INT_XFER_COMPLETE | + SDHCI_INT_CARD_INT | SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | + SDHCI_INT_END_BIT | SDHCI_INT_INDEX | SDHCI_INT_DATA_TIMEOUT | + SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DMA); - val = esdhc_read32(esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); + val = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); val |= SYSCTL_HCKEN | SYSCTL_IPGEN; - esdhc_write32(esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val); + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val); cmd.cmdidx = MMC_CMD_READ_MULTIPLE_BLOCK; cmd.cmdarg = 0; @@ -240,7 +58,7 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) data.blocksize = SECTOR_SIZE; data.flags = MMC_DATA_READ; - ret = esdhc_send_cmd(esdhc, &cmd, &data); + ret = esdhc_send_cmd(host, &cmd, &data); if (ret) { pr_debug("send command failed with %d\n", ret); return ret; @@ -250,13 +68,13 @@ static int esdhc_read_blocks(struct esdhc *esdhc, void *dst, size_t len) cmd.cmdarg = 0; cmd.resp_type = MMC_RSP_R1b; - esdhc_send_cmd(esdhc, &cmd, NULL); + esdhc_send_cmd(host, &cmd, NULL); return 0; } #ifdef CONFIG_ARCH_IMX -static int esdhc_search_header(struct esdhc *esdhc, +static int esdhc_search_header(struct fsl_esdhc_host *host, struct imx_flash_header_v2 **header_pointer, void *buffer, u32 *offset) { @@ -266,7 +84,7 @@ static int esdhc_search_header(struct esdhc *esdhc, struct imx_flash_header_v2 *hdr; for (i = 0; i < header_count; i++) { - ret = esdhc_read_blocks(esdhc, buf, + ret = esdhc_read_blocks(host, buf, *offset + SZ_1K + SECTOR_SIZE); if (ret) return ret; @@ -303,7 +121,7 @@ static int esdhc_search_header(struct esdhc *esdhc, } static int -esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, +esdhc_start_image(struct fsl_esdhc_host *host, ptrdiff_t address, ptrdiff_t entry, u32 offset) { @@ -316,7 +134,7 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, len = imx_image_size(); len = ALIGN(len, SECTOR_SIZE); - ret = esdhc_search_header(esdhc, &hdr, buf, &offset); + ret = esdhc_search_header(host, &hdr, buf, &offset); if (ret) return ret; @@ -351,7 +169,7 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, buf = (void *)(entry - ofs); } - ret = esdhc_read_blocks(esdhc, buf, offset + len); + ret = esdhc_read_blocks(host, buf, offset + len); if (ret) { pr_err("Loading image failed with %d\n", ret); return ret; @@ -366,6 +184,40 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, bb(); } +static void imx_esdhc_init(struct fsl_esdhc_host *host, + struct esdhc_soc_data *data) +{ + data->flags = ESDHC_FLAG_USDHC; + host->socdata = data; + esdhc_populate_sdhci(host); + + sdhci_write32(&host->sdhci, IMX_SDHCI_WML, + FIELD_PREP(WML_WR_BRST_LEN, 16) | + FIELD_PREP(WML_WR_WML_MASK, SECTOR_WML) | + FIELD_PREP(WML_RD_BRST_LEN, 16) | + FIELD_PREP(WML_RD_WML_MASK, SECTOR_WML)); +} + +static int imx8_esdhc_init(struct fsl_esdhc_host *host, + struct esdhc_soc_data *data, + int instance) +{ + switch (instance) { + case 0: + host->regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR); + break; + case 1: + host->regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR); + break; + default: + return -EINVAL; + } + + imx_esdhc_init(host, data); + + return 0; +} + /** * imx6_esdhc_start_image - Load and start an image from USDHC controller * @instance: The USDHC controller instance (0..4) @@ -380,30 +232,29 @@ esdhc_start_image(struct esdhc *esdhc, ptrdiff_t address, ptrdiff_t entry, */ int imx6_esdhc_start_image(int instance) { - struct esdhc esdhc; + struct esdhc_soc_data data; + struct fsl_esdhc_host host; switch (instance) { case 0: - esdhc.regs = IOMEM(MX6_USDHC1_BASE_ADDR); + host.regs = IOMEM(MX6_USDHC1_BASE_ADDR); break; case 1: - esdhc.regs = IOMEM(MX6_USDHC2_BASE_ADDR); + host.regs = IOMEM(MX6_USDHC2_BASE_ADDR); break; case 2: - esdhc.regs = IOMEM(MX6_USDHC3_BASE_ADDR); + host.regs = IOMEM(MX6_USDHC3_BASE_ADDR); break; case 3: - esdhc.regs = IOMEM(MX6_USDHC4_BASE_ADDR); + host.regs = IOMEM(MX6_USDHC4_BASE_ADDR); break; default: return -EINVAL; } - esdhc.is_be = 0; - esdhc.is_mx6 = 1; - esdhc.wrap_wml = false; + imx_esdhc_init(&host, &data); - return esdhc_start_image(&esdhc, 0x10000000, 0x10000000, 0); + return esdhc_start_image(&host, 0x10000000, 0x10000000, 0); } /** @@ -420,24 +271,15 @@ int imx6_esdhc_start_image(int instance) */ int imx8_esdhc_start_image(int instance) { - struct esdhc esdhc; - - switch (instance) { - case 0: - esdhc.regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR); - break; - case 1: - esdhc.regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR); - break; - default: - return -EINVAL; - } + struct esdhc_soc_data data; + struct fsl_esdhc_host host; + int ret; - esdhc.is_be = 0; - esdhc.is_mx6 = 1; - esdhc.wrap_wml = false; + ret = imx8_esdhc_init(&host, &data, instance); + if (ret) + return ret; - return esdhc_start_image(&esdhc, MX8MQ_DDR_CSD1_BASE_ADDR, + return esdhc_start_image(&host, MX8MQ_DDR_CSD1_BASE_ADDR, MX8MQ_ATF_BL33_BASE_ADDR, SZ_32K); } @@ -445,24 +287,14 @@ int imx8_esdhc_load_piggy(int instance) { void *buf, *piggy; struct imx_flash_header_v2 *hdr = NULL; - struct esdhc esdhc; + struct esdhc_soc_data data; + struct fsl_esdhc_host host; int ret, len; int offset = SZ_32K; - switch (instance) { - case 0: - esdhc.regs = IOMEM(MX8MQ_USDHC1_BASE_ADDR); - break; - case 1: - esdhc.regs = IOMEM(MX8MQ_USDHC2_BASE_ADDR); - break; - default: - return -EINVAL; - } - - esdhc.is_be = 0; - esdhc.is_mx6 = 1; - esdhc.wrap_wml = false; + ret = imx8_esdhc_init(&host, &data, instance); + if (ret) + return ret; /* * We expect to be running at MX8MQ_ATF_BL33_BASE_ADDR where the atf @@ -471,14 +303,14 @@ int imx8_esdhc_load_piggy(int instance) */ buf = (void *)MX8MQ_ATF_BL33_BASE_ADDR + SZ_32M; - ret = esdhc_search_header(&esdhc, &hdr, buf, &offset); + ret = esdhc_search_header(&host, &hdr, buf, &offset); if (ret) return ret; len = offset + hdr->boot_data.size + piggydata_size(); len = ALIGN(len, SECTOR_SIZE); - ret = esdhc_read_blocks(&esdhc, buf, len); + ret = esdhc_read_blocks(&host, buf, len); /* * Calculate location of the piggydata at the offset loaded into RAM @@ -516,28 +348,33 @@ int ls1046a_esdhc_start_image(unsigned long r0, unsigned long r1, unsigned long { int ret; uint32_t val; - struct esdhc esdhc = { + struct esdhc_soc_data data = { + .flags = ESDHC_FLAG_BIGENDIAN, + }; + struct fsl_esdhc_host host = { .regs = IOMEM(0x01560000), - .is_be = true, - .wrap_wml = true, + .socdata = &data, }; unsigned long sdram = 0x80000000; void (*barebox)(unsigned long, unsigned long, unsigned long) = (void *)(sdram + LS1046A_SD_IMAGE_OFFSET); + esdhc_populate_sdhci(&host); + sdhci_write32(&host.sdhci, IMX_SDHCI_WML, 0); + /* * The ROM leaves us here with a clock frequency of around 400kHz. Speed * this up a bit. FIXME: The resulting frequency has not yet been verified * to work on all cards. */ - val = esdhc_read32(&esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); + val = sdhci_read32(&host.sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); val &= ~0x0000fff0; val |= (8 << 8) | (3 << 4); - esdhc_write32(&esdhc, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val); + sdhci_write32(&host.sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, val); - esdhc_write32(&esdhc, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP); + sdhci_write32(&host.sdhci, ESDHC_DMA_SYSCTL, ESDHC_SYSCTL_DMA_SNOOP); - ret = esdhc_read_blocks(&esdhc, (void *)sdram, + ret = esdhc_read_blocks(&host, (void *)sdram, ALIGN(barebox_image_size + LS1046A_SD_IMAGE_OFFSET, 512)); if (ret) { pr_err("%s: reading blocks failed with: %d\n", __func__, ret); diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index db3450a26d..4816608a23 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -39,267 +39,12 @@ #include "sdhci.h" #include "imx-esdhc.h" -/* - * The CMDTYPE of the CMD register (offset 0xE) should be set to - * "11" when the STOP CMD12 is issued on imx53 to abort one - * open ended multi-blk IO. Otherwise the TC INT wouldn't - * be generated. - * In exact block transfer, the controller doesn't complete the - * operations automatically as required at the end of the - * transfer and remains on hold if the abort command is not sent. - * As a result, the TC flag is not asserted and SW received timeout - * exeception. Bit1 of Vendor Spec registor is used to fix it. - */ -#define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1) -/* - * The flag enables the workaround for ESDHC errata ENGcm07207 which - * affects i.MX25 and i.MX35. - */ -#define ESDHC_FLAG_ENGCM07207 BIT(2) -/* - * The flag tells that the ESDHC controller is an USDHC block that is - * integrated on the i.MX6 series. - */ -#define ESDHC_FLAG_USDHC BIT(3) -/* The IP supports manual tuning process */ -#define ESDHC_FLAG_MAN_TUNING BIT(4) -/* The IP supports standard tuning process */ -#define ESDHC_FLAG_STD_TUNING BIT(5) -/* The IP has SDHCI_CAPABILITIES_1 register */ -#define ESDHC_FLAG_HAVE_CAP1 BIT(6) -/* - * The IP has errata ERR004536 - * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow, - * when reading data from the card - */ -#define ESDHC_FLAG_ERR004536 BIT(7) -/* The IP supports HS200 mode */ -#define ESDHC_FLAG_HS200 BIT(8) -/* The IP supports HS400 mode */ -#define ESDHC_FLAG_HS400 BIT(9) - -/* Need to access registers in bigendian mode */ -#define ESDHC_FLAG_BIGENDIAN BIT(10) -/* Enable cache snooping */ -#define ESDHC_FLAG_CACHE_SNOOPING BIT(11) - -struct esdhc_soc_data { - u32 flags; - const char *clkidx; -}; +#define PRSSTAT_SDSTB 0x00000008 -struct fsl_esdhc_host { - struct mci_host mci; - void __iomem *regs; - struct device_d *dev; - struct clk *clk; - const struct esdhc_soc_data *socdata; -}; #define to_fsl_esdhc(mci) container_of(mci, struct fsl_esdhc_host, mci) -#define SDHCI_CMD_ABORTCMD (0xC0 << 16) - -static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data) -{ - return !!(data->socdata->flags & ESDHC_FLAG_USDHC); -} - -static inline u32 esdhc_read32(struct fsl_esdhc_host *host, unsigned int reg) -{ - if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) - return in_be32(host->regs + reg); - else - return readl(host->regs + reg); -} - -static inline void esdhc_write32(struct fsl_esdhc_host *host, unsigned int reg, - u32 val) -{ - if (host->socdata->flags & ESDHC_FLAG_BIGENDIAN) - out_be32(host->regs + reg, val); - else - writel(val, host->regs + reg); -} - -static inline void esdhc_clrsetbits32(struct fsl_esdhc_host *host, unsigned int reg, - u32 clear, u32 set) -{ - u32 val; - - val = esdhc_read32(host, reg); - val &= ~clear; - val |= set; - esdhc_write32(host, reg, val); -} - -static inline void esdhc_clrbits32(struct fsl_esdhc_host *host, unsigned int reg, - u32 clear) -{ - esdhc_clrsetbits32(host, reg, clear, 0); -} - -static inline void esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg, - u32 set) -{ - esdhc_clrsetbits32(host, reg, 0, set); -} - -/* Return the XFERTYP flags for a given command and data packet */ -static u32 esdhc_xfertyp(struct fsl_esdhc_host *host, - struct mci_cmd *cmd, struct mci_data *data) -{ - u32 xfertyp = 0; - - if (data) { - xfertyp |= COMMAND_DPSEL; - - if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) - xfertyp |= TRANSFER_MODE_DMAEN; - - if (data->blocks > 1) { - xfertyp |= TRANSFER_MODE_MSBSEL; - xfertyp |= TRANSFER_MODE_BCEN; - } - - if (data->flags & MMC_DATA_READ) - xfertyp |= TRANSFER_MODE_DTDSEL; - } - - if (cmd->resp_type & MMC_RSP_CRC) - xfertyp |= COMMAND_CCCEN; - if (cmd->resp_type & MMC_RSP_OPCODE) - xfertyp |= COMMAND_CICEN; - if (cmd->resp_type & MMC_RSP_136) - xfertyp |= COMMAND_RSPTYP_136; - else if (cmd->resp_type & MMC_RSP_BUSY) - xfertyp |= COMMAND_RSPTYP_48_BUSY; - else if (cmd->resp_type & MMC_RSP_PRESENT) - xfertyp |= COMMAND_RSPTYP_48; - if ((host->socdata->flags & ESDHC_FLAG_MULTIBLK_NO_INT) && - (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION)) - xfertyp |= SDHCI_CMD_ABORTCMD; - - return COMMAND_CMD(cmd->cmdidx) | xfertyp; -} - -/* - * PIO Read/Write Mode reduce the performace as DMA is not used in this mode. - */ -static int -esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) -{ - struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - u32 blocks; - char *buffer; - u32 databuf; - u32 size; - u32 irqstat; - u32 timeout; - - if (data->flags & MMC_DATA_READ) { - blocks = data->blocks; - buffer = data->dest; - while (blocks) { - timeout = PIO_TIMEOUT; - size = data->blocksize; - irqstat = esdhc_read32(host, SDHCI_INT_STATUS); - while (!(esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_BREN) - && --timeout); - if (timeout <= 0) { - dev_err(host->dev, "Data Read Failed\n"); - return -ETIMEDOUT; - } - while (size && (!(irqstat & IRQSTAT_TC))) { - udelay(100); /* Wait before last byte transfer complete */ - irqstat = esdhc_read32(host, SDHCI_INT_STATUS); - databuf = esdhc_read32(host, SDHCI_BUFFER); - *((u32 *)buffer) = databuf; - buffer += 4; - size -= 4; - } - blocks--; - } - } else { - blocks = data->blocks; - buffer = (char *)data->src; - while (blocks) { - timeout = PIO_TIMEOUT; - size = data->blocksize; - irqstat = esdhc_read32(host, SDHCI_INT_STATUS); - while (!(esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_BWEN) - && --timeout); - if (timeout <= 0) { - dev_err(host->dev, "Data Write Failed\n"); - return -ETIMEDOUT; - } - while (size && (!(irqstat & IRQSTAT_TC))) { - udelay(100); /* Wait before last byte transfer complete */ - databuf = *((u32 *)buffer); - buffer += 4; - size -= 4; - irqstat = esdhc_read32(host, SDHCI_INT_STATUS); - esdhc_write32(host, SDHCI_BUFFER, databuf); - } - blocks--; - } - } - - return 0; -} - -static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data, - dma_addr_t dma) -{ - struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - u32 wml_value; - - if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) { - wml_value = data->blocksize/4; - - if (data->flags & MMC_DATA_READ) { - if (wml_value > 0x10) - wml_value = 0x10; - - esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value); - } else { - if (wml_value > 0x80) - wml_value = 0x80; - - esdhc_clrsetbits32(host, IMX_SDHCI_WML, WML_WR_WML_MASK, - wml_value << 16); - } - esdhc_write32(host, SDHCI_DMA_ADDRESS, dma); - } - - esdhc_write32(host, SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize); - - return 0; -} - -static int esdhc_do_data(struct mci_host *mci, struct mci_data *data) -{ - struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - u32 irqstat; - - if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) - return esdhc_pio_read_write(mci, data); - - do { - irqstat = esdhc_read32(host, SDHCI_INT_STATUS); - - if (irqstat & DATA_ERR) - return -EIO; - - if (irqstat & IRQSTAT_DTOE) - return -ETIMEDOUT; - } while (!(irqstat & IRQSTAT_TC) && - (esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_DLA)); - - return 0; -} - /* * Sends a command out on the bus. Takes the mci pointer, * a command pointer, and an optional data pointer. @@ -307,137 +52,9 @@ static int esdhc_do_data(struct mci_host *mci, struct mci_data *data) static int esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) { - u32 xfertyp, mixctrl; - u32 irqstat; struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - unsigned int num_bytes = 0; - int ret; - void *ptr; - enum dma_data_direction dir = 0; - dma_addr_t dma = 0; - - esdhc_write32(host, SDHCI_INT_STATUS, -1); - - /* Wait at least 8 SD clock cycles before the next command */ - udelay(1); - - /* Set up for a data transfer if we have one */ - if (data) { - int err; - - if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) { - num_bytes = data->blocks * data->blocksize; - - if (data->flags & MMC_DATA_WRITE) { - ptr = (void *)data->src; - dir = DMA_TO_DEVICE; - } else { - ptr = data->dest; - dir = DMA_FROM_DEVICE; - } - - dma = dma_map_single(host->dev, ptr, num_bytes, dir); - if (dma_mapping_error(host->dev, dma)) - return -EFAULT; - } - - err = esdhc_setup_data(mci, data, dma); - if(err) - return err; - } - - /* Figure out the transfer arguments */ - xfertyp = esdhc_xfertyp(host, cmd, data); - - /* Send the command */ - esdhc_write32(host, SDHCI_ARGUMENT, cmd->cmdarg); - - if (esdhc_is_usdhc(host)) { - /* write lower-half of xfertyp to mixctrl */ - mixctrl = xfertyp & 0xFFFF; - /* Keep the bits 22-25 of the register as is */ - mixctrl |= (esdhc_read32(host, IMX_SDHCI_MIXCTRL) & (0xF << 22)); - esdhc_write32(host, IMX_SDHCI_MIXCTRL, mixctrl); - } - - esdhc_write32(host, SDHCI_TRANSFER_MODE__COMMAND, xfertyp); - - /* Wait for the command to complete */ - ret = wait_on_timeout(100 * MSECOND, - esdhc_read32(host, SDHCI_INT_STATUS) & IRQSTAT_CC); - if (ret) { - dev_dbg(host->dev, "timeout 1\n"); - return -ETIMEDOUT; - } - - irqstat = esdhc_read32(host, SDHCI_INT_STATUS); - esdhc_write32(host, SDHCI_INT_STATUS, irqstat); - - if (irqstat & CMD_ERR) - return -EIO; - - if (irqstat & IRQSTAT_CTOE) - return -ETIMEDOUT; - - /* Workaround for ESDHC errata ENGcm03648 / ENGcm12360 */ - if (!data && (cmd->resp_type & MMC_RSP_BUSY)) { - /* - * Poll on DATA0 line for cmd with busy signal for - * timout / 10 usec since DLA polling can be insecure. - */ - ret = wait_on_timeout(2500 * MSECOND, - (esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_DAT0)); - - if (ret) { - dev_err(host->dev, "timeout PRSSTAT_DAT0\n"); - return -ETIMEDOUT; - } - } - - /* Copy the response to the response buffer */ - if (cmd->resp_type & MMC_RSP_136) { - u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; - - cmdrsp3 = esdhc_read32(host, SDHCI_RESPONSE_3); - cmdrsp2 = esdhc_read32(host, SDHCI_RESPONSE_2); - cmdrsp1 = esdhc_read32(host, SDHCI_RESPONSE_1); - cmdrsp0 = esdhc_read32(host, SDHCI_RESPONSE_0); - cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); - cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); - cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); - cmd->response[3] = (cmdrsp0 << 8); - } else - cmd->response[0] = esdhc_read32(host, SDHCI_RESPONSE_0); - - /* Wait until all of the blocks are transferred */ - if (data) { - ret = esdhc_do_data(mci, data); - if (ret) - return ret; - if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) - dma_unmap_single(host->dev, dma, num_bytes, dir); - } - - esdhc_write32(host, SDHCI_INT_STATUS, -1); - - /* Wait for the bus to be idle */ - ret = wait_on_timeout(SECOND, - !(esdhc_read32(host, SDHCI_PRESENT_STATE) & - (PRSSTAT_CICHB | PRSSTAT_CIDHB))); - if (ret) { - dev_err(host->dev, "timeout 2\n"); - return -ETIMEDOUT; - } - - ret = wait_on_timeout(100 * MSECOND, - !(esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_DLA)); - if (ret) { - dev_err(host->dev, "timeout 3\n"); - return -ETIMEDOUT; - } - - return 0; + return __esdhc_send_cmd(host, cmd, data); } static void set_sysctl(struct mci_host *mci, u32 clock) @@ -486,16 +103,18 @@ static void set_sysctl(struct mci_host *mci, u32 clock) esdhc_clrsetbits32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, SYSCTL_CLOCK_MASK, clk); - wait_on_timeout(10 * MSECOND, - esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_SDSTB); + esdhc_poll(host, SDHCI_PRESENT_STATE, + PRSSTAT_SDSTB, PRSSTAT_SDSTB, + 10 * MSECOND); clk = SYSCTL_PEREN | SYSCTL_CKEN | SYSCTL_INITA; esdhc_setbits32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, clk); - wait_on_timeout(1 * MSECOND, - !(esdhc_read32(host, SDHCI_CLOCK_CONTROL) & SYSCTL_INITA)); + esdhc_poll(host, SDHCI_CLOCK_CONTROL, + SYSCTL_INITA, SYSCTL_INITA, + 10 * MSECOND); } static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) @@ -540,7 +159,7 @@ static int esdhc_card_present(struct mci_host *mci) case ESDHC_CD_PERMANENT: return 1; case ESDHC_CD_CONTROLLER: - return !(esdhc_read32(host, SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL); + return !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); case ESDHC_CD_GPIO: ret = gpio_direction_input(pdata->cd_gpio); if (ret) @@ -553,34 +172,29 @@ static int esdhc_card_present(struct mci_host *mci) static int esdhc_reset(struct fsl_esdhc_host *host) { - uint64_t start; int val; /* reset the controller */ - esdhc_write32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, SYSCTL_RSTA); /* extra register reset for i.MX6 Solo/DualLite */ if (esdhc_is_usdhc(host)) { /* reset bit FBCLK_SEL */ - val = esdhc_read32(host, IMX_SDHCI_MIXCTRL); + val = sdhci_read32(&host->sdhci, IMX_SDHCI_MIXCTRL); val &= ~IMX_SDHCI_MIX_CTRL_FBCLK_SEL; - esdhc_write32(host, IMX_SDHCI_MIXCTRL, val); + sdhci_write32(&host->sdhci, IMX_SDHCI_MIXCTRL, val); /* reset delay line settings in IMX_SDHCI_DLL_CTRL */ - esdhc_write32(host, IMX_SDHCI_DLL_CTRL, 0x0); + sdhci_write32(&host->sdhci, IMX_SDHCI_DLL_CTRL, 0x0); } - start = get_time_ns(); /* hardware clears the bit when it is done */ - while (1) { - if (!(esdhc_read32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET) - & SYSCTL_RSTA)) - break; - if (is_timeout(start, 100 * MSECOND)) { - dev_err(host->dev, "Reset never completed.\n"); - return -EIO; - } + if (esdhc_poll(host, + SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + SYSCTL_RSTA, 0, 100 * MSECOND)) { + dev_err(host->dev, "Reset never completed.\n"); + return -EIO; } return 0; @@ -595,11 +209,11 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev) if (ret) return ret; - esdhc_write32(host, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, SYSCTL_HCKEN | SYSCTL_IPGEN); /* RSTA doesn't reset MMC_BOOT register, so manually reset it */ - esdhc_write32(host, SDHCI_MMC_BOOT, 0); + sdhci_write32(&host->sdhci, SDHCI_MMC_BOOT, 0); /* Enable cache snooping */ if (host->socdata->flags & ESDHC_FLAG_CACHE_SNOOPING) @@ -608,13 +222,14 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev) /* Set the initial clock speed */ set_sysctl(mci, 400000); - esdhc_write32(host, SDHCI_INT_ENABLE, IRQSTATEN_CC | IRQSTATEN_TC | - IRQSTATEN_CINT | IRQSTATEN_CTOE | IRQSTATEN_CCE | - IRQSTATEN_CEBE | IRQSTATEN_CIE | IRQSTATEN_DTOE | - IRQSTATEN_DCE | IRQSTATEN_DEBE | IRQSTATEN_DINT); + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, SDHCI_INT_CMD_COMPLETE | + SDHCI_INT_XFER_COMPLETE | SDHCI_INT_CARD_INT | + SDHCI_INT_TIMEOUT | SDHCI_INT_CRC | SDHCI_INT_END_BIT | + SDHCI_INT_INDEX | SDHCI_INT_DATA_TIMEOUT | + SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT | SDHCI_INT_DMA); /* Put the PROCTL reg back to the default */ - esdhc_write32(host, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, + sdhci_write32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, PROCTL_INIT); /* Set timout to the maximum value */ @@ -673,7 +288,9 @@ static int fsl_esdhc_probe(struct device_d *dev) } host->regs = IOMEM(iores->start); - caps = esdhc_read32(host, SDHCI_CAPABILITIES); + esdhc_populate_sdhci(host); + + caps = sdhci_read32(&host->sdhci, SDHCI_CAPABILITIES); if (caps & ESDHC_HOSTCAPBLT_VS18) mci->voltages |= MMC_VDD_165_195; diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h index 2d5471969d..4bf890edf9 100644 --- a/drivers/mci/imx-esdhc.h +++ b/drivers/mci/imx-esdhc.h @@ -22,6 +22,7 @@ #ifndef __FSL_ESDHC_H__ #define __FSL_ESDHC_H__ +#include <dma.h> #include <errno.h> #include <asm/byteorder.h> #include <linux/bitfield.h> @@ -35,8 +36,8 @@ #define SYSCTL_HCKEN 0x00000002 #define SYSCTL_IPGEN 0x00000001 -#define CMD_ERR (IRQSTAT_CIE | IRQSTAT_CEBE | IRQSTAT_CCE) -#define DATA_ERR (IRQSTAT_DEBE | IRQSTAT_DCE | IRQSTAT_DTOE) +#define CMD_ERR (SDHCI_INT_INDEX | SDHCI_INT_END_BIT | SDHCI_INT_CRC) +#define DATA_ERR (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT) #define PROCTL_INIT 0x00000020 #define PROCTL_DTW_4 0x00000002 @@ -69,9 +70,106 @@ #define ESDHC_DMA_SYSCTL 0x40c /* Layerscape specific */ #define ESDHC_SYSCTL_DMA_SNOOP BIT(6) -struct fsl_esdhc_cfg { - u32 esdhc_base; - u32 no_snoop; + +/* + * The CMDTYPE of the CMD register (offset 0xE) should be set to + * "11" when the STOP CMD12 is issued on imx53 to abort one + * open ended multi-blk IO. Otherwise the TC INT wouldn't + * be generated. + * In exact block transfer, the controller doesn't complete the + * operations automatically as required at the end of the + * transfer and remains on hold if the abort command is not sent. + * As a result, the TC flag is not asserted and SW received timeout + * exeception. Bit1 of Vendor Spec registor is used to fix it. + */ +#define ESDHC_FLAG_MULTIBLK_NO_INT BIT(1) +/* + * The flag enables the workaround for ESDHC errata ENGcm07207 which + * affects i.MX25 and i.MX35. + */ +#define ESDHC_FLAG_ENGCM07207 BIT(2) +/* + * The flag tells that the ESDHC controller is an USDHC block that is + * integrated on the i.MX6 series. + */ +#define ESDHC_FLAG_USDHC BIT(3) +/* The IP supports manual tuning process */ +#define ESDHC_FLAG_MAN_TUNING BIT(4) +/* The IP supports standard tuning process */ +#define ESDHC_FLAG_STD_TUNING BIT(5) +/* The IP has SDHCI_CAPABILITIES_1 register */ +#define ESDHC_FLAG_HAVE_CAP1 BIT(6) + +/* + * The IP has errata ERR004536 + * uSDHC: ADMA Length Mismatch Error occurs if the AHB read access is slow, + * when reading data from the card + */ +#define ESDHC_FLAG_ERR004536 BIT(7) +/* The IP supports HS200 mode */ +#define ESDHC_FLAG_HS200 BIT(8) +/* The IP supports HS400 mode */ +#define ESDHC_FLAG_HS400 BIT(9) +/* Need to access registers in bigendian mode */ +#define ESDHC_FLAG_BIGENDIAN BIT(10) +/* Enable cache snooping */ +#define ESDHC_FLAG_CACHE_SNOOPING BIT(11) + +struct esdhc_soc_data { + u32 flags; + const char *clkidx; +}; + +struct fsl_esdhc_host { + struct mci_host mci; + struct clk *clk; + struct device_d *dev; + void __iomem *regs; + const struct esdhc_soc_data *socdata; + struct sdhci sdhci; }; +static inline int esdhc_is_usdhc(struct fsl_esdhc_host *data) +{ + return !!(data->socdata->flags & ESDHC_FLAG_USDHC); +} + +static inline struct fsl_esdhc_host *sdhci_to_esdhc(struct sdhci *sdhci) +{ + return container_of(sdhci, struct fsl_esdhc_host, sdhci); +} + +static inline void +esdhc_clrsetbits32(struct fsl_esdhc_host *host, unsigned int reg, + u32 clear, u32 set) +{ + u32 val; + + val = sdhci_read32(&host->sdhci, reg); + val &= ~clear; + val |= set; + sdhci_write32(&host->sdhci, reg, val); +} + +static inline void +esdhc_clrbits32(struct fsl_esdhc_host *host, unsigned int reg, + u32 clear) +{ + esdhc_clrsetbits32(host, reg, clear, 0); +} + +static inline void +esdhc_setbits32(struct fsl_esdhc_host *host, unsigned int reg, + u32 set) +{ + esdhc_clrsetbits32(host, reg, 0, set); +} + +void esdhc_populate_sdhci(struct fsl_esdhc_host *host); +int esdhc_poll(struct fsl_esdhc_host *host, unsigned int off, + unsigned int mask, unsigned int val, + uint64_t timeout); +int __esdhc_send_cmd(struct fsl_esdhc_host *host, struct mci_cmd *cmd, + struct mci_data *data); + #endif /* __FSL_ESDHC_H__ */ diff --git a/drivers/mci/mci-bcm2835.c b/drivers/mci/mci-bcm2835.c index 2ed1251672..b18d681870 100644 --- a/drivers/mci/mci-bcm2835.c +++ b/drivers/mci/mci-bcm2835.c @@ -51,10 +51,13 @@ struct bcm2835_mci_host { u32 max_clock; u32 version; uint64_t last_write; + struct sdhci sdhci; }; -static void bcm2835_mci_write(struct bcm2835_mci_host *host, u32 reg, u32 val) +static void bcm2835_sdhci_write32(struct sdhci *sdhci, int reg, u32 val) { + struct bcm2835_mci_host *host = container_of(sdhci, struct bcm2835_mci_host, sdhci); + /* * The Arasan has a bugette whereby it may lose the content of * successive writes to registers that are within two SD-card clock @@ -64,95 +67,21 @@ static void bcm2835_mci_write(struct bcm2835_mci_host *host, u32 reg, u32 val) * too) */ - if (host->last_write != 0) - while ((get_time_ns() - host->last_write) < twoticks_delay) - ; - host->last_write = get_time_ns(); - writel(val, host->regs + reg); -} - -static u32 bcm2835_mci_read(struct bcm2835_mci_host *host, u32 reg) -{ - return readl(host->regs + reg); -} + if (reg != SDHCI_BUFFER) { + if (host->last_write != 0) + while ((get_time_ns() - host->last_write) < twoticks_delay) + ; + host->last_write = get_time_ns(); + } -/* Create special write data function since the data - * register is not affected by the twoticks_delay bug - * and we can thus get better speed here - */ -static void bcm2835_mci_write_data(struct bcm2835_mci_host *host, u32 *p) -{ - writel(*p, host->regs + SDHCI_BUFFER); + writel(val, host->regs + reg); } -/* Make a read data functions as well just to keep structure */ -static void bcm2835_mci_read_data(struct bcm2835_mci_host *host, u32 *p) +static u32 bcm2835_sdhci_read32(struct sdhci *sdhci, int reg) { - *p = readl(host->regs + SDHCI_BUFFER); -} + struct bcm2835_mci_host *host = container_of(sdhci, struct bcm2835_mci_host, sdhci); -static int bcm2835_mci_transfer_data(struct bcm2835_mci_host *host, - struct mci_cmd *cmd, struct mci_data *data) { - u32 *p; - u32 data_size, status, intr_status = 0; - u32 data_ready_intr_mask; - u32 data_ready_status_mask; - int i = 0; - void (*read_write_func)(struct bcm2835_mci_host*, u32*); - - data_size = data->blocksize * data->blocks; - - if (data->flags & MMC_DATA_READ) { - p = (u32 *) data->dest; - data_ready_intr_mask = IRQSTAT_BRR; - data_ready_status_mask = PRSSTAT_BREN; - read_write_func = &bcm2835_mci_read_data; - } else { - p = (u32 *) data->src; - data_ready_intr_mask = IRQSTAT_BWR; - data_ready_status_mask = PRSSTAT_BWEN; - read_write_func = &bcm2835_mci_write_data; - } - do { - intr_status = bcm2835_mci_read(host, SDHCI_INT_STATUS); - if (intr_status & IRQSTAT_CIE) { - dev_err(host->hw_dev, - "Error occured while transferring data: 0x%X\n", - intr_status); - return -EPERM; - } - if (intr_status & data_ready_intr_mask) { - status = bcm2835_mci_read(host, SDHCI_PRESENT_STATE); - if ((status & data_ready_status_mask) == 0) - continue; - /*Clear latest int and transfer one block size of data*/ - bcm2835_mci_write(host, SDHCI_INT_STATUS, - data_ready_intr_mask); - for (i = 0; i < data->blocksize; i += 4) { - read_write_func(host, p); - p++; - data_size -= 4; - } - } - } while ((intr_status & IRQSTAT_TC) == 0); - - if (data_size != 0) { - if (data->flags & MMC_DATA_READ) - dev_err(host->hw_dev, "Error while reading:\n"); - else - dev_err(host->hw_dev, "Error while writing:\n"); - - dev_err(host->hw_dev, "Transferred %d bytes of data, wanted %d\n", - (data->blocksize * data->blocks) - data_size, - data->blocksize * data->blocks); - - dev_err(host->hw_dev, "Status: 0x%X, Interrupt: 0x%X\n", - bcm2835_mci_read(host, SDHCI_PRESENT_STATE), - bcm2835_mci_read(host, SDHCI_INT_STATUS)); - - return -EPERM; - } - return 0; + return readl(host->regs + reg); } static u32 bcm2835_mci_wait_command_done(struct bcm2835_mci_host *host) @@ -160,11 +89,10 @@ static u32 bcm2835_mci_wait_command_done(struct bcm2835_mci_host *host) u32 interrupt = 0; while (true) { - interrupt = bcm2835_mci_read( - host, SDHCI_INT_STATUS); - if (interrupt & IRQSTAT_CIE) + interrupt = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS); + if (interrupt & SDHCI_INT_INDEX) return -EPERM; - if (interrupt & IRQSTAT_CC) + if (interrupt & SDHCI_INT_CMD_COMPLETE) break; } return 0; @@ -174,15 +102,15 @@ static void bcm2835_mci_reset_emmc(struct bcm2835_mci_host *host, u32 reset, u32 wait_for) { u32 ret; - u32 current = bcm2835_mci_read(host, + u32 current = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, current | reset); while (true) { - ret = bcm2835_mci_read(host, + ret = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); if (ret & wait_for) continue; @@ -199,31 +127,14 @@ static void bcm2835_mci_reset_emmc(struct bcm2835_mci_host *host, u32 reset, */ static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) { - u32 command, block_data = 0, ret = 0; - u32 wait_inhibit_mask = PRSSTAT_CICHB | PRSSTAT_CIDHB; + u32 command, block_data = 0, ret = 0, transfer_mode = 0; + u32 wait_inhibit_mask = SDHCI_CMD_INHIBIT_CMD | SDHCI_CMD_INHIBIT_DATA; struct bcm2835_mci_host *host = to_bcm2835_host(mci); - command = COMMAND_CMD(cmd->cmdidx); - - if (cmd->resp_type != MMC_RSP_NONE) { - if (cmd->resp_type & MMC_RSP_136) - command |= COMMAND_RSPTYP_136; - else if (cmd->resp_type & MMC_RSP_BUSY) - command |= COMMAND_RSPTYP_48_BUSY; - else - command |= COMMAND_RSPTYP_48; - if (cmd->resp_type & MMC_RSP_CRC) - command |= COMMAND_CCCEN; - } - if (data != NULL) { - command |= COMMAND_DPSEL | TRANSFER_MODE_BCEN; - - if (data->blocks > 1) - command |= TRANSFER_MODE_MSBSEL; - - if (data->flags & MMC_DATA_READ) - command |= TRANSFER_MODE_DTDSEL; + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, false, + &command, &transfer_mode); + if (data != NULL) { block_data = (data->blocks << BLOCK_SHIFT); block_data |= data->blocksize; } @@ -231,55 +142,39 @@ static int bcm2835_mci_request(struct mci_host *mci, struct mci_cmd *cmd, /* We shouldn't wait for data inihibit for stop commands, even though they might use busy signaling */ if (cmd->cmdidx == MMC_CMD_STOP_TRANSMISSION) - wait_inhibit_mask = PRSSTAT_CICHB; + wait_inhibit_mask = SDHCI_CMD_INHIBIT_CMD; /*Wait for old command*/ - while (bcm2835_mci_read(host, SDHCI_PRESENT_STATE) + while (sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & wait_inhibit_mask) ; - bcm2835_mci_write(host, SDHCI_INT_ENABLE, 0xFFFFFFFF); - bcm2835_mci_write(host, SDHCI_INT_STATUS, 0xFFFFFFFF); + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, 0xFFFFFFFF); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, 0xFFFFFFFF); - bcm2835_mci_write(host, SDHCI_BLOCK_SIZE__BLOCK_COUNT, block_data); - bcm2835_mci_write(host, SDHCI_ARGUMENT, cmd->cmdarg); - bcm2835_mci_write(host, SDHCI_TRANSFER_MODE__COMMAND, command); + sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, block_data); + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); + sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, + command << 16 | transfer_mode); ret = bcm2835_mci_wait_command_done(host); if (ret) { dev_err(host->hw_dev, "Error while executing command %d\n", cmd->cmdidx); dev_err(host->hw_dev, "Status: 0x%X, Interrupt: 0x%X\n", - bcm2835_mci_read(host, SDHCI_PRESENT_STATE), - bcm2835_mci_read(host, SDHCI_INT_STATUS)); + sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE), + sdhci_read32(&host->sdhci, SDHCI_INT_STATUS)); } if (cmd->resp_type != 0 && ret != -1) { - int i = 0; - - /* CRC is stripped so we need to do some shifting. */ - if (cmd->resp_type & MMC_RSP_136) { - for (i = 0; i < 4; i++) { - cmd->response[i] = bcm2835_mci_read( - host, - SDHCI_RESPONSE_0 + (3 - i) * 4) << 8; - if (i != 3) - cmd->response[i] |= - readb((u32) (host->regs) + - SDHCI_RESPONSE_0 + - (3 - i) * 4 - 1); - } - } else { - cmd->response[0] = bcm2835_mci_read( - host, SDHCI_RESPONSE_0); - } - bcm2835_mci_write(host, SDHCI_INT_STATUS, - IRQSTAT_CC); + sdhci_read_response(&host->sdhci, cmd); + + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, SDHCI_INT_CMD_COMPLETE); } if (!ret && data) - ret = bcm2835_mci_transfer_data(host, cmd, data); + ret = sdhci_transfer_data(&host->sdhci, data); - bcm2835_mci_write(host, SDHCI_INT_STATUS, 0xFFFFFFFF); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, 0xFFFFFFFF); if (ret) { bcm2835_mci_reset_emmc(host, CONTROL1_CMDRST, CONTROL1_CMDRST); @@ -343,19 +238,19 @@ static void bcm2835_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) struct bcm2835_mci_host *host = to_bcm2835_host(mci); - current_val = bcm2835_mci_read(host, + current_val = sdhci_read32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL); switch (ios->bus_width) { case MMC_BUS_WIDTH_4: - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, current_val | CONTROL0_4DATA); host->bus_width = 1; dev_dbg(host->hw_dev, "Changing bus width to 4\n"); break; case MMC_BUS_WIDTH_1: - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, current_val & ~CONTROL0_4DATA); host->bus_width = 0; @@ -367,15 +262,15 @@ static void bcm2835_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) return; } if (ios->clock != host->clock && ios->clock != 0) { - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, 0x00); if (ios->clock > 26000000) { - enable = bcm2835_mci_read(host, + enable = sdhci_read32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL); enable |= CONTROL0_HISPEED; - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, enable); } @@ -388,18 +283,18 @@ static void bcm2835_mci_set_ios(struct mci_host *mci, struct mci_ios *ios) enable |= (divider_msb << CONTROL1_CLKMSB); enable |= CONTROL1_INTCLKENA | CONTROL1_TIMEOUT; - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, enable); while (true) { - u32 ret = bcm2835_mci_read(host, + u32 ret = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); if (ret & CONTROL1_CLK_STABLE) break; } enable |= CONTROL1_CLKENA; - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, enable); @@ -437,37 +332,37 @@ static int bcm2835_mci_reset(struct mci_host *mci, struct device_d *mci_dev) bcm2835_mci_reset_emmc(host, enable | reset, CONTROL1_HOSTRST); - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL, 0x00); - bcm2835_mci_write(host, SDHCI_ACMD12_ERR__HOST_CONTROL2, + sdhci_write32(&host->sdhci, SDHCI_ACMD12_ERR__HOST_CONTROL2, 0x00); - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, enable); while (true) { - ret = bcm2835_mci_read(host, + ret = sdhci_read32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET); if (ret & CONTROL1_CLK_STABLE) break; } enable |= CONTROL1_CLKENA; - bcm2835_mci_write(host, + sdhci_write32(&host->sdhci, SDHCI_CLOCK_CONTROL__TIMEOUT_CONTROL__SOFTWARE_RESET, enable); /*Delay atelast 74 clk cycles for card init*/ mdelay(100); - bcm2835_mci_write(host, SDHCI_INT_ENABLE, + sdhci_write32(&host->sdhci, SDHCI_INT_ENABLE, 0xFFFFFFFF); - bcm2835_mci_write(host, SDHCI_INT_STATUS, + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, 0xFFFFFFFF); /*Now write command 0 and see if we get response*/ - bcm2835_mci_write(host, SDHCI_ARGUMENT, 0x0); - bcm2835_mci_write(host, SDHCI_TRANSFER_MODE__COMMAND, 0x0); + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, 0x0); + sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, 0x0); return bcm2835_mci_wait_command_done(host); } @@ -507,6 +402,9 @@ static int bcm2835_mci_probe(struct device_d *hw_dev) host->hw_dev = hw_dev; host->max_clock = clk_get_rate(clk); + host->sdhci.read32 = bcm2835_sdhci_read32; + host->sdhci.write32 = bcm2835_sdhci_write32; + mci_of_parse(&host->mci); iores = dev_request_mem_resource(hw_dev, 0); @@ -540,8 +438,7 @@ static int bcm2835_mci_probe(struct device_d *hw_dev) twoticks_delay = ((2 * 1000000000) / MIN_FREQ) + 1; - host->version = bcm2835_mci_read( - host, BCM2835_MCI_SLOTISR_VER); + host->version = sdhci_read32(&host->sdhci, BCM2835_MCI_SLOTISR_VER); host->version = (host->version >> 16) & 0xFF; return mci_register(&host->mci); } diff --git a/drivers/mci/mci-core.c b/drivers/mci/mci-core.c index 9e39cbbb55..67257bcd18 100644 --- a/drivers/mci/mci-core.c +++ b/drivers/mci/mci-core.c @@ -1819,10 +1819,6 @@ int mci_register(struct mci_host *host) host->supply = regulator_get(host->hw_dev, "vmmc"); if (IS_ERR(host->supply)) { - if (host->supply == ERR_PTR(-EPROBE_DEFER)) { - ret = -EPROBE_DEFER; - goto err_free; - } dev_err(&mci->dev, "Failed to get 'vmmc' regulator.\n"); host->supply = NULL; } diff --git a/drivers/mci/sdhci.c b/drivers/mci/sdhci.c new file mode 100644 index 0000000000..172c8343a1 --- /dev/null +++ b/drivers/mci/sdhci.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <driver.h> +#include <mci.h> +#include <io.h> + +#include "sdhci.h" + +void sdhci_read_response(struct sdhci *sdhci, struct mci_cmd *cmd) +{ + if (cmd->resp_type & MMC_RSP_136) { + u32 cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; + + cmdrsp3 = sdhci_read32(sdhci, SDHCI_RESPONSE_3); + cmdrsp2 = sdhci_read32(sdhci, SDHCI_RESPONSE_2); + cmdrsp1 = sdhci_read32(sdhci, SDHCI_RESPONSE_1); + cmdrsp0 = sdhci_read32(sdhci, SDHCI_RESPONSE_0); + cmd->response[0] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); + cmd->response[1] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); + cmd->response[2] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); + cmd->response[3] = (cmdrsp0 << 8); + } else { + cmd->response[0] = sdhci_read32(sdhci, SDHCI_RESPONSE_0); + } +} + +void sdhci_set_cmd_xfer_mode(struct sdhci *host, struct mci_cmd *cmd, + struct mci_data *data, bool dma, u32 *command, + u32 *xfer) +{ + *command = 0; + *xfer = 0; + + if (!(cmd->resp_type & MMC_RSP_PRESENT)) + *command |= SDHCI_RESP_NONE; + else if (cmd->resp_type & MMC_RSP_136) + *command |= SDHCI_RESP_TYPE_136; + else if (cmd->resp_type & MMC_RSP_BUSY) + *command |= SDHCI_RESP_TYPE_48_BUSY; + else + *command |= SDHCI_RESP_TYPE_48; + + if (cmd->resp_type & MMC_RSP_CRC) + *command |= SDHCI_CMD_CRC_CHECK_EN; + if (cmd->resp_type & MMC_RSP_OPCODE) + *command |= SDHCI_CMD_INDEX_CHECK_EN; + + *command |= SDHCI_CMD_INDEX(cmd->cmdidx); + + if (data) { + *command |= SDHCI_DATA_PRESENT; + + *xfer |= SDHCI_BLOCK_COUNT_EN; + + if (data->blocks > 1) + *xfer |= SDHCI_MULTIPLE_BLOCKS; + + if (data->flags & MMC_DATA_READ) + *xfer |= SDHCI_DATA_TO_HOST; + + if (dma) + *xfer |= SDHCI_DMA_EN; + } +} + +static void sdhci_rx_pio(struct sdhci *sdhci, struct mci_data *data, + unsigned int block) +{ + u32 *buf = (u32 *)data->dest; + int i; + + buf += block * data->blocksize / sizeof(u32); + + for (i = 0; i < data->blocksize / sizeof(u32); i++) + buf[i] = sdhci_read32(sdhci, SDHCI_BUFFER); +} + +static void sdhci_tx_pio(struct sdhci *sdhci, struct mci_data *data, + unsigned int block) +{ + const u32 *buf = (const u32 *)data->src; + int i; + + buf += block * data->blocksize / sizeof(u32); + + for (i = 0; i < data->blocksize / sizeof(u32); i++) + sdhci_write32(sdhci, SDHCI_BUFFER, buf[i]); +} + +#ifdef __PBL__ +/* + * Stubs to make timeout logic below work in PBL + */ + +#define get_time_ns() 0 +/* + * Use time in us as a busy counter timeout value + */ +#define is_timeout(s, t) ((s)++ > ((t) / 1000)) + +#endif + +int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data) +{ + unsigned int block = 0; + u32 stat, prs; + uint64_t start = get_time_ns(); + + do { + stat = sdhci_read32(sdhci, SDHCI_INT_STATUS); + if (stat & SDHCI_INT_ERROR) + return -EIO; + + if (block >= data->blocks) + continue; + + prs = sdhci_read32(sdhci, SDHCI_PRESENT_STATE); + + if (prs & SDHCI_BUFFER_READ_ENABLE && + data->flags & MMC_DATA_READ) { + sdhci_rx_pio(sdhci, data, block); + block++; + start = get_time_ns(); + } + + if (prs & SDHCI_BUFFER_WRITE_ENABLE && + !(data->flags & MMC_DATA_READ)) { + sdhci_tx_pio(sdhci, data, block); + block++; + start = get_time_ns(); + } + + if (is_timeout(start, 10 * SECOND)) + return -ETIMEDOUT; + + } while (!(stat & SDHCI_INT_XFER_COMPLETE)); + + return 0; +} diff --git a/drivers/mci/sdhci.h b/drivers/mci/sdhci.h index 90595e6433..a307dc97cd 100644 --- a/drivers/mci/sdhci.h +++ b/drivers/mci/sdhci.h @@ -24,6 +24,9 @@ #define SDHCI_DMA_EN BIT(0) #define SDHCI_COMMAND 0x0e #define SDHCI_CMD_INDEX(c) (((c) & 0x3f) << 8) +#define SDHCI_COMMAND_CMDTYP_SUSPEND (1 << 6) +#define SDHCI_COMMAND_CMDTYP_RESUME (2 << 6) +#define SDHCI_COMMAND_CMDTYP_ABORT (3 << 6) #define SDHCI_DATA_PRESENT BIT(5) #define SDHCI_CMD_INDEX_CHECK_EN BIT(4) #define SDHCI_CMD_CRC_CHECK_EN BIT(3) @@ -37,11 +40,18 @@ #define SDHCI_RESPONSE_3 0x1c #define SDHCI_BUFFER 0x20 #define SDHCI_PRESENT_STATE 0x24 +#define SDHCI_WRITE_PROTECT BIT(19) +#define SDHCI_CARD_DETECT BIT(18) +#define SDHCI_BUFFER_READ_ENABLE BIT(11) +#define SDHCI_BUFFER_WRITE_ENABLE BIT(10) +#define SDHCI_DATA_LINE_ACTIVE BIT(2) #define SDHCI_CMD_INHIBIT_DATA BIT(1) #define SDHCI_CMD_INHIBIT_CMD BIT(0) #define SDHCI_PRESENT_STATE1 0x26 #define SDHCI_HOST_CONTROL__POWER_CONTROL__BLOCK_GAP_CONTROL 0x28 #define SDHCI_HOST_CONTROL 0x28 +#define SDHCI_CARD_DETECT_SIGNAL_SELECTION BIT(7) +#define SDHCI_CARD_DETECT_TEST_LEVEL BIT(6) #define SDHCI_DATA_WIDTH_8BIT BIT(5) #define SDHCI_HIGHSPEED_EN BIT(2) #define SDHCI_DATA_WIDTH_4BIT BIT(1) @@ -60,7 +70,17 @@ #define SDHCI_RESET_ALL BIT(0) #define SDHCI_INT_STATUS 0x30 #define SDHCI_INT_NORMAL_STATUS 0x30 +#define SDHCI_INT_DATA_END_BIT BIT(22) +#define SDHCI_INT_DATA_CRC BIT(21) +#define SDHCI_INT_DATA_TIMEOUT BIT(20) +#define SDHCI_INT_INDEX BIT(19) +#define SDHCI_INT_END_BIT BIT(18) +#define SDHCI_INT_CRC BIT(17) +#define SDHCI_INT_TIMEOUT BIT(16) #define SDHCI_INT_ERROR BIT(15) +#define SDHCI_INT_CARD_INT BIT(8) +#define SDHCI_INT_DATA_AVAIL BIT(5) +#define SDHCI_INT_SPACE_AVAIL BIT(4) #define SDHCI_INT_DMA BIT(3) #define SDHCI_INT_XFER_COMPLETE BIT(1) #define SDHCI_INT_CMD_COMPLETE BIT(0) @@ -79,74 +99,49 @@ #define SDHCI_SPEC_200_MAX_CLK_DIVIDER 256 #define SDHCI_MMC_BOOT 0xC4 -#define COMMAND_CMD(x) ((x & 0x3f) << 24) -#define COMMAND_CMDTYP_NORMAL 0x0 -#define COMMAND_CMDTYP_SUSPEND 0x00400000 -#define COMMAND_CMDTYP_RESUME 0x00800000 -#define COMMAND_CMDTYP_ABORT 0x00c00000 -#define COMMAND_DPSEL 0x00200000 -#define COMMAND_CICEN 0x00100000 -#define COMMAND_CCCEN 0x00080000 -#define COMMAND_RSPTYP_NONE 0 -#define COMMAND_RSPTYP_136 0x00010000 -#define COMMAND_RSPTYP_48 0x00020000 -#define COMMAND_RSPTYP_48_BUSY 0x00030000 -#define TRANSFER_MODE_MSBSEL 0x00000020 -#define TRANSFER_MODE_DTDSEL 0x00000010 -#define TRANSFER_MODE_AC12EN 0x00000004 -#define TRANSFER_MODE_BCEN 0x00000002 -#define TRANSFER_MODE_DMAEN 0x00000001 +struct sdhci { + u32 (*read32)(struct sdhci *host, int reg); + u16 (*read16)(struct sdhci *host, int reg); + u8 (*read8)(struct sdhci *host, int reg); + void (*write32)(struct sdhci *host, int reg, u32 val); + void (*write16)(struct sdhci *host, int reg, u16 val); + void (*write8)(struct sdhci *host, int reg, u8 val); +}; -#define IRQSTAT_TE 0x04000000 -#define IRQSTAT_DMAE 0x02000000 -#define IRQSTAT_AC12E 0x01000000 -#define IRQSTAT_CLE 0x00800000 -#define IRQSTAT_DEBE 0x00400000 -#define IRQSTAT_DCE 0x00200000 -#define IRQSTAT_DTOE 0x00100000 -#define IRQSTAT_CIE 0x00080000 -#define IRQSTAT_CEBE 0x00040000 -#define IRQSTAT_CCE 0x00020000 -#define IRQSTAT_CTOE 0x00010000 -#define IRQSTAT_CINT 0x00000100 -#define IRQSTAT_CRM 0x00000080 -#define IRQSTAT_CINS 0x00000040 -#define IRQSTAT_BRR 0x00000020 -#define IRQSTAT_BWR 0x00000010 -#define IRQSTAT_DINT 0x00000008 -#define IRQSTAT_BGE 0x00000004 -#define IRQSTAT_TC 0x00000002 -#define IRQSTAT_CC 0x00000001 +static inline u32 sdhci_read32(struct sdhci *host, int reg) +{ + return host->read32(host, reg); +} -#define IRQSTATEN_DMAE 0x10000000 -#define IRQSTATEN_AC12E 0x01000000 -#define IRQSTATEN_DEBE 0x00400000 -#define IRQSTATEN_DCE 0x00200000 -#define IRQSTATEN_DTOE 0x00100000 -#define IRQSTATEN_CIE 0x00080000 -#define IRQSTATEN_CEBE 0x00040000 -#define IRQSTATEN_CCE 0x00020000 -#define IRQSTATEN_CTOE 0x00010000 -#define IRQSTATEN_CINT 0x00000100 -#define IRQSTATEN_CRM 0x00000080 -#define IRQSTATEN_CINS 0x00000040 -#define IRQSTATEN_BRR 0x00000020 -#define IRQSTATEN_BWR 0x00000010 -#define IRQSTATEN_DINT 0x00000008 -#define IRQSTATEN_BGE 0x00000004 -#define IRQSTATEN_TC 0x00000002 -#define IRQSTATEN_CC 0x00000001 +static inline u32 sdhci_read16(struct sdhci *host, int reg) +{ + return host->read16(host, reg); +} -#define PRSSTAT_DAT0 0x01000000 -#define PRSSTAT_CLSL 0x00800000 -#define PRSSTAT_WPSPL 0x00080000 -#define PRSSTAT_CDPL 0x00040000 -#define PRSSTAT_CINS 0x00010000 -#define PRSSTAT_BREN 0x00000800 -#define PRSSTAT_BWEN 0x00000400 -#define PRSSTAT_SDSTB 0x00000008 -#define PRSSTAT_DLA 0x00000004 -#define PRSSTAT_CIDHB 0x00000002 -#define PRSSTAT_CICHB 0x00000001 +static inline u32 sdhci_read8(struct sdhci *host, int reg) +{ + return host->read8(host, reg); +} + +static inline void sdhci_write32(struct sdhci *host, int reg, u32 val) +{ + host->write32(host, reg, val); +} + +static inline void sdhci_write16(struct sdhci *host, int reg, u32 val) +{ + host->write16(host, reg, val); +} + +static inline void sdhci_write8(struct sdhci *host, int reg, u32 val) +{ + host->write8(host, reg, val); +} + +void sdhci_read_response(struct sdhci *host, struct mci_cmd *cmd); +void sdhci_set_cmd_xfer_mode(struct sdhci *host, struct mci_cmd *cmd, + struct mci_data *data, bool dma, u32 *command, + u32 *xfer); +int sdhci_transfer_data(struct sdhci *sdhci, struct mci_data *data); #endif /* __MCI_SDHCI_H */ diff --git a/drivers/mci/tegra-sdmmc.c b/drivers/mci/tegra-sdmmc.c index 4c47918076..1cc75dc524 100644 --- a/drivers/mci/tegra-sdmmc.c +++ b/drivers/mci/tegra-sdmmc.c @@ -74,9 +74,24 @@ struct tegra_sdmmc_host { struct clk *clk; struct reset_control *reset; int gpio_cd, gpio_pwr; + struct sdhci sdhci; }; #define to_tegra_sdmmc_host(mci) container_of(mci, struct tegra_sdmmc_host, mci) +static u32 tegra_sdmmc_read32(struct sdhci *sdhci, int reg) +{ + struct tegra_sdmmc_host *host = container_of(sdhci, struct tegra_sdmmc_host, sdhci); + + return readl(host->regs + reg); +} + +static void tegra_sdmmc_write32(struct sdhci *sdhci, int reg, u32 val) +{ + struct tegra_sdmmc_host *host = container_of(sdhci, struct tegra_sdmmc_host, sdhci); + + writel(val, host->regs + reg); +} + static int tegra_sdmmc_wait_inhibit(struct tegra_sdmmc_host *host, struct mci_cmd *cmd, struct mci_data *data, unsigned int timeout) @@ -91,7 +106,7 @@ static int tegra_sdmmc_wait_inhibit(struct tegra_sdmmc_host *host, val |= TEGRA_SDMMC_PRESENT_STATE_CMD_INHIBIT_DAT; wait_on_timeout(timeout * MSECOND, - !(readl(host->regs + TEGRA_SDMMC_PRESENT_STATE) & val)); + !(sdhci_read32(&host->sdhci, TEGRA_SDMMC_PRESENT_STATE) & val)); return 0; } @@ -101,7 +116,7 @@ static int tegra_sdmmc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, { struct tegra_sdmmc_host *host = to_tegra_sdmmc_host(mci); unsigned int num_bytes = 0; - u32 val = 0; + u32 val = 0, command, xfer; int ret; ret = tegra_sdmmc_wait_inhibit(host, cmd, data, 10); @@ -115,102 +130,66 @@ static int tegra_sdmmc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, if (data->flags & MMC_DATA_WRITE) { dma_sync_single_for_device((unsigned long)data->src, num_bytes, DMA_TO_DEVICE); - writel((u32)data->src, host->regs + SDHCI_DMA_ADDRESS); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, (u32)data->src); } else { dma_sync_single_for_device((unsigned long)data->dest, num_bytes, DMA_FROM_DEVICE); - writel((u32)data->dest, host->regs + SDHCI_DMA_ADDRESS); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, (u32)data->dest); } - writel((7 << 12) | data->blocks << 16 | data->blocksize, - host->regs + SDHCI_BLOCK_SIZE__BLOCK_COUNT); + sdhci_write32(&host->sdhci, SDHCI_BLOCK_SIZE__BLOCK_COUNT, + (7 << 12) | data->blocks << 16 | data->blocksize); } - writel(cmd->cmdarg, host->regs + SDHCI_ARGUMENT); + sdhci_write32(&host->sdhci, SDHCI_ARGUMENT, cmd->cmdarg); if ((cmd->resp_type & MMC_RSP_136) && (cmd->resp_type & MMC_RSP_BUSY)) return -1; - if (data) { - if (data->blocks > 1) - val |= TRANSFER_MODE_MSBSEL; - - if (data->flags & MMC_DATA_READ) - val |= TRANSFER_MODE_DTDSEL; - - val |= TRANSFER_MODE_DMAEN | TRANSFER_MODE_BCEN; - } - - if (!(cmd->resp_type & MMC_RSP_PRESENT)) - val |= COMMAND_RSPTYP_NONE; - else if (cmd->resp_type & MMC_RSP_136) - val |= COMMAND_RSPTYP_136; - else if (cmd->resp_type & MMC_RSP_BUSY) - val |= COMMAND_RSPTYP_48_BUSY; - else - val |= COMMAND_RSPTYP_48; - - if (cmd->resp_type & MMC_RSP_CRC) - val |= COMMAND_CCCEN; - if (cmd->resp_type & MMC_RSP_OPCODE) - val |= COMMAND_CICEN; + sdhci_set_cmd_xfer_mode(&host->sdhci, cmd, data, true, &command, &xfer); - if (data) - val |= COMMAND_DPSEL; - - writel(COMMAND_CMD(cmd->cmdidx) | val, - host->regs + SDHCI_TRANSFER_MODE__COMMAND); + sdhci_write32(&host->sdhci, SDHCI_TRANSFER_MODE__COMMAND, + command << 16 | xfer); ret = wait_on_timeout(100 * MSECOND, - (val = readl(host->regs + SDHCI_INT_STATUS)) - & IRQSTAT_CC); + (val = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS)) + & SDHCI_INT_CMD_COMPLETE); if (ret) { - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); return ret; } - if ((val & IRQSTAT_CC) && !data) - writel(val, host->regs + SDHCI_INT_STATUS); + if ((val & SDHCI_INT_CMD_COMPLETE) && !data) + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); if (val & TEGRA_SDMMC_INTERRUPT_STATUS_CMD_TIMEOUT) { /* Timeout Error */ dev_dbg(mci->hw_dev, "timeout: %08x cmd %d\n", val, cmd->cmdidx); - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); return -ETIMEDOUT; } else if (val & TEGRA_SDMMC_INTERRUPT_STATUS_ERR_INTERRUPT) { /* Error Interrupt */ dev_dbg(mci->hw_dev, "error: %08x cmd %d\n", val, cmd->cmdidx); - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); return -EIO; } if (cmd->resp_type & MMC_RSP_PRESENT) { - if (cmd->resp_type & MMC_RSP_136) { - u32 cmdrsp[4]; - - cmdrsp[3] = readl(host->regs + SDHCI_RESPONSE_3); - cmdrsp[2] = readl(host->regs + SDHCI_RESPONSE_2); - cmdrsp[1] = readl(host->regs + SDHCI_RESPONSE_1); - cmdrsp[0] = readl(host->regs + SDHCI_RESPONSE_0); - cmd->response[0] = (cmdrsp[3] << 8) | (cmdrsp[2] >> 24); - cmd->response[1] = (cmdrsp[2] << 8) | (cmdrsp[1] >> 24); - cmd->response[2] = (cmdrsp[1] << 8) | (cmdrsp[0] >> 24); - cmd->response[3] = (cmdrsp[0] << 8); - } else if (cmd->resp_type & MMC_RSP_BUSY) { + sdhci_read_response(&host->sdhci, cmd); + + if (cmd->resp_type & MMC_RSP_BUSY) { ret = wait_on_timeout(100 * MSECOND, - readl(host->regs + TEGRA_SDMMC_PRESENT_STATE) + sdhci_read32(&host->sdhci, TEGRA_SDMMC_PRESENT_STATE) & (1 << 20)); if (ret) { dev_err(mci->hw_dev, "card is still busy\n"); - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); return ret; } - cmd->response[0] = readl(host->regs + SDHCI_RESPONSE_0); - } else { - cmd->response[0] = readl(host->regs + SDHCI_RESPONSE_0); + cmd->response[0] = sdhci_read32(&host->sdhci, SDHCI_RESPONSE_0); } } @@ -218,15 +197,15 @@ static int tegra_sdmmc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, uint64_t start = get_time_ns(); while (1) { - val = readl(host->regs + SDHCI_INT_STATUS); + val = sdhci_read32(&host->sdhci, SDHCI_INT_STATUS); if (val & TEGRA_SDMMC_INTERRUPT_STATUS_ERR_INTERRUPT) { /* Error Interrupt */ - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); dev_err(mci->hw_dev, "error during transfer: 0x%08x\n", val); return -EIO; - } else if (val & IRQSTAT_DINT) { + } else if (val & SDHCI_INT_DMA) { /* * DMA Interrupt, restart the transfer where * it was interrupted. @@ -234,27 +213,26 @@ static int tegra_sdmmc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, u32 address = readl(host->regs + SDHCI_DMA_ADDRESS); - writel(IRQSTAT_DINT, - host->regs + SDHCI_INT_STATUS); - writel(address, host->regs + SDHCI_DMA_ADDRESS); - } else if (val & IRQSTAT_TC) { + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, SDHCI_INT_DMA); + sdhci_write32(&host->sdhci, SDHCI_DMA_ADDRESS, address); + } else if (val & SDHCI_INT_XFER_COMPLETE) { /* Transfer Complete */; break; } else if (is_timeout(start, 2 * SECOND)) { - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); dev_err(mci->hw_dev, "MMC Timeout\n" " Interrupt status 0x%08x\n" " Interrupt status enable 0x%08x\n" " Interrupt signal enable 0x%08x\n" " Present status 0x%08x\n", val, - readl(host->regs + SDHCI_INT_ENABLE), - readl(host->regs + SDHCI_SIGNAL_ENABLE), - readl(host->regs + SDHCI_PRESENT_STATE)); + sdhci_read32(&host->sdhci, SDHCI_INT_ENABLE), + sdhci_read32(&host->sdhci, SDHCI_SIGNAL_ENABLE), + sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE)); return -ETIMEDOUT; } } - writel(val, host->regs + SDHCI_INT_STATUS); + sdhci_write32(&host->sdhci, SDHCI_INT_STATUS, val); if (data->flags & MMC_DATA_WRITE) dma_sync_single_for_cpu((unsigned long)data->src, @@ -277,25 +255,25 @@ static void tegra_sdmmc_set_clock(struct tegra_sdmmc_host *host, u32 clock) } /* clear clock related bits */ - val = readl(host->regs + TEGRA_SDMMC_CLK_CNTL); + val = sdhci_read32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL); val &= 0xffff0000; - writel(val, host->regs + TEGRA_SDMMC_CLK_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL, val); /* set new frequency */ val |= prediv << 8; val |= TEGRA_SDMMC_CLK_CNTL_INTERNAL_CLOCK_EN; - writel(val, host->regs + TEGRA_SDMMC_CLK_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL, val); clk_set_rate(host->clk, adjusted_clock); /* wait for controller to settle */ wait_on_timeout(10 * MSECOND, - !(readl(host->regs + TEGRA_SDMMC_CLK_CNTL) & + !(sdhci_read32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL) & TEGRA_SDMMC_CLK_INTERNAL_CLOCK_STABLE)); /* enable card clock */ val |= TEGRA_SDMMC_CLK_CNTL_SD_CLOCK_EN; - writel(val, host->regs + TEGRA_SDMMC_CLK_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL, val); } static void tegra_sdmmc_set_ios(struct mci_host *mci, struct mci_ios *ios) @@ -308,7 +286,7 @@ static void tegra_sdmmc_set_ios(struct mci_host *mci, struct mci_ios *ios) tegra_sdmmc_set_clock(host, ios->clock); /* set bus width */ - val = readl(host->regs + TEGRA_SDMMC_PWR_CNTL); + val = sdhci_read32(&host->sdhci, TEGRA_SDMMC_PWR_CNTL); val &= ~(0x21); if (ios->bus_width == MMC_BUS_WIDTH_8) @@ -316,7 +294,7 @@ static void tegra_sdmmc_set_ios(struct mci_host *mci, struct mci_ios *ios) else if (ios->bus_width == MMC_BUS_WIDTH_4) val |= (1 << 1); - writel(val, host->regs + TEGRA_SDMMC_PWR_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_PWR_CNTL, val); } static int tegra_sdmmc_init(struct mci_host *mci, struct device_d *dev) @@ -327,8 +305,8 @@ static int tegra_sdmmc_init(struct mci_host *mci, struct device_d *dev) int ret; /* reset controller */ - writel(TEGRA_SDMMC_CLK_CNTL_SW_RESET_FOR_ALL, - regs + TEGRA_SDMMC_CLK_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL, + TEGRA_SDMMC_CLK_CNTL_SW_RESET_FOR_ALL); ret = wait_on_timeout(100 * MSECOND, !(readl(regs + TEGRA_SDMMC_CLK_CNTL) & @@ -342,7 +320,7 @@ static int tegra_sdmmc_init(struct mci_host *mci, struct device_d *dev) val = readl(regs + TEGRA_SDMMC_PWR_CNTL); val &= ~(0xff << 8); val |= TEGRA_SDMMC_PWR_CNTL_33_V | TEGRA_SDMMC_PWR_CNTL_SD_BUS; - writel(val, regs + TEGRA_SDMMC_PWR_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_PWR_CNTL, val); /* sdmmc1 and sdmmc3 on T30 need a bit of padctrl init */ if (of_device_is_compatible(mci->hw_dev->device_node, @@ -351,21 +329,21 @@ static int tegra_sdmmc_init(struct mci_host *mci, struct device_d *dev) val = readl(regs + TEGRA_SDMMC_SDMEMCOMPPADCTRL); val &= 0xfffffff0; val |= 0x7 << TEGRA_SDMMC_SDMEMCOMPPADCTRL_VREF_SEL_SHIFT; - writel(val, regs + TEGRA_SDMMC_SDMEMCOMPPADCTRL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_SDMEMCOMPPADCTRL, val); val = readl(regs + TEGRA_SDMMC_AUTO_CAL_CONFIG); val &= 0xffff0000; val |= (0x62 << TEGRA_SDMMC_AUTO_CAL_CONFIG_PU_OFFSET_SHIFT) | (0x70 << TEGRA_SDMMC_AUTO_CAL_CONFIG_PD_OFFSET_SHIFT) | TEGRA_SDMMC_AUTO_CAL_CONFIG_ENABLE; - writel(val, regs + TEGRA_SDMMC_AUTO_CAL_CONFIG); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_AUTO_CAL_CONFIG, val); } /* setup signaling */ - writel(0xffffffff, regs + TEGRA_SDMMC_INT_STAT_EN); - writel(0xffffffff, regs + TEGRA_SDMMC_INT_SIG_EN); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_INT_STAT_EN, 0xffffffff); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_INT_SIG_EN, 0xffffffff); - writel(0xe << 16, regs + TEGRA_SDMMC_CLK_CNTL); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_CLK_CNTL, 0xe << 16); val = readl(regs + TEGRA_SDMMC_INT_STAT_EN); val &= ~(0xffff); @@ -374,12 +352,12 @@ static int tegra_sdmmc_init(struct mci_host *mci, struct device_d *dev) TEGRA_SDMMC_INT_STAT_EN_DMA_INTERRUPT | TEGRA_SDMMC_INT_STAT_EN_BUFFER_WRITE_READY | TEGRA_SDMMC_INT_STAT_EN_BUFFER_READ_READY); - writel(val, regs + TEGRA_SDMMC_INT_STAT_EN); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_INT_STAT_EN, val); val = readl(regs + TEGRA_SDMMC_INT_SIG_EN); val &= ~(0xffff); val |= TEGRA_SDMMC_INT_SIG_EN_XFER_COMPLETE; - writel(val, regs + TEGRA_SDMMC_INT_SIG_EN); + sdhci_write32(&host->sdhci, TEGRA_SDMMC_INT_SIG_EN, val); tegra_sdmmc_set_clock(host, 400000); @@ -398,7 +376,7 @@ static int tegra_sdmmc_card_present(struct mci_host *mci) return gpio_get_value(host->gpio_cd) ? 0 : 1; } - return !(readl(host->regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL); + return !(sdhci_read32(&host->sdhci, SDHCI_PRESENT_STATE) & SDHCI_WRITE_PROTECT); } static int tegra_sdmmc_detect(struct device_d *dev) @@ -442,6 +420,9 @@ static int tegra_sdmmc_probe(struct device_d *dev) } host->regs = IOMEM(iores->start); + host->sdhci.read32 = tegra_sdmmc_read32; + host->sdhci.write32 = tegra_sdmmc_write32; + mci->hw_dev = dev; mci->f_max = 48000000; mci->f_min = 375000; diff --git a/drivers/mfd/da9053.c b/drivers/mfd/da9053.c index 1faba813be..1f32869038 100644 --- a/drivers/mfd/da9053.c +++ b/drivers/mfd/da9053.c @@ -235,7 +235,7 @@ static void da9053_detect_reset_source(struct da9053_priv *da9053) else return; - reset_source_set_device(da9053->dev, ltype); + reset_source_set_device(da9053->dev, type); ret = da9053_reg_write(da9053, DA9053_FAULTLOG_REG, val); if (ret < 0) @@ -271,7 +271,6 @@ static int da9053_probe(struct device_d *dev) da9053->dev = dev; da9053->client = to_i2c_client(dev); da9053->wd.set_timeout = da9053_set_timeout; - da9053->wd.priority = of_get_watchdog_priority(dev->device_node); da9053->wd.hwdev = dev; ret = da9053_enable_multiwrite(da9053); diff --git a/drivers/mfd/da9063.c b/drivers/mfd/da9063.c index e1343bac76..e48c38affa 100644 --- a/drivers/mfd/da9063.c +++ b/drivers/mfd/da9063.c @@ -377,7 +377,6 @@ static int da9063_probe(struct device_d *dev) dev_data = ret < 0 ? NULL : dev_data_tmp; priv = xzalloc(sizeof(struct da9063)); - priv->wd.priority = of_get_watchdog_priority(dev->device_node); priv->wd.set_timeout = da9063_watchdog_set_timeout; priv->wd.hwdev = dev; priv->timeout = DA9063_INITIAL_TIMEOUT; @@ -402,13 +401,15 @@ static int da9063_probe(struct device_d *dev) restart_handler_register(&priv->restart); - priv->gpio.base = -1; - priv->gpio.ngpio = 5; - priv->gpio.ops = &da9063_gpio_ops; - priv->gpio.dev = dev; - ret = gpiochip_add(&priv->gpio); - if (ret) - goto on_error; + if (IS_ENABLED(CONFIG_GPIOLIB)) { + priv->gpio.base = -1; + priv->gpio.ngpio = 5; + priv->gpio.ops = &da9063_gpio_ops; + priv->gpio.dev = dev; + ret = gpiochip_add(&priv->gpio); + if (ret) + goto on_error; + } if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) return of_platform_populate(dev->device_node, NULL, dev); diff --git a/drivers/mfd/stpmic1.c b/drivers/mfd/stpmic1.c index eae6fe3a4e..ab13ded0ec 100644 --- a/drivers/mfd/stpmic1.c +++ b/drivers/mfd/stpmic1.c @@ -12,8 +12,7 @@ #include <of.h> #include <regmap.h> #include <xfuncs.h> - -#define VERSION_SR 0x6 +#include <linux/mfd/stpmic1.h> struct stpmic1 { struct device_d *dev; diff --git a/drivers/mfd/superio.c b/drivers/mfd/superio.c index 12d74b40f6..ab94a4fa8f 100644 --- a/drivers/mfd/superio.c +++ b/drivers/mfd/superio.c @@ -24,7 +24,7 @@ struct device_d *superio_func_add(struct superio_chip *siochip, const char *name return dev; } -EXPORT_SYMBOL(superio_func_add) +EXPORT_SYMBOL(superio_func_add); static int superio_reg_read(void *ctx, unsigned int reg, unsigned int *val) { @@ -95,4 +95,4 @@ void superio_chip_add(struct superio_chip *siochip) pr_warn("registering %s regmap cdev failed: %s\n", chipname, strerror(-ret)); } -EXPORT_SYMBOL(superio_chip_add) +EXPORT_SYMBOL(superio_chip_add); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 0f736f8bde..87674a2a29 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -25,6 +25,7 @@ config DEV_MEM config UBOOTVAR bool "U-Boot environment storage" + depends on OFTREE help This driver exposes U-Boot environment variable storage as a single mmap-able device, hiding various low-level details @@ -35,4 +36,10 @@ config UBOOTVAR While it can be used standalone, it is best when coupled with corresponding filesystem driver. +config ACPI_TEST + bool "ACPI Test driver" + depends on ACPI + help + This is a simple Test driver to test the ACPI bus. + endmenu diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index bc1c01ea4d..4d92465a1e 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -7,3 +7,4 @@ obj-$(CONFIG_SRAM) += sram.o obj-$(CONFIG_STATE_DRV) += state.o obj-$(CONFIG_DEV_MEM) += mem.o obj-$(CONFIG_UBOOTVAR) += ubootvar.o +obj-$(CONFIG_ACPI_TEST) += acpi-test.o diff --git a/drivers/misc/acpi-test.c b/drivers/misc/acpi-test.c new file mode 100644 index 0000000000..970b435a0e --- /dev/null +++ b/drivers/misc/acpi-test.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Ahmad Fatoum + */ + +#include <common.h> +#include <init.h> +#include <acpi.h> + +static const char *profiles[] = { + "Unspecified", + "Desktop", + "Mobile", + "Workstation", + "Enterprise Server", + "SOHO Server", + "Applicance PC", + "Performance Server", + "Tablet", +}; + +static int acpi_test_probe(struct device_d *dev) +{ + const char *profile = "reserved"; + u8 *sdt; + u8 profileno; + + dev_dbg(dev, "driver initializing...\n"); + + sdt = (u8 __force *)dev_request_mem_region_by_name(dev, "SDT"); + if (IS_ERR(sdt)) { + dev_err(dev, "no SDT resource available: %s\n", strerrorp(sdt)); + return PTR_ERR(sdt); + } + + dev_dbg(dev, "SDT is at 0x%p\n", sdt); + + profileno = sdt[45]; + + if (profileno < ARRAY_SIZE(profiles)) + profile = profiles[profileno]; + + dev_info(dev, "PM profile is for '%s'\n", profile); + + return 0; +} + +static void acpi_test_remove(struct device_d *dev) +{ + dev_info(dev, "FADT driver removed\n"); +} + +static struct acpi_driver acpi_test_driver = { + .signature = "FACP", + .driver = { + .name = "acpi-test", + .probe = acpi_test_probe, + .remove = acpi_test_remove, + } +}; +device_acpi_driver(acpi_test_driver); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 6b7d01919c..00f0f75884 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -407,7 +407,7 @@ static int nand_block_markbad_lowlevel(struct mtd_info *mtd, loff_t ofs) } /* Mark block bad in BBT */ - if (chip->bbt) { + if (IS_ENABLED(CONFIG_NAND_BBT) && chip->bbt) { res = nand_markbad_bbt(mtd, ofs); if (!ret) ret = res; @@ -458,7 +458,7 @@ static int nand_block_markgood_lowlevel(struct mtd_info *mtd, loff_t ofs) } /* Mark block good in BBT */ - if (chip->bbt) { + if (IS_ENABLED(CONFIG_NAND_BBT) && chip->bbt) { ret = nand_markgood_bbt(mtd, ofs); if (ret) return ret; diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index b251035982..1e1b69626a 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -677,6 +677,8 @@ static const struct spi_device_id spi_nor_ids[] = { SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp016d", INFO(0x9d6015, 0, 64 * 1024, 32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, + { "is25lp01g", INFO(0x9d601b, 0, 64 * 1024, 2048, + SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp080d", INFO(0x9d6014, 0, 64 * 1024, 16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, { "is25lp032", INFO(0x9d6016, 0, 64 * 1024, 64, diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 62e522a302..5823320b03 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -90,8 +90,9 @@ endif config DRIVER_NET_DESIGNWARE_EQOS bool "Designware Designware Ethernet QoS support" depends on HAS_DMA + depends on COMMON_CLK + depends on OFTREE select PHYLIB - select OFTREE help This option enables support for the Synopsys Designware Ethernet Quality-of-Service (GMAC4). diff --git a/drivers/net/designware_eqos.c b/drivers/net/designware_eqos.c index a49239e057..da67adf9a0 100644 --- a/drivers/net/designware_eqos.c +++ b/drivers/net/designware_eqos.c @@ -204,7 +204,7 @@ static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO not idle at entry\n"); + dev_err(&bus->dev, "MDIO not idle at entry\n"); return ret; } @@ -222,7 +222,7 @@ static int eqos_mdio_read(struct mii_bus *bus, int addr, int reg) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO read didn't complete\n"); + dev_err(&bus->dev, "MDIO read didn't complete\n"); return ret; } @@ -237,7 +237,7 @@ static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO not idle at entry\n"); + dev_err(&bus->dev, "MDIO not idle at entry\n"); return ret; } @@ -256,7 +256,7 @@ static int eqos_mdio_write(struct mii_bus *bus, int addr, int reg, u16 val) ret = eqos_mdio_wait_idle(eqos); if (ret) { - eqos_err(eqos, "MDIO read didn't complete\n"); + dev_err(&bus->dev, "MDIO read didn't complete\n"); return ret; } @@ -365,7 +365,7 @@ static int phy_resume(struct phy_device *phydev) return 0; } -int eqos_start(struct eth_device *edev) +static int eqos_start(struct eth_device *edev) { struct eqos *eqos = edev->priv; u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl; @@ -611,7 +611,7 @@ int eqos_start(struct eth_device *edev) return 0; } -void eqos_stop(struct eth_device *edev) +static void eqos_stop(struct eth_device *edev) { struct eqos *eqos = edev->priv; int i; @@ -841,10 +841,10 @@ int eqos_probe(struct device_d *dev, const struct eqos_ops *ops, void *priv) dev->priv = edev->priv = eqos; edev->parent = dev; - edev->open = ops->start; + edev->open = eqos_start; edev->send = eqos_send; edev->recv = eqos_recv; - edev->halt = ops->stop; + edev->halt = eqos_stop; edev->get_ethaddr = ops->get_ethaddr; edev->set_ethaddr = ops->set_ethaddr; @@ -869,6 +869,8 @@ void eqos_remove(struct device_d *dev) { struct eqos *eqos = dev->priv; + eth_unregister(&eqos->netdev); + mdiobus_unregister(&eqos->miibus); dma_free(phys_to_virt(eqos->rx_descs[0].des0)); diff --git a/drivers/net/designware_eqos.h b/drivers/net/designware_eqos.h index 969a524c0a..f794195db4 100644 --- a/drivers/net/designware_eqos.h +++ b/drivers/net/designware_eqos.h @@ -11,8 +11,6 @@ struct eth_device; struct eqos_ops { int (*init)(struct device_d *dev, struct eqos *priv); - int (*start)(struct eth_device *edev); - void (*stop)(struct eth_device *edev); int (*get_ethaddr)(struct eth_device *dev, unsigned char *mac); int (*set_ethaddr)(struct eth_device *edev, const unsigned char *mac); void (*adjust_link)(struct eth_device *edev); @@ -73,8 +71,6 @@ int eqos_reset(struct eqos *priv); int eqos_get_ethaddr(struct eth_device *edev, unsigned char *mac); int eqos_set_ethaddr(struct eth_device *edev, const unsigned char *mac); -int eqos_start(struct eth_device *edev); -void eqos_stop(struct eth_device *edev); void eqos_adjust_link(struct eth_device *edev); #define eqos_dbg(eqos, ...) dev_dbg(&eqos->netdev.dev, __VA_ARGS__) diff --git a/drivers/net/designware_stm32.c b/drivers/net/designware_stm32.c index 5b087ad5a3..4c682a5dac 100644 --- a/drivers/net/designware_stm32.c +++ b/drivers/net/designware_stm32.c @@ -164,16 +164,6 @@ static int eqos_init_stm32(struct device_d *dev, struct eqos *eqos) dev_dbg(dev, "No phy clock provided. Continuing without.\n"); } - return 0; - -} - -static int eqos_start_stm32(struct eth_device *edev) -{ - struct eqos *eqos = edev->priv; - struct eqos_stm32 *priv = to_stm32(eqos); - int ret; - ret = clk_bulk_enable(priv->num_clks, priv->clks); if (ret < 0) { eqos_err(eqos, "clk_bulk_enable() failed: %s\n", @@ -181,34 +171,13 @@ static int eqos_start_stm32(struct eth_device *edev) return ret; } - udelay(10); - - ret = eqos_start(edev); - if (ret) - goto err_stop_clks; - return 0; - -err_stop_clks: - clk_bulk_disable(priv->num_clks, priv->clks); - - return ret; -} - -static void eqos_stop_stm32(struct eth_device *edev) -{ - struct eqos_stm32 *priv = to_stm32(edev->priv); - - clk_bulk_disable(priv->num_clks, priv->clks); } -// todo split! static struct eqos_ops stm32_ops = { .init = eqos_init_stm32, .get_ethaddr = eqos_get_ethaddr, .set_ethaddr = eqos_set_ethaddr, - .start = eqos_start_stm32, - .stop = eqos_stop_stm32, .adjust_link = eqos_adjust_link, .get_csr_clk_rate = eqos_get_csr_clk_rate_stm32, @@ -228,6 +197,7 @@ static void eqos_remove_stm32(struct device_d *dev) eqos_remove(dev); + clk_bulk_disable(priv->num_clks, priv->clks); clk_bulk_put(priv->num_clks, priv->clks); } diff --git a/drivers/net/designware_tegra186.c b/drivers/net/designware_tegra186.c index 58484d4095..20521db1c7 100644 --- a/drivers/net/designware_tegra186.c +++ b/drivers/net/designware_tegra186.c @@ -230,29 +230,16 @@ static int eqos_init_tegra186(struct device_d *dev, struct eqos *eqos) priv->clks = xmemdup(tegra186_clks, sizeof(tegra186_clks)); priv->num_clks = ARRAY_SIZE(tegra186_clks); - return 0; - -release_res: - reset_control_put(priv->rst); - return ret; -} - -static int eqos_start_tegra186(struct eth_device *edev) -{ - struct eqos *eqos = edev->priv; - struct eqos_tegra186 *priv = to_tegra186(eqos); - int ret; - ret = clk_bulk_enable(priv->num_clks, priv->clks); if (ret < 0) { eqos_err(eqos, "clk_bulk_enable() failed: %s\n", strerror(-ret)); - return ret; + goto release_res; } ret = eqos_clks_set_rate_tegra186(priv); if (ret < 0) { eqos_err(eqos, "clks_set_rate() failed: %s\n", strerror(-ret)); - goto err; + goto err_stop_clks; } eqos_reset_tegra186(priv, false); @@ -261,30 +248,14 @@ static int eqos_start_tegra186(struct eth_device *edev) goto err_stop_clks; } - udelay(10); - - ret = eqos_start(edev); - if (ret) - goto err_stop_resets; - return 0; -err_stop_resets: - eqos_reset_tegra186(priv, true); err_stop_clks: clk_bulk_disable(priv->num_clks, priv->clks); -err: - return ret; -} - - -static void eqos_stop_tegra186(struct eth_device *edev) -{ - struct eqos_tegra186 *priv = to_tegra186(edev->priv); - - eqos_reset_tegra186(priv, true); +release_res: + reset_control_put(priv->rst); - clk_bulk_disable(priv->num_clks, priv->clks); + return ret; } static void eqos_adjust_link_tegra186(struct eth_device *edev) @@ -306,8 +277,6 @@ static const struct eqos_ops tegra186_ops = { .init = eqos_init_tegra186, .get_ethaddr = eqos_get_ethaddr, .set_ethaddr = eqos_set_ethaddr_tegra186, - .start = eqos_start_tegra186, - .stop = eqos_stop_tegra186, .adjust_link = eqos_adjust_link_tegra186, .get_csr_clk_rate = eqos_get_csr_clk_rate_tegra186, @@ -327,6 +296,10 @@ static void eqos_remove_tegra186(struct device_d *dev) eqos_remove(dev); + eqos_reset_tegra186(priv, true); + + clk_bulk_disable(priv->num_clks, priv->clks); + clk_bulk_put(priv->num_clks, priv->clks); gpio_free(priv->phy_reset_gpio); diff --git a/drivers/net/fsl-fman.c b/drivers/net/fsl-fman.c index 4e6bb2ecfd..1aae58e494 100644 --- a/drivers/net/fsl-fman.c +++ b/drivers/net/fsl-fman.c @@ -104,11 +104,11 @@ struct fm_eth { struct device_d *dev; struct fm_port_global_pram *rx_pram; /* Rx parameter table */ struct fm_port_global_pram *tx_pram; /* Tx parameter table */ - void *rx_bd_ring; /* Rx BD ring base */ - void *cur_rxbd; /* current Rx BD */ + struct fm_port_bd *rx_bd_ring; /* Rx BD ring base */ + int cur_rxbd_idx; /* current Rx BD index */ void *rx_buf; /* Rx buffer base */ - void *tx_bd_ring; /* Tx BD ring base */ - void *cur_txbd; /* current Tx BD */ + struct fm_port_bd *tx_bd_ring; /* Tx BD ring base */ + int cur_txbd_idx; /* current Tx BD index */ struct memac *regs; }; @@ -628,12 +628,13 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) /* save them to fm_eth */ fm_eth->rx_bd_ring = rx_bd_ring_base; - fm_eth->cur_rxbd = rx_bd_ring_base; + fm_eth->cur_rxbd_idx = 0; fm_eth->rx_buf = rx_buf_pool; /* init Rx BDs ring */ - rxbd = rx_bd_ring_base; for (i = 0; i < RX_BD_RING_SIZE; i++) { + rxbd = &fm_eth->rx_bd_ring[i]; + muram_writew(&rxbd->status, RxBD_EMPTY); muram_writew(&rxbd->len, 0); buf_hi = upper_32_bits(virt_to_phys(rx_buf_pool + @@ -644,7 +645,6 @@ static int fm_eth_rx_port_parameter_init(struct fm_eth *fm_eth) MAX_RXBUF_LEN, DMA_FROM_DEVICE); muram_writew(&rxbd->buf_ptr_hi, (u16)buf_hi); out_be32(&rxbd->buf_ptr_lo, buf_lo); - rxbd++; } /* set the Rx queue descriptor */ @@ -702,16 +702,16 @@ static int fm_eth_tx_port_parameter_init(struct fm_eth *fm_eth) * TX_BD_RING_SIZE); /* save it to fm_eth */ fm_eth->tx_bd_ring = tx_bd_ring_base; - fm_eth->cur_txbd = tx_bd_ring_base; + fm_eth->cur_txbd_idx = 0; /* init Tx BDs ring */ - txbd = tx_bd_ring_base; for (i = 0; i < TX_BD_RING_SIZE; i++) { + txbd = &fm_eth->tx_bd_ring[i]; + muram_writew(&txbd->status, TxBD_LAST); muram_writew(&txbd->len, 0); muram_writew(&txbd->buf_ptr_hi, 0); out_be32(&txbd->buf_ptr_lo, 0); - txbd++; } /* set the Tx queue decriptor */ @@ -834,13 +834,12 @@ static int fm_eth_send(struct eth_device *edev, void *buf, int len) { struct fm_eth *fm_eth = to_fm_eth(edev); struct fm_port_global_pram *pram; - struct fm_port_bd *txbd, *txbd_base; - u16 offset_in; - int i; + struct fm_port_bd *txbd; + int i, ret; dma_addr_t dma; pram = fm_eth->tx_pram; - txbd = fm_eth->cur_txbd; + txbd = &fm_eth->tx_bd_ring[fm_eth->cur_txbd_idx]; /* find one empty TxBD */ for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { @@ -862,41 +861,35 @@ static int fm_eth_send(struct eth_device *edev, void *buf, int len) muram_writew(&txbd->len, len); muram_writew(&txbd->status, TxBD_READY | TxBD_LAST); + /* advance the TxBD */ + fm_eth->cur_txbd_idx = (fm_eth->cur_txbd_idx + 1) % TX_BD_RING_SIZE; + /* update TxQD, let RISC to send the packet */ - offset_in = muram_readw(&pram->txqd.offset_in); - offset_in += sizeof(struct fm_port_bd); - if (offset_in >= muram_readw(&pram->txqd.bd_ring_size)) - offset_in = 0; - muram_writew(&pram->txqd.offset_in, offset_in); + muram_writew(&pram->txqd.offset_in, + fm_eth->cur_txbd_idx * sizeof(struct fm_port_bd)); /* wait for buffer to be transmitted */ + ret = 0; for (i = 0; muram_readw(&txbd->status) & TxBD_READY; i++) { udelay(10); if (i > 0x10000) { dev_err(&edev->dev, "Tx error, txbd->status = 0x%x\n", muram_readw(&txbd->status)); - return -EIO; + ret = -EIO; + break; } } dma_unmap_single(fm_eth->dev, dma, len, DMA_TO_DEVICE); - /* advance the TxBD */ - txbd++; - txbd_base = fm_eth->tx_bd_ring; - if (txbd >= (txbd_base + TX_BD_RING_SIZE)) - txbd = txbd_base; - /* update current txbd */ - fm_eth->cur_txbd = (void *)txbd; - - return 0; + return ret; } static int fm_eth_recv(struct eth_device *edev) { struct fm_eth *fm_eth = to_fm_eth(edev); struct fm_port_global_pram *pram; - struct fm_port_bd *rxbd, *rxbd_base; + struct fm_port_bd *rxbd; u16 status, len; u32 buf_lo, buf_hi; u8 *data; @@ -904,10 +897,14 @@ static int fm_eth_recv(struct eth_device *edev) int ret = 1; pram = fm_eth->rx_pram; - rxbd = fm_eth->cur_rxbd; - status = muram_readw(&rxbd->status); - while (!(status & RxBD_EMPTY)) { + while (1) { + rxbd = &fm_eth->rx_bd_ring[fm_eth->cur_rxbd_idx]; + + status = muram_readw(&rxbd->status); + if (status & RxBD_EMPTY) + break; + if (!(status & RxBD_ERROR)) { buf_hi = muram_readw(&rxbd->buf_ptr_hi); buf_lo = in_be32(&rxbd->buf_ptr_lo); @@ -933,12 +930,7 @@ static int fm_eth_recv(struct eth_device *edev) muram_writew(&rxbd->len, 0); /* advance RxBD */ - rxbd++; - rxbd_base = fm_eth->rx_bd_ring; - if (rxbd >= (rxbd_base + RX_BD_RING_SIZE)) - rxbd = rxbd_base; - /* read next status */ - status = muram_readw(&rxbd->status); + fm_eth->cur_rxbd_idx = (fm_eth->cur_rxbd_idx + 1) % RX_BD_RING_SIZE; /* update RxQD */ offset_out = muram_readw(&pram->rxqd.offset_out); @@ -947,7 +939,6 @@ static int fm_eth_recv(struct eth_device *edev) offset_out = 0; muram_writew(&pram->rxqd.offset_out, offset_out); } - fm_eth->cur_rxbd = rxbd; return ret; } @@ -1175,6 +1166,8 @@ static int fsl_fman_memac_probe(struct device_d *dev) /* alloc the FMan ethernet private struct */ fm_eth = xzalloc(sizeof(*fm_eth)); + dev->priv = fm_eth; + fm_eth->dev = dev; ret = fsl_fman_memac_port_bind(fm_eth, FMAN_PORT_TYPE_TX); @@ -1216,6 +1209,13 @@ static int fsl_fman_memac_probe(struct device_d *dev) return 0; } +static void fsl_fman_memac_remove(struct device_d *dev) +{ + struct fm_eth *fm_eth = dev->priv; + + fm_eth_halt(&fm_eth->edev); +} + static int fsl_fman_muram_probe(struct device_d *dev) { struct resource *iores; @@ -1274,6 +1274,7 @@ static struct of_device_id fsl_fman_memac_dt_ids[] = { static struct driver_d fman_memac_driver = { .name = "fsl-fman-memac", .probe = fsl_fman_memac_probe, + .remove = fsl_fman_memac_remove, .of_compatible = DRV_OF_COMPAT(fsl_fman_memac_dt_ids), }; @@ -1303,6 +1304,7 @@ static int fsl_fman_probe(struct device_d *dev) return PTR_ERR(iores); reg = IOMEM(iores->start); + dev->priv = reg; ret = of_platform_populate(dev->device_node, NULL, dev); if (ret) @@ -1320,6 +1322,13 @@ static int fsl_fman_probe(struct device_d *dev) return 0; } +static void fsl_fman_remove(struct device_d *dev) +{ + struct ccsr_fman *reg = dev->priv; + + setbits_be32(®->fm_fpm.fmrstc, FMFP_RSTC_RFM); +} + static struct of_device_id fsl_fman_dt_ids[] = { { .compatible = "fsl,fman", @@ -1330,6 +1339,45 @@ static struct of_device_id fsl_fman_dt_ids[] = { static struct driver_d fman_driver = { .name = "fsl-fman", .probe = fsl_fman_probe, + .remove = fsl_fman_remove, .of_compatible = DRV_OF_COMPAT(fsl_fman_dt_ids), }; device_platform_driver(fman_driver); + +static int fman_of_fixup(struct device_node *root, void *context) +{ + struct device_node *fman, *fman_bb; + struct device_node *child, *child_bb; + + fman_bb = of_find_compatible_node(NULL, NULL, "fsl,fman"); + fman = of_find_compatible_node(root, NULL, "fsl,fman"); + + /* + * The dts files in the Linux tree have all network interfaces + * enabled. Disable the ones that are disabled under barebox + * as well. + */ + for_each_child_of_node(fman, child) { + if (!of_device_is_compatible(child, "fsl,fman-memac")) + continue; + + child_bb = of_get_child_by_name(fman_bb, child->name); + if (!child_bb) + continue; + + if (of_device_is_available(child_bb)) + of_device_enable(child); + else + of_device_disable(child); + } + + return 0; +} + +static int fman_register_of_fixup(void) +{ + of_register_fixup(fman_of_fixup, NULL); + + return 0; +} +late_initcall(fman_register_of_fixup); diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index d2c2b6f306..257679fae8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -20,7 +20,7 @@ int nvme_submit_sync_cmd(struct nvme_ctrl *ctrl, return __nvme_submit_sync_cmd(ctrl, cmd, NULL, buffer, bufflen, 0, NVME_QID_ADMIN); } -EXPORT_SYMBOL_GPL(nvme_sec_submit); +EXPORT_SYMBOL_GPL(nvme_submit_sync_cmd); static int nvme_identify_ctrl(struct nvme_ctrl *dev, struct nvme_id_ctrl **id) { diff --git a/drivers/nvmem/bsec.c b/drivers/nvmem/bsec.c index 8235d468d1..d772d0b7af 100644 --- a/drivers/nvmem/bsec.c +++ b/drivers/nvmem/bsec.c @@ -57,7 +57,7 @@ static int bsec_smc(struct bsec_priv *priv, u8 op, enum bsec_field field, return -ENXIO; } -static int st32_bsec_read_shadow(void *ctx, unsigned reg, unsigned *val) +static int stm32_bsec_read_shadow(void *ctx, unsigned reg, unsigned *val) { return bsec_smc(ctx, BSEC_SMC_READ_SHADOW, reg, 0, val); } @@ -69,7 +69,7 @@ static int stm32_bsec_reg_write_shadow(void *ctx, unsigned reg, unsigned val) static struct regmap_bus stm32_bsec_regmap_bus = { .reg_write = stm32_bsec_reg_write_shadow, - .reg_read = st32_bsec_read_shadow, + .reg_read = stm32_bsec_read_shadow, }; static int stm32_bsec_write(struct device_d *dev, int offset, diff --git a/drivers/of/base.c b/drivers/of/base.c index 98ef5fc0d4..80ceeab13b 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -887,54 +887,6 @@ int of_property_read_string(struct device_node *np, const char *propname, EXPORT_SYMBOL_GPL(of_property_read_string); /** - * of_property_read_string_index - Find and read a string from a multiple - * strings property. - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * @index: index of the string in the list of strings - * @out_string: pointer to null terminated return string, modified only if - * return value is 0. - * - * Search for a property in a device tree node and retrieve a null - * terminated string value (pointer to data, not a copy) in the list of strings - * contained in that property. - * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if - * property does not have a value, and -EILSEQ if the string is not - * null-terminated within the length of the property data. - * - * The out_string pointer is modified only if a valid string can be decoded. - */ -int of_property_read_string_index(struct device_node *np, const char *propname, - int index, const char **output) -{ - struct property *prop = of_find_property(np, propname, NULL); - int i = 0; - size_t l = 0, total = 0; - const char *p; - const void *value; - - if (!prop) - return -EINVAL; - value = of_property_get_value(prop); - if (!value) - return -ENODATA; - if (strnlen(value, prop->length) >= prop->length) - return -EILSEQ; - - p = value; - - for (i = 0; total < prop->length; total += l, p += l) { - l = strlen(p) + 1; - if (i++ == index) { - *output = p; - return 0; - } - } - return -ENODATA; -} -EXPORT_SYMBOL_GPL(of_property_read_string_index); - -/** * of_property_match_string() - Find string in a list and return index * @np: pointer to node containing string list property * @propname: string list property name @@ -972,43 +924,6 @@ int of_property_match_string(struct device_node *np, const char *propname, } EXPORT_SYMBOL_GPL(of_property_match_string); -/** - * of_property_count_strings - Find and return the number of strings from a - * multiple strings property. - * @np: device node from which the property value is to be read. - * @propname: name of the property to be searched. - * - * Search for a property in a device tree node and retrieve the number of null - * terminated string contain in it. Returns the number of strings on - * success, -EINVAL if the property does not exist, -ENODATA if property - * does not have a value, and -EILSEQ if the string is not null-terminated - * within the length of the property data. - */ -int of_property_count_strings(struct device_node *np, const char *propname) -{ - struct property *prop = of_find_property(np, propname, NULL); - int i = 0; - size_t l = 0, total = 0; - const char *p; - const void *value; - - if (!prop) - return -EINVAL; - value = of_property_get_value(prop); - if (!value) - return -ENODATA; - if (strnlen(value, prop->length) >= prop->length) - return -EILSEQ; - - p = value; - - for (i = 0; total < prop->length; total += l, p += l, i++) - l = strlen(p) + 1; - - return i; -} -EXPORT_SYMBOL_GPL(of_property_count_strings); - const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, u32 *pu) { @@ -1777,6 +1692,43 @@ struct device_node *of_get_child_by_name(const struct device_node *node, } EXPORT_SYMBOL(of_get_child_by_name); +/** + * of_property_read_string_helper() - Utility helper for parsing string properties + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_strs: output array of string pointers. + * @sz: number of array elements to read. + * @skip: Number of strings to skip over at beginning of list. + * + * Don't call this function directly. It is a utility helper for the + * of_property_read_string*() family of functions. + */ +int of_property_read_string_helper(const struct device_node *np, + const char *propname, const char **out_strs, + size_t sz, int skip) +{ + const struct property *prop = of_find_property(np, propname, NULL); + int l = 0, i = 0; + const char *p, *end; + + if (!prop) + return -EINVAL; + if (!prop->value) + return -ENODATA; + p = prop->value; + end = p + prop->length; + + for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) { + l = strnlen(p, end - p) + 1; + if (p + l > end) + return -EILSEQ; + if (out_strs && i >= skip) + *out_strs++ = p; + } + i -= skip; + return i <= 0 ? -ENODATA : i; +} + static void __of_print_nodes(struct device_node *node, int indent, const char *prefix) { struct device_node *n; diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 44a89d005f..025c418f2b 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -47,6 +47,13 @@ config PCI_IMX6 select OF_PCI select PCI +config PCI_LAYERSCAPE + bool "Freescale Layerscape PCIe controller" + depends on ARCH_LAYERSCAPE + select PCIE_DW + select OF_PCI + select PCI + endmenu endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index 562304c65d..3ca6708657 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -11,3 +11,4 @@ obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o obj-$(CONFIG_PCIE_DW) += pcie-designware.o pcie-designware-host.o obj-$(CONFIG_PCI_IMX6) += pci-imx6.o +obj-$(CONFIG_PCI_LAYERSCAPE) += pci-layerscape.o diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c index ac15623307..251be4fffa 100644 --- a/drivers/pci/bus.c +++ b/drivers/pci/bus.c @@ -23,6 +23,32 @@ pci_match_one_device(const struct pci_device_id *id, const struct pci_dev *dev) return NULL; } +/** + * pci_match_id - See if a pci device matches a given pci_id table + * @ids: array of PCI device id structures to search in + * @dev: the PCI device structure to match against. + * + * Used by a driver to check whether a PCI device present in the + * system is in its list of supported devices. Returns the matching + * pci_device_id structure or %NULL if there is no match. + * + * Deprecated, don't use this as it will not catch any dynamic ids + * that a driver might want to check for. + */ +const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, + struct pci_dev *dev) +{ + if (ids) { + while (ids->vendor || ids->subvendor || ids->class_mask) { + if (pci_match_one_device(ids, dev)) + return ids; + ids++; + } + } + return NULL; +} +EXPORT_SYMBOL(pci_match_id); + static int pci_match(struct device_d *dev, struct driver_d *drv) { struct pci_dev *pdev = to_pci_dev(dev); diff --git a/drivers/pci/pci-imx6.c b/drivers/pci/pci-imx6.c index 85307bad3e..05df9c0f79 100644 --- a/drivers/pci/pci-imx6.c +++ b/drivers/pci/pci-imx6.c @@ -97,8 +97,6 @@ struct imx6_pcie { #define PCIE_PL_PFLR (PL_OFFSET + 0x08) #define PCIE_PL_PFLR_LINK_STATE_MASK (0x3f << 16) #define PCIE_PL_PFLR_FORCE_LINK (1 << 15) -#define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) -#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29) #define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4) #define PCIE_PHY_CTRL (PL_OFFSET + 0x114) @@ -112,7 +110,6 @@ struct imx6_pcie { #define PCIE_PHY_STAT_ACK_LOC 16 #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C -#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) /* PHY registers (not memory-mapped) */ #define PCIE_PHY_RX_ASIC_OUT 0x100D @@ -636,8 +633,8 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie) err_reset_phy: dev_dbg(dev, "PHY DEBUG_R0=0x%08x DEBUG_R1=0x%08x\n", - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R0), - dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1)); + dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG0), + dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1)); imx6_pcie_reset_phy(imx6_pcie); return ret; @@ -659,8 +656,8 @@ static int imx6_pcie_host_init(struct pcie_port *pp) static int imx6_pcie_link_up(struct dw_pcie *pci) { - return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) & - PCIE_PHY_DEBUG_R1_XMLH_LINK_UP; + return dw_pcie_readl_dbi(pci, PCIE_PORT_DEBUG1) & + PCIE_PORT_DEBUG1_LINK_UP; } static const struct dw_pcie_ops dw_pcie_ops = { diff --git a/drivers/pci/pci-layerscape.c b/drivers/pci/pci-layerscape.c new file mode 100644 index 0000000000..ccdc025c2e --- /dev/null +++ b/drivers/pci/pci-layerscape.c @@ -0,0 +1,484 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * PCIe host controller driver for Freescale Layerscape SoCs + * + * Copyright (C) 2014 Freescale Semiconductor. + * + * Author: Minghuan Lian <Minghuan.Lian@freescale.com> + */ + +#include <common.h> +#include <clock.h> +#include <abort.h> +#include <malloc.h> +#include <io.h> +#include <init.h> +#include <gpio.h> +#include <asm/mmu.h> +#include <of_gpio.h> +#include <of_device.h> +#include <linux/clk.h> +#include <linux/kernel.h> +#include <of_address.h> +#include <of_pci.h> +#include <regmap.h> +#include <mfd/syscon.h> +#include <linux/pci.h> +#include <linux/phy/phy.h> +#include <linux/reset.h> +#include <linux/sizes.h> + +#include "pcie-designware.h" + +/* PEX1/2 Misc Ports Status Register */ +#define SCFG_PEXMSCPORTSR(pex_idx) (0x94 + (pex_idx) * 4) +#define LTSSM_STATE_SHIFT 20 +#define LTSSM_STATE_MASK 0x3f +#define LTSSM_PCIE_L0 0x11 /* L0 state */ + +/* PEX Internal Configuration Registers */ +#define PCIE_STRFMR1 0x71c /* Symbol Timer & Filter Mask Register1 */ +#define PCIE_ABSERR 0x8d0 /* Bridge Slave Error Response Register */ +#define PCIE_ABSERR_SETTING 0x9401 /* Forward error of non-posted request */ + +#define PCIE_IATU_NUM 6 + +#define PCIE_LUT_UDR(n) (0x800 + (n) * 8) +#define PCIE_LUT_ENABLE (1 << 31) +#define PCIE_LUT_LDR(n) (0x804 + (n) * 8) + +struct ls_pcie_drvdata { + u32 lut_offset; + u32 ltssm_shift; + u32 lut_dbg; + int pex_stream_id_start; + int pex_stream_id_end; + const struct dw_pcie_host_ops *ops; + const struct dw_pcie_ops *dw_pcie_ops; +}; + +struct ls_pcie { + struct dw_pcie pci; + void __iomem *lut; + struct regmap *scfg; + const char *compatible; + const struct ls_pcie_drvdata *drvdata; + int index; + int next_lut_index; +}; + +static struct ls_pcie *to_ls_pcie(struct dw_pcie *pci) +{ + return container_of(pci, struct ls_pcie, pci); +} + +static u32 lut_readl(struct ls_pcie *pcie, unsigned int offset) +{ + return in_be32(pcie->lut + offset); +} + +static void lut_writel(struct ls_pcie *pcie, unsigned int value, + unsigned int offset) +{ + out_be32(pcie->lut + offset, value); +} + +static int ls_pcie_next_streamid(struct ls_pcie *pcie) +{ + static int next_stream_id; + int first = pcie->drvdata->pex_stream_id_start; + int last = pcie->drvdata->pex_stream_id_end; + int current = next_stream_id + first; + + if (current > last) + return -EINVAL; + + next_stream_id++; + + return current; +} + +#define PCIE_LUT_ENTRY_COUNT 32 + +static int ls_pcie_next_lut_index(struct ls_pcie *pcie) +{ + if (pcie->next_lut_index < PCIE_LUT_ENTRY_COUNT) + return pcie->next_lut_index++; + else + return -ENOSPC; /* LUT is full */ +} + +static void ls_pcie_lut_set_mapping(struct ls_pcie *pcie, int index, u32 devid, + u32 stream_id) +{ + /* leave mask as all zeroes, want to match all bits */ + lut_writel(pcie, devid << 16, PCIE_LUT_UDR(index)); + lut_writel(pcie, stream_id | PCIE_LUT_ENABLE, PCIE_LUT_LDR(index)); +} + +static bool ls_pcie_is_bridge(struct ls_pcie *pcie) +{ + struct dw_pcie *pci = &pcie->pci; + u32 header_type; + + header_type = ioread8(pci->dbi_base + PCI_HEADER_TYPE); + header_type &= 0x7f; + + return header_type == PCI_HEADER_TYPE_BRIDGE; +} + +/* Clear multi-function bit */ +static void ls_pcie_clear_multifunction(struct ls_pcie *pcie) +{ + struct dw_pcie *pci = &pcie->pci; + + iowrite8(PCI_HEADER_TYPE_BRIDGE, pci->dbi_base + PCI_HEADER_TYPE); +} + +/* Drop MSG TLP except for Vendor MSG */ +static void ls_pcie_drop_msg_tlp(struct ls_pcie *pcie) +{ + u32 val; + struct dw_pcie *pci = &pcie->pci; + + val = ioread32(pci->dbi_base + PCIE_STRFMR1); + val &= 0xDFFFFFFF; + iowrite32(val, pci->dbi_base + PCIE_STRFMR1); +} + +static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie) +{ + int i; + + for (i = 0; i < PCIE_IATU_NUM; i++) + dw_pcie_disable_atu(&pcie->pci, i, DW_PCIE_REGION_OUTBOUND); +} + +static int ls1021_pcie_link_up(struct dw_pcie *pci) +{ + u32 state; + struct ls_pcie *pcie = to_ls_pcie(pci); + + if (!pcie->scfg) + return 0; + + regmap_read(pcie->scfg, SCFG_PEXMSCPORTSR(pcie->index), &state); + state = (state >> LTSSM_STATE_SHIFT) & LTSSM_STATE_MASK; + + if (state < LTSSM_PCIE_L0) + return 0; + + return 1; +} + +static int ls_pcie_link_up(struct dw_pcie *pci) +{ + struct ls_pcie *pcie = to_ls_pcie(pci); + u32 state; + + state = (ioread32(pcie->lut + pcie->drvdata->lut_dbg) >> + pcie->drvdata->ltssm_shift) & + LTSSM_STATE_MASK; + + if (state < LTSSM_PCIE_L0) + return 0; + + return 1; +} + +/* Forward error response of outbound non-posted requests */ +static void ls_pcie_fix_error_response(struct ls_pcie *pcie) +{ + struct dw_pcie *pci = &pcie->pci; + + iowrite32(PCIE_ABSERR_SETTING, pci->dbi_base + PCIE_ABSERR); +} + +static int ls_pcie_host_init(struct pcie_port *pp) +{ + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct ls_pcie *pcie = to_ls_pcie(pci); + + /* + * Disable outbound windows configured by the bootloader to avoid + * one transaction hitting multiple outbound windows. + * dw_pcie_setup_rc() will reconfigure the outbound windows. + */ + ls_pcie_disable_outbound_atus(pcie); + ls_pcie_fix_error_response(pcie); + + dw_pcie_dbi_ro_wr_en(pci); + ls_pcie_clear_multifunction(pcie); + dw_pcie_dbi_ro_wr_dis(pci); + + ls_pcie_drop_msg_tlp(pcie); + + dw_pcie_setup_rc(pp); + + return 0; +} + +static int ls1021_pcie_host_init(struct pcie_port *pp) +{ + struct dw_pcie *pci = to_dw_pcie_from_pp(pp); + struct ls_pcie *pcie = to_ls_pcie(pci); + struct device_d *dev = pci->dev; + u32 index[2]; + int ret; + + pcie->scfg = syscon_regmap_lookup_by_phandle(dev->device_node, + "fsl,pcie-scfg"); + if (IS_ERR(pcie->scfg)) { + ret = PTR_ERR(pcie->scfg); + dev_err(dev, "No syscfg phandle specified\n"); + pcie->scfg = NULL; + return ret; + } + + if (of_property_read_u32_array(dev->device_node, + "fsl,pcie-scfg", index, 2)) { + pcie->scfg = NULL; + return -EINVAL; + } + pcie->index = index[1]; + + return ls_pcie_host_init(pp); +} + +static const struct dw_pcie_host_ops ls1021_pcie_host_ops = { + .host_init = ls1021_pcie_host_init, +}; + +static const struct dw_pcie_host_ops ls_pcie_host_ops = { + .host_init = ls_pcie_host_init, +}; + +static const struct dw_pcie_ops dw_ls1021_pcie_ops = { + .link_up = ls1021_pcie_link_up, +}; + +static const struct dw_pcie_ops dw_ls_pcie_ops = { + .link_up = ls_pcie_link_up, +}; + +static const struct ls_pcie_drvdata ls1021_drvdata = { + .ops = &ls1021_pcie_host_ops, + .dw_pcie_ops = &dw_ls1021_pcie_ops, +}; + +static const struct ls_pcie_drvdata ls1043_drvdata = { + .lut_offset = 0x10000, + .ltssm_shift = 24, + .lut_dbg = 0x7fc, + .pex_stream_id_start = 11, + .pex_stream_id_end = 26, + .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, +}; + +static const struct ls_pcie_drvdata ls1046_drvdata = { + .lut_offset = 0x80000, + .ltssm_shift = 24, + .lut_dbg = 0x407fc, + .pex_stream_id_start = 11, + .pex_stream_id_end = 26, + .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, +}; + +static const struct ls_pcie_drvdata ls2080_drvdata = { + .lut_offset = 0x80000, + .ltssm_shift = 0, + .lut_dbg = 0x7fc, + .pex_stream_id_start = 7, + .pex_stream_id_end = 22, + .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, +}; + +static const struct ls_pcie_drvdata ls2088_drvdata = { + .lut_offset = 0x80000, + .ltssm_shift = 0, + .lut_dbg = 0x407fc, + .pex_stream_id_start = 7, + .pex_stream_id_end = 18, + .ops = &ls_pcie_host_ops, + .dw_pcie_ops = &dw_ls_pcie_ops, +}; + +static const struct of_device_id ls_pcie_of_match[] = { + { .compatible = "fsl,ls1012a-pcie", .data = &ls1046_drvdata }, + { .compatible = "fsl,ls1021a-pcie", .data = &ls1021_drvdata }, + { .compatible = "fsl,ls1043a-pcie", .data = &ls1043_drvdata }, + { .compatible = "fsl,ls1046a-pcie", .data = &ls1046_drvdata }, + { .compatible = "fsl,ls2080a-pcie", .data = &ls2080_drvdata }, + { .compatible = "fsl,ls2085a-pcie", .data = &ls2080_drvdata }, + { .compatible = "fsl,ls2088a-pcie", .data = &ls2088_drvdata }, + { .compatible = "fsl,ls1088a-pcie", .data = &ls2088_drvdata }, + { }, +}; + +static int __init ls_add_pcie_port(struct ls_pcie *pcie) +{ + struct dw_pcie *pci = &pcie->pci; + struct pcie_port *pp = &pci->pp; + struct device_d *dev = pci->dev; + int ret; + + pp->ops = pcie->drvdata->ops; + + ret = dw_pcie_host_init(pp); + if (ret) { + dev_err(dev, "failed to initialize host\n"); + return ret; + } + + return 0; +} + +static int ls_pcie_of_fixup(struct device_node *root, void *ctx) +{ + struct ls_pcie *pcie = ctx; + struct device_d *dev = pcie->pci.dev; + struct device_node *np; + char *name; + u32 *arr, phandle; + int nluts; + int ret, i; + u32 devid, stream_id; + + name = of_get_reproducible_name(dev->device_node); + + np = root; + do { + np = of_find_node_by_reproducible_name(np, name); + if (!np) + return -ENODEV; + } while (!of_device_is_compatible(np, pcie->compatible)); + + nluts = pcie->next_lut_index; + + ret = of_property_read_u32(np, "msi-parent", &phandle); + if (ret) { + dev_err(pcie->pci.dev, "Unable to get \"msi-parent\" phandle\n"); + return ret; + } + + arr = xmalloc(nluts * sizeof(u32) * 4); + + for (i = 0; i < nluts; i++) { + u32 udr = lut_readl(pcie, PCIE_LUT_UDR(i)); + u32 ldr = lut_readl(pcie, PCIE_LUT_LDR(i)); + + if (!(ldr & PCIE_LUT_ENABLE)) + break; + + devid = udr >> 16; + stream_id = ldr & 0x7fff; + + arr[i * 4] = devid; + arr[i * 4 + 1] = phandle; + arr[i * 4 + 2] = stream_id; + arr[i * 4 + 3] = 1; + } + + /* + * An msi-map is a property to be added to the pci controller + * node. It is a table, where each entry consists of 4 fields + * e.g.: + * + * msi-map = <[devid] [phandle-to-msi-ctrl] [stream-id] [count] + * [devid] [phandle-to-msi-ctrl] [stream-id] [count]>; + */ + + ret = of_property_write_u32_array(np, "msi-map", arr, nluts * 4); + if (ret) + goto out; + + of_device_enable(np); + + ret = 0; + +out: + free(arr); + return ret; +} + +static int __init ls_pcie_probe(struct device_d *dev) +{ + struct dw_pcie *pci; + struct ls_pcie *pcie; + struct resource *dbi_base; + const struct of_device_id *match; + int ret; + + pcie = xzalloc(sizeof(*pcie)); + if (!pcie) + return -ENOMEM; + + pci = &pcie->pci; + + match = of_match_device(dev->driver->of_compatible, dev); + if (!match) + return -ENODEV; + + pcie->drvdata = match->data; + pcie->compatible = match->compatible; + + pci->dev = dev; + pci->ops = pcie->drvdata->dw_pcie_ops; + + dbi_base = dev_request_mem_resource(dev, 0); + if (IS_ERR(dbi_base)) + return PTR_ERR(dbi_base); + + pci->dbi_base = IOMEM(dbi_base->start); + + pcie->lut = pci->dbi_base + pcie->drvdata->lut_offset; + + if (!ls_pcie_is_bridge(pcie)) + return -ENODEV; + + dev->priv = pcie; + + ret = ls_add_pcie_port(pcie); + if (ret < 0) + return ret; + + of_register_fixup(ls_pcie_of_fixup, pcie); + + return 0; +} + +static struct driver_d ls_pcie_driver = { + .name = "layerscape-pcie", + .of_compatible = DRV_OF_COMPAT(ls_pcie_of_match), + .probe = ls_pcie_probe, +}; +device_platform_driver(ls_pcie_driver); + +static void ls_pcie_fixup(struct pci_dev *pcidev) +{ + struct pci_bus *bus = pcidev->bus, *p; + struct pci_controller *host = bus->host; + struct pcie_port *pp = container_of(host, struct pcie_port, pci); + struct dw_pcie *dwpcie = container_of(pp, struct dw_pcie, pp); + struct ls_pcie *lspcie = container_of(dwpcie, struct ls_pcie, pci); + int stream_id, index; + int base_bus_num = 0; + + stream_id = ls_pcie_next_streamid(lspcie); + index = ls_pcie_next_lut_index(lspcie); + + p = pcidev->bus; + while (p) { + base_bus_num = p->number; + p = p->parent_bus; + } + + ls_pcie_lut_set_mapping(lspcie, index, + (pcidev->bus->number - base_bus_num) << 8 | pcidev->devfn, + stream_id); +} + +DECLARE_PCI_FIXUP_EARLY(PCI_ANY_ID, PCI_ANY_ID, ls_pcie_fixup); diff --git a/drivers/pci/pcie-designware-host.c b/drivers/pci/pcie-designware-host.c index 7a95b2a092..b2d46d38f8 100644 --- a/drivers/pci/pcie-designware-host.c +++ b/drivers/pci/pcie-designware-host.c @@ -340,17 +340,6 @@ static const struct pci_ops dw_pcie_ops = { .write = dw_pcie_wr_conf, }; -static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) -{ - u32 val; - - val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT); - if (val == 0xffffffff) - return 1; - - return 0; -} - void dw_pcie_setup_rc(struct pcie_port *pp) { u32 val; @@ -381,11 +370,6 @@ void dw_pcie_setup_rc(struct pcie_port *pp) * we should not program the ATU here. */ if (!pp->ops->rd_other_conf) { - /* get iATU unroll support */ - pci->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pci); - dev_dbg(pci->dev, "iATU unroll: %s\n", - pci->iatu_unroll_enabled ? "enabled" : "disabled"); - dw_pcie_prog_outbound_atu(pci, PCIE_ATU_REGION_INDEX0, PCIE_ATU_TYPE_MEM, pp->mem_mod_base, pp->mem_bus_addr, pp->mem_size); diff --git a/drivers/pci/pcie-designware.c b/drivers/pci/pcie-designware.c index c6d19559f4..e2007dba6d 100644 --- a/drivers/pci/pcie-designware.c +++ b/drivers/pci/pcie-designware.c @@ -29,7 +29,7 @@ int dw_pcie_read(void __iomem *addr, int size, u32 *val) { - if ((uintptr_t)addr & (size - 1)) { + if (!IS_ALIGNED((uintptr_t)addr, size)) { *val = 0; return PCIBIOS_BAD_REGISTER_NUMBER; } @@ -50,7 +50,7 @@ int dw_pcie_read(void __iomem *addr, int size, u32 *val) int dw_pcie_write(void __iomem *addr, int size, u32 val) { - if ((uintptr_t)addr & (size - 1)) + if (!IS_ALIGNED((uintptr_t)addr, size)) return PCIBIOS_BAD_REGISTER_NUMBER; if (size == 4) @@ -65,42 +65,69 @@ int dw_pcie_write(void __iomem *addr, int size, u32 val) return PCIBIOS_SUCCESSFUL; } -u32 __dw_pcie_readl_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg, - size_t size) +u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size) { int ret; u32 val; - if (pci->ops->readl_dbi) - return pci->ops->readl_dbi(pci, base, reg, size); + if (pci->ops->read_dbi) + return pci->ops->read_dbi(pci, pci->dbi_base, reg, size); - ret = dw_pcie_read(base + reg, size, &val); + ret = dw_pcie_read(pci->dbi_base + reg, size, &val); if (ret) dev_err(pci->dev, "Read DBI address failed\n"); return val; } -void __dw_pcie_writel_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg, - size_t size, u32 val) +void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val) { int ret; - if (pci->ops->writel_dbi) { - pci->ops->writel_dbi(pci, base, reg, size, val); + if (pci->ops->write_dbi) { + pci->ops->write_dbi(pci, pci->dbi_base, reg, size, val); return; } - ret = dw_pcie_write(base + reg, size, val); + ret = dw_pcie_write(pci->dbi_base + reg, size, val); if (ret) dev_err(pci->dev, "Write DBI address failed\n"); } +u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size) +{ + int ret; + u32 val; + + if (pci->ops->read_dbi) + return pci->ops->read_dbi(pci, pci->atu_base, reg, size); + + ret = dw_pcie_read(pci->atu_base + reg, size, &val); + if (ret) + dev_err(pci->dev, "Read ATU address failed\n"); + + return val; +} + +void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val) +{ + int ret; + + if (pci->ops->write_dbi) { + pci->ops->write_dbi(pci, pci->atu_base, reg, size, val); + return; + } + + ret = dw_pcie_write(pci->atu_base + reg, size, val); + if (ret) + dev_err(pci->dev, "Write ATU address failed\n"); +} + static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg) { u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); - return dw_pcie_readl_dbi(pci, offset + reg); + return dw_pcie_readl_atu(pci, offset + reg); } static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, @@ -108,7 +135,7 @@ static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, { u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index); - dw_pcie_writel_dbi(pci, offset + reg, val); + dw_pcie_writel_atu(pci, offset + reg, val); } static void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index, @@ -188,6 +215,26 @@ void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, dev_err(pci->dev, "Outbound iATU is not being enabled\n"); } +void dw_pcie_disable_atu(struct dw_pcie *pci, int index, + enum dw_pcie_region_type type) +{ + int region; + + switch (type) { + case DW_PCIE_REGION_INBOUND: + region = PCIE_ATU_REGION_INBOUND; + break; + case DW_PCIE_REGION_OUTBOUND: + region = PCIE_ATU_REGION_OUTBOUND; + break; + default: + return; + } + + dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index); + dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, (u32)~PCIE_ATU_ENABLE); +} + int dw_pcie_wait_for_link(struct dw_pcie *pci) { int retries; @@ -213,9 +260,20 @@ int dw_pcie_link_up(struct dw_pcie *pci) if (pci->ops->link_up) return pci->ops->link_up(pci); - val = readl(pci->dbi_base + PCIE_PHY_DEBUG_R1); - return ((val & PCIE_PHY_DEBUG_R1_LINK_UP) && - !(val & PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING)); + val = readl(pci->dbi_base + PCIE_PORT_DEBUG1); + return ((val & PCIE_PORT_DEBUG1_LINK_UP) && + (!(val & PCIE_PORT_DEBUG1_LINK_IN_TRAINING))); +} + +static u8 dw_pcie_iatu_unroll_enabled(struct dw_pcie *pci) +{ + u32 val; + + val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT); + if (val == 0xffffffff) + return 1; + + return 0; } void dw_pcie_setup(struct dw_pcie *pci) @@ -226,9 +284,21 @@ void dw_pcie_setup(struct dw_pcie *pci) struct device_d *dev = pci->dev; struct device_node *np = dev->device_node; + if (pci->version >= 0x480A || (!pci->version && + dw_pcie_iatu_unroll_enabled(pci))) { + pci->iatu_unroll_enabled = true; + if (!pci->atu_base) + pci->atu_base = pci->dbi_base + DEFAULT_DBI_ATU_OFFSET; + } + dev_dbg(pci->dev, "iATU unroll: %s\n", pci->iatu_unroll_enabled ? + "enabled" : "disabled"); + + ret = of_property_read_u32(np, "num-lanes", &lanes); - if (ret) - lanes = 0; + if (ret) { + dev_dbg(pci->dev, "property num-lanes isn't found\n"); + return; + } /* Set the number of lanes */ val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL); diff --git a/drivers/pci/pcie-designware.h b/drivers/pci/pcie-designware.h index 058a0acbb2..de20654e42 100644 --- a/drivers/pci/pcie-designware.h +++ b/drivers/pci/pcie-designware.h @@ -11,6 +11,8 @@ #ifndef _PCIE_DESIGNWARE_H #define _PCIE_DESIGNWARE_H +#include <linux/bitfield.h> + /* Parameters for the waiting for link up routine */ #define LINK_WAIT_MAX_RETRIES 10 #define LINK_WAIT_USLEEP_MAX 100000 @@ -19,19 +21,30 @@ #define LINK_WAIT_MAX_IATU_RETRIES 5 #define LINK_WAIT_IATU_MAX 10000 -/* Synopsis specific PCIE configuration registers */ +/* Synopsys-specific PCIe configuration registers */ #define PCIE_PORT_LINK_CONTROL 0x710 -#define PORT_LINK_MODE_MASK (0x3f << 16) -#define PORT_LINK_MODE_1_LANES (0x1 << 16) -#define PORT_LINK_MODE_2_LANES (0x3 << 16) -#define PORT_LINK_MODE_4_LANES (0x7 << 16) +#define PORT_LINK_MODE_MASK GENMASK(21, 16) +#define PORT_LINK_MODE(n) FIELD_PREP(PORT_LINK_MODE_MASK, n) +#define PORT_LINK_MODE_1_LANES PORT_LINK_MODE(0x1) +#define PORT_LINK_MODE_2_LANES PORT_LINK_MODE(0x3) +#define PORT_LINK_MODE_4_LANES PORT_LINK_MODE(0x7) +#define PORT_LINK_MODE_8_LANES PORT_LINK_MODE(0xf) + +#define PCIE_PORT_DEBUG0 0x728 +#define PORT_LOGIC_LTSSM_STATE_MASK 0x1f +#define PORT_LOGIC_LTSSM_STATE_L0 0x11 +#define PCIE_PORT_DEBUG1 0x72C +#define PCIE_PORT_DEBUG1_LINK_UP BIT(4) +#define PCIE_PORT_DEBUG1_LINK_IN_TRAINING BIT(29) #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C -#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) -#define PORT_LOGIC_LINK_WIDTH_MASK (0x1f << 8) -#define PORT_LOGIC_LINK_WIDTH_1_LANES (0x1 << 8) -#define PORT_LOGIC_LINK_WIDTH_2_LANES (0x2 << 8) -#define PORT_LOGIC_LINK_WIDTH_4_LANES (0x4 << 8) +#define PORT_LOGIC_SPEED_CHANGE BIT(17) +#define PORT_LOGIC_LINK_WIDTH_MASK GENMASK(12, 8) +#define PORT_LOGIC_LINK_WIDTH(n) FIELD_PREP(PORT_LOGIC_LINK_WIDTH_MASK, n) +#define PORT_LOGIC_LINK_WIDTH_1_LANES PORT_LOGIC_LINK_WIDTH(0x1) +#define PORT_LOGIC_LINK_WIDTH_2_LANES PORT_LOGIC_LINK_WIDTH(0x2) +#define PORT_LOGIC_LINK_WIDTH_4_LANES PORT_LOGIC_LINK_WIDTH(0x4) +#define PORT_LOGIC_LINK_WIDTH_8_LANES PORT_LOGIC_LINK_WIDTH(0x8) #define PCIE_MSI_ADDR_LO 0x820 #define PCIE_MSI_ADDR_HI 0x824 @@ -40,61 +53,86 @@ #define PCIE_MSI_INTR0_STATUS 0x830 #define PCIE_ATU_VIEWPORT 0x900 -#define PCIE_ATU_REGION_INBOUND (0x1 << 31) -#define PCIE_ATU_REGION_OUTBOUND (0x0 << 31) -#define PCIE_ATU_REGION_INDEX2 (0x2 << 0) -#define PCIE_ATU_REGION_INDEX1 (0x1 << 0) -#define PCIE_ATU_REGION_INDEX0 (0x0 << 0) +#define PCIE_ATU_REGION_INBOUND BIT(31) +#define PCIE_ATU_REGION_OUTBOUND 0 +#define PCIE_ATU_REGION_INDEX2 0x2 +#define PCIE_ATU_REGION_INDEX1 0x1 +#define PCIE_ATU_REGION_INDEX0 0x0 #define PCIE_ATU_CR1 0x904 -#define PCIE_ATU_TYPE_MEM (0x0 << 0) -#define PCIE_ATU_TYPE_IO (0x2 << 0) -#define PCIE_ATU_TYPE_CFG0 (0x4 << 0) -#define PCIE_ATU_TYPE_CFG1 (0x5 << 0) +#define PCIE_ATU_TYPE_MEM 0x0 +#define PCIE_ATU_TYPE_IO 0x2 +#define PCIE_ATU_TYPE_CFG0 0x4 +#define PCIE_ATU_TYPE_CFG1 0x5 #define PCIE_ATU_CR2 0x908 -#define PCIE_ATU_ENABLE (0x1 << 31) -#define PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30) +#define PCIE_ATU_ENABLE BIT(31) +#define PCIE_ATU_BAR_MODE_ENABLE BIT(30) #define PCIE_ATU_LOWER_BASE 0x90C #define PCIE_ATU_UPPER_BASE 0x910 #define PCIE_ATU_LIMIT 0x914 #define PCIE_ATU_LOWER_TARGET 0x918 -#define PCIE_ATU_BUS(x) (((x) & 0xff) << 24) -#define PCIE_ATU_DEV(x) (((x) & 0x1f) << 19) -#define PCIE_ATU_FUNC(x) (((x) & 0x7) << 16) +#define PCIE_ATU_BUS(x) FIELD_PREP(GENMASK(31, 24), x) +#define PCIE_ATU_DEV(x) FIELD_PREP(GENMASK(23, 19), x) +#define PCIE_ATU_FUNC(x) FIELD_PREP(GENMASK(18, 16), x) #define PCIE_ATU_UPPER_TARGET 0x91C +#define PCIE_MISC_CONTROL_1_OFF 0x8BC +#define PCIE_DBI_RO_WR_EN BIT(0) + +#define PCIE_PL_CHK_REG_CONTROL_STATUS 0xB20 +#define PCIE_PL_CHK_REG_CHK_REG_START BIT(0) +#define PCIE_PL_CHK_REG_CHK_REG_CONTINUOUS BIT(1) +#define PCIE_PL_CHK_REG_CHK_REG_COMPARISON_ERROR BIT(16) +#define PCIE_PL_CHK_REG_CHK_REG_LOGIC_ERROR BIT(17) +#define PCIE_PL_CHK_REG_CHK_REG_COMPLETE BIT(18) + +#define PCIE_PL_CHK_REG_ERR_ADDR 0xB28 + /* * iATU Unroll-specific register definitions * From 4.80 core version the address translation will be made by unroll */ #define PCIE_ATU_UNR_REGION_CTRL1 0x00 #define PCIE_ATU_UNR_REGION_CTRL2 0x04 -#define PCIE_ATU_UNR_LOWER_BASE 0x08 -#define PCIE_ATU_UNR_UPPER_BASE 0x0C +#define PCIE_ATU_UNR_LOWER_BASE 0x08 +#define PCIE_ATU_UNR_UPPER_BASE 0x0C #define PCIE_ATU_UNR_LIMIT 0x10 #define PCIE_ATU_UNR_LOWER_TARGET 0x14 #define PCIE_ATU_UNR_UPPER_TARGET 0x18 +/* + * The default address offset between dbi_base and atu_base. Root controller + * drivers are not required to initialize atu_base if the offset matches this + * default; the driver core automatically derives atu_base from dbi_base using + * this offset, if atu_base not set. + */ +#define DEFAULT_DBI_ATU_OFFSET (0x3 << 20) + /* Register address builder */ -#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) ((0x3 << 20) | (region << 9)) +#define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region) \ + ((region) << 9) -/* PCIe Port Logic registers */ -#define PLR_OFFSET 0x700 -#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c) -#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4) -#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29) +#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region) \ + (((region) << 9) | BIT(8)) -#define PCIE_MISC_CONTROL_1_OFF 0x8BC -#define PCIE_DBI_RO_WR_EN (0x1 << 0) +#define MAX_MSI_IRQS 256 +#define MAX_MSI_IRQS_PER_CTRL 32 +#define MAX_MSI_CTRLS (MAX_MSI_IRQS / MAX_MSI_IRQS_PER_CTRL) +#define MSI_REG_CTRL_BLOCK_SIZE 12 +#define MSI_DEF_NUM_VECTORS 32 -/* PCIe Port Logic registers */ -#define PLR_OFFSET 0x700 -#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c) -#define PCIE_PHY_DEBUG_R1_LINK_UP (0x1 << 4) -#define PCIE_PHY_DEBUG_R1_LINK_IN_TRAINING (0x1 << 29) +/* Maximum number of inbound/outbound iATUs */ +#define MAX_IATU_IN 256 +#define MAX_IATU_OUT 256 struct pcie_port; struct dw_pcie; +enum dw_pcie_region_type { + DW_PCIE_REGION_UNKNOWN, + DW_PCIE_REGION_INBOUND, + DW_PCIE_REGION_OUTBOUND, +}; + struct dw_pcie_host_ops { int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val); int (*wr_own_conf)(struct pcie_port *pp, int where, int size, u32 val); @@ -134,20 +172,23 @@ struct pcie_port { }; struct dw_pcie_ops { - u32 (*readl_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, - size_t size); - void (*writel_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, - size_t size, u32 val); + u32 (*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, + size_t size); + void (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg, + size_t size, u32 val); int (*link_up)(struct dw_pcie *pcie); }; struct dw_pcie { struct device_d *dev; void __iomem *dbi_base; + /* Used when iatu_unroll_enabled is true */ + void __iomem *atu_base; u32 num_viewport; u8 iatu_unroll_enabled; struct pcie_port pp; const struct dw_pcie_ops *ops; + unsigned int version; }; #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp) @@ -156,26 +197,37 @@ int dw_pcie_read(void __iomem *addr, int size, u32 *val); int dw_pcie_write(void __iomem *addr, int size, u32 val); void dw_pcie_setup_rc(struct pcie_port *pp); int dw_pcie_host_init(struct pcie_port *pp); - -u32 __dw_pcie_readl_dbi(struct dw_pcie *pci, void __iomem *addr, u32 reg, - size_t size); -void __dw_pcie_writel_dbi(struct dw_pcie *pci, void __iomem *addr, u32 reg, - size_t size, u32 val); +u32 dw_pcie_read_dbi(struct dw_pcie *pci, u32 reg, size_t size); +void dw_pcie_write_dbi(struct dw_pcie *pci, u32 reg, size_t size, u32 val); +u32 dw_pcie_read_atu(struct dw_pcie *pci, u32 reg, size_t size); +void dw_pcie_write_atu(struct dw_pcie *pci, u32 reg, size_t size, u32 val); int dw_pcie_link_up(struct dw_pcie *pci); int dw_pcie_wait_for_link(struct dw_pcie *pci); void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type, u64 cpu_addr, u64 pci_addr, u32 size); +void dw_pcie_disable_atu(struct dw_pcie *pci, int index, + enum dw_pcie_region_type type); void dw_pcie_setup(struct dw_pcie *pci); static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val) { - __dw_pcie_writel_dbi(pci, pci->dbi_base, reg, 0x4, val); + dw_pcie_write_dbi(pci, reg, 0x4, val); } static inline u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg) { - return __dw_pcie_readl_dbi(pci, pci->dbi_base, reg, 0x4); + return dw_pcie_read_dbi(pci, reg, 0x4); +} + +static inline void dw_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val) +{ + dw_pcie_write_atu(pci, reg, 0x4, val); +} + +static inline u32 dw_pcie_readl_atu(struct dw_pcie *pci, u32 reg) +{ + return dw_pcie_read_atu(pci, reg, 0x4); } static inline void dw_pcie_dbi_ro_wr_en(struct dw_pcie *pci) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 95c6708f4a..fd75ea6a4f 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -17,16 +17,6 @@ config PINCTRL_AT91 help The pinmux controller found on AT91 SoCs. -config PINCTRL_AT91PIO4 - bool "AT91 PIO4 pinctrl driver" - depends on OFDEVICE - depends on ARCH_AT91 - select GPIOLIB - select OF_GPIO - help - Say Y here to enable the at91 pinctrl/gpio driver for Atmel PIO4 - controller available on sama5d2 SoC. - config PINCTRL_BCM283X bool "GPIO and pinmux support for BCM283X" depends on ARCH_BCM283X @@ -55,6 +45,16 @@ comment "OFDEVICE is not enabled." comment "Without device tree support PINCTRL won't do anything" endif +config PINCTRL_AT91PIO4 + bool "AT91 PIO4 pinctrl driver" + depends on ARCH_AT91 + depends on OFDEVICE + select GPIOLIB + select OF_GPIO + help + Say Y here to enable the at91 pinctrl/gpio driver for Atmel PIO4 + controller available on sama5d2 SoC. + config PINCTRL_MXS bool "MXS pinctrl" depends on ARCH_MXS diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index ffb04eebbf..278ea8c4a0 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -388,7 +388,7 @@ static const struct tegra_drive_pingroup tegra30_drive_groups[] = { DRV_PG(vi1, 0x8c8, -1, -1, -1, 14, 5, 19, 5, 24, 4, 28, 4), }; -static const struct pinctrl_tegra30_drvdata tegra30_drvdata = { +__maybe_unused static const struct pinctrl_tegra30_drvdata tegra30_drvdata = { .pingrps = tegra30_pin_groups, .num_pingrps = ARRAY_SIZE(tegra30_pin_groups), .drvgrps = tegra30_drive_groups, @@ -632,7 +632,7 @@ static const struct tegra_drive_pingroup tegra124_drive_groups[] = { DRV_PG(ao4, 0x9c8, 2, 3, 4, 12, 7, 20, 7, 28, 2, 30, 2), }; -static const struct pinctrl_tegra30_drvdata tegra124_drvdata = { +__maybe_unused static const struct pinctrl_tegra30_drvdata tegra124_drvdata = { .pingrps = tegra124_pin_groups, .num_pingrps = ARRAY_SIZE(tegra124_pin_groups), .drvgrps = tegra124_drive_groups, diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 8139b6442c..a193fadb69 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -21,6 +21,16 @@ config IMX_REMOTEPROC It's safe to say N here. +config STM32_REMOTEPROC + tristate "STM32 remoteproc support" + depends on ARCH_STM32MP + select MFD_SYSCON + help + Say y here to support STM32 MCU processors via the + remote processor framework. + + It's safe to say N here. + endif # REMOTEPROC endmenu diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index 1072969229..43658df5c6 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_REMOTEPROC) += remoteproc_core.o remoteproc_elf_loader.o obj-$(CONFIG_IMX_REMOTEPROC) += imx_rproc.o +obj-$(CONFIG_STM32_REMOTEPROC) += stm32_rproc.o diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 7cac47e06c..8a28c1bafc 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -107,14 +107,36 @@ static int rproc_firmware_finish(struct firmware_handler *fh) return ret; } +static int rproc_register_dev(struct rproc *rproc, const char *alias) +{ + if (alias) { + rproc->dev.id = DEVICE_ID_SINGLE; + dev_set_name(&rproc->dev, alias); + } else { + rproc->dev.id = DEVICE_ID_DYNAMIC; + dev_set_name(&rproc->dev, "remoteproc"); + } + + return register_device(&rproc->dev); +} + int rproc_add(struct rproc *rproc) { struct device_d *dev = &rproc->dev; struct firmware_handler *fh; + const char *alias = NULL; int ret; + if (dev->device_node) + alias = of_alias_get(dev->device_node); + + ret = rproc_register_dev(rproc, alias); + if (ret) + return ret; + fh = &rproc->fh; - fh->id = xstrdup(rproc->name); + fh->id = xstrdup(dev_name(dev)); + fh->model = xstrdup(rproc->name); fh->open = rproc_firmware_start; fh->write = rproc_firmware_write_buf; fh->close = rproc_firmware_finish; @@ -153,11 +175,6 @@ struct rproc *rproc_alloc(struct device_d *dev, const char *name, rproc->dev.parent = dev; rproc->dev.priv = rproc; - /* Assign a unique device index and name */ - rproc->index = 1; - - dev_set_name(&rproc->dev, "remoteproc%d", rproc->index); - /* Default to ELF loader if no load function is specified */ if (!rproc->ops->load) rproc->ops->load = rproc_elf_load_segments; diff --git a/drivers/remoteproc/stm32_rproc.c b/drivers/remoteproc/stm32_rproc.c new file mode 100644 index 0000000000..bfd4d59768 --- /dev/null +++ b/drivers/remoteproc/stm32_rproc.c @@ -0,0 +1,199 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) STMicroelectronics 2018 - All Rights Reserved + * Authors: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics. + * Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. + * Copyright (C) 2019 Ahmad Fatoum, Pengutronix + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <io.h> +#include <mach/smc.h> +#include <mfd/syscon.h> +#include <of_address.h> +#include <regmap.h> +#include <linux/remoteproc.h> +#include <linux/reset.h> + +#include "remoteproc_internal.h" + +#define HOLD_BOOT 0 +#define RELEASE_BOOT 1 + +struct stm32_syscon { + struct regmap *map; + u32 reg; + u32 mask; +}; + +struct stm32_rproc { + struct reset_control *rst; + struct stm32_syscon hold_boot; + bool secured_soc; +}; + +static void *stm32_rproc_da_to_va(struct rproc *rproc, u64 da, int len) +{ + __be32 in_addr = cpu_to_be32(da); + struct device_d *dev = &rproc->dev; + u64 paddr; + + paddr = of_translate_dma_address(dev->parent->device_node, &in_addr); + if (paddr == OF_BAD_ADDR) + return NULL; + + return phys_to_virt(paddr); +} + +static int stm32_rproc_set_hold_boot(struct rproc *rproc, bool hold) +{ + struct stm32_rproc *ddata = rproc->priv; + struct stm32_syscon *hold_boot = &ddata->hold_boot; + struct arm_smccc_res smc_res; + int val, err; + + val = hold ? HOLD_BOOT : RELEASE_BOOT; + + if (IS_ENABLED(CONFIG_ARM_SMCC) && ddata->secured_soc) { + arm_smccc_smc(STM32_SMC_RCC, STM32_SMC_REG_WRITE, + hold_boot->reg, val, 0, 0, 0, 0, &smc_res); + err = smc_res.a0; + } else { + err = regmap_update_bits(hold_boot->map, hold_boot->reg, + hold_boot->mask, val); + } + + if (err) + dev_err(&rproc->dev, "failed to set hold boot\n"); + + return err; +} + +static int stm32_rproc_start(struct rproc *rproc) +{ + int err; + + err = stm32_rproc_set_hold_boot(rproc, false); + if (err) + return err; + + return stm32_rproc_set_hold_boot(rproc, true); +} + +static int stm32_rproc_stop(struct rproc *rproc) +{ + struct stm32_rproc *ddata = rproc->priv; + int err; + + err = stm32_rproc_set_hold_boot(rproc, true); + if (err) + return err; + + err = reset_control_assert(ddata->rst); + if (err) { + dev_err(&rproc->dev, "failed to assert the reset\n"); + return err; + } + + return 0; +} + +static struct rproc_ops st_rproc_ops = { + .start = stm32_rproc_start, + .stop = stm32_rproc_stop, + .da_to_va = stm32_rproc_da_to_va, +}; + +static int stm32_rproc_get_syscon(struct device_node *np, const char *prop, + struct stm32_syscon *syscon) +{ + int err = 0; + + syscon->map = syscon_regmap_lookup_by_phandle(np, prop); + if (IS_ERR(syscon->map)) { + err = PTR_ERR(syscon->map); + syscon->map = NULL; + goto out; + } + + err = of_property_read_u32_index(np, prop, 1, &syscon->reg); + if (err) + goto out; + + err = of_property_read_u32_index(np, prop, 2, &syscon->mask); + +out: + return err; +} + +static int stm32_rproc_parse_dt(struct device_d *dev, struct stm32_rproc *ddata) +{ + struct device_node *np = dev->device_node; + struct stm32_syscon tz; + unsigned int tzen; + int err; + + ddata->rst = reset_control_get(dev, NULL); + if (IS_ERR(ddata->rst)) { + dev_err(dev, "failed to get mcu reset\n"); + return PTR_ERR(ddata->rst); + } + + /* + * if platform is secured the hold boot bit must be written by + * smc call and read normally. + * if not secure the hold boot bit could be read/write normally + */ + err = stm32_rproc_get_syscon(np, "st,syscfg-tz", &tz); + if (err) { + dev_err(dev, "failed to get tz syscfg\n"); + return err; + } + + err = regmap_read(tz.map, tz.reg, &tzen); + if (err) { + dev_err(dev, "failed to read tzen\n"); + return err; + } + ddata->secured_soc = tzen & tz.mask; + + err = stm32_rproc_get_syscon(np, "st,syscfg-holdboot", + &ddata->hold_boot); + if (err) { + dev_err(dev, "failed to get hold boot\n"); + return err; + } + + return 0; +} + +static int stm32_rproc_probe(struct device_d *dev) +{ + struct rproc *rproc; + int ret; + + rproc = rproc_alloc(dev, dev_name(dev), &st_rproc_ops, + sizeof(struct stm32_rproc)); + if (!rproc) + return -ENOMEM; + + ret = stm32_rproc_parse_dt(dev, rproc->priv); + if (ret) + return ret; + + return rproc_add(rproc); +} + +static const struct of_device_id stm32_rproc_of_match[] = { + { .compatible = "st,stm32mp1-m4" }, + { /* sentinel */ }, +}; + +static struct driver_d stm32_rproc_driver = { + .name = "stm32-rproc", + .probe = stm32_rproc_probe, + .of_compatible = DRV_OF_COMPAT(stm32_rproc_of_match), +}; +device_platform_driver(stm32_rproc_driver); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7a411d456e..bd02fe2137 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -97,6 +97,14 @@ config DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS help Say Y here if you are using OMAP extensions to NS16550 +config DRIVER_SERIAL_NS16550_PCI + depends on DRIVER_SERIAL_NS16550 + depends on PCI + default y + bool "NS16550 PCI serial driver" + help + Enable this to get support for NS16550 UARTs connected over PCI + config DRIVER_SERIAL_PL010 depends on ARCH_EP93XX default y diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 6f9e3b7835..8a2abbbe45 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_DRIVER_SERIAL_LINUX_CONSOLE) += linux_console.o obj-$(CONFIG_DRIVER_SERIAL_MPC5XXX) += serial_mpc5xxx.o obj-$(CONFIG_DRIVER_SERIAL_CLPS711X) += serial_clps711x.o obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial_ns16550.o +obj-$(CONFIG_DRIVER_SERIAL_NS16550_PCI) += serial_ns16550_pci.o obj-$(CONFIG_DRIVER_SERIAL_PL010) += serial_pl010.o obj-$(CONFIG_DRIVER_SERIAL_S3C) += serial_s3c.o obj-$(CONFIG_DRIVER_SERIAL_STM32) += serial_stm32.o diff --git a/drivers/serial/serial_ns16550_pci.c b/drivers/serial/serial_ns16550_pci.c new file mode 100644 index 0000000000..d4b5bd8898 --- /dev/null +++ b/drivers/serial/serial_ns16550_pci.c @@ -0,0 +1,5311 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Probe module for 8250/16550-type PCI serial ports. + * + * Based on Linux drivers/tty/serial/8250_pci.c + * Itself based on Linux drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * Copyright (C) 2001 Russell King, All Rights Reserved. + * Copyright (C) 2019 Ahmad Fatoum, Pengutronix + */ + +#include <common.h> +#include <init.h> +#include <linux/pci.h> +#include <driver.h> +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/bitops.h> + +#include <asm/byteorder.h> +#include <asm/io.h> + +#include <platform_data/serial-ns16550.h> +#include "serial_ns16550.h" + +#define PCI_NUM_BAR_RESOURCES 6 + +#define FL_BASE_MASK 0x0007 +#define FL_BASE0 0x0000 +#define FL_BASE1 0x0001 +#define FL_BASE2 0x0002 +#define FL_BASE3 0x0003 +#define FL_BASE4 0x0004 +#define FL_GET_BASE(x) (x & FL_BASE_MASK) + +/* Use successive BARs (PCI base address registers), + else use offset into some specified BAR */ +#define FL_BASE_BARS 0x0008 + +/* do not assign an irq; no-op, we use no irqs */ +#define FL_NOIRQ 0x0080 + +/* Use the Base address register size to cap number of ports */ +#define FL_REGION_SZ_CAP 0x0100 + + +struct uart_8250_port { + struct NS16550_plat *pdata; + struct resource resource; + +}; + +struct pciserial_board { + unsigned int flags; + unsigned int num_ports; + unsigned int base_baud; + unsigned int uart_offset; + unsigned int reg_shift; + unsigned int first_offset; +}; + +struct serial_private; + +/* + * init function returns: + * > 0 - number of ports + * = 0 - use board->num_ports + * < 0 - error + */ +struct pci_serial_quirk { + u32 vendor; + u32 device; + u32 subvendor; + u32 subdevice; + int (*probe)(struct pci_dev *dev); + int (*init)(struct pci_dev *dev); + int (*setup)(struct serial_private *, + const struct pciserial_board *, + struct uart_8250_port *, int); + void (*exit)(struct pci_dev *dev); +}; + +#define PCI_NUM_BAR_RESOURCES 6 + +struct serial_private { + struct pci_dev *dev; + unsigned int nr; + struct pci_serial_quirk *quirk; + const struct pciserial_board *board; + void *private_data; /* for use by quirks */ +}; + +static int pci_default_setup(struct serial_private*, + const struct pciserial_board*, struct uart_8250_port *, int); + +static void moan_device(const char *str, struct pci_dev *dev) +{ + dev_err(&dev->dev, + "%s: %s\n" + "Please send the output of lspci -vv, this\n" + "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n" + "manufacturer and name of serial board or\n" + "modem board to <linux-serial@vger.kernel.org>.\n", + dev_name(&dev->dev), str, dev->vendor, dev->device, + dev->subsystem_vendor, dev->subsystem_device); +} + +static int +setup_port(struct serial_private *priv, struct uart_8250_port *port, + int bar, int offset, int regshift) +{ + struct pci_dev *dev = priv->dev; + + if (bar >= PCI_NUM_BAR_RESOURCES) + return -EINVAL; + + port->resource.flags = IORESOURCE_MEM_8BIT; + + if (pci_resource_flags(dev, bar) & IORESOURCE_MEM) { + if (!pci_iomap(dev, bar)) + return -ENOMEM; + + port->resource.flags |= IORESOURCE_MEM; + } else { + port->resource.flags |= IORESOURCE_IO; + } + + port->resource.start = pci_resource_start(dev, bar) + offset; + port->resource.end = port->resource.start + pci_resource_len(dev, bar) - 1; + + port->pdata->shift = regshift; + + return 0; +} + +/* + * ADDI-DATA GmbH communication cards <info@addi-data.com> + */ +static int addidata_apci7800_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar = 0, offset = board->first_offset; + bar = FL_GET_BASE(board->flags); + + if (idx < 2) { + offset += idx * board->uart_offset; + } else if ((idx >= 2) && (idx < 4)) { + bar += 1; + offset += ((idx - 2) * board->uart_offset); + } else if ((idx >= 4) && (idx < 6)) { + bar += 2; + offset += ((idx - 4) * board->uart_offset); + } else if (idx >= 6) { + bar += 3; + offset += ((idx - 6) * board->uart_offset); + } + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +/* + * AFAVLAB uses a different mixture of BARs and offsets + * Not that ugly ;) -- HW + */ +static int +afavlab_setup(struct serial_private *priv, const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar, offset = board->first_offset; + + bar = FL_GET_BASE(board->flags); + if (idx < 4) + bar += idx; + else { + bar = 4; + offset += (idx - 4) * board->uart_offset; + } + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +/* + * HP's Remote Management Console. The Diva chip came in several + * different versions. N-class, L2000 and A500 have two Diva chips, each + * with 3 UARTs (the third UART on the second chip is unused). Superdome + * and Keystone have one Diva chip with 3 UARTs. Some later machines have + * one Diva chip, but it has been expanded to 5 UARTs. + */ +static int pci_hp_diva_init(struct pci_dev *dev) +{ + int rc = 0; + + switch (dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_TOSCA1: + case PCI_DEVICE_ID_HP_DIVA_HALFDOME: + case PCI_DEVICE_ID_HP_DIVA_KEYSTONE: + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + rc = 3; + break; + case PCI_DEVICE_ID_HP_DIVA_TOSCA2: + rc = 2; + break; + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + rc = 4; + break; + case PCI_DEVICE_ID_HP_DIVA_POWERBAR: + case PCI_DEVICE_ID_HP_DIVA_HURRICANE: + rc = 1; + break; + } + + return rc; +} + +/* + * HP's Diva chip puts the 4th/5th serial port further out, and + * some serial ports are supposed to be hidden on certain models. + */ +static int +pci_hp_diva_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int offset = board->first_offset; + unsigned int bar = FL_GET_BASE(board->flags); + + switch (priv->dev->subsystem_device) { + case PCI_DEVICE_ID_HP_DIVA_MAESTRO: + if (idx == 3) + idx++; + break; + case PCI_DEVICE_ID_HP_DIVA_EVEREST: + if (idx > 0) + idx++; + if (idx > 2) + idx++; + break; + } + if (idx > 2) + offset = 0x18; + + offset += idx * board->uart_offset; + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +/* + * Added for EKF Intel i960 serial boards + */ +static int pci_inteli960ni_init(struct pci_dev *dev) +{ + u32 oldval; + + if (!(dev->subsystem_device & 0x1000)) + return -ENODEV; + + /* is firmware started? */ + pci_read_config_dword(dev, 0x44, &oldval); + if (oldval == 0x00001000L) { /* RESET value */ + dev_dbg(&dev->dev, "Local i960 firmware missing\n"); + return -ENODEV; + } + return 0; +} + +/* + * Some PCI serial cards using the PLX 9050 PCI interface chip require + * that the card interrupt be explicitly enabled or disabled. This + * seems to be mainly needed on card using the PLX which also use I/O + * mapped memory. + */ +static int pci_plx9050_init(struct pci_dev *dev) +{ + void __iomem *p; + + if ((pci_resource_flags(dev, 0) & IORESOURCE_MEM) == 0) { + moan_device("no memory in bar 0", dev); + return 0; + } + + /* + * disable interrupts + */ + p = pci_iomap(dev, 0); + if (p == NULL) + return -ENOMEM; + + writel(0, p + 0x4c); + + /* + * Read the register back to ensure that it took effect. + */ + readl(p + 0x4c); + + return 0; +} + +#define NI8420_INT_ENABLE_REG 0x38 +#define NI8420_INT_ENABLE_BIT 0x2000 + +/* MITE registers */ +#define MITE_IOWBSR1 0xc4 +#define MITE_IOWCR1 0xf4 +#define MITE_LCIMR1 0x08 +#define MITE_LCIMR2 0x10 + +#define MITE_LCIMR2_CLR_CPU_IE (1 << 30) + +/* SBS Technologies Inc. PMC-OCTPRO and P-OCTAL cards */ +static int +sbs_setup(struct serial_private *priv, const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar, offset = board->first_offset; + + bar = 0; + + if (idx < 4) { + /* first four channels map to 0, 0x100, 0x200, 0x300 */ + offset += idx * board->uart_offset; + } else if (idx < 8) { + /* last four channels map to 0x1000, 0x1100, 0x1200, 0x1300 */ + offset += idx * board->uart_offset + 0xC00; + } else /* we have only 8 ports on PMC-OCTALPRO */ + return 1; + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +/* +* This does initialization for PMC OCTALPRO cards: +* maps the device memory, resets the UARTs (needed, bc +* if the module is removed and inserted again, the card +* is in the sleep mode) and enables global interrupt. +*/ + +/* global control register offset for SBS PMC-OctalPro */ +#define OCT_REG_CR_OFF 0x500 + +static int sbs_init(struct pci_dev *dev) +{ + u8 __iomem *p; + + p = pci_iomap(dev, 0); + + if (p == NULL) + return -ENOMEM; + /* Set bit-4 Control Register (UART RESET) in to reset the uarts */ + writeb(0x10, p + OCT_REG_CR_OFF); + udelay(50); + writeb(0x0, p + OCT_REG_CR_OFF); + + /* Clear especially bit-2 (INTENABLE) of Control Register */ + writeb(0, p + OCT_REG_CR_OFF); + + return 0; +} + +/* + * SIIG serial cards have an PCI interface chip which also controls + * the UART clocking frequency. Each UART can be clocked independently + * (except cards equipped with 4 UARTs) and initial clocking settings + * are stored in the EEPROM chip. It can cause problems because this + * version of serial driver doesn't support differently clocked UART's + * on single PCI card. To prevent this, initialization functions set + * high frequency clocking for all UART's on given card. It is safe (I + * hope) because it doesn't touch EEPROM settings to prevent conflicts + * with other OSes (like M$ DOS). + * + * SIIG support added by Andrey Panin <pazke@donpac.ru>, 10/1999 + * + * There is two family of SIIG serial cards with different PCI + * interface chip and different configuration methods: + * - 10x cards have control registers in IO and/or memory space; + * - 20x cards have control registers in standard PCI configuration space. + * + * Note: all 10x cards have PCI device ids 0x10.. + * all 20x cards have PCI device ids 0x20.. + * + * There are also Quartet Serial cards which use Oxford Semiconductor + * 16954 quad UART PCI chip clocked by 18.432 MHz quartz. + * + * Note: some SIIG cards are probed by the parport_serial object. + */ + +#define PCI_DEVICE_ID_SIIG_1S_10x (PCI_DEVICE_ID_SIIG_1S_10x_550 & 0xfffc) +#define PCI_DEVICE_ID_SIIG_2S_10x (PCI_DEVICE_ID_SIIG_2S_10x_550 & 0xfff8) + +static int pci_siig10x_init(struct pci_dev *dev) +{ + u16 data; + void __iomem *p; + + switch (dev->device & 0xfff8) { + case PCI_DEVICE_ID_SIIG_1S_10x: /* 1S */ + data = 0xffdf; + break; + case PCI_DEVICE_ID_SIIG_2S_10x: /* 2S, 2S1P */ + data = 0xf7ff; + break; + default: /* 1S1P, 4S */ + data = 0xfffb; + break; + } + + p = pci_iomap(dev, 0); + if (p == NULL) + return -ENOMEM; + + writew(readw(p + 0x28) & data, p + 0x28); + readw(p + 0x28); + + + return 0; +} + +#define PCI_DEVICE_ID_SIIG_2S_20x (PCI_DEVICE_ID_SIIG_2S_20x_550 & 0xfffc) +#define PCI_DEVICE_ID_SIIG_2S1P_20x (PCI_DEVICE_ID_SIIG_2S1P_20x_550 & 0xfffc) + +static int pci_siig20x_init(struct pci_dev *dev) +{ + u8 data; + + /* Change clock frequency for the first UART. */ + pci_read_config_byte(dev, 0x6f, &data); + pci_write_config_byte(dev, 0x6f, data & 0xef); + + /* If this card has 2 UART, we have to do the same with second UART. */ + if (((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S_20x) || + ((dev->device & 0xfffc) == PCI_DEVICE_ID_SIIG_2S1P_20x)) { + pci_read_config_byte(dev, 0x73, &data); + pci_write_config_byte(dev, 0x73, data & 0xef); + } + return 0; +} + +static int pci_siig_init(struct pci_dev *dev) +{ + unsigned int type = dev->device & 0xff00; + + if (type == 0x1000) + return pci_siig10x_init(dev); + else if (type == 0x2000) + return pci_siig20x_init(dev); + + moan_device("Unknown SIIG card", dev); + return -ENODEV; +} + +static int pci_siig_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar = FL_GET_BASE(board->flags) + idx, offset = 0; + + if (idx > 3) { + bar = 4; + offset = (idx - 4) * 8; + } + + return setup_port(priv, port, bar, offset, 0); +} + +/* + * Timedia has an explosion of boards, and to avoid the PCI table from + * growing *huge*, we use this function to collapse some 70 entries + * in the PCI table into one, for sanity's and compactness's sake. + */ +static const unsigned short timedia_single_port[] = { + 0x4025, 0x4027, 0x4028, 0x5025, 0x5027, 0 +}; + +static const unsigned short timedia_dual_port[] = { + 0x0002, 0x4036, 0x4037, 0x4038, 0x4078, 0x4079, 0x4085, + 0x4088, 0x4089, 0x5037, 0x5078, 0x5079, 0x5085, 0x6079, + 0x7079, 0x8079, 0x8137, 0x8138, 0x8237, 0x8238, 0x9079, + 0x9137, 0x9138, 0x9237, 0x9238, 0xA079, 0xB079, 0xC079, + 0xD079, 0 +}; + +static const unsigned short timedia_quad_port[] = { + 0x4055, 0x4056, 0x4095, 0x4096, 0x5056, 0x8156, 0x8157, + 0x8256, 0x8257, 0x9056, 0x9156, 0x9157, 0x9158, 0x9159, + 0x9256, 0x9257, 0xA056, 0xA157, 0xA158, 0xA159, 0xB056, + 0xB157, 0 +}; + +static const unsigned short timedia_eight_port[] = { + 0x4065, 0x4066, 0x5065, 0x5066, 0x8166, 0x9066, 0x9166, + 0x9167, 0x9168, 0xA066, 0xA167, 0xA168, 0 +}; + +static const struct timedia_struct { + int num; + const unsigned short *ids; +} timedia_data[] = { + { 1, timedia_single_port }, + { 2, timedia_dual_port }, + { 4, timedia_quad_port }, + { 8, timedia_eight_port } +}; + +/* + * There are nearly 70 different Timedia/SUNIX PCI serial devices. Instead of + * listing them individually, this driver merely grabs them all with + * PCI_ANY_ID. Some of these devices, however, also feature a parallel port, + * and should be left free to be claimed by parport_serial instead. + */ +static int pci_timedia_probe(struct pci_dev *dev) +{ + /* + * Check the third digit of the subdevice ID + * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel) + */ + if ((dev->subsystem_device & 0x00f0) >= 0x70) { + dev_info(&dev->dev, + "ignoring Timedia subdevice %04x for parport_serial\n", + dev->subsystem_device); + return -ENODEV; + } + + return 0; +} + +static int pci_timedia_init(struct pci_dev *dev) +{ + const unsigned short *ids; + int i, j; + + for (i = 0; i < ARRAY_SIZE(timedia_data); i++) { + ids = timedia_data[i].ids; + for (j = 0; ids[j]; j++) + if (dev->subsystem_device == ids[j]) + return timedia_data[i].num; + } + return 0; +} + +/* + * Timedia/SUNIX uses a mixture of BARs and offsets + * Ugh, this is ugly as all hell --- TYT + */ +static int +pci_timedia_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar = 0, offset = board->first_offset; + + switch (idx) { + case 0: + bar = 0; + break; + case 1: + offset = board->uart_offset; + bar = 0; + break; + case 2: + bar = 1; + break; + case 3: + offset = board->uart_offset; + /* FALLTHROUGH */ + case 4: /* BAR 2 */ + case 5: /* BAR 3 */ + case 6: /* BAR 4 */ + case 7: /* BAR 5 */ + bar = idx - 2; + } + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +/* + * Some Titan cards are also a little weird + */ +static int +titan_400l_800l_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar, offset = board->first_offset; + + switch (idx) { + case 0: + bar = 1; + break; + case 1: + bar = 2; + break; + default: + bar = 4; + offset = (idx - 2) * board->uart_offset; + } + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +static int pci_xircom_init(struct pci_dev *dev) +{ + mdelay(100); + return 0; +} + +static int pci_ni8420_init(struct pci_dev *dev) +{ + void __iomem *p; + unsigned int bar = 0; + + if ((pci_resource_flags(dev, bar) & IORESOURCE_MEM) == 0) { + moan_device("no memory in bar", dev); + return 0; + } + + p = pci_iomap(dev, bar); + if (p == NULL) + return -ENOMEM; + + /* Disable the CPU Interrupt */ + writel(readl(p + NI8420_INT_ENABLE_REG) & ~(NI8420_INT_ENABLE_BIT), + p + NI8420_INT_ENABLE_REG); + + return 0; +} + +static int pci_ni8430_init(struct pci_dev *dev) +{ + return -ENOSYS; +} + +/* UART Port Control Register */ +#define NI16550_PCR_OFFSET 0x0f +#define NI16550_PCR_RS422 0x00 +#define NI16550_PCR_ECHO_RS485 0x01 +#define NI16550_PCR_DTR_RS485 0x02 +#define NI16550_PCR_AUTO_RS485 0x03 +#define NI16550_PCR_WIRE_MODE_MASK 0x03 +#define NI16550_PCR_TXVR_ENABLE_BIT BIT(3) +#define NI16550_PCR_RS485_TERMINATION_BIT BIT(6) +#define NI16550_ACR_DTR_AUTO_DTR (0x2 << 3) +#define NI16550_ACR_DTR_MANUAL_DTR (0x0 << 3) + +static int +pci_ni8430_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + struct pci_dev *dev = priv->dev; + void __iomem *p; + unsigned int bar, offset = board->first_offset; + + if (idx >= board->num_ports) + return 1; + + bar = FL_GET_BASE(board->flags); + offset += idx * board->uart_offset; + + p = pci_iomap(dev, bar); + if (!p) + return -ENOMEM; + + /* enable the transceiver */ + writeb(readb(p + offset + NI16550_PCR_OFFSET) | NI16550_PCR_TXVR_ENABLE_BIT, + p + offset + NI16550_PCR_OFFSET); + + return setup_port(priv, port, bar, offset, board->reg_shift); +} + +static int pci_ni8431_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *uart, int idx) +{ + return -ENOSYS; +} + +static int pci_netmos_9900_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar; + + if ((priv->dev->device != PCI_DEVICE_ID_NETMOS_9865) && + (priv->dev->subsystem_device & 0xff00) == 0x3000) { + /* netmos apparently orders BARs by datasheet layout, so serial + * ports get BARs 0 and 3 (or 1 and 4 for memmapped) + */ + bar = 3 * idx; + + return setup_port(priv, port, bar, 0, board->reg_shift); + } else { + return pci_default_setup(priv, board, port, idx); + } +} + +/* the 99xx series comes with a range of device IDs and a variety + * of capabilities: + * + * 9900 has varying capabilities and can cascade to sub-controllers + * (cascading should be purely internal) + * 9904 is hardwired with 4 serial ports + * 9912 and 9922 are hardwired with 2 serial ports + */ +static int pci_netmos_9900_numports(struct pci_dev *dev) +{ + unsigned int c = dev->class; + unsigned int pi; + unsigned short sub_serports; + + pi = c & 0xff; + + if (pi == 2) + return 1; + + if ((pi == 0) && (dev->device == PCI_DEVICE_ID_NETMOS_9900)) { + /* two possibilities: 0x30ps encodes number of parallel and + * serial ports, or 0x1000 indicates *something*. This is not + * immediately obvious, since the 2s1p+4s configuration seems + * to offer all functionality on functions 0..2, while still + * advertising the same function 3 as the 4s+2s1p config. + */ + sub_serports = dev->subsystem_device & 0xf; + if (sub_serports > 0) + return sub_serports; + + dev_err(&dev->dev, + "NetMos/Mostech serial driver ignoring port on ambiguous config.\n"); + return 0; + } + + moan_device("unknown NetMos/Mostech program interface", dev); + return 0; +} + +static int pci_netmos_init(struct pci_dev *dev) +{ + /* subdevice 0x00PS means <P> parallel, <S> serial */ + unsigned int num_serial = dev->subsystem_device & 0xf; + + if ((dev->device == PCI_DEVICE_ID_NETMOS_9901) || + (dev->device == PCI_DEVICE_ID_NETMOS_9865)) + return 0; + + if (dev->subsystem_vendor == PCI_VENDOR_ID_IBM && + dev->subsystem_device == 0x0299) + return 0; + + switch (dev->device) { /* FALLTHROUGH on all */ + case PCI_DEVICE_ID_NETMOS_9904: + case PCI_DEVICE_ID_NETMOS_9912: + case PCI_DEVICE_ID_NETMOS_9922: + case PCI_DEVICE_ID_NETMOS_9900: + num_serial = pci_netmos_9900_numports(dev); + break; + + default: + break; + } + + if (num_serial == 0) { + moan_device("unknown NetMos/Mostech device", dev); + return -ENODEV; + } + + return num_serial; +} + +/* + * These chips are available with optionally one parallel port and up to + * two serial ports. Unfortunately they all have the same product id. + * + * Basic configuration is done over a region of 32 I/O ports. The base + * ioport is called INTA or INTC, depending on docs/other drivers. + * + * The region of the 32 I/O ports is configured in POSIO0R... + */ + +/* registers */ +#define ITE_887x_MISCR 0x9c +#define ITE_887x_INTCBAR 0x78 +#define ITE_887x_UARTBAR 0x7c +#define ITE_887x_PS0BAR 0x10 +#define ITE_887x_POSIO0 0x60 + +/* I/O space size */ +#define ITE_887x_IOSIZE 32 +/* I/O space size (bits 26-24; 8 bytes = 011b) */ +#define ITE_887x_POSIO_IOSIZE_8 (3 << 24) +/* I/O space size (bits 26-24; 32 bytes = 101b) */ +#define ITE_887x_POSIO_IOSIZE_32 (5 << 24) +/* Decoding speed (1 = slow, 2 = medium, 3 = fast) */ +#define ITE_887x_POSIO_SPEED (3 << 29) +/* enable IO_Space bit */ +#define ITE_887x_POSIO_ENABLE (1 << 31) + +static int pci_ite887x_init(struct pci_dev *dev) +{ + struct serial_private *priv; + /* inta_addr are the configuration addresses of the ITE */ + static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, + 0x200, 0x280, 0 }; + int ret, i, type; + struct resource *iobase = NULL; + u32 miscr, uartbar, ioport; + + /* search for the base-ioport */ + i = 0; + while (inta_addr[i] && iobase == NULL) { + iobase = request_ioport_region("ite887x", + inta_addr[i], + inta_addr[i] + ITE_887x_IOSIZE - 1); + if (!IS_ERR(iobase)) { + /* write POSIO0R - speed | size | ioport */ + pci_write_config_dword(dev, ITE_887x_POSIO0, + ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED | + ITE_887x_POSIO_IOSIZE_32 | inta_addr[i]); + /* write INTCBAR - ioport */ + pci_write_config_dword(dev, ITE_887x_INTCBAR, + inta_addr[i]); + ret = inb(inta_addr[i]); + if (ret != 0xff) { + /* ioport connected */ + break; + } + release_region(iobase); + iobase = NULL; + } + i++; + } + + if (!inta_addr[i]) { + dev_err(&dev->dev, "ite887x: could not find iobase\n"); + return -ENODEV; + } + + /* start of undocumented type checking (see parport_pc.c) */ + type = inb(iobase->start + 0x18) & 0x0f; + + switch (type) { + case 0x2: /* ITE8871 (1P) */ + case 0xa: /* ITE8875 (1P) */ + ret = 0; + break; + case 0xe: /* ITE8872 (2S1P) */ + ret = 2; + break; + case 0x6: /* ITE8873 (1S) */ + ret = 1; + break; + case 0x8: /* ITE8874 (2S) */ + ret = 2; + break; + default: + moan_device("Unknown ITE887x", dev); + ret = -ENODEV; + } + + /* configure all serial ports */ + for (i = 0; i < ret; i++) { + /* read the I/O port from the device */ + pci_read_config_dword(dev, ITE_887x_PS0BAR + (0x4 * (i + 1)), + &ioport); + ioport &= 0x0000FF00; /* the actual base address */ + pci_write_config_dword(dev, ITE_887x_POSIO0 + (0x4 * (i + 1)), + ITE_887x_POSIO_ENABLE | ITE_887x_POSIO_SPEED | + ITE_887x_POSIO_IOSIZE_8 | ioport); + + /* write the ioport to the UARTBAR */ + pci_read_config_dword(dev, ITE_887x_UARTBAR, &uartbar); + uartbar &= ~(0xffff << (16 * i)); /* clear half the reg */ + uartbar |= (ioport << (16 * i)); /* set the ioport */ + pci_write_config_dword(dev, ITE_887x_UARTBAR, uartbar); + + /* get current config */ + pci_read_config_dword(dev, ITE_887x_MISCR, &miscr); + /* disable interrupts (UARTx_Routing[3:0]) */ + miscr &= ~(0xf << (12 - 4 * i)); + /* activate the UART (UARTx_En) */ + miscr |= 1 << (23 - i); + /* write new config with activated UART */ + pci_write_config_dword(dev, ITE_887x_MISCR, miscr); + } + + if (ret <= 0) { + /* the device has no UARTs if we get here */ + release_region(iobase); + } + + priv = dev->dev.priv; + priv->private_data = iobase; + + return ret; +} + +static void pci_ite887x_exit(struct pci_dev *dev) +{ + struct serial_private *priv; + u32 ioport; + /* the ioport is bit 0-15 in POSIO0R */ + pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport); + ioport &= 0xffff; + + priv = dev->dev.priv; + if (priv->private_data) + release_region(priv->private_data); +} + +/* + * EndRun Technologies. + * Determine the number of ports available on the device. + */ +#define PCI_VENDOR_ID_ENDRUN 0x7401 +#define PCI_DEVICE_ID_ENDRUN_1588 0xe100 + +static int pci_endrun_init(struct pci_dev *dev) +{ + u8 __iomem *p; + unsigned long deviceID; + unsigned int number_uarts = 0; + + /* EndRun device is all 0xexxx */ + if (dev->vendor == PCI_VENDOR_ID_ENDRUN && + (dev->device & 0xf000) != 0xe000) + return 0; + + p = pci_iomap(dev, 0); + if (p == NULL) + return -ENOMEM; + + deviceID = ioread32(p); + /* EndRun device */ + if (deviceID == 0x07000200) { + number_uarts = ioread8(p + 4); + dev_dbg(&dev->dev, + "%d ports detected on EndRun PCI Express device\n", + number_uarts); + } + + return number_uarts; +} + +/* + * Oxford Semiconductor Inc. + * Check that device is part of the Tornado range of devices, then determine + * the number of ports available on the device. + */ +static int pci_oxsemi_tornado_init(struct pci_dev *dev) +{ + u8 __iomem *p; + unsigned long deviceID; + unsigned int number_uarts = 0; + + /* OxSemi Tornado devices are all 0xCxxx */ + if (dev->vendor == PCI_VENDOR_ID_OXSEMI && + (dev->device & 0xF000) != 0xC000) + return 0; + + p = pci_iomap(dev, 0); + if (p == NULL) + return -ENOMEM; + + deviceID = ioread32(p); + /* Tornado device */ + if (deviceID == 0x07000200) { + number_uarts = ioread8(p + 4); + dev_dbg(&dev->dev, + "%d ports detected on Oxford PCI Express device\n", + number_uarts); + } + + return number_uarts; +} + +static int pci_asix_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +/* Quatech devices have their own extra interface features */ + +struct quatech_feature { + u16 devid; + bool amcc; +}; + +#define QPCR_TEST_FOR1 0x3F +#define QPCR_TEST_GET1 0x00 +#define QPCR_TEST_FOR2 0x40 +#define QPCR_TEST_GET2 0x40 +#define QPCR_TEST_FOR3 0x80 +#define QPCR_TEST_GET3 0x40 +#define QPCR_TEST_FOR4 0xC0 +#define QPCR_TEST_GET4 0x80 + +#define QOPR_CLOCK_X1 0x0000 +#define QOPR_CLOCK_X2 0x0001 +#define QOPR_CLOCK_X4 0x0002 +#define QOPR_CLOCK_X8 0x0003 +#define QOPR_CLOCK_RATE_MASK 0x0003 + + +static struct quatech_feature quatech_cards[] = { + { PCI_DEVICE_ID_QUATECH_QSC100, 1 }, + { PCI_DEVICE_ID_QUATECH_DSC100, 1 }, + { PCI_DEVICE_ID_QUATECH_DSC100E, 0 }, + { PCI_DEVICE_ID_QUATECH_DSC200, 1 }, + { PCI_DEVICE_ID_QUATECH_DSC200E, 0 }, + { PCI_DEVICE_ID_QUATECH_ESC100D, 1 }, + { PCI_DEVICE_ID_QUATECH_ESC100M, 1 }, + { PCI_DEVICE_ID_QUATECH_QSCP100, 1 }, + { PCI_DEVICE_ID_QUATECH_DSCP100, 1 }, + { PCI_DEVICE_ID_QUATECH_QSCP200, 1 }, + { PCI_DEVICE_ID_QUATECH_DSCP200, 1 }, + { PCI_DEVICE_ID_QUATECH_ESCLP100, 0 }, + { PCI_DEVICE_ID_QUATECH_QSCLP100, 0 }, + { PCI_DEVICE_ID_QUATECH_DSCLP100, 0 }, + { PCI_DEVICE_ID_QUATECH_SSCLP100, 0 }, + { PCI_DEVICE_ID_QUATECH_QSCLP200, 0 }, + { PCI_DEVICE_ID_QUATECH_DSCLP200, 0 }, + { PCI_DEVICE_ID_QUATECH_SSCLP200, 0 }, + { PCI_DEVICE_ID_QUATECH_SPPXP_100, 0 }, + { 0, } +}; + +static int pci_quatech_amcc(u16 devid) +{ + struct quatech_feature *qf = &quatech_cards[0]; + while (qf->devid) { + if (qf->devid == devid) + return qf->amcc; + qf++; + } + pr_err("quatech: unknown port type '0x%04X'.\n", devid); + return 0; +}; + +static int pci_quatech_rqopr(struct uart_8250_port *port) +{ + unsigned long base = port->resource.start; + u8 LCR, val; + + LCR = inb(base + lcr); + outb(0xBF, base + lcr); + val = inb(base + scr); + outb(LCR, base + lcr); + return val; +} + +static void pci_quatech_wqopr(struct uart_8250_port *port, u8 qopr) +{ + unsigned long base = port->resource.start; + u8 LCR; + + LCR = inb(base + lcr); + outb(0xBF, base + lcr); + inb(base + scr); + outb(qopr, base + scr); + outb(LCR, base + lcr); +} + +static int pci_quatech_rqmcr(struct uart_8250_port *port) +{ + unsigned long base = port->resource.start; + u8 LCR, val, qmcr; + + LCR = inb(base + lcr); + outb(0xBF, base + lcr); + val = inb(base + scr); + outb(val | 0x10, base + scr); + qmcr = inb(base + mcr); + outb(val, base + scr); + outb(LCR, base + lcr); + + return qmcr; +} + +static void pci_quatech_wqmcr(struct uart_8250_port *port, u8 qmcr) +{ + unsigned long base = port->resource.start; + u8 LCR, val; + + LCR = inb(base + lcr); + outb(0xBF, base + lcr); + val = inb(base + scr); + outb(val | 0x10, base + scr); + outb(qmcr, base + mcr); + outb(val, base + scr); + outb(LCR, base + lcr); +} + +static int pci_quatech_has_qmcr(struct uart_8250_port *port) +{ + unsigned long base = port->resource.start; + u8 LCR, val; + + LCR = inb(base + lcr); + outb(0xBF, base + lcr); + val = inb(base + scr); + if (val & 0x20) { + outb(0x80, lcr); + if (!(inb(scr) & 0x20)) { + outb(LCR, base + lcr); + return 1; + } + } + return 0; +} + +static int pci_quatech_test(struct uart_8250_port *port) +{ + u8 reg, qopr; + + qopr = pci_quatech_rqopr(port); + pci_quatech_wqopr(port, qopr & QPCR_TEST_FOR1); + reg = pci_quatech_rqopr(port) & 0xC0; + if (reg != QPCR_TEST_GET1) + return -EINVAL; + pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR2); + reg = pci_quatech_rqopr(port) & 0xC0; + if (reg != QPCR_TEST_GET2) + return -EINVAL; + pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR3); + reg = pci_quatech_rqopr(port) & 0xC0; + if (reg != QPCR_TEST_GET3) + return -EINVAL; + pci_quatech_wqopr(port, (qopr & QPCR_TEST_FOR1)|QPCR_TEST_FOR4); + reg = pci_quatech_rqopr(port) & 0xC0; + if (reg != QPCR_TEST_GET4) + return -EINVAL; + + pci_quatech_wqopr(port, qopr); + return 0; +} + +static int pci_quatech_clock(struct uart_8250_port *port) +{ + u8 qopr, reg, set; + unsigned long clock; + + if (pci_quatech_test(port) < 0) + return 1843200; + + qopr = pci_quatech_rqopr(port); + + pci_quatech_wqopr(port, qopr & ~QOPR_CLOCK_X8); + reg = pci_quatech_rqopr(port); + if (reg & QOPR_CLOCK_X8) { + clock = 1843200; + goto out; + } + pci_quatech_wqopr(port, qopr | QOPR_CLOCK_X8); + reg = pci_quatech_rqopr(port); + if (!(reg & QOPR_CLOCK_X8)) { + clock = 1843200; + goto out; + } + reg &= QOPR_CLOCK_X8; + if (reg == QOPR_CLOCK_X2) { + clock = 3685400; + set = QOPR_CLOCK_X2; + } else if (reg == QOPR_CLOCK_X4) { + clock = 7372800; + set = QOPR_CLOCK_X4; + } else if (reg == QOPR_CLOCK_X8) { + clock = 14745600; + set = QOPR_CLOCK_X8; + } else { + clock = 1843200; + set = QOPR_CLOCK_X1; + } + qopr &= ~QOPR_CLOCK_RATE_MASK; + qopr |= set; + +out: + pci_quatech_wqopr(port, qopr); + return clock; +} + +static int pci_quatech_rs422(struct uart_8250_port *port) +{ + u8 qmcr; + int rs422 = 0; + + if (!pci_quatech_has_qmcr(port)) + return 0; + qmcr = pci_quatech_rqmcr(port); + pci_quatech_wqmcr(port, 0xFF); + if (pci_quatech_rqmcr(port)) + rs422 = 1; + pci_quatech_wqmcr(port, qmcr); + return rs422; +} + +static int pci_quatech_init(struct pci_dev *dev) +{ + if (pci_quatech_amcc(dev->device)) { + unsigned long base = pci_resource_start(dev, 0); + if (base) { + u32 tmp; + + outl(inl(base + 0x38) | 0x00002000, base + 0x38); + tmp = inl(base + 0x3c); + outl(tmp | 0x01000000, base + 0x3c); + outl(tmp &= ~0x01000000, base + 0x3c); + } + } + return 0; +} + +static int pci_quatech_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + /* Needed by pci_quatech calls below */ + port->resource.start = pci_resource_start(priv->dev, FL_GET_BASE(board->flags)); + /* Set up the clocking */ + port->pdata->clock = pci_quatech_clock(port); + /* For now just warn about RS422 */ + if (pci_quatech_rs422(port)) + pr_warn("quatech: software control of RS422 features not currently supported.\n"); + return pci_default_setup(priv, board, port, idx); +} + +static int pci_default_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar, offset = board->first_offset, maxnr; + + bar = FL_GET_BASE(board->flags); + if (board->flags & FL_BASE_BARS) + bar += idx; + else + offset += idx * board->uart_offset; + + maxnr = (pci_resource_len(priv->dev, bar) - board->first_offset) >> + (board->reg_shift + 3); + + if (board->flags & FL_REGION_SZ_CAP && idx >= maxnr) + return 1; + + return setup_port(priv, port, bar, offset, board->reg_shift); +} +static int pci_pericom_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int pci_pericom_setup_four_at_eight(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +ce4100_serial_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +pci_omegapci_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return setup_port(priv, port, 2, idx * 8, 0); +} + +static int +pci_brcm_trumanage_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +/* RTS will control by MCR if this bit is 0 */ +#define FINTEK_RTS_CONTROL_BY_HW BIT(4) +/* only worked with FINTEK_RTS_CONTROL_BY_HW on */ +#define FINTEK_RTS_INVERT BIT(5) + +static int pci_fintek_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + struct pci_dev *pdev = priv->dev; + u8 config_base; + u16 iobase; + + config_base = 0x40 + 0x08 * idx; + + /* Get the io address from configuration space */ + pci_read_config_word(pdev, config_base + 4, &iobase); + + dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase); + + port->resource.flags = IORESOURCE_IO; + port->resource.start = iobase; + port->resource.end = iobase + 8 - 1; + + return 0; +} + +static int pci_fintek_init(struct pci_dev *dev) +{ + unsigned long iobase; + u32 max_port, i; + resource_size_t bar_data[3]; + u8 config_base; + + if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) || + !(pci_resource_flags(dev, 4) & IORESOURCE_IO) || + !(pci_resource_flags(dev, 3) & IORESOURCE_IO)) + return -ENODEV; + + switch (dev->device) { + case 0x1104: /* 4 ports */ + case 0x1108: /* 8 ports */ + max_port = dev->device & 0xff; + break; + case 0x1112: /* 12 ports */ + max_port = 12; + break; + default: + return -EINVAL; + } + + /* Get the io address dispatch from the BIOS */ + bar_data[0] = pci_resource_start(dev, 5); + bar_data[1] = pci_resource_start(dev, 4); + bar_data[2] = pci_resource_start(dev, 3); + + for (i = 0; i < max_port; ++i) { + /* UART0 configuration offset start from 0x40 */ + config_base = 0x40 + 0x08 * i; + + /* Calculate Real IO Port */ + iobase = (bar_data[i / 4] & 0xffffffe0) + (i % 4) * 8; + + /* Enable UART I/O port */ + pci_write_config_byte(dev, config_base + 0x00, 0x01); + + /* Select 128-byte FIFO and 8x FIFO threshold */ + pci_write_config_byte(dev, config_base + 0x01, 0x33); + + /* LSB UART */ + pci_write_config_byte(dev, config_base + 0x04, + (u8)(iobase & 0xff)); + + /* MSB UART */ + pci_write_config_byte(dev, config_base + 0x05, + (u8)((iobase & 0xff00) >> 8)); + + /* First init without port data + * force init to RS232 Mode + */ + pci_write_config_byte(dev, config_base + 0x07, 0x01); + } + + return max_port; +} + +static int pci_fintek_f815xxa_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int pci_fintek_f815xxa_init(struct pci_dev *dev) +{ + u32 max_port, i; + int config_base; + + if (!(pci_resource_flags(dev, 0) & IORESOURCE_MEM)) + return -ENODEV; + + switch (dev->device) { + case 0x1204: /* 4 ports */ + case 0x1208: /* 8 ports */ + max_port = dev->device & 0xff; + break; + case 0x1212: /* 12 ports */ + max_port = 12; + break; + default: + return -EINVAL; + } + + /* Set to mmio decode */ + pci_write_config_byte(dev, 0x209, 0x40); + + for (i = 0; i < max_port; ++i) { + /* UART0 configuration offset start from 0x2A0 */ + config_base = 0x2A0 + 0x08 * i; + + /* Select 128-byte FIFO and 8x FIFO threshold */ + pci_write_config_byte(dev, config_base + 0x01, 0x33); + + /* Enable UART I/O port */ + pci_write_config_byte(dev, config_base + 0, 0x01); + } + + return max_port; +} + +static int skip_tx_en_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int kt_serial_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +pci_wch_ch353_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +pci_wch_ch355_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +pci_wch_ch38x_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +pci_sunix_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + return -ENOSYS; +} + +static int +pci_moxa_setup(struct serial_private *priv, + const struct pciserial_board *board, + struct uart_8250_port *port, int idx) +{ + unsigned int bar = FL_GET_BASE(board->flags); + int offset; + + if (board->num_ports == 4 && idx == 3) + offset = 7 * board->uart_offset; + else + offset = idx * board->uart_offset; + + return setup_port(priv, port, bar, offset, 0); +} + +#define PCI_VENDOR_ID_SBSMODULARIO 0x124B +#define PCI_SUBVENDOR_ID_SBSMODULARIO 0x124B +#define PCI_DEVICE_ID_OCTPRO 0x0001 +#define PCI_SUBDEVICE_ID_OCTPRO232 0x0108 +#define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 +#define PCI_SUBDEVICE_ID_POCTAL232 0x0308 +#define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 +#define PCI_VENDOR_ID_ADVANTECH 0x13fe +#define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 +#define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 +#define PCI_DEVICE_ID_ADVANTECH_PCI3618 0x3618 +#define PCI_DEVICE_ID_ADVANTECH_PCIf618 0xf618 +#define PCI_DEVICE_ID_TITAN_200I 0x8028 +#define PCI_DEVICE_ID_TITAN_400I 0x8048 +#define PCI_DEVICE_ID_TITAN_800I 0x8088 +#define PCI_DEVICE_ID_TITAN_800EH 0xA007 +#define PCI_DEVICE_ID_TITAN_800EHB 0xA008 +#define PCI_DEVICE_ID_TITAN_400EH 0xA009 +#define PCI_DEVICE_ID_TITAN_100E 0xA010 +#define PCI_DEVICE_ID_TITAN_200E 0xA012 +#define PCI_DEVICE_ID_TITAN_400E 0xA013 +#define PCI_DEVICE_ID_TITAN_800E 0xA014 +#define PCI_DEVICE_ID_TITAN_200EI 0xA016 +#define PCI_DEVICE_ID_TITAN_200EISI 0xA017 +#define PCI_DEVICE_ID_TITAN_200V3 0xA306 +#define PCI_DEVICE_ID_TITAN_400V3 0xA310 +#define PCI_DEVICE_ID_TITAN_410V3 0xA312 +#define PCI_DEVICE_ID_TITAN_800V3 0xA314 +#define PCI_DEVICE_ID_TITAN_800V3B 0xA315 +#define PCI_DEVICE_ID_OXSEMI_16PCI958 0x9538 +#define PCIE_DEVICE_ID_NEO_2_OX_IBM 0x00F6 +#define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 +#define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d +#define PCI_VENDOR_ID_WCH 0x4348 +#define PCI_DEVICE_ID_WCH_CH352_2S 0x3253 +#define PCI_DEVICE_ID_WCH_CH353_4S 0x3453 +#define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046 +#define PCI_DEVICE_ID_WCH_CH353_1S1P 0x5053 +#define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053 +#define PCI_DEVICE_ID_WCH_CH355_4S 0x7173 +#define PCI_VENDOR_ID_AGESTAR 0x5372 +#define PCI_DEVICE_ID_AGESTAR_9375 0x6872 +#define PCI_VENDOR_ID_ASIX 0x9710 +#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a +#define PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800 0x818e + +#define PCIE_VENDOR_ID_WCH 0x1c00 +#define PCIE_DEVICE_ID_WCH_CH382_2S1P 0x3250 +#define PCIE_DEVICE_ID_WCH_CH384_4S 0x3470 +#define PCIE_DEVICE_ID_WCH_CH382_2S 0x3253 + +#define PCI_VENDOR_ID_PERICOM 0x12D8 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7951 0x7951 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7952 0x7952 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7954 0x7954 +#define PCI_DEVICE_ID_PERICOM_PI7C9X7958 0x7958 + +#define PCI_VENDOR_ID_ACCESIO 0x494f +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB 0x1051 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S 0x1053 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB 0x105C +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S 0x105E +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB 0x1091 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2 0x1093 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB 0x1099 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4 0x109B +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB 0x10D1 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM 0x10D3 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB 0x10DA +#define PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM 0x10DC +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1 0x1108 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2 0x1110 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2 0x1111 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4 0x1118 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4 0x1119 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S 0x1152 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S 0x115A +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2 0x1190 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2 0x1191 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4 0x1198 +#define PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4 0x1199 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM 0x11D0 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4 0x105A +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4 0x105B +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8 0x106A +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8 0x106B +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4 0x1098 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8 0x10A9 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM 0x10D9 +#define PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM 0x10E9 +#define PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM 0x11D8 + +#define PCIE_DEVICE_ID_NI_PXIE8430_2328 0x74C2 +#define PCIE_DEVICE_ID_NI_PXIE8430_23216 0x74C1 +#define PCI_DEVICE_ID_NI_PXI8431_4852 0x7081 +#define PCI_DEVICE_ID_NI_PXI8431_4854 0x70DE +#define PCI_DEVICE_ID_NI_PXI8431_4858 0x70E3 +#define PCI_DEVICE_ID_NI_PXI8433_4852 0x70E9 +#define PCI_DEVICE_ID_NI_PXI8433_4854 0x70ED +#define PCIE_DEVICE_ID_NI_PXIE8431_4858 0x74C4 +#define PCIE_DEVICE_ID_NI_PXIE8431_48516 0x74C3 + +#define PCI_DEVICE_ID_MOXA_CP102E 0x1024 +#define PCI_DEVICE_ID_MOXA_CP102EL 0x1025 +#define PCI_DEVICE_ID_MOXA_CP104EL_A 0x1045 +#define PCI_DEVICE_ID_MOXA_CP114EL 0x1144 +#define PCI_DEVICE_ID_MOXA_CP116E_A_A 0x1160 +#define PCI_DEVICE_ID_MOXA_CP116E_A_B 0x1161 +#define PCI_DEVICE_ID_MOXA_CP118EL_A 0x1182 +#define PCI_DEVICE_ID_MOXA_CP118E_A_I 0x1183 +#define PCI_DEVICE_ID_MOXA_CP132EL 0x1322 +#define PCI_DEVICE_ID_MOXA_CP134EL_A 0x1342 +#define PCI_DEVICE_ID_MOXA_CP138E_A 0x1381 +#define PCI_DEVICE_ID_MOXA_CP168EL_A 0x1683 + +/* Unknown vendors/cards - this should not be in linux/pci_ids.h */ +#define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 +#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588 + +/* + * Master list of serial port init/setup/exit quirks. + * This does not describe the general nature of the port. + * (ie, baud base, number and location of ports, etc) + * + * This list is ordered alphabetically by vendor then device. + * Specific entries must come before more generic entries. + */ +static struct pci_serial_quirk pci_serial_quirks[] = { + /* + * ADDI-DATA GmbH communication cards <info@addi-data.com> + */ + { + .vendor = PCI_VENDOR_ID_AMCC, + .device = PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = addidata_apci7800_setup, + }, + /* + * AFAVLAB cards - these may be called via parport_serial + * It is not clear whether this applies to all products. + */ + { + .vendor = PCI_VENDOR_ID_AFAVLAB, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = afavlab_setup, + }, + /* + * HP Diva + */ + { + .vendor = PCI_VENDOR_ID_HP, + .device = PCI_DEVICE_ID_HP_DIVA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_hp_diva_init, + .setup = pci_hp_diva_setup, + }, + /* + * Intel + */ + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_80960_RP, + .subvendor = 0xe4bf, + .subdevice = PCI_ANY_ID, + .init = pci_inteli960ni_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_8257X_SOL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = skip_tx_en_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82573L_SOL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = skip_tx_en_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_82573E_SOL, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = skip_tx_en_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_CE4100_UART, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = ce4100_serial_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = PCI_DEVICE_ID_INTEL_PATSBURG_KT, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = kt_serial_setup, + }, + /* + * ITE + */ + { + .vendor = PCI_VENDOR_ID_ITE, + .device = PCI_DEVICE_ID_ITE_8872, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ite887x_init, + .setup = pci_default_setup, + .exit = pci_ite887x_exit, + }, + /* + * National Instruments + */ + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PCI23216, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PCI2328, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PCI2324, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PCI2322, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PCI2324I, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PCI2322I, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8420_23216, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8420_2328, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8420_2324, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8420_2322, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8422_2324, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8422_2322, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8420_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8430_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8430_2328, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8430_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8430_23216, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8430_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8431_4852, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8431_4854, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8431_4858, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8433_4852, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCI_DEVICE_ID_NI_PXI8433_4854, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8431_4858, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + { + .vendor = PCI_VENDOR_ID_NI, + .device = PCIE_DEVICE_ID_NI_PXIE8431_48516, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_ni8430_init, + .setup = pci_ni8431_setup, + }, + /* Quatech */ + { + .vendor = PCI_VENDOR_ID_QUATECH, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_quatech_init, + .setup = pci_quatech_setup, + }, + /* + * Panacom + */ + { + .vendor = PCI_VENDOR_ID_PANACOM, + .device = PCI_DEVICE_ID_PANACOM_QUADMODEM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_plx9050_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_PANACOM, + .device = PCI_DEVICE_ID_PANACOM_DUALMODEM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_plx9050_init, + .setup = pci_default_setup, + }, + /* + * Pericom (Only 7954 - It have a offset jump for port 4) + */ + { + .vendor = PCI_VENDOR_ID_PERICOM, + .device = PCI_DEVICE_ID_PERICOM_PI7C9X7954, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + /* + * PLX + */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9050, + .subvendor = PCI_SUBVENDOR_ID_EXSYS, + .subdevice = PCI_SUBDEVICE_ID_EXSYS_4055, + .init = pci_plx9050_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_9050, + .subvendor = PCI_SUBVENDOR_ID_KEYSPAN, + .subdevice = PCI_SUBDEVICE_ID_KEYSPAN_SX2, + .init = pci_plx9050_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_ROMULUS, + .subvendor = PCI_VENDOR_ID_PLX, + .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, + .init = pci_plx9050_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup_four_at_eight, + }, + { + .vendor = PCI_VENDOR_ID_ACCESIO, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_pericom_setup, + }, /* + * SBS Technologies, Inc., PMC-OCTALPRO 232 + */ + { + .vendor = PCI_VENDOR_ID_SBSMODULARIO, + .device = PCI_DEVICE_ID_OCTPRO, + .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO, + .subdevice = PCI_SUBDEVICE_ID_OCTPRO232, + .init = sbs_init, + .setup = sbs_setup, + }, + /* + * SBS Technologies, Inc., PMC-OCTALPRO 422 + */ + { + .vendor = PCI_VENDOR_ID_SBSMODULARIO, + .device = PCI_DEVICE_ID_OCTPRO, + .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO, + .subdevice = PCI_SUBDEVICE_ID_OCTPRO422, + .init = sbs_init, + .setup = sbs_setup, + }, + /* + * SBS Technologies, Inc., P-Octal 232 + */ + { + .vendor = PCI_VENDOR_ID_SBSMODULARIO, + .device = PCI_DEVICE_ID_OCTPRO, + .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO, + .subdevice = PCI_SUBDEVICE_ID_POCTAL232, + .init = sbs_init, + .setup = sbs_setup, + }, + /* + * SBS Technologies, Inc., P-Octal 422 + */ + { + .vendor = PCI_VENDOR_ID_SBSMODULARIO, + .device = PCI_DEVICE_ID_OCTPRO, + .subvendor = PCI_SUBVENDOR_ID_SBSMODULARIO, + .subdevice = PCI_SUBDEVICE_ID_POCTAL422, + .init = sbs_init, + .setup = sbs_setup, + }, + /* + * SIIG cards - these may be called via parport_serial + */ + { + .vendor = PCI_VENDOR_ID_SIIG, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_siig_init, + .setup = pci_siig_setup, + }, + /* + * Titan cards + */ + { + .vendor = PCI_VENDOR_ID_TITAN, + .device = PCI_DEVICE_ID_TITAN_400L, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = titan_400l_800l_setup, + }, + { + .vendor = PCI_VENDOR_ID_TITAN, + .device = PCI_DEVICE_ID_TITAN_800L, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = titan_400l_800l_setup, + }, + /* + * Timedia cards + */ + { + .vendor = PCI_VENDOR_ID_TIMEDIA, + .device = PCI_DEVICE_ID_TIMEDIA_1889, + .subvendor = PCI_VENDOR_ID_TIMEDIA, + .subdevice = PCI_ANY_ID, + .probe = pci_timedia_probe, + .init = pci_timedia_init, + .setup = pci_timedia_setup, + }, + { + .vendor = PCI_VENDOR_ID_TIMEDIA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_timedia_setup, + }, + /* + * Sunix PCI serial boards + */ + { + .vendor = PCI_VENDOR_ID_SUNIX, + .device = PCI_DEVICE_ID_SUNIX_1999, + .subvendor = PCI_VENDOR_ID_SUNIX, + .subdevice = PCI_ANY_ID, + .setup = pci_sunix_setup, + }, + /* + * Xircom cards + */ + { + .vendor = PCI_VENDOR_ID_XIRCOM, + .device = PCI_DEVICE_ID_XIRCOM_X3201_MDM, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_xircom_init, + .setup = pci_default_setup, + }, + /* + * Netmos cards - these may be called via parport_serial + */ + { + .vendor = PCI_VENDOR_ID_NETMOS, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_netmos_init, + .setup = pci_netmos_9900_setup, + }, + /* + * EndRun Technologies + */ + { + .vendor = PCI_VENDOR_ID_ENDRUN, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_endrun_init, + .setup = pci_default_setup, + }, + /* + * For Oxford Semiconductor Tornado based devices + */ + { + .vendor = PCI_VENDOR_ID_OXSEMI, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_MAINPINE, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_DIGI, + .device = PCIE_DEVICE_ID_NEO_2_OX_IBM, + .subvendor = PCI_SUBVENDOR_ID_IBM, + .subdevice = PCI_ANY_ID, + .init = pci_oxsemi_tornado_init, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8811, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8812, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8813, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = PCI_VENDOR_ID_INTEL, + .device = 0x8814, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = 0x10DB, + .device = 0x8027, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = 0x10DB, + .device = 0x8028, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = 0x10DB, + .device = 0x8029, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = 0x10DB, + .device = 0x800C, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + { + .vendor = 0x10DB, + .device = 0x800D, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + }, + /* + * Cronyx Omega PCI (PLX-chip based) + */ + { + .vendor = PCI_VENDOR_ID_PLX, + .device = PCI_DEVICE_ID_PLX_CRONYX_OMEGA, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_omegapci_setup, + }, + /* WCH CH353 1S1P card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH353_1S1P, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch353_setup, + }, + /* WCH CH353 2S1P card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH353_2S1P, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch353_setup, + }, + /* WCH CH353 4S card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH353_4S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch353_setup, + }, + /* WCH CH353 2S1PF card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH353_2S1PF, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch353_setup, + }, + /* WCH CH352 2S card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH352_2S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch353_setup, + }, + /* WCH CH355 4S card (16550 clone) */ + { + .vendor = PCI_VENDOR_ID_WCH, + .device = PCI_DEVICE_ID_WCH_CH355_4S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch355_setup, + }, + /* WCH CH382 2S card (16850 clone) */ + { + .vendor = PCIE_VENDOR_ID_WCH, + .device = PCIE_DEVICE_ID_WCH_CH382_2S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch38x_setup, + }, + /* WCH CH382 2S1P card (16850 clone) */ + { + .vendor = PCIE_VENDOR_ID_WCH, + .device = PCIE_DEVICE_ID_WCH_CH382_2S1P, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch38x_setup, + }, + /* WCH CH384 4S card (16850 clone) */ + { + .vendor = PCIE_VENDOR_ID_WCH, + .device = PCIE_DEVICE_ID_WCH_CH384_4S, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_wch_ch38x_setup, + }, + /* + * ASIX devices with FIFO bug + */ + { + .vendor = PCI_VENDOR_ID_ASIX, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_asix_setup, + }, + /* + * Broadcom TruManage (NetXtreme) + */ + { + .vendor = PCI_VENDOR_ID_BROADCOM, + .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_brcm_trumanage_setup, + }, + { + .vendor = 0x1c29, + .device = 0x1104, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_setup, + .init = pci_fintek_init, + }, + { + .vendor = 0x1c29, + .device = 0x1108, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_setup, + .init = pci_fintek_init, + }, + { + .vendor = 0x1c29, + .device = 0x1112, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_setup, + .init = pci_fintek_init, + }, + /* + * MOXA + */ + { + .vendor = PCI_VENDOR_ID_MOXA, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_moxa_setup, + }, + { + .vendor = 0x1c29, + .device = 0x1204, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_f815xxa_setup, + .init = pci_fintek_f815xxa_init, + }, + { + .vendor = 0x1c29, + .device = 0x1208, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_f815xxa_setup, + .init = pci_fintek_f815xxa_init, + }, + { + .vendor = 0x1c29, + .device = 0x1212, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_fintek_f815xxa_setup, + .init = pci_fintek_f815xxa_init, + }, + + /* + * Default "match everything" terminator entry + */ + { + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + .setup = pci_default_setup, + } +}; + +static inline int quirk_id_matches(u32 quirk_id, u32 dev_id) +{ + return quirk_id == PCI_ANY_ID || quirk_id == dev_id; +} + +static struct pci_serial_quirk *find_quirk(struct pci_dev *dev) +{ + struct pci_serial_quirk *quirk; + + for (quirk = pci_serial_quirks; ; quirk++) + if (quirk_id_matches(quirk->vendor, dev->vendor) && + quirk_id_matches(quirk->device, dev->device) && + quirk_id_matches(quirk->subvendor, dev->subsystem_vendor) && + quirk_id_matches(quirk->subdevice, dev->subsystem_device)) + break; + return quirk; +} + +/* + * This is the configuration table for all of the PCI serial boards + * which we support. It is directly indexed by the pci_board_num_t enum + * value, which is encoded in the pci_device_id PCI probe table's + * driver_data member. + * + * The makeup of these names are: + * pbn_bn{_bt}_n_baud{_offsetinhex} + * + * bn = PCI BAR number + * bt = Index using PCI BARs + * n = number of serial ports + * baud = baud rate + * offsetinhex = offset for each sequential port (in hex) + * + * This table is sorted by (in order): bn, bt, baud, offsetindex, n. + * + * Please note: in theory if n = 1, _bt infix should make no difference. + * ie, pbn_b0_1_115200 is the same as pbn_b0_bt_1_115200 + */ +enum pci_board_num_t { + pbn_default = 0, + + pbn_b0_1_115200, + pbn_b0_2_115200, + pbn_b0_4_115200, + pbn_b0_5_115200, + pbn_b0_8_115200, + + pbn_b0_1_921600, + pbn_b0_2_921600, + pbn_b0_4_921600, + + pbn_b0_2_1130000, + + pbn_b0_4_1152000, + + pbn_b0_4_1250000, + + pbn_b0_2_1843200, + pbn_b0_4_1843200, + + pbn_b0_1_4000000, + + pbn_b0_bt_1_115200, + pbn_b0_bt_2_115200, + pbn_b0_bt_4_115200, + pbn_b0_bt_8_115200, + + pbn_b0_bt_1_460800, + pbn_b0_bt_2_460800, + pbn_b0_bt_4_460800, + + pbn_b0_bt_1_921600, + pbn_b0_bt_2_921600, + pbn_b0_bt_4_921600, + pbn_b0_bt_8_921600, + + pbn_b1_1_115200, + pbn_b1_2_115200, + pbn_b1_4_115200, + pbn_b1_8_115200, + pbn_b1_16_115200, + + pbn_b1_1_921600, + pbn_b1_2_921600, + pbn_b1_4_921600, + pbn_b1_8_921600, + + pbn_b1_2_1250000, + + pbn_b1_bt_1_115200, + pbn_b1_bt_2_115200, + pbn_b1_bt_4_115200, + + pbn_b1_bt_2_921600, + + pbn_b1_1_1382400, + pbn_b1_2_1382400, + pbn_b1_4_1382400, + pbn_b1_8_1382400, + + pbn_b2_1_115200, + pbn_b2_2_115200, + pbn_b2_4_115200, + pbn_b2_8_115200, + + pbn_b2_1_460800, + pbn_b2_4_460800, + pbn_b2_8_460800, + pbn_b2_16_460800, + + pbn_b2_1_921600, + pbn_b2_4_921600, + pbn_b2_8_921600, + + pbn_b2_8_1152000, + + pbn_b2_bt_1_115200, + pbn_b2_bt_2_115200, + pbn_b2_bt_4_115200, + + pbn_b2_bt_2_921600, + pbn_b2_bt_4_921600, + + pbn_b3_2_115200, + pbn_b3_4_115200, + pbn_b3_8_115200, + + pbn_b4_bt_2_921600, + pbn_b4_bt_4_921600, + pbn_b4_bt_8_921600, + + /* + * Board-specific versions. + */ + pbn_panacom, + pbn_panacom2, + pbn_panacom4, + pbn_plx_romulus, + pbn_endrun_2_4000000, + pbn_oxsemi, + pbn_oxsemi_1_4000000, + pbn_oxsemi_2_4000000, + pbn_oxsemi_4_4000000, + pbn_oxsemi_8_4000000, + pbn_intel_i960, + pbn_sgi_ioc3, + pbn_computone_4, + pbn_computone_6, + pbn_computone_8, + pbn_sbsxrsio, + pbn_pasemi_1682M, + pbn_ni8430_2, + pbn_ni8430_4, + pbn_ni8430_8, + pbn_ni8430_16, + pbn_ni8430_pxie_8, + pbn_ni8430_pxie_16, + pbn_ni8431_2, + pbn_ni8431_4, + pbn_ni8431_8, + pbn_ni8431_pxie_8, + pbn_ni8431_pxie_16, + pbn_ADDIDATA_PCIe_1_3906250, + pbn_ADDIDATA_PCIe_2_3906250, + pbn_ADDIDATA_PCIe_4_3906250, + pbn_ADDIDATA_PCIe_8_3906250, + pbn_ce4100_1_115200, + pbn_omegapci, + pbn_NETMOS9900_2s_115200, + pbn_brcm_trumanage, + pbn_fintek_4, + pbn_fintek_8, + pbn_fintek_12, + pbn_fintek_F81504A, + pbn_fintek_F81508A, + pbn_fintek_F81512A, + pbn_wch382_2, + pbn_wch384_4, + pbn_pericom_PI7C9X7951, + pbn_pericom_PI7C9X7952, + pbn_pericom_PI7C9X7954, + pbn_pericom_PI7C9X7958, + pbn_sunix_pci_1s, + pbn_sunix_pci_2s, + pbn_sunix_pci_4s, + pbn_sunix_pci_8s, + pbn_sunix_pci_16s, + pbn_moxa8250_2p, + pbn_moxa8250_4p, + pbn_moxa8250_8p, +}; + +/* + * uart_offset - the space between channels + * reg_shift - describes how the UART registers are mapped + * to PCI memory by the card. + * For example IER register on SBS, Inc. PMC-OctPro is located at + * offset 0x10 from the UART base, while UART_IER is defined as 1 + * in include/linux/serial_reg.h, + * see first lines of serial_in() and serial_out() in 8250.c +*/ + +static struct pciserial_board pci_boards[] = { + [pbn_default] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_1_115200] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_2_115200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_4_115200] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_5_115200] = { + .flags = FL_BASE0, + .num_ports = 5, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_8_115200] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_1_921600] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_2_921600] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_4_921600] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b0_2_1130000] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 1130000, + .uart_offset = 8, + }, + + [pbn_b0_4_1152000] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 1152000, + .uart_offset = 8, + }, + + [pbn_b0_4_1250000] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 1250000, + .uart_offset = 8, + }, + + [pbn_b0_2_1843200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 1843200, + .uart_offset = 8, + }, + [pbn_b0_4_1843200] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 1843200, + .uart_offset = 8, + }, + + [pbn_b0_1_4000000] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 4000000, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_2_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_4_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b0_bt_8_115200] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b0_bt_2_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b0_bt_4_460800] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 460800, + .uart_offset = 8, + }, + + [pbn_b0_bt_1_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_2_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_4_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b0_bt_8_921600] = { + .flags = FL_BASE0|FL_BASE_BARS, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_1_115200] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_2_115200] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_4_115200] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_8_115200] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_16_115200] = { + .flags = FL_BASE1, + .num_ports = 16, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b1_1_921600] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_2_921600] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_4_921600] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_8_921600] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b1_2_1250000] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 1250000, + .uart_offset = 8, + }, + + [pbn_b1_bt_1_115200] = { + .flags = FL_BASE1|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_bt_2_115200] = { + .flags = FL_BASE1|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b1_bt_4_115200] = { + .flags = FL_BASE1|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b1_bt_2_921600] = { + .flags = FL_BASE1|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b1_1_1382400] = { + .flags = FL_BASE1, + .num_ports = 1, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_2_1382400] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_4_1382400] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 1382400, + .uart_offset = 8, + }, + [pbn_b1_8_1382400] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 1382400, + .uart_offset = 8, + }, + + [pbn_b2_1_115200] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_2_115200] = { + .flags = FL_BASE2, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_4_115200] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_8_115200] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b2_1_460800] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_4_460800] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_8_460800] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 460800, + .uart_offset = 8, + }, + [pbn_b2_16_460800] = { + .flags = FL_BASE2, + .num_ports = 16, + .base_baud = 460800, + .uart_offset = 8, + }, + + [pbn_b2_1_921600] = { + .flags = FL_BASE2, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_4_921600] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_8_921600] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b2_8_1152000] = { + .flags = FL_BASE2, + .num_ports = 8, + .base_baud = 1152000, + .uart_offset = 8, + }, + + [pbn_b2_bt_1_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 1, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_bt_2_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b2_bt_4_115200] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b2_bt_2_921600] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b2_bt_4_921600] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + + [pbn_b3_2_115200] = { + .flags = FL_BASE3, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b3_4_115200] = { + .flags = FL_BASE3, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_b3_8_115200] = { + .flags = FL_BASE3, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 8, + }, + + [pbn_b4_bt_2_921600] = { + .flags = FL_BASE4, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b4_bt_4_921600] = { + .flags = FL_BASE4, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8, + }, + [pbn_b4_bt_8_921600] = { + .flags = FL_BASE4, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 8, + }, + + /* + * Entries following this are board-specific. + */ + + /* + * Panacom - IOMEM + */ + [pbn_panacom] = { + .flags = FL_BASE2, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + [pbn_panacom2] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + [pbn_panacom4] = { + .flags = FL_BASE2|FL_BASE_BARS, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x400, + .reg_shift = 7, + }, + + /* I think this entry is broken - the first_offset looks wrong --rmk */ + [pbn_plx_romulus] = { + .flags = FL_BASE2, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 8 << 2, + .reg_shift = 2, + .first_offset = 0x03, + }, + + /* + * EndRun Technologies + * Uses the size of PCI Base region 0 to + * signal now many ports are available + * 2 port 952 Uart support + */ + [pbn_endrun_2_4000000] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + + /* + * This board uses the size of PCI Base region 0 to + * signal now many ports are available + */ + [pbn_oxsemi] = { + .flags = FL_BASE0|FL_REGION_SZ_CAP, + .num_ports = 32, + .base_baud = 115200, + .uart_offset = 8, + }, + [pbn_oxsemi_1_4000000] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_oxsemi_2_4000000] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_oxsemi_4_4000000] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_oxsemi_8_4000000] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 4000000, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + + + /* + * EKF addition for i960 Boards form EKF with serial port. + * Max 256 ports. + */ + [pbn_intel_i960] = { + .flags = FL_BASE0, + .num_ports = 32, + .base_baud = 921600, + .uart_offset = 8 << 2, + .reg_shift = 2, + .first_offset = 0x10000, + }, + [pbn_sgi_ioc3] = { + .flags = FL_BASE0|FL_NOIRQ, + .num_ports = 1, + .base_baud = 458333, + .uart_offset = 8, + .reg_shift = 0, + .first_offset = 0x20178, + }, + + /* + * Computone - uses IOMEM. + */ + [pbn_computone_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_computone_6] = { + .flags = FL_BASE0, + .num_ports = 6, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_computone_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x40, + .reg_shift = 2, + .first_offset = 0x200, + }, + [pbn_sbsxrsio] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 460800, + .uart_offset = 256, + .reg_shift = 4, + }, + /* + * PA Semi PWRficient PA6T-1682M on-chip UART + */ + [pbn_pasemi_1682M] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 8333333, + }, + /* + * National Instruments 843x + */ + [pbn_ni8430_16] = { + .flags = FL_BASE0, + .num_ports = 16, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8430_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8430_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8430_2] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8430_pxie_16] = { + .flags = FL_BASE0, + .num_ports = 16, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8430_pxie_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_2] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 3686400, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_pxie_16] = { + .flags = FL_BASE0, + .num_ports = 16, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + [pbn_ni8431_pxie_8] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3125000, + .uart_offset = 0x10, + .first_offset = 0x800, + }, + /* + * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com> + */ + [pbn_ADDIDATA_PCIe_1_3906250] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ADDIDATA_PCIe_2_3906250] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ADDIDATA_PCIe_4_3906250] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ADDIDATA_PCIe_8_3906250] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 3906250, + .uart_offset = 0x200, + .first_offset = 0x1000, + }, + [pbn_ce4100_1_115200] = { + .flags = FL_BASE_BARS, + .num_ports = 2, + .base_baud = 921600, + .reg_shift = 2, + }, + [pbn_omegapci] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 115200, + .uart_offset = 0x200, + }, + [pbn_NETMOS9900_2s_115200] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + }, + [pbn_brcm_trumanage] = { + .flags = FL_BASE0, + .num_ports = 1, + .reg_shift = 2, + .base_baud = 115200, + }, + [pbn_fintek_4] = { + .num_ports = 4, + .uart_offset = 8, + .base_baud = 115200, + .first_offset = 0x40, + }, + [pbn_fintek_8] = { + .num_ports = 8, + .uart_offset = 8, + .base_baud = 115200, + .first_offset = 0x40, + }, + [pbn_fintek_12] = { + .num_ports = 12, + .uart_offset = 8, + .base_baud = 115200, + .first_offset = 0x40, + }, + [pbn_fintek_F81504A] = { + .num_ports = 4, + .uart_offset = 8, + .base_baud = 115200, + }, + [pbn_fintek_F81508A] = { + .num_ports = 8, + .uart_offset = 8, + .base_baud = 115200, + }, + [pbn_fintek_F81512A] = { + .num_ports = 12, + .uart_offset = 8, + .base_baud = 115200, + }, + [pbn_wch382_2] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 115200, + .uart_offset = 8, + .first_offset = 0xC0, + }, + [pbn_wch384_4] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 115200, + .uart_offset = 8, + .first_offset = 0xC0, + }, + /* + * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART + */ + [pbn_pericom_PI7C9X7951] = { + .flags = FL_BASE0, + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_pericom_PI7C9X7952] = { + .flags = FL_BASE0, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_pericom_PI7C9X7954] = { + .flags = FL_BASE0, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_pericom_PI7C9X7958] = { + .flags = FL_BASE0, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_1s] = { + .num_ports = 1, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_2s] = { + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_4s] = { + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_8s] = { + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_sunix_pci_16s] = { + .num_ports = 16, + .base_baud = 921600, + .uart_offset = 0x8, + }, + [pbn_moxa8250_2p] = { + .flags = FL_BASE1, + .num_ports = 2, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_moxa8250_4p] = { + .flags = FL_BASE1, + .num_ports = 4, + .base_baud = 921600, + .uart_offset = 0x200, + }, + [pbn_moxa8250_8p] = { + .flags = FL_BASE1, + .num_ports = 8, + .base_baud = 921600, + .uart_offset = 0x200, + }, +}; + +static const struct pci_device_id blacklist[] = { + /* softmodems */ + { PCI_VDEVICE(AL, 0x5457), }, /* ALi Corporation M5457 AC'97 Modem */ + { PCI_VDEVICE(MOTOROLA, 0x3052), }, /* Motorola Si3052-based modem */ + { PCI_DEVICE(0x1543, 0x3052), }, /* Si3052-based modem, default IDs */ + + /* multi-io cards handled by parport_serial */ + { PCI_DEVICE(0x4348, 0x7053), }, /* WCH CH353 2S1P */ + { PCI_DEVICE(0x4348, 0x5053), }, /* WCH CH353 1S1P */ + { PCI_DEVICE(0x1c00, 0x3250), }, /* WCH CH382 2S1P */ + + /* Intel platforms with MID UART */ + { PCI_VDEVICE(INTEL, 0x081b), }, + { PCI_VDEVICE(INTEL, 0x081c), }, + { PCI_VDEVICE(INTEL, 0x081d), }, + { PCI_VDEVICE(INTEL, 0x1191), }, + { PCI_VDEVICE(INTEL, 0x18d8), }, + { PCI_VDEVICE(INTEL, 0x19d8), }, + + /* Intel platforms with DesignWare UART */ + { PCI_VDEVICE(INTEL, 0x0936), }, + { PCI_VDEVICE(INTEL, 0x0f0a), }, + { PCI_VDEVICE(INTEL, 0x0f0c), }, + { PCI_VDEVICE(INTEL, 0x228a), }, + { PCI_VDEVICE(INTEL, 0x228c), }, + { PCI_VDEVICE(INTEL, 0x9ce3), }, + { PCI_VDEVICE(INTEL, 0x9ce4), }, + + /* Exar devices */ + { PCI_VDEVICE(EXAR, PCI_ANY_ID), }, + { PCI_VDEVICE(COMMTECH, PCI_ANY_ID), }, + + /* End of the black list */ + { } +}; + +static int serial_pci_is_class_communication(struct pci_dev *dev) +{ + /* + * If it is not a communications device or the programming + * interface is greater than 6, give up. + */ + if ((((dev->class >> 8) != PCI_CLASS_COMMUNICATION_SERIAL) && + ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MULTISERIAL) && + ((dev->class >> 8) != PCI_CLASS_COMMUNICATION_MODEM)) || + (dev->class & 0xff) > 6) + return -ENODEV; + + return 0; +} + +/* + * Given a complete unknown PCI device, try to use some heuristics to + * guess what the configuration might be, based on the pitiful PCI + * serial specs. Returns 0 on success, -ENODEV on failure. + */ +static int +serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board) +{ + int num_iomem, num_port, first_port = -1, i; + int rc; + + rc = serial_pci_is_class_communication(dev); + if (rc) + return rc; + + /* + * Should we try to make guesses for multiport serial devices later? + */ + if ((dev->class >> 8) == PCI_CLASS_COMMUNICATION_MULTISERIAL) + return -ENODEV; + + num_iomem = num_port = 0; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO) { + num_port++; + if (first_port == -1) + first_port = i; + } + if (pci_resource_flags(dev, i) & IORESOURCE_MEM) + num_iomem++; + } + + /* + * If there is 1 or 0 iomem regions, and exactly one port, + * use it. We guess the number of ports based on the IO + * region size. + */ + if (num_iomem <= 1 && num_port == 1) { + board->flags = first_port; + board->num_ports = pci_resource_len(dev, first_port) / 8; + return 0; + } + + /* + * Now guess if we've got a board which indexes by BARs. + * Each IO BAR should be 8 bytes, and they should follow + * consecutively. + */ + first_port = -1; + num_port = 0; + for (i = 0; i < PCI_NUM_BAR_RESOURCES; i++) { + if (pci_resource_flags(dev, i) & IORESOURCE_IO && + pci_resource_len(dev, i) == 8 && + (first_port == -1 || (first_port + num_port) == i)) { + num_port++; + if (first_port == -1) + first_port = i; + } + } + + if (num_port > 1) { + board->flags = first_port | FL_BASE_BARS; + board->num_ports = num_port; + return 0; + } + + return -ENODEV; +} + +static inline int +serial_pci_matches(const struct pciserial_board *board, + const struct pciserial_board *guessed) +{ + return + board->num_ports == guessed->num_ports && + board->base_baud == guessed->base_baud && + board->uart_offset == guessed->uart_offset && + board->reg_shift == guessed->reg_shift && + board->first_offset == guessed->first_offset; +} + +static struct serial_private * +pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) +{ + struct uart_8250_port uart; + struct serial_private *priv; + struct pci_serial_quirk *quirk; + int rc, nr_ports, i; + + nr_ports = board->num_ports; + + /* + * Find an init and setup quirks. + */ + quirk = find_quirk(dev); + + /* + * Run the new-style initialization function. + * The initialization function returns: + * <0 - error + * 0 - use board->num_ports + * >0 - number of ports + */ + if (quirk->init) { + rc = quirk->init(dev); + if (rc < 0) { + priv = ERR_PTR(rc); + goto err_out; + } + if (rc) + nr_ports = rc; + } + + priv = xzalloc(sizeof(struct serial_private) + + sizeof(unsigned int) * nr_ports); + + priv->dev = dev; + priv->quirk = quirk; + + memset(&uart, 0, sizeof(uart)); + uart.pdata = xzalloc(sizeof(*uart.pdata)); + uart.pdata->clock = board->base_baud * 16; + + if (rc < 0) { + kfree(priv); + priv = ERR_PTR(rc); + goto err_deinit; + } + + for (i = 0; i < nr_ports; i++) { + struct device_d *ns16550_dev; + struct resource *res; + + rc = quirk->setup(priv, board, &uart, i); + if (rc == -ENOSYS) { + priv = ERR_PTR(-ENOSYS); + goto err_deinit; + } + + if (rc) + break; + + res = &uart.resource; + + dev_dbg(&dev->dev, "setup PCI %s console @ 0x%llx-0x%llx\n", + res->flags & IORESOURCE_MEM ? "MMIO" : "IO port", + res->start, res->end); + + ns16550_dev = device_alloc("ns16550_serial", DEVICE_ID_DYNAMIC); + ns16550_dev->platform_data = uart.pdata; + ns16550_dev->parent = &dev->dev; + device_add_resource(ns16550_dev, NULL, + res->start, res->end - res->start + 1, + res->flags); + + rc = platform_device_register(ns16550_dev); + if (rc < 0) { + dev_err(&dev->dev, "couldn't register PCI %s console @0x%llx: %s\n", + res->flags & IORESOURCE_MEM ? "MMIO" : "IO port", + res->start, strerror(-rc)); + + break; + } + } + priv->nr = i; + priv->board = board; + return priv; + +err_deinit: + if (quirk->exit) + quirk->exit(dev); +err_out: + return priv; +} + +/* + * Probe one serial board. Unfortunately, there is no rhyme nor reason + * to the arrangement of serial ports on a PCI card. + */ +static int +pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent) +{ + struct pci_serial_quirk *quirk; + struct serial_private *priv; + const struct pciserial_board *board; + const struct pci_device_id *exclude; + struct pciserial_board tmp; + int rc; + + quirk = find_quirk(dev); + if (quirk->probe) { + rc = quirk->probe(dev); + if (rc) + return rc; + } + + if (ent->driver_data >= ARRAY_SIZE(pci_boards)) { + dev_err(&dev->dev, "invalid driver_data: %ld\n", + ent->driver_data); + return -EINVAL; + } + + board = &pci_boards[ent->driver_data]; + + exclude = pci_match_id(blacklist, dev); + if (exclude) + return -ENODEV; + + rc = pci_enable_device(dev); + if (rc) + return rc; + + if (ent->driver_data == pbn_default) { + /* + * Use a copy of the pci_board entry for this; + * avoid changing entries in the table. + */ + memcpy(&tmp, board, sizeof(struct pciserial_board)); + board = &tmp; + + /* + * We matched one of our class entries. Try to + * determine the parameters of this board. + */ + rc = serial_pci_guess_board(dev, &tmp); + if (rc) + return rc; + } else { + /* + * We matched an explicit entry. If we are able to + * detect this boards settings with our heuristic, + * then we no longer need this entry. + */ + memcpy(&tmp, &pci_boards[pbn_default], + sizeof(struct pciserial_board)); + rc = serial_pci_guess_board(dev, &tmp); + if (rc == 0 && serial_pci_matches(board, &tmp)) + moan_device("Redundant entry in serial pci_table.", + dev); + } + + priv = pciserial_init_ports(dev, board); + if (IS_ERR(priv)) { + if (PTR_ERR(priv) == -ENOSYS) { + dev_err(&dev->dev, + "serial port requires not-yet-supported quirky behavior.\n" + "Consider porting it over from the Linux 8250_pci driver\n"); + } + + return PTR_ERR(priv); + } + + dev->dev.priv = priv; + return 0; +} + +static const struct pci_device_id serial_pci_tbl[] = { + /* Advantech use PCI_DEVICE_ID_ADVANTECH_PCI3620 (0x3620) as 'PCI_SUBVENDOR_ID' */ + { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3620, + PCI_DEVICE_ID_ADVANTECH_PCI3620, 0x0001, 0, 0, + pbn_b2_8_921600 }, + /* Advantech also use 0x3618 and 0xf618 */ + { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCI3618, + PCI_DEVICE_ID_ADVANTECH_PCI3618, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_ADVANTECH_PCIf618, + PCI_DEVICE_ID_ADVANTECH_PCI3618, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, + pbn_b1_8_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, + pbn_b1_4_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V960, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, + pbn_b1_2_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_232, 0, 0, + pbn_b1_8_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_232, 0, 0, + pbn_b1_4_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_232, 0, 0, + pbn_b1_2_1382400 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_4_4, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485, 0, 0, + pbn_b1_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH4_485_2_2, 0, 0, + pbn_b1_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_485, 0, 0, + pbn_b1_2_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH8_485_2_6, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH081101V1, 0, 0, + pbn_b1_8_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH041101V1, 0, 0, + pbn_b1_4_921600 }, + { PCI_VENDOR_ID_V3, PCI_DEVICE_ID_V3_V351, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_BH2_20MHZ, 0, 0, + pbn_b1_2_1250000 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_2, 0, 0, + pbn_b0_2_1843200 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_SUBVENDOR_ID_CONNECT_TECH, + PCI_SUBDEVICE_ID_CONNECT_TECH_TITAN_4, 0, 0, + pbn_b0_4_1843200 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_AFAVLAB, + PCI_SUBDEVICE_ID_AFAVLAB_P061, 0, 0, + pbn_b0_4_1152000 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_1_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM422, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM232, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_COMM8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_115200 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_7803, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_460800 }, + { PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_UCOMM8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_115200 }, + + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_GTEK_SERIAL2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_921600 }, + /* + * VScom SPCOM800, from sl@s.pl + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_SPCOM800, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_921600 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_1077, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_4_921600 }, + /* Unknown card - subdevice 0x1584 */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_PLX, + PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0, + pbn_b2_4_115200 }, + /* Unknown card - subdevice 0x1588 */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_VENDOR_ID_PLX, + PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0, + pbn_b2_8_115200 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_KEYSPAN, + PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, + pbn_panacom }, + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_QUADMODEM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_panacom4 }, + { PCI_VENDOR_ID_PANACOM, PCI_DEVICE_ID_PANACOM_DUALMODEM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_panacom2 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, + PCI_VENDOR_ID_ESDGMBH, + PCI_DEVICE_ID_ESDGMBH_CPCIASIO4, 0, 0, + pbn_b2_4_115200 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST4, 0, 0, + pbn_b2_4_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST8, 0, 0, + pbn_b2_8_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST16, 0, 0, + pbn_b2_16_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIFAST, + PCI_SUBDEVICE_ID_CHASE_PCIFAST16FMC, 0, 0, + pbn_b2_16_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIRAS, + PCI_SUBDEVICE_ID_CHASE_PCIRAS4, 0, 0, + pbn_b2_4_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_CHASE_PCIRAS, + PCI_SUBDEVICE_ID_CHASE_PCIRAS8, 0, 0, + pbn_b2_8_460800 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, + PCI_SUBVENDOR_ID_EXSYS, + PCI_SUBDEVICE_ID_EXSYS_4055, 0, 0, + pbn_b2_4_115200 }, + /* + * Megawolf Romulus PCI Serial Card, from Mike Hudson + * (Exoray@isys.ca) + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS, + 0x10b5, 0x106a, 0, 0, + pbn_plx_romulus }, + /* + * EndRun Technologies. PCI express device range. + * EndRun PTP/1588 has 2 Native UARTs. + */ + { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_endrun_2_4000000 }, + /* + * Quatech cards. These actually have configurable clocks but for + * now we just use the default. + * + * 100 series are RS232, 200 series RS422, + */ + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC100E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSC200E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSC200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100D, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_8_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESC100M, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_8_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCP200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCP200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_QSCLP200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_4_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_DSCLP200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_2_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_SSCLP200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_115200 }, + { PCI_VENDOR_ID_QUATECH, PCI_DEVICE_ID_QUATECH_ESCLP100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_8_115200 }, + + { PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_VENDOR_ID_SPECIALIX, PCI_SUBDEVICE_ID_SPECIALIX_SPEED4, + 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL, + 0, 0, + pbn_b0_4_1152000 }, + { PCI_VENDOR_ID_OXSEMI, 0x9505, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_921600 }, + + /* + * The below card is a little controversial since it is the + * subject of a PCI vendor/device ID clash. (See + * www.ussg.iu.edu/hypermail/linux/kernel/0303.1/0516.html). + * For now just used the hex ID 0x950a. + */ + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_2_1130000 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950, + PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0, + pbn_b0_1_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_115200 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI958, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_8_1152000 }, + + /* + * Oxford Semiconductor Inc. Tornado PCI express device range. + */ + { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_4_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_4_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_8_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_8_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */ + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + /* + * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado + */ + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0, + pbn_oxsemi_2_4000000 }, + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0, + pbn_oxsemi_4_4000000 }, + { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */ + PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0, + pbn_oxsemi_8_4000000 }, + + /* + * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado + */ + { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM, + PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + + /* + * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards, + * from skokodyn@yahoo.com + */ + { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO, + PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO232, 0, 0, + pbn_sbsxrsio }, + { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO, + PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_OCTPRO422, 0, 0, + pbn_sbsxrsio }, + { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO, + PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL232, 0, 0, + pbn_sbsxrsio }, + { PCI_VENDOR_ID_SBSMODULARIO, PCI_DEVICE_ID_OCTPRO, + PCI_SUBVENDOR_ID_SBSMODULARIO, PCI_SUBDEVICE_ID_POCTAL422, 0, 0, + pbn_sbsxrsio }, + + /* + * Digitan DS560-558, from jimd@esoft.com + */ + { PCI_VENDOR_ID_ATT, PCI_DEVICE_ID_ATT_VENUS_MODEM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_115200 }, + + /* + * Titan Electronic cards + * The 400L and 800L have a custom setup quirk. + */ + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_2_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100L, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200L, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400L, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800L, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b4_bt_2_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b4_bt_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b4_bt_8_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400EH, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EH, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800EHB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_1_4000000 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_4_4000000 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_8_4000000 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi_2_4000000 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200V3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400V3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_410V3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800V3B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_4_921600 }, + + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_460800 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_460800 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_460800 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_10x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_1S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_2S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_4S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_550, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + { PCI_VENDOR_ID_SIIG, PCI_DEVICE_ID_SIIG_8S_20x_850, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_921600 }, + + /* + * Computone devices submitted by Doug McNash dmcnash@computone.com + */ + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG4, + 0, 0, pbn_computone_4 }, + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG8, + 0, 0, pbn_computone_8 }, + { PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_PG, + PCI_SUBVENDOR_ID_COMPUTONE, PCI_SUBDEVICE_ID_COMPUTONE_PG6, + 0, 0, pbn_computone_6 }, + + { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI95N, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_oxsemi }, + { PCI_VENDOR_ID_TIMEDIA, PCI_DEVICE_ID_TIMEDIA_1889, + PCI_VENDOR_ID_TIMEDIA, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_921600 }, + + /* + * Sunix PCI serial boards + */ + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0001, 0, 0, + pbn_sunix_pci_1s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0002, 0, 0, + pbn_sunix_pci_2s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0004, 0, 0, + pbn_sunix_pci_4s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0084, 0, 0, + pbn_sunix_pci_4s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0008, 0, 0, + pbn_sunix_pci_8s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0088, 0, 0, + pbn_sunix_pci_8s }, + { PCI_VENDOR_ID_SUNIX, PCI_DEVICE_ID_SUNIX_1999, + PCI_VENDOR_ID_SUNIX, 0x0010, 0, 0, + pbn_sunix_pci_16s }, + + /* + * AFAVLAB serial card, from Harald Welte <laforge@gnumonks.org> + */ + { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P028, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_115200 }, + { PCI_VENDOR_ID_AFAVLAB, PCI_DEVICE_ID_AFAVLAB_P030, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_8_115200 }, + + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_DSERIAL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATRO_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUATTRO_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_OCTO_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_4_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_PLUS, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_QUAD_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_2_460800 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_SSERIAL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_115200 }, + { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_PORT_650, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_bt_1_460800 }, + + /* + * Korenix Jetcard F0/F1 cards (JC1204, JC1208, JC1404, JC1408). + * Cards are identified by their subsystem vendor IDs, which + * (in hex) match the model number. + * + * Note that JC140x are RS422/485 cards which require ox950 + * ACR = 0x10, and as such are not currently fully supported. + */ + { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0, + 0x1204, 0x0004, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0, + 0x1208, 0x0004, 0, 0, + pbn_b0_4_921600 }, +/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0, + 0x1402, 0x0002, 0, 0, + pbn_b0_2_921600 }, */ +/* { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF0, + 0x1404, 0x0004, 0, 0, + pbn_b0_4_921600 }, */ + { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF1, + 0x1208, 0x0004, 0, 0, + pbn_b0_4_921600 }, + + { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2, + 0x1204, 0x0004, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF2, + 0x1208, 0x0004, 0, 0, + pbn_b0_4_921600 }, + { PCI_VENDOR_ID_KORENIX, PCI_DEVICE_ID_KORENIX_JETCARDF3, + 0x1208, 0x0004, 0, 0, + pbn_b0_4_921600 }, + /* + * Dell Remote Access Card 4 - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RAC4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + + /* + * Dell Remote Access Card III - Tim_T_Murphy@Dell.com + */ + { PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_RACIII, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_1_1382400 }, + + /* + * RAStel 2 port modem, gerg@moreton.com.au + */ + { PCI_VENDOR_ID_MORETON, PCI_DEVICE_ID_RASTEL_2PORT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_bt_2_115200 }, + + /* + * EKF addition for i960 Boards form EKF with serial port + */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_80960_RP, + 0xE4BF, PCI_ANY_ID, 0, 0, + pbn_intel_i960 }, + + /* + * Xircom Cardbus/Ethernet combos + */ + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_X3201_MDM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, + /* + * Xircom RBM56G cardbus modem - Dirk Arnold (temp entry) + */ + { PCI_VENDOR_ID_XIRCOM, PCI_DEVICE_ID_XIRCOM_RBM56G, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, + + /* + * Untested PCI modems, sent in from various folks... + */ + + /* + * Elsa Model 56K PCI Modem, from Andreas Rath <arh@01019freenet.de> + */ + { PCI_VENDOR_ID_ROCKWELL, 0x1004, + 0x1048, 0x1500, 0, 0, + pbn_b1_1_115200 }, + + { PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, + 0xFF00, 0, 0, 0, + pbn_sgi_ioc3 }, + + /* + * HP Diva card + */ + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, + PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_RMP3, 0, 0, + pbn_b1_1_115200 }, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_5_115200 }, + { PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b2_1_115200 }, + + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b3_2_115200 }, + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b3_4_115200 }, + { PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b3_8_115200 }, + /* + * Pericom PI7C9X795[1248] Uno/Dual/Quad/Octal UART + */ + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7951, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7951 }, + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7952, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7954, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_PERICOM, PCI_DEVICE_ID_PERICOM_PI7C9X7958, + PCI_ANY_ID, PCI_ANY_ID, + 0, + 0, pbn_pericom_PI7C9X7958 }, + /* + * ACCES I/O Products quad + */ + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_2DB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4DB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_2SMDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_2SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SMDB, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_COM_4SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_1, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7951 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM422_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM485_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_2, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_MPCIE_ICM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_2SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7952 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM422_8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM485_8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_4, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM232_8, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_4SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_COM_8SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7958 }, + { PCI_VENDOR_ID_ACCESIO, PCI_DEVICE_ID_ACCESIO_PCIE_ICM_4SM, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pericom_PI7C9X7954 }, + /* + * Topic TP560 Data/Fax/Voice 56k modem (reported by Evan Clarke) + */ + { PCI_VENDOR_ID_TOPIC, PCI_DEVICE_ID_TOPIC_TP560, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b0_1_115200 }, + /* + * ITE + */ + { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_8872, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + pbn_b1_bt_1_115200 }, + + /* + * IntaShield IS-200 + */ + { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS200, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0811 */ + pbn_b2_2_115200 }, + /* + * IntaShield IS-400 + */ + { PCI_VENDOR_ID_INTASHIELD, PCI_DEVICE_ID_INTASHIELD_IS400, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, /* 135a.0dc0 */ + pbn_b2_4_115200 }, + /* + * BrainBoxes UC-260 + */ + { PCI_VENDOR_ID_INTASHIELD, 0x0D21, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, + pbn_b2_4_115200 }, + { PCI_VENDOR_ID_INTASHIELD, 0x0E34, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, 0xffff00, + pbn_b2_4_115200 }, + /* + * Perle PCI-RAS cards + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, + PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS4, + 0, 0, pbn_b2_4_921600 }, + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030, + PCI_SUBVENDOR_ID_PERLE, PCI_SUBDEVICE_ID_PCI_RAS8, + 0, 0, pbn_b2_8_921600 }, + + /* + * Mainpine series cards: Fairly standard layout but fools + * parts of the autodetect in some cases and uses otherwise + * unmatched communications subclasses in the PCI Express case + */ + + { /* RockForceDUO */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0200, + 0, 0, pbn_b0_2_115200 }, + { /* RockForceQUATRO */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0300, + 0, 0, pbn_b0_4_115200 }, + { /* RockForceDUO+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0400, + 0, 0, pbn_b0_2_115200 }, + { /* RockForceQUATRO+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0500, + 0, 0, pbn_b0_4_115200 }, + { /* RockForce+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0600, + 0, 0, pbn_b0_2_115200 }, + { /* RockForce+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0700, + 0, 0, pbn_b0_4_115200 }, + { /* RockForceOCTO+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0800, + 0, 0, pbn_b0_8_115200 }, + { /* RockForceDUO+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0C00, + 0, 0, pbn_b0_2_115200 }, + { /* RockForceQUARTRO+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x0D00, + 0, 0, pbn_b0_4_115200 }, + { /* RockForceOCTO+ */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x1D00, + 0, 0, pbn_b0_8_115200 }, + { /* RockForceD1 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2000, + 0, 0, pbn_b0_1_115200 }, + { /* RockForceF1 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2100, + 0, 0, pbn_b0_1_115200 }, + { /* RockForceD2 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2200, + 0, 0, pbn_b0_2_115200 }, + { /* RockForceF2 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2300, + 0, 0, pbn_b0_2_115200 }, + { /* RockForceD4 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2400, + 0, 0, pbn_b0_4_115200 }, + { /* RockForceF4 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2500, + 0, 0, pbn_b0_4_115200 }, + { /* RockForceD8 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2600, + 0, 0, pbn_b0_8_115200 }, + { /* RockForceF8 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x2700, + 0, 0, pbn_b0_8_115200 }, + { /* IQ Express D1 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3000, + 0, 0, pbn_b0_1_115200 }, + { /* IQ Express F1 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3100, + 0, 0, pbn_b0_1_115200 }, + { /* IQ Express D2 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3200, + 0, 0, pbn_b0_2_115200 }, + { /* IQ Express F2 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3300, + 0, 0, pbn_b0_2_115200 }, + { /* IQ Express D4 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3400, + 0, 0, pbn_b0_4_115200 }, + { /* IQ Express F4 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3500, + 0, 0, pbn_b0_4_115200 }, + { /* IQ Express D8 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3C00, + 0, 0, pbn_b0_8_115200 }, + { /* IQ Express F8 */ + PCI_VENDOR_ID_MAINPINE, PCI_DEVICE_ID_MAINPINE_PBRIDGE, + PCI_VENDOR_ID_MAINPINE, 0x3D00, + 0, 0, pbn_b0_8_115200 }, + + + /* + * PA Semi PA6T-1682M on-chip UART + */ + { PCI_VENDOR_ID_PASEMI, 0xa004, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_pasemi_1682M }, + + /* + * National Instruments + */ + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI23216, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_16_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2328, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_8_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_4_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2324I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_4_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI2322I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_23216, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_16_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2328, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_8_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_4_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8420_2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_4_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8422_2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_b1_bt_2_115200 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_4 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_4 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_2328, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_8 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_2328, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_8 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8430_23216, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_16 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8430_23216, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_16 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2322, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8432_2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_4 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PCI8432_2324, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_4 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_2328, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_pxie_8 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8430_23216, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8430_pxie_16 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4852, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4854, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_4 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8431_4858, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_8 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_4858, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_pxie_8 }, + { PCI_VENDOR_ID_NI, PCIE_DEVICE_ID_NI_PXIE8431_48516, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_pxie_16 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4852, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_2 }, + { PCI_VENDOR_ID_NI, PCI_DEVICE_ID_NI_PXI8433_4854, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ni8431_4 }, + + /* + * MOXA + */ + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102E, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_2p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP102EL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_2p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP104EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_4p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP114EL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_4p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP116E_A_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP116E_A_B, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP118E_A_I, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP132EL, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_2p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP134EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_4p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP138E_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + { PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP168EL_A, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_moxa8250_8p }, + + /* + * ADDI-DATA GmbH communication cards <info@addi-data.com> + */ + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7500, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_4_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7420, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_2_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7300, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_AMCC, + PCI_DEVICE_ID_AMCC_ADDIDATA_APCI7800, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b1_8_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7500_2, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_4_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7420_2, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_2_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7300_2, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7500_3, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_4_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7420_3, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_2_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7300_3, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCI7800_3, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_b0_8_115200 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7500, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_4_3906250 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7420, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_2_3906250 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7300, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_1_3906250 }, + + { PCI_VENDOR_ID_ADDIDATA, + PCI_DEVICE_ID_ADDIDATA_APCIe7800, + PCI_ANY_ID, + PCI_ANY_ID, + 0, + 0, + pbn_ADDIDATA_PCIe_8_3906250 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, + PCI_VENDOR_ID_IBM, 0x0299, + 0, 0, pbn_b0_bt_2_115200 }, + + /* + * other NetMos 9835 devices are most likely handled by the + * parport_serial driver, check drivers/parport/parport_serial.c + * before adding them here. + */ + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + + /* the 9901 is a rebranded 9912 */ + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9912, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9904, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900, + 0xA000, 0x3002, + 0, 0, pbn_NETMOS9900_2s_115200 }, + + /* + * Best Connectivity and Rosewill PCI Multi I/O cards + */ + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, + 0xA000, 0x1000, + 0, 0, pbn_b0_1_115200 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, + 0xA000, 0x3002, + 0, 0, pbn_b0_bt_2_115200 }, + + { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9865, + 0xA000, 0x3004, + 0, 0, pbn_b0_bt_4_115200 }, + /* Intel CE4100 */ + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CE4100_UART, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_ce4100_1_115200 }, + + /* + * Cronyx Omega PCI + */ + { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_CRONYX_OMEGA, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_omegapci }, + + /* + * Broadcom TruManage + */ + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, + pbn_brcm_trumanage }, + + /* + * AgeStar as-prs2-009 + */ + { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_b0_bt_2_115200 }, + + /* + * WCH CH353 series devices: The 2S1P is handled by parport_serial + * so not listed here. + */ + { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_4S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_b0_bt_4_115200 }, + + { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH353_2S1PF, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_b0_bt_2_115200 }, + + { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH355_4S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_b0_bt_4_115200 }, + + { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH382_2S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_wch382_2 }, + + { PCIE_VENDOR_ID_WCH, PCIE_DEVICE_ID_WCH_CH384_4S, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, pbn_wch384_4 }, + + /* Fintek PCI serial cards */ + { PCI_DEVICE(0x1c29, 0x1104), .driver_data = pbn_fintek_4 }, + { PCI_DEVICE(0x1c29, 0x1108), .driver_data = pbn_fintek_8 }, + { PCI_DEVICE(0x1c29, 0x1112), .driver_data = pbn_fintek_12 }, + { PCI_DEVICE(0x1c29, 0x1204), .driver_data = pbn_fintek_F81504A }, + { PCI_DEVICE(0x1c29, 0x1208), .driver_data = pbn_fintek_F81508A }, + { PCI_DEVICE(0x1c29, 0x1212), .driver_data = pbn_fintek_F81512A }, + + /* MKS Tenta SCOM-080x serial cards */ + { PCI_DEVICE(0x1601, 0x0800), .driver_data = pbn_b0_4_1250000 }, + { PCI_DEVICE(0x1601, 0xa801), .driver_data = pbn_b0_4_1250000 }, + + /* Amazon PCI serial device */ + { PCI_DEVICE(0x1d0f, 0x8250), .driver_data = pbn_b0_1_115200 }, + + /* + * These entries match devices with class COMMUNICATION_SERIAL, + * COMMUNICATION_MODEM or COMMUNICATION_MULTISERIAL + */ + { PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_SERIAL << 8, + 0xffff00, pbn_default }, + { PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_MODEM << 8, + 0xffff00, pbn_default }, + { PCI_ANY_ID, PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, + PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, + 0xffff00, pbn_default }, + { 0, } +}; + +static struct pci_driver serial_pci_driver = { + .name = "ns16550_serial_pci", + .probe = pciserial_init_one, + .id_table = serial_pci_tbl, +}; + +static int __init serial_pci_register(void) +{ + return pci_driver_register(&serial_pci_driver); +} +console_initcall(serial_pci_register); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index d9311d4af5..bd615b4e99 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -283,7 +283,7 @@ int spi_register_controller(struct spi_controller *ctrl) return status; } -EXPORT_SYMBOL(spi_register_ctrl); +EXPORT_SYMBOL(spi_register_controller); struct spi_controller *spi_get_controller(int bus) { diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index 09da121374..aa04897d79 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -1,7 +1,9 @@ config USB_DWC3 tristate "DesignWare USB3 DRD Core Support" depends on USB && HAS_DMA + depends on OFDEVICE select USB_XHCI + select USB_OTGDEV help Say Y or M here if your system has a Dual Role SuperSpeed USB controller based on the DesignWare USB3 IP Core. @@ -29,6 +31,7 @@ config USB_DWC3_GADGET config USB_DWC3_DUAL_ROLE bool "Dual Role mode" + depends on USB_GADGET help This is the default mode of working of DWC3 controller where both host and gadget features are enabled. diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index d3f9d9ef27..04b700d12d 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -348,12 +348,9 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); dft = reg & DWC3_GFLADJ_30MHZ_MASK; - if (!WARN(dft == dwc->fladj, - "request value same as default, ignoring\n")) { - reg &= ~DWC3_GFLADJ_30MHZ_MASK; - reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; - dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); - } + reg &= ~DWC3_GFLADJ_30MHZ_MASK; + reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; + dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); } static void dwc3_core_num_eps(struct dwc3 *dwc) @@ -914,7 +911,6 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (IS_ERR(dwc->usb2_generic_phy)) { ret = PTR_ERR(dwc->usb2_generic_phy); if (ret == -ENOSYS || ret == -ENODEV) { - dev_err(dev, "no usb2 phy configured\n"); dwc->usb2_generic_phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; @@ -928,7 +924,6 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) if (IS_ERR(dwc->usb3_generic_phy)) { ret = PTR_ERR(dwc->usb3_generic_phy); if (ret == -ENOSYS || ret == -ENODEV) { - dev_err(dev, "no usb2 phy configured\n"); dwc->usb3_generic_phy = NULL; } else if (ret == -EPROBE_DEFER) { return ret; @@ -941,12 +936,13 @@ static int dwc3_core_get_phy(struct dwc3 *dwc) return 0; } -static int dwc3_core_init_mode(struct dwc3 *dwc) +static int dwc3_set_mode(void *ctx, enum usb_dr_mode mode) { + struct dwc3 *dwc = ctx; struct device_d *dev = dwc->dev; int ret; - switch (dwc->dr_mode) { + switch (mode) { case USB_DR_MODE_PERIPHERAL: dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE); @@ -968,13 +964,20 @@ static int dwc3_core_init_mode(struct dwc3 *dwc) } break; default: - dev_err(dev, "Unsupported mode of operation %d\n", dwc->dr_mode); return -EINVAL; } return 0; } +static int dwc3_core_init_mode(struct dwc3 *dwc) +{ + if (dwc->dr_mode == USB_DR_MODE_OTG) + return usb_register_otg_device(dwc->dev, dwc3_set_mode, dwc); + else + return dwc3_set_mode(dwc, dwc->dr_mode); +} + static void dwc3_get_properties(struct dwc3 *dwc) { struct device_d *dev = dwc->dev; diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index df0a188a63..f2f7a311d1 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -1336,7 +1336,6 @@ struct dwc3_gadget_ep_cmd_params { /* prototypes */ int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc); void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode); -void dwc3_set_mode(struct dwc3 *dwc, u32 mode); /* check whether we are on the DWC_usb3 core */ static inline bool dwc3_is_usb3(struct dwc3 *dwc) diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 82a202cc21..35c4b8cf4c 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -861,7 +861,7 @@ static int check_ubi(struct f_fastboot *f_fb, struct file_list_entry *fentry, if (filetype == filetype_ubi) { fastboot_tx_print(f_fb, FASTBOOT_MSG_INFO, - "This is an UBI image..."); + "This is a UBI image..."); return 1; } else { fastboot_tx_print(f_fb, FASTBOOT_MSG_FAIL, diff --git a/drivers/usb/imx/Kconfig b/drivers/usb/imx/Kconfig index 05f17fbd2f..34f35e0ff6 100644 --- a/drivers/usb/imx/Kconfig +++ b/drivers/usb/imx/Kconfig @@ -2,6 +2,7 @@ config USB_IMX_CHIPIDEA bool "i.MX USB support (read help)" depends on ARCH_IMX + select USB_OTGDEV help The Freescale i.MX SoCs have a variant of the chipidea ci13xxx for USB support. Traditionally in barebox this is supported through the diff --git a/drivers/usb/imx/chipidea-imx.c b/drivers/usb/imx/chipidea-imx.c index 6c60c383f0..3cf5d26dcd 100644 --- a/drivers/usb/imx/chipidea-imx.c +++ b/drivers/usb/imx/chipidea-imx.c @@ -36,12 +36,11 @@ struct imx_chipidea { void __iomem *base; struct ehci_data data; unsigned long flags; - uint32_t mode; + enum usb_dr_mode mode; int portno; struct device_d *usbmisc; enum usb_phy_interface phymode; struct param_d *param_mode; - int role_registered; struct regulator *vbus; struct phy *phy; struct usb_phy *usbphy; @@ -103,7 +102,6 @@ static int imx_chipidea_port_post_init(void *drvdata) static int imx_chipidea_probe_dt(struct imx_chipidea *ci) { struct of_phandle_args out_args; - enum usb_dr_mode mode; if (of_parse_phandle_with_args(ci->dev->device_node, "fsl,usbmisc", "#index-cells", 0, &out_args)) @@ -116,29 +114,17 @@ static int imx_chipidea_probe_dt(struct imx_chipidea *ci) ci->portno = out_args.args[0]; ci->flags = MXC_EHCI_MODE_UTMI_8BIT; - mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); + ci->mode = of_usb_get_dr_mode(ci->dev->device_node, NULL); - switch (mode) { - case USB_DR_MODE_HOST: - default: - ci->mode = IMX_USB_MODE_HOST; - break; - case USB_DR_MODE_PERIPHERAL: - ci->mode = IMX_USB_MODE_DEVICE; - break; - case USB_DR_MODE_OTG: - ci->mode = IMX_USB_MODE_OTG; - break; - case USB_DR_MODE_UNKNOWN: + if (ci->mode == USB_DR_MODE_UNKNOWN) { /* * No dr_mode specified. This means it can either be OTG * for port 0 or host mode for the other host-only ports. */ if (ci->portno == 0) - ci->mode = IMX_USB_MODE_OTG; + ci->mode = USB_DR_MODE_OTG; else - ci->mode = IMX_USB_MODE_HOST; - break; + ci->mode = USB_DR_MODE_HOST; } ci->phymode = of_usb_get_phy_mode(ci->dev->device_node, NULL); @@ -184,18 +170,15 @@ static int ci_ehci_detect(struct device_d *dev) return ehci_detect(ci->ehci); } -static int ci_register_role(struct imx_chipidea *ci) +static int ci_set_mode(void *ctx, enum usb_dr_mode mode) { + struct imx_chipidea *ci = ctx; int ret; - if (ci->role_registered != IMX_USB_MODE_OTG) - return -EBUSY; - - if (ci->mode == IMX_USB_MODE_HOST) { + if (mode == USB_DR_MODE_HOST) { if (IS_ENABLED(CONFIG_USB_EHCI)) { struct ehci_host *ehci; - ci->role_registered = IMX_USB_MODE_HOST; ret = regulator_enable(ci->vbus); if (ret) return ret; @@ -215,10 +198,9 @@ static int ci_register_role(struct imx_chipidea *ci) } } - if (ci->mode == IMX_USB_MODE_DEVICE) { + if (mode == USB_DR_MODE_PERIPHERAL) { if (IS_ENABLED(CONFIG_USB_GADGET_DRIVER_ARC)) { struct fsl_udc *udc; - ci->role_registered = IMX_USB_MODE_DEVICE; udc = ci_udc_register(ci->dev, ci->base); if (IS_ERR(udc)) @@ -234,48 +216,6 @@ static int ci_register_role(struct imx_chipidea *ci) return 0; } -static int ci_set_mode(struct param_d *param, void *priv) -{ - struct imx_chipidea *ci = priv; - - if (ci->role_registered != IMX_USB_MODE_OTG) { - if (ci->role_registered == ci->mode) - return 0; - else - return -EBUSY; - } - - return ci_register_role(ci); -} - -static const char *ci_mode_names[] = { - "host", "peripheral", "otg" -}; - -static struct device_d imx_otg_device = { - .name = "otg", - .id = DEVICE_ID_SINGLE, -}; - -static int ci_register_otg_device(struct imx_chipidea *ci) -{ - int ret; - - if (imx_otg_device.parent) - return -EBUSY; - - imx_otg_device.parent = ci->dev; - - ret = register_device(&imx_otg_device); - if (ret) - return ret; - - ci->param_mode = dev_add_param_enum(&imx_otg_device, "mode", - ci_set_mode, NULL, &ci->mode, - ci_mode_names, ARRAY_SIZE(ci_mode_names), ci); - return 0; -} - static int imx_chipidea_probe(struct device_d *dev) { struct resource *iores; @@ -288,7 +228,6 @@ static int imx_chipidea_probe(struct device_d *dev) ci = xzalloc(sizeof(*ci)); ci->dev = dev; dev->priv = ci; - ci->role_registered = IMX_USB_MODE_OTG; if (IS_ENABLED(CONFIG_OFDEVICE) && dev->device_node) { ret = imx_chipidea_probe_dt(ci); @@ -361,10 +300,10 @@ static int imx_chipidea_probe(struct device_d *dev) ci->data.hcor = base + 0x140; ci->data.flags = EHCI_HAS_TT; - if (ci->mode == IMX_USB_MODE_OTG) - ret = ci_register_otg_device(ci); + if (ci->mode == USB_DR_MODE_OTG) + ret = usb_register_otg_device(ci->dev, ci_set_mode, ci); else - ret = ci_register_role(ci); + ret = ci_set_mode(ci, ci->mode); return ret; }; diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 7d6c9da594..270606f50b 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -6,6 +6,7 @@ comment "USB Miscellaneous drivers" config USB_HUB_USB251XB bool "USB251XB Hub Controller Configuration Driver" depends on I2C + depends on OFDEVICE select NLS help This option enables support for configuration via SMBus of the diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index b795f30275..127d6d1955 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -6,6 +6,7 @@ if USB_MUSB config USB_MUSB_DSPS tristate select OFDEVICE + select USB_OTGDEV config USB_MUSB_AM335X tristate "AM335x USB support" diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 5fe3bcb7cd..3b76b6cc61 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -303,50 +303,20 @@ static int get_musb_port_mode(struct device_d *dev) } } -static int dsps_set_mode(struct param_d *param, void *priv) +static int dsps_set_mode(void *ctx, enum usb_dr_mode mode) { - struct dsps_glue *glue = priv; + struct dsps_glue *glue = ctx; - if (glue->pdata.mode != MUSB_PORT_MODE_DUAL_ROLE) - return -EBUSY; - - switch (glue->otgmode) { - case 0: - default: - return -EINVAL; - case 1: + if (mode == USB_DR_MODE_HOST) glue->pdata.mode = MUSB_PORT_MODE_HOST; - break; - case 2: + else if (mode == USB_DR_MODE_PERIPHERAL) glue->pdata.mode = MUSB_PORT_MODE_GADGET; - break; - } + else + return -EINVAL; return musb_init_controller(&glue->musb, &glue->pdata); } -static const char *dsps_mode_names[] = { - "otg", "host", "peripheral" -}; - -static int dsps_register_otg_device(struct dsps_glue *glue) -{ - int ret; - - dev_set_name(&glue->otg_dev, "otg"); - glue->otg_dev.id = DEVICE_ID_DYNAMIC, - glue->otg_dev.parent = glue->dev; - - ret = register_device(&glue->otg_dev); - if (ret) - return ret; - - dev_add_param_enum(&glue->otg_dev, "mode", - dsps_set_mode, NULL, &glue->otgmode, - dsps_mode_names, ARRAY_SIZE(dsps_mode_names), glue); - return 0; -} - static int dsps_probe(struct device_d *dev) { struct resource *iores; @@ -405,7 +375,7 @@ static int dsps_probe(struct device_d *dev) config->multipoint = of_property_read_bool(dn, "mentor,multipoint"); if (pdata->mode == MUSB_PORT_MODE_DUAL_ROLE) { - ret = dsps_register_otg_device(glue); + ret = usb_register_otg_device(dev, dsps_set_mode, glue); if (ret) return ret; return 0; diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 2c9fb46e4d..2c094452b6 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -6,3 +6,7 @@ config USB_ULPI config USB_TWL4030 depends on MFD_TWL4030 bool "TWL4030 Transceiver support" + +config USB_OTGDEV + bool + diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index 465a7f098c..49c2491e58 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_USB_ULPI) += ulpi.o obj-$(CONFIG_USB_TWL4030) += twl4030.o - +obj-$(CONFIG_USB_OTGDEV) += otgdev.o diff --git a/drivers/usb/otg/otgdev.c b/drivers/usb/otg/otgdev.c new file mode 100644 index 0000000000..7017796e8c --- /dev/null +++ b/drivers/usb/otg/otgdev.c @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <common.h> +#include <driver.h> +#include <usb/usb.h> + +static int (*set_mode_callback)(void *ctx, enum usb_dr_mode mode); +static unsigned int otg_mode; + +static int otg_set_mode(struct param_d *param, void *ctx) +{ + static int cur_mode = USB_DR_MODE_OTG; + int ret; + + if (otg_mode == USB_DR_MODE_UNKNOWN) + return -EINVAL; + + if (otg_mode == cur_mode) + return 0; + + if (cur_mode != USB_DR_MODE_OTG) + return -EBUSY; + + ret = set_mode_callback(ctx, otg_mode); + if (ret) + return ret; + + cur_mode = otg_mode; + + return 0; +} + +static const char *otg_mode_names[] = { + [USB_DR_MODE_UNKNOWN] = "unknown", + [USB_DR_MODE_HOST] = "host", + [USB_DR_MODE_PERIPHERAL] = "peripheral", + [USB_DR_MODE_OTG] = "otg", +}; + +static struct device_d otg_device = { + .name = "otg", + .id = DEVICE_ID_SINGLE, +}; + +int usb_register_otg_device(struct device_d *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx) +{ + int ret; + struct param_d *param_mode; + + if (otg_device.parent) + return -EBUSY; + + otg_device.parent = parent; + set_mode_callback = set_mode; + otg_mode = USB_DR_MODE_OTG; + + ret = register_device(&otg_device); + if (ret) + return ret; + + param_mode = dev_add_param_enum(&otg_device, "mode", + otg_set_mode, NULL, &otg_mode, + otg_mode_names, ARRAY_SIZE(otg_mode_names), ctx); + if (IS_ERR(param_mode)) + return PTR_ERR(param_mode); + + return 0; +} diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 4f881a1d02..5307ab0b3e 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -222,7 +222,7 @@ static int f71808e_wdt_init(struct f71808e_wdt *wd, struct device_d *dev) { struct watchdog *wdd = &wd->wdd; const char * const *names = pulse_width_names; - int wdt_conf; + unsigned long wdt_conf; int ret; superio_enter(wd->sioaddr); @@ -262,6 +262,11 @@ static int f71808e_wdt_init(struct f71808e_wdt *wd, struct device_d *dev) dev_info(dev, "reset reason: %s\n", reset_source_name()); + if (test_bit(F71808FG_FLAG_WD_EN, &wdt_conf)) + wdd->running = WDOG_HW_RUNNING; + else + wdd->running = WDOG_HW_NOT_RUNNING; + ret = watchdog_register(wdd); if (ret) return ret; diff --git a/drivers/watchdog/imxwd.c b/drivers/watchdog/imxwd.c index 77a3bd76ce..b2cfd1cd3a 100644 --- a/drivers/watchdog/imxwd.c +++ b/drivers/watchdog/imxwd.c @@ -28,6 +28,7 @@ struct imx_wd_ops { int (*set_timeout)(struct imx_wd *, unsigned); void (*soc_reset)(struct imx_wd *); int (*init)(struct imx_wd *); + bool (*is_running)(struct imx_wd *); unsigned int timeout_max; }; @@ -111,6 +112,11 @@ static void imx1_soc_reset(struct imx_wd *priv) writew(IMX1_WDOG_WCR_WDE, priv->base + IMX1_WDOG_WCR); } +static inline bool imx21_watchdog_is_running(struct imx_wd *priv) +{ + return imxwd_read(priv, IMX21_WDOG_WCR) & IMX21_WDOG_WCR_WDE; +} + static int imx21_watchdog_set_timeout(struct imx_wd *priv, unsigned timeout) { u16 val; @@ -243,6 +249,13 @@ static int imx_wd_probe(struct device_d *dev) "fsl,ext-reset-output"); if (IS_ENABLED(CONFIG_WATCHDOG_IMX)) { + if (priv->ops->is_running) { + if (priv->ops->is_running(priv)) + priv->wd.running = WDOG_HW_RUNNING; + else + priv->wd.running = WDOG_HW_NOT_RUNNING; + } + ret = watchdog_register(&priv->wd); if (ret) goto on_error; @@ -277,6 +290,7 @@ static const struct imx_wd_ops imx21_wd_ops = { .set_timeout = imx21_watchdog_set_timeout, .soc_reset = imx21_soc_reset, .init = imx21_wd_init, + .is_running = imx21_watchdog_is_running, .timeout_max = 128, }; diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c index 4d252e558c..c7a5cb9caa 100644 --- a/drivers/watchdog/stm32_iwdg.c +++ b/drivers/watchdog/stm32_iwdg.c @@ -132,7 +132,7 @@ static int stm32_iwdg_set_timeout(struct watchdog *wdd, unsigned int timeout) int ret; if (!timeout) - return -EINVAL; /* can't disable */ + return -ENOSYS; /* can't disable */ if (timeout > wdd->timeout_max) return -EINVAL; @@ -256,6 +256,7 @@ static int stm32_iwdg_probe(struct device_d *dev) wdd->set_timeout = stm32_iwdg_set_timeout; wdd->timeout_max = (RLR_MAX + 1) * data->max_prescaler * 1000; wdd->timeout_max /= wd->rate * 1000; + wdd->running = WDOG_HW_RUNNING_UNSUPPORTED; /* ONF bit not present in IP */ ret = watchdog_register(wdd); if (ret) { diff --git a/drivers/watchdog/stpmic1_wdt.c b/drivers/watchdog/stpmic1_wdt.c index 9b7a586387..40273ffc4c 100644 --- a/drivers/watchdog/stpmic1_wdt.c +++ b/drivers/watchdog/stpmic1_wdt.c @@ -14,22 +14,15 @@ #include <restart.h> #include <reset_source.h> -#define RESTART_SR 0x05 -#define MAIN_CR 0x10 -#define WCHDG_CR 0x1B -#define WCHDG_TIMER_CR 0x1C +#include <linux/mfd/stpmic1.h> -/* Restart Status Register (RESTART_SR) */ +/* Restart Status Register (RREQ_STATE_SR) */ #define R_RST BIT(0) #define R_SWOFF BIT(1) #define R_WDG BIT(2) #define R_PKEYLKP BIT(3) #define R_VINOK_FA BIT(4) -/* Main PMIC Control Register (MAIN_CR) */ -#define SWOFF BIT(0) -#define RREQ_EN BIT(1) - /* Watchdog Control Register (WCHDG_CR) */ #define WDT_START BIT(0) #define WDT_PING BIT(1) @@ -106,8 +99,9 @@ static void __noreturn stpmic1_restart_handler(struct restart_handler *rst) { struct stpmic1_wdt *wdt = container_of(rst, struct stpmic1_wdt, restart); - regmap_write_bits(wdt->regmap, MAIN_CR, - SWOFF | RREQ_EN, SWOFF | RREQ_EN); + regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR, + SOFTWARE_SWITCH_OFF_ENABLED | RESTART_REQUEST_ENABLED, + SOFTWARE_SWITCH_OFF_ENABLED | RESTART_REQUEST_ENABLED); mdelay(1000); hang(); @@ -119,8 +113,9 @@ static void __noreturn stpmic1_poweroff(struct poweroff_handler *handler) shutdown_barebox(); - regmap_write_bits(wdt->regmap, MAIN_CR, - SWOFF | RREQ_EN, SWOFF); + regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR, + SOFTWARE_SWITCH_OFF_ENABLED | RESTART_REQUEST_ENABLED, + SOFTWARE_SWITCH_OFF_ENABLED); mdelay(1000); hang(); @@ -142,7 +137,7 @@ static int stpmic1_set_reset_reason(struct regmap *map) int ret; int i, instance = 0; - ret = regmap_read(map, RESTART_SR, ®); + ret = regmap_read(map, RREQ_STATE_SR, ®); if (ret) return ret; @@ -156,7 +151,7 @@ static int stpmic1_set_reset_reason(struct regmap *map) reset_source_set_prinst(type, 400, instance); - pr_info("STPMIC1 reset reason %s (RESTART_SR: 0x%08x)\n", + pr_info("STPMIC1 reset reason %s (RREQ_STATE_SR: 0x%08x)\n", reset_source_name(), reg); return 0; @@ -180,7 +175,8 @@ static int stpmic1_wdt_probe(struct device_d *dev) wdd->timeout_max = PMIC_WDT_MAX_TIMEOUT; /* have the watchdog reset, not power-off the system */ - regmap_write_bits(wdt->regmap, MAIN_CR, RREQ_EN, RREQ_EN); + regmap_write_bits(wdt->regmap, SWOFF_PWRCTRL_CR, + RESTART_REQUEST_ENABLED, RESTART_REQUEST_ENABLED); ret = watchdog_register(wdd); if (ret) { diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c index 8b13950238..b6e2a37b1f 100644 --- a/drivers/watchdog/wd_core.c +++ b/drivers/watchdog/wd_core.c @@ -37,6 +37,8 @@ static const char *watchdog_name(struct watchdog *wd) */ int watchdog_set_timeout(struct watchdog *wd, unsigned timeout) { + int ret; + if (!wd) return -ENODEV; @@ -45,7 +47,13 @@ int watchdog_set_timeout(struct watchdog *wd, unsigned timeout) pr_debug("setting timeout on %s to %ds\n", watchdog_name(wd), timeout); - return wd->set_timeout(wd, timeout); + ret = wd->set_timeout(wd, timeout); + if (ret) + return ret; + + wd->running = timeout ? WDOG_HW_RUNNING : WDOG_HW_NOT_RUNNING; + + return 0; } EXPORT_SYMBOL(watchdog_set_timeout); @@ -127,6 +135,23 @@ static int watchdog_register_dev(struct watchdog *wd, const char *name, int id) return register_device(&wd->dev); } +/** + * dev_get_watchdog_priority() - get a device's desired watchdog priority + * @dev: The device, which device_node to read the property from + * + * return: The priority + */ +static unsigned int dev_get_watchdog_priority(struct device_d *dev) +{ + unsigned int priority = WATCHDOG_DEFAULT_PRIORITY; + + if (dev) + of_property_read_u32(dev->device_node, "watchdog-priority", + &priority); + + return priority; +} + int watchdog_register(struct watchdog *wd) { struct param_d *p; @@ -145,8 +170,12 @@ int watchdog_register(struct watchdog *wd) if (ret) return ret; + p = dev_add_param_tristate_ro(&wd->dev, "running", &wd->running); + if (IS_ERR(p)) + return PTR_ERR(p); + if (!wd->priority) - wd->priority = WATCHDOG_DEFAULT_PRIORITY; + wd->priority = dev_get_watchdog_priority(wd->hwdev); p = dev_add_param_uint32(&wd->dev, "priority", watchdog_set_priority, NULL, @@ -232,18 +261,3 @@ struct watchdog *watchdog_get_by_name(const char *name) return NULL; } EXPORT_SYMBOL(watchdog_get_by_name); - -/** - * of_get_watchdog_priority() - get the desired watchdog priority from device tree - * @node: The device_node to read the property from - * - * return: The priority - */ -unsigned int of_get_watchdog_priority(struct device_node *node) -{ - unsigned int priority = WATCHDOG_DEFAULT_PRIORITY; - - of_property_read_u32(node, "watchdog-priority", &priority); - - return priority; -} diff --git a/dts/scripts/cronjob b/dts/scripts/cronjob index ccdbc0607e..b7511e4253 100755 --- a/dts/scripts/cronjob +++ b/dts/scripts/cronjob @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e diff --git a/dts/scripts/index-filter.sh b/dts/scripts/index-filter.sh index 9610855020..c301fcea1c 100755 --- a/dts/scripts/index-filter.sh +++ b/dts/scripts/index-filter.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash set -e set -o pipefail diff --git a/dts/scripts/merge-new-release.sh b/dts/scripts/merge-new-release.sh index a2763c69bb..554b97b8eb 100755 --- a/dts/scripts/merge-new-release.sh +++ b/dts/scripts/merge-new-release.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash case $1 in v*-dts) ;; diff --git a/dts/src/arm/imx6-logicpd-baseboard.dtsi b/dts/src/arm/imx6-logicpd-baseboard.dtsi index 2a6ce87071..9e027b9a5f 100644 --- a/dts/src/arm/imx6-logicpd-baseboard.dtsi +++ b/dts/src/arm/imx6-logicpd-baseboard.dtsi @@ -328,6 +328,10 @@ pinctrl-0 = <&pinctrl_pwm3>; }; +&snvs_pwrkey { + status = "okay"; +}; + &ssi2 { status = "okay"; }; diff --git a/dts/src/arm/imx6qdl-sabreauto.dtsi b/dts/src/arm/imx6qdl-sabreauto.dtsi index f3404dd105..cf628465cd 100644 --- a/dts/src/arm/imx6qdl-sabreauto.dtsi +++ b/dts/src/arm/imx6qdl-sabreauto.dtsi @@ -230,6 +230,8 @@ accelerometer@1c { compatible = "fsl,mma8451"; reg = <0x1c>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_mma8451_int>; interrupt-parent = <&gpio6>; interrupts = <31 IRQ_TYPE_LEVEL_LOW>; }; @@ -628,6 +630,12 @@ >; }; + pinctrl_mma8451_int: mma8451intgrp { + fsl,pins = < + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0xb0b1 + >; + }; + pinctrl_pwm3: pwm1grp { fsl,pins = < MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1 diff --git a/dts/src/arm/stm32mp157c-ev1.dts b/dts/src/arm/stm32mp157c-ev1.dts index 89d29b50c3..91fc0a315c 100644 --- a/dts/src/arm/stm32mp157c-ev1.dts +++ b/dts/src/arm/stm32mp157c-ev1.dts @@ -183,14 +183,12 @@ ov5640: camera@3c { compatible = "ovti,ov5640"; - pinctrl-names = "default"; - pinctrl-0 = <&ov5640_pins>; reg = <0x3c>; clocks = <&clk_ext_camera>; clock-names = "xclk"; DOVDD-supply = <&v2v8>; - powerdown-gpios = <&stmfx_pinctrl 18 GPIO_ACTIVE_HIGH>; - reset-gpios = <&stmfx_pinctrl 19 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&stmfx_pinctrl 18 (GPIO_ACTIVE_HIGH | GPIO_PUSH_PULL)>; + reset-gpios = <&stmfx_pinctrl 19 (GPIO_ACTIVE_LOW | GPIO_PUSH_PULL)>; rotation = <180>; status = "okay"; @@ -223,15 +221,8 @@ joystick_pins: joystick { pins = "gpio0", "gpio1", "gpio2", "gpio3", "gpio4"; - drive-push-pull; bias-pull-down; }; - - ov5640_pins: camera { - pins = "agpio2", "agpio3"; /* stmfx pins 18 & 19 */ - drive-push-pull; - output-low; - }; }; }; }; diff --git a/dts/src/arm/stm32mp157c.dtsi b/dts/src/arm/stm32mp157c.dtsi index 9b11654a0a..f98e0370c0 100644 --- a/dts/src/arm/stm32mp157c.dtsi +++ b/dts/src/arm/stm32mp157c.dtsi @@ -932,7 +932,7 @@ interrupt-names = "int0", "int1"; clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; clock-names = "hclk", "cclk"; - bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; + bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; status = "disabled"; }; @@ -945,7 +945,7 @@ interrupt-names = "int0", "int1"; clocks = <&rcc CK_HSE>, <&rcc FDCAN_K>; clock-names = "hclk", "cclk"; - bosch,mram-cfg = <0x0 0 0 32 0 0 2 2>; + bosch,mram-cfg = <0x1400 0 0 32 0 0 2 2>; status = "disabled"; }; diff --git a/dts/src/arm/sun8i-a83t-tbs-a711.dts b/dts/src/arm/sun8i-a83t-tbs-a711.dts index 568b90ece3..3bec3e0a81 100644 --- a/dts/src/arm/sun8i-a83t-tbs-a711.dts +++ b/dts/src/arm/sun8i-a83t-tbs-a711.dts @@ -192,6 +192,7 @@ vqmmc-supply = <®_dldo1>; non-removable; wakeup-source; + keep-power-in-suspend; status = "okay"; brcmf: wifi@1 { diff --git a/dts/src/arm64/freescale/fsl-ls1028a-qds.dts b/dts/src/arm64/freescale/fsl-ls1028a-qds.dts index d98346da01..078a501022 100644 --- a/dts/src/arm64/freescale/fsl-ls1028a-qds.dts +++ b/dts/src/arm64/freescale/fsl-ls1028a-qds.dts @@ -127,7 +127,7 @@ status = "okay"; i2c-mux@77 { - compatible = "nxp,pca9847"; + compatible = "nxp,pca9547"; reg = <0x77>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/src/arm64/freescale/imx8mm.dtsi b/dts/src/arm64/freescale/imx8mm.dtsi index 58b8cd06ca..23c8fad793 100644 --- a/dts/src/arm64/freescale/imx8mm.dtsi +++ b/dts/src/arm64/freescale/imx8mm.dtsi @@ -394,7 +394,7 @@ }; sdma2: dma-controller@302c0000 { - compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma"; + compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma"; reg = <0x302c0000 0x10000>; interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SDMA2_ROOT>, @@ -405,7 +405,7 @@ }; sdma3: dma-controller@302b0000 { - compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma"; + compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma"; reg = <0x302b0000 0x10000>; interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SDMA3_ROOT>, @@ -737,7 +737,7 @@ }; sdma1: dma-controller@30bd0000 { - compatible = "fsl,imx8mm-sdma", "fsl,imx7d-sdma"; + compatible = "fsl,imx8mm-sdma", "fsl,imx8mq-sdma"; reg = <0x30bd0000 0x10000>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MM_CLK_SDMA1_ROOT>, diff --git a/dts/src/arm64/freescale/imx8mn.dtsi b/dts/src/arm64/freescale/imx8mn.dtsi index 98496f5707..43c4db3121 100644 --- a/dts/src/arm64/freescale/imx8mn.dtsi +++ b/dts/src/arm64/freescale/imx8mn.dtsi @@ -288,7 +288,7 @@ }; sdma3: dma-controller@302b0000 { - compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma"; + compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma"; reg = <0x302b0000 0x10000>; interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MN_CLK_SDMA3_ROOT>, @@ -299,7 +299,7 @@ }; sdma2: dma-controller@302c0000 { - compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma"; + compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma"; reg = <0x302c0000 0x10000>; interrupts = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MN_CLK_SDMA2_ROOT>, @@ -612,7 +612,7 @@ }; sdma1: dma-controller@30bd0000 { - compatible = "fsl,imx8mn-sdma", "fsl,imx7d-sdma"; + compatible = "fsl,imx8mn-sdma", "fsl,imx8mq-sdma"; reg = <0x30bd0000 0x10000>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk IMX8MN_CLK_SDMA1_ROOT>, diff --git a/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi b/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi index 087b5b6ebe..32ce14936b 100644 --- a/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi +++ b/dts/src/arm64/freescale/imx8mq-zii-ultra.dtsi @@ -88,7 +88,7 @@ regulator-name = "0V9_ARM"; regulator-min-microvolt = <900000>; regulator-max-microvolt = <1000000>; - gpios = <&gpio3 19 GPIO_ACTIVE_HIGH>; + gpios = <&gpio3 16 GPIO_ACTIVE_HIGH>; states = <1000000 0x1 900000 0x0>; regulator-always-on; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 15c0174b1f..f4b77226d9 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -46,35 +46,6 @@ void pstore_set_kmsg_bytes(int bytes) static int pstore_ready; -static void pstore_console_write(const char *s, unsigned c) -{ - const char *e = s + c; - - while (s < e) { - struct pstore_record record = { - .type = PSTORE_TYPE_CONSOLE, - .psi = psinfo, - }; - - if (c > psinfo->bufsize) - c = psinfo->bufsize; - - record.buf = (char *)s; - record.size = c; - psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &record.id, 0, - record.buf, 0, record.size, psinfo); - s += c; - c = e - s; - } -} - -static int pstore_console_puts(struct console_device *cdev, const char *s, - size_t nbytes) -{ - pstore_console_write(s, nbytes); - return nbytes; -} - void pstore_log(const char *str) { uint64_t id; @@ -102,6 +73,9 @@ static void pstore_console_capture_log(void) uint64_t id; struct log_entry *log, *tmp; + if (IS_ENABLED(CONFIG_CONSOLE_NONE)) + return; + list_for_each_entry_safe(log, tmp, &barebox_logbuf, list) { psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0, log->msg, 0, strlen(log->msg), psinfo); diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 86049f989e..958f46b0ea 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -623,10 +623,10 @@ static int ramoops_probe(struct device_d *dev) if (!IS_ENABLED(CONFIG_OFTREE)) { scnprintf(kernelargs, sizeof(kernelargs), - "ramoops.record_size=0x%x " - "ramoops.console_size=0x%x " - "ramoops.ftrace_size=0x%x " - "ramoops.pmsg_size=0x%x " + "ramoops.record_size=0x%zx " + "ramoops.console_size=0x%zx " + "ramoops.ftrace_size=0x%zx " + "ramoops.pmsg_size=0x%zx " "ramoops.mem_address=0x%llx " "ramoops.mem_size=0x%lx " "ramoops.ecc=%d", @@ -646,7 +646,6 @@ static int ramoops_probe(struct device_d *dev) return 0; fail_buf: -fail_clear: kfree(cxt->mprz); fail_init_mprz: kfree(cxt->fprz); diff --git a/images/.gitignore b/images/.gitignore index 949f534d9a..b673c98194 100644 --- a/images/.gitignore +++ b/images/.gitignore @@ -27,3 +27,4 @@ barebox.sha.bin barebox.sum *.pimximg *.psimximg +*.zynqimg diff --git a/images/Makefile.imx b/images/Makefile.imx index a8f8a9b7d6..53d4ac8202 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -2,6 +2,24 @@ # barebox image generation Makefile for i.MX images # +# params: CONFIG symbol, entry point, flash header path string, board identifier string +define build_imx_habv4img = +$(eval +ifeq ($($(strip $(1))), y) + pblb-y += $(strip $(2)) + CFG_$(strip $(2)).pblb.imximg = $(board)/$(strip $(3)).imxcfg + FILE_barebox-$(strip $(4)).img = $(strip $(2)).pblb.imximg + FILE_barebox-$(strip $(4))-s.img = $(strip $(2)).pblb.simximg + FILE_barebox-$(strip $(4))-us.img = $(strip $(2)).pblb.usimximg + FILE_barebox-$(strip $(4))-es.img = $(strip $(2)).pblb.esimximg + image-y += barebox-$(strip $(4)).img + image-$(CONFIG_HABV4_IMAGE_SIGNED) += barebox-$(strip $(4))-s.img + image-$(CONFIG_HABV4_IMAGE_SIGNED_USB) += barebox-$(strip $(4))-us.img + image-$(CONFIG_HABV4_IMAGE_SIGNED_ENCRYPTED) += barebox-$(strip $(4))-es.img +endif +) +endef + # %.imximg - convert into i.MX image # ---------------------------------------------------------------- @@ -13,17 +31,20 @@ $(obj)/%.pimximg: $(obj)/% FORCE -p $($(patsubst $(obj)/%.pblb,PBL_MEMORY_SIZE_%,$<))) $(obj)/%.psimximg: $(obj)/% FORCE - $(call if_changed,imx_image,$(CFG_$(patsubst %.psimximg,%.imximg,$(@F))),-s \ - -p $($(patsubst $(obj)/%.pblb,PBL_MEMORY_SIZE_%,$<))) + $(call if_changed,imx_image,$(CFG_$(patsubst %.psimximg,%.imximg,$(@F))),\ + -p $($(patsubst $(obj)/%.pblb,PBL_MEMORY_SIZE_%,$<)) -s) $(obj)/%.simximg: $(obj)/% FORCE $(call if_changed,imx_image,$(CFG_$(patsubst %.simximg,%.imximg,$(@F))),-s) $(obj)/%.usimximg: $(obj)/% FORCE - $(call if_changed,imx_image,$(CFG_$(patsubst %.usimximg,%.imximg,$(@F))),-s -u) + $(call if_changed,imx_image,$(CFG_$(patsubst %.usimximg,%.imximg,$(@F))),-u -s) + +$(obj)/%.esimximg: $(obj)/% FORCE + $(call if_changed,imx_image,$(CFG_$(patsubst %.esimximg,%.imximg,$(@F))),-e -s) -$(obj)/%.esimximg $(obj)/%.esimximg.dek: $(obj)/% FORCE - $(call if_changed,imx_image,$(CFG_$(patsubst %.esimximg,%.imximg,$(@F))),-s -e) +$(obj)/%.esimximg.dek: $(obj)/% FORCE + $(call if_changed,imx_image,$(CFG_$(patsubst %.esimximg,%.imximg,$(@F))),-e -s) .SECONDEXPANSION: $(obj)/%.img.dek: $(obj)/$$(FILE_$$(@F)) @@ -156,406 +177,166 @@ FILE_barebox-tx53-1011.img = start_imx53_tx53_1011.pblb.imximg image-$(CONFIG_MACH_TX53) += barebox-tx53-1011.img # ----------------------- i.MX6 based boards --------------------------- -pblb-$(CONFIG_MACH_REALQ7) += start_imx6_realq7 -CFG_start_imx6_realq7.pblb.imximg = $(board)/datamodul-edm-qmx6/flash-header.imxcfg -FILE_barebox-datamodul-edm-qmx6.img = start_imx6_realq7.pblb.imximg -image-$(CONFIG_MACH_REALQ7) += barebox-datamodul-edm-qmx6.img - -pblb-$(CONFIG_MACH_GUF_SANTARO) += start_imx6q_guf_santaro -CFG_start_imx6q_guf_santaro.pblb.imximg = $(board)/guf-santaro/flash-header.imxcfg -FILE_barebox-guf-santaro.img = start_imx6q_guf_santaro.pblb.imximg -image-$(CONFIG_MACH_GUF_SANTARO) += barebox-guf-santaro.img - -pblb-$(CONFIG_MACH_GK802) += start_imx6_gk802 -CFG_start_imx6_gk802.pblb.imximg = $(board)/gk802/flash-header.imxcfg -FILE_barebox-gk802.img = start_imx6_gk802.pblb.imximg -image-$(CONFIG_MACH_GK802) += barebox-gk802.img - -pblb-$(CONFIG_MACH_TQMA6X) += start_imx6dl_mba6x -CFG_start_imx6dl_mba6x.pblb.imximg = $(board)/tqma6x/flash-header-tqma6dl.imxcfg -FILE_barebox-tq-tqma6s-mba6x.img = start_imx6dl_mba6x.pblb.imximg -image-$(CONFIG_MACH_TQMA6X) += barebox-tq-tqma6s-mba6x.img - -pblb-$(CONFIG_MACH_TQMA6X) += start_imx6q_mba6x -CFG_start_imx6q_mba6x.pblb.imximg = $(board)/tqma6x/flash-header-tqma6q.imxcfg -FILE_barebox-tq-tqma6q-mba6x.img = start_imx6q_mba6x.pblb.imximg -image-$(CONFIG_MACH_TQMA6X) += barebox-tq-tqma6q-mba6x.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01_4gib -CFG_start_phytec_pbab01_4gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-4gib.imxcfg -FILE_barebox-phytec-pbab01-4gib.img = start_phytec_pbab01_4gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01-4gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01_2gib -CFG_start_phytec_pbab01_2gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-2gib.imxcfg -FILE_barebox-phytec-pbab01-2gib.img = start_phytec_pbab01_2gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01-2gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01_1gib -CFG_start_phytec_pbab01_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-1gib.imxcfg -FILE_barebox-phytec-pbab01-1gib.img = start_phytec_pbab01_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01_1gib_1bank -CFG_start_phytec_pbab01_1gib_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank.imxcfg -FILE_barebox-phytec-pbab01-1gib-1bank.img = start_phytec_pbab01_1gib_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01-1gib-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01_512mb_1bank -CFG_start_phytec_pbab01_512mb_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-512mb-1bank.imxcfg -FILE_barebox-phytec-pbab01-512mb-1bank.img = start_phytec_pbab01_512mb_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01-512mb-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01dl_1gib -CFG_start_phytec_pbab01dl_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg -FILE_barebox-phytec-pbab01dl-1gib.img = start_phytec_pbab01dl_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01dl-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01dl_1gib_1bank -CFG_start_phytec_pbab01dl_1gib_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank.imxcfg -FILE_barebox-phytec-pbab01dl-1gib-1bank.img = start_phytec_pbab01dl_1gib_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01dl-1gib-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01s_512mb_1bank -CFG_start_phytec_pbab01s_512mb_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg -FILE_barebox-phytec-pbab01s-512mb-1bank.img = start_phytec_pbab01s_512mb_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01s-512mb-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01s_256mb_1bank -CFG_start_phytec_pbab01s_256mb_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank.imxcfg -FILE_barebox-phytec-pbab01s-256mb-1bank.img = start_phytec_pbab01s_256mb_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01s-256mb-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbab01s_128mb_1bank -CFG_start_phytec_pbab01s_128mb_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank.imxcfg -FILE_barebox-phytec-pbab01s-128mb-1bank.img = start_phytec_pbab01s_128mb_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbab01s-128mb-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phyboard_alcor_1gib -CFG_start_phytec_phyboard_alcor_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-1gib.imxcfg -FILE_barebox-phytec-phyboard-alcor-1gib.img = start_phytec_phyboard_alcor_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phyboard-alcor-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phyboard_subra_512mb_1bank -CFG_start_phytec_phyboard_subra_512mb_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank.imxcfg -FILE_barebox-phytec-phyboard-subra-512mb-1bank.img = start_phytec_phyboard_subra_512mb_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phyboard-subra-512mb-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phyboard_subra_1gib_1bank -CFG_start_phytec_phyboard_subra_1gib_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank.imxcfg -FILE_barebox-phytec-phyboard-subra-1gib-1bank.img = start_phytec_phyboard_subra_1gib_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phyboard-subra-1gib-1bank.img - -pblb-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6dl_dfi_fs700_m60_6s -CFG_start_imx6dl_dfi_fs700_m60_6s.pblb.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6s.imxcfg -FILE_barebox-dfi-fs700-m60-6s.img = start_imx6dl_dfi_fs700_m60_6s.pblb.imximg -image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6s.img - -pblb-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_micron -CFG_start_imx6q_dfi_fs700_m60_6q_micron.pblb.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6q-micron.imxcfg -FILE_barebox-dfi-fs700-m60-6q-micron.img = start_imx6q_dfi_fs700_m60_6q_micron.pblb.imximg -image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6q-micron.img - -pblb-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_nanya -CFG_start_imx6q_dfi_fs700_m60_6q_nanya.pblb.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6q-nanya.imxcfg -FILE_barebox-dfi-fs700-m60-6q-nanya.img = start_imx6q_dfi_fs700_m60_6q_nanya.pblb.imximg -image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6q-nanya.img - -pblb-$(CONFIG_MACH_SABRELITE) += start_imx6q_sabrelite -CFG_start_imx6q_sabrelite.pblb.imximg = $(board)/freescale-mx6-sabrelite/flash-header-mx6-sabrelite.imxcfg -FILE_barebox-freescale-imx6q-sabrelite.img = start_imx6q_sabrelite.pblb.imximg -image-$(CONFIG_MACH_SABRELITE) += barebox-freescale-imx6q-sabrelite.img - -pblb-$(CONFIG_MACH_SABRELITE) += start_imx6dl_sabrelite -CFG_start_imx6dl_sabrelite.pblb.imximg = $(board)/freescale-mx6-sabrelite/flash-header-mx6-sabrelite.imxcfg -FILE_barebox-freescale-imx6dl-sabrelite.img = start_imx6dl_sabrelite.pblb.imximg -image-$(CONFIG_MACH_SABRELITE) += barebox-freescale-imx6dl-sabrelite.img - -pblb-$(CONFIG_MACH_SABRESD) += start_imx6q_sabresd -CFG_start_imx6q_sabresd.pblb.imximg = $(board)/freescale-mx6-sabresd/flash-header-mx6-sabresd.imxcfg -FILE_barebox-freescale-imx6q-sabresd.img = start_imx6q_sabresd.pblb.imximg -image-$(CONFIG_MACH_SABRESD) += barebox-freescale-imx6q-sabresd.img - -pblb-$(CONFIG_MACH_UDOO_NEO) += start_imx6sx_udoo_neo -CFG_start_imx6sx_udoo_neo.pblb.imximg = $(board)/udoo-neo/flash-header-mx6sx-udoo-neo_full.imxcfg -FILE_barebox-udoo-neo.img = start_imx6sx_udoo_neo.pblb.imximg -image-$(CONFIG_MACH_UDOO_NEO) += barebox-udoo-neo.img - -pblb-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += start_imx6sx_sabresdb -CFG_start_imx6sx_sabresdb.pblb.imximg = $(board)/freescale-mx6sx-sabresdb/flash-header-mx6sx-sabresdb.imxcfg -FILE_barebox-freescale-imx6sx-sabresdb.img = start_imx6sx_sabresdb.pblb.imximg -image-$(CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB) += barebox-freescale-imx6sx-sabresdb.img - -pblb-$(CONFIG_MACH_TECHNEXION_WANDBOARD) += start_imx6_wandboard -CFG_start_imx6_wandboard.pblb.imximg = $(board)/technexion-wandboard/flash-header-technexion-wandboard.imxcfg -FILE_barebox-imx6-wandboard.img = start_imx6_wandboard.pblb.imximg -image-$(CONFIG_MACH_TECHNEXION_WANDBOARD) += barebox-imx6-wandboard.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard_microsom_i1 -CFG_start_hummingboard_microsom_i1.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i1.imxcfg -FILE_barebox-solidrun-hummingboard-microsom-i1.img = start_hummingboard_microsom_i1.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard-microsom-i1.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard_microsom_i2 -CFG_start_hummingboard_microsom_i2.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i2.imxcfg -FILE_barebox-solidrun-hummingboard-microsom-i2.img = start_hummingboard_microsom_i2.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard-microsom-i2.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard_microsom_i2ex -CFG_start_hummingboard_microsom_i2ex.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i2eX.imxcfg -FILE_barebox-solidrun-hummingboard-microsom-i2eX.img = start_hummingboard_microsom_i2ex.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard-microsom-i2eX.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard_microsom_i4 -CFG_start_hummingboard_microsom_i4.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i4.imxcfg -FILE_barebox-solidrun-hummingboard-microsom-i4.img = start_hummingboard_microsom_i4.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard-microsom-i4.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard2_microsom_i1 -CFG_start_hummingboard2_microsom_i1.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i1.imxcfg -FILE_barebox-solidrun-hummingboard2-microsom-i1.img = start_hummingboard2_microsom_i1.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard2-microsom-i1.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard2_microsom_i2 -CFG_start_hummingboard2_microsom_i2.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i2.imxcfg -FILE_barebox-solidrun-hummingboard2-microsom-i2.img = start_hummingboard2_microsom_i2.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard2-microsom-i2.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard2_microsom_i2ex -CFG_start_hummingboard2_microsom_i2ex.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i2eX.imxcfg -FILE_barebox-solidrun-hummingboard2-microsom-i2eX.img = start_hummingboard2_microsom_i2ex.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard2-microsom-i2eX.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_hummingboard2_microsom_i4 -CFG_start_hummingboard2_microsom_i4.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i4.imxcfg -FILE_barebox-solidrun-hummingboard2-microsom-i4.img = start_hummingboard2_microsom_i4.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-solidrun-hummingboard2-microsom-i4.img - -pblb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += start_h100_microsom_i2ex -CFG_start_h100_microsom_i2ex.pblb.imximg = $(board)/solidrun-microsom/flash-header-microsom-i2eX.imxcfg -FILE_barebox-auvidea-h100-microsom-i2eX.img = start_h100_microsom_i2ex.pblb.imximg -image-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += barebox-auvidea-h100-microsom-i2eX.img - -pblb-$(CONFIG_MACH_NITROGEN6) += start_imx6q_nitrogen6x_1g -CFG_start_imx6q_nitrogen6x_1g.pblb.imximg = $(board)/boundarydevices-nitrogen6/flash-header-nitrogen6q-1g.imxcfg -FILE_barebox-boundarydevices-imx6q-nitrogen6x-1g.img = start_imx6q_nitrogen6x_1g.pblb.imximg -image-$(CONFIG_MACH_NITROGEN6) += barebox-boundarydevices-imx6q-nitrogen6x-1g.img - -pblb-$(CONFIG_MACH_NITROGEN6) += start_imx6q_nitrogen6x_2g -CFG_start_imx6q_nitrogen6x_2g.pblb.imximg = $(board)/boundarydevices-nitrogen6/flash-header-nitrogen6q-2g.imxcfg -FILE_barebox-boundarydevices-imx6q-nitrogen6x-2g.img = start_imx6q_nitrogen6x_2g.pblb.imximg -image-$(CONFIG_MACH_NITROGEN6) += barebox-boundarydevices-imx6q-nitrogen6x-2g.img - -pblb-$(CONFIG_MACH_NITROGEN6) += start_imx6dl_nitrogen6x_1g -CFG_start_imx6dl_nitrogen6x_1g.pblb.imximg = $(board)/boundarydevices-nitrogen6/flash-header-nitrogen6dl-1g.imxcfg -FILE_barebox-boundarydevices-imx6dl-nitrogen6x-1g.img = start_imx6dl_nitrogen6x_1g.pblb.imximg -image-$(CONFIG_MACH_NITROGEN6) += barebox-boundarydevices-imx6dl-nitrogen6x-1g.img - -pblb-$(CONFIG_MACH_NITROGEN6) += start_imx6dl_nitrogen6x_2g -CFG_start_imx6dl_nitrogen6x_2g.pblb.imximg = $(board)/boundarydevices-nitrogen6/flash-header-nitrogen6dl-2g.imxcfg -FILE_barebox-boundarydevices-imx6dl-nitrogen6x-2g.img = start_imx6dl_nitrogen6x_2g.pblb.imximg -image-$(CONFIG_MACH_NITROGEN6) += barebox-boundarydevices-imx6dl-nitrogen6x-2g.img - -pblb-$(CONFIG_MACH_NITROGEN6) += start_imx6qp_nitrogen6_max -CFG_start_imx6qp_nitrogen6_max.pblb.imximg = $(board)/boundarydevices-nitrogen6/flash-header-nitrogen6qp-max.imxcfg -FILE_barebox-boundarydevices-imx6qp-nitrogen6_max.img = start_imx6qp_nitrogen6_max.pblb.imximg -image-$(CONFIG_MACH_NITROGEN6) += barebox-boundarydevices-imx6qp-nitrogen6_max.img - -pblb-$(CONFIG_MACH_TX6X) += start_imx6dl_tx6x_512m -CFG_start_imx6dl_tx6x_512m.pblb.imximg = $(board)/karo-tx6x/flash-header-tx6dl-512m.imxcfg -FILE_barebox-karo-imx6dl-tx6x-512m.img = start_imx6dl_tx6x_512m.pblb.imximg -image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6dl-tx6x-512m.img - -pblb-$(CONFIG_MACH_TX6X) += start_imx6dl_tx6x_1g -CFG_start_imx6dl_tx6x_1g.pblb.imximg = $(board)/karo-tx6x/flash-header-tx6dl-1g.imxcfg -FILE_barebox-karo-imx6dl-tx6x-1g.img = start_imx6dl_tx6x_1g.pblb.imximg -image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6dl-tx6x-1g.img - -pblb-$(CONFIG_MACH_TX6X) += start_imx6q_tx6x_1g -CFG_start_imx6q_tx6x_1g.pblb.imximg = $(board)/karo-tx6x/flash-header-tx6q-1g.imxcfg -FILE_barebox-karo-imx6q-tx6x-1g.img = start_imx6q_tx6x_1g.pblb.imximg -image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6q-tx6x-1g.img - -pblb-$(CONFIG_MACH_TX6X) += start_imx6q_tx6x_2g -CFG_start_imx6q_tx6x_2g.pblb.imximg = $(board)/karo-tx6x/flash-header-tx6qp-2g.imxcfg -FILE_barebox-karo-imx6qp-tx6x-2g.img = start_imx6q_tx6x_2g.pblb.imximg -image-$(CONFIG_MACH_TX6X) += barebox-karo-imx6qp-tx6x-2g.img - -pblb-$(CONFIG_MACH_UDOO) += start_imx6_udoo -CFG_start_imx6_udoo.pblb.imximg = $(board)/udoo/flash-header-mx6-udoo.imxcfg -FILE_barebox-udoo-imx6q.img = start_imx6_udoo.pblb.imximg -image-$(CONFIG_MACH_UDOO) += barebox-udoo-imx6q.img - -pblb-$(CONFIG_MACH_CM_FX6) += start_imx6_cm_fx6 -CFG_start_imx6_cm_fx6.pblb.imximg = $(board)/cm-fx6/flash-header-mx6-cm-fx6.imxcfg -FILE_barebox-cm-fx6.img = start_imx6_cm_fx6.pblb.imximg -image-$(CONFIG_MACH_CM_FX6) += barebox-cm-fx6.img - -pblb-$(CONFIG_MACH_CM_FX6) += start_imx6_utilite -CFG_start_imx6_utilite.pblb.imximg = $(board)/cm-fx6/flash-header-mx6-cm-fx6.imxcfg -FILE_barebox-utilite.img = start_imx6_utilite.pblb.imximg -image-$(CONFIG_MACH_CM_FX6) += barebox-utilite.img - -pblb-$(CONFIG_MACH_VARISCITE_MX6) += start_variscite_custom -CFG_start_variscite_custom.pblb.imximg = $(board)/variscite-mx6/flash-header-variscite.imxcfg -FILE_barebox-variscite-custom.img = start_variscite_custom.pblb.imximg -image-$(CONFIG_MACH_VARISCITE_MX6) += barebox-variscite-custom.img - -pblb-$(CONFIG_MACH_EMBEDSKY_E9) += start_imx6q_embedsky_e9 -CFG_start_imx6q_embedsky_e9.pblb.imximg = $(board)/embedsky-e9/flash-header-e9.imxcfg -FILE_barebox-embedsky-imx6q-e9.img = start_imx6q_embedsky_e9.pblb.imximg -image-$(CONFIG_MACH_EMBEDSKY_E9) += barebox-embedsky-imx6q-e9.img - -pblb-$(CONFIG_MACH_EMBEST_MARSBOARD) += start_imx6q_marsboard -CFG_start_imx6q_marsboard.pblb.imximg = $(board)/embest-marsboard/flash-header-embest-marsboard.imxcfg -FILE_barebox-embest-imx6q-marsboard.img = start_imx6q_marsboard.pblb.imximg -image-$(CONFIG_MACH_EMBEST_MARSBOARD) += barebox-embest-imx6q-marsboard.img - -pblb-$(CONFIG_MACH_EMBEST_RIOTBOARD) += start_imx6s_riotboard -CFG_start_imx6s_riotboard.pblb.imximg = $(board)/embest-riotboard/flash-header-embest-riotboard.imxcfg -FILE_barebox-embest-imx6s-riotboard.img = start_imx6s_riotboard.pblb.imximg -image-$(CONFIG_MACH_EMBEST_RIOTBOARD) += barebox-embest-imx6s-riotboard.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbaa03_1gib -CFG_start_phytec_pbaa03_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib.imxcfg -FILE_barebox-phytec-pbaa03-1gib.img = start_phytec_pbaa03_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbaa03-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbaa03_1gib_1bank -CFG_start_phytec_pbaa03_1gib_1bank.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib-1bank.imxcfg -FILE_barebox-phytec-pbaa03-1gib-1bank.img = start_phytec_pbaa03_1gib_1bank.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbaa03-1gib-1bank.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_pbaa03_2gib -CFG_start_phytec_pbaa03_2gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcaaxl3-2gib.imxcfg -FILE_barebox-phytec-pbaa03-2gib.img = start_phytec_pbaa03_2gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-pbaa03-2gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6q_som_nand_1gib -CFG_start_phytec_phycore_imx6q_som_nand_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg -FILE_barebox-phytec-phycore-imx6q-som-nand-1gib.img = start_phytec_phycore_imx6q_som_nand_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6q-som-nand-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6qp_som_nand_1gib -CFG_start_phytec_phycore_imx6qp_som_nand_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058qp-1gib.imxcfg -FILE_barebox-phytec-phycore-imx6qp-som-nand-1gib.img = start_phytec_phycore_imx6qp_som_nand_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6qp-som-nand-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6q_som_emmc_1gib -CFG_start_phytec_phycore_imx6q_som_emmc_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058-1gib.imxcfg -FILE_barebox-phytec-phycore-imx6q-som-emmc-1gib.img = start_phytec_phycore_imx6q_som_emmc_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6q-som-emmc-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6q_som_emmc_2gib -CFG_start_phytec_phycore_imx6q_som_emmc_2gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058-2gib.imxcfg -FILE_barebox-phytec-phycore-imx6q-som-emmc-2gib.img = start_phytec_phycore_imx6q_som_emmc_2gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6q-som-emmc-2gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_nand_256mb -CFG_start_phytec_phycore_imx6dl_som_nand_256mb.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-256mb.imxcfg -FILE_barebox-phytec-phycore-imx6dl-som-nand-256mb.img = start_phytec_phycore_imx6dl_som_nand_256mb.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-nand-256mb.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_nand_1gib -CFG_start_phytec_phycore_imx6dl_som_nand_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit.imxcfg -FILE_barebox-phytec-phycore-imx6dl-som-nand-1gib.img = start_phytec_phycore_imx6dl_som_nand_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-nand-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_lc_nand_256mb -CFG_start_phytec_phycore_imx6dl_som_lc_nand_256mb.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-256mb.imxcfg -FILE_barebox-phytec-phycore-imx6dl-som-lc-nand-256mb.img = start_phytec_phycore_imx6dl_som_lc_nand_256mb.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-lc-nand-256mb.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_emmc_1gib -CFG_start_phytec_phycore_imx6dl_som_emmc_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg -FILE_barebox-phytec-phycore-imx6dl-som-emmc-1gib.img = start_phytec_phycore_imx6dl_som_emmc_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-emmc-1gib.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6dl_som_lc_emmc_1gib -CFG_start_phytec_phycore_imx6dl_som_lc_emmc_1gib.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcm058dl-1gib.imxcfg -FILE_barebox-phytec-phycore-imx6dl-som-lc-emmc-1gib.img = start_phytec_phycore_imx6dl_som_lc_emmc_1gib.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6dl-som-lc-emmc-1gib.img - -pblb-$(CONFIG_MACH_KONTRON_SAMX6I) += start_imx6q_samx6i -CFG_start_imx6q_samx6i.pblb.imximg = $(board)/kontron-samx6i/flash-header-samx6i-quad.imxcfg -FILE_barebox-imx6q-samx6i.img = start_imx6q_samx6i.pblb.imximg -image-$(CONFIG_MACH_KONTRON_SAMX6I) += barebox-imx6q-samx6i.img - -pblb-$(CONFIG_MACH_KONTRON_SAMX6I) += start_imx6dl_samx6i -CFG_start_imx6dl_samx6i.pblb.imximg = $(board)/kontron-samx6i/flash-header-samx6i-duallite.imxcfg -FILE_barebox-imx6dl-samx6i.img = start_imx6dl_samx6i.pblb.imximg -image-$(CONFIG_MACH_KONTRON_SAMX6I) += barebox-imx6dl-samx6i.img - -pblb-$(CONFIG_MACH_GW_VENTANA) += start_imx6q_gw54xx_1gx64 -CFG_start_imx6q_gw54xx_1gx64.pblb.imximg = $(board)/gateworks-ventana/flash-header-ventana-quad-1gx64.imxcfg -FILE_barebox-gateworks-imx6q-ventana-1gx64.img = start_imx6q_gw54xx_1gx64.pblb.imximg -image-$(CONFIG_MACH_GW_VENTANA) += barebox-gateworks-imx6q-ventana-1gx64.img - -pblb-$(CONFIG_MACH_ELTEC_HIPERCAM) += start_imx6dl_eltec_hipercam -CFG_start_imx6dl_eltec_hipercam.pblb.imximg = $(board)/eltec-hipercam/flash-header-eltec-hipercam.imxcfg -FILE_barebox-eltec-hipercam.img = start_imx6dl_eltec_hipercam.pblb.imximg -image-$(CONFIG_MACH_ELTEC_HIPERCAM) += barebox-eltec-hipercam.img - -pblb-$(CONFIG_MACH_ADVANTECH_ROM_742X) += start_advantech_imx6dl_rom_7421 -CFG_start_advantech_imx6dl_rom_7421.pblb.imximg = $(board)/advantech-mx6/flash-header-advantech-rom-7421.imxcfg -FILE_barebox-advantech-imx6dl-rom-7421.img = start_advantech_imx6dl_rom_7421.pblb.imximg -image-$(CONFIG_MACH_ADVANTECH_ROM_742X) += barebox-advantech-imx6dl-rom-7421.img - -pblb-$(CONFIG_MACH_ZII_RDU2) += start_imx6_zii_rdu2 -CFG_start_imx6_zii_rdu2.pblb.imximg = $(board)/zii-imx6q-rdu2/flash-header-rdu2.imxcfg -FILE_barebox-zii-imx6-rdu2.img = start_imx6_zii_rdu2.pblb.imximg -image-$(CONFIG_MACH_ZII_RDU2) += barebox-zii-imx6-rdu2.img +$(call build_imx_habv4img, CONFIG_MACH_REALQ7, start_imx6_realq7, datamodul-edm-qmx6/flash-header, datamodul-edm-qmx6) + +$(call build_imx_habv4img, CONFIG_MACH_GUF_SANTARO, start_imx6q_guf_santaro, guf-santaro/flash-header, guf-santaro) + +$(call build_imx_habv4img, CONFIG_MACH_GK802, start_imx6_gk802, gk802/flash-header, gk802) + +$(call build_imx_habv4img, CONFIG_MACH_TQMA6X, start_imx6dl_mba6x, tqma6x/flash-header-tqma6dl, tq-tqma6s-mba6x) + +$(call build_imx_habv4img, CONFIG_MACH_TQMA6X, start_imx6q_mba6x, tqma6x/flash-header-tqma6q, tq-tqma6q-mba6x) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01_4gib, phytec-som-imx6/flash-header-phytec-pfla02-4gib, phytec-pbab01-4gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01_2gib, phytec-som-imx6/flash-header-phytec-pfla02-2gib, phytec-pbab01-2gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01_1gib, phytec-som-imx6/flash-header-phytec-pfla02-1gib, phytec-pbab01-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01_1gib_1bank, phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank, phytec-pbab01-1gib-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01_512mb_1bank, phytec-som-imx6/flash-header-phytec-pfla02-512mb-1bank, phytec-pbab01-512mb-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01dl_1gib, phytec-som-imx6/flash-header-phytec-pfla02dl-1gib, phytec-pbab01dl-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01dl_1gib_1bank, phytec-som-imx6/flash-header-phytec-pfla02dl-1gib-1bank, phytec-pbab01dl-1gib-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01s_512mb_1bank, phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank, phytec-pbab01s-512mb-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01s_256mb_1bank, phytec-som-imx6/flash-header-phytec-pfla02s-256mb-1bank, phytec-pbab01s-256mb-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbab01s_128mb_1bank, phytec-som-imx6/flash-header-phytec-pfla02s-128mb-1bank, phytec-pbab01s-128mb-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_alcor_1gib, phytec-som-imx6/flash-header-phytec-pfla02-1gib, phytec-phyboard-alcor-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_subra_512mb_1bank, phytec-som-imx6/flash-header-phytec-pfla02s-512mb-1bank, phytec-phyboard-subra-512mb-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phyboard_subra_1gib_1bank, phytec-som-imx6/flash-header-phytec-pfla02-1gib-1bank, phytec-phyboard-subra-1gib-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6dl_dfi_fs700_m60_6s, dfi-fs700-m60/flash-header-fs700-m60-6s, dfi-fs700-m60-6s) + +$(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6q_dfi_fs700_m60_6q_micron, dfi-fs700-m60/flash-header-fs700-m60-6q-micron, dfi-fs700-m60-6q-micron) + +$(call build_imx_habv4img, CONFIG_MACH_DFI_FS700_M60, start_imx6q_dfi_fs700_m60_6q_nanya, dfi-fs700-m60/flash-header-fs700-m60-6q-nanya, dfi-fs700-m60-6q-nanya) + +$(call build_imx_habv4img, CONFIG_MACH_SABRELITE, start_imx6q_sabrelite, freescale-mx6-sabrelite/flash-header-mx6-sabrelite, freescale-imx6q-sabrelite) + +$(call build_imx_habv4img, CONFIG_MACH_SABRELITE, start_imx6dl_sabrelite, freescale-mx6-sabrelite/flash-header-mx6-sabrelite, freescale-imx6dl-sabrelite) + +$(call build_imx_habv4img, CONFIG_MACH_SABRESD, start_imx6q_sabresd, freescale-mx6-sabresd/flash-header-mx6-sabresd, freescale-imx6q-sabresd) + +$(call build_imx_habv4img, CONFIG_MACH_UDOO_NEO, start_imx6sx_udoo_neo, udoo-neo/flash-header-mx6sx-udoo-neo_full, udoo-neo) + +$(call build_imx_habv4img, CONFIG_MACH_FREESCALE_IMX6SX_SABRESDB, start_imx6sx_sabresdb, freescale-mx6sx-sabresdb/flash-header-mx6sx-sabresdb, freescale-imx6sx-sabresdb) + +$(call build_imx_habv4img, CONFIG_MACH_TECHNEXION_WANDBOARD, start_imx6_wandboard, technexion-wandboard/flash-header-technexion-wandboard, imx6-wandboard) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard_microsom_i1, solidrun-microsom/flash-header-microsom-i1, solidrun-hummingboard-microsom-i1) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard_microsom_i2, solidrun-microsom/flash-header-microsom-i2, solidrun-hummingboard-microsom-i2) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard_microsom_i2ex, solidrun-microsom/flash-header-microsom-i2eX, solidrun-hummingboard-microsom-i2eX) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard_microsom_i4, solidrun-microsom/flash-header-microsom-i4, solidrun-hummingboard-microsom-i4) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard2_microsom_i1, solidrun-microsom/flash-header-microsom-i1, solidrun-hummingboard2-microsom-i1) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard2_microsom_i2, solidrun-microsom/flash-header-microsom-i2, solidrun-hummingboard2-microsom-i2) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard2_microsom_i2ex, solidrun-microsom/flash-header-microsom-i2eX, solidrun-hummingboard2-microsom-i2eX) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_hummingboard2_microsom_i4, solidrun-microsom/flash-header-microsom-i4, solidrun-hummingboard2-microsom-i4) + +$(call build_imx_habv4img, CONFIG_MACH_SOLIDRUN_MICROSOM, start_h100_microsom_i2ex, solidrun-microsom/flash-header-microsom-i2eX, auvidea-h100-microsom-i2eX) + +$(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6q_nitrogen6x_1g, boundarydevices-nitrogen6/flash-header-nitrogen6q-1g, boundarydevices-imx6q-nitrogen6x-1g) + +$(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6q_nitrogen6x_2g, boundarydevices-nitrogen6/flash-header-nitrogen6q-2g, boundarydevices-imx6q-nitrogen6x-2g) + +$(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6dl_nitrogen6x_1g, boundarydevices-nitrogen6/flash-header-nitrogen6dl-1g, boundarydevices-imx6dl-nitrogen6x-1g) + +$(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6dl_nitrogen6x_2g, boundarydevices-nitrogen6/flash-header-nitrogen6dl-2g, boundarydevices-imx6dl-nitrogen6x-2g) + +$(call build_imx_habv4img, CONFIG_MACH_NITROGEN6, start_imx6qp_nitrogen6_max, boundarydevices-nitrogen6/flash-header-nitrogen6qp-max, boundarydevices-imx6qp-nitrogen6_max) + +$(call build_imx_habv4img, CONFIG_MACH_TX6X, start_imx6dl_tx6x_512m, karo-tx6x/flash-header-tx6dl-512m, karo-imx6dl-tx6x-512m) + +$(call build_imx_habv4img, CONFIG_MACH_TX6X, start_imx6dl_tx6x_1g, karo-tx6x/flash-header-tx6dl-1g, karo-imx6dl-tx6x-1g) + +$(call build_imx_habv4img, CONFIG_MACH_TX6X, start_imx6q_tx6x_1g, karo-tx6x/flash-header-tx6q-1g, karo-imx6q-tx6x-1g) + +$(call build_imx_habv4img, CONFIG_MACH_TX6X, start_imx6q_tx6x_2g, karo-tx6x/flash-header-tx6qp-2g, karo-imx6qp-tx6x-2g) + +$(call build_imx_habv4img, CONFIG_MACH_UDOO, start_imx6_udoo, udoo/flash-header-mx6-udoo, udoo-imx6q) + +$(call build_imx_habv4img, CONFIG_MACH_CM_FX6, start_imx6_cm_fx6, cm-fx6/flash-header-mx6-cm-fx6, cm-fx6) + +$(call build_imx_habv4img, CONFIG_MACH_CM_FX6, start_imx6_utilite, cm-fx6/flash-header-mx6-cm-fx6, utilite) + +$(call build_imx_habv4img, CONFIG_MACH_VARISCITE_MX6, start_variscite_custom, variscite-mx6/flash-header-variscite, variscite-custom) + +$(call build_imx_habv4img, CONFIG_MACH_EMBEDSKY_E9, start_imx6q_embedsky_e9, embedsky-e9/flash-header-e9, embedsky-imx6q-e9) + +$(call build_imx_habv4img, CONFIG_MACH_EMBEST_MARSBOARD, start_imx6q_marsboard, embest-marsboard/flash-header-embest-marsboard, barebox-embest-imx6q-marsboard) + +$(call build_imx_habv4img, CONFIG_MACH_EMBEST_RIOTBOARD, start_imx6s_riotboard, embest-riotboard/flash-header-embest-riotboard, embest-imx6s-riotboard) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbaa03_1gib, phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib, phytec-pbaa03-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbaa03_1gib_1bank, phytec-som-imx6/flash-header-phytec-pcaaxl3-1gib-1bank, phytec-pbaa03-1gib-1bank) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_pbaa03_2gib, phytec-som-imx6/flash-header-phytec-pcaaxl3-2gib, phytec-pbaa03-2gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6q_som_nand_1gib, phytec-som-imx6/flash-header-phytec-pcm058-1gib, phytec-phycore-imx6q-som-nand-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6qp_som_nand_1gib, phytec-som-imx6/flash-header-phytec-pcm058qp-1gib, phytec-phycore-imx6qp-som-nand-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6q_som_emmc_1gib, phytec-som-imx6/flash-header-phytec-pcm058-1gib, phytec-phycore-imx6q-som-emmc-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6q_som_emmc_2gib, phytec-som-imx6/flash-header-phytec-pcm058-2gib, phytec-phycore-imx6q-som-emmc-2gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6dl_som_nand_256mb, phytec-som-imx6/flash-header-phytec-pcm058dl-256mb, phytec-phycore-imx6dl-som-nand-256mb) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6dl_som_nand_1gib, phytec-som-imx6/flash-header-phytec-pcm058dl-1gib-32bit, phytec-phycore-imx6dl-som-nand-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6dl_som_lc_nand_256mb, phytec-som-imx6/flash-header-phytec-pcm058dl-256mb, phytec-phycore-imx6dl-som-lc-nand-256mb) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6dl_som_emmc_1gib, phytec-som-imx6/flash-header-phytec-pcm058dl-1gib, phytec-phycore-imx6dl-som-emmc-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6dl_som_lc_emmc_1gib, phytec-som-imx6/flash-header-phytec-pcm058dl-1gib, phytec-phycore-imx6dl-som-lc-emmc-1gib) + +$(call build_imx_habv4img, CONFIG_MACH_KONTRON_SAMX6I, start_imx6q_samx6i, kontron-samx6i/flash-header-samx6i-quad, imx6q-samx6i) + +$(call build_imx_habv4img, CONFIG_MACH_KONTRON_SAMX6I, start_imx6dl_samx6i, kontron-samx6i/flash-header-samx6i-duallite, imx6dl-samx6i) + +$(call build_imx_habv4img, CONFIG_MACH_GW_VENTANA, start_imx6q_gw54xx_1gx64, gateworks-ventana/flash-header-ventana-quad-1gx64, gateworks-imx6q-ventana-1gx64) + +$(call build_imx_habv4img, CONFIG_MACH_ELTEC_HIPERCAM, start_imx6dl_eltec_hipercam, eltec-hipercam/flash-header-eltec-hipercam, eltec-hipercam) + +$(call build_imx_habv4img, CONFIG_MACH_ADVANTECH_ROM_742X, start_advantech_imx6dl_rom_7421, advantech-mx6/flash-header-advantech-rom-7421, advantech-imx6dl-rom-7421) + +$(call build_imx_habv4img, CONFIG_MACH_ZII_RDU2, start_imx6_zii_rdu2, zii-imx6q-rdu2/flash-header-rdu2, zii-imx6-rdu2) # ----------------------- i.MX6ul / i.MX6ull based boards -------------- -pblb-$(CONFIG_MACH_GRINN_LITEBOARD) += start_imx6ul_liteboard_256mb -CFG_start_imx6ul_liteboard_256mb.pblb.imximg = $(board)/grinn-liteboard/flash-header-liteboard-256mb.imxcfg -FILE_barebox-grinn-liteboard-256mb.img = start_imx6ul_liteboard_256mb.pblb.imximg -image-$(CONFIG_MACH_GRINN_LITEBOARD) += barebox-grinn-liteboard-256mb.img - -pblb-$(CONFIG_MACH_GRINN_LITEBOARD) += start_imx6ul_liteboard_512mb -CFG_start_imx6ul_liteboard_512mb.pblb.imximg = $(board)/grinn-liteboard/flash-header-liteboard-512mb.imxcfg -FILE_barebox-grinn-liteboard-512mb.img = start_imx6ul_liteboard_512mb.pblb.imximg -image-$(CONFIG_MACH_GRINN_LITEBOARD) += barebox-grinn-liteboard-512mb.img - -pblb-$(CONFIG_MACH_NXP_IMX6ULL_EVK) += start_nxp_imx6ull_evk -CFG_start_nxp_imx6ull_evk.pblb.imximg = $(board)/nxp-imx6ull-evk/flash-header-nxp-imx6ull-evk.imxcfg -FILE_barebox-nxp-imx6ull-evk.img = start_nxp_imx6ull_evk.pblb.imximg -image-$(CONFIG_MACH_NXP_IMX6ULL_EVK) += barebox-nxp-imx6ull-evk.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6ul_som_nand_512mb -CFG_start_phytec_phycore_imx6ul_som_nand_512mb.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg -FILE_barebox-phytec-phycore-imx6ul-nand-512mb.img = start_phytec_phycore_imx6ul_som_nand_512mb.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6ul-nand-512mb.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6ull_som_lc_nand_256mb -CFG_start_phytec_phycore_imx6ull_som_lc_nand_256mb.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcl063-256mb.imxcfg -FILE_barebox-phytec-phycore-imx6ull-lc-nand-256mb.img = start_phytec_phycore_imx6ull_som_lc_nand_256mb.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6ull-lc-nand-256mb.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6ull_som_nand_512mb -CFG_start_phytec_phycore_imx6ull_som_nand_512mb.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg -FILE_barebox-phytec-phycore-imx6ull-nand-512mb.img = start_phytec_phycore_imx6ull_som_nand_512mb.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6ull-nand-512mb.img - -pblb-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += start_phytec_phycore_imx6ull_som_emmc_512mb -CFG_start_phytec_phycore_imx6ull_som_emmc_512mb.pblb.imximg = $(board)/phytec-som-imx6/flash-header-phytec-pcl063-512mb.imxcfg -FILE_barebox-phytec-phycore-imx6ull-emmc-512mb.img = start_phytec_phycore_imx6ull_som_emmc_512mb.pblb.imximg -image-$(CONFIG_MACH_PHYTEC_SOM_IMX6) += barebox-phytec-phycore-imx6ull-emmc-512mb.img - -pblb-$(CONFIG_MACH_TECHNEXION_PICO_HOBBIT) += start_imx6ul_pico_hobbit_256mb -CFG_start_imx6ul_pico_hobbit_256mb.pblb.imximg = $(board)/technexion-pico-hobbit/flash-header-imx6ul-pico-hobbit-256.imxcfg -FILE_barebox-imx6ul-pico-hobbit-256mb.img = start_imx6ul_pico_hobbit_256mb.pblb.imximg -image-$(CONFIG_MACH_TECHNEXION_PICO_HOBBIT) += barebox-imx6ul-pico-hobbit-256mb.img - -pblb-$(CONFIG_MACH_TECHNEXION_PICO_HOBBIT) += start_imx6ul_pico_hobbit_512mb -CFG_start_imx6ul_pico_hobbit_512mb.pblb.imximg = $(board)/technexion-pico-hobbit/flash-header-imx6ul-pico-hobbit-512.imxcfg -FILE_barebox-imx6ul-pico-hobbit-512mb.img = start_imx6ul_pico_hobbit_512mb.pblb.imximg -image-$(CONFIG_MACH_TECHNEXION_PICO_HOBBIT) += barebox-imx6ul-pico-hobbit-512mb.img - -pblb-$(CONFIG_MACH_DIGI_CCIMX6ULSBCPRO) += start_imx6ul_ccimx6ulsbcpro -CFG_start_imx6ul_ccimx6ulsbcpro.pblb.imximg = $(board)/digi-ccimx6ulsom/flash-header-imx6ul-ccimx6ulsbcpro.imxcfg -FILE_barebox-imx6ul-ccimx6ulsbcpro.img = start_imx6ul_ccimx6ulsbcpro.pblb.imximg -image-$(CONFIG_MACH_DIGI_CCIMX6ULSBCPRO) += barebox-imx6ul-ccimx6ulsbcpro.img +$(call build_imx_habv4img, CONFIG_MACH_GRINN_LITEBOARD, start_imx6ul_liteboard_256mb, grinn-liteboard/flash-header-liteboard-256mb, grinn-liteboard-256mb) + +$(call build_imx_habv4img, CONFIG_MACH_GRINN_LITEBOARD, start_imx6ul_liteboard_512mb, grinn-liteboard/flash-header-liteboard-512mb, grinn-liteboard-512mb) + +$(call build_imx_habv4img, CONFIG_MACH_NXP_IMX6ULL_EVK, start_nxp_imx6ull_evk, nxp-imx6ull-evk/flash-header-nxp-imx6ull-evk, nxp-imx6ull-evk) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6ul_som_nand_512mb, phytec-som-imx6/flash-header-phytec-pcl063-512mb, phytec-phycore-imx6ul-nand-512mb) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6ull_som_lc_nand_256mb, phytec-som-imx6/flash-header-phytec-pcl063-256mb, phytec-phycore-imx6ull-lc-nand-256mb) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6ull_som_nand_512mb, phytec-som-imx6/flash-header-phytec-pcl063-512mb, phytec-phycore-imx6ull-nand-512mb) + +$(call build_imx_habv4img, CONFIG_MACH_PHYTEC_SOM_IMX6, start_phytec_phycore_imx6ull_som_emmc_512mb, phytec-som-imx6/flash-header-phytec-pcl063-512mb, phytec-phycore-imx6ull-emmc-512mb) + +$(call build_imx_habv4img, CONFIG_MACH_TECHNEXION_PICO_HOBBIT, start_imx6ul_pico_hobbit_256mb, technexion-pico-hobbit/flash-header-imx6ul-pico-hobbit-256, imx6ul-pico-hobbit-256mb) + +$(call build_imx_habv4img, CONFIG_MACH_TECHNEXION_PICO_HOBBIT, start_imx6ul_pico_hobbit_512mb, technexion-pico-hobbit/flash-header-imx6ul-pico-hobbit-512, imx6ul-pico-hobbit-512mb) + +$(call build_imx_habv4img, CONFIG_MACH_DIGI_CCIMX6ULSBCPRO, start_imx6ul_ccimx6ulsbcpro, digi-ccimx6ulsom/flash-header-imx6ul-ccimx6ulsbcpro, imx6ul-ccimx6ulsbcpro) # ----------------------- vf6xx based boards --------------------------- pblb-$(CONFIG_MACH_VF610_TWR) += start_vf610_twr diff --git a/include/acpi.h b/include/acpi.h new file mode 100644 index 0000000000..2d5fd3086a --- /dev/null +++ b/include/acpi.h @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 Ahmad Fatoum + */ + +#ifndef __ACPI_H_ +#define __ACPI_H_ + +#include <linux/types.h> +#include <driver.h> + +typedef char acpi_sig_t[4]; + +struct __packed acpi_rsdp { /* root system description pointer */ + char signature[8]; + u8 checksum; + u8 oem_id[6]; + u8 revision; + u32 rsdt_addr; +}; + +struct __packed acpi2_rsdp { /* root system description */ + struct acpi_rsdp acpi1; + u32 length; + u64 xsdt_addr; + u8 extended_checksum; + u8 reserved[3]; +}; + +struct __packed acpi_sdt { /* system description table header */ + acpi_sig_t signature; + u32 len; + u8 revision; + u8 checksum; + char oem_id[6]; + char oem_table_id[8]; + u32 oem_revision; + u32 creator_id; + u32 creator_revision; +}; + +struct __packed acpi_rsdt { /* system description table header */ + struct acpi_sdt sdt; + struct acpi_sdt * __aligned(8) entries[]; +}; + +struct acpi_driver { + struct driver_d driver; + acpi_sig_t signature; +}; + +extern struct bus_type acpi_bus; + +static inline struct acpi_driver *to_acpi_driver(struct driver_d *drv) +{ + return container_of(drv, struct acpi_driver, driver); +} + +#define device_acpi_driver(drv) \ + register_driver_macro(device, acpi, drv) + +static inline int acpi_driver_register(struct acpi_driver *acpidrv) +{ + acpidrv->driver.bus = &acpi_bus; + return register_driver(&acpidrv->driver); +} + +static inline int acpi_sigcmp(const acpi_sig_t sig_a, const acpi_sig_t sig_b) +{ + return memcmp(sig_a, sig_b, sizeof(acpi_sig_t)); +} + +#endif diff --git a/include/common.h b/include/common.h index 6563068467..c6eb50420f 100644 --- a/include/common.h +++ b/include/common.h @@ -68,7 +68,12 @@ long get_ram_size (volatile long *, long); /* common/console.c */ int ctrlc(void); int arch_ctrlc(void); + +#ifdef CONFIG_CONSOLE_FULL void ctrlc_handled(void); +#else +static inline void ctrlc_handled(void) { } +#endif #ifdef CONFIG_ARCH_HAS_STACK_DUMP void dump_stack(void); diff --git a/include/console.h b/include/console.h index 7afe59e93a..537ac97ab3 100644 --- a/include/console.h +++ b/include/console.h @@ -207,7 +207,12 @@ static inline void pbl_set_putc(void (*putcf)(void *ctx, int c), void *ctx) {} bool console_allow_color(void); +#ifdef CONFIG_CONSOLE_FULL void console_ctrlc_allow(void); void console_ctrlc_forbid(void); +#else +static inline void console_ctrlc_allow(void) { } +static inline void console_ctrlc_forbid(void) { } +#endif #endif diff --git a/include/driver.h b/include/driver.h index 300603fa32..ad59ce90c3 100644 --- a/include/driver.h +++ b/include/driver.h @@ -155,12 +155,12 @@ int unregister_device(struct device_d *); /* Iterate over a devices children */ #define device_for_each_child(dev, child) \ - list_for_each_entry(child, &dev->children, sibling) + list_for_each_entry(child, &(dev)->children, sibling) /* Iterate over a devices children - Safe against removal version */ #define device_for_each_child_safe(dev, tmpdev, child) \ - list_for_each_entry_safe(child, tmpdev, &dev->children, sibling) + list_for_each_entry_safe(child, tmpdev, &(dev)->children, sibling) /* Iterate through the devices of a given type. if last is NULL, the * first device of this type is returned. Put this pointer in as diff --git a/include/efi.h b/include/efi.h index 166803a58f..43c0593951 100644 --- a/include/efi.h +++ b/include/efi.h @@ -91,21 +91,23 @@ typedef struct { */ /* Memory types: */ -#define EFI_RESERVED_TYPE 0 -#define EFI_LOADER_CODE 1 -#define EFI_LOADER_DATA 2 -#define EFI_BOOT_SERVICES_CODE 3 -#define EFI_BOOT_SERVICES_DATA 4 -#define EFI_RUNTIME_SERVICES_CODE 5 -#define EFI_RUNTIME_SERVICES_DATA 6 -#define EFI_CONVENTIONAL_MEMORY 7 -#define EFI_UNUSABLE_MEMORY 8 -#define EFI_ACPI_RECLAIM_MEMORY 9 -#define EFI_ACPI_MEMORY_NVS 10 -#define EFI_MEMORY_MAPPED_IO 11 -#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 -#define EFI_PAL_CODE 13 -#define EFI_MAX_MEMORY_TYPE 14 +enum efi_memory_type { + EFI_RESERVED_TYPE, + EFI_LOADER_CODE, + EFI_LOADER_DATA, + EFI_BOOT_SERVICES_CODE, + EFI_BOOT_SERVICES_DATA, + EFI_RUNTIME_SERVICES_CODE, + EFI_RUNTIME_SERVICES_DATA, + EFI_CONVENTIONAL_MEMORY, + EFI_UNUSABLE_MEMORY, + EFI_ACPI_RECLAIM_MEMORY, + EFI_ACPI_MEMORY_NVS, + EFI_MEMORY_MAPPED_IO, + EFI_MEMORY_MAPPED_IO_PORT_SPACE, + EFI_PAL_CODE, + EFI_MAX_MEMORY_TYPE +}; /* Attribute values: */ #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ @@ -124,10 +126,12 @@ typedef struct { /* * Allocation types for calls to boottime->allocate_pages. */ -#define EFI_ALLOCATE_ANY_PAGES 0 -#define EFI_ALLOCATE_MAX_ADDRESS 1 -#define EFI_ALLOCATE_ADDRESS 2 -#define EFI_MAX_ALLOCATE_TYPE 3 +enum efi_allocate_type { + EFI_ALLOCATE_ANY_PAGES, + EFI_ALLOCATE_MAX_ADDRESS, + EFI_ALLOCATE_ADDRESS, + EFI_MAX_ALLOCATE_TYPE +}; typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); diff --git a/include/efi/efi-device.h b/include/efi/efi-device.h index 5eaf1f260d..5ec59a8a2d 100644 --- a/include/efi/efi-device.h +++ b/include/efi/efi-device.h @@ -45,4 +45,16 @@ int efi_connect_all(void); void efi_register_devices(void); struct efi_device *efi_get_bootsource(void); +static inline bool efi_device_has_guid(struct efi_device *efidev, efi_guid_t guid) +{ + int i; + + for (i = 0; i < efidev->num_guids; i++) { + if (!efi_guidcmp(efidev->guids[i], guid)) + return true; + } + + return false; +} + #endif /* __EFI_EFI_DEVICE_H */ diff --git a/include/gpio.h b/include/gpio.h index 4d5f2c25c7..0c0c0337e0 100644 --- a/include/gpio.h +++ b/include/gpio.h @@ -114,6 +114,11 @@ static inline int gpio_request(unsigned gpio, const char *label) return 0; } +static inline int gpio_find_by_name(const char *name) +{ + return -ENOSYS; +} + static inline int gpio_find_by_label(const char *label) { return -ENOSYS; @@ -141,6 +146,7 @@ static inline void gpio_free_array(const struct gpio *array, size_t num) } #else int gpio_request(unsigned gpio, const char *label); +int gpio_find_by_name(const char *name); int gpio_find_by_label(const char *label); void gpio_free(unsigned gpio); int gpio_request_one(unsigned gpio, unsigned long flags, const char *label); diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index d8125214a0..1fbb3dc5c1 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -15,6 +15,7 @@ struct pci_device_id { __u32 vendor, device; /* Vendor and device ID or PCI_ANY_ID*/ __u32 subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */ __u32 class, class_mask; /* (class,subclass,prog-if) triplet */ + unsigned long driver_data; /* Data private to the driver */ }; #define SPI_NAME_SIZE 32 diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 105f381ada..1c6f442866 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -116,7 +116,7 @@ #define FSR_READY BIT(7) /* Configuration Register bits. */ -#define CR_QUAD_EN_SPAN BIT(2) /* Spansion Quad I/O */ +#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ /* Supported SPI protocols */ #define SNOR_PROTO_INST_MASK GENMASK(23, 16) diff --git a/include/linux/pci.h b/include/linux/pci.h index d92d70b6bd..c742570e36 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -115,6 +115,17 @@ struct pci_dev { }; #define to_pci_dev(d) container_of(d, struct pci_dev, dev) +#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) +#define pci_resource_end(dev, bar) ((dev)->resource[(bar)].end) +#define pci_resource_flags(dev, bar) ((dev)->resource[(bar)].flags) +#define pci_resource_len(dev,bar) \ + ((pci_resource_start((dev), (bar)) == 0 && \ + pci_resource_end((dev), (bar)) == \ + pci_resource_start((dev), (bar))) ? 0 : \ + \ + (pci_resource_end((dev), (bar)) - \ + pci_resource_start((dev), (bar)) + 1)) + enum { PCI_BUS_RESOURCE_IO = 0, PCI_BUS_RESOURCE_MEM = 1, @@ -211,6 +222,20 @@ struct pci_driver { .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID /** + * PCI_DEVICE_SUB - macro used to describe a specific PCI device with subsystem + * @vend: the 16 bit PCI Vendor ID + * @dev: the 16 bit PCI Device ID + * @subvend: the 16 bit PCI Subvendor ID + * @subdev: the 16 bit PCI Subdevice ID + * + * This macro is used to create a struct pci_device_id that matches a + * specific device with subsystem information. + */ +#define PCI_DEVICE_SUB(vend, dev, subvend, subdev) \ + .vendor = (vend), .device = (dev), \ + .subvendor = (subvend), .subdevice = (subdev) + +/** * PCI_DEVICE_CLASS - macro used to describe a specific pci device class * @dev_class: the class, subclass, prog-if triple for this device * @dev_class_mask: the class mask for this device @@ -350,4 +375,13 @@ enum pci_fixup_pass { void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev); +#ifdef CONFIG_PCI +const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, + struct pci_dev *dev); +#else +static inline const struct pci_device_id *pci_match_id(const struct pci_device_id *ids, + struct pci_dev *dev) +{ return NULL; } +#endif + #endif /* LINUX_PCI_H */ diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index feee9ee4ee..c6264d1c0a 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -38,7 +38,6 @@ struct rproc { void *priv; struct rproc_ops *ops; struct device_d dev; - int index; void *fw_buf; size_t fw_buf_ofs; diff --git a/include/of.h b/include/of.h index 98ddf795cb..f63a3efe13 100644 --- a/include/of.h +++ b/include/of.h @@ -197,14 +197,12 @@ extern int of_property_read_u64(const struct device_node *np, extern int of_property_read_string(struct device_node *np, const char *propname, const char **out_string); -extern int of_property_read_string_index(struct device_node *np, - const char *propname, - int index, const char **output); extern int of_property_match_string(struct device_node *np, const char *propname, const char *string); -extern int of_property_count_strings(struct device_node *np, - const char *propname); +extern int of_property_read_string_helper(const struct device_node *np, + const char *propname, + const char **out_strs, size_t sz, int index); extern const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur, u32 *pu); @@ -444,20 +442,15 @@ static inline int of_property_read_string(struct device_node *np, return -ENOSYS; } -static inline int of_property_read_string_index(struct device_node *np, - const char *propname, int index, const char **output) -{ - return -ENOSYS; -} - static inline int of_property_match_string(struct device_node *np, const char *propname, const char *string) { return -ENOSYS; } -static inline int of_property_count_strings(struct device_node *np, - const char *propname) +static inline int of_property_read_string_helper(const struct device_node *np, + const char *propname, + const char **out_strs, size_t sz, int index) { return -ENOSYS; } @@ -753,6 +746,70 @@ static inline struct device_node *of_find_matching_node( child = of_get_next_available_child(parent, child)) /** + * of_property_read_string_array() - Read an array of strings from a multiple + * strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @out_strs: output array of string pointers. + * @sz: number of array elements to read. + * + * Search for a property in a device tree node and retrieve a list of + * terminated string values (pointer to data, not a copy) in that property. + * + * If @out_strs is NULL, the number of strings in the property is returned. + */ +static inline int of_property_read_string_array(const struct device_node *np, + const char *propname, const char **out_strs, + size_t sz) +{ + return of_property_read_string_helper(np, propname, out_strs, sz, 0); +} + +/** + * of_property_count_strings() - Find and return the number of strings from a + * multiple strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * + * Search for a property in a device tree node and retrieve the number of null + * terminated string contain in it. Returns the number of strings on + * success, -EINVAL if the property does not exist, -ENODATA if property + * does not have a value, and -EILSEQ if the string is not null-terminated + * within the length of the property data. + */ +static inline int of_property_count_strings(const struct device_node *np, + const char *propname) +{ + return of_property_read_string_helper(np, propname, NULL, 0, 0); +} + +/** + * of_property_read_string_index() - Find and read a string from a multiple + * strings property. + * @np: device node from which the property value is to be read. + * @propname: name of the property to be searched. + * @index: index of the string in the list of strings + * @out_string: pointer to null terminated return string, modified only if + * return value is 0. + * + * Search for a property in a device tree node and retrieve a null + * terminated string value (pointer to data, not a copy) in the list of strings + * contained in that property. + * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EILSEQ if the string is not + * null-terminated within the length of the property data. + * + * The out_string pointer is modified only if a valid string can be decoded. + */ +static inline int of_property_read_string_index(const struct device_node *np, + const char *propname, + int index, const char **output) +{ + int rc = of_property_read_string_helper(np, propname, output, 1, index); + return rc < 0 ? rc : 0; +} + +/** * of_property_read_bool - Findfrom a property * @np: device node from which the property value is to be read. * @propname: name of the property to be searched. diff --git a/include/param.h b/include/param.h index 4ac502e726..d75f50ea3e 100644 --- a/include/param.h +++ b/include/param.h @@ -63,6 +63,16 @@ struct param_d *dev_add_param_enum(struct device_d *dev, const char *name, int (*get)(struct param_d *p, void *priv), int *value, const char * const *names, int max, void *priv); +enum param_tristate { PARAM_TRISTATE_UNKNOWN, PARAM_TRISTATE_TRUE, PARAM_TRISTATE_FALSE }; + +struct param_d *dev_add_param_tristate(struct device_d *dev, const char *name, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, void *priv); + +struct param_d *dev_add_param_tristate_ro(struct device_d *dev, const char *name, + int *value); + struct param_d *dev_add_param_bitmask(struct device_d *dev, const char *name, int (*set)(struct param_d *p, void *priv), int (*get)(struct param_d *p, void *priv), @@ -144,6 +154,20 @@ static inline struct param_d *dev_add_param_bitmask(struct device_d *dev, const return ERR_PTR(-ENOSYS); } +static inline struct param_d *dev_add_param_tristate(struct device_d *dev, const char *name, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, void *priv) +{ + return ERR_PTR(-ENOSYS); +} + +static inline struct param_d *dev_add_param_tristate_ro(struct device_d *dev, const char *name, + int *value) +{ + return ERR_PTR(-ENOSYS); +} + static inline struct param_d *dev_add_param_ip(struct device_d *dev, const char *name, int (*set)(struct param_d *p, void *priv), int (*get)(struct param_d *p, void *priv), diff --git a/include/reset_source.h b/include/reset_source.h index 3ccd529fdd..305dde0102 100644 --- a/include/reset_source.h +++ b/include/reset_source.h @@ -60,6 +60,11 @@ static inline struct device_d *reset_source_get_device(void) return NULL; } +static inline void reset_source_set_device(struct device_d *dev, + enum reset_src_type st) +{ +} + static inline void reset_source_set_prinst(enum reset_src_type type, unsigned int priority, int instance) { diff --git a/include/soc/fsl/fsl_fman.h b/include/soc/fsl/fsl_fman.h index 96d61298ef..fd69fded38 100644 --- a/include/soc/fsl/fsl_fman.h +++ b/include/soc/fsl/fsl_fman.h @@ -348,6 +348,9 @@ struct fm_fpm { /* FPM Flush Control Register */ #define FMFP_FLC_DISP_LIM_NONE 0x00000000 /* no dispatch limitation */ +/* FMan Reset Command Register */ +#define FMFP_RSTC_RFM 0x80000000 /* FMan Soft Reset Command */ + /* FMFP_EE - FPM event and enable register */ #define FMFPEE_DECC 0x80000000 /* double ECC err on FPM ram */ #define FMFPEE_STL 0x40000000 /* stall of task ... */ diff --git a/include/usb/chipidea-imx.h b/include/usb/chipidea-imx.h index 973aee6a0e..5ea5fcc26d 100644 --- a/include/usb/chipidea-imx.h +++ b/include/usb/chipidea-imx.h @@ -37,16 +37,10 @@ #define MXC_EHCI_DISABLE_OVERCURRENT (1 << 14) -enum imx_usb_mode { - IMX_USB_MODE_HOST, - IMX_USB_MODE_DEVICE, - IMX_USB_MODE_OTG, -}; - struct imxusb_platformdata { unsigned long flags; enum usb_phy_interface phymode; - enum imx_usb_mode mode; + enum usb_dr_mode mode; }; int imx_usbmisc_port_init(struct device_d *dev, int port, unsigned flags); diff --git a/include/usb/usb.h b/include/usb/usb.h index 0045608d64..d39de71aff 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -444,6 +444,9 @@ enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np, enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np, const char *propname); +int usb_register_otg_device(struct device_d *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx); + extern struct list_head usb_device_list; #endif /*_USB_H_ */ diff --git a/include/watchdog.h b/include/watchdog.h index 184a218916..9741570ce2 100644 --- a/include/watchdog.h +++ b/include/watchdog.h @@ -15,6 +15,13 @@ #include <poller.h> #include <driver.h> +#include <param.h> + +enum wdog_hw_runnning { + WDOG_HW_RUNNING_UNSUPPORTED = PARAM_TRISTATE_UNKNOWN, + WDOG_HW_RUNNING = PARAM_TRISTATE_TRUE, + WDOG_HW_NOT_RUNNING = PARAM_TRISTATE_FALSE +}; struct watchdog { int (*set_timeout)(struct watchdog *, unsigned); @@ -27,15 +34,27 @@ struct watchdog { unsigned int poller_enable; struct poller_async poller; struct list_head list; + int running; /* enum wdog_hw_running */ }; +/* + * Use the following function to check whether or not the hardware watchdog + * is running + */ +static inline int watchdog_hw_running(struct watchdog *w) +{ + if (w->running == WDOG_HW_RUNNING_UNSUPPORTED) + return -ENOSYS; + + return w->running == WDOG_HW_RUNNING; +} + #ifdef CONFIG_WATCHDOG int watchdog_register(struct watchdog *); int watchdog_deregister(struct watchdog *); struct watchdog *watchdog_get_default(void); struct watchdog *watchdog_get_by_name(const char *name); int watchdog_set_timeout(struct watchdog*, unsigned); -unsigned int of_get_watchdog_priority(struct device_node *node); #else static inline int watchdog_register(struct watchdog *w) { @@ -61,12 +80,6 @@ static inline int watchdog_set_timeout(struct watchdog*w, unsigned t) { return 0; } - - -static inline unsigned int of_get_watchdog_priority(struct device_node *node) -{ - return 0; -} #endif #define WATCHDOG_DEFAULT_PRIORITY 100 diff --git a/lib/Kconfig b/lib/Kconfig index 6216fdd6ba..9a80780186 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -105,6 +105,11 @@ config LIBFDT config RATP select CRC_ITU_T + select COMPILE_MEMORY + select COMMAND_SUPPORT + select POLLER + depends on CONSOLE_FULL + depends on !SHELL_NONE bool "RATP protocol support" help Reliable Asynchronous Transfer Protocol (RATP) is a protocol for reliably diff --git a/lib/gui/picopng.c b/lib/gui/picopng.c index ad44efa689..80f03beb68 100644 --- a/lib/gui/picopng.c +++ b/lib/gui/picopng.c @@ -32,7 +32,7 @@ typedef struct png_alloc_node { png_alloc_node_t *png_alloc_head = NULL; png_alloc_node_t *png_alloc_tail = NULL; -png_alloc_node_t *png_alloc_find_node(void *addr) +static png_alloc_node_t *png_alloc_find_node(void *addr) { png_alloc_node_t *node; for (node = png_alloc_head; node; node = node->next) @@ -41,7 +41,7 @@ png_alloc_node_t *png_alloc_find_node(void *addr) return node; } -void png_alloc_add_node(void *addr, size_t size) +static void png_alloc_add_node(void *addr, size_t size) { png_alloc_node_t *node; if (png_alloc_find_node(addr)) @@ -58,7 +58,7 @@ void png_alloc_add_node(void *addr, size_t size) png_alloc_head = node; } -void png_alloc_remove_node(png_alloc_node_t *node) +static void png_alloc_remove_node(png_alloc_node_t *node) { if (node->prev) node->prev->next = node->next; @@ -72,14 +72,14 @@ void png_alloc_remove_node(png_alloc_node_t *node) free(node); } -void *png_alloc_malloc(size_t size) +static void *png_alloc_malloc(size_t size) { void *addr = malloc(size); png_alloc_add_node(addr, size); return addr; } -void *png_alloc_realloc(void *addr, size_t size) +static void *png_alloc_realloc(void *addr, size_t size) { void *new_addr; if (!addr) @@ -94,7 +94,7 @@ void *png_alloc_realloc(void *addr, size_t size) return new_addr; } -void png_alloc_free(void *addr) +static void png_alloc_free(void *addr) { png_alloc_node_t *node = png_alloc_find_node(addr); if (!node) @@ -114,7 +114,7 @@ void png_alloc_free_all() /*************************************************************************************************/ -__maybe_unused void vector32_cleanup(vector32_t *p) +__maybe_unused static void vector32_cleanup(vector32_t *p) { p->size = p->allocsize = 0; if (p->data) @@ -122,7 +122,7 @@ __maybe_unused void vector32_cleanup(vector32_t *p) p->data = NULL; } -uint32_t vector32_resize(vector32_t *p, size_t size) +static uint32_t vector32_resize(vector32_t *p, size_t size) { // returns 1 if success, 0 if failure ==> nothing done if (size * sizeof (uint32_t) > p->allocsize) { size_t newsize = size * sizeof (uint32_t) * 2; @@ -138,7 +138,7 @@ uint32_t vector32_resize(vector32_t *p, size_t size) return 1; } -uint32_t vector32_resizev(vector32_t *p, size_t size, uint32_t value) +static uint32_t vector32_resizev(vector32_t *p, size_t size, uint32_t value) { // resize and give all new elements the value size_t oldsize = p->size, i; if (!vector32_resize(p, size)) @@ -148,13 +148,13 @@ uint32_t vector32_resizev(vector32_t *p, size_t size, uint32_t value) return 1; } -void vector32_init(vector32_t *p) +static void vector32_init(vector32_t *p) { p->data = NULL; p->size = p->allocsize = 0; } -vector32_t *vector32_new(size_t size, uint32_t value) +__maybe_unused static vector32_t *vector32_new(size_t size, uint32_t value) { vector32_t *p = png_alloc_malloc(sizeof (vector32_t)); vector32_init(p); @@ -165,7 +165,7 @@ vector32_t *vector32_new(size_t size, uint32_t value) /*************************************************************************************************/ -__maybe_unused void vector8_cleanup(vector8_t *p) +__maybe_unused static void vector8_cleanup(vector8_t *p) { p->size = p->allocsize = 0; if (p->data) @@ -173,7 +173,7 @@ __maybe_unused void vector8_cleanup(vector8_t *p) p->data = NULL; } -uint32_t vector8_resize(vector8_t *p, size_t size) +static uint32_t vector8_resize(vector8_t *p, size_t size) { // returns 1 if success, 0 if failure ==> nothing done // xxx: the use of sizeof uint32_t here seems like a bug (this descends from the lodepng vector // compatibility functions which do the same). without this there is corruption in certain cases, @@ -192,7 +192,7 @@ uint32_t vector8_resize(vector8_t *p, size_t size) return 1; } -uint32_t vector8_resizev(vector8_t *p, size_t size, uint8_t value) +static uint32_t vector8_resizev(vector8_t *p, size_t size, uint8_t value) { // resize and give all new elements the value size_t oldsize = p->size, i; if (!vector8_resize(p, size)) @@ -202,13 +202,13 @@ uint32_t vector8_resizev(vector8_t *p, size_t size, uint8_t value) return 1; } -void vector8_init(vector8_t *p) +static void vector8_init(vector8_t *p) { p->data = NULL; p->size = p->allocsize = 0; } -vector8_t *vector8_new(size_t size, uint8_t value) +static vector8_t *vector8_new(size_t size, uint8_t value) { vector8_t *p = png_alloc_malloc(sizeof (vector8_t)); vector8_init(p); @@ -217,7 +217,7 @@ vector8_t *vector8_new(size_t size, uint8_t value) return p; } -vector8_t *vector8_copy(vector8_t *p) +static vector8_t *vector8_copy(vector8_t *p) { vector8_t *q = vector8_new(p->size, 0); uint32_t n; @@ -227,7 +227,7 @@ vector8_t *vector8_copy(vector8_t *p) } /*************************************************************************************************/ -int Zlib_decompress(vector8_t *out, const vector8_t *in) // returns error value +static int Zlib_decompress(vector8_t *out, const vector8_t *in) // returns error value { return picopng_zlib_decompress(out->data, out->size, in->data, in->size); } @@ -244,14 +244,14 @@ int Zlib_decompress(vector8_t *out, const vector8_t *in) // returns error value int PNG_error; -uint32_t PNG_readBitFromReversedStream(size_t *bitp, const uint8_t *bits) +static uint32_t PNG_readBitFromReversedStream(size_t *bitp, const uint8_t *bits) { uint32_t result = (bits[*bitp >> 3] >> (7 - (*bitp & 0x7))) & 1; (*bitp)++; return result; } -uint32_t PNG_readBitsFromReversedStream(size_t *bitp, const uint8_t *bits, uint32_t nbits) +static uint32_t PNG_readBitsFromReversedStream(size_t *bitp, const uint8_t *bits, uint32_t nbits) { uint32_t i, result = 0; for (i = nbits - 1; i < nbits; i--) @@ -259,18 +259,18 @@ uint32_t PNG_readBitsFromReversedStream(size_t *bitp, const uint8_t *bits, uint3 return result; } -void PNG_setBitOfReversedStream(size_t *bitp, uint8_t *bits, uint32_t bit) +static void PNG_setBitOfReversedStream(size_t *bitp, uint8_t *bits, uint32_t bit) { bits[*bitp >> 3] |= (bit << (7 - (*bitp & 0x7))); (*bitp)++; } -uint32_t PNG_read32bitInt(const uint8_t *buffer) +static uint32_t PNG_read32bitInt(const uint8_t *buffer) { return (buffer[0] << 24) | (buffer[1] << 16) | (buffer[2] << 8) | buffer[3]; } -int PNG_checkColorValidity(uint32_t colorType, uint32_t bd) // return type is a LodePNG error code +static int PNG_checkColorValidity(uint32_t colorType, uint32_t bd) // return type is a LodePNG error code { if ((colorType == 2 || colorType == 4 || colorType == 6)) { if (!(bd == 8 || bd == 16)) @@ -291,7 +291,7 @@ int PNG_checkColorValidity(uint32_t colorType, uint32_t bd) // return type is a return 31; // nonexistent color type } -uint32_t PNG_getBpp(const PNG_info_t *info) +static uint32_t PNG_getBpp(const PNG_info_t *info) { uint32_t bitDepth, colorType; bitDepth = info->bitDepth; @@ -304,7 +304,7 @@ uint32_t PNG_getBpp(const PNG_info_t *info) return bitDepth; } -void PNG_readPngHeader(PNG_info_t *info, const uint8_t *in, size_t inlength) +static void PNG_readPngHeader(PNG_info_t *info, const uint8_t *in, size_t inlength) { // read the information from the header and store it in the Info if (inlength < 29) { PNG_error = 27; // error: the data length is smaller than the length of the header @@ -340,7 +340,7 @@ void PNG_readPngHeader(PNG_info_t *info, const uint8_t *in, size_t inlength) PNG_error = PNG_checkColorValidity(info->colorType, info->bitDepth); } -int PNG_paethPredictor(int a, int b, int c) // Paeth predicter, used by PNG filter type 4 +static int PNG_paethPredictor(int a, int b, int c) // Paeth predicter, used by PNG filter type 4 { int p, pa, pb, pc; p = a + b - c; @@ -350,7 +350,7 @@ int PNG_paethPredictor(int a, int b, int c) // Paeth predicter, used by PNG filt return (pa <= pb && pa <= pc) ? a : (pb <= pc ? b : c); } -void PNG_unFilterScanline(uint8_t *recon, const uint8_t *scanline, const uint8_t *precon, +static void PNG_unFilterScanline(uint8_t *recon, const uint8_t *scanline, const uint8_t *precon, size_t bytewidth, uint32_t filterType, size_t length) { size_t i; @@ -406,7 +406,7 @@ void PNG_unFilterScanline(uint8_t *recon, const uint8_t *scanline, const uint8_t } } -void PNG_adam7Pass(uint8_t *out, uint8_t *linen, uint8_t *lineo, const uint8_t *in, uint32_t w, +static void PNG_adam7Pass(uint8_t *out, uint8_t *linen, uint8_t *lineo, const uint8_t *in, uint32_t w, size_t passleft, size_t passtop, size_t spacex, size_t spacey, size_t passw, size_t passh, uint32_t bpp) { @@ -446,7 +446,7 @@ void PNG_adam7Pass(uint8_t *out, uint8_t *linen, uint8_t *lineo, const uint8_t * } } -int PNG_convert(const PNG_info_t *info, vector8_t *out, const uint8_t *in) +static int PNG_convert(const PNG_info_t *info, vector8_t *out, const uint8_t *in) { // converts from any color type to 32-bit. return value = LodePNG error code size_t i, c; uint32_t bitDepth, colorType; @@ -530,7 +530,7 @@ int PNG_convert(const PNG_info_t *info, vector8_t *out, const uint8_t *in) return 0; } -PNG_info_t *PNG_info_new(void) +static PNG_info_t *PNG_info_new(void) { PNG_info_t *info = png_alloc_malloc(sizeof (PNG_info_t)); uint32_t i; diff --git a/lib/parameter.c b/lib/parameter.c index fdbb2e71d1..22695634e5 100644 --- a/lib/parameter.c +++ b/lib/parameter.c @@ -588,6 +588,28 @@ struct param_d *dev_add_param_enum(struct device_d *dev, const char *name, return &pe->param; } +static const char *const tristate_names[] = { + [PARAM_TRISTATE_UNKNOWN] = "unknown", + [PARAM_TRISTATE_TRUE] = "1", + [PARAM_TRISTATE_FALSE] = "0", +}; + +struct param_d *dev_add_param_tristate(struct device_d *dev, const char *name, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, void *priv) +{ + return dev_add_param_enum(dev, name, set, get, value, tristate_names, + ARRAY_SIZE(tristate_names), priv); +} + +struct param_d *dev_add_param_tristate_ro(struct device_d *dev, const char *name, + int *value) +{ + return dev_add_param_enum_ro(dev, name, value, tristate_names, + ARRAY_SIZE(tristate_names)); +} + struct param_bitmask { struct param_d param; unsigned long *value; diff --git a/lib/zstd/decompress.c b/lib/zstd/decompress.c index 8203b815ca..19bf712881 100644 --- a/lib/zstd/decompress.c +++ b/lib/zstd/decompress.c @@ -123,7 +123,7 @@ size_t ZSTD_decompressBegin(ZSTD_DCtx *dctx) return 0; } -ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem) +static ZSTD_DCtx *ZSTD_createDCtx_advanced(ZSTD_customMem customMem) { ZSTD_DCtx *dctx; @@ -391,7 +391,7 @@ typedef struct { /*! ZSTD_getcBlockSize() : * Provides the size of compressed block from block header `src` */ -size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr) +static size_t ZSTD_getcBlockSize(const void *src, size_t srcSize, blockProperties_t *bpPtr) { if (srcSize < ZSTD_blockHeaderSize) return ERROR(srcSize_wrong); @@ -429,7 +429,7 @@ static size_t ZSTD_setRleBlock(void *dst, size_t dstCapacity, const void *src, s /*! ZSTD_decodeLiteralsBlock() : @return : nb of bytes read from src (< srcSize ) */ -size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ +static size_t ZSTD_decodeLiteralsBlock(ZSTD_DCtx *dctx, const void *src, size_t srcSize) /* note : srcSize < BLOCKSIZE */ { if (srcSize < MIN_CBLOCK_SIZE) return ERROR(corruption_detected); @@ -791,7 +791,7 @@ static size_t ZSTD_buildSeqTable(FSE_DTable *DTableSpace, const FSE_DTable **DTa } } -size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, const void *src, size_t srcSize) +static size_t ZSTD_decodeSeqHeaders(ZSTD_DCtx *dctx, int *nbSeqPtr, const void *src, size_t srcSize) { const BYTE *const istart = (const BYTE *const)src; const BYTE *const iend = istart + srcSize; @@ -1494,7 +1494,7 @@ size_t ZSTD_insertBlock(ZSTD_DCtx *dctx, const void *blockStart, size_t blockSiz return blockSize; } -size_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length) +static size_t ZSTD_generateNxBytes(void *dst, size_t dstCapacity, BYTE byte, size_t length) { if (length > dstCapacity) return ERROR(dstSize_tooSmall); diff --git a/scripts/canon-a1100-image b/scripts/canon-a1100-image index 6c08d7493a..17fd47373e 100755 --- a/scripts/canon-a1100-image +++ b/scripts/canon-a1100-image @@ -1,4 +1,6 @@ -#!/bin/bash -e +#!/usr/bin/env bash + +set -e IFILE=$1 OFILE=$2 diff --git a/scripts/check_size b/scripts/check_size index 8530435d3a..76608eccce 100755 --- a/scripts/check_size +++ b/scripts/check_size @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash symbol="$1" file="$2" diff --git a/scripts/dfuboot.sh b/scripts/dfuboot.sh index 524113b613..9847579ced 100755 --- a/scripts/dfuboot.sh +++ b/scripts/dfuboot.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash DEVICETREE= KERNEL= diff --git a/scripts/extract_symbol_offset b/scripts/extract_symbol_offset index 78b866830e..d0ea22434a 100755 --- a/scripts/extract_symbol_offset +++ b/scripts/extract_symbol_offset @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash symbol="$1" file="$2" diff --git a/scripts/gen-dtb-s b/scripts/gen-dtb-s index b2dd253c27..0649247f93 100755 --- a/scripts/gen-dtb-s +++ b/scripts/gen-dtb-s @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash name=$1 dtb=$2 diff --git a/scripts/genenv b/scripts/genenv index 5ebe699632..454f2327b2 100755 --- a/scripts/genenv +++ b/scripts/genenv @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Generate the default environment file from a list of directories # usage: genenv <basedir> <objdir> <target> <dir>... diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c index b3e8d62ba8..b8d939a431 100644 --- a/scripts/imx/imx.c +++ b/scripts/imx/imx.c @@ -673,13 +673,16 @@ static char *readcmd(struct config_data *data, FILE *f) } } -int parse_config(struct config_data *data, const char *filename) +int parse_config(struct config_data *data, const char *_filename) { FILE *f; int lineno = 0; char *line = NULL, *tmp; char *argv[MAXARGS]; int nargs, i, ret = 0; + char *filename; + + filename = strdup(_filename); f = fopen(filename, "r"); if (!f) { @@ -695,8 +698,17 @@ int parse_config(struct config_data *data, const char *filename) lineno++; tmp = strchr(line, '#'); - if (tmp) - *tmp = 0; + if (tmp) { + char *endptr; + long linenum = strtol(tmp + 1, &endptr, 10); + if (strncmp(endptr, " \"", 2) == 0 && endptr[2]) { + free(filename); + lineno = linenum - 1; + filename = strdup(endptr + 2); + filename[strlen(filename) - 1] = '\0'; + } + *tmp = '\0'; + } nargs = parse_line(line, argv); if (!nargs) @@ -708,8 +720,8 @@ int parse_config(struct config_data *data, const char *filename) if (!strcmp(cmds[i].name, argv[0])) { ret = cmds[i].parse(data, nargs, argv); if (ret) { - fprintf(stderr, "error in line %d: %s\n", - lineno, strerror(-ret)); + fprintf(stderr, "%s:%d: %s\n", + filename, lineno, strerror(-ret)); goto cleanup; } break; @@ -724,5 +736,6 @@ int parse_config(struct config_data *data, const char *filename) cleanup: fclose(f); + free(filename); return ret; } diff --git a/scripts/socfpga_get_sequencer b/scripts/socfpga_get_sequencer index 36f67498bc..5405bfa6ba 100755 --- a/scripts/socfpga_get_sequencer +++ b/scripts/socfpga_get_sequencer @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if [ "$#" -lt "2" ] then diff --git a/scripts/socfpga_import_preloader b/scripts/socfpga_import_preloader index 6c748fadb8..23e3c380db 100755 --- a/scripts/socfpga_import_preloader +++ b/scripts/socfpga_import_preloader @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash if [ "$#" -lt "2" ] then diff --git a/scripts/socfpga_xml_to_config.sh b/scripts/socfpga_xml_to_config.sh index 7e22ebb9e8..3bb0dd283b 100755 --- a/scripts/socfpga_xml_to_config.sh +++ b/scripts/socfpga_xml_to_config.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash ## TODO: ## - read in mpuclk and nocclk, must be calculated by hand at the moment |