From a84cea06bb8fff69810a890ac0e4b47ea5726512 Mon Sep 17 00:00:00 2001 From: Tom Rini Date: Wed, 27 Oct 2021 18:54:53 +0200 Subject: Revert "arm64: Layerscape: Survive LPI one-way reset workaround" Ad-hoc bindings that are not part of the upstream device tree / bindings are not allowed in-tree. Only bindings that are in-progress with upstream and then re-synced once agreed upon are. This reverts commit af288cb291da3abef6be0875527729296f7de7a0. Cc: Hou Zhiqiang Cc: Priyanka Jain Reported-by: Michael Walle Signed-off-by: Tom Rini Acked-by: Marc Zyngier --- arch/arm/cpu/armv8/fsl-layerscape/soc.c | 18 +----------------- arch/arm/dts/fsl-ls1028a.dtsi | 6 ------ arch/arm/dts/fsl-ls1088a.dtsi | 6 ------ arch/arm/dts/fsl-ls2080a.dtsi | 6 ------ arch/arm/dts/fsl-lx2160a.dtsi | 6 ------ 5 files changed, 1 insertion(+), 41 deletions(-) diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index 9820d3290e7..c0e100d21c2 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -43,23 +43,7 @@ DECLARE_GLOBAL_DATA_PTR; #ifdef CONFIG_GIC_V3_ITS int ls_gic_rd_tables_init(void *blob) { - struct fdt_memory lpi_base; - fdt_addr_t addr; - fdt_size_t size; - int offset, ret; - - offset = fdt_path_offset(gd->fdt_blob, "/syscon@0x80000000"); - addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, offset, "reg", - 0, &size, false); - - lpi_base.start = addr; - lpi_base.end = addr + size - 1; - ret = fdtdec_add_reserved_memory(blob, "lpi_rd_table", &lpi_base, NULL, - 0, NULL, 0); - if (ret) { - debug("%s: failed to add reserved memory\n", __func__); - return ret; - } + int ret; ret = gic_lpi_tables_init(); if (ret) diff --git a/arch/arm/dts/fsl-ls1028a.dtsi b/arch/arm/dts/fsl-ls1028a.dtsi index 50f9b527cde..53b052ed327 100644 --- a/arch/arm/dts/fsl-ls1028a.dtsi +++ b/arch/arm/dts/fsl-ls1028a.dtsi @@ -44,12 +44,6 @@ IRQ_TYPE_LEVEL_LOW)>; }; - gic_lpi_base: syscon@0x80000000 { - compatible = "gic-lpi-base"; - reg = <0x0 0x80000000 0x0 0x100000>; - max-gic-redistributors = <2>; - }; - timer { compatible = "arm,armv8-timer"; interrupts = ; }; - gic_lpi_base: syscon@0x80000000 { - compatible = "gic-lpi-base"; - reg = <0x0 0x80000000 0x0 0x100000>; - max-gic-redistributors = <8>; - }; - timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */ diff --git a/arch/arm/dts/fsl-ls2080a.dtsi b/arch/arm/dts/fsl-ls2080a.dtsi index 7374d580e07..278daeeb6ee 100644 --- a/arch/arm/dts/fsl-ls2080a.dtsi +++ b/arch/arm/dts/fsl-ls2080a.dtsi @@ -27,12 +27,6 @@ interrupts = <1 9 0x4>; }; - gic_lpi_base: syscon@0x80000000 { - compatible = "gic-lpi-base"; - reg = <0x0 0x80000000 0x0 0x100000>; - max-gic-redistributors = <8>; - }; - timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */ diff --git a/arch/arm/dts/fsl-lx2160a.dtsi b/arch/arm/dts/fsl-lx2160a.dtsi index a6f0e9bc56b..3b5f0d119e7 100644 --- a/arch/arm/dts/fsl-lx2160a.dtsi +++ b/arch/arm/dts/fsl-lx2160a.dtsi @@ -43,12 +43,6 @@ interrupts = <1 9 0x4>; }; - gic_lpi_base: syscon@0x80000000 { - compatible = "gic-lpi-base"; - reg = <0x0 0x80000000 0x0 0x200000>; - max-gic-redistributors = <16>; - }; - timer { compatible = "arm,armv8-timer"; interrupts = <1 13 0x8>, /* Physical Secure PPI, active-low */ -- cgit v1.2.3 From 60b9b47d295b9f197d1dee2f893a8c49fcbee10e Mon Sep 17 00:00:00 2001 From: Michael Walle Date: Wed, 27 Oct 2021 18:54:54 +0200 Subject: Revert "arch: arm: use dt and UCLASS_SYSCON to get gic lpi details" Stop using the device tree as a source for ad-hoc information. This reverts commit 2ae7adc659f7fca9ea65df4318e5bca2b8274310. Signed-off-by: Michael Walle [trini: Also make board/broadcom/bcmns3/ns3.c fail clearly now] Signed-off-by: Tom Rini --- arch/arm/Kconfig | 2 - arch/arm/cpu/armv8/fsl-layerscape/soc.c | 27 +++++++++++++- arch/arm/include/asm/gic-v3.h | 4 +- arch/arm/lib/gic-v3-its.c | 66 ++++----------------------------- board/broadcom/bcmns3/ns3.c | 3 +- 5 files changed, 38 insertions(+), 64 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 02f8306f15a..86c1ebde05c 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -82,8 +82,6 @@ config GICV3 config GIC_V3_ITS bool "ARM GICV3 ITS" - select REGMAP - select SYSCON select IRQ help ARM GICV3 Interrupt translation service (ITS). diff --git a/arch/arm/cpu/armv8/fsl-layerscape/soc.c b/arch/arm/cpu/armv8/fsl-layerscape/soc.c index c0e100d21c2..a08ed3f5440 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/soc.c +++ b/arch/arm/cpu/armv8/fsl-layerscape/soc.c @@ -41,11 +41,36 @@ DECLARE_GLOBAL_DATA_PTR; #endif #ifdef CONFIG_GIC_V3_ITS +#define PENDTABLE_MAX_SZ ALIGN(BIT(ITS_MAX_LPI_NRBITS), SZ_64K) +#define PROPTABLE_MAX_SZ ALIGN(BIT(ITS_MAX_LPI_NRBITS) / 8, SZ_64K) +#define GIC_LPI_SIZE ALIGN(cpu_numcores() * PENDTABLE_MAX_SZ + \ + PROPTABLE_MAX_SZ, SZ_1M) +static int fdt_add_resv_mem_gic_rd_tables(void *blob, u64 base, size_t size) +{ + int err; + struct fdt_memory gic_rd_tables; + + gic_rd_tables.start = base; + gic_rd_tables.end = base + size - 1; + err = fdtdec_add_reserved_memory(blob, "gic-rd-tables", &gic_rd_tables, + NULL, 0, NULL, 0); + if (err < 0) + debug("%s: failed to add reserved memory: %d\n", __func__, err); + + return err; +} + int ls_gic_rd_tables_init(void *blob) { + u64 gic_lpi_base; int ret; - ret = gic_lpi_tables_init(); + gic_lpi_base = ALIGN(gd->arch.resv_ram - GIC_LPI_SIZE, SZ_64K); + ret = fdt_add_resv_mem_gic_rd_tables(blob, gic_lpi_base, GIC_LPI_SIZE); + if (ret) + return ret; + + ret = gic_lpi_tables_init(gic_lpi_base, cpu_numcores()); if (ret) debug("%s: failed to init gic-lpi-tables\n", __func__); diff --git a/arch/arm/include/asm/gic-v3.h b/arch/arm/include/asm/gic-v3.h index 35efec78c3e..5131fabec45 100644 --- a/arch/arm/include/asm/gic-v3.h +++ b/arch/arm/include/asm/gic-v3.h @@ -127,9 +127,9 @@ #define GIC_REDISTRIBUTOR_OFFSET 0x20000 #ifdef CONFIG_GIC_V3_ITS -int gic_lpi_tables_init(void); +int gic_lpi_tables_init(u64 base, u32 max_redist); #else -int gic_lpi_tables_init(void) +int gic_lpi_tables_init(u64 base, u32 max_redist) { return 0; } diff --git a/arch/arm/lib/gic-v3-its.c b/arch/arm/lib/gic-v3-its.c index 2d3fdb600eb..f6211a2d92c 100644 --- a/arch/arm/lib/gic-v3-its.c +++ b/arch/arm/lib/gic-v3-its.c @@ -5,8 +5,6 @@ #include #include #include -#include -#include #include #include #include @@ -19,22 +17,15 @@ static u32 lpi_id_bits; #define LPI_PROPBASE_SZ ALIGN(BIT(LPI_NRBITS), SZ_64K) #define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K) -/* Number of GIC re-distributors */ -#define MAX_GIC_REDISTRIBUTORS 8 - /* * gic_v3_its_priv - gic details * * @gicd_base: gicd base address * @gicr_base: gicr base address - * @lpi_base: gic lpi base address - * @num_redist: number of gic re-distributors */ struct gic_v3_its_priv { ulong gicd_base; ulong gicr_base; - ulong lpi_base; - u32 num_redist; }; static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv) @@ -68,39 +59,13 @@ static int gic_v3_its_get_gic_addr(struct gic_v3_its_priv *priv) return 0; } -static int gic_v3_its_get_gic_lpi_addr(struct gic_v3_its_priv *priv) -{ - struct regmap *regmap; - struct udevice *dev; - int ret; - - ret = uclass_get_device_by_driver(UCLASS_SYSCON, - DM_DRIVER_GET(gic_lpi_syscon), &dev); - if (ret) { - pr_err("%s: failed to get %s syscon device\n", __func__, - DM_DRIVER_GET(gic_lpi_syscon)->name); - return ret; - } - - regmap = syscon_get_regmap(dev); - if (!regmap) { - pr_err("%s: failed to regmap for %s syscon device\n", __func__, - DM_DRIVER_GET(gic_lpi_syscon)->name); - return -ENODEV; - } - priv->lpi_base = regmap->ranges[0].start; - - priv->num_redist = dev_read_u32_default(dev, "max-gic-redistributors", - MAX_GIC_REDISTRIBUTORS); - - return 0; -} - /* * Program the GIC LPI configuration tables for all * the re-distributors and enable the LPI table + * base: Configuration table address + * num_redist: number of redistributors */ -int gic_lpi_tables_init(void) +int gic_lpi_tables_init(u64 base, u32 num_redist) { struct gic_v3_its_priv priv; u32 gicd_typer; @@ -109,15 +74,12 @@ int gic_lpi_tables_init(void) int i; u64 redist_lpi_base; u64 pend_base; - ulong pend_tab_total_sz; + ulong pend_tab_total_sz = num_redist * LPI_PENDBASE_SZ; void *pend_tab_va; if (gic_v3_its_get_gic_addr(&priv)) return -EINVAL; - if (gic_v3_its_get_gic_lpi_addr(&priv)) - return -EINVAL; - gicd_typer = readl((uintptr_t)(priv.gicd_base + GICD_TYPER)); /* GIC support for Locality specific peripheral interrupts (LPI's) */ if (!(gicd_typer & GICD_TYPER_LPIS)) { @@ -130,7 +92,7 @@ int gic_lpi_tables_init(void) * Once the LPI table is enabled, can not program the * LPI configuration tables again, unless the GIC is reset. */ - for (i = 0; i < priv.num_redist; i++) { + for (i = 0; i < num_redist; i++) { u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; if ((readl((uintptr_t)(priv.gicr_base + offset))) & @@ -146,7 +108,7 @@ int gic_lpi_tables_init(void) ITS_MAX_LPI_NRBITS); /* Set PropBase */ - val = (priv.lpi_base | + val = (base | GICR_PROPBASER_INNERSHAREABLE | GICR_PROPBASER_RAWAWB | ((LPI_NRBITS - 1) & GICR_PROPBASER_IDBITS_MASK)); @@ -163,8 +125,7 @@ int gic_lpi_tables_init(void) } } - redist_lpi_base = priv.lpi_base + LPI_PROPBASE_SZ; - pend_tab_total_sz = priv.num_redist * LPI_PENDBASE_SZ; + redist_lpi_base = base + LPI_PROPBASE_SZ; pend_tab_va = map_physmem(redist_lpi_base, pend_tab_total_sz, MAP_NOCACHE); memset(pend_tab_va, 0, pend_tab_total_sz); @@ -172,7 +133,7 @@ int gic_lpi_tables_init(void) unmap_physmem(pend_tab_va, MAP_NOCACHE); pend_base = priv.gicr_base + GICR_PENDBASER; - for (i = 0; i < priv.num_redist; i++) { + for (i = 0; i < num_redist; i++) { u32 offset = i * GIC_REDISTRIBUTOR_OFFSET; val = ((redist_lpi_base + (i * LPI_PENDBASE_SZ)) | @@ -207,14 +168,3 @@ U_BOOT_DRIVER(arm_gic_v3_its) = { .id = UCLASS_IRQ, .of_match = gic_v3_its_ids, }; - -static const struct udevice_id gic_lpi_syscon_ids[] = { - { .compatible = "gic-lpi-base" }, - {} -}; - -U_BOOT_DRIVER(gic_lpi_syscon) = { - .name = "gic-lpi-base", - .id = UCLASS_SYSCON, - .of_match = gic_lpi_syscon_ids, -}; diff --git a/board/broadcom/bcmns3/ns3.c b/board/broadcom/bcmns3/ns3.c index 758a358f542..32acf367842 100644 --- a/board/broadcom/bcmns3/ns3.c +++ b/board/broadcom/bcmns3/ns3.c @@ -196,7 +196,8 @@ int ft_board_setup(void *fdt, struct bd_info *bd) { u32 chimp_hs = CHIMP_HANDSHAKE_WAIT_TIMEOUT; - gic_lpi_tables_init(); + /* FIXME: Need to call gic_lpi_tables_init correctly now */ + printf("%s: failed to init gic-lpi-tables\n", __func__); /* * Check for chimp handshake status. -- cgit v1.2.3 From d73db3042734f8077a5866d9d60d2eeda685b2ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Fri, 29 Oct 2021 14:09:48 +0200 Subject: arm: mvebu: Fix booting from SATA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use proper SATA macro for boot_device switch in spl_boot_device() function. Signed-off-by: Pali Rohár Fixes: 2226ca173486 ("arm: mvebu: Load U-Boot proper binary in SPL code based on kwbimage header") --- arch/arm/mach-mvebu/spl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-mvebu/spl.c b/arch/arm/mach-mvebu/spl.c index cad3f0a4889..73c4b9af3e6 100644 --- a/arch/arm/mach-mvebu/spl.c +++ b/arch/arm/mach-mvebu/spl.c @@ -199,8 +199,8 @@ u32 spl_boot_device(void) return BOOT_DEVICE_MMC1; #endif #ifdef CONFIG_SPL_SATA - case BOOT_FROM_SATA: - return BOOT_FROM_SATA; + case BOOT_DEVICE_SATA: + return BOOT_DEVICE_SATA; #endif #ifdef CONFIG_SPL_SPI_FLASH_SUPPORT case BOOT_DEVICE_SPI: -- cgit v1.2.3 From 40dbf03d7d2dd2b5516f797069e3ea830db6fecc Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:01 +0200 Subject: iommu: Add IOMMU uclass This uclass is intended to manage IOMMUs on systems where the IOMMUs are not in bypass mode by default. In that case U-Boot cannot ignore the IOMMUs if it wants to use devices that need to do DMA and sit behind such an IOMMU. This initial IOMMU uclass implementation does not implement and device ops and is intended for IOMMUs that have a bypass mode that does not require address translation. Support for IOMMUs that do require address translation is planned and device ops will be defined when support for such IOMMUs will be added. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- doc/device-tree-bindings/iommu/iommu.txt | 206 +++++++++++++++++++++++++++++++ drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/core/device.c | 8 ++ drivers/iommu/Kconfig | 17 +++ drivers/iommu/Makefile | 3 + drivers/iommu/iommu-uclass.c | 45 +++++++ include/dm/uclass-id.h | 1 + include/iommu.h | 16 +++ 9 files changed, 299 insertions(+) create mode 100644 doc/device-tree-bindings/iommu/iommu.txt create mode 100644 drivers/iommu/Kconfig create mode 100644 drivers/iommu/Makefile create mode 100644 drivers/iommu/iommu-uclass.c create mode 100644 include/iommu.h diff --git a/doc/device-tree-bindings/iommu/iommu.txt b/doc/device-tree-bindings/iommu/iommu.txt new file mode 100644 index 00000000000..26ba9e530f1 --- /dev/null +++ b/doc/device-tree-bindings/iommu/iommu.txt @@ -0,0 +1,206 @@ +This document describes the generic device tree binding for IOMMUs and their +master(s). + + +IOMMU device node: +================== + +An IOMMU can provide the following services: + +* Remap address space to allow devices to access physical memory ranges that + they otherwise wouldn't be capable of accessing. + + Example: 32-bit DMA to 64-bit physical addresses + +* Implement scatter-gather at page level granularity so that the device does + not have to. + +* Provide system protection against "rogue" DMA by forcing all accesses to go + through the IOMMU and faulting when encountering accesses to unmapped + address regions. + +* Provide address space isolation between multiple contexts. + + Example: Virtualization + +Device nodes compatible with this binding represent hardware with some of the +above capabilities. + +IOMMUs can be single-master or multiple-master. Single-master IOMMU devices +typically have a fixed association to the master device, whereas multiple- +master IOMMU devices can translate accesses from more than one master. + +The device tree node of the IOMMU device's parent bus must contain a valid +"dma-ranges" property that describes how the physical address space of the +IOMMU maps to memory. An empty "dma-ranges" property means that there is a +1:1 mapping from IOMMU to memory. + +Required properties: +-------------------- +- #iommu-cells: The number of cells in an IOMMU specifier needed to encode an + address. + +The meaning of the IOMMU specifier is defined by the device tree binding of +the specific IOMMU. Below are a few examples of typical use-cases: + +- #iommu-cells = <0>: Single master IOMMU devices are not configurable and + therefore no additional information needs to be encoded in the specifier. + This may also apply to multiple master IOMMU devices that do not allow the + association of masters to be configured. Note that an IOMMU can by design + be multi-master yet only expose a single master in a given configuration. + In such cases the number of cells will usually be 1 as in the next case. +- #iommu-cells = <1>: Multiple master IOMMU devices may need to be configured + in order to enable translation for a given master. In such cases the single + address cell corresponds to the master device's ID. In some cases more than + one cell can be required to represent a single master ID. +- #iommu-cells = <4>: Some IOMMU devices allow the DMA window for masters to + be configured. The first cell of the address in this may contain the master + device's ID for example, while the second cell could contain the start of + the DMA window for the given device. The length of the DMA window is given + by the third and fourth cells. + +Note that these are merely examples and real-world use-cases may use different +definitions to represent their individual needs. Always refer to the specific +IOMMU binding for the exact meaning of the cells that make up the specifier. + + +IOMMU master node: +================== + +Devices that access memory through an IOMMU are called masters. A device can +have multiple master interfaces (to one or more IOMMU devices). + +Required properties: +-------------------- +- iommus: A list of phandle and IOMMU specifier pairs that describe the IOMMU + master interfaces of the device. One entry in the list describes one master + interface of the device. + +When an "iommus" property is specified in a device tree node, the IOMMU will +be used for address translation. If a "dma-ranges" property exists in the +device's parent node it will be ignored. An exception to this rule is if the +referenced IOMMU is disabled, in which case the "dma-ranges" property of the +parent shall take effect. Note that merely disabling a device tree node does +not guarantee that the IOMMU is really disabled since the hardware may not +have a means to turn off translation. But it is invalid in such cases to +disable the IOMMU's device tree node in the first place because it would +prevent any driver from properly setting up the translations. + +Optional properties: +-------------------- +- pasid-num-bits: Some masters support multiple address spaces for DMA, by + tagging DMA transactions with an address space identifier. By default, + this is 0, which means that the device only has one address space. + +- dma-can-stall: When present, the master can wait for a transaction to + complete for an indefinite amount of time. Upon translation fault some + IOMMUs, instead of aborting the translation immediately, may first + notify the driver and keep the transaction in flight. This allows the OS + to inspect the fault and, for example, make physical pages resident + before updating the mappings and completing the transaction. Such IOMMU + accepts a limited number of simultaneous stalled transactions before + having to either put back-pressure on the master, or abort new faulting + transactions. + + Firmware has to opt-in stalling, because most buses and masters don't + support it. In particular it isn't compatible with PCI, where + transactions have to complete before a time limit. More generally it + won't work in systems and masters that haven't been designed for + stalling. For example the OS, in order to handle a stalled transaction, + may attempt to retrieve pages from secondary storage in a stalled + domain, leading to a deadlock. + + +Notes: +====== + +One possible extension to the above is to use an "iommus" property along with +a "dma-ranges" property in a bus device node (such as PCI host bridges). This +can be useful to describe how children on the bus relate to the IOMMU if they +are not explicitly listed in the device tree (e.g. PCI devices). However, the +requirements of that use-case haven't been fully determined yet. Implementing +this is therefore not recommended without further discussion and extension of +this binding. + + +Examples: +========= + +Single-master IOMMU: +-------------------- + + iommu { + #iommu-cells = <0>; + }; + + master { + iommus = <&{/iommu}>; + }; + +Multiple-master IOMMU with fixed associations: +---------------------------------------------- + + /* multiple-master IOMMU */ + iommu { + /* + * Masters are statically associated with this IOMMU and share + * the same address translations because the IOMMU does not + * have sufficient information to distinguish between masters. + * + * Consequently address translation is always on or off for + * all masters at any given point in time. + */ + #iommu-cells = <0>; + }; + + /* static association with IOMMU */ + master@1 { + reg = <1>; + iommus = <&{/iommu}>; + }; + + /* static association with IOMMU */ + master@2 { + reg = <2>; + iommus = <&{/iommu}>; + }; + +Multiple-master IOMMU: +---------------------- + + iommu { + /* the specifier represents the ID of the master */ + #iommu-cells = <1>; + }; + + master@1 { + /* device has master ID 42 in the IOMMU */ + iommus = <&{/iommu} 42>; + }; + + master@2 { + /* device has master IDs 23 and 24 in the IOMMU */ + iommus = <&{/iommu} 23>, <&{/iommu} 24>; + }; + +Multiple-master IOMMU with configurable DMA window: +--------------------------------------------------- + + / { + iommu { + /* + * One cell for the master ID and one cell for the + * address of the DMA window. The length of the DMA + * window is encoded in two cells. + * + * The DMA window is the range addressable by the + * master (i.e. the I/O virtual address space). + */ + #iommu-cells = <4>; + }; + + master { + /* master ID 42, 4 GiB DMA window starting at 0 */ + iommus = <&{/iommu} 42 0 0x1 0x0>; + }; + }; diff --git a/drivers/Kconfig b/drivers/Kconfig index 417d6f88c29..b26ca8cf70c 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -50,6 +50,8 @@ source "drivers/i2c/Kconfig" source "drivers/input/Kconfig" +source "drivers/iommu/Kconfig" + source "drivers/led/Kconfig" source "drivers/mailbox/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 4cbc40787db..4e7cf284405 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -102,6 +102,7 @@ obj-y += mtd/ obj-y += pwm/ obj-y += reset/ obj-y += input/ +obj-y += iommu/ # SOC specific infrastructure drivers. obj-y += smem/ obj-y += thermal/ diff --git a/drivers/core/device.c b/drivers/core/device.c index d7a778a2413..efd07176e37 100644 --- a/drivers/core/device.c +++ b/drivers/core/device.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -543,6 +544,13 @@ int device_probe(struct udevice *dev) goto fail; } + if (CONFIG_IS_ENABLED(IOMMU) && dev->parent && + (device_get_uclass_id(dev) != UCLASS_IOMMU)) { + ret = dev_iommu_enable(dev); + if (ret) + goto fail; + } + ret = device_get_dma_constraints(dev); if (ret) goto fail; diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig new file mode 100644 index 00000000000..3e35ce8fcc8 --- /dev/null +++ b/drivers/iommu/Kconfig @@ -0,0 +1,17 @@ +# +# IOMMU devices +# + +menu "IOMMU device drivers" + +config IOMMU + bool "Enable Driver Model for IOMMU drivers" + depends on DM + help + Enable driver model for IOMMU devices. An IOMMU maps device + virtiual memory addresses to physical addresses. Devices + that sit behind an IOMMU can typically only access physical + memory if the IOMMU has been programmed to allow access to + that memory. + +endmenu diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile new file mode 100644 index 00000000000..f1ceb101507 --- /dev/null +++ b/drivers/iommu/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-$(CONFIG_IOMMU) += iommu-uclass.o diff --git a/drivers/iommu/iommu-uclass.c b/drivers/iommu/iommu-uclass.c new file mode 100644 index 00000000000..ed917b3c3e8 --- /dev/null +++ b/drivers/iommu/iommu-uclass.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Mark Kettenis + */ + +#define LOG_CATEGORY UCLASS_IOMMU + +#include +#include + +#if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) +int dev_iommu_enable(struct udevice *dev) +{ + struct ofnode_phandle_args args; + struct udevice *dev_iommu; + int i, count, ret = 0; + + count = dev_count_phandle_with_args(dev, "iommus", + "#iommu-cells", 0); + for (i = 0; i < count; i++) { + ret = dev_read_phandle_with_args(dev, "iommus", + "#iommu-cells", 0, i, &args); + if (ret) { + debug("%s: dev_read_phandle_with_args failed: %d\n", + __func__, ret); + return ret; + } + + ret = uclass_get_device_by_ofnode(UCLASS_IOMMU, args.node, + &dev_iommu); + if (ret) { + debug("%s: uclass_get_device_by_ofnode failed: %d\n", + __func__, ret); + return ret; + } + } + + return 0; +} +#endif + +UCLASS_DRIVER(iommu) = { + .id = UCLASS_IOMMU, + .name = "iommu", +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 3768432b680..fd139b9b2a0 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -62,6 +62,7 @@ enum uclass_id { UCLASS_I2C_MUX, /* I2C multiplexer */ UCLASS_I2S, /* I2S bus */ UCLASS_IDE, /* IDE device */ + UCLASS_IOMMU, /* IOMMU */ UCLASS_IRQ, /* Interrupt controller */ UCLASS_KEYBOARD, /* Keyboard input device */ UCLASS_LED, /* Light-emitting diode (LED) */ diff --git a/include/iommu.h b/include/iommu.h new file mode 100644 index 00000000000..6c46adf449e --- /dev/null +++ b/include/iommu.h @@ -0,0 +1,16 @@ +#ifndef _IOMMU_H +#define _IOMMU_H + +struct udevice; + +#if (CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA)) && \ + CONFIG_IS_ENABLED(IOMMU) +int dev_iommu_enable(struct udevice *dev); +#else +static inline int dev_iommu_enable(struct udevice *dev) +{ + return 0; +} +#endif + +#endif -- cgit v1.2.3 From fb5746243707d6b84dea02490a86868c3d7f534d Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:02 +0200 Subject: test: Add tests for IOMMU uclass Add a set of tests for the IOMMU uclass. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- arch/sandbox/dts/test.dts | 6 ++++++ configs/sandbox64_defconfig | 1 + configs/sandbox_defconfig | 1 + configs/sandbox_flattree_defconfig | 1 + configs/sandbox_noinst_defconfig | 1 + configs/sandbox_spl_defconfig | 1 + drivers/iommu/Makefile | 2 ++ drivers/iommu/sandbox_iommu.c | 18 ++++++++++++++++++ test/dm/Makefile | 1 + test/dm/iommu.c | 28 ++++++++++++++++++++++++++++ 10 files changed, 60 insertions(+) create mode 100644 drivers/iommu/sandbox_iommu.c create mode 100644 test/dm/iommu.c diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index e27d106466b..8cd688e8d26 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -764,6 +764,11 @@ vss-microvolts = <0>; }; + iommu: iommu@0 { + compatible = "sandbox,iommu"; + #iommu-cells = <0>; + }; + irq: irq { compatible = "sandbox,irq"; interrupt-controller; @@ -1226,6 +1231,7 @@ usb_1: usb@1 { compatible = "sandbox,usb"; + iommus = <&iommu>; hub { compatible = "usb-hub"; usb,device-class = <9>; diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 838280e1472..45828899f23 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -130,6 +130,7 @@ CONFIG_SPL_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=y CONFIG_CROS_EC_KEYB=y CONFIG_I8042_KEYB=y +CONFIG_IOMMU=y CONFIG_LED=y CONFIG_LED_BLINK=y CONFIG_LED_GPIO=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index d07a7f302e6..93858574f86 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -168,6 +168,7 @@ CONFIG_SPL_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=y CONFIG_CROS_EC_KEYB=y CONFIG_I8042_KEYB=y +CONFIG_IOMMU=y CONFIG_LED=y CONFIG_LED_BLINK=y CONFIG_LED_GPIO=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 5980c8610ea..edfdac8b029 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -107,6 +107,7 @@ CONFIG_SPL_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=y CONFIG_CROS_EC_KEYB=y CONFIG_I8042_KEYB=y +CONFIG_IOMMU=y CONFIG_LED=y CONFIG_LED_BLINK=y CONFIG_LED_GPIO=y diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 238604f5cde..ab378494d29 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -128,6 +128,7 @@ CONFIG_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=y CONFIG_CROS_EC_KEYB=y CONFIG_I8042_KEYB=y +CONFIG_IOMMU=y CONFIG_LED=y CONFIG_LED_BLINK=y CONFIG_LED_GPIO=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index b9da8dc8e97..9a0a678c032 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -130,6 +130,7 @@ CONFIG_I2C_MUX=y CONFIG_I2C_ARB_GPIO_CHALLENGE=y CONFIG_CROS_EC_KEYB=y CONFIG_I8042_KEYB=y +CONFIG_IOMMU=y CONFIG_LED=y CONFIG_LED_BLINK=y CONFIG_LED_GPIO=y diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index f1ceb101507..af1c6bbb7ac 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -1,3 +1,5 @@ # SPDX-License-Identifier: GPL-2.0+ obj-$(CONFIG_IOMMU) += iommu-uclass.o + +obj-$(CONFIG_SANDBOX) += sandbox_iommu.o diff --git a/drivers/iommu/sandbox_iommu.c b/drivers/iommu/sandbox_iommu.c new file mode 100644 index 00000000000..c8161a40aef --- /dev/null +++ b/drivers/iommu/sandbox_iommu.c @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Mark Kettenis + */ + +#include +#include + +static const struct udevice_id sandbox_iommu_ids[] = { + { .compatible = "sandbox,iommu" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sandbox_iommu) = { + .name = "sandbox_iommu", + .id = UCLASS_IOMMU, + .of_match = sandbox_iommu_ids, +}; diff --git a/test/dm/Makefile b/test/dm/Makefile index 55162e9499d..7de013f6368 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_DM_I2C) += i2c.o obj-$(CONFIG_SOUND) += i2s.o obj-y += irq.o obj-$(CONFIG_CLK_K210_SET_RATE) += k210_pll.o +obj-$(CONFIG_IOMMU) += iommu.o obj-$(CONFIG_LED) += led.o obj-$(CONFIG_DM_MAILBOX) += mailbox.o obj-$(CONFIG_DM_MDIO) += mdio.o diff --git a/test/dm/iommu.c b/test/dm/iommu.c new file mode 100644 index 00000000000..94174a7482b --- /dev/null +++ b/test/dm/iommu.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Mark Kettenis + */ + +#include +#include +#include +#include +#include +#include +#include + +static int dm_test_iommu(struct unit_test_state *uts) +{ + struct udevice *dev; + + ut_assertok(uclass_find_device(UCLASS_IOMMU, 0, &dev)); + ut_assert(!(dev_get_flags(dev) & DM_FLAG_ACTIVATED)); + + /* Probing USB probes the IOMMU through the "iommus" property */ + ut_assertok(uclass_probe_all(UCLASS_USB)); + ut_assert(dev_get_flags(dev) & DM_FLAG_ACTIVATED); + + return 0; +} + +DM_TEST(dm_test_iommu, UT_TESTF_SCAN_FDT); -- cgit v1.2.3 From 003b657edcdc7ee96b7df277a16480129a5260a7 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:03 +0200 Subject: arm: apple: Add initial support for Apple's M1 SoC Add support for Apple's M1 SoC that is used in "Apple Silicon" Macs. This builds a basic U-Boot that can be used as a payload for the m1n1 boot loader being developed by the Asahi Linux project. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass [trini: Add MAINTAINERS entry] --- MAINTAINERS | 9 ++ arch/arm/Kconfig | 21 +++++ arch/arm/Makefile | 1 + arch/arm/mach-apple/Kconfig | 18 ++++ arch/arm/mach-apple/Makefile | 4 + arch/arm/mach-apple/board.c | 162 ++++++++++++++++++++++++++++++++++++ arch/arm/mach-apple/lowlevel_init.S | 17 ++++ configs/apple_m1_defconfig | 15 ++++ include/configs/apple.h | 36 ++++++++ 9 files changed, 283 insertions(+) create mode 100644 arch/arm/mach-apple/Kconfig create mode 100644 arch/arm/mach-apple/Makefile create mode 100644 arch/arm/mach-apple/board.c create mode 100644 arch/arm/mach-apple/lowlevel_init.S create mode 100644 configs/apple_m1_defconfig create mode 100644 include/configs/apple.h diff --git a/MAINTAINERS b/MAINTAINERS index 5069f188065..4ed72aecee0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -108,6 +108,15 @@ L: uboot-snps-arc@synopsys.com F: doc/device-tree-bindings/mmc/snps,dw-mmc.txt F: drivers/mmc/snps_dw_mmc.c +APPLE M1 SOC SUPPORT +M: Mark Kettenis +S: Maintained +F: arch/arm/include/asm/arch-m1/ +F: arch/arm/mach-apple/ +F: configs/apple_m1_defconfig +F: drivers/iommu/apple_dart.c +F: include/configs/apple.h + ARM M: Tom Rini S: Maintained diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 86c1ebde05c..48188aad018 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -920,6 +920,25 @@ config ARCH_NEXELL select DM select GPIO_EXTRA_HEADER +config ARCH_APPLE + bool "Apple SoCs" + select ARM64 + select BLK + select CMD_USB + select DM + select DM_KEYBOARD + select DM_SERIAL + select DM_USB + select DM_VIDEO + select LINUX_KERNEL_IMAGE_HEADER + select OF_CONTROL + select OF_BOARD + select POSITION_INDEPENDENT + select USB + imply CMD_DM + imply CMD_GPT + imply DISTRO_DEFAULTS + config ARCH_OWL bool "Actions Semi OWL SoCs" select DM @@ -2016,6 +2035,8 @@ config ISW_ENTRY_ADDR image headers. endif +source "arch/arm/mach-apple/Kconfig" + source "arch/arm/mach-aspeed/Kconfig" source "arch/arm/mach-at91/Kconfig" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 6c9a00c5a48..ad757e982e3 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -55,6 +55,7 @@ PLATFORM_CPPFLAGS += $(arch-y) $(tune-y) # Machine directory name. This list is sorted alphanumerically # by CONFIG_* macro name. +machine-$(CONFIG_ARCH_APPLE) += apple machine-$(CONFIG_ARCH_ASPEED) += aspeed machine-$(CONFIG_ARCH_AT91) += at91 machine-$(CONFIG_ARCH_BCM283X) += bcm283x diff --git a/arch/arm/mach-apple/Kconfig b/arch/arm/mach-apple/Kconfig new file mode 100644 index 00000000000..66cab91b2a3 --- /dev/null +++ b/arch/arm/mach-apple/Kconfig @@ -0,0 +1,18 @@ +if ARCH_APPLE + +config SYS_TEXT_BASE + default 0x00000000 + +config SYS_CONFIG_NAME + default "apple" + +config SYS_SOC + default "m1" + +config SYS_MALLOC_LEN + default 0x4000000 + +config SYS_MALLOC_F_LEN + default 0x4000 + +endif diff --git a/arch/arm/mach-apple/Makefile b/arch/arm/mach-apple/Makefile new file mode 100644 index 00000000000..e74a8c9df10 --- /dev/null +++ b/arch/arm/mach-apple/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0+ + +obj-y += board.o +obj-y += lowlevel_init.o diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c new file mode 100644 index 00000000000..0bfbc473ec1 --- /dev/null +++ b/arch/arm/mach-apple/board.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2021 Mark Kettenis + */ + +#include +#include +#include + +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +static struct mm_region apple_mem_map[] = { + { + /* I/O */ + .virt = 0x200000000, + .phys = 0x200000000, + .size = 8UL * SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x500000000, + .phys = 0x500000000, + .size = 2UL * SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* I/O */ + .virt = 0x680000000, + .phys = 0x680000000, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* PCIE */ + .virt = 0x6a0000000, + .phys = 0x6a0000000, + .size = SZ_512M, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* PCIE */ + .virt = 0x6c0000000, + .phys = 0x6c0000000, + .size = SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRE) | + PTE_BLOCK_INNER_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + /* RAM */ + .virt = 0x800000000, + .phys = 0x800000000, + .size = 8UL * SZ_1G, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* Empty entry for framebuffer */ + 0, + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = apple_mem_map; + +int board_init(void) +{ + return 0; +} + +int dram_init(void) +{ + ofnode node; + int index, ret; + fdt_addr_t base; + fdt_size_t size; + + ret = fdtdec_setup_mem_size_base(); + if (ret) + return ret; + + /* Update RAM mapping */ + index = ARRAY_SIZE(apple_mem_map) - 3; + apple_mem_map[index].virt = gd->ram_base; + apple_mem_map[index].phys = gd->ram_base; + apple_mem_map[index].size = gd->ram_size; + + node = ofnode_path("/chosen/framebuffer"); + if (!ofnode_valid(node)) + return 0; + + base = ofnode_get_addr_size(node, "reg", &size); + if (base == FDT_ADDR_T_NONE) + return 0; + + /* Add framebuffer mapping */ + index = ARRAY_SIZE(apple_mem_map) - 2; + apple_mem_map[index].virt = base; + apple_mem_map[index].phys = base; + apple_mem_map[index].size = size; + apple_mem_map[index].attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) | + PTE_BLOCK_INNER_SHARE | PTE_BLOCK_PXN | PTE_BLOCK_UXN; + + return 0; +} + +int dram_init_banksize(void) +{ + return fdtdec_setup_memory_banksize(); +} + +#define APPLE_WDT_BASE 0x23d2b0000ULL + +#define APPLE_WDT_SYS_CTL_ENABLE BIT(2) + +typedef struct apple_wdt { + u32 reserved0[3]; + u32 chip_ctl; + u32 sys_tmr; + u32 sys_cmp; + u32 reserved1; + u32 sys_ctl; +} apple_wdt_t; + +void reset_cpu(void) +{ + apple_wdt_t *wdt = (apple_wdt_t *)APPLE_WDT_BASE; + + writel(0, &wdt->sys_cmp); + writel(APPLE_WDT_SYS_CTL_ENABLE, &wdt->sys_ctl); + + while(1) + wfi(); +} + +extern long fw_dtb_pointer; + +void *board_fdt_blob_setup(int *err) +{ + /* Return DTB pointer passed by m1n1 */ + *err = 0; + return (void *)fw_dtb_pointer; +} + +ulong board_get_usable_ram_top(ulong total_size) +{ + /* + * Top part of RAM is used by firmware for things like the + * framebuffer. This gives us plenty of room to play with. + */ + return 0x980000000; +} diff --git a/arch/arm/mach-apple/lowlevel_init.S b/arch/arm/mach-apple/lowlevel_init.S new file mode 100644 index 00000000000..e1c0d91cef2 --- /dev/null +++ b/arch/arm/mach-apple/lowlevel_init.S @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2021 Mark Kettenis + */ + +.align 8 +.global fw_dtb_pointer +fw_dtb_pointer: + .quad 0 + +.global save_boot_params +save_boot_params: + /* Stash DTB pointer passed by m1n1 */ + adr x1, fw_dtb_pointer + str x0, [x1] + + b save_boot_params_ret diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig new file mode 100644 index 00000000000..6072e7524c8 --- /dev/null +++ b/configs/apple_m1_defconfig @@ -0,0 +1,15 @@ +CONFIG_ARM=y +CONFIG_ARCH_APPLE=y +# CONFIG_DISPLAY_CPUINFO is not set +# CONFIG_MMC is not set +# CONFIG_NET is not set +CONFIG_VIDEO_SIMPLE=y +CONFIG_DISPLAY_BOARDINFO_LATE=y +CONFIG_USB_XHCI_HCD=y +CONFIG_USB_XHCI_DWC3=y +CONFIG_USB_KEYBOARD=y +CONFIG_USB_STORAGE=y +CONFIG_USE_PREBOOT=y +CONFIG_PREBOOT="usb start" +CONFIG_SYS_LOAD_ADDR=0x880000000 +# CONFIG_GENERATE_SMBIOS_TABLE is not set diff --git a/include/configs/apple.h b/include/configs/apple.h new file mode 100644 index 00000000000..b1f60431746 --- /dev/null +++ b/include/configs/apple.h @@ -0,0 +1,36 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#include + +#define CONFIG_SYS_SDRAM_BASE 0x880000000 + +#define CONFIG_LNX_KRNL_IMG_TEXT_OFFSET_BASE CONFIG_SYS_TEXT_BASE + +/* Environment */ +#define ENV_DEVICE_SETTINGS \ + "stdin=serial,usbkbd\0" \ + "stdout=serial,vidconsole\0" \ + "stderr=serial,vidconsole\0" + +#define ENV_MEM_LAYOUT_SETTINGS \ + "fdt_addr_r=0x960100000\0" \ + "kernel_addr_r=0x960200000\0" + +#if CONFIG_IS_ENABLED(CMD_USB) + #define BOOT_TARGET_USB(func) func(USB, usb, 0) +#else + #define BOOT_TARGET_USB(func) +#endif + +#define BOOT_TARGET_DEVICES(func) \ + BOOT_TARGET_USB(func) + +#include + +#define CONFIG_EXTRA_ENV_SETTINGS \ + ENV_DEVICE_SETTINGS \ + ENV_MEM_LAYOUT_SETTINGS \ + BOOTENV + +#endif -- cgit v1.2.3 From d520e1fb7276d9d14f3cf35e028c5fdb934b049c Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:04 +0200 Subject: serial: s5p: Add Apple M1 support Apple M1 SoCs include an S5L UART which is a variant of the S5P UART. Add support for this variant and enable it by default on Apple SoCs. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- arch/arm/Kconfig | 1 + arch/arm/include/asm/arch-m1/uart.h | 41 ++++++++++++++ configs/apple_m1_defconfig | 4 ++ drivers/serial/Kconfig | 4 +- drivers/serial/serial_s5p.c | 104 ++++++++++++++++++++++++++++-------- 5 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 arch/arm/include/asm/arch-m1/uart.h diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 48188aad018..293e3e39283 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -924,6 +924,7 @@ config ARCH_APPLE bool "Apple SoCs" select ARM64 select BLK + select CLK select CMD_USB select DM select DM_KEYBOARD diff --git a/arch/arm/include/asm/arch-m1/uart.h b/arch/arm/include/asm/arch-m1/uart.h new file mode 100644 index 00000000000..d2a17a221e3 --- /dev/null +++ b/arch/arm/include/asm/arch-m1/uart.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * (C) Copyright 2009 Samsung Electronics + * Minkyu Kang + * Heungjun Kim + */ + +#ifndef __ASM_ARCH_UART_H_ +#define __ASM_ARCH_UART_H_ + +#ifndef __ASSEMBLY__ +/* baudrate rest value */ +union br_rest { + unsigned short slot; /* udivslot */ + unsigned char value; /* ufracval */ +}; + +struct s5p_uart { + unsigned int ulcon; + unsigned int ucon; + unsigned int ufcon; + unsigned int umcon; + unsigned int utrstat; + unsigned int uerstat; + unsigned int ufstat; + unsigned int umstat; + unsigned int utxh; + unsigned int urxh; + unsigned int ubrdiv; + union br_rest rest; + unsigned char res3[0x3fd0]; +}; + +static inline int s5p_uart_divslot(void) +{ + return 0; +} + +#endif /* __ASSEMBLY__ */ + +#endif diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index 6072e7524c8..520d7c7632a 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -13,3 +13,7 @@ CONFIG_USE_PREBOOT=y CONFIG_PREBOOT="usb start" CONFIG_SYS_LOAD_ADDR=0x880000000 # CONFIG_GENERATE_SMBIOS_TABLE is not set +CONFIG_DEBUG_UART=y +CONFIG_DEBUG_UART_ANNOUNCE=y +CONFIG_DEBUG_UART_BASE=0x235200000 +CONFIG_DEBUG_UART_CLOCK=240000 diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 122a39789cb..7ee12901e78 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -290,7 +290,7 @@ config DEBUG_SBI_CONSOLE config DEBUG_UART_S5P bool "Samsung S5P" - depends on ARCH_EXYNOS || ARCH_S5PC1XX + depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX help Select this to enable a debug UART using the serial_s5p driver. You will need to provide parameters to make this work. The driver will @@ -737,7 +737,7 @@ config ROCKCHIP_SERIAL config S5P_SERIAL bool "Support for Samsung S5P UART" - depends on ARCH_EXYNOS || ARCH_S5PC1XX + depends on ARCH_APPLE || ARCH_EXYNOS || ARCH_S5PC1XX default y help Select this to enable Samsung S5P UART support. diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index 6d09952a5dc..53a7b0bd1bd 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -14,24 +14,45 @@ #include #include #include +#if !CONFIG_IS_ENABLED(ARCH_APPLE) #include +#endif #include #include #include DECLARE_GLOBAL_DATA_PTR; -#define RX_FIFO_COUNT_SHIFT 0 -#define RX_FIFO_COUNT_MASK (0xff << RX_FIFO_COUNT_SHIFT) -#define RX_FIFO_FULL (1 << 8) -#define TX_FIFO_COUNT_SHIFT 16 -#define TX_FIFO_COUNT_MASK (0xff << TX_FIFO_COUNT_SHIFT) -#define TX_FIFO_FULL (1 << 24) +enum { + PORT_S5P = 0, + PORT_S5L +}; + +#define S5L_RX_FIFO_COUNT_SHIFT 0 +#define S5L_RX_FIFO_COUNT_MASK (0xf << S5L_RX_FIFO_COUNT_SHIFT) +#define S5L_RX_FIFO_FULL (1 << 8) +#define S5L_TX_FIFO_COUNT_SHIFT 4 +#define S5L_TX_FIFO_COUNT_MASK (0xf << S5L_TX_FIFO_COUNT_SHIFT) +#define S5L_TX_FIFO_FULL (1 << 9) + +#define S5P_RX_FIFO_COUNT_SHIFT 0 +#define S5P_RX_FIFO_COUNT_MASK (0xff << S5P_RX_FIFO_COUNT_SHIFT) +#define S5P_RX_FIFO_FULL (1 << 8) +#define S5P_TX_FIFO_COUNT_SHIFT 16 +#define S5P_TX_FIFO_COUNT_MASK (0xff << S5P_TX_FIFO_COUNT_SHIFT) +#define S5P_TX_FIFO_FULL (1 << 24) /* Information about a serial port */ struct s5p_serial_plat { struct s5p_uart *reg; /* address of registers in physical memory */ + u8 reg_width; /* register width */ u8 port_id; /* uart port number */ + u8 rx_fifo_count_shift; + u8 tx_fifo_count_shift; + u32 rx_fifo_count_mask; + u32 tx_fifo_count_mask; + u32 rx_fifo_full; + u32 tx_fifo_full; }; /* @@ -71,8 +92,8 @@ static void __maybe_unused s5p_serial_init(struct s5p_uart *uart) writel(0x245, &uart->ucon); } -static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk, - int baudrate) +static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, u8 reg_width, + uint uclk, int baudrate) { u32 val; @@ -82,6 +103,8 @@ static void __maybe_unused s5p_serial_baud(struct s5p_uart *uart, uint uclk, if (s5p_uart_divslot()) writew(udivslot[val % 16], &uart->rest.slot); + else if (reg_width == 4) + writel(val % 16, &uart->rest.value); else writeb(val % 16, &uart->rest.value); } @@ -93,7 +116,7 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate) struct s5p_uart *const uart = plat->reg; u32 uclk; -#ifdef CONFIG_CLK_EXYNOS +#if CONFIG_IS_ENABLED(CLK_EXYNOS) || CONFIG_IS_ENABLED(ARCH_APPLE) struct clk clk; u32 ret; @@ -105,7 +128,7 @@ int s5p_serial_setbrg(struct udevice *dev, int baudrate) uclk = get_uart_clk(plat->port_id); #endif - s5p_serial_baud(uart, uclk, baudrate); + s5p_serial_baud(uart, plat->reg_width, uclk, baudrate); return 0; } @@ -144,11 +167,14 @@ static int s5p_serial_getc(struct udevice *dev) struct s5p_serial_plat *plat = dev_get_plat(dev); struct s5p_uart *const uart = plat->reg; - if (!(readl(&uart->ufstat) & RX_FIFO_COUNT_MASK)) + if (!(readl(&uart->ufstat) & plat->rx_fifo_count_mask)) return -EAGAIN; serial_err_check(uart, 0); - return (int)(readb(&uart->urxh) & 0xff); + if (plat->reg_width == 4) + return (int)(readl(&uart->urxh) & 0xff); + else + return (int)(readb(&uart->urxh) & 0xff); } static int s5p_serial_putc(struct udevice *dev, const char ch) @@ -156,10 +182,13 @@ static int s5p_serial_putc(struct udevice *dev, const char ch) struct s5p_serial_plat *plat = dev_get_plat(dev); struct s5p_uart *const uart = plat->reg; - if (readl(&uart->ufstat) & TX_FIFO_FULL) + if (readl(&uart->ufstat) & plat->tx_fifo_full) return -EAGAIN; - writeb(ch, &uart->utxh); + if (plat->reg_width == 4) + writel(ch, &uart->utxh); + else + writeb(ch, &uart->utxh); serial_err_check(uart, 1); return 0; @@ -171,15 +200,19 @@ static int s5p_serial_pending(struct udevice *dev, bool input) struct s5p_uart *const uart = plat->reg; uint32_t ufstat = readl(&uart->ufstat); - if (input) - return (ufstat & RX_FIFO_COUNT_MASK) >> RX_FIFO_COUNT_SHIFT; - else - return (ufstat & TX_FIFO_COUNT_MASK) >> TX_FIFO_COUNT_SHIFT; + if (input) { + return (ufstat & plat->rx_fifo_count_mask) >> + plat->rx_fifo_count_shift; + } else { + return (ufstat & plat->tx_fifo_count_mask) >> + plat->tx_fifo_count_shift; + } } static int s5p_serial_of_to_plat(struct udevice *dev) { struct s5p_serial_plat *plat = dev_get_plat(dev); + const ulong port_type = dev_get_driver_data(dev); fdt_addr_t addr; addr = dev_read_addr(dev); @@ -187,8 +220,26 @@ static int s5p_serial_of_to_plat(struct udevice *dev) return -EINVAL; plat->reg = (struct s5p_uart *)addr; + plat->reg_width = dev_read_u32_default(dev, "reg-io-width", 1); plat->port_id = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "id", dev_seq(dev)); + + if (port_type == PORT_S5L) { + plat->rx_fifo_count_shift = S5L_RX_FIFO_COUNT_SHIFT; + plat->rx_fifo_count_mask = S5L_RX_FIFO_COUNT_MASK; + plat->rx_fifo_full = S5L_RX_FIFO_FULL; + plat->tx_fifo_count_shift = S5L_TX_FIFO_COUNT_SHIFT; + plat->tx_fifo_count_mask = S5L_TX_FIFO_COUNT_MASK; + plat->tx_fifo_full = S5L_TX_FIFO_FULL; + } else { + plat->rx_fifo_count_shift = S5P_RX_FIFO_COUNT_SHIFT; + plat->rx_fifo_count_mask = S5P_RX_FIFO_COUNT_MASK; + plat->rx_fifo_full = S5P_RX_FIFO_FULL; + plat->tx_fifo_count_shift = S5P_TX_FIFO_COUNT_SHIFT; + plat->tx_fifo_count_mask = S5P_TX_FIFO_COUNT_MASK; + plat->tx_fifo_full = S5P_TX_FIFO_FULL; + } + return 0; } @@ -200,7 +251,8 @@ static const struct dm_serial_ops s5p_serial_ops = { }; static const struct udevice_id s5p_serial_ids[] = { - { .compatible = "samsung,exynos4210-uart" }, + { .compatible = "samsung,exynos4210-uart", .data = PORT_S5P }, + { .compatible = "apple,s5l-uart", .data = PORT_S5L }, { } }; @@ -224,16 +276,24 @@ static inline void _debug_uart_init(void) struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE; s5p_serial_init(uart); - s5p_serial_baud(uart, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); +#if CONFIG_IS_ENABLED(ARCH_APPLE) + s5p_serial_baud(uart, 4, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); +#else + s5p_serial_baud(uart, 1, CONFIG_DEBUG_UART_CLOCK, CONFIG_BAUDRATE); +#endif } static inline void _debug_uart_putc(int ch) { struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE; - while (readl(&uart->ufstat) & TX_FIFO_FULL); - +#if CONFIG_IS_ENABLED(ARCH_APPLE) + while (readl(&uart->ufstat) & S5L_TX_FIFO_FULL); + writel(ch, &uart->utxh); +#else + while (readl(&uart->ufstat) & S5P_TX_FIFO_FULL); writeb(ch, &uart->utxh); +#endif } DEBUG_UART_FUNCS -- cgit v1.2.3 From 785cfde5b3a0d24dc293792c7c277a091c46ef3a Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:05 +0200 Subject: iommu: Add Apple DART driver The DART is an IOMMU that is used on Apple's M1 SoC. This driver configures the DART such that it operates in bypass mode which is enough to support DMA for the USB3 ports integrated on the SoC. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- arch/arm/Kconfig | 1 + drivers/iommu/Kconfig | 10 ++++++++ drivers/iommu/Makefile | 1 + drivers/iommu/apple_dart.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 drivers/iommu/apple_dart.c diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 293e3e39283..b4808d4c752 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -931,6 +931,7 @@ config ARCH_APPLE select DM_SERIAL select DM_USB select DM_VIDEO + select IOMMU select LINUX_KERNEL_IMAGE_HEADER select OF_CONTROL select OF_BOARD diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 3e35ce8fcc8..dabc1f900d5 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -14,4 +14,14 @@ config IOMMU memory if the IOMMU has been programmed to allow access to that memory. +config APPLE_DART + bool "Apple DART support" + depends on IOMMU && ARCH_APPLE + default y + help + Enable support for the DART on Apple SoCs. The DART is Apple's + IOMMU implementation. The driver performs the necessary + configuration to put the DART into bypass mode such that it can + be used transparently by U-Boot. + endmenu diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index af1c6bbb7ac..e3e0900e170 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -2,4 +2,5 @@ obj-$(CONFIG_IOMMU) += iommu-uclass.o +obj-$(CONFIG_APPLE_DART) += apple_dart.o obj-$(CONFIG_SANDBOX) += sandbox_iommu.o diff --git a/drivers/iommu/apple_dart.c b/drivers/iommu/apple_dart.c new file mode 100644 index 00000000000..ff8c5fa62c2 --- /dev/null +++ b/drivers/iommu/apple_dart.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2021 Mark Kettenis + */ + +#include +#include +#include +#include + +#define DART_PARAMS2 0x0004 +#define DART_PARAMS2_BYPASS_SUPPORT BIT(0) +#define DART_TLB_OP 0x0020 +#define DART_TLB_OP_OPMASK (0xfff << 20) +#define DART_TLB_OP_FLUSH (0x001 << 20) +#define DART_TLB_OP_BUSY BIT(2) +#define DART_TLB_OP_SIDMASK 0x0034 +#define DART_ERROR_STATUS 0x0040 +#define DART_TCR(sid) (0x0100 + 4 * (sid)) +#define DART_TCR_TRANSLATE_ENABLE BIT(7) +#define DART_TCR_BYPASS_DART BIT(8) +#define DART_TCR_BYPASS_DAPF BIT(12) +#define DART_TTBR(sid, idx) (0x0200 + 16 * (sid) + 4 * (idx)) +#define DART_TTBR_VALID BIT(31) +#define DART_TTBR_SHIFT 12 + +static int apple_dart_probe(struct udevice *dev) +{ + void *base; + int sid, i; + + base = dev_read_addr_ptr(dev); + if (!base) + return -EINVAL; + + u32 params2 = readl(base + DART_PARAMS2); + if (params2 & DART_PARAMS2_BYPASS_SUPPORT) { + for (sid = 0; sid < 16; sid++) { + writel(DART_TCR_BYPASS_DART | DART_TCR_BYPASS_DAPF, + base + DART_TCR(sid)); + for (i = 0; i < 4; i++) + writel(0, base + DART_TTBR(sid, i)); + } + } + + return 0; +} + +static const struct udevice_id apple_dart_ids[] = { + { .compatible = "apple,t8103-dart" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(apple_dart) = { + .name = "apple_dart", + .id = UCLASS_IOMMU, + .of_match = apple_dart_ids, + .probe = apple_dart_probe +}; -- cgit v1.2.3 From 3dfef536103d61b4a2b98a248af236aa9bf05e45 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:06 +0200 Subject: arm: dts: apple: Add preliminary device trees Add preliminary device trees for the Apple M1 mini (2020) and Apple M1 Macbook Pro 13" (2020). Device tree bindings for the Apple M1 SoC are still being formalized and these device trees will be synchronized with the Linux kernel as needed. The device trees in this commit are based on the initial Apple M1 device trees from Linux 5.13, nodes for dart, pcie, pinctrl, pmgr, usb based on bindings on track for inclusion in Linux 5.15 and 5.16 and nodes for i2c, mailbox, nvme, pmu, spmi and watchdog that don't have a proposed binding yet. These device trees are provided as a reference only as U-Boot uses the device tree passed by the m1n1 bootloader. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- arch/arm/dts/Makefile | 4 + arch/arm/dts/t8103-j274.dts | 135 +++++ arch/arm/dts/t8103-j293.dts | 97 ++++ arch/arm/dts/t8103.dtsi | 560 +++++++++++++++++++++ configs/apple_m1_defconfig | 1 + .../dt-bindings/interrupt-controller/apple-aic.h | 15 + include/dt-bindings/pinctrl/apple.h | 13 + include/dt-bindings/spmi/spmi.h | 10 + 8 files changed, 835 insertions(+) create mode 100644 arch/arm/dts/t8103-j274.dts create mode 100644 arch/arm/dts/t8103-j293.dts create mode 100644 arch/arm/dts/t8103.dtsi create mode 100644 include/dt-bindings/interrupt-controller/apple-aic.h create mode 100644 include/dt-bindings/pinctrl/apple.h create mode 100644 include/dt-bindings/spmi/spmi.h diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index a88aecc5bd9..a7222cc2726 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -29,6 +29,10 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \ exynos5422-odroidxu3.dtb dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb +dtb-$(CONFIG_ARCH_APPLE) += \ + t8103-j274.dtb \ + t8103-j293.dtb + dtb-$(CONFIG_ARCH_DAVINCI) += \ da850-evm.dtb \ da850-lcdk.dtb \ diff --git a/arch/arm/dts/t8103-j274.dts b/arch/arm/dts/t8103-j274.dts new file mode 100644 index 00000000000..aef1ae29b63 --- /dev/null +++ b/arch/arm/dts/t8103-j274.dts @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Apple Mac mini (M1, 2020) + * + * target-type: J274 + * + * Copyright The Asahi Linux Contributors + */ + +/dts-v1/; + +#include "t8103.dtsi" + +/ { + compatible = "apple,j274", "apple,t8103", "apple,arm-platform"; + model = "Apple Mac mini (M1, 2020)"; + + aliases { + serial0 = &serial0; + ethernet0 = ð0; + wifi0 = &wifi0; + }; + + chosen { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + stdout-path = "serial0"; + + framebuffer0: framebuffer@0 { + compatible = "apple,simple-framebuffer", "simple-framebuffer"; + reg = <0 0 0 0>; /* To be filled by loader */ + /* Format properties will be added by loader */ + status = "disabled"; + }; + }; + + memory@800000000 { + device_type = "memory"; + reg = <0x8 0 0x2 0>; /* To be filled by loader */ + }; +}; + +&serial0 { + status = "okay"; +}; + +&pcie0_dart_0 { + status = "okay"; +}; + +&pcie0_dart_1 { + status = "okay"; +}; + +&pcie0_dart_2 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + pci0: pci@0,0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + pwren-gpios = <&smc 13 0>; + reset-gpios = <&pinctrl_ap 152 0>; + max-link-speed = <2>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + + pci1: pci@1,0 { + device_type = "pci"; + reg = <0x800 0x0 0x0 0x0 0x0>; + reset-gpios = <&pinctrl_ap 153 0>; + max-link-speed = <2>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; + + pci2: pci@2,0 { + device_type = "pci"; + reg = <0x1000 0x0 0x0 0x0 0x0>; + reset-gpios = <&pinctrl_ap 33 0>; + max-link-speed = <1>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&pci0 { + wifi0: network@0,0 { + reg = <0x10000 0x0 0x0 0x0 0x0>; + local-mac-address = [00 00 00 00 00 00]; + }; +}; + +&pci2 { + eth0: ethernet@0,0 { + reg = <0x30000 0x0 0x0 0x0 0x0>; + local-mac-address = [00 00 00 00 00 00]; + }; +}; + +&dwc3_0_dart_0 { + status = "okay"; +}; + +&dwc3_0_dart_1 { + status = "okay"; +}; + +&dwc3_0 { + status = "okay"; +}; + +&dwc3_1_dart_0 { + status = "okay"; +}; + +&dwc3_1_dart_1 { + status = "okay"; +}; + +&dwc3_1 { + status = "okay"; +}; diff --git a/arch/arm/dts/t8103-j293.dts b/arch/arm/dts/t8103-j293.dts new file mode 100644 index 00000000000..4a22596cf4e --- /dev/null +++ b/arch/arm/dts/t8103-j293.dts @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Apple Macbook Pro (M1, 2020) + * + * target-type: J293 + * + * Copyright The Asahi Linux Contributors + */ + +/dts-v1/; + +#include "t8103.dtsi" + +/ { + compatible = "apple,j293", "apple,t8103", "apple,arm-platform"; + model = "Apple Macbook Pro (M1, 2020)"; + + aliases { + serial0 = &serial0; + wifi0 = &wifi0; + }; + + chosen { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + stdout-path = "serial0"; + + framebuffer0: framebuffer@0 { + compatible = "apple,simple-framebuffer", "simple-framebuffer"; + reg = <0 0 0 0>; /* To be filled by loader */ + /* Format properties will be added by loader */ + status = "disabled"; + }; + }; + + memory@800000000 { + device_type = "memory"; + reg = <0x8 0 0x2 0>; /* To be filled by loader */ + }; +}; + +&serial0 { + status = "okay"; +}; + +&pcie0_dart_0 { + status = "okay"; +}; + +&pcie0 { + status = "okay"; + + pci0: pci@0,0 { + device_type = "pci"; + reg = <0x0 0x0 0x0 0x0 0x0>; + pwren-gpios = <&smc 13 0>; + reset-gpios = <&pinctrl_ap 152 0>; + max-link-speed = <2>; + + #address-cells = <3>; + #size-cells = <2>; + ranges; + }; +}; + +&pci0 { + wifi0: network@0,0 { + reg = <0x10000 0x0 0x0 0x0 0x0>; + local-mac-address = [00 00 00 00 00 00]; + }; +}; + +&dwc3_0_dart_0 { + status = "okay"; +}; + +&dwc3_0_dart_1 { + status = "okay"; +}; + +&dwc3_0 { + status = "okay"; +}; + +&dwc3_1_dart_0 { + status = "okay"; +}; + +&dwc3_1_dart_1 { + status = "okay"; +}; + +&dwc3_1 { + status = "okay"; +}; diff --git a/arch/arm/dts/t8103.dtsi b/arch/arm/dts/t8103.dtsi new file mode 100644 index 00000000000..7d9cb272f93 --- /dev/null +++ b/arch/arm/dts/t8103.dtsi @@ -0,0 +1,560 @@ +// SPDX-License-Identifier: GPL-2.0+ OR MIT +/* + * Apple T8103 "M1" SoC + * + * Other names: H13G, "Tonga" + * + * Copyright The Asahi Linux Contributors + */ + +#include +#include +#include +#include +#include + +/ { + compatible = "apple,t8103", "apple,arm-platform"; + + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "apple,icestorm"; + device_type = "cpu"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu1: cpu@1 { + compatible = "apple,icestorm"; + device_type = "cpu"; + reg = <0x0 0x1>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu2: cpu@2 { + compatible = "apple,icestorm"; + device_type = "cpu"; + reg = <0x0 0x2>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu3: cpu@3 { + compatible = "apple,icestorm"; + device_type = "cpu"; + reg = <0x0 0x3>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu4: cpu@10100 { + compatible = "apple,firestorm"; + device_type = "cpu"; + reg = <0x0 0x10100>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu5: cpu@10101 { + compatible = "apple,firestorm"; + device_type = "cpu"; + reg = <0x0 0x10101>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu6: cpu@10102 { + compatible = "apple,firestorm"; + device_type = "cpu"; + reg = <0x0 0x10102>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + + cpu7: cpu@10103 { + compatible = "apple,firestorm"; + device_type = "cpu"; + reg = <0x0 0x10103>; + enable-method = "spin-table"; + cpu-release-addr = <0 0>; /* To be filled by loader */ + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupt-parent = <&aic>; + interrupt-names = "hyp-phys", "hyp-virt", "phys", "virt"; + interrupts = , + , + , + ; + }; + + clkref: clock-ref { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "clkref"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + + ranges; + dma-ranges; + dma-coherent; + nonposted-mmio; + + serial0: serial@235200000 { + compatible = "apple,s5l-uart"; + reg = <0x2 0x35200000 0x0 0x1000>; + reg-io-width = <4>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>, <&clkref>, <&clkref>; + clock-names = "uart", "clk_uart_baud0", "clk_uart_baud1"; + power-domains = <&ps_uart0>; + status = "disabled"; + }; + + serial2: serial@235208000 { + compatible = "apple,s5l-uart"; + reg = <0x2 0x35208000 0x0 0x1000>; + reg-io-width = <4>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>, <&clkref>, <&clkref>; + clock-names = "uart", "clk_uart_baud0", "clk_uart_baud1"; + power-domains = <&ps_uart2>; + status = "disabled"; + }; + + aic: interrupt-controller@23b100000 { + compatible = "apple,t8103-aic", "apple,aic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x2 0x3b100000 0x0 0x8000>; + }; + + pmgr: power-controller@23b700000 { + compatible = "apple,t8103-pmgr", "apple,pmgr", "syscon", "simple-mfd"; + #address-cells = <1>; + #size-cells = <0>; + + reg = <0x2 0x3b700000 0x0 0x14000>; + + ps_pcie_ref: power-controller@1a0 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x1a0>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "pcie_ref"; + }; + + ps_imx: power-controller@1b8 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x1b8>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "imx"; + apple,always-on; + }; + + ps_sio: power-controller@1c0 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x1c0>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "sio"; + }; + + ps_uart_p: power-controller@220 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x220>; + #power-domain-cells = <0>; + #reset-cells = <0>; + power-domains = <&ps_sio>; + apple,domain-name = "uart_p"; + }; + + ps_uart0: power-controller@270 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x270>; + #power-domain-cells = <0>; + #reset-cells = <0>; + power-domains = <&ps_uart_p>; + apple,domain-name = "uart0"; + }; + + ps_uart1: power-controller@278 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x278>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "uart1"; + power-domains = <&ps_uart_p>; + }; + + ps_uart2: power-controller@280 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x280>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "uart2"; + power-domains = <&ps_uart_p>; + }; + + ps_uart3: power-controller@288 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x288>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "uart3"; + power-domains = <&ps_uart_p>; + }; + + ps_apcie: power-controller@348 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x348>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "apcie"; + power-domains = <&ps_imx>; + }; + + ps_apcie_gp: power-controller@3e8 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x3e8>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "apcie_gp"; + power-domains = <&ps_apcie>; + }; + + ps_ans2: power-controller@3f0 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x3f0>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "ans2"; + power-domains = <&ps_apcie_st>; + }; + + ps_apcie_st: power-controller@418 { + compatible = "apple,t8103-pmgr-pwrstate", "apple,pmgr-pwrstate"; + reg = <0x418>; + #power-domain-cells = <0>; + #reset-cells = <0>; + apple,domain-name = "apcie_st"; + power-domains = <&ps_apcie>; + }; + }; + + pinctrl_ap: pinctrl@23c100000 { + compatible = "apple,t8103-pinctrl", "apple,pinctrl"; + reg = <0x2 0x3c100000 0x0 0x100000>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_ap 0 0 212>; + + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + + i2c0_pins: i2c0_pins { + pinmux = , + ; + }; + + pcie_pins: pcie-pins { + pinmux = , + , + ; + }; + }; + + pinctrl_aop: pinctrl@24a820000 { + compatible = "apple,t8103-pinctrl", "apple,pinctrl"; + reg = <0x2 0x4a820000 0x0 0x4000>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_aop 0 0 42>; + + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + }; + + pinctrl_nub: pinctrl@23d1f0000 { + compatible = "apple,t8103-pinctrl", "apple,pinctrl"; + reg = <0x2 0x3d1f0000 0x0 0x4000>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_nub 0 0 23>; + + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + }; + + pinctrl_smc: pinctrl@23e820000 { + compatible = "apple,t8103-pinctrl", "apple,pinctrl"; + reg = <0x2 0x3e820000 0x0 0x4000>; + + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&pinctrl_smc 0 0 16>; + + interrupt-controller; + interrupt-parent = <&aic>; + interrupts = , + , + , + , + , + , + ; + }; + + i2c0: i2c@20a110000 { + compatible = "apple,i2c-v0"; + reg = <0x2 0x35010000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + clocks = <&clkref>; + pinctrl-0 = <&i2c0_pins>; + pinctrl-names = "default"; + #address-cells = <0x1>; + #size-cells = <0x0>; + + hpm0: hpm@38 { + compatible = "ti,tps6598x"; + reg = <0x38>; + }; + + hpm1: hpm@3f { + compatible = "ti,tps6598x"; + reg = <0x3f>; + }; + }; + + ans_mbox: mbox@277400000 { + compatible = "apple,iop-mailbox-m1"; + reg = <0x2 0x77400000 0x0 0x20000>; + interrupt-parent = <&aic>; + interrupts = , + ; + power-domains = <&ps_ans2>; + #mbox-cells = <1>; + endpoints = <32>; + }; + + ans@27bcc0000 { + compatible = "apple,nvme-m1"; + reg = <0x2 0x7bcc0000 0x0 0x40000>, + <0x2 0x7bc50000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + power-domains = <&ps_apcie_st>; + mboxes = <&ans_mbox 32>; + }; + + pcie0_dart_0: iommu@681008000 { + compatible = "apple,t8103-dart", "apple,dart-m1"; + reg = <0x6 0x81008000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + pcie0_dart_1: iommu@682008000 { + compatible = "apple,t8103-dart", "apple,dart-m1"; + reg = <0x6 0x82008000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + pcie0_dart_2: iommu@683008000 { + compatible = "apple,t8103-dart", "apple,dart-m1"; + reg = <0x6 0x83008000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + smc_mbox: mbox@23e400000 { + compatible = "apple,iop-mailbox-m1"; + reg = <0x2 0x3e400000 0x0 0x20000>; + #mbox-cells = <1>; + endpoints = <32>; + }; + + smc: smc@23e050000 { + compatible = "apple,smc-m1"; + reg = <0x2 0x3e050000 0x0 0x4000>; + mboxes = <&smc_mbox 32>; + gpio-controller; + #gpio-cells = <2>; + gpio-13 = <0x00800000>; + }; + + pcie0: pcie@690000000 { + compatible = "apple,t8103-pcie", "apple,pcie"; + + reg = <0x6 0x90000000 0x0 0x1000000>, + <0x6 0x80000000 0x0 0x4000>, + <0x6 0x81000000 0x0 0x8000>, + <0x6 0x82000000 0x0 0x8000>, + <0x6 0x83000000 0x0 0x8000>; + reg-names = "config", "rc", "port0", "port1", "port2"; + + interrupt-parent = <&aic>; + interrupts = , + , + ; + + msi-controller; + msi-parent = <&pcie0>; + msi-ranges = <&aic AIC_IRQ 704 IRQ_TYPE_EDGE_RISING 32>; + + iommu-map = <0x100 &pcie0_dart_0 1 1>, + <0x200 &pcie0_dart_1 1 1>, + <0x300 &pcie0_dart_2 1 1>; + iommu-map-mask = <0xff00>; + + bus-range = <0 3>; + #address-cells = <3>; + #size-cells = <2>; + ranges = <0x43000000 0x6 0xa0000000 0x6 0xa0000000 + 0x0 0x20000000>, + <0x02000000 0x0 0xc0000000 0x6 0xc0000000 + 0x0 0x40000000>; + + power-domains = <&ps_apcie>, <&ps_apcie_gp>, <&ps_pcie_ref>; + pinctrl-0 = <&pcie_pins>; + pinctrl-names = "default"; + + device_type = "pci"; + status = "disabled"; + }; + + dwc3_0_dart_0: iommu@382f00000 { + compatible = "apple,t8103-dart"; + reg = <0x3 0x82f00000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + dwc3_0_dart_1: iommu@382f80000 { + compatible = "apple,t8103-dart"; + reg = <0x3 0x82f80000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + dwc3_0: usb@382280000{ + compatible = "snps,dwc3"; + reg = <0x3 0x82280000 0x0 0x100000>; + interrupt-parent = <&aic>; + interrupts = ; + dr_mode = "host"; + iommus = <&dwc3_0_dart_0 0>, <&dwc3_0_dart_1 1>; + status = "disabled"; + }; + + dwc3_1_dart_0: iommu@502f00000 { + compatible = "apple,t8103-dart"; + reg = <0x5 0x02f00000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + dwc3_1_dart_1: iommu@502f80000 { + compatible = "apple,t8103-dart"; + reg = <0x5 0x02f80000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + #iommu-cells = <1>; + status = "disabled"; + }; + + dwc3_1: usb@502280000{ + compatible = "snps,dwc3"; + reg = <0x5 0x02280000 0x0 0x100000>; + interrupt-parent = <&aic>; + interrupts = ; + dr_mode = "host"; + iommus = <&dwc3_1_dart_0 0>, <&dwc3_1_dart_1 1>; + status = "disabled"; + }; + + reboot@23d2b0000 { + compatible = "apple,reboot-v0"; + reg = <0x2 0x3d2b0000 0x0 0x4000>; + }; + + spi@23510c000 { + compatible = "apple,t8103-spi", "apple,spi"; + reg = <0x2 0x3510c000 0x0 0x4000>; + interrupt-parent = <&aic>; + interrupts = ; + cs-gpios = <&pinctrl_ap 49 GPIO_ACTIVE_HIGH>; + }; + + spmi@23d0d8000 { + compatible = "apple,t8103-spmi", "apple,spmi"; + reg = <0x2 0x3d0d9300 0x0 0x100>; + interrupt-parent = <&aic>; + interrupts = ; + + #address-cells = <2>; + #size-cells = <0>; + + pmu@f { + compatible = "apple,sera-pmu"; + reg = <0xf SPMI_USID>; + }; + }; + }; +}; diff --git a/configs/apple_m1_defconfig b/configs/apple_m1_defconfig index 520d7c7632a..d71cbfd043e 100644 --- a/configs/apple_m1_defconfig +++ b/configs/apple_m1_defconfig @@ -1,5 +1,6 @@ CONFIG_ARM=y CONFIG_ARCH_APPLE=y +CONFIG_DEFAULT_DEVICE_TREE="t8103-j274" # CONFIG_DISPLAY_CPUINFO is not set # CONFIG_MMC is not set # CONFIG_NET is not set diff --git a/include/dt-bindings/interrupt-controller/apple-aic.h b/include/dt-bindings/interrupt-controller/apple-aic.h new file mode 100644 index 00000000000..9ac56a7e6d3 --- /dev/null +++ b/include/dt-bindings/interrupt-controller/apple-aic.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_APPLE_AIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_APPLE_AIC_H + +#include + +#define AIC_IRQ 0 +#define AIC_FIQ 1 + +#define AIC_TMR_HV_PHYS 0 +#define AIC_TMR_HV_VIRT 1 +#define AIC_TMR_GUEST_PHYS 2 +#define AIC_TMR_GUEST_VIRT 3 + +#endif diff --git a/include/dt-bindings/pinctrl/apple.h b/include/dt-bindings/pinctrl/apple.h new file mode 100644 index 00000000000..ea0a6f46659 --- /dev/null +++ b/include/dt-bindings/pinctrl/apple.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR MIT */ +/* + * This header provides constants for Apple pinctrl bindings. + */ + +#ifndef _DT_BINDINGS_PINCTRL_APPLE_H +#define _DT_BINDINGS_PINCTRL_APPLE_H + +#define APPLE_PINMUX(pin, func) ((pin) | ((func) << 16)) +#define APPLE_PIN(pinmux) ((pinmux) & 0xffff) +#define APPLE_FUNC(pinmux) ((pinmux) >> 16) + +#endif /* _DT_BINDINGS_PINCTRL_APPLE_H */ diff --git a/include/dt-bindings/spmi/spmi.h b/include/dt-bindings/spmi/spmi.h new file mode 100644 index 00000000000..ad4a43481de --- /dev/null +++ b/include/dt-bindings/spmi/spmi.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + */ +#ifndef __DT_BINDINGS_SPMI_H +#define __DT_BINDINGS_SPMI_H + +#define SPMI_USID 0 +#define SPMI_GSID 1 + +#endif -- cgit v1.2.3 From 91ce6bf20bdffe3f67dfa2637d14a74e2244f3c5 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Sat, 23 Oct 2021 16:58:07 +0200 Subject: doc: board: apple: Add Apple M1 documentation Provide preliminary instructions on how to get U-Boot to run on Apple Silicon Macs. Signed-off-by: Mark Kettenis Reviewed-by: Simon Glass --- doc/board/apple/index.rst | 9 ++++++++ doc/board/apple/m1.rst | 59 +++++++++++++++++++++++++++++++++++++++++++++++ doc/board/index.rst | 1 + 3 files changed, 69 insertions(+) create mode 100644 doc/board/apple/index.rst create mode 100644 doc/board/apple/m1.rst diff --git a/doc/board/apple/index.rst b/doc/board/apple/index.rst new file mode 100644 index 00000000000..84468478182 --- /dev/null +++ b/doc/board/apple/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Apple +===== + +.. toctree:: + :maxdepth: 2 + + m1 diff --git a/doc/board/apple/m1.rst b/doc/board/apple/m1.rst new file mode 100644 index 00000000000..9fa21767c92 --- /dev/null +++ b/doc/board/apple/m1.rst @@ -0,0 +1,59 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +U-Boot for Apple Silicon Macs +============================= + +Allows Apple Silicon Macs to boot U-Boot via the m1n1 bootloader +developed by the Asahi Linux project. At this point the machines with +the following SoCs work: + + - Apple M1 SoC + +On these SoCs the following hardware is supported: + + - S5L serial port + - Framebuffer + - USB 3.1 Type-C ports + +Device trees are currently provided for the M1 Mac mini (2020, J274) +and M1 MacBook Pro 13" (2020, J293). The M1 MacBook Air (2020) is +expected to work with the J293 device tree. The M1 iMac (2021) may +work with the J274 device tree. + +Building U-Boot +--------------- + +.. code-block:: bash + + $ export CROSS_COMPILE=aarch64-none-elf- + $ make apple_m1_defconfig + $ make + +This will build ``u-boot-nodtb.bin`` as well as devices trees for some +of the supported machines. These device trees can be found in the +``arch/arm/dts`` subdirectory of your build. + +Image creation +-------------- + +In order to run U-Boot on an Apple Silicon Mac, U-Boot has to be used +as a payload for the m1n1 bootloader. Instructions for building m1n1 +can be found here: + + https://github.com/AsahiLinux/docs/wiki/SW%3Am1n1 + +.. code-block:: bash + + $ cat m1n1.macho t8103-j274.dtb u-boot-nodtb.bin > u-boot.macho + +This uses ``u-boot-nodtb.bin`` as the device tree is passed to U-Boot +by m1n1 after making some adjustments. + +Image installation +------------------ + +Instructions on how to install U-Boot on your Mac can be found at: + + https://github.com/AsahiLinux/docs/wiki/Developer-Quickstart + +Just replace ``m1n1.macho`` with ``u-boot.macho`` in the instructions. diff --git a/doc/board/index.rst b/doc/board/index.rst index aa397ab9421..1b93ced5634 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -10,6 +10,7 @@ Board-specific doc advantech/index AndesTech/index amlogic/index + apple/index atmel/index congatec/index coreboot/index -- cgit v1.2.3 From 324df15a292e938d9341df94e2192a4a465c714e Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:44:27 +0300 Subject: serial: qcom: add support for GENI serial driver Generic Interface (GENI) Serial Engine (SE) based uart can be found on newer qualcomm SOCs, starting from SDM845. Tested on Samsung SM-G9600(starqltechn) by chain-loading u-boot with stock bootloader. Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried Cc: Tom Rini --- MAINTAINERS | 1 + .../serial/msm-geni-serial.txt | 6 + drivers/serial/Kconfig | 18 + drivers/serial/Makefile | 1 + drivers/serial/serial_msm_geni.c | 613 +++++++++++++++++++++ 5 files changed, 639 insertions(+) create mode 100644 doc/device-tree-bindings/serial/msm-geni-serial.txt create mode 100644 drivers/serial/serial_msm_geni.c diff --git a/MAINTAINERS b/MAINTAINERS index 4ed72aecee0..1b3f6c57695 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -400,6 +400,7 @@ F: drivers/gpio/msm_gpio.c F: drivers/mmc/msm_sdhci.c F: drivers/phy/msm8916-usbh-phy.c F: drivers/serial/serial_msm.c +F: drivers/serial/serial_msm_geni.c F: drivers/smem/msm_smem.c F: drivers/usb/host/ehci-msm.c diff --git a/doc/device-tree-bindings/serial/msm-geni-serial.txt b/doc/device-tree-bindings/serial/msm-geni-serial.txt new file mode 100644 index 00000000000..9eadc2561b4 --- /dev/null +++ b/doc/device-tree-bindings/serial/msm-geni-serial.txt @@ -0,0 +1,6 @@ +Qualcomm GENI UART + +Required properties: +- compatible: must be "qcom,msm-geni-uart" +- reg: start address and size of the registers +- clock: interface clock (must accept baudrate as a frequency) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 7ee12901e78..6c8fdda9a0a 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -296,6 +296,14 @@ config DEBUG_UART_S5P will need to provide parameters to make this work. The driver will be available until the real driver-model serial is running. +config DEBUG_UART_MSM_GENI + bool "Qualcomm snapdragon" + depends on ARCH_SNAPDRAGON + help + Select this to enable a debug UART using the serial_msm driver. You + will need to provide parameters to make this work. The driver will + be available until the real driver-model serial is running. + config DEBUG_UART_MESON bool "Amlogic Meson" depends on MESON_SERIAL @@ -801,6 +809,16 @@ config MSM_SERIAL for example APQ8016 and MSM8916. Single baudrate is supported in current implementation (115200). +config MSM_GENI_SERIAL + bool "Qualcomm on-chip GENI UART" + help + Support UART based on Generic Interface (GENI) Serial Engine (SE), + used on Qualcomm Snapdragon SoCs. Should support all qualcomm SOCs + with Qualcomm Universal Peripheral (QUP) Wrapper cores, + i.e. newer ones, starting from SDM845. + Driver works in FIFO mode. + Multiple baudrates supported. + config OCTEON_SERIAL_BOOTCMD bool "MIPS Octeon PCI remote bootcmd input" depends on ARCH_OCTEON diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 4edd2aa9458..8168af640ff 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_PIC32_SERIAL) += serial_pic32.o obj-$(CONFIG_BCM283X_MU_SERIAL) += serial_bcm283x_mu.o obj-$(CONFIG_BCM283X_PL011_SERIAL) += serial_bcm283x_pl011.o obj-$(CONFIG_MSM_SERIAL) += serial_msm.o +obj-$(CONFIG_MSM_GENI_SERIAL) += serial_msm_geni.o obj-$(CONFIG_MVEBU_A3700_UART) += serial_mvebu_a3700.o obj-$(CONFIG_MPC8XX_CONS) += serial_mpc8xx.o obj-$(CONFIG_NULLDEV_SERIAL) += serial_nulldev.o diff --git a/drivers/serial/serial_msm_geni.c b/drivers/serial/serial_msm_geni.c new file mode 100644 index 00000000000..3e255a99dcc --- /dev/null +++ b/drivers/serial/serial_msm_geni.c @@ -0,0 +1,613 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm GENI serial engine UART driver + * + * (C) Copyright 2021 Dzmitry Sankouski + * + * Based on Linux driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define UART_OVERSAMPLING 32 +#define STALE_TIMEOUT 160 + +#define USEC_PER_SEC 1000000L + +/* Registers*/ +#define GENI_FORCE_DEFAULT_REG 0x20 +#define GENI_SER_M_CLK_CFG 0x48 +#define GENI_SER_S_CLK_CFG 0x4C +#define SE_HW_PARAM_0 0xE24 +#define SE_GENI_STATUS 0x40 +#define SE_GENI_S_CMD0 0x630 +#define SE_GENI_S_CMD_CTRL_REG 0x634 +#define SE_GENI_S_IRQ_CLEAR 0x648 +#define SE_GENI_S_IRQ_STATUS 0x640 +#define SE_GENI_S_IRQ_EN 0x644 +#define SE_GENI_M_CMD0 0x600 +#define SE_GENI_M_CMD_CTRL_REG 0x604 +#define SE_GENI_M_IRQ_CLEAR 0x618 +#define SE_GENI_M_IRQ_STATUS 0x610 +#define SE_GENI_M_IRQ_EN 0x614 +#define SE_GENI_TX_FIFOn 0x700 +#define SE_GENI_RX_FIFOn 0x780 +#define SE_GENI_TX_FIFO_STATUS 0x800 +#define SE_GENI_RX_FIFO_STATUS 0x804 +#define SE_GENI_TX_WATERMARK_REG 0x80C +#define SE_GENI_TX_PACKING_CFG0 0x260 +#define SE_GENI_TX_PACKING_CFG1 0x264 +#define SE_GENI_RX_PACKING_CFG0 0x284 +#define SE_GENI_RX_PACKING_CFG1 0x288 +#define SE_UART_RX_STALE_CNT 0x294 +#define SE_UART_TX_TRANS_LEN 0x270 +#define SE_UART_TX_STOP_BIT_LEN 0x26c +#define SE_UART_TX_WORD_LEN 0x268 +#define SE_UART_RX_WORD_LEN 0x28c +#define SE_UART_TX_TRANS_CFG 0x25c +#define SE_UART_TX_PARITY_CFG 0x2a4 +#define SE_UART_RX_TRANS_CFG 0x280 +#define SE_UART_RX_PARITY_CFG 0x2a8 + +#define M_TX_FIFO_WATERMARK_EN (BIT(30)) +#define DEF_TX_WM 2 +/* GENI_FORCE_DEFAULT_REG fields */ +#define FORCE_DEFAULT (BIT(0)) + +#define S_CMD_ABORT_EN (BIT(5)) + +#define UART_START_READ 0x1 + +/* GENI_M_CMD_CTRL_REG */ +#define M_GENI_CMD_CANCEL (BIT(2)) +#define M_GENI_CMD_ABORT (BIT(1)) +#define M_GENI_DISABLE (BIT(0)) + +#define M_CMD_ABORT_EN (BIT(5)) +#define M_CMD_DONE_EN (BIT(0)) +#define M_CMD_DONE_DISABLE_MASK (~M_CMD_DONE_EN) + +#define S_GENI_CMD_ABORT (BIT(1)) + +/* GENI_S_CMD0 fields */ +#define S_OPCODE_MSK (GENMASK(31, 27)) +#define S_PARAMS_MSK (GENMASK(26, 0)) + +/* GENI_STATUS fields */ +#define M_GENI_CMD_ACTIVE (BIT(0)) +#define S_GENI_CMD_ACTIVE (BIT(12)) +#define M_CMD_DONE_EN (BIT(0)) +#define S_CMD_DONE_EN (BIT(0)) + +#define M_OPCODE_SHIFT 27 +#define S_OPCODE_SHIFT 27 +#define M_TX_FIFO_WATERMARK_EN (BIT(30)) +#define UART_START_TX 0x1 +#define UART_CTS_MASK (BIT(1)) +#define M_SEC_IRQ_EN (BIT(31)) +#define TX_FIFO_WC_MSK (GENMASK(27, 0)) +#define RX_FIFO_WC_MSK (GENMASK(24, 0)) + +#define S_RX_FIFO_WATERMARK_EN (BIT(26)) +#define S_RX_FIFO_LAST_EN (BIT(27)) +#define M_RX_FIFO_WATERMARK_EN (BIT(26)) +#define M_RX_FIFO_LAST_EN (BIT(27)) + +/* GENI_SER_M_CLK_CFG/GENI_SER_S_CLK_CFG */ +#define SER_CLK_EN (BIT(0)) +#define CLK_DIV_MSK (GENMASK(15, 4)) +#define CLK_DIV_SHFT 4 + +/* SE_HW_PARAM_0 fields */ +#define TX_FIFO_WIDTH_MSK (GENMASK(29, 24)) +#define TX_FIFO_WIDTH_SHFT 24 +#define TX_FIFO_DEPTH_MSK (GENMASK(21, 16)) +#define TX_FIFO_DEPTH_SHFT 16 + +/* + * Predefined packing configuration of the serial engine (CFG0, CFG1 regs) + * for uart mode. + * + * Defines following configuration: + * - Bits of data per transfer word 8 + * - Number of words per fifo element 4 + * - Transfer from MSB to LSB or vice-versa false + */ +#define UART_PACKING_CFG0 0xf +#define UART_PACKING_CFG1 0x0 + +DECLARE_GLOBAL_DATA_PTR; + +struct msm_serial_data { + phys_addr_t base; + u32 baud; +}; + +unsigned long root_freq[] = {7372800, 14745600, 19200000, 29491200, + 32000000, 48000000, 64000000, 80000000, + 96000000, 100000000}; + +/** + * get_clk_cfg() - Get clock rate to apply on clock supplier. + * @clk_freq: Desired clock frequency after build-in divider. + * + * Return: frequency, supported by clock supplier, multiple of clk_freq. + */ +static int get_clk_cfg(unsigned long clk_freq) +{ + for (int i = 0; i < ARRAY_SIZE(root_freq); i++) { + if (!(root_freq[i] % clk_freq)) + return root_freq[i]; + } + return 0; +} + +/** + * get_clk_div_rate() - Find clock supplier frequency, and calculate divisor. + * @baud: Baudrate. + * @sampling_rate: Clock ticks per character. + * @clk_div: Pointer to calculated divisor. + * + * This function searches for suitable frequency for clock supplier, + * calculates divisor for internal divider, based on found frequency, + * and stores divisor under clk_div pointer. + * + * Return: frequency, supported by clock supplier, multiple of clk_freq. + */ +static int get_clk_div_rate(u32 baud, + u64 sampling_rate, u32 *clk_div) +{ + unsigned long ser_clk; + unsigned long desired_clk; + + desired_clk = baud * sampling_rate; + ser_clk = get_clk_cfg(desired_clk); + if (!ser_clk) { + pr_err("%s: Can't find matching DFS entry for baud %d\n", + __func__, baud); + return ser_clk; + } + + *clk_div = ser_clk / desired_clk; + return ser_clk; +} + +static int geni_serial_set_clock_rate(struct udevice *dev, u64 rate) +{ + struct clk *clk; + int ret; + + clk = devm_clk_get(dev, "se-clk"); + if (!clk) + return -EINVAL; + + ret = clk_set_rate(clk, rate); + return ret; +} + +/** + * geni_se_get_tx_fifo_depth() - Get the TX fifo depth of the serial engine + * @base: Pointer to the concerned serial engine. + * + * This function is used to get the depth i.e. number of elements in the + * TX fifo of the serial engine. + * + * Return: TX fifo depth in units of FIFO words. + */ +static inline u32 geni_se_get_tx_fifo_depth(long base) +{ + u32 tx_fifo_depth; + + tx_fifo_depth = ((readl(base + SE_HW_PARAM_0) & TX_FIFO_DEPTH_MSK) >> + TX_FIFO_DEPTH_SHFT); + return tx_fifo_depth; +} + +/** + * geni_se_get_tx_fifo_width() - Get the TX fifo width of the serial engine + * @base: Pointer to the concerned serial engine. + * + * This function is used to get the width i.e. word size per element in the + * TX fifo of the serial engine. + * + * Return: TX fifo width in bits + */ +static inline u32 geni_se_get_tx_fifo_width(long base) +{ + u32 tx_fifo_width; + + tx_fifo_width = ((readl(base + SE_HW_PARAM_0) & TX_FIFO_WIDTH_MSK) >> + TX_FIFO_WIDTH_SHFT); + return tx_fifo_width; +} + +static inline void geni_serial_baud(phys_addr_t base_address, u32 clk_div, + int baud) +{ + u32 s_clk_cfg = 0; + + s_clk_cfg |= SER_CLK_EN; + s_clk_cfg |= (clk_div << CLK_DIV_SHFT); + + writel(s_clk_cfg, base_address + GENI_SER_M_CLK_CFG); + writel(s_clk_cfg, base_address + GENI_SER_S_CLK_CFG); +} + +int msm_serial_setbrg(struct udevice *dev, int baud) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + priv->baud = baud; + u32 clk_div; + u64 clk_rate; + + clk_rate = get_clk_div_rate(baud, UART_OVERSAMPLING, &clk_div); + geni_serial_set_clock_rate(dev, clk_rate); + geni_serial_baud(priv->base, clk_div, baud); + + return 0; +} + +/** + * qcom_geni_serial_poll_bit() - Poll reg bit until desired value or timeout. + * @base: Pointer to the concerned serial engine. + * @offset: Offset to register address. + * @field: AND bitmask for desired bit. + * @set: Desired bit value. + * + * This function is used to get the width i.e. word size per element in the + * TX fifo of the serial engine. + * + * Return: true, when register bit equals desired value, false, when timeout + * reached. + */ +static bool qcom_geni_serial_poll_bit(const struct udevice *dev, int offset, + int field, bool set) +{ + u32 reg; + struct msm_serial_data *priv = dev_get_priv(dev); + unsigned int baud; + unsigned int tx_fifo_depth; + unsigned int tx_fifo_width; + unsigned int fifo_bits; + unsigned long timeout_us = 10000; + + baud = 115200; + + if (priv) { + baud = priv->baud; + if (!baud) + baud = 115200; + tx_fifo_depth = geni_se_get_tx_fifo_depth(priv->base); + tx_fifo_width = geni_se_get_tx_fifo_width(priv->base); + fifo_bits = tx_fifo_depth * tx_fifo_width; + /* + * Total polling iterations based on FIFO worth of bytes to be + * sent at current baud. Add a little fluff to the wait. + */ + timeout_us = ((fifo_bits * USEC_PER_SEC) / baud) + 500; + } + + timeout_us = DIV_ROUND_UP(timeout_us, 10) * 10; + while (timeout_us) { + reg = readl(priv->base + offset); + if ((bool)(reg & field) == set) + return true; + udelay(10); + timeout_us -= 10; + } + return false; +} + +static void qcom_geni_serial_setup_tx(u64 base, u32 xmit_size) +{ + u32 m_cmd; + + writel(xmit_size, base + SE_UART_TX_TRANS_LEN); + m_cmd = UART_START_TX << M_OPCODE_SHIFT; + writel(m_cmd, base + SE_GENI_M_CMD0); +} + +static inline void qcom_geni_serial_poll_tx_done(const struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + int done = 0; + u32 irq_clear = M_CMD_DONE_EN; + + done = qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS, + M_CMD_DONE_EN, true); + if (!done) { + writel(M_GENI_CMD_ABORT, priv->base + SE_GENI_M_CMD_CTRL_REG); + irq_clear |= M_CMD_ABORT_EN; + qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS, + M_CMD_ABORT_EN, true); + } + writel(irq_clear, priv->base + SE_GENI_M_IRQ_CLEAR); +} + +static u32 qcom_geni_serial_tx_empty(u64 base) +{ + return !readl(base + SE_GENI_TX_FIFO_STATUS); +} + +/** + * geni_se_setup_s_cmd() - Setup the secondary sequencer + * @se: Pointer to the concerned serial engine. + * @cmd: Command/Operation to setup in the secondary sequencer. + * @params: Parameter for the sequencer command. + * + * This function is used to configure the secondary sequencer with the + * command and its associated parameters. + */ +static inline void geni_se_setup_s_cmd(u64 base, u32 cmd, u32 params) +{ + u32 s_cmd; + + s_cmd = readl(base + SE_GENI_S_CMD0); + s_cmd &= ~(S_OPCODE_MSK | S_PARAMS_MSK); + s_cmd |= (cmd << S_OPCODE_SHIFT); + s_cmd |= (params & S_PARAMS_MSK); + writel(s_cmd, base + SE_GENI_S_CMD0); +} + +static void qcom_geni_serial_start_tx(u64 base) +{ + u32 irq_en; + u32 status; + + status = readl(base + SE_GENI_STATUS); + if (status & M_GENI_CMD_ACTIVE) + return; + + if (!qcom_geni_serial_tx_empty(base)) + return; + + irq_en = readl(base + SE_GENI_M_IRQ_EN); + irq_en |= M_TX_FIFO_WATERMARK_EN | M_CMD_DONE_EN; + + writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG); + writel(irq_en, base + SE_GENI_M_IRQ_EN); +} + +static void qcom_geni_serial_start_rx(struct udevice *dev) +{ + u32 status; + struct msm_serial_data *priv = dev_get_priv(dev); + + status = readl(priv->base + SE_GENI_STATUS); + + geni_se_setup_s_cmd(priv->base, UART_START_READ, 0); + + setbits_le32(priv->base + SE_GENI_S_IRQ_EN, S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); + setbits_le32(priv->base + SE_GENI_M_IRQ_EN, M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); +} + +static void qcom_geni_serial_abort_rx(struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + u32 irq_clear = S_CMD_DONE_EN | S_CMD_ABORT_EN; + + writel(S_GENI_CMD_ABORT, priv->base + SE_GENI_S_CMD_CTRL_REG); + qcom_geni_serial_poll_bit(dev, SE_GENI_S_CMD_CTRL_REG, + S_GENI_CMD_ABORT, false); + writel(irq_clear, priv->base + SE_GENI_S_IRQ_CLEAR); + writel(FORCE_DEFAULT, priv->base + GENI_FORCE_DEFAULT_REG); +} + +static void msm_geni_serial_setup_rx(struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + qcom_geni_serial_abort_rx(dev); + + writel(UART_PACKING_CFG0, priv->base + SE_GENI_RX_PACKING_CFG0); + writel(UART_PACKING_CFG1, priv->base + SE_GENI_RX_PACKING_CFG1); + + geni_se_setup_s_cmd(priv->base, UART_START_READ, 0); + + setbits_le32(priv->base + SE_GENI_S_IRQ_EN, S_RX_FIFO_WATERMARK_EN | S_RX_FIFO_LAST_EN); + setbits_le32(priv->base + SE_GENI_M_IRQ_EN, M_RX_FIFO_WATERMARK_EN | M_RX_FIFO_LAST_EN); +} + +static int msm_serial_putc(struct udevice *dev, const char ch) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + writel(DEF_TX_WM, priv->base + SE_GENI_TX_WATERMARK_REG); + qcom_geni_serial_setup_tx(priv->base, 1); + + qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS, + M_TX_FIFO_WATERMARK_EN, true); + + writel(ch, priv->base + SE_GENI_TX_FIFOn); + writel(M_TX_FIFO_WATERMARK_EN, priv->base + SE_GENI_M_IRQ_CLEAR); + + qcom_geni_serial_poll_tx_done(dev); + + return 0; +} + +static int msm_serial_getc(struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + u32 rx_fifo; + u32 m_irq_status; + u32 s_irq_status; + + writel(1 << S_OPCODE_SHIFT, priv->base + SE_GENI_S_CMD0); + + qcom_geni_serial_poll_bit(dev, SE_GENI_M_IRQ_STATUS, M_SEC_IRQ_EN, + true); + + m_irq_status = readl(priv->base + SE_GENI_M_IRQ_STATUS); + s_irq_status = readl(priv->base + SE_GENI_S_IRQ_STATUS); + writel(m_irq_status, priv->base + SE_GENI_M_IRQ_CLEAR); + writel(s_irq_status, priv->base + SE_GENI_S_IRQ_CLEAR); + qcom_geni_serial_poll_bit(dev, SE_GENI_RX_FIFO_STATUS, RX_FIFO_WC_MSK, + true); + + if (!readl(priv->base + SE_GENI_RX_FIFO_STATUS)) + return 0; + + rx_fifo = readl(priv->base + SE_GENI_RX_FIFOn); + return rx_fifo & 0xff; +} + +static int msm_serial_pending(struct udevice *dev, bool input) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + if (input) + return readl(priv->base + SE_GENI_RX_FIFO_STATUS) & + RX_FIFO_WC_MSK; + else + return readl(priv->base + SE_GENI_TX_FIFO_STATUS) & + TX_FIFO_WC_MSK; + + return 0; +} + +static const struct dm_serial_ops msm_serial_ops = { + .putc = msm_serial_putc, + .pending = msm_serial_pending, + .getc = msm_serial_getc, + .setbrg = msm_serial_setbrg, +}; + +static inline void geni_serial_init(struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + phys_addr_t base_address = priv->base; + u32 tx_trans_cfg; + u32 tx_parity_cfg = 0; /* Disable Tx Parity */ + u32 rx_trans_cfg = 0; + u32 rx_parity_cfg = 0; /* Disable Rx Parity */ + u32 stop_bit_len = 0; /* Default stop bit length - 1 bit */ + u32 bits_per_char; + + /* + * Ignore Flow control. + * n = 8. + */ + tx_trans_cfg = UART_CTS_MASK; + bits_per_char = BITS_PER_BYTE; + + /* + * Make an unconditional cancel on the main sequencer to reset + * it else we could end up in data loss scenarios. + */ + qcom_geni_serial_poll_tx_done(dev); + qcom_geni_serial_abort_rx(dev); + + writel(UART_PACKING_CFG0, base_address + SE_GENI_TX_PACKING_CFG0); + writel(UART_PACKING_CFG1, base_address + SE_GENI_TX_PACKING_CFG1); + writel(UART_PACKING_CFG0, base_address + SE_GENI_RX_PACKING_CFG0); + writel(UART_PACKING_CFG1, base_address + SE_GENI_RX_PACKING_CFG1); + + writel(tx_trans_cfg, base_address + SE_UART_TX_TRANS_CFG); + writel(tx_parity_cfg, base_address + SE_UART_TX_PARITY_CFG); + writel(rx_trans_cfg, base_address + SE_UART_RX_TRANS_CFG); + writel(rx_parity_cfg, base_address + SE_UART_RX_PARITY_CFG); + writel(bits_per_char, base_address + SE_UART_TX_WORD_LEN); + writel(bits_per_char, base_address + SE_UART_RX_WORD_LEN); + writel(stop_bit_len, base_address + SE_UART_TX_STOP_BIT_LEN); +} + +static int msm_serial_probe(struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + /* No need to reinitialize the UART after relocation */ + if (gd->flags & GD_FLG_RELOC) + return 0; + + geni_serial_init(dev); + msm_geni_serial_setup_rx(dev); + qcom_geni_serial_start_rx(dev); + qcom_geni_serial_start_tx(priv->base); + + return 0; +} + +static int msm_serial_ofdata_to_platdata(struct udevice *dev) +{ + struct msm_serial_data *priv = dev_get_priv(dev); + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + return 0; +} + +static const struct udevice_id msm_serial_ids[] = { + {.compatible = "qcom,msm-geni-uart"}, {}}; + +U_BOOT_DRIVER(serial_msm_geni) = { + .name = "serial_msm_geni", + .id = UCLASS_SERIAL, + .of_match = msm_serial_ids, + .of_to_plat = msm_serial_ofdata_to_platdata, + .priv_auto = sizeof(struct msm_serial_data), + .probe = msm_serial_probe, + .ops = &msm_serial_ops, +}; + +#ifdef CONFIG_DEBUG_UART_MSM_GENI + +static struct msm_serial_data init_serial_data = { + .base = CONFIG_DEBUG_UART_BASE +}; + +/* Serial dumb device, to reuse driver code */ +static struct udevice init_dev = { + .priv_ = &init_serial_data, +}; + +#include + +#define CLK_DIV (CONFIG_DEBUG_UART_CLOCK / \ + (CONFIG_BAUDRATE * UART_OVERSAMPLING)) +#if (CONFIG_DEBUG_UART_CLOCK % (CONFIG_BAUDRATE * UART_OVERSAMPLING) > 0) +#error Clocks cannot be set at early debug. Change CONFIG_BAUDRATE +#endif + +static inline void _debug_uart_init(void) +{ + phys_addr_t base = CONFIG_DEBUG_UART_BASE; + + geni_serial_init(&init_dev); + geni_serial_baud(base, CLK_DIV, CONFIG_BAUDRATE); + qcom_geni_serial_start_tx(base); +} + +static inline void _debug_uart_putc(int ch) +{ + phys_addr_t base = CONFIG_DEBUG_UART_BASE; + + writel(DEF_TX_WM, base + SE_GENI_TX_WATERMARK_REG); + qcom_geni_serial_setup_tx(base, 1); + qcom_geni_serial_poll_bit(&init_dev, SE_GENI_M_IRQ_STATUS, + M_TX_FIFO_WATERMARK_EN, true); + + writel(ch, base + SE_GENI_TX_FIFOn); + writel(M_TX_FIFO_WATERMARK_EN, base + SE_GENI_M_IRQ_CLEAR); + qcom_geni_serial_poll_tx_done(&init_dev); +} + +DEBUG_UART_FUNCS + +#endif -- cgit v1.2.3 From f5a2d6b4b03ae594f485624092f8634b580daa58 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:44:28 +0300 Subject: spmi: msm: add arbiter version 5 support Currently driver supports only version 1 and 2. Version 5 has slightly different registers structure Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried Cc: Tom Rini --- MAINTAINERS | 1 + drivers/spmi/spmi-msm.c | 154 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 105 insertions(+), 50 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 1b3f6c57695..9d8cba90280 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -402,6 +402,7 @@ F: drivers/phy/msm8916-usbh-phy.c F: drivers/serial/serial_msm.c F: drivers/serial/serial_msm_geni.c F: drivers/smem/msm_smem.c +F: drivers/spmi/spmi-msm.c F: drivers/usb/host/ehci-msm.c ARM STI diff --git a/drivers/spmi/spmi-msm.c b/drivers/spmi/spmi-msm.c index 5a335e50aa6..27a035c0a59 100644 --- a/drivers/spmi/spmi-msm.c +++ b/drivers/spmi/spmi-msm.c @@ -19,39 +19,63 @@ DECLARE_GLOBAL_DATA_PTR; /* PMIC Arbiter configuration registers */ -#define PMIC_ARB_VERSION 0x0000 -#define PMIC_ARB_VERSION_V2_MIN 0x20010000 - -#define ARB_CHANNEL_OFFSET(n) (0x4 * (n)) -#define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000) - -#define SPMI_REG_CMD0 0x0 -#define SPMI_REG_CONFIG 0x4 -#define SPMI_REG_STATUS 0x8 -#define SPMI_REG_WDATA 0x10 -#define SPMI_REG_RDATA 0x18 - -#define SPMI_CMD_OPCODE_SHIFT 27 -#define SPMI_CMD_SLAVE_ID_SHIFT 20 -#define SPMI_CMD_ADDR_SHIFT 12 -#define SPMI_CMD_ADDR_OFFSET_SHIFT 4 -#define SPMI_CMD_BYTE_CNT_SHIFT 0 - -#define SPMI_CMD_EXT_REG_WRITE_LONG 0x00 -#define SPMI_CMD_EXT_REG_READ_LONG 0x01 - -#define SPMI_STATUS_DONE 0x1 +#define PMIC_ARB_VERSION 0x0000 +#define PMIC_ARB_VERSION_V2_MIN 0x20010000 +#define PMIC_ARB_VERSION_V3_MIN 0x30000000 +#define PMIC_ARB_VERSION_V5_MIN 0x50000000 + +#define APID_MAP_OFFSET_V1_V2_V3 (0x800) +#define APID_MAP_OFFSET_V5 (0x900) +#define ARB_CHANNEL_OFFSET(n) (0x4 * (n)) +#define SPMI_CH_OFFSET(chnl) ((chnl) * 0x8000) +#define SPMI_V5_OBS_CH_OFFSET(chnl) ((chnl) * 0x80) +#define SPMI_V5_RW_CH_OFFSET(chnl) ((chnl) * 0x10000) + +#define SPMI_REG_CMD0 0x0 +#define SPMI_REG_CONFIG 0x4 +#define SPMI_REG_STATUS 0x8 +#define SPMI_REG_WDATA 0x10 +#define SPMI_REG_RDATA 0x18 + +#define SPMI_CMD_OPCODE_SHIFT 27 +#define SPMI_CMD_SLAVE_ID_SHIFT 20 +#define SPMI_CMD_ADDR_SHIFT 12 +#define SPMI_CMD_ADDR_OFFSET_SHIFT 4 +#define SPMI_CMD_BYTE_CNT_SHIFT 0 + +#define SPMI_CMD_EXT_REG_WRITE_LONG 0x00 +#define SPMI_CMD_EXT_REG_READ_LONG 0x01 + +#define SPMI_STATUS_DONE 0x1 + +#define SPMI_MAX_CHANNELS 128 +#define SPMI_MAX_SLAVES 16 +#define SPMI_MAX_PERIPH 256 + +enum arb_ver { + V1 = 1, + V2, + V3, + V5 = 5 +}; -#define SPMI_MAX_CHANNELS 128 -#define SPMI_MAX_SLAVES 16 -#define SPMI_MAX_PERIPH 256 +/* + * PMIC arbiter version 5 uses different register offsets for read/write vs + * observer channels. + */ +enum pmic_arb_channel { + PMIC_ARB_CHANNEL_RW, + PMIC_ARB_CHANNEL_OBS, +}; struct msm_spmi_priv { - phys_addr_t arb_chnl; /* ARB channel mapping base */ + phys_addr_t arb_chnl; /* ARB channel mapping base */ phys_addr_t spmi_core; /* SPMI core */ - phys_addr_t spmi_obs; /* SPMI observer */ + phys_addr_t spmi_obs; /* SPMI observer */ /* SPMI channel map */ uint8_t channel_map[SPMI_MAX_SLAVES][SPMI_MAX_PERIPH]; + /* SPMI bus arbiter version */ + u32 arb_ver; }; static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, @@ -59,6 +83,7 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, { struct msm_spmi_priv *priv = dev_get_priv(dev); unsigned channel; + unsigned int ch_offset; uint32_t reg = 0; if (usid >= SPMI_MAX_SLAVES) @@ -69,8 +94,8 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, channel = priv->channel_map[usid][pid]; /* Disable IRQ mode for the current channel*/ - writel(0x0, priv->spmi_core + SPMI_CH_OFFSET(channel) + - SPMI_REG_CONFIG); + writel(0x0, + priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG); /* Write single byte */ writel(val, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_WDATA); @@ -82,6 +107,11 @@ static int msm_spmi_write(struct udevice *dev, int usid, int pid, int off, reg |= (off << SPMI_CMD_ADDR_OFFSET_SHIFT); reg |= 1; /* byte count */ + if (priv->arb_ver == V5) + ch_offset = SPMI_V5_RW_CH_OFFSET(channel); + else + ch_offset = SPMI_CH_OFFSET(channel); + /* Send write command */ writel(reg, priv->spmi_core + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0); @@ -104,6 +134,7 @@ static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off) { struct msm_spmi_priv *priv = dev_get_priv(dev); unsigned channel; + unsigned int ch_offset; uint32_t reg = 0; if (usid >= SPMI_MAX_SLAVES) @@ -113,8 +144,13 @@ static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off) channel = priv->channel_map[usid][pid]; + if (priv->arb_ver == V5) + ch_offset = SPMI_V5_OBS_CH_OFFSET(channel); + else + ch_offset = SPMI_CH_OFFSET(channel); + /* Disable IRQ mode for the current channel*/ - writel(0x0, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CONFIG); + writel(0x0, priv->spmi_obs + ch_offset + SPMI_REG_CONFIG); /* Prepare read command */ reg |= SPMI_CMD_EXT_REG_READ_LONG << SPMI_CMD_OPCODE_SHIFT; @@ -124,13 +160,12 @@ static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off) reg |= 1; /* byte count */ /* Request read */ - writel(reg, priv->spmi_obs + SPMI_CH_OFFSET(channel) + SPMI_REG_CMD0); + writel(reg, priv->spmi_obs + ch_offset + SPMI_REG_CMD0); /* Wait till CMD DONE status */ reg = 0; while (!reg) { - reg = readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) + - SPMI_REG_STATUS); + reg = readl(priv->spmi_obs + ch_offset + SPMI_REG_STATUS); } if (reg ^ SPMI_STATUS_DONE) { @@ -139,8 +174,8 @@ static int msm_spmi_read(struct udevice *dev, int usid, int pid, int off) } /* Read the data */ - return readl(priv->spmi_obs + SPMI_CH_OFFSET(channel) + - SPMI_REG_RDATA) & 0xFF; + return readl(priv->spmi_obs + ch_offset + + SPMI_REG_RDATA) & 0xFF; } static struct dm_spmi_ops msm_spmi_ops = { @@ -150,31 +185,50 @@ static struct dm_spmi_ops msm_spmi_ops = { static int msm_spmi_probe(struct udevice *dev) { - struct udevice *parent = dev->parent; struct msm_spmi_priv *priv = dev_get_priv(dev); - int node = dev_of_offset(dev); + phys_addr_t config_addr; u32 hw_ver; - bool is_v1; + u32 version; int i; + int err; + + config_addr = dev_read_addr_index(dev, 0); + priv->spmi_core = dev_read_addr_index(dev, 1); + priv->spmi_obs = dev_read_addr_index(dev, 2); + + hw_ver = readl(config_addr + PMIC_ARB_VERSION); + + if (hw_ver < PMIC_ARB_VERSION_V3_MIN) { + priv->arb_ver = V2; + version = 2; + priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3; + } else if (hw_ver < PMIC_ARB_VERSION_V5_MIN) { + priv->arb_ver = V3; + version = 3; + priv->arb_chnl = config_addr + APID_MAP_OFFSET_V1_V2_V3; + } else { + priv->arb_ver = V5; + version = 5; + priv->arb_chnl = config_addr + APID_MAP_OFFSET_V5; + + if (err) { + dev_err(dev, "could not read APID->PPID mapping table, rc= %d\n", err); + return -1; + } + } - priv->arb_chnl = dev_read_addr(dev); - priv->spmi_core = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - dev_of_offset(parent), node, "reg", 1, NULL, false); - priv->spmi_obs = fdtdec_get_addr_size_auto_parent(gd->fdt_blob, - dev_of_offset(parent), node, "reg", 2, NULL, false); - - hw_ver = readl(priv->arb_chnl + PMIC_ARB_VERSION - 0x800); - is_v1 = (hw_ver < PMIC_ARB_VERSION_V2_MIN); - - dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", (is_v1 ? 1 : 2), hw_ver); + dev_dbg(dev, "PMIC Arb Version-%d (0x%x)\n", version, hw_ver); if (priv->arb_chnl == FDT_ADDR_T_NONE || priv->spmi_core == FDT_ADDR_T_NONE || priv->spmi_obs == FDT_ADDR_T_NONE) return -EINVAL; + dev_dbg(dev, "priv->arb_chnl address (%llu)\n", priv->arb_chnl); + dev_dbg(dev, "priv->spmi_core address (%llu)\n", priv->spmi_core); + dev_dbg(dev, "priv->spmi_obs address (%llu)\n", priv->spmi_obs); /* Scan peripherals connected to each SPMI channel */ - for (i = 0; i < SPMI_MAX_PERIPH ; i++) { + for (i = 0; i < SPMI_MAX_PERIPH; i++) { uint32_t periph = readl(priv->arb_chnl + ARB_CHANNEL_OFFSET(i)); uint8_t slave_id = (periph & 0xf0000) >> 16; uint8_t pid = (periph & 0xff00) >> 8; @@ -195,5 +249,5 @@ U_BOOT_DRIVER(msm_spmi) = { .of_match = msm_spmi_ids, .ops = &msm_spmi_ops, .probe = msm_spmi_probe, - .priv_auto = sizeof(struct msm_spmi_priv), + .priv_auto = sizeof(struct msm_spmi_priv), }; -- cgit v1.2.3 From 7964c30541dfb3411c7aeec94af483185ee58c28 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:44:29 +0300 Subject: pinctrl: qcom: add pinctrl and gpio drivers for SDM845 SoC Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried Cc: Stephan Gerhold [trini: Add CONFIG_SDM845 around sdm845_data usage] --- arch/arm/mach-snapdragon/pinctrl-sdm845.c | 44 +++++++++++++++++++++++++++ arch/arm/mach-snapdragon/pinctrl-snapdragon.c | 3 ++ arch/arm/mach-snapdragon/pinctrl-snapdragon.h | 1 + drivers/gpio/msm_gpio.c | 1 + drivers/gpio/pm8916_gpio.c | 8 +++-- 5 files changed, 54 insertions(+), 3 deletions(-) create mode 100644 arch/arm/mach-snapdragon/pinctrl-sdm845.c diff --git a/arch/arm/mach-snapdragon/pinctrl-sdm845.c b/arch/arm/mach-snapdragon/pinctrl-sdm845.c new file mode 100644 index 00000000000..40f2f012fa0 --- /dev/null +++ b/arch/arm/mach-snapdragon/pinctrl-sdm845.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm SDM845 pinctrl + * + * (C) Copyright 2021 Dzmitry Sankouski + * + */ + +#include "pinctrl-snapdragon.h" +#include + +#define MAX_PIN_NAME_LEN 32 +static char pin_name[MAX_PIN_NAME_LEN] __section(".data"); + +static const struct pinctrl_function msm_pinctrl_functions[] = { + {"qup9", 1}, + {"gpio", 0}, +}; + +static const char *sdm845_get_function_name(struct udevice *dev, + unsigned int selector) +{ + return msm_pinctrl_functions[selector].name; +} + +static const char *sdm845_get_pin_name(struct udevice *dev, + unsigned int selector) +{ + snprintf(pin_name, MAX_PIN_NAME_LEN, "GPIO_%u", selector); + return pin_name; +} + +static unsigned int sdm845_get_function_mux(unsigned int selector) +{ + return msm_pinctrl_functions[selector].val; +} + +struct msm_pinctrl_data sdm845_data = { + .pin_count = 150, + .functions_count = ARRAY_SIZE(msm_pinctrl_functions), + .get_function_name = sdm845_get_function_name, + .get_function_mux = sdm845_get_function_mux, + .get_pin_name = sdm845_get_pin_name, +}; diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c index e6b87c35732..d1c560dd401 100644 --- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.c +++ b/arch/arm/mach-snapdragon/pinctrl-snapdragon.c @@ -116,6 +116,9 @@ static struct pinctrl_ops msm_pinctrl_ops = { static const struct udevice_id msm_pinctrl_ids[] = { { .compatible = "qcom,tlmm-apq8016", .data = (ulong)&apq8016_data }, { .compatible = "qcom,tlmm-apq8096", .data = (ulong)&apq8096_data }, +#ifdef CONFIG_SDM845 + { .compatible = "qcom,tlmm-sdm845", .data = (ulong)&sdm845_data }, +#endif { } }; diff --git a/arch/arm/mach-snapdragon/pinctrl-snapdragon.h b/arch/arm/mach-snapdragon/pinctrl-snapdragon.h index 61d466f4d84..ea524312a04 100644 --- a/arch/arm/mach-snapdragon/pinctrl-snapdragon.h +++ b/arch/arm/mach-snapdragon/pinctrl-snapdragon.h @@ -27,5 +27,6 @@ struct pinctrl_function { extern struct msm_pinctrl_data apq8016_data; extern struct msm_pinctrl_data apq8096_data; +extern struct msm_pinctrl_data sdm845_data; #endif diff --git a/drivers/gpio/msm_gpio.c b/drivers/gpio/msm_gpio.c index e1ff84c1c03..a3c3cd7824c 100644 --- a/drivers/gpio/msm_gpio.c +++ b/drivers/gpio/msm_gpio.c @@ -120,6 +120,7 @@ static const struct udevice_id msm_gpio_ids[] = { { .compatible = "qcom,msm8916-pinctrl" }, { .compatible = "qcom,apq8016-pinctrl" }, { .compatible = "qcom,ipq4019-pinctrl" }, + { .compatible = "qcom,sdm845-pinctrl" }, { } }; diff --git a/drivers/gpio/pm8916_gpio.c b/drivers/gpio/pm8916_gpio.c index 40b0f2578b9..7ad95784a89 100644 --- a/drivers/gpio/pm8916_gpio.c +++ b/drivers/gpio/pm8916_gpio.c @@ -202,6 +202,7 @@ static int pm8916_gpio_of_to_plat(struct udevice *dev) static const struct udevice_id pm8916_gpio_ids[] = { { .compatible = "qcom,pm8916-gpio" }, { .compatible = "qcom,pm8994-gpio" }, /* 22 GPIO's */ + { .compatible = "qcom,pm8998-gpio" }, { } }; @@ -266,7 +267,7 @@ static int pm8941_pwrkey_probe(struct udevice *dev) return log_msg_ret("bad type", -ENXIO); reg = pmic_reg_read(dev->parent, priv->pid + REG_SUBTYPE); - if (reg != 0x1) + if ((reg & 0x5) == 0) return log_msg_ret("bad subtype", -ENXIO); return 0; @@ -287,11 +288,12 @@ static int pm8941_pwrkey_of_to_plat(struct udevice *dev) static const struct udevice_id pm8941_pwrkey_ids[] = { { .compatible = "qcom,pm8916-pwrkey" }, { .compatible = "qcom,pm8994-pwrkey" }, + { .compatible = "qcom,pm8998-pwrkey" }, { } }; -U_BOOT_DRIVER(pwrkey_pm8941) = { - .name = "pwrkey_pm8916", +U_BOOT_DRIVER(pwrkey_pm89xx) = { + .name = "pwrkey_pm89xx", .id = UCLASS_GPIO, .of_match = pm8941_pwrkey_ids, .of_to_plat = pm8941_pwrkey_of_to_plat, -- cgit v1.2.3 From 90496afc27525a9da373f94e84b99bcfd313f2ec Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:44:30 +0300 Subject: clocks: qcom: add clocks for SDM845 debug uart Allows to change clock frequency of debug uart, thus supporting wide range of baudrates. Enable / disable functionality is not implemented yet. In most use cases of SDM845 (i.e. mobile phones and tablets) it's not needed, because qualcomm first stage bootloader leaves it initialized, and on the other hand there's no possibility to replace signed first stage bootloader with u-boot. Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried Cc: Tom Rini --- arch/arm/mach-snapdragon/clock-sdm845.c | 92 +++++++++++++++++++++++++++++ arch/arm/mach-snapdragon/clock-snapdragon.c | 1 + arch/arm/mach-snapdragon/clock-snapdragon.h | 3 +- 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 arch/arm/mach-snapdragon/clock-sdm845.c diff --git a/arch/arm/mach-snapdragon/clock-sdm845.c b/arch/arm/mach-snapdragon/clock-sdm845.c new file mode 100644 index 00000000000..95726392388 --- /dev/null +++ b/arch/arm/mach-snapdragon/clock-sdm845.c @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Clock drivers for Qualcomm SDM845 + * + * (C) Copyright 2017 Jorge Ramirez Ortiz + * (C) Copyright 2021 Dzmitry Sankouski + * + * Based on Little Kernel driver, simplified + */ + +#include +#include +#include +#include +#include +#include +#include "clock-snapdragon.h" + +#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } + +struct freq_tbl { + uint freq; + uint src; + u8 pre_div; + u16 m; + u16 n; +}; + +static const struct freq_tbl ftbl_gcc_qupv3_wrap0_s0_clk_src[] = { + F(7372800, CFG_CLK_SRC_GPLL0_EVEN, 1, 384, 15625), + F(14745600, CFG_CLK_SRC_GPLL0_EVEN, 1, 768, 15625), + F(19200000, CFG_CLK_SRC_CXO, 1, 0, 0), + F(29491200, CFG_CLK_SRC_GPLL0_EVEN, 1, 1536, 15625), + F(32000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 75), + F(48000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 25), + F(64000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 16, 75), + F(80000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 4, 15), + F(96000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 8, 25), + F(100000000, CFG_CLK_SRC_GPLL0_EVEN, 3, 0, 0), + F(102400000, CFG_CLK_SRC_GPLL0_EVEN, 1, 128, 375), + F(112000000, CFG_CLK_SRC_GPLL0_EVEN, 1, 28, 75), + F(117964800, CFG_CLK_SRC_GPLL0_EVEN, 1, 6144, 15625), + F(120000000, CFG_CLK_SRC_GPLL0_EVEN, 2.5, 0, 0), + F(128000000, CFG_CLK_SRC_GPLL0, 1, 16, 75), + { } +}; + +static const struct bcr_regs uart2_regs = { + .cfg_rcgr = SE9_UART_APPS_CFG_RCGR, + .cmd_rcgr = SE9_UART_APPS_CMD_RCGR, + .M = SE9_UART_APPS_M, + .N = SE9_UART_APPS_N, + .D = SE9_UART_APPS_D, +}; + +const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, uint rate) +{ + if (!f) + return NULL; + + if (!f->freq) + return f; + + for (; f->freq; f++) + if (rate <= f->freq) + return f; + + /* Default to our fastest rate */ + return f - 1; +} + +static int clk_init_uart(struct msm_clk_priv *priv, uint rate) +{ + const struct freq_tbl *freq = qcom_find_freq(ftbl_gcc_qupv3_wrap0_s0_clk_src, rate); + + clk_rcg_set_rate_mnd(priv->base, &uart2_regs, + freq->pre_div, freq->m, freq->n, freq->src); + + return 0; +} + +ulong msm_set_rate(struct clk *clk, ulong rate) +{ + struct msm_clk_priv *priv = dev_get_priv(clk->dev); + + switch (clk->id) { + case 0x58: /*UART2*/ + return clk_init_uart(priv, rate); + default: + return 0; + } +} diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.c b/arch/arm/mach-snapdragon/clock-snapdragon.c index 2b76371718c..3deb08ac4a9 100644 --- a/arch/arm/mach-snapdragon/clock-snapdragon.c +++ b/arch/arm/mach-snapdragon/clock-snapdragon.c @@ -135,6 +135,7 @@ static const struct udevice_id msm_clk_ids[] = { { .compatible = "qcom,gcc-apq8016" }, { .compatible = "qcom,gcc-msm8996" }, { .compatible = "qcom,gcc-apq8096" }, + { .compatible = "qcom,gcc-sdm845" }, { } }; diff --git a/arch/arm/mach-snapdragon/clock-snapdragon.h b/arch/arm/mach-snapdragon/clock-snapdragon.h index 58fab40a2e4..2ac53b538dc 100644 --- a/arch/arm/mach-snapdragon/clock-snapdragon.h +++ b/arch/arm/mach-snapdragon/clock-snapdragon.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * Qualcomm APQ8016, APQ8096 + * Qualcomm APQ8016, APQ8096, SDM845 * * (C) Copyright 2017 Jorge Ramirez-Ortiz */ @@ -9,6 +9,7 @@ #define CFG_CLK_SRC_CXO (0 << 8) #define CFG_CLK_SRC_GPLL0 (1 << 8) +#define CFG_CLK_SRC_GPLL0_EVEN (6 << 8) #define CFG_CLK_SRC_MASK (7 << 8) struct pll_vote_clk { -- cgit v1.2.3 From 4cbc16ceb2db5935aede65ac8d52c234809c66d6 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:44:31 +0300 Subject: SoC: qcom: add support for SDM845 Hi-end qualcomm chip, introduced in late 2017. Mostly used in flagship phones and tablets of 2018. Features: - arm64 arch - total of 8 Kryo 385 Gold / Silver cores - Hexagon 685 DSP - Adreno 630 GPU Tested only as second-stage bootloader. Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried Cc: Tom Rini Cc: Stephan Gerhold --- arch/arm/dts/sdm845.dtsi | 116 +++++++++++++++++++++ arch/arm/mach-snapdragon/Kconfig | 4 + arch/arm/mach-snapdragon/Makefile | 4 + .../mach-snapdragon/include/mach/sysmap-sdm845.h | 42 ++++++++ arch/arm/mach-snapdragon/init_sdm845.c | 82 +++++++++++++++ arch/arm/mach-snapdragon/sysmap-sdm845.c | 31 ++++++ include/configs/sdm845.h | 33 ++++++ 7 files changed, 312 insertions(+) create mode 100644 arch/arm/dts/sdm845.dtsi create mode 100644 arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h create mode 100644 arch/arm/mach-snapdragon/init_sdm845.c create mode 100644 arch/arm/mach-snapdragon/sysmap-sdm845.c create mode 100644 include/configs/sdm845.h diff --git a/arch/arm/dts/sdm845.dtsi b/arch/arm/dts/sdm845.dtsi new file mode 100644 index 00000000000..1185b712169 --- /dev/null +++ b/arch/arm/dts/sdm845.dtsi @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm SDM845 chip device tree source + * + * (C) Copyright 2021 Dzmitry Sankouski + * + */ + +/dts-v1/; + +#include "skeleton64.dtsi" + +/ { + soc: soc { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0 0 0xffffffff>; + compatible = "simple-bus"; + + gcc: clock-controller@100000 { + u-boot,dm-pre-reloc; + compatible = "qcom,gcc-sdm845"; + reg = <0x100000 0x1f0000>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + + gpio_north: gpio_north@3900000 { + u-boot,dm-pre-reloc; + #gpio-cells = <2>; + compatible = "qcom,sdm845-pinctrl"; + reg = <0x3900000 0x400000>; + gpio-count = <150>; + gpio-controller; + gpio-ranges = <&gpio_north 0 0 150>; + gpio-bank-name = "soc_north."; + }; + + tlmm_north: pinctrl_north@3900000 { + u-boot,dm-pre-reloc; + compatible = "qcom,tlmm-sdm845"; + reg = <0x3900000 0x400000>; + gpio-count = <150>; + gpio-controller; + #gpio-cells = <2>; + gpio-ranges = <&tlmm_north 0 0 150>; + + /* DEBUG UART */ + qup_uart9: qup-uart9-default { + pinmux { + pins = "GPIO_4", "GPIO_5"; + function = "qup9"; + }; + }; + }; + + debug_uart: serial@a84000 { + compatible = "qcom,msm-geni-uart"; + reg = <0xa84000 0x4000>; + reg-names = "se_phys"; + clock-names = "se-clk"; + clocks = <&gcc 0x58>; + pinctrl-names = "default"; + pinctrl-0 = <&qup_uart9>; + qcom,wrapper-core = <0x8a>; + status = "disabled"; + }; + + spmi@c440000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0xc440000 0x1100>, + <0xc600000 0x2000000>, + <0xe600000 0x100000>; + reg-names = "cnfg", "core", "obsrvr"; + #address-cells = <0x1>; + #size-cells = <0x1>; + + qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + + pmic0: pm8998@0 { + compatible = "qcom,spmi-pmic"; + reg = <0x0 0x1>; + #address-cells = <0x1>; + #size-cells = <0x1>; + + pm8998_pon: pm8998_pon@800 { + compatible = "qcom,pm8998-pwrkey"; + reg = <0x800 0x100>; + #gpio-cells = <2>; + gpio-controller; + gpio-bank-name = "pm8998_key."; + }; + + pm8998_gpios: pm8998_gpios@c000 { + compatible = "qcom,pm8998-gpio"; + reg = <0xc000 0x1a00>; + gpio-controller; + gpio-count = <21>; + #gpio-cells = <2>; + gpio-bank-name = "pm8998."; + }; + }; + + pmic1: pm8998@1 { + compatible = "qcom,spmi-pmic"; + reg = <0x1 0x0>; + #address-cells = <0x2>; + #size-cells = <0x0>; + }; + }; + }; +}; diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index 0ec74fa5d3e..1a6a6089673 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -9,6 +9,10 @@ config SYS_MALLOC_F_LEN config SPL_SYS_MALLOC_F_LEN default 0x2000 +config SDM845 + bool "Qualcomm Snapdragon 845 SoC" + default n + choice prompt "Snapdragon board select" diff --git a/arch/arm/mach-snapdragon/Makefile b/arch/arm/mach-snapdragon/Makefile index 709919fce4c..962855eb8cc 100644 --- a/arch/arm/mach-snapdragon/Makefile +++ b/arch/arm/mach-snapdragon/Makefile @@ -2,6 +2,9 @@ # # (C) Copyright 2015 Mateusz Kulikowski +obj-$(CONFIG_SDM845) += clock-sdm845.o +obj-$(CONFIG_SDM845) += sysmap-sdm845.o +obj-$(CONFIG_SDM845) += init_sdm845.o obj-$(CONFIG_TARGET_DRAGONBOARD820C) += clock-apq8096.o obj-$(CONFIG_TARGET_DRAGONBOARD820C) += sysmap-apq8096.o obj-$(CONFIG_TARGET_DRAGONBOARD410C) += clock-apq8016.o @@ -12,3 +15,4 @@ obj-y += dram.o obj-y += pinctrl-snapdragon.o obj-y += pinctrl-apq8016.o obj-y += pinctrl-apq8096.o +obj-$(CONFIG_SDM845) += pinctrl-sdm845.o diff --git a/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h b/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h new file mode 100644 index 00000000000..7165985bcd1 --- /dev/null +++ b/arch/arm/mach-snapdragon/include/mach/sysmap-sdm845.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Qualcomm SDM845 sysmap + * + * (C) Copyright 2021 Dzmitry Sankouski + */ +#ifndef _MACH_SYSMAP_SDM845_H +#define _MACH_SYSMAP_SDM845_H + +#define TLMM_BASE_ADDR (0x1010000) + +/* Strength (sdc1) */ +#define SDC1_HDRV_PULL_CTL_REG (TLMM_BASE_ADDR + 0x0012D000) + +/* Clocks: (from CLK_CTL_BASE) */ +#define GPLL0_STATUS (0x0000) +#define APCS_GPLL_ENA_VOTE (0x52000) +#define APCS_CLOCK_BRANCH_ENA_VOTE (0x52004) + +#define SDCC2_BCR (0x14000) /* block reset */ +#define SDCC2_APPS_CBCR (0x14004) /* branch control */ +#define SDCC2_AHB_CBCR (0x14008) +#define SDCC2_CMD_RCGR (0x1400c) +#define SDCC2_CFG_RCGR (0x14010) +#define SDCC2_M (0x14014) +#define SDCC2_N (0x14018) +#define SDCC2_D (0x1401C) + +#define RCG2_CFG_REG 0x4 +#define M_REG 0x8 +#define N_REG 0xc +#define D_REG 0x10 + +#define SE9_AHB_CBCR (0x25004) +#define SE9_UART_APPS_CBCR (0x29004) +#define SE9_UART_APPS_CMD_RCGR (0x18148) +#define SE9_UART_APPS_CFG_RCGR (0x1814C) +#define SE9_UART_APPS_M (0x18150) +#define SE9_UART_APPS_N (0x18154) +#define SE9_UART_APPS_D (0x18158) + +#endif diff --git a/arch/arm/mach-snapdragon/init_sdm845.c b/arch/arm/mach-snapdragon/init_sdm845.c new file mode 100644 index 00000000000..5f53c219471 --- /dev/null +++ b/arch/arm/mach-snapdragon/init_sdm845.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Common init part for boards based on SDM845 + * + * (C) Copyright 2021 Dzmitry Sankouski + */ + +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +int dram_init(void) +{ + return fdtdec_setup_mem_size_base(); +} + +void reset_cpu(void) +{ + psci_system_reset(); +} + +__weak int board_init(void) +{ + return 0; +} + +/* Check for vol- and power buttons */ +__weak int misc_init_r(void) +{ + struct udevice *pon; + struct gpio_desc resin; + int node, ret; + + ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8998_pon@800", &pon); + if (ret < 0) { + printf("Failed to find PMIC pon node. Check device tree\n"); + return 0; + } + + node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), + "key_vol_down"); + if (node < 0) { + printf("Failed to find key_vol_down node. Check device tree\n"); + return 0; + } + if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, + &resin, 0)) { + printf("Failed to request key_vol_down button.\n"); + return 0; + } + if (dm_gpio_get_value(&resin)) { + env_set("key_vol_down", "1"); + printf("Volume down button pressed\n"); + } else { + env_set("key_vol_down", "0"); + } + + node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), + "key_power"); + if (node < 0) { + printf("Failed to find key_power node. Check device tree\n"); + return 0; + } + if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, + &resin, 0)) { + printf("Failed to request key_power button.\n"); + return 0; + } + if (dm_gpio_get_value(&resin)) { + env_set("key_power", "1"); + printf("Power button pressed\n"); + } else { + env_set("key_power", "0"); + } + + return 0; +} diff --git a/arch/arm/mach-snapdragon/sysmap-sdm845.c b/arch/arm/mach-snapdragon/sysmap-sdm845.c new file mode 100644 index 00000000000..721ac411665 --- /dev/null +++ b/arch/arm/mach-snapdragon/sysmap-sdm845.c @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Qualcomm SDM845 memory map + * + * (C) Copyright 2021 Dzmitry Sankouski + */ + +#include +#include + +static struct mm_region sdm845_mem_map[] = { + { + .virt = 0x0UL, /* Peripheral block */ + .phys = 0x0UL, /* Peripheral block */ + .size = 0x10000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN + }, { + .virt = 0x80000000UL, /* DDR */ + .phys = 0x80000000UL, /* DDR */ + .size = 0x200000000UL, /* 8GiB - maximum allowed memory */ + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE + }, { + /* List terminator */ + 0, + } +}; + +struct mm_region *mem_map = sdm845_mem_map; diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h new file mode 100644 index 00000000000..c77d0acac6b --- /dev/null +++ b/include/configs/sdm845.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Configuration file for boards, based on Qualcomm SDM845 chip + * + * (C) Copyright 2021 Dzmitry Sankouski + */ + +#ifndef __CONFIGS_SDM845_H +#define __CONFIGS_SDM845_H + +#include +#include + +#define CONFIG_SYS_LOAD_ADDR 0x80000000 +#define CONFIG_SYS_BAUDRATE_TABLE { 115200, 230400, 460800, 921600 } + +/* Generic Timer Definitions */ +#define COUNTER_FREQUENCY 19000000 + +#define EXTRA_ENV_SETTINGS \ + +#define CONFIG_EXTRA_ENV_SETTINGS \ + "loadaddr=0x80000000\0" + +/* Size of malloc() pool */ +#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + SZ_8M) +#define CONFIG_SYS_BOOTM_LEN SZ_64M + +/* Monitor Command Prompt */ +#define CONFIG_SYS_CBSIZE 512 +#define CONFIG_SYS_MAXARGS 64 + +#endif -- cgit v1.2.3 From 80565ec6f0c666e70b0fedd63617f0811c9fcfa7 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:44:32 +0300 Subject: board: samsung: add Samsung Galaxy S9/S9+(SM-G96x0) board Samsung S9 SM-G9600 - Snapdragon SDM845 version of the phone, for China \ Hong Kong markets. Has unlockable bootloader, unlike SM-G960U (American market version), which allows running u-boot as a chain-loaded bootloader. Signed-off-by: Dzmitry Sankouski Cc: Ramon Fried Cc: Tom Rini --- arch/arm/dts/Makefile | 1 + arch/arm/dts/starqltechn-uboot.dtsi | 39 ++++++++++++++++++++++++ arch/arm/dts/starqltechn.dts | 53 +++++++++++++++++++++++++++++++++ arch/arm/mach-snapdragon/Kconfig | 17 +++++++++++ board/samsung/starqltechn/Kconfig | 22 ++++++++++++++ board/samsung/starqltechn/MAINTAINERS | 6 ++++ board/samsung/starqltechn/Makefile | 9 ++++++ board/samsung/starqltechn/starqltechn.c | 10 +++++++ configs/starqltechn_defconfig | 24 +++++++++++++++ doc/board/qualcomm/index.rst | 1 + doc/board/qualcomm/sdm845.rst | 38 +++++++++++++++++++++++ include/configs/sdm845.h | 7 ----- 12 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 arch/arm/dts/starqltechn-uboot.dtsi create mode 100644 arch/arm/dts/starqltechn.dts create mode 100644 board/samsung/starqltechn/Kconfig create mode 100644 board/samsung/starqltechn/MAINTAINERS create mode 100644 board/samsung/starqltechn/Makefile create mode 100644 board/samsung/starqltechn/starqltechn.c create mode 100644 configs/starqltechn_defconfig create mode 100644 doc/board/qualcomm/sdm845.rst diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index a7222cc2726..fdf85da9c02 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -477,6 +477,7 @@ dtb-$(CONFIG_TARGET_SL28) += fsl-ls1028a-kontron-sl28.dtb \ dtb-$(CONFIG_TARGET_DRAGONBOARD410C) += dragonboard410c.dtb dtb-$(CONFIG_TARGET_DRAGONBOARD820C) += dragonboard820c.dtb +dtb-$(CONFIG_TARGET_STARQLTECHN) += starqltechn.dtb dtb-$(CONFIG_TARGET_STEMMY) += ste-ux500-samsung-stemmy.dtb diff --git a/arch/arm/dts/starqltechn-uboot.dtsi b/arch/arm/dts/starqltechn-uboot.dtsi new file mode 100644 index 00000000000..d8d75e018a2 --- /dev/null +++ b/arch/arm/dts/starqltechn-uboot.dtsi @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * U-Boot addition to handle Samsung S9 SM-G9600 (starqltechn) pins + * + * (C) Copyright 2021 Dzmitry Sankouski + * + */ + +/ +{ + soc { + u-boot,dm-pre-reloc; + gcc { + clock-controller@100000 { + u-boot,dm-pre-reloc; + }; + serial@0xa84000 { + u-boot,dm-pre-reloc; + }; + gpio_north@3900000 { + u-boot,dm-pre-reloc; + }; + pinctrl@3900000 { + u-boot,dm-pre-reloc; + }; + }; + }; +}; + +&pm8998_pon { + key_vol_down { + gpios = <&pm8998_pon 1 0>; + label = "key_vol_down"; + }; + key_power { + gpios = <&pm8998_pon 0 0>; + label = "key_power"; + }; +}; diff --git a/arch/arm/dts/starqltechn.dts b/arch/arm/dts/starqltechn.dts new file mode 100644 index 00000000000..387420f30b5 --- /dev/null +++ b/arch/arm/dts/starqltechn.dts @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung S9 SM-G9600 (starqltechn) board device tree source + * + * (C) Copyright 2021 Dzmitry Sankouski + * + */ + +/dts-v1/; + +#include "sdm845.dtsi" + +/ { + model = "Samsung S9 (SM-G9600)"; + compatible = "qcom,sdm845-mtp", "qcom,sdm845", "qcom,mtp"; + #address-cells = <2>; + #size-cells = <2>; + + chosen { + stdout-path = "serial0:921600n8"; + }; + + aliases { + serial0 = &debug_uart; + }; + + memory { + device_type = "memory"; + reg = <0 0x80000000 0 0xfe1bffff>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + soc: soc { + serial@0xa84000 { + status = "ok"; + }; + + pinctrl@3900000 { + muic_i2c: muic_i2c { + pins = "GPIO_33", "GPIO_34"; + drive-strength = <0x2>; + function = "gpio"; + bias-disable; + }; + }; + }; +}; + +#include "starqltechn-uboot.dtsi" diff --git a/arch/arm/mach-snapdragon/Kconfig b/arch/arm/mach-snapdragon/Kconfig index 1a6a6089673..12cf02a56aa 100644 --- a/arch/arm/mach-snapdragon/Kconfig +++ b/arch/arm/mach-snapdragon/Kconfig @@ -12,6 +12,10 @@ config SPL_SYS_MALLOC_F_LEN config SDM845 bool "Qualcomm Snapdragon 845 SoC" default n + select LINUX_KERNEL_IMAGE_HEADER + +config LNX_KRNL_IMG_TEXT_OFFSET_BASE + default 0x80000000 choice prompt "Snapdragon board select" @@ -40,9 +44,22 @@ config TARGET_DRAGONBOARD820C - 3GiB RAM - 32GiB UFS drive +config TARGET_STARQLTECHN + bool "Samsung S9 SM-G9600(starqltechn)" + help + Support for Samsung S9 SM-G9600(starqltechn) board. + Features: + - Qualcomm Snapdragon SDM845 SoC + - 4GiB RAM + - 64GiB UFS drive + select MISC_INIT_R + select SDM845 + select DM_ETH if NET + endchoice source "board/qualcomm/dragonboard410c/Kconfig" source "board/qualcomm/dragonboard820c/Kconfig" +source "board/samsung/starqltechn/Kconfig" endif diff --git a/board/samsung/starqltechn/Kconfig b/board/samsung/starqltechn/Kconfig new file mode 100644 index 00000000000..0eea666d035 --- /dev/null +++ b/board/samsung/starqltechn/Kconfig @@ -0,0 +1,22 @@ +if TARGET_STARQLTECHN + +config SYS_BOARD + default "starqltechn" + help + starqltechn is a production board for S9 and S9+ phones(SM-G96x0) phones based on SDM845 SoC. + +config SYS_CONFIG_NAME + string "Board configuration name" + default "sdm845" + help + This option contains information about board configuration name. + Based on this option include/configs/.h header + will be used for board configuration. + +config SYS_VENDOR + default "samsung" + +config SYS_CONFIG_NAME + default "starqltechn" + +endif diff --git a/board/samsung/starqltechn/MAINTAINERS b/board/samsung/starqltechn/MAINTAINERS new file mode 100644 index 00000000000..135cafdd69c --- /dev/null +++ b/board/samsung/starqltechn/MAINTAINERS @@ -0,0 +1,6 @@ +Samsung S9 (SM-G9600)(starqltechn) Board +M: Dzmitry Sankouski +S: Maintained +F: board/samsung/starqltechn/ +F: include/configs/starqltechn.h +F: configs/starqltechn_defconfig diff --git a/board/samsung/starqltechn/Makefile b/board/samsung/starqltechn/Makefile new file mode 100644 index 00000000000..c38c0b47109 --- /dev/null +++ b/board/samsung/starqltechn/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# (C) Copyright 2021 Dzmitry Sankouski +# +# This empty file prevents make error. +# Board logic defined in board/qualcomm/common/sdm845.c, no custom logic for starqltechn so far. +# + +obj-y += starqltechn.o diff --git a/board/samsung/starqltechn/starqltechn.c b/board/samsung/starqltechn/starqltechn.c new file mode 100644 index 00000000000..f2cdb4eec2c --- /dev/null +++ b/board/samsung/starqltechn/starqltechn.c @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * This empty file prevents make linking error. + * No custom logic for starqltechn so far. + * + * (C) Copyright 2021 Dzmitry Sankouski + * + */ + +void nooop(void) {} diff --git a/configs/starqltechn_defconfig b/configs/starqltechn_defconfig new file mode 100644 index 00000000000..f57bb859ccb --- /dev/null +++ b/configs/starqltechn_defconfig @@ -0,0 +1,24 @@ +CONFIG_ARM=y +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_POSITION_INDEPENDENT=y +CONFIG_ARCH_SNAPDRAGON=y +CONFIG_SYS_TEXT_BASE=0x80000000 +CONFIG_SYS_MALLOC_LEN=0x81f000 +CONFIG_DEFAULT_DEVICE_TREE="starqltechn" +CONFIG_TARGET_STARQLTECHN=y +CONFIG_IDENT_STRING="\nSamsung S9 SM-G9600" +CONFIG_SYS_LOAD_ADDR=0x80000000 +CONFIG_USE_PREBOOT=y +# CONFIG_DISPLAY_CPUINFO is not set +CONFIG_HUSH_PARSER=y +CONFIG_CMD_GPIO=y +# CONFIG_NET is not set +# CONFIG_DM_STDIO is not set +CONFIG_CLK=y +CONFIG_MSM_GPIO=y +CONFIG_PM8916_GPIO=y +CONFIG_PINCTRL=y +CONFIG_DM_PMIC=y +CONFIG_PMIC_PM8916=y +CONFIG_MSM_GENI_SERIAL=y +CONFIG_SPMI_MSM=y diff --git a/doc/board/qualcomm/index.rst b/doc/board/qualcomm/index.rst index f7e0aa92986..10b98214e96 100644 --- a/doc/board/qualcomm/index.rst +++ b/doc/board/qualcomm/index.rst @@ -7,3 +7,4 @@ Qualcomm :maxdepth: 2 dragonboard410c + sdm845 diff --git a/doc/board/qualcomm/sdm845.rst b/doc/board/qualcomm/sdm845.rst new file mode 100644 index 00000000000..cd46cbe9cf1 --- /dev/null +++ b/doc/board/qualcomm/sdm845.rst @@ -0,0 +1,38 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Dzmitry Sankouski + +Snapdragon 845 +================ + +About this +---------- +This document describes the information about Qualcomm Snapdragon 845 +supported boards and it's usage steps. + +SDM845 - hi-end qualcomm chip, introduced in late 2017. +Mostly used in flagship phones and tablets of 2018. + +U-Boot can be used as a replacement for Qualcomm's original ABL (UEFI) bootloader. +It is loaded as an Android boot image through ABL + +Installation +------------ +First, setup ``CROSS_COMPILE`` for aarch64. Then, build U-Boot for your board:: + + $ export CROSS_COMPILE= + $ make _defconfig + $ make + +This will build ``u-boot.bin`` in the configured output directory. + +Boards +------------ +starqlte +^^^^^^^^^^^^ + +The starqltechn is a production board for Samsung S9 (SM-G9600) phone, +based on the Qualcomm SDM845 SoC. + +More information can be found on the `Samsung S9 page`_. + +.. _Samsung S9 page: https://en.wikipedia.org/wiki/Samsung_Galaxy_S9 diff --git a/include/configs/sdm845.h b/include/configs/sdm845.h index c77d0acac6b..af9ba197d49 100644 --- a/include/configs/sdm845.h +++ b/include/configs/sdm845.h @@ -11,19 +11,12 @@ #include #include -#define CONFIG_SYS_LOAD_ADDR 0x80000000 #define CONFIG_SYS_BAUDRATE_TABLE { 115200, 230400, 460800, 921600 } /* Generic Timer Definitions */ #define COUNTER_FREQUENCY 19000000 -#define EXTRA_ENV_SETTINGS \ - -#define CONFIG_EXTRA_ENV_SETTINGS \ - "loadaddr=0x80000000\0" - /* Size of malloc() pool */ -#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + SZ_8M) #define CONFIG_SYS_BOOTM_LEN SZ_64M /* Monitor Command Prompt */ -- cgit v1.2.3 From 85fcf9416032dea49c3a82816f03e528019dea9e Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:45:39 +0300 Subject: serial: samsung: add support for skip debug init in s5p Signed-off-by: Dzmitry Sankouski Cc: Minkyu Kang --- drivers/serial/serial_s5p.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/serial/serial_s5p.c b/drivers/serial/serial_s5p.c index 53a7b0bd1bd..de420d2d945 100644 --- a/drivers/serial/serial_s5p.c +++ b/drivers/serial/serial_s5p.c @@ -273,6 +273,9 @@ U_BOOT_DRIVER(serial_s5p) = { static inline void _debug_uart_init(void) { + if (IS_ENABLED(CONFIG_DEBUG_UART_SKIP_INIT)) + return; + struct s5p_uart *uart = (struct s5p_uart *)CONFIG_DEBUG_UART_BASE; s5p_serial_init(uart); -- cgit v1.2.3 From d8428f73c34b6edb322d7736741d069a81919ef6 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:45:40 +0300 Subject: pinctrl: exynos: add support for multiple pin banks Iterate all pin banks to find a pin Signed-off-by: Dzmitry Sankouski Cc: Minkyu Kang --- drivers/pinctrl/exynos/pinctrl-exynos.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/drivers/pinctrl/exynos/pinctrl-exynos.c b/drivers/pinctrl/exynos/pinctrl-exynos.c index 2640c8fcefc..898185479ba 100644 --- a/drivers/pinctrl/exynos/pinctrl-exynos.c +++ b/drivers/pinctrl/exynos/pinctrl-exynos.c @@ -5,6 +5,7 @@ * Thomas Abraham */ +#include #include #include #include @@ -38,9 +39,9 @@ static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name, u32 *pin) { struct exynos_pinctrl_priv *priv = dev_get_priv(dev); - const struct samsung_pin_ctrl *pin_ctrl = priv->pin_ctrl; - const struct samsung_pin_bank_data *bank_data = pin_ctrl->pin_banks; - u32 nr_banks = pin_ctrl->nr_banks, idx = 0; + const struct samsung_pin_ctrl *pin_ctrl_array = priv->pin_ctrl; + const struct samsung_pin_bank_data *bank_data; + u32 nr_banks, pin_ctrl_idx = 0, idx = 0, bank_base; char bank[10]; /* @@ -55,11 +56,26 @@ static unsigned long pin_to_bank_base(struct udevice *dev, const char *pin_name, *pin = pin_name[++idx] - '0'; /* lookup the pin bank data using the pin bank name */ - for (idx = 0; idx < nr_banks; idx++) - if (!strcmp(bank, bank_data[idx].name)) + while (true) { + const struct samsung_pin_ctrl *pin_ctrl = &pin_ctrl_array[pin_ctrl_idx]; + + nr_banks = pin_ctrl->nr_banks; + if (!nr_banks) break; - return priv->base + bank_data[idx].offset; + bank_data = pin_ctrl->pin_banks; + for (idx = 0; idx < nr_banks; idx++) { + debug("pinctrl[%d] bank_data[%d] name is: %s\n", + pin_ctrl_idx, idx, bank_data[idx].name); + if (!strcmp(bank, bank_data[idx].name)) { + bank_base = priv->base + bank_data[idx].offset; + break; + } + } + pin_ctrl_idx++; + } + + return bank_base; } /** -- cgit v1.2.3 From 69bde0410a9ce5749a4cab5ed134527c2cb8b9e4 Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:45:41 +0300 Subject: SoC: exynos: add support for exynos 78x0 Samsung Exynos 7880 \ 7870 - SoC for mainstream smartphones and tablets introduced on March 2017. Features: - 8 Cortex A53 cores - ARM Mali-T830 MP3 GPU - LTE Cat. 7 (7880) or 6 (7870) modem Signed-off-by: Dzmitry Sankouski Cc: Minkyu Kang --- arch/arm/dts/exynos78x0-gpio.dtsi | 204 ++++++++++++++++++++ arch/arm/dts/exynos78x0-pinctrl.dtsi | 280 ++++++++++++++++++++++++++++ arch/arm/dts/exynos78x0.dtsi | 98 ++++++++++ arch/arm/mach-exynos/mmu-arm64.c | 66 +++++++ drivers/gpio/s5p_gpio.c | 1 + drivers/pinctrl/exynos/Kconfig | 8 + drivers/pinctrl/exynos/Makefile | 1 + drivers/pinctrl/exynos/pinctrl-exynos78x0.c | 119 ++++++++++++ include/configs/exynos78x0-common.h | 112 +++++++++++ 9 files changed, 889 insertions(+) create mode 100644 arch/arm/dts/exynos78x0-gpio.dtsi create mode 100644 arch/arm/dts/exynos78x0-pinctrl.dtsi create mode 100644 arch/arm/dts/exynos78x0.dtsi create mode 100644 drivers/pinctrl/exynos/pinctrl-exynos78x0.c create mode 100644 include/configs/exynos78x0-common.h diff --git a/arch/arm/dts/exynos78x0-gpio.dtsi b/arch/arm/dts/exynos78x0-gpio.dtsi new file mode 100644 index 00000000000..a7f75c5ca99 --- /dev/null +++ b/arch/arm/dts/exynos78x0-gpio.dtsi @@ -0,0 +1,204 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung's Exynos7880 SoC pin-mux and pin-config device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/ { + /* ALIVE */ + gpio@139F0000 { + etc0: etc0 { + gpio-controller; + #gpio-cells = <2>; + }; + + etc1: etc1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpa0: gpa0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpa1: gpa1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpa2: gpa2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpa3: gpa3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpq0: gpq0 { + gpio-controller; + #gpio-cells = <2>; + }; + }; + + /* CCORE */ + gpio@10630000 { + gpm0: gpm0 { + gpio-controller; + #gpio-cells = <2>; + }; + }; + + /* DISP/AUD */ + gpio@148C0000 { + gpz0: gpz0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpz1: gpz1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpz2: gpz2 { + gpio-controller; + #gpio-cells = <2>; + }; + }; + + /* FSYS0 */ + gpio@13750000 { + gpr0: gpr0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpr1: gpr1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpr2: gpr2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpr3: gpr3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpr4: gpr4 { + gpio-controller; + #gpio-cells = <2>; + }; + }; + + /* TOP */ + gpio@139B0000 { + gpb0: gpb0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc0: gpc0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc1: gpc1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc4: gpc4 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc5: gpc5 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc6: gpc6 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc8: gpc8 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpc9: gpc9 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpd1: gpd1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpd2: gpd2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpd3: gpd3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpd4: gpd4 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpd5: gpd5 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpe0: gpe0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpf0: gpf0 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpf1: gpf1 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpf2: gpf2 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpf3: gpf3 { + gpio-controller; + #gpio-cells = <2>; + }; + + gpf4: gpf4 { + gpio-controller; + #gpio-cells = <2>; + }; + }; +}; diff --git a/arch/arm/dts/exynos78x0-pinctrl.dtsi b/arch/arm/dts/exynos78x0-pinctrl.dtsi new file mode 100644 index 00000000000..4958c55119c --- /dev/null +++ b/arch/arm/dts/exynos78x0-pinctrl.dtsi @@ -0,0 +1,280 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung's Exynos7880 SoC pin-mux and pin-config device tree source + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * http://www.samsung.com + * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com) + * + * Samsung's Exynos7880 SoC pin-mux and pin-config options are listed as device + * tree nodes are listed in this file. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +/ { + /* ALIVE */ + pinctrl@139F0000 { + uart2_bus: uart2-bus { + samsung,pins = "gpa1-1", "gpa1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + }; + + dwmmc2_cd_ext_irq: dwmmc2_cd_ext_irq { + samsung,pins = "gpa3-3"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <4>; + }; + + key_power: key-power { + samsung,pins = "gpa0-0"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + key_voldown: key-voldown { + samsung,pins = "gpa2-1"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + key_volup: key-volup { + samsung,pins = "gpa2-0"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + key_home: key-home { + samsung,pins = "gpa1-7"; + samsung,pin-function = <0xf>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + }; + + /* TOP */ + pinctrl@139B0000 { + i2c0_bus: i2c0-bus { + samsung,pins = "gpc1-1", "gpc1-0"; + samsung,pin-function = <2>; + }; + + sd0_rst: sd0_rst { + samsung,pins = "gpc0-2"; + samsung,pin-function = <0>; + }; + }; + + /* DISP/AUD */ + pinctrl@148C0000 { + i2s_pmic_bus: i2s-pmic-bus { + samsung,pins = "gpz1-0", "gpz1-1", "gpz1-2", "gpz1-3", "gpz1-4"; + samsung,pin-function = <2>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + + i2s_pmic_bus_idle: i2s-pmic-bus_idle { + samsung,pins = "gpz1-0", "gpz1-1", "gpz1-2", "gpz1-3", "gpz1-4"; + samsung,pin-function = <0>; + samsung,pin-pud = <1>; + samsung,pin-drv = <0>; + }; + }; + + /* FSYS0 */ + pinctrl@13750000 { + sd0_clk: sd0-clk { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd0_cmd: sd0-cmd { + samsung,pins = "gpr0-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd0_rdqs: sd0-rdqs { + samsung,pins = "gpr0-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd0_clk_fast_slew_rate_1x: sd0-clk_fast_slew_rate_1x { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd0_clk_fast_slew_rate_2x: sd0-clk_fast_slew_rate_2x { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <1>; + }; + + sd0_clk_fast_slew_rate_3x: sd0-clk_fast_slew_rate_3x { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd0_clk_fast_slew_rate_4x: sd0-clk_fast_slew_rate_4x { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + + sd0_clk_fast_slew_rate_5x: sd0-clk_fast_slew_rate_5x { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <4>; + }; + + sd0_clk_fast_slew_rate_6x: sd0-clk_fast_slew_rate_6x { + samsung,pins = "gpr0-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <5>; + }; + + sd0_bus1: sd0-bus-width1 { + samsung,pins = "gpr1-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd0_bus4: sd0-bus-width4 { + samsung,pins = "gpr1-1", "gpr1-2", "gpr1-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd0_bus8: sd0-bus-width8 { + samsung,pins = "gpr1-4", "gpr1-5", "gpr1-6", "gpr1-7"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd1_clk: sd1-clk { + samsung,pins = "gpr2-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd1_cmd: sd1-cmd { + samsung,pins = "gpr2-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd1_bus1: sd1-bus-width1 { + samsung,pins = "gpr3-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + samsung,pin-con-pdn = <2>; + samsung,pin-pud-pdn = <3>; + }; + + sd1_bus4: sd1-bus-width4 { + samsung,pins = "gpr3-1", "gpr3-2", "gpr3-3"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + samsung,pin-con-pdn = <2>; + samsung,pin-pud-pdn = <3>; + }; + + sd2_clk: sd2-clk { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd2_cmd: sd2-cmd { + samsung,pins = "gpr4-1"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd2_bus1: sd2-bus-width1 { + samsung,pins = "gpr4-2"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd2_bus4: sd2-bus-width4 { + samsung,pins = "gpr4-3", "gpr4-4", "gpr4-5"; + samsung,pin-function = <2>; + samsung,pin-pud = <3>; + samsung,pin-drv = <2>; + }; + + sd2_clk_output: sd2-clk-output { + samsung,pins = "gpr4-0"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd2_cmd_output: sd2-cmd-output { + samsung,pins = "gpr4-1"; + samsung,pin-function = <1>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd2_clk_fast_slew_rate_1x: sd2-clk_fast_slew_rate_1x { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <0>; + }; + + sd2_clk_fast_slew_rate_2x: sd2-clk_fast_slew_rate_2x { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <1>; + }; + + sd2_clk_fast_slew_rate_3x: sd2-clk_fast_slew_rate_3x { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <2>; + }; + + sd2_clk_fast_slew_rate_4x: sd2-clk_fast_slew_rate_4x { + samsung,pins = "gpr4-0"; + samsung,pin-function = <2>; + samsung,pin-pud = <0>; + samsung,pin-drv = <3>; + }; + }; +}; diff --git a/arch/arm/dts/exynos78x0.dtsi b/arch/arm/dts/exynos78x0.dtsi new file mode 100644 index 00000000000..fb9c9cbdf90 --- /dev/null +++ b/arch/arm/dts/exynos78x0.dtsi @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung Exynos7880 SoC device tree source + * + * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com) + */ + +/dts-v1/; +#include "skeleton.dtsi" +#include "exynos78x0-pinctrl.dtsi" +#include "exynos78x0-gpio.dtsi" +/ { + compatible = "samsung,exynos7880"; + + fin_pll: xxti { + compatible = "fixed-clock"; + clock-output-names = "fin_pll"; + u-boot,dm-pre-reloc; + #clock-cells = <0>; + }; + + /* Dummy clock for uart */ + fin_uart: uart_dummy_fin { + compatible = "fixed-clock"; + clock-output-names = "fin_uart"; + clock-frequency = <132710400>; + u-boot,dm-pre-reloc; + #clock-cells = <0>; + }; + + uart2: serial@13820000 { + compatible = "samsung,exynos4210-uart"; + reg = <0x13820000 0x100>; + u-boot,dm-pre-reloc; + clocks = <&fin_uart>, <&fin_uart>; // driver uses 1st clock + clock-names = "uart", "clk_uart_baud0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart2_bus>; + }; + + gpioi2c0: i2c-0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "i2c-gpio"; + status = "disabled"; + gpios = < + &gpc1 0 0 /* sda */ + &gpc1 1 0 /* scl */ + >; + i2c-gpio,delay-us = <5>; + + s2mu004@3d { + compatible = "samsung,s2mu004mfd"; + }; + }; + + /* ALIVE */ + pinctrl_0: pinctrl@139F0000 { + compatible = "samsung,exynos78x0-pinctrl"; + reg = <0x139F0000 0x1000>; + }; + + /* DISP/AUD */ + pinctrl_2: pinctrl@148C0000 { + compatible = "samsung,exynos78x0-pinctrl"; + reg = <0x148C0000 0x1000>; + }; + + /* FSYS0 */ + pinctrl_4: pinctrl@13750000 { + compatible = "samsung,exynos78x0-pinctrl"; + reg = <0x13750000 0x1000>; + }; + + /* ALIVE */ + gpio_0: gpio@139F0000 { + compatible = "samsung,exynos78x0-gpio"; + reg = <0x139F0000 0x1000>; + }; + + /* DISP/AUD */ + gpio_2: gpio@148C0000 { + compatible = "samsung,exynos78x0-gpio"; + reg = <0x148C0000 0x1000>; + }; + + /* FSYS0 */ + gpio_4: gpio@13750000 { + compatible = "samsung,exynos78x0-gpio"; + reg = <0x13750000 0x1000>; + }; + + /* TOP */ + gpio_6: gpio@139B0000 { + compatible = "samsung,exynos78x0-gpio"; + reg = <0x139B0000 0x1000>; + }; +}; diff --git a/arch/arm/mach-exynos/mmu-arm64.c b/arch/arm/mach-exynos/mmu-arm64.c index 46b8169d19d..e3bd995143a 100644 --- a/arch/arm/mach-exynos/mmu-arm64.c +++ b/arch/arm/mach-exynos/mmu-arm64.c @@ -29,3 +29,69 @@ static struct mm_region exynos7420_mem_map[] = { struct mm_region *mem_map = exynos7420_mem_map; #endif + +#ifdef CONFIG_EXYNOS7870 +static struct mm_region exynos7870_mem_map[] = { + { + .virt = 0x10000000UL, + .phys = 0x10000000UL, + .size = 0x10000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, + { + .virt = 0x40000000UL, + .phys = 0x40000000UL, + .size = 0x3E400000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, + { + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x40000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, + + { + /* List terminator */ + }, +}; + +struct mm_region *mem_map = exynos7870_mem_map; +#endif + +#ifdef CONFIG_EXYNOS7880 +static struct mm_region exynos7880_mem_map[] = { + { + .virt = 0x10000000UL, + .phys = 0x10000000UL, + .size = 0x10000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | + PTE_BLOCK_NON_SHARE | + PTE_BLOCK_PXN | PTE_BLOCK_UXN, + }, + { + .virt = 0x40000000UL, + .phys = 0x40000000UL, + .size = 0x3E400000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, + { + .virt = 0x80000000UL, + .phys = 0x80000000UL, + .size = 0x80000000UL, + .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | + PTE_BLOCK_INNER_SHARE, + }, + + { + /* List terminator */ + }, +}; + +struct mm_region *mem_map = exynos7880_mem_map; +#endif diff --git a/drivers/gpio/s5p_gpio.c b/drivers/gpio/s5p_gpio.c index 76f35ac5d92..06ed585f3d6 100644 --- a/drivers/gpio/s5p_gpio.c +++ b/drivers/gpio/s5p_gpio.c @@ -357,6 +357,7 @@ static const struct udevice_id exynos_gpio_ids[] = { { .compatible = "samsung,exynos4x12-pinctrl" }, { .compatible = "samsung,exynos5250-pinctrl" }, { .compatible = "samsung,exynos5420-pinctrl" }, + { .compatible = "samsung,exynos78x0-gpio" }, { } }; diff --git a/drivers/pinctrl/exynos/Kconfig b/drivers/pinctrl/exynos/Kconfig index 84b6aaae09c..a60f49869b4 100644 --- a/drivers/pinctrl/exynos/Kconfig +++ b/drivers/pinctrl/exynos/Kconfig @@ -8,3 +8,11 @@ config PINCTRL_EXYNOS7420 help Support pin multiplexing and pin configuration control on Samsung's Exynos7420 SoC. + +config PINCTRL_EXYNOS78x0 + bool "Samsung Exynos78x0 pinctrl driver" + depends on ARCH_EXYNOS && PINCTRL_FULL + select PINCTRL_EXYNOS + help + Support pin multiplexing and pin configuration control on + Samsung's Exynos78x0 SoC. diff --git a/drivers/pinctrl/exynos/Makefile b/drivers/pinctrl/exynos/Makefile index 6a14a474bf2..07db970ca94 100644 --- a/drivers/pinctrl/exynos/Makefile +++ b/drivers/pinctrl/exynos/Makefile @@ -5,3 +5,4 @@ obj-$(CONFIG_PINCTRL_EXYNOS) += pinctrl-exynos.o obj-$(CONFIG_PINCTRL_EXYNOS7420) += pinctrl-exynos7420.o +obj-$(CONFIG_PINCTRL_EXYNOS78x0) += pinctrl-exynos78x0.o diff --git a/drivers/pinctrl/exynos/pinctrl-exynos78x0.c b/drivers/pinctrl/exynos/pinctrl-exynos78x0.c new file mode 100644 index 00000000000..01e9a4fede5 --- /dev/null +++ b/drivers/pinctrl/exynos/pinctrl-exynos78x0.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Exynos78x0 pinctrl driver. + * + * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com) + * + * based on drivers/pinctrl/exynos/pinctrl-exynos7420.c : + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "pinctrl-exynos.h" + +static struct pinctrl_ops exynos78x0_pinctrl_ops = { + .set_state = exynos_pinctrl_set_state +}; + +/* pin banks of exynos78x0 pin-controller 0 (ALIVE) */ +static struct samsung_pin_bank_data exynos78x0_pin_banks0[] = { + EXYNOS_PIN_BANK(6, 0x000, "etc0"), + EXYNOS_PIN_BANK(3, 0x020, "etc1"), + EXYNOS_PIN_BANK(8, 0x040, "gpa0"), + EXYNOS_PIN_BANK(8, 0x060, "gpa1"), + EXYNOS_PIN_BANK(8, 0x080, "gpa2"), + EXYNOS_PIN_BANK(5, 0x0a0, "gpa3"), + EXYNOS_PIN_BANK(2, 0x0c0, "gpq0"), +}; + +/* pin banks of exynos78x0 pin-controller 1 (CCORE) */ +static struct samsung_pin_bank_data exynos78x0_pin_banks1[] = { + EXYNOS_PIN_BANK(2, 0x000, "gpm0"), +}; + +/* pin banks of exynos78x0 pin-controller 2 (DISPAUD) */ +static struct samsung_pin_bank_data exynos78x0_pin_banks2[] = { + EXYNOS_PIN_BANK(4, 0x000, "gpz0"), + EXYNOS_PIN_BANK(6, 0x020, "gpz1"), + EXYNOS_PIN_BANK(4, 0x040, "gpz2"), +}; + +/* pin banks of exynos78x0 pin-controller 4 (FSYS) */ +static struct samsung_pin_bank_data exynos78x0_pin_banks4[] = { + EXYNOS_PIN_BANK(3, 0x000, "gpr0"), + EXYNOS_PIN_BANK(8, 0x020, "gpr1"), + EXYNOS_PIN_BANK(2, 0x040, "gpr2"), + EXYNOS_PIN_BANK(4, 0x060, "gpr3"), + EXYNOS_PIN_BANK(6, 0x080, "gpr4"), +}; + +/* pin banks of exynos78x0 pin-controller 6 (TOP) */ +static struct samsung_pin_bank_data exynos78x0_pin_banks6[] = { + EXYNOS_PIN_BANK(4, 0x000, "gpb0"), + EXYNOS_PIN_BANK(3, 0x020, "gpc0"), + EXYNOS_PIN_BANK(4, 0x040, "gpc1"), + EXYNOS_PIN_BANK(4, 0x060, "gpc4"), + EXYNOS_PIN_BANK(2, 0x080, "gpc5"), + EXYNOS_PIN_BANK(4, 0x0a0, "gpc6"), + EXYNOS_PIN_BANK(2, 0x0c0, "gpc8"), + EXYNOS_PIN_BANK(2, 0x0e0, "gpc9"), + EXYNOS_PIN_BANK(7, 0x100, "gpd1"), + EXYNOS_PIN_BANK(6, 0x120, "gpd2"), + EXYNOS_PIN_BANK(8, 0x140, "gpd3"), + EXYNOS_PIN_BANK(7, 0x160, "gpd4"), + EXYNOS_PIN_BANK(5, 0x180, "gpd5"), + EXYNOS_PIN_BANK(3, 0x1a0, "gpe0"), + EXYNOS_PIN_BANK(4, 0x1c0, "gpf0"), + EXYNOS_PIN_BANK(2, 0x1e0, "gpf1"), + EXYNOS_PIN_BANK(2, 0x200, "gpf2"), + EXYNOS_PIN_BANK(4, 0x220, "gpf3"), + EXYNOS_PIN_BANK(5, 0x240, "gpf4"), +}; + +struct samsung_pin_ctrl exynos78x0_pin_ctrl[] = { + { + /* pin-controller instance 0 Alive data */ + .pin_banks = exynos78x0_pin_banks0, + .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks0), + }, { + /* pin-controller instance 1 CCORE data */ + .pin_banks = exynos78x0_pin_banks1, + .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks1), + }, { + /* pin-controller instance 2 DISPAUD data */ + .pin_banks = exynos78x0_pin_banks2, + .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks2), + }, { + /* pin-controller instance 4 FSYS data */ + .pin_banks = exynos78x0_pin_banks4, + .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks4), + }, { + /* pin-controller instance 6 TOP data */ + .pin_banks = exynos78x0_pin_banks6, + .nr_banks = ARRAY_SIZE(exynos78x0_pin_banks6), + }, + {/* list terminator */} +}; + +static const struct udevice_id exynos78x0_pinctrl_ids[] = { + { .compatible = "samsung,exynos78x0-pinctrl", + .data = (ulong)exynos78x0_pin_ctrl }, + { } +}; + +U_BOOT_DRIVER(pinctrl_exynos78x0) = { + .name = "pinctrl_exynos78x0", + .id = UCLASS_PINCTRL, + .of_match = exynos78x0_pinctrl_ids, + .priv_auto = sizeof(struct exynos_pinctrl_priv), + .ops = &exynos78x0_pinctrl_ops, + .probe = exynos_pinctrl_probe, +}; diff --git a/include/configs/exynos78x0-common.h b/include/configs/exynos78x0-common.h new file mode 100644 index 00000000000..478a0c42b1d --- /dev/null +++ b/include/configs/exynos78x0-common.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Configuration settings for the EXYNOS 78x0 based boards. + * + * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com) + * based on include/exynos7420-common.h + * Copyright (C) 2016 Samsung Electronics + * Thomas Abraham + */ + +#ifndef __CONFIG_EXYNOS78x0_COMMON_H +#define __CONFIG_EXYNOS78x0_COMMON_H + +/* High Level Configuration Options */ +#define CONFIG_SAMSUNG /* in a SAMSUNG core */ +#define CONFIG_S5P + +#include /* get chip and board defs */ +#include + +/* Miscellaneous configurable options */ +#define CONFIG_SYS_CBSIZE 1024 /* Console I/O Buffer Size */ +#define CONFIG_SYS_PBSIZE 1024 /* Print Buffer Size */ + +/* Boot Argument Buffer Size */ +#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE + +/* Timer input clock frequency */ +#define COUNTER_FREQUENCY 26000000 + +/* Device Tree */ +#define CONFIG_DEVICE_TREE_LIST "EXYNOS78x0-a5y17lte" + +#define CPU_RELEASE_ADDR secondary_boot_addr + +#define CONFIG_SYS_BAUDRATE_TABLE \ + {9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600} + +#define CONFIG_BOARD_COMMON + +#define CONFIG_SYS_SDRAM_BASE 0x40000000 +#define CONFIG_SYS_INIT_SP_ADDR (CONFIG_SYS_TEXT_BASE + SZ_2M - GENERATED_GBL_DATA_SIZE) +/* DRAM Memory Banks */ +#define SDRAM_BANK_SIZE (256UL << 20UL) /* 256 MB */ +#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE +#define PHYS_SDRAM_1_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_2 (CONFIG_SYS_SDRAM_BASE + SDRAM_BANK_SIZE) +#define PHYS_SDRAM_2_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_3 (CONFIG_SYS_SDRAM_BASE + (2 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_3_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_4 (CONFIG_SYS_SDRAM_BASE + (3 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_4_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_5 (CONFIG_SYS_SDRAM_BASE + (4 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_5_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_6 (CONFIG_SYS_SDRAM_BASE + (5 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_6_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_7 (CONFIG_SYS_SDRAM_BASE + (6 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_7_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_8 (CONFIG_SYS_SDRAM_BASE + (7 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_8_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_9 (CONFIG_SYS_SDRAM_BASE + (8 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_9_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_10 (CONFIG_SYS_SDRAM_BASE + (9 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_10_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_11 (CONFIG_SYS_SDRAM_BASE + (10 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_11_SIZE SDRAM_BANK_SIZE +#define PHYS_SDRAM_12 (CONFIG_SYS_SDRAM_BASE + (11 * SDRAM_BANK_SIZE)) +#define PHYS_SDRAM_12_SIZE SDRAM_BANK_SIZE + +#define CONFIG_DEBUG_UART_CLOCK 132710400 + +#define CONFIG_PREBOOT \ +"echo Read pressed buttons status;" \ +"KEY_VOLUMEUP=gpa20;" \ +"KEY_HOME=gpa17;" \ +"KEY_VOLUMEDOWN=gpa21;" \ +"KEY_POWER=gpa00;" \ +"PRESSED=0;" \ +"RELEASED=1;" \ +"if gpio input $KEY_VOLUMEUP; then setenv VOLUME_UP $PRESSED; " \ +"else setenv VOLUME_UP $RELEASED; fi;" \ +"if gpio input $KEY_VOLUMEDOWN; then setenv VOLUME_DOWN $PRESSED; " \ +"else setenv VOLUME_DOWN $RELEASED; fi;" \ +"if gpio input $KEY_HOME; then setenv HOME $PRESSED; else setenv HOME $RELEASED; fi;" \ +"if gpio input $KEY_POWER; then setenv POWER $PRESSED; else setenv POWER $RELEASED; fi;" + +#ifndef MEM_LAYOUT_ENV_SETTINGS +#define MEM_LAYOUT_ENV_SETTINGS \ + "bootm_size=0x10000000\0" \ + "bootm_low=0x40000000\0" +#endif + +#ifndef EXYNOS_DEVICE_SETTINGS +#define EXYNOS_DEVICE_SETTINGS \ + "stdin=serial\0" \ + "stdout=serial\0" \ + "stderr=serial\0" +#endif + +#ifndef EXYNOS_FDTFILE_SETTING +#define EXYNOS_FDTFILE_SETTING +#endif + +#define EXTRA_ENV_SETTINGS \ + EXYNOS_DEVICE_SETTINGS \ + EXYNOS_FDTFILE_SETTING \ + MEM_LAYOUT_ENV_SETTINGS + +#define CONFIG_EXTRA_ENV_SETTINGS \ + EXTRA_ENV_SETTINGS + +#endif /* __CONFIG_EXYNOS78x0_COMMON_H */ -- cgit v1.2.3 From 3e2095e960b47a3c0211a3a1e52c74b1761cb0be Mon Sep 17 00:00:00 2001 From: Dzmitry Sankouski Date: Sun, 17 Oct 2021 13:45:42 +0300 Subject: board: samsung: add support for Galaxy A series of 2017 (a5y17lte) Samsung Galaxy A3, A5, A7 (2017) - middle class Samsung smartphones. U-boot can be used as chain-loaded bootloader to gain control on booting vanilla linux(and possibly others) kernels Signed-off-by: Dzmitry Sankouski Cc: Minkyu Kang --- arch/arm/dts/Makefile | 3 ++ arch/arm/dts/exynos78x0-axy17lte.dts | 29 +++++++++++ arch/arm/mach-exynos/Kconfig | 28 +++++++++++ board/samsung/axy17lte/Kconfig | 58 ++++++++++++++++++++++ board/samsung/axy17lte/MAINTAINERS | 8 +++ board/samsung/axy17lte/Makefile | 3 ++ board/samsung/axy17lte/axy17lte.c | 11 +++++ configs/a3y17lte_defconfig | 24 +++++++++ configs/a5y17lte_defconfig | 24 +++++++++ configs/a7y17lte_defconfig | 24 +++++++++ doc/board/index.rst | 1 + doc/board/samsung/axy17lte.rst | 94 ++++++++++++++++++++++++++++++++++++ doc/board/samsung/index.rst | 9 ++++ 13 files changed, 316 insertions(+) create mode 100644 arch/arm/dts/exynos78x0-axy17lte.dts create mode 100644 board/samsung/axy17lte/Kconfig create mode 100644 board/samsung/axy17lte/MAINTAINERS create mode 100644 board/samsung/axy17lte/Makefile create mode 100644 board/samsung/axy17lte/axy17lte.c create mode 100644 configs/a3y17lte_defconfig create mode 100644 configs/a5y17lte_defconfig create mode 100644 configs/a7y17lte_defconfig create mode 100644 doc/board/samsung/axy17lte.rst create mode 100644 doc/board/samsung/index.rst diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index fdf85da9c02..cc34da7bd83 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -28,6 +28,9 @@ dtb-$(CONFIG_EXYNOS5) += exynos5250-arndale.dtb \ exynos5800-peach-pi.dtb \ exynos5422-odroidxu3.dtb dtb-$(CONFIG_EXYNOS7420) += exynos7420-espresso7420.dtb +dtb-$(CONFIG_TARGET_A5Y17LTE) += exynos78x0-axy17lte.dtb +dtb-$(CONFIG_TARGET_A3Y17LTE) += exynos78x0-axy17lte.dtb +dtb-$(CONFIG_TARGET_A7Y17LTE) += exynos78x0-axy17lte.dtb dtb-$(CONFIG_ARCH_APPLE) += \ t8103-j274.dtb \ diff --git a/arch/arm/dts/exynos78x0-axy17lte.dts b/arch/arm/dts/exynos78x0-axy17lte.dts new file mode 100644 index 00000000000..7fae8db8749 --- /dev/null +++ b/arch/arm/dts/exynos78x0-axy17lte.dts @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung Exynos78x0 SoC device tree source + * + * Copyright (c) 2020 Dzmitry Sankouski (dsankouski@gmail.com) + */ + +/dts-v1/; +#include "exynos78x0.dtsi" +/ { + compatible = "samsung,exynos78x0", "samsung,exynos7880", "samsung,exynos7870"; + + aliases { + console = &uart2; + }; + + chosen { + stdout-path = &uart2; + }; +}; + +&gpioi2c0 { + status = "okay"; +}; + +&fin_pll { + clock-frequency = <26000000>; +}; + diff --git a/arch/arm/mach-exynos/Kconfig b/arch/arm/mach-exynos/Kconfig index 7df0e176179..7f3aee57129 100644 --- a/arch/arm/mach-exynos/Kconfig +++ b/arch/arm/mach-exynos/Kconfig @@ -151,6 +151,33 @@ config TARGET_ESPRESSO7420 select PINCTRL_EXYNOS7420 select SUPPORT_SPL +config TARGET_A5Y17LTE + bool "Samsung SM-A520F board" + select ARM64 + select CLK_EXYNOS + select OF_CONTROL + select PINCTRL + select PINCTRL_EXYNOS78x0 + select SUPPORT_SPL + +config TARGET_A7Y17LTE + bool "Samsung SM-A520F board" + select ARM64 + select CLK_EXYNOS + select OF_CONTROL + select PINCTRL + select PINCTRL_EXYNOS78x0 + select SUPPORT_SPL + +config TARGET_A3Y17LTE + bool "Samsung SM-A520F board" + select ARM64 + select CLK_EXYNOS + select OF_CONTROL + select PINCTRL + select PINCTRL_EXYNOS7880 + select SUPPORT_SPL + endchoice endif @@ -167,6 +194,7 @@ source "board/samsung/arndale/Kconfig" source "board/samsung/smdk5250/Kconfig" source "board/samsung/smdk5420/Kconfig" source "board/samsung/espresso7420/Kconfig" +source "board/samsung/axy17lte/Kconfig" config SPL_LDSCRIPT default "board/samsung/common/exynos-uboot-spl.lds" if ARCH_EXYNOS5 || ARCH_EXYNOS4 diff --git a/board/samsung/axy17lte/Kconfig b/board/samsung/axy17lte/Kconfig new file mode 100644 index 00000000000..2abf8e7acfc --- /dev/null +++ b/board/samsung/axy17lte/Kconfig @@ -0,0 +1,58 @@ +config SYS_CONFIG_NAME + string "Board configuration name" + default "exynos78x0-common.h" + help + This option contains information about board configuration name. + Based on this option include/configs/.h header + will be used for board configuration. + +if TARGET_A5Y17LTE +config SYS_BOARD + default "axy17lte" + help + a5y17lte is a production board for SM-A520F phone on Exynos7880 SoC. + +config SYS_VENDOR + default "samsung" + +config SYS_CONFIG_NAME + default "a5y17lte" + +config EXYNOS7880 + bool "Exynos 7880 SOC support" + default y +endif + +if TARGET_A7Y17LTE +config SYS_BOARD + default "axy17lte" + help + a5y17lte is a production board for SM-A520F phone on Exynos7880 SoC. + +config SYS_VENDOR + default "samsung" + +config SYS_CONFIG_NAME + default "a5y17lte" + +config EXYNOS7880 + bool "Exynos 7880 SOC support" + default y +endif + +if TARGET_A3Y17LTE +config SYS_BOARD + default "axy17lte" + help + a3y17lte is a production board for SM-A520F phone on Exynos7880 SoC. + +config SYS_VENDOR + default "samsung" + +config SYS_CONFIG_NAME + default "a3y17lte" + +config EXYNOS7870 + bool "Exynos 7870 SOC support" + default y +endif diff --git a/board/samsung/axy17lte/MAINTAINERS b/board/samsung/axy17lte/MAINTAINERS new file mode 100644 index 00000000000..13feba62a7f --- /dev/null +++ b/board/samsung/axy17lte/MAINTAINERS @@ -0,0 +1,8 @@ +Samsung A series 2017 phones Board +M: Dzmitry Sankouski +S: Maintained +F: board/samsung/axy17lte/ +F: include/configs/exynos78x0-common.h +F: configs/a3y17lte_defconfig +F: configs/a5y17lte_defconfig +F: configs/a7y17lte_defconfig diff --git a/board/samsung/axy17lte/Makefile b/board/samsung/axy17lte/Makefile new file mode 100644 index 00000000000..4e11f289dce --- /dev/null +++ b/board/samsung/axy17lte/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +obj-y += axy17lte.o diff --git a/board/samsung/axy17lte/axy17lte.c b/board/samsung/axy17lte/axy17lte.c new file mode 100644 index 00000000000..c38297a05ba --- /dev/null +++ b/board/samsung/axy17lte/axy17lte.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Samsung A5Y17 and A3Y17 LTE boards based on Exynos 7880 and Exynos 7870 SoCs + */ + +#include + +int exynos_init(void) +{ + return 0; +} diff --git a/configs/a3y17lte_defconfig b/configs/a3y17lte_defconfig new file mode 100644 index 00000000000..36404d15f71 --- /dev/null +++ b/configs/a3y17lte_defconfig @@ -0,0 +1,24 @@ +CONFIG_ARM=y +CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS7=y +CONFIG_S5P=y +CONFIG_TARGET_A3Y17LTE=y +# This option is a number of 256MB DRAM banks, i.e. (ram size) / 256MB. +# Used in samsung common board dram_init function. +CONFIG_NR_DRAM_BANKS=8 +CONFIG_SYS_CONFIG_NAME="exynos78x0-common" +CONFIG_DEFAULT_DEVICE_TREE="exynos78x0-axy17lte" +CONFIG_SYS_TEXT_BASE=0x40001000 +CONFIG_SYS_LOAD_ADDR=0x40001000 +CONFIG_HUSH_PARSER=y +CONFIG_FIT=y +CONFIG_BOARD_EARLY_INIT_F=n +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_CMD_GPIO=y +CONFIG_DISPLAY_CPUINFO=n +CONFIG_CMD_I2C=y +CONFIG_DM_I2C_GPIO=y +CONFIG_PINCTRL_EXYNOS78x0=y +CONFIG_PINCTRL_EXYNOS=y +# CONFIG_DEBUG_UART_S5P=y +# CONFIG_DEBUG_UART_BASE=0x13820000 \ No newline at end of file diff --git a/configs/a5y17lte_defconfig b/configs/a5y17lte_defconfig new file mode 100644 index 00000000000..273ad1078ee --- /dev/null +++ b/configs/a5y17lte_defconfig @@ -0,0 +1,24 @@ +CONFIG_ARM=y +CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS7=y +CONFIG_S5P=y +CONFIG_TARGET_A5Y17LTE=y +# This option is a number of 256MB DRAM banks, i.e. (ram size) / 256MB. +# Used in samsung common board dram_init function. +CONFIG_NR_DRAM_BANKS=12 +CONFIG_SYS_CONFIG_NAME="exynos78x0-common" +CONFIG_DEFAULT_DEVICE_TREE="exynos78x0-axy17lte" +CONFIG_SYS_TEXT_BASE=0x40001000 +CONFIG_SYS_LOAD_ADDR=0x40001000 +CONFIG_HUSH_PARSER=y +CONFIG_FIT=y +CONFIG_BOARD_EARLY_INIT_F=n +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_CMD_GPIO=y +CONFIG_DISPLAY_CPUINFO=n +CONFIG_CMD_I2C=y +CONFIG_DM_I2C_GPIO=y +CONFIG_PINCTRL_EXYNOS78x0=y +CONFIG_PINCTRL_EXYNOS=y +# CONFIG_DEBUG_UART_S5P=y +# CONFIG_DEBUG_UART_BASE=0x13820000 \ No newline at end of file diff --git a/configs/a7y17lte_defconfig b/configs/a7y17lte_defconfig new file mode 100644 index 00000000000..f544f629ef1 --- /dev/null +++ b/configs/a7y17lte_defconfig @@ -0,0 +1,24 @@ +CONFIG_ARM=y +CONFIG_ARCH_EXYNOS=y +CONFIG_ARCH_EXYNOS7=y +CONFIG_S5P=y +CONFIG_TARGET_A7Y17LTE=y +# This option is a number of 256MB DRAM banks, i.e. (ram size) / 256MB. +# Used in samsung common board dram_init function. +CONFIG_NR_DRAM_BANKS=12 +CONFIG_SYS_CONFIG_NAME="exynos78x0-common" +CONFIG_DEFAULT_DEVICE_TREE="exynos78x0-axy17lte" +CONFIG_SYS_TEXT_BASE=0x40001000 +CONFIG_SYS_LOAD_ADDR=0x40001000 +CONFIG_HUSH_PARSER=y +CONFIG_FIT=y +CONFIG_BOARD_EARLY_INIT_F=n +CONFIG_SKIP_LOWLEVEL_INIT=y +CONFIG_CMD_GPIO=y +CONFIG_DISPLAY_CPUINFO=n +CONFIG_CMD_I2C=y +CONFIG_DM_I2C_GPIO=y +CONFIG_PINCTRL_EXYNOS78x0=y +CONFIG_PINCTRL_EXYNOS=y +# CONFIG_DEBUG_UART_S5P=y +# CONFIG_DEBUG_UART_BASE=0x13820000 \ No newline at end of file diff --git a/doc/board/index.rst b/doc/board/index.rst index 1b93ced5634..74ea33e0816 100644 --- a/doc/board/index.rst +++ b/doc/board/index.rst @@ -23,6 +23,7 @@ Board-specific doc openpiton/index qualcomm/index rockchip/index + samsung/index siemens/index sifive/index sipeed/index diff --git a/doc/board/samsung/axy17lte.rst b/doc/board/samsung/axy17lte.rst new file mode 100644 index 00000000000..511cd57a22f --- /dev/null +++ b/doc/board/samsung/axy17lte.rst @@ -0,0 +1,94 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. sectionauthor:: Dzmitry Sankouski + +Samsung 2017 A series phones +============================ + +About this +---------- +This document describes the information about Samsung A(7/5/3) 2017 midrange +phones and u-boot usage steps. + +U-Boot can be used as a chain-loaded bootloader to replace Samsung's original SBOOT bootloader. +It is loaded as an Android boot image through SBOOT. + +Phone specs +----------- +A3 (SM-320) (a3y17lte) +^^^^^^^^^^^^^^^^^^^^^^ +- 4.7 AMOLED display +- Exynos 7870 SoC +- 16GB flash +- 2GB RAM + +.. A3 2017 wiki page: https://en.wikipedia.org/wiki/Samsung_Galaxy_A3_(2017) + +A5 (SM-520) (a5y17lte) +^^^^^^^^^^^^^^^^^^^^^^ +- 5.2 AMOLED display +- Exynos 7880 SoC +- 32GB flash +- 3GB RAM + +.. A5 2017 wiki page: https://en.wikipedia.org/wiki/Samsung_Galaxy_A5_(2017) + +A7 (SM-720) (a5y17lte) +^^^^^^^^^^^^^^^^^^^^^^ +- 5.7 AMOLED display +- Exynos 7880 SoC +- 32GB flash +- 3GB RAM + +.. A7 2017 wiki page: https://en.wikipedia.org/wiki/Samsung_Galaxy_A7_(2017) + +Installation +------------ + +Building u-boot +^^^^^^^^^^^^^^^ + +First, setup ``CROSS_COMPILE`` for aarch64. +Then, build U-Boot for your phone, for example ``a5y17lte``:: + + $ export CROSS_COMPILE= + $ make a5y17lte_defconfig + $ make + +This will build ``u-boot.bin`` in the configured output directory. + +Payload +^^^^^^^ +What is a payload? +"""""""""""""""""" +A payload file is a file to be used instead of linux kernel in android boot image. +This file will be loaded into memory, and executed by SBOOT, +and is therefore SBOOT's payload. +It may be pure u-boot (with loading u-boot's payload from flash in mind), +or u-boot + u-boot's payload. + +It should be kept in mind, that SBOOT binary patches it's payload after loading +in address range 0x401f8550-0x401f9280. Given SBOOT loads payload to 0x40001000, +a range of 0x1f7550-0x1f8280 (2061648-2065024) in a payload file +will be corrupted after loading to RAM. + +Creating payload file +""""""""""""""""""""" +- Assemble FIT image for your kernel +- Create a file for u-boot payload ``touch sboot-payload`` +- Write zeroes till 0x200000 address to be sure SBOOT won't corrupt your info + ``dd if=/dev/zero of=sboot-payload bs=$((0x200000)) count=1`` +- Write u-boot to the start of the payload ``dd if= of=sboot-payload`` +- Write FIT image to payload from 0x200000 address + ``dd if= of=sboot-payload seek=1 bs=2M`` + +Creating android boot image +""""""""""""""""""""""""""" +Once payload created, it's time for android image:: + + mkbootimg --base 0x40000000 --kernel_offset 0x00000000 --ramdisk_offset 0x01000000 --tags_offset 0x00000100 --pagesize 2048 --second_offset 0x00f00000 --kernel -o uboot.img + +Note, that stock Samsung bootloader ignores offsets, set in mkbootimg. + +Flashing +"""""""" +Flash like regular android boot image. diff --git a/doc/board/samsung/index.rst b/doc/board/samsung/index.rst new file mode 100644 index 00000000000..c904372dff3 --- /dev/null +++ b/doc/board/samsung/index.rst @@ -0,0 +1,9 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +Samsung +======== + +.. toctree:: + :maxdepth: 2 + + axy17lte -- cgit v1.2.3