diff options
Diffstat (limited to 'drivers')
51 files changed, 1419 insertions, 375 deletions
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c index b040447575ad..dcfb32ee5cb6 100644 --- a/drivers/bus/omap_l3_noc.c +++ b/drivers/bus/omap_l3_noc.c @@ -285,7 +285,7 @@ static int omap_l3_probe(struct platform_device *pdev) */ l3->debug_irq = platform_get_irq(pdev, 0); ret = devm_request_irq(l3->dev, l3->debug_irq, l3_interrupt_handler, - 0x0, "l3-dbg-irq", l3); + IRQF_NO_THREAD, "l3-dbg-irq", l3); if (ret) { dev_err(l3->dev, "request_irq failed for %d\n", l3->debug_irq); @@ -294,7 +294,7 @@ static int omap_l3_probe(struct platform_device *pdev) l3->app_irq = platform_get_irq(pdev, 1); ret = devm_request_irq(l3->dev, l3->app_irq, l3_interrupt_handler, - 0x0, "l3-app-irq", l3); + IRQF_NO_THREAD, "l3-app-irq", l3); if (ret) dev_err(l3->dev, "request_irq failed for %d\n", l3->app_irq); diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index a27d751cf219..8880259b41ae 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -288,7 +288,7 @@ static int sysc_add_named_clock_from_child(struct sysc *ddata, * limit for clk_get(). If cl ever needs to be freed, it should be done * with clkdev_drop(). */ - cl = kcalloc(1, sizeof(*cl), GFP_KERNEL); + cl = kzalloc(sizeof(*cl), GFP_KERNEL); if (!cl) return -ENOMEM; @@ -635,6 +635,51 @@ static int sysc_parse_and_check_child_range(struct sysc *ddata) return 0; } +/* Interconnect instances to probe before l4_per instances */ +static struct resource early_bus_ranges[] = { + /* am3/4 l4_wkup */ + { .start = 0x44c00000, .end = 0x44c00000 + 0x300000, }, + /* omap4/5 and dra7 l4_cfg */ + { .start = 0x4a000000, .end = 0x4a000000 + 0x300000, }, + /* omap4 l4_wkup */ + { .start = 0x4a300000, .end = 0x4a300000 + 0x30000, }, + /* omap5 and dra7 l4_wkup without dra7 dcan segment */ + { .start = 0x4ae00000, .end = 0x4ae00000 + 0x30000, }, +}; + +static atomic_t sysc_defer = ATOMIC_INIT(10); + +/** + * sysc_defer_non_critical - defer non_critical interconnect probing + * @ddata: device driver data + * + * We want to probe l4_cfg and l4_wkup interconnect instances before any + * l4_per instances as l4_per instances depend on resources on l4_cfg and + * l4_wkup interconnects. + */ +static int sysc_defer_non_critical(struct sysc *ddata) +{ + struct resource *res; + int i; + + if (!atomic_read(&sysc_defer)) + return 0; + + for (i = 0; i < ARRAY_SIZE(early_bus_ranges); i++) { + res = &early_bus_ranges[i]; + if (ddata->module_pa >= res->start && + ddata->module_pa <= res->end) { + atomic_set(&sysc_defer, 0); + + return 0; + } + } + + atomic_dec_if_positive(&sysc_defer); + + return -EPROBE_DEFER; +} + static struct device_node *stdout_path; static void sysc_init_stdout_path(struct sysc *ddata) @@ -856,15 +901,19 @@ static int sysc_map_and_check_registers(struct sysc *ddata) struct device_node *np = ddata->dev->of_node; int error; - if (!of_get_property(np, "reg", NULL)) - return 0; - error = sysc_parse_and_check_child_range(ddata); if (error) return error; + error = sysc_defer_non_critical(ddata); + if (error) + return error; + sysc_check_children(ddata); + if (!of_get_property(np, "reg", NULL)) + return 0; + error = sysc_parse_registers(ddata); if (error) return error; @@ -1447,12 +1496,16 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("dwc3", 0, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, 0), SYSC_QUIRK("d2d", 0x4a0b6000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("d2d", 0x4a0cd000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), + SYSC_QUIRK("elm", 0x48080000, 0, 0x10, 0x14, 0x00000020, 0xffffffff, 0), + SYSC_QUIRK("emif", 0, 0, -ENODEV, -ENODEV, 0x40441403, 0xffff0fff, 0), + SYSC_QUIRK("emif", 0, 0, -ENODEV, -ENODEV, 0x50440500, 0xffffffff, 0), SYSC_QUIRK("epwmss", 0, 0, 0x4, -ENODEV, 0x47400001, 0xffffffff, 0), SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -ENODEV, 0, 0, 0), SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, 0), SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50031d00, 0xffffffff, 0), SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), SYSC_QUIRK("iss", 0, 0, 0x10, -ENODEV, 0x40000101, 0xffffffff, 0), + SYSC_QUIRK("keypad", 0x4a31c000, 0, 0x10, 0x14, 0x00000020, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44306302, 0xffffffff, 0), SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44307b02, 0xffffffff, 0), SYSC_QUIRK("mcbsp", 0, -ENODEV, 0x8c, -ENODEV, 0, 0, 0), @@ -1464,11 +1517,14 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("ocp2scp", 0, 0, -ENODEV, -ENODEV, 0x50060007, 0xffffffff, 0), SYSC_QUIRK("padconf", 0, 0, 0x10, -ENODEV, 0x4fff0800, 0xffffffff, 0), SYSC_QUIRK("padconf", 0, 0, -ENODEV, -ENODEV, 0x40001100, 0xffffffff, 0), + SYSC_QUIRK("pcie", 0x51000000, -ENODEV, -ENODEV, -ENODEV, 0, 0, 0), + SYSC_QUIRK("pcie", 0x51800000, -ENODEV, -ENODEV, -ENODEV, 0, 0, 0), SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000100, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x00004102, 0xffffffff, 0), SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000400, 0xffffffff, 0), SYSC_QUIRK("rfbi", 0x4832a800, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), SYSC_QUIRK("rfbi", 0x58002000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0), + SYSC_QUIRK("sata", 0, 0xfc, 0x1100, -ENODEV, 0x5e412000, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4e8b0100, 0xffffffff, 0), SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4f000100, 0xffffffff, 0), @@ -1592,7 +1648,7 @@ static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset, case SOC_UNKNOWN: default: return 0; - }; + } /* Remap the whole module range to be able to reset dispc outputs */ devm_iounmap(ddata->dev, ddata->module_va); @@ -2802,6 +2858,7 @@ static int sysc_init_soc(struct sysc *ddata) const struct soc_device_attribute *match; struct ti_sysc_platform_data *pdata; unsigned long features = 0; + struct device_node *np; if (sysc_soc) return 0; @@ -2822,6 +2879,21 @@ static int sysc_init_soc(struct sysc *ddata) if (match && match->data) sysc_soc->soc = (int)match->data; + /* + * Check and warn about possible old incomplete dtb. We now want to see + * simple-pm-bus instead of simple-bus in the dtb for genpd using SoCs. + */ + switch (sysc_soc->soc) { + case SOC_AM3: + case SOC_AM4: + np = of_find_node_by_path("/ocp"); + WARN_ONCE(np && of_device_is_compatible(np, "simple-bus"), + "ti-sysc: Incomplete old dtb, please update\n"); + break; + default: + break; + } + /* Ignore devices that are not available on HS and EMU SoCs */ if (!sysc_soc->general_purpose) { switch (sysc_soc->soc) { @@ -2830,7 +2902,7 @@ static int sysc_init_soc(struct sysc *ddata) break; default: break; - }; + } } match = soc_device_match(sysc_soc_feat_match); @@ -3053,7 +3125,9 @@ static int sysc_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - reset_control_assert(ddata->rsts); + + if (!reset_control_status(ddata->rsts)) + reset_control_assert(ddata->rsts); unprepare: sysc_unprepare(ddata); diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index a588d56502d4..1d1891b9cad2 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -394,6 +394,7 @@ source "drivers/clk/renesas/Kconfig" source "drivers/clk/rockchip/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/sifive/Kconfig" +source "drivers/clk/socfpga/Kconfig" source "drivers/clk/sprd/Kconfig" source "drivers/clk/sunxi/Kconfig" source "drivers/clk/sunxi-ng/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index b22ae4f81e0b..9b582b3fca34 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -104,9 +104,7 @@ obj-y += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_CLK_SIFIVE) += sifive/ -obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ -obj-$(CONFIG_ARCH_AGILEX) += socfpga/ -obj-$(CONFIG_ARCH_STRATIX10) += socfpga/ +obj-y += socfpga/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-y += sprd/ obj-$(CONFIG_ARCH_STI) += st/ diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index f89b9cfc4309..dd3b71eafabf 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -314,7 +314,7 @@ static int raspberrypi_clk_probe(struct platform_device *pdev) return -ENOENT; } - firmware = rpi_firmware_get(firmware_node); + firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node); of_node_put(firmware_node); if (!firmware) return -EPROBE_DEFER; diff --git a/drivers/clk/socfpga/Kconfig b/drivers/clk/socfpga/Kconfig new file mode 100644 index 000000000000..0cf16b894efb --- /dev/null +++ b/drivers/clk/socfpga/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 +config CLK_INTEL_SOCFPGA + bool "Intel SoCFPGA family clock support" if COMPILE_TEST && !ARCH_INTEL_SOCFPGA + default ARCH_INTEL_SOCFPGA + help + Support for the clock controllers present on Intel SoCFPGA and eASIC + devices like Aria, Cyclone, Stratix 10, Agilex and N5X eASIC. + +if CLK_INTEL_SOCFPGA + +config CLK_INTEL_SOCFPGA32 + bool "Intel Aria / Cyclone clock controller support" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA) + default ARM && ARCH_INTEL_SOCFPGA + +config CLK_INTEL_SOCFPGA64 + bool "Intel Stratix / Agilex / N5X clock controller support" if COMPILE_TEST && (!ARM64 || !ARCH_INTEL_SOCFPGA) + default ARM64 && ARCH_INTEL_SOCFPGA + +endif # CLK_INTEL_SOCFPGA diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile index bf736f8d201a..e8dfce339c91 100644 --- a/drivers/clk/socfpga/Makefile +++ b/drivers/clk/socfpga/Makefile @@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_ARCH_SOCFPGA) += clk.o clk-gate.o clk-pll.o clk-periph.o -obj-$(CONFIG_ARCH_SOCFPGA) += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o -obj-$(CONFIG_ARCH_STRATIX10) += clk-s10.o -obj-$(CONFIG_ARCH_STRATIX10) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o -obj-$(CONFIG_ARCH_AGILEX) += clk-agilex.o -obj-$(CONFIG_ARCH_AGILEX) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o +obj-$(CONFIG_CLK_INTEL_SOCFPGA32) += clk.o clk-gate.o clk-pll.o clk-periph.o \ + clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o +obj-$(CONFIG_CLK_INTEL_SOCFPGA64) += clk-s10.o \ + clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o \ + clk-agilex.o diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index c5cc0a2dac6f..0193cebe8c5a 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -2515,18 +2515,6 @@ static int clk_plle_tegra210_enable(struct clk_hw *hw) pll_writel(val, PLLE_SS_CTRL, pll); udelay(1); - val = pll_readl_misc(pll); - val &= ~PLLE_MISC_IDDQ_SW_CTRL; - pll_writel_misc(val, pll); - - val = pll_readl(pll->params->aux_reg, pll); - val |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE); - val &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL); - pll_writel(val, pll->params->aux_reg, pll); - udelay(1); - val |= PLLE_AUX_SEQ_ENABLE; - pll_writel(val, pll->params->aux_reg, pll); - out: if (pll->lock) spin_unlock_irqrestore(pll->lock, flags); diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index 68cbb98af567..b9099012dc7b 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2014 NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2012-2020 NVIDIA CORPORATION. All rights reserved. */ #include <linux/io.h> @@ -403,6 +403,14 @@ static unsigned long tegra210_input_freq[] = { #define PLLRE_BASE_DEFAULT_MASK 0x1c000000 #define PLLRE_MISC0_WRITE_MASK 0x67ffffff +/* PLLE */ +#define PLLE_MISC_IDDQ_SW_CTRL (1 << 14) +#define PLLE_AUX_USE_LOCKDET (1 << 3) +#define PLLE_AUX_SS_SEQ_INCLUDE (1 << 31) +#define PLLE_AUX_ENABLE_SWCTL (1 << 4) +#define PLLE_AUX_SS_SWCTL (1 << 6) +#define PLLE_AUX_SEQ_ENABLE (1 << 24) + /* PLLX */ #define PLLX_USE_DYN_RAMP 1 #define PLLX_BASE_LOCK (1 << 27) @@ -489,6 +497,49 @@ static unsigned long tegra210_input_freq[] = { #define PLLU_MISC0_WRITE_MASK 0xbfffffff #define PLLU_MISC1_WRITE_MASK 0x00000007 +bool tegra210_plle_hw_sequence_is_enabled(void) +{ + u32 value; + + value = readl_relaxed(clk_base + PLLE_AUX); + if (value & PLLE_AUX_SEQ_ENABLE) + return true; + + return false; +} +EXPORT_SYMBOL_GPL(tegra210_plle_hw_sequence_is_enabled); + +int tegra210_plle_hw_sequence_start(void) +{ + u32 value; + + if (tegra210_plle_hw_sequence_is_enabled()) + return 0; + + /* skip if PLLE is not enabled yet */ + value = readl_relaxed(clk_base + PLLE_MISC0); + if (!(value & PLLE_MISC_LOCK)) + return -EIO; + + value &= ~PLLE_MISC_IDDQ_SW_CTRL; + writel_relaxed(value, clk_base + PLLE_MISC0); + + value = readl_relaxed(clk_base + PLLE_AUX); + value |= (PLLE_AUX_USE_LOCKDET | PLLE_AUX_SS_SEQ_INCLUDE); + value &= ~(PLLE_AUX_ENABLE_SWCTL | PLLE_AUX_SS_SWCTL); + writel_relaxed(value, clk_base + PLLE_AUX); + + fence_udelay(1, clk_base); + + value |= PLLE_AUX_SEQ_ENABLE; + writel_relaxed(value, clk_base + PLLE_AUX); + + fence_udelay(1, clk_base); + + return 0; +} +EXPORT_SYMBOL_GPL(tegra210_plle_hw_sequence_start); + void tegra210_xusb_pll_hw_control_enable(void) { u32 val; diff --git a/drivers/clk/ti/clk-54xx.c b/drivers/clk/ti/clk-54xx.c index f0542391ca4b..90e0a9ea6351 100644 --- a/drivers/clk/ti/clk-54xx.c +++ b/drivers/clk/ti/clk-54xx.c @@ -156,6 +156,8 @@ static const struct omap_clkctrl_reg_data omap5_l3main1_clkctrl_regs[] __initcon static const struct omap_clkctrl_reg_data omap5_l3main2_clkctrl_regs[] __initconst = { { OMAP5_L3_MAIN_2_CLKCTRL, NULL, 0, "l3_iclk_div" }, + { OMAP5_L3_MAIN_2_GPMC_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" }, + { OMAP5_L3_MAIN_2_OCMC_RAM_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" }, { 0 }, }; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 0c2827fd8c19..a0836ffc22e0 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -100,7 +100,7 @@ config AT_XDMAC config AXI_DMAC tristate "Analog Devices AXI-DMAC DMA support" - depends on MICROBLAZE || NIOS2 || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_SOCFPGA || COMPILE_TEST + depends on MICROBLAZE || NIOS2 || ARCH_ZYNQ || ARCH_ZYNQMP || ARCH_INTEL_SOCFPGA || COMPILE_TEST select DMA_ENGINE select DMA_VIRTUAL_CHANNELS select REGMAP_MMIO diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 27d0c4cdc58d..1e836e320edd 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -396,7 +396,7 @@ config EDAC_THUNDERX config EDAC_ALTERA bool "Altera SOCFPGA ECC" - depends on EDAC=y && (ARCH_SOCFPGA || ARCH_STRATIX10) + depends on EDAC=y && ARCH_INTEL_SOCFPGA help Support for error detection and correction on the Altera SOCs. This is the global enable for the diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c index e91cf1147a4e..5f7fd79ec82f 100644 --- a/drivers/edac/altera_edac.c +++ b/drivers/edac/altera_edac.c @@ -1501,8 +1501,13 @@ static int altr_portb_setup(struct altr_edac_device_dev *device) dci->mod_name = ecc_name; dci->dev_name = ecc_name; - /* Update the PortB IRQs - A10 has 4, S10 has 2, Index accordingly */ -#ifdef CONFIG_ARCH_STRATIX10 + /* + * Update the PortB IRQs - A10 has 4, S10 has 2, Index accordingly + * + * FIXME: Instead of ifdefs with different architectures the driver + * should properly use compatibles. + */ +#ifdef CONFIG_64BIT altdev->sb_irq = irq_of_parse_and_map(np, 1); #else altdev->sb_irq = irq_of_parse_and_map(np, 2); @@ -1521,7 +1526,7 @@ static int altr_portb_setup(struct altr_edac_device_dev *device) goto err_release_group_1; } -#ifdef CONFIG_ARCH_STRATIX10 +#ifdef CONFIG_64BIT /* Use IRQ to determine SError origin instead of assigning IRQ */ rc = of_property_read_u32_index(np, "interrupts", 1, &altdev->db_irq); if (rc) { @@ -1931,7 +1936,7 @@ static int altr_edac_a10_device_add(struct altr_arria10_edac *edac, goto err_release_group1; } -#ifdef CONFIG_ARCH_STRATIX10 +#ifdef CONFIG_64BIT /* Use IRQ to determine SError origin instead of assigning IRQ */ rc = of_property_read_u32_index(np, "interrupts", 0, &altdev->db_irq); if (rc) { @@ -2016,7 +2021,7 @@ static const struct irq_domain_ops a10_eccmgr_ic_ops = { /************** Stratix 10 EDAC Double Bit Error Handler ************/ #define to_a10edac(p, m) container_of(p, struct altr_arria10_edac, m) -#ifdef CONFIG_ARCH_STRATIX10 +#ifdef CONFIG_64BIT /* panic routine issues reboot on non-zero panic_timeout */ extern int panic_timeout; @@ -2109,7 +2114,7 @@ static int altr_edac_a10_probe(struct platform_device *pdev) altr_edac_a10_irq_handler, edac); -#ifdef CONFIG_ARCH_STRATIX10 +#ifdef CONFIG_64BIT { int dberror, err_addr; diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 3f14dffb9669..6a4e882e448d 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -206,7 +206,7 @@ config FW_CFG_SYSFS_CMDLINE config INTEL_STRATIX10_SERVICE tristate "Intel Stratix10 Service Layer" - depends on (ARCH_STRATIX10 || ARCH_AGILEX) && HAVE_ARM_SMCCC + depends on ARCH_INTEL_SOCFPGA && HAVE_ARM_SMCCC default n help Intel Stratix10 service layer runs at privileged exception level, diff --git a/drivers/firmware/imx/scu-pd.c b/drivers/firmware/imx/scu-pd.c index 08533ee67626..ff6569c4a53b 100644 --- a/drivers/firmware/imx/scu-pd.c +++ b/drivers/firmware/imx/scu-pd.c @@ -29,6 +29,10 @@ * The framework needs some proper extension to support multi power * domain cases. * + * Update: Genpd assigns the ->of_node for the virtual device before it + * invokes ->attach_dev() callback, hence parsing for device resources via + * DT should work fine. + * * 2. It also breaks most of current drivers as the driver probe sequence * behavior changed if removing ->power_on|off() callback and use * ->start() and ->stop() instead. genpd_dev_pm_attach will only power @@ -39,8 +43,11 @@ * domain enabled will trigger a HW access error. That means we need fix * most drivers probe sequence with proper runtime pm. * - * In summary, we need fix above two issue before being able to switch to - * the "single global power domain" way. + * Update: Runtime PM support isn't necessary. Instead, this can easily be + * fixed in drivers by adding a call to dev_pm_domain_start() during probe. + * + * In summary, the second part needs to be addressed via minor updates to the + * relevant drivers, before the "single global power domain" model can be used. * */ @@ -86,6 +93,8 @@ struct imx_sc_pd_soc { u8 num_ranges; }; +static int imx_con_rsrc; + static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { /* LSIO SS */ { "pwm", IMX_SC_R_PWM_0, 8, true, 0 }, @@ -134,7 +143,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { { "can", IMX_SC_R_CAN_0, 3, true, 0 }, { "ftm", IMX_SC_R_FTM_0, 2, true, 0 }, { "lpi2c", IMX_SC_R_I2C_0, 4, true, 0 }, - { "adc", IMX_SC_R_ADC_0, 1, true, 0 }, + { "adc", IMX_SC_R_ADC_0, 2, true, 0 }, { "lcd", IMX_SC_R_LCD_0, 1, true, 0 }, { "lcd0-pwm", IMX_SC_R_LCD_0_PWM_0, 1, true, 0 }, { "lpuart", IMX_SC_R_UART_0, 4, true, 0 }, @@ -207,6 +216,23 @@ to_imx_sc_pd(struct generic_pm_domain *genpd) return container_of(genpd, struct imx_sc_pm_domain, pd); } +static void imx_sc_pd_get_console_rsrc(void) +{ + struct of_phandle_args specs; + int ret; + + if (!of_stdout) + return; + + ret = of_parse_phandle_with_args(of_stdout, "power-domains", + "#power-domain-cells", + 0, &specs); + if (ret) + return; + + imx_con_rsrc = specs.args[0]; +} + static int imx_sc_pd_power(struct generic_pm_domain *domain, bool power_on) { struct imx_sc_msg_req_set_resource_power_mode msg; @@ -267,6 +293,7 @@ imx_scu_add_pm_domain(struct device *dev, int idx, const struct imx_sc_pd_range *pd_ranges) { struct imx_sc_pm_domain *sc_pd; + bool is_off = true; int ret; if (!imx_sc_rm_is_resource_owned(pm_ipc_handle, pd_ranges->rsrc + idx)) @@ -288,6 +315,10 @@ imx_scu_add_pm_domain(struct device *dev, int idx, "%s", pd_ranges->name); sc_pd->pd.name = sc_pd->name; + if (imx_con_rsrc == sc_pd->rsrc) { + sc_pd->pd.flags = GENPD_FLAG_RPM_ALWAYS_ON; + is_off = false; + } if (sc_pd->rsrc >= IMX_SC_R_LAST) { dev_warn(dev, "invalid pd %s rsrc id %d found", @@ -297,7 +328,7 @@ imx_scu_add_pm_domain(struct device *dev, int idx, return NULL; } - ret = pm_genpd_init(&sc_pd->pd, NULL, true); + ret = pm_genpd_init(&sc_pd->pd, NULL, is_off); if (ret) { dev_warn(dev, "failed to init pd %s rsrc id %d", sc_pd->name, sc_pd->rsrc); @@ -363,6 +394,8 @@ static int imx_sc_pd_probe(struct platform_device *pdev) if (!pd_soc) return -ENODEV; + imx_sc_pd_get_console_rsrc(); + return imx_scu_init_pm_domains(&pdev->dev, pd_soc); } diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c index 30259dc9b805..250e01680742 100644 --- a/drivers/firmware/raspberrypi.c +++ b/drivers/firmware/raspberrypi.c @@ -7,6 +7,7 @@ */ #include <linux/dma-mapping.h> +#include <linux/kref.h> #include <linux/mailbox_client.h> #include <linux/module.h> #include <linux/of_platform.h> @@ -27,6 +28,8 @@ struct rpi_firmware { struct mbox_chan *chan; /* The property channel. */ struct completion c; u32 enabled; + + struct kref consumers; }; static DEFINE_MUTEX(transaction_lock); @@ -225,12 +228,38 @@ static void rpi_register_clk_driver(struct device *dev) -1, NULL, 0); } +static void rpi_firmware_delete(struct kref *kref) +{ + struct rpi_firmware *fw = container_of(kref, struct rpi_firmware, + consumers); + + mbox_free_channel(fw->chan); + kfree(fw); +} + +void rpi_firmware_put(struct rpi_firmware *fw) +{ + kref_put(&fw->consumers, rpi_firmware_delete); +} +EXPORT_SYMBOL_GPL(rpi_firmware_put); + +static void devm_rpi_firmware_put(void *data) +{ + struct rpi_firmware *fw = data; + + rpi_firmware_put(fw); +} + static int rpi_firmware_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct rpi_firmware *fw; - fw = devm_kzalloc(dev, sizeof(*fw), GFP_KERNEL); + /* + * Memory will be freed by rpi_firmware_delete() once all users have + * released their firmware handles. Don't use devm_kzalloc() here. + */ + fw = kzalloc(sizeof(*fw), GFP_KERNEL); if (!fw) return -ENOMEM; @@ -247,6 +276,7 @@ static int rpi_firmware_probe(struct platform_device *pdev) } init_completion(&fw->c); + kref_init(&fw->consumers); platform_set_drvdata(pdev, fw); @@ -275,7 +305,8 @@ static int rpi_firmware_remove(struct platform_device *pdev) rpi_hwmon = NULL; platform_device_unregister(rpi_clk); rpi_clk = NULL; - mbox_free_channel(fw->chan); + + rpi_firmware_put(fw); return 0; } @@ -284,19 +315,51 @@ static int rpi_firmware_remove(struct platform_device *pdev) * rpi_firmware_get - Get pointer to rpi_firmware structure. * @firmware_node: Pointer to the firmware Device Tree node. * + * The reference to rpi_firmware has to be released with rpi_firmware_put(). + * * Returns NULL is the firmware device is not ready. */ struct rpi_firmware *rpi_firmware_get(struct device_node *firmware_node) { struct platform_device *pdev = of_find_device_by_node(firmware_node); + struct rpi_firmware *fw; if (!pdev) return NULL; - return platform_get_drvdata(pdev); + fw = platform_get_drvdata(pdev); + if (!fw) + return NULL; + + if (!kref_get_unless_zero(&fw->consumers)) + return NULL; + + return fw; } EXPORT_SYMBOL_GPL(rpi_firmware_get); +/** + * devm_rpi_firmware_get - Get pointer to rpi_firmware structure. + * @firmware_node: Pointer to the firmware Device Tree node. + * + * Returns NULL is the firmware device is not ready. + */ +struct rpi_firmware *devm_rpi_firmware_get(struct device *dev, + struct device_node *firmware_node) +{ + struct rpi_firmware *fw; + + fw = rpi_firmware_get(firmware_node); + if (!fw) + return NULL; + + if (devm_add_action_or_reset(dev, devm_rpi_firmware_put, fw)) + return NULL; + + return fw; +} +EXPORT_SYMBOL_GPL(devm_rpi_firmware_get); + static const struct of_device_id rpi_firmware_of_match[] = { { .compatible = "raspberrypi,bcm2835-firmware", }, {}, diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index 5ff9438b7b46..b1026c6fb119 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -14,13 +14,13 @@ if FPGA config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" - depends on ARCH_SOCFPGA || COMPILE_TEST + depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST help FPGA manager driver support for Altera SOCFPGA. config FPGA_MGR_SOCFPGA_A10 tristate "Altera SoCFPGA Arria10" - depends on ARCH_SOCFPGA || COMPILE_TEST + depends on ARCH_INTEL_SOCFPGA || COMPILE_TEST select REGMAP_MMIO help FPGA manager driver support for Altera Arria10 SoCFPGA. @@ -60,7 +60,7 @@ config FPGA_MGR_ZYNQ_FPGA config FPGA_MGR_STRATIX10_SOC tristate "Intel Stratix10 SoC FPGA Manager" - depends on (ARCH_STRATIX10 && INTEL_STRATIX10_SERVICE) + depends on (ARCH_INTEL_SOCFPGA && INTEL_STRATIX10_SERVICE) help FPGA manager driver support for the Intel Stratix10 SoC. @@ -99,7 +99,7 @@ config FPGA_BRIDGE config SOCFPGA_FPGA_BRIDGE tristate "Altera SoCFPGA FPGA Bridges" - depends on ARCH_SOCFPGA && FPGA_BRIDGE + depends on ARCH_INTEL_SOCFPGA && FPGA_BRIDGE help Say Y to enable drivers for FPGA bridges for Altera SOCFPGA devices. diff --git a/drivers/gpio/gpio-raspberrypi-exp.c b/drivers/gpio/gpio-raspberrypi-exp.c index bb100e0124e6..64a552ecc2ad 100644 --- a/drivers/gpio/gpio-raspberrypi-exp.c +++ b/drivers/gpio/gpio-raspberrypi-exp.c @@ -208,7 +208,7 @@ static int rpi_exp_gpio_probe(struct platform_device *pdev) return -ENOENT; } - fw = rpi_firmware_get(fw_node); + fw = devm_rpi_firmware_get(&pdev->dev, fw_node); of_node_put(fw_node); if (!fw) return -EPROBE_DEFER; diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 05ebf7546e3f..3eec59f1fed3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -369,7 +369,7 @@ comment "I2C system bus drivers (mostly embedded / system-on-chip)" config I2C_ALTERA tristate "Altera Soft IP I2C" - depends on ARCH_SOCFPGA || NIOS2 || COMPILE_TEST + depends on ARCH_INTEL_SOCFPGA || NIOS2 || COMPILE_TEST depends on OF help If you say yes to this option, support will be included for the diff --git a/drivers/input/touchscreen/raspberrypi-ts.c b/drivers/input/touchscreen/raspberrypi-ts.c index ef6aaed217cf..5000f5fd9ec3 100644 --- a/drivers/input/touchscreen/raspberrypi-ts.c +++ b/drivers/input/touchscreen/raspberrypi-ts.c @@ -160,7 +160,7 @@ static int rpi_ts_probe(struct platform_device *pdev) touchbuf = (u32)ts->fw_regs_phys; error = rpi_firmware_property(fw, RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF, &touchbuf, sizeof(touchbuf)); - + rpi_firmware_put(fw); if (error || touchbuf != 0) { dev_warn(dev, "Failed to set touchbuf, %d\n", error); return error; diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b74efa469e90..2ce9edb90901 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -21,7 +21,7 @@ config MFD_CS5535 config MFD_ALTERA_A10SR bool "Altera Arria10 DevKit System Resource chip" - depends on ARCH_SOCFPGA && SPI_MASTER=y && OF + depends on ARCH_INTEL_SOCFPGA && SPI_MASTER=y && OF select REGMAP_SPI select MFD_CORE help @@ -32,7 +32,7 @@ config MFD_ALTERA_A10SR config MFD_ALTERA_SYSMGR bool "Altera SOCFPGA System Manager" - depends on (ARCH_SOCFPGA || ARCH_STRATIX10) && OF + depends on ARCH_INTEL_SOCFPGA && OF select MFD_SYSCON help Select this to get System Manager support for all Altera branded diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index e675ba12fde2..7737e4d0bb9e 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -140,8 +140,8 @@ config DWMAC_ROCKCHIP config DWMAC_SOCFPGA tristate "SOCFPGA dwmac support" - default (ARCH_SOCFPGA || ARCH_STRATIX10) - depends on OF && (ARCH_SOCFPGA || ARCH_STRATIX10 || COMPILE_TEST) + default ARCH_INTEL_SOCFPGA + depends on OF && (ARCH_INTEL_SOCFPGA || COMPILE_TEST) select MFD_SYSCON help Support for ethernet controller on Altera SOCFPGA diff --git a/drivers/pci/controller/dwc/pci-dra7xx.c b/drivers/pci/controller/dwc/pci-dra7xx.c index b105af63854a..047cfbdc1330 100644 --- a/drivers/pci/controller/dwc/pci-dra7xx.c +++ b/drivers/pci/controller/dwc/pci-dra7xx.c @@ -443,8 +443,8 @@ static const struct dw_pcie_ep_ops pcie_ep_ops = { .get_features = dra7xx_pcie_get_features, }; -static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, - struct platform_device *pdev) +static int dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, + struct platform_device *pdev) { int ret; struct dw_pcie_ep *ep; @@ -472,8 +472,8 @@ static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx, return 0; } -static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, - struct platform_device *pdev) +static int dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx, + struct platform_device *pdev) { int ret; struct dw_pcie *pci = dra7xx->pci; @@ -682,7 +682,7 @@ static int dra7xx_pcie_configure_two_lane(struct device *dev, return 0; } -static int __init dra7xx_pcie_probe(struct platform_device *pdev) +static int dra7xx_pcie_probe(struct platform_device *pdev) { u32 reg; int ret; @@ -938,6 +938,7 @@ static const struct dev_pm_ops dra7xx_pcie_pm_ops = { }; static struct platform_driver dra7xx_pcie_driver = { + .probe = dra7xx_pcie_probe, .driver = { .name = "dra7-pcie", .of_match_table = of_dra7xx_pcie_match, @@ -946,4 +947,4 @@ static struct platform_driver dra7xx_pcie_driver = { }, .shutdown = dra7xx_pcie_shutdown, }; -builtin_platform_driver_probe(dra7xx_pcie_driver, dra7xx_pcie_probe); +builtin_platform_driver(dra7xx_pcie_driver); diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 9a4f66ae8070..43d9f1884cd3 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -423,6 +423,15 @@ config PWM_PXA To compile this driver as a module, choose M here: the module will be called pwm-pxa. +config PWM_RASPBERRYPI_POE + tristate "Raspberry Pi Firwmware PoE Hat PWM support" + # Make sure not 'y' when RASPBERRYPI_FIRMWARE is 'm'. This can only + # happen when COMPILE_TEST=y, hence the added !RASPBERRYPI_FIRMWARE. + depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE) + help + Enable Raspberry Pi firmware controller PWM bus used to control the + official RPI PoE hat + config PWM_RCAR tristate "Renesas R-Car PWM support" depends on ARCH_RENESAS || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 6374d3b1d6f3..211db810c439 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -38,6 +38,7 @@ obj-$(CONFIG_PWM_MXS) += pwm-mxs.o obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o obj-$(CONFIG_PWM_PXA) += pwm-pxa.o +obj-$(CONFIG_PWM_RASPBERRYPI_POE) += pwm-raspberrypi-poe.o obj-$(CONFIG_PWM_RCAR) += pwm-rcar.o obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o diff --git a/drivers/pwm/pwm-raspberrypi-poe.c b/drivers/pwm/pwm-raspberrypi-poe.c new file mode 100644 index 000000000000..043fc32e8be8 --- /dev/null +++ b/drivers/pwm/pwm-raspberrypi-poe.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2021 Nicolas Saenz Julienne <nsaenzjulienne@suse.de> + * For more information on Raspberry Pi's PoE hat see: + * https://www.raspberrypi.org/products/poe-hat/ + * + * Limitations: + * - No disable bit, so a disabled PWM is simulated by duty_cycle 0 + * - Only normal polarity + * - Fixed 12.5 kHz period + * + * The current period is completed when HW is reconfigured. + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> + +#include <soc/bcm2835/raspberrypi-firmware.h> +#include <dt-bindings/pwm/raspberrypi,firmware-poe-pwm.h> + +#define RPI_PWM_MAX_DUTY 255 +#define RPI_PWM_PERIOD_NS 80000 /* 12.5 kHz */ + +#define RPI_PWM_CUR_DUTY_REG 0x0 + +struct raspberrypi_pwm { + struct rpi_firmware *firmware; + struct pwm_chip chip; + unsigned int duty_cycle; +}; + +struct raspberrypi_pwm_prop { + __le32 reg; + __le32 val; + __le32 ret; +} __packed; + +static inline +struct raspberrypi_pwm *raspberrypi_pwm_from_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct raspberrypi_pwm, chip); +} + +static int raspberrypi_pwm_set_property(struct rpi_firmware *firmware, + u32 reg, u32 val) +{ + struct raspberrypi_pwm_prop msg = { + .reg = cpu_to_le32(reg), + .val = cpu_to_le32(val), + }; + int ret; + + ret = rpi_firmware_property(firmware, RPI_FIRMWARE_SET_POE_HAT_VAL, + &msg, sizeof(msg)); + if (ret) + return ret; + if (msg.ret) + return -EIO; + + return 0; +} + +static int raspberrypi_pwm_get_property(struct rpi_firmware *firmware, + u32 reg, u32 *val) +{ + struct raspberrypi_pwm_prop msg = { + .reg = reg + }; + int ret; + + ret = rpi_firmware_property(firmware, RPI_FIRMWARE_GET_POE_HAT_VAL, + &msg, sizeof(msg)); + if (ret) + return ret; + if (msg.ret) + return -EIO; + + *val = le32_to_cpu(msg.val); + + return 0; +} + +static void raspberrypi_pwm_get_state(struct pwm_chip *chip, + struct pwm_device *pwm, + struct pwm_state *state) +{ + struct raspberrypi_pwm *rpipwm = raspberrypi_pwm_from_chip(chip); + + state->period = RPI_PWM_PERIOD_NS; + state->duty_cycle = DIV_ROUND_UP(rpipwm->duty_cycle * RPI_PWM_PERIOD_NS, + RPI_PWM_MAX_DUTY); + state->enabled = !!(rpipwm->duty_cycle); + state->polarity = PWM_POLARITY_NORMAL; +} + +static int raspberrypi_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct raspberrypi_pwm *rpipwm = raspberrypi_pwm_from_chip(chip); + unsigned int duty_cycle; + int ret; + + if (state->period < RPI_PWM_PERIOD_NS || + state->polarity != PWM_POLARITY_NORMAL) + return -EINVAL; + + if (!state->enabled) + duty_cycle = 0; + else if (state->duty_cycle < RPI_PWM_PERIOD_NS) + duty_cycle = DIV_ROUND_DOWN_ULL(state->duty_cycle * RPI_PWM_MAX_DUTY, + RPI_PWM_PERIOD_NS); + else + duty_cycle = RPI_PWM_MAX_DUTY; + + if (duty_cycle == rpipwm->duty_cycle) + return 0; + + ret = raspberrypi_pwm_set_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG, + duty_cycle); + if (ret) { + dev_err(chip->dev, "Failed to set duty cycle: %pe\n", + ERR_PTR(ret)); + return ret; + } + + rpipwm->duty_cycle = duty_cycle; + + return 0; +} + +static const struct pwm_ops raspberrypi_pwm_ops = { + .get_state = raspberrypi_pwm_get_state, + .apply = raspberrypi_pwm_apply, + .owner = THIS_MODULE, +}; + +static int raspberrypi_pwm_probe(struct platform_device *pdev) +{ + struct device_node *firmware_node; + struct device *dev = &pdev->dev; + struct rpi_firmware *firmware; + struct raspberrypi_pwm *rpipwm; + int ret; + + firmware_node = of_get_parent(dev->of_node); + if (!firmware_node) { + dev_err(dev, "Missing firmware node\n"); + return -ENOENT; + } + + firmware = devm_rpi_firmware_get(&pdev->dev, firmware_node); + of_node_put(firmware_node); + if (!firmware) + return dev_err_probe(dev, -EPROBE_DEFER, + "Failed to get firmware handle\n"); + + rpipwm = devm_kzalloc(&pdev->dev, sizeof(*rpipwm), GFP_KERNEL); + if (!rpipwm) + return -ENOMEM; + + rpipwm->firmware = firmware; + rpipwm->chip.dev = dev; + rpipwm->chip.ops = &raspberrypi_pwm_ops; + rpipwm->chip.base = -1; + rpipwm->chip.npwm = RASPBERRYPI_FIRMWARE_PWM_NUM; + + platform_set_drvdata(pdev, rpipwm); + + ret = raspberrypi_pwm_get_property(rpipwm->firmware, RPI_PWM_CUR_DUTY_REG, + &rpipwm->duty_cycle); + if (ret) { + dev_err(dev, "Failed to get duty cycle: %pe\n", ERR_PTR(ret)); + return ret; + } + + return pwmchip_add(&rpipwm->chip); +} + +static int raspberrypi_pwm_remove(struct platform_device *pdev) +{ + struct raspberrypi_pwm *rpipwm = platform_get_drvdata(pdev); + + return pwmchip_remove(&rpipwm->chip); +} + +static const struct of_device_id raspberrypi_pwm_of_match[] = { + { .compatible = "raspberrypi,firmware-poe-pwm", }, + { } +}; +MODULE_DEVICE_TABLE(of, raspberrypi_pwm_of_match); + +static struct platform_driver raspberrypi_pwm_driver = { + .driver = { + .name = "raspberrypi-poe-pwm", + .of_match_table = raspberrypi_pwm_of_match, + }, + .probe = raspberrypi_pwm_probe, + .remove = raspberrypi_pwm_remove, +}; +module_platform_driver(raspberrypi_pwm_driver); + +MODULE_AUTHOR("Nicolas Saenz Julienne <nsaenzjulienne@suse.de>"); +MODULE_DESCRIPTION("Raspberry Pi Firmware Based PWM Bus Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 4171c6f76385..7043c7f6dcf0 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -183,7 +183,7 @@ config RESET_SCMI config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST - default ARCH_AGILEX || ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARC + default ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC help This enables a simple reset controller driver for reset lines that that can be asserted and deasserted by toggling bits in a contiguous, @@ -205,8 +205,8 @@ config RESET_STM32MP157 This enables the RCC reset controller driver for STM32 MPUs. config RESET_SOCFPGA - bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA - default ARCH_SOCFPGA + bool "SoCFPGA Reset Driver" if COMPILE_TEST && (!ARM || !ARCH_INTEL_SOCFPGA) + default ARM && ARCH_INTEL_SOCFPGA select RESET_SIMPLE help This enables the reset driver for the SoCFPGA ARMv7 platforms. This diff --git a/drivers/reset/reset-raspberrypi.c b/drivers/reset/reset-raspberrypi.c index 02f59c06f69b..fa23db554bcf 100644 --- a/drivers/reset/reset-raspberrypi.c +++ b/drivers/reset/reset-raspberrypi.c @@ -82,7 +82,7 @@ static int rpi_reset_probe(struct platform_device *pdev) return -ENOENT; } - fw = rpi_firmware_get(np); + fw = devm_rpi_firmware_get(&pdev->dev, np); of_node_put(np); if (!fw) return -EPROBE_DEFER; diff --git a/drivers/soc/bcm/bcm63xx/bcm-pmb.c b/drivers/soc/bcm/bcm63xx/bcm-pmb.c index c223023dc64f..774465c119be 100644 --- a/drivers/soc/bcm/bcm63xx/bcm-pmb.c +++ b/drivers/soc/bcm/bcm63xx/bcm-pmb.c @@ -209,6 +209,28 @@ static int bcm_pmb_power_on_device(struct bcm_pmb *pmb, int bus, u8 device) return err; } +static int bcm_pmb_power_on_sata(struct bcm_pmb *pmb, int bus, u8 device) +{ + int err; + + err = bcm_pmb_power_on_zone(pmb, bus, device, 0); + if (err) + return err; + + /* Does not apply to the BCM963158 */ + err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_MISC_CONTROL, 0); + if (err) + return err; + + err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0xffffffff); + if (err) + return err; + + err = bcm_pmb_bpcm_write(pmb, bus, device, BPCM_SR_CONTROL, 0); + + return err; +} + static int bcm_pmb_power_on(struct generic_pm_domain *genpd) { struct bcm_pmb_pm_domain *pd = container_of(genpd, struct bcm_pmb_pm_domain, genpd); @@ -222,6 +244,8 @@ static int bcm_pmb_power_on(struct generic_pm_domain *genpd) return bcm_pmb_power_on_zone(pmb, data->bus, data->device, 0); case BCM_PMB_HOST_USB: return bcm_pmb_power_on_device(pmb, data->bus, data->device); + case BCM_PMB_SATA: + return bcm_pmb_power_on_sata(pmb, data->bus, data->device); default: dev_err(pmb->dev, "unsupported device id: %d\n", data->id); return -EINVAL; @@ -317,8 +341,14 @@ static const struct bcm_pmb_pd_data bcm_pmb_bcm4908_data[] = { { }, }; +static const struct bcm_pmb_pd_data bcm_pmb_bcm63138_data[] = { + { .name = "sata", .id = BCM_PMB_SATA, .bus = 0, .device = 3, }, + { }, +}; + static const struct of_device_id bcm_pmb_of_match[] = { { .compatible = "brcm,bcm4908-pmb", .data = &bcm_pmb_bcm4908_data, }, + { .compatible = "brcm,bcm63138-pmb", .data = &bcm_pmb_bcm63138_data, }, { }, }; diff --git a/drivers/soc/bcm/raspberrypi-power.c b/drivers/soc/bcm/raspberrypi-power.c index 5d1aacdd84ef..068715d6e66d 100644 --- a/drivers/soc/bcm/raspberrypi-power.c +++ b/drivers/soc/bcm/raspberrypi-power.c @@ -177,7 +177,7 @@ static int rpi_power_probe(struct platform_device *pdev) return -ENODEV; } - rpi_domains->fw = rpi_firmware_get(fw_np); + rpi_domains->fw = devm_rpi_firmware_get(&pdev->dev, fw_np); of_node_put(fw_np); if (!rpi_domains->fw) return -EPROBE_DEFER; diff --git a/drivers/soc/imx/soc-imx.c b/drivers/soc/imx/soc-imx.c index 01bfea1cb64a..0738c0f36792 100644 --- a/drivers/soc/imx/soc-imx.c +++ b/drivers/soc/imx/soc-imx.c @@ -13,6 +13,8 @@ #include <soc/imx/cpu.h> #include <soc/imx/revision.h> +#define IIM_UID 0x820 + #define OCOTP_UID_H 0x420 #define OCOTP_UID_L 0x410 @@ -32,6 +34,7 @@ static int __init imx_soc_device_init(void) u64 soc_uid = 0; u32 val; int ret; + int i; if (of_machine_is_compatible("fsl,ls1021a")) return 0; @@ -68,9 +71,11 @@ static int __init imx_soc_device_init(void) soc_id = "i.MX35"; break; case MXC_CPU_MX51: + ocotp_compat = "fsl,imx51-iim"; soc_id = "i.MX51"; break; case MXC_CPU_MX53: + ocotp_compat = "fsl,imx53-iim"; soc_id = "i.MX53"; break; case MXC_CPU_IMX6SL: @@ -153,6 +158,13 @@ static int __init imx_soc_device_init(void) regmap_read(ocotp, OCOTP_ULP_UID_1, &val); soc_uid <<= 16; soc_uid |= val & 0xffff; + } else if (__mxc_cpu_type == MXC_CPU_MX51 || + __mxc_cpu_type == MXC_CPU_MX53) { + for (i=0; i < 8; i++) { + regmap_read(ocotp, IIM_UID + i*4, &val); + soc_uid <<= 8; + soc_uid |= (val & 0xff); + } } else { regmap_read(ocotp, OCOTP_UID_H, &val); soc_uid = val; diff --git a/drivers/soc/mediatek/mt8167-pm-domains.h b/drivers/soc/mediatek/mt8167-pm-domains.h index ad0b8dfa0527..15559ddf26e4 100644 --- a/drivers/soc/mediatek/mt8167-pm-domains.h +++ b/drivers/soc/mediatek/mt8167-pm-domains.h @@ -15,6 +15,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { [MT8167_POWER_DOMAIN_MM] = { + .name = "mm", .sta_mask = PWR_STATUS_DISP, .ctl_offs = SPM_DIS_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), @@ -26,6 +27,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { .caps = MTK_SCPD_ACTIVE_WAKEUP, }, [MT8167_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = PWR_STATUS_VDEC, .ctl_offs = SPM_VDE_PWR_CON, .sram_pdn_bits = GENMASK(8, 8), @@ -33,6 +35,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { .caps = MTK_SCPD_ACTIVE_WAKEUP, }, [MT8167_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = PWR_STATUS_ISP, .ctl_offs = SPM_ISP_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), @@ -40,6 +43,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { .caps = MTK_SCPD_ACTIVE_WAKEUP, }, [MT8167_POWER_DOMAIN_MFG_ASYNC] = { + .name = "mfg_async", .sta_mask = MT8167_PWR_STATUS_MFG_ASYNC, .ctl_offs = SPM_MFG_ASYNC_PWR_CON, .sram_pdn_bits = 0, @@ -50,18 +54,21 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8167[] = { }, }, [MT8167_POWER_DOMAIN_MFG_2D] = { + .name = "mfg_2d", .sta_mask = MT8167_PWR_STATUS_MFG_2D, .ctl_offs = SPM_MFG_2D_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8167_POWER_DOMAIN_MFG] = { + .name = "mfg", .sta_mask = PWR_STATUS_MFG, .ctl_offs = SPM_MFG_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8167_POWER_DOMAIN_CONN] = { + .name = "conn", .sta_mask = PWR_STATUS_CONN, .ctl_offs = SPM_CONN_PWR_CON, .sram_pdn_bits = GENMASK(8, 8), diff --git a/drivers/soc/mediatek/mt8173-pm-domains.h b/drivers/soc/mediatek/mt8173-pm-domains.h index 3e8ee5dabb43..654c717e5467 100644 --- a/drivers/soc/mediatek/mt8173-pm-domains.h +++ b/drivers/soc/mediatek/mt8173-pm-domains.h @@ -12,24 +12,28 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { [MT8173_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = PWR_STATUS_VDEC, .ctl_offs = SPM_VDE_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8173_POWER_DOMAIN_VENC] = { + .name = "venc", .sta_mask = PWR_STATUS_VENC, .ctl_offs = SPM_VEN_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8173_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = PWR_STATUS_ISP, .ctl_offs = SPM_ISP_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(13, 12), }, [MT8173_POWER_DOMAIN_MM] = { + .name = "mm", .sta_mask = PWR_STATUS_DISP, .ctl_offs = SPM_DIS_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), @@ -40,18 +44,21 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { }, }, [MT8173_POWER_DOMAIN_VENC_LT] = { + .name = "venc_lt", .sta_mask = PWR_STATUS_VENC_LT, .ctl_offs = SPM_VEN2_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8173_POWER_DOMAIN_AUDIO] = { + .name = "audio", .sta_mask = PWR_STATUS_AUDIO, .ctl_offs = SPM_AUDIO_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8173_POWER_DOMAIN_USB] = { + .name = "usb", .sta_mask = PWR_STATUS_USB, .ctl_offs = SPM_USB_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), @@ -59,18 +66,21 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = { .caps = MTK_SCPD_ACTIVE_WAKEUP, }, [MT8173_POWER_DOMAIN_MFG_ASYNC] = { + .name = "mfg_async", .sta_mask = PWR_STATUS_MFG_ASYNC, .ctl_offs = SPM_MFG_ASYNC_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = 0, }, [MT8173_POWER_DOMAIN_MFG_2D] = { + .name = "mfg_2d", .sta_mask = PWR_STATUS_MFG_2D, .ctl_offs = SPM_MFG_2D_PWR_CON, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(13, 12), }, [MT8173_POWER_DOMAIN_MFG] = { + .name = "mfg", .sta_mask = PWR_STATUS_MFG, .ctl_offs = SPM_MFG_PWR_CON, .sram_pdn_bits = GENMASK(13, 8), diff --git a/drivers/soc/mediatek/mt8183-mmsys.h b/drivers/soc/mediatek/mt8183-mmsys.h new file mode 100644 index 000000000000..579dfc8dc8fc --- /dev/null +++ b/drivers/soc/mediatek/mt8183-mmsys.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MT8183_MMSYS_H +#define __SOC_MEDIATEK_MT8183_MMSYS_H + +#define MT8183_DISP_OVL0_MOUT_EN 0xf00 +#define MT8183_DISP_OVL0_2L_MOUT_EN 0xf04 +#define MT8183_DISP_OVL1_2L_MOUT_EN 0xf08 +#define MT8183_DISP_DITHER0_MOUT_EN 0xf0c +#define MT8183_DISP_PATH0_SEL_IN 0xf24 +#define MT8183_DISP_DSI0_SEL_IN 0xf2c +#define MT8183_DISP_DPI0_SEL_IN 0xf30 +#define MT8183_DISP_RDMA0_SOUT_SEL_IN 0xf50 +#define MT8183_DISP_RDMA1_SOUT_SEL_IN 0xf54 + +#define MT8183_OVL0_MOUT_EN_OVL0_2L BIT(4) +#define MT8183_OVL0_2L_MOUT_EN_DISP_PATH0 BIT(0) +#define MT8183_OVL1_2L_MOUT_EN_RDMA1 BIT(4) +#define MT8183_DITHER0_MOUT_IN_DSI0 BIT(0) +#define MT8183_DISP_PATH0_SEL_IN_OVL0_2L 0x1 +#define MT8183_DSI0_SEL_IN_RDMA0 0x1 +#define MT8183_DSI0_SEL_IN_RDMA1 0x3 +#define MT8183_DPI0_SEL_IN_RDMA0 0x1 +#define MT8183_DPI0_SEL_IN_RDMA1 0x2 +#define MT8183_RDMA0_SOUT_COLOR0 0x1 +#define MT8183_RDMA1_SOUT_DSI0 0x1 + +static const struct mtk_mmsys_routes mmsys_mt8183_routing_table[] = { + { + DDP_COMPONENT_OVL0, DDP_COMPONENT_OVL_2L0, + MT8183_DISP_OVL0_MOUT_EN, MT8183_OVL0_MOUT_EN_OVL0_2L + }, { + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, + MT8183_DISP_OVL0_2L_MOUT_EN, MT8183_OVL0_2L_MOUT_EN_DISP_PATH0 + }, { + DDP_COMPONENT_OVL_2L1, DDP_COMPONENT_RDMA1, + MT8183_DISP_OVL1_2L_MOUT_EN, MT8183_OVL1_2L_MOUT_EN_RDMA1 + }, { + DDP_COMPONENT_DITHER, DDP_COMPONENT_DSI0, + MT8183_DISP_DITHER0_MOUT_EN, MT8183_DITHER0_MOUT_IN_DSI0 + }, { + DDP_COMPONENT_OVL_2L0, DDP_COMPONENT_RDMA0, + MT8183_DISP_PATH0_SEL_IN, MT8183_DISP_PATH0_SEL_IN_OVL0_2L + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, + MT8183_DISP_DPI0_SEL_IN, MT8183_DPI0_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_COLOR0, + MT8183_DISP_RDMA0_SOUT_SEL_IN, MT8183_RDMA0_SOUT_COLOR0 + } +}; + +#endif /* __SOC_MEDIATEK_MT8183_MMSYS_H */ + diff --git a/drivers/soc/mediatek/mt8183-pm-domains.h b/drivers/soc/mediatek/mt8183-pm-domains.h index aa5230e6c12f..98a9940d05fb 100644 --- a/drivers/soc/mediatek/mt8183-pm-domains.h +++ b/drivers/soc/mediatek/mt8183-pm-domains.h @@ -12,12 +12,14 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { [MT8183_POWER_DOMAIN_AUDIO] = { + .name = "audio", .sta_mask = PWR_STATUS_AUDIO, .ctl_offs = 0x0314, .sram_pdn_bits = GENMASK(11, 8), .sram_pdn_ack_bits = GENMASK(15, 12), }, [MT8183_POWER_DOMAIN_CONN] = { + .name = "conn", .sta_mask = PWR_STATUS_CONN, .ctl_offs = 0x032c, .sram_pdn_bits = 0, @@ -28,12 +30,14 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_MFG_ASYNC] = { + .name = "mfg_async", .sta_mask = PWR_STATUS_MFG_ASYNC, .ctl_offs = 0x0334, .sram_pdn_bits = 0, .sram_pdn_ack_bits = 0, }, [MT8183_POWER_DOMAIN_MFG] = { + .name = "mfg", .sta_mask = PWR_STATUS_MFG, .ctl_offs = 0x0338, .sram_pdn_bits = GENMASK(8, 8), @@ -41,18 +45,21 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { .caps = MTK_SCPD_DOMAIN_SUPPLY, }, [MT8183_POWER_DOMAIN_MFG_CORE0] = { + .name = "mfg_core0", .sta_mask = BIT(7), .ctl_offs = 0x034c, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8183_POWER_DOMAIN_MFG_CORE1] = { + .name = "mfg_core1", .sta_mask = BIT(20), .ctl_offs = 0x0310, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8183_POWER_DOMAIN_MFG_2D] = { + .name = "mfg_2d", .sta_mask = PWR_STATUS_MFG_2D, .ctl_offs = 0x0348, .sram_pdn_bits = GENMASK(8, 8), @@ -65,6 +72,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_DISP] = { + .name = "disp", .sta_mask = PWR_STATUS_DISP, .ctl_offs = 0x030c, .sram_pdn_bits = GENMASK(8, 8), @@ -83,6 +91,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_CAM] = { + .name = "cam", .sta_mask = BIT(25), .ctl_offs = 0x0344, .sram_pdn_bits = GENMASK(9, 8), @@ -105,6 +114,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = PWR_STATUS_ISP, .ctl_offs = 0x0308, .sram_pdn_bits = GENMASK(9, 8), @@ -127,6 +137,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = BIT(31), .ctl_offs = 0x0300, .sram_pdn_bits = GENMASK(8, 8), @@ -139,6 +150,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_VENC] = { + .name = "venc", .sta_mask = PWR_STATUS_VENC, .ctl_offs = 0x0304, .sram_pdn_bits = GENMASK(11, 8), @@ -151,6 +163,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_VPU_TOP] = { + .name = "vpu_top", .sta_mask = BIT(26), .ctl_offs = 0x0324, .sram_pdn_bits = GENMASK(8, 8), @@ -177,6 +190,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { }, }, [MT8183_POWER_DOMAIN_VPU_CORE0] = { + .name = "vpu_core0", .sta_mask = BIT(27), .ctl_offs = 0x33c, .sram_pdn_bits = GENMASK(11, 8), @@ -194,6 +208,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = { .caps = MTK_SCPD_SRAM_ISO, }, [MT8183_POWER_DOMAIN_VPU_CORE1] = { + .name = "vpu_core1", .sta_mask = BIT(28), .ctl_offs = 0x0340, .sram_pdn_bits = GENMASK(11, 8), diff --git a/drivers/soc/mediatek/mt8192-pm-domains.h b/drivers/soc/mediatek/mt8192-pm-domains.h index 0fdf6dc6231f..543dda70de01 100644 --- a/drivers/soc/mediatek/mt8192-pm-domains.h +++ b/drivers/soc/mediatek/mt8192-pm-domains.h @@ -12,6 +12,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { [MT8192_POWER_DOMAIN_AUDIO] = { + .name = "audio", .sta_mask = BIT(21), .ctl_offs = 0x0354, .sram_pdn_bits = GENMASK(8, 8), @@ -24,6 +25,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_CONN] = { + .name = "conn", .sta_mask = PWR_STATUS_CONN, .ctl_offs = 0x0304, .sram_pdn_bits = 0, @@ -45,12 +47,14 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { .caps = MTK_SCPD_KEEP_DEFAULT_OFF, }, [MT8192_POWER_DOMAIN_MFG0] = { + .name = "mfg0", .sta_mask = BIT(2), .ctl_offs = 0x0308, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG1] = { + .name = "mfg1", .sta_mask = BIT(3), .ctl_offs = 0x030c, .sram_pdn_bits = GENMASK(8, 8), @@ -75,36 +79,42 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_MFG2] = { + .name = "mfg2", .sta_mask = BIT(4), .ctl_offs = 0x0310, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG3] = { + .name = "mfg3", .sta_mask = BIT(5), .ctl_offs = 0x0314, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG4] = { + .name = "mfg4", .sta_mask = BIT(6), .ctl_offs = 0x0318, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG5] = { + .name = "mfg5", .sta_mask = BIT(7), .ctl_offs = 0x031c, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_MFG6] = { + .name = "mfg6", .sta_mask = BIT(8), .ctl_offs = 0x0320, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_DISP] = { + .name = "disp", .sta_mask = BIT(20), .ctl_offs = 0x0350, .sram_pdn_bits = GENMASK(8, 8), @@ -133,6 +143,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_IPE] = { + .name = "ipe", .sta_mask = BIT(14), .ctl_offs = 0x0338, .sram_pdn_bits = GENMASK(8, 8), @@ -149,6 +160,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_ISP] = { + .name = "isp", .sta_mask = BIT(12), .ctl_offs = 0x0330, .sram_pdn_bits = GENMASK(8, 8), @@ -165,6 +177,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_ISP2] = { + .name = "isp2", .sta_mask = BIT(13), .ctl_offs = 0x0334, .sram_pdn_bits = GENMASK(8, 8), @@ -181,6 +194,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_MDP] = { + .name = "mdp", .sta_mask = BIT(19), .ctl_offs = 0x034c, .sram_pdn_bits = GENMASK(8, 8), @@ -197,6 +211,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_VENC] = { + .name = "venc", .sta_mask = BIT(17), .ctl_offs = 0x0344, .sram_pdn_bits = GENMASK(8, 8), @@ -213,6 +228,7 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_VDEC] = { + .name = "vdec", .sta_mask = BIT(15), .ctl_offs = 0x033c, .sram_pdn_bits = GENMASK(8, 8), @@ -229,12 +245,14 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_VDEC2] = { + .name = "vdec2", .sta_mask = BIT(16), .ctl_offs = 0x0340, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_CAM] = { + .name = "cam", .sta_mask = BIT(23), .ctl_offs = 0x035c, .sram_pdn_bits = GENMASK(8, 8), @@ -263,18 +281,21 @@ static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = { }, }, [MT8192_POWER_DOMAIN_CAM_RAWA] = { + .name = "cam_rawa", .sta_mask = BIT(24), .ctl_offs = 0x0360, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_CAM_RAWB] = { + .name = "cam_rawb", .sta_mask = BIT(25), .ctl_offs = 0x0364, .sram_pdn_bits = GENMASK(8, 8), .sram_pdn_ack_bits = GENMASK(12, 12), }, [MT8192_POWER_DOMAIN_CAM_RAWC] = { + .name = "cam_rawc", .sta_mask = BIT(26), .ctl_offs = 0x0368, .sram_pdn_bits = GENMASK(8, 8), diff --git a/drivers/soc/mediatek/mtk-mmsys.c b/drivers/soc/mediatek/mtk-mmsys.c index 18f93979e14a..79e55150210e 100644 --- a/drivers/soc/mediatek/mtk-mmsys.c +++ b/drivers/soc/mediatek/mtk-mmsys.c @@ -10,79 +10,19 @@ #include <linux/platform_device.h> #include <linux/soc/mediatek/mtk-mmsys.h> -#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x040 -#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN 0x044 -#define DISP_REG_CONFIG_DISP_OD_MOUT_EN 0x048 -#define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN 0x04c -#define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN 0x050 -#define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x084 -#define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN 0x088 -#define DISP_REG_CONFIG_DSIE_SEL_IN 0x0a4 -#define DISP_REG_CONFIG_DSIO_SEL_IN 0x0a8 -#define DISP_REG_CONFIG_DPI_SEL_IN 0x0ac -#define DISP_REG_CONFIG_DISP_RDMA2_SOUT 0x0b8 -#define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN 0x0c4 -#define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN 0x0c8 -#define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100 - -#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 -#define DISP_REG_CONFIG_OUT_SEL 0x04c -#define DISP_REG_CONFIG_DSI_SEL 0x050 -#define DISP_REG_CONFIG_DPI_SEL 0x064 - -#define OVL0_MOUT_EN_COLOR0 0x1 -#define OD_MOUT_EN_RDMA0 0x1 -#define OD1_MOUT_EN_RDMA1 BIT(16) -#define UFOE_MOUT_EN_DSI0 0x1 -#define COLOR0_SEL_IN_OVL0 0x1 -#define OVL1_MOUT_EN_COLOR1 0x1 -#define GAMMA_MOUT_EN_RDMA1 0x1 -#define RDMA0_SOUT_DPI0 0x2 -#define RDMA0_SOUT_DPI1 0x3 -#define RDMA0_SOUT_DSI1 0x1 -#define RDMA0_SOUT_DSI2 0x4 -#define RDMA0_SOUT_DSI3 0x5 -#define RDMA1_SOUT_DPI0 0x2 -#define RDMA1_SOUT_DPI1 0x3 -#define RDMA1_SOUT_DSI1 0x1 -#define RDMA1_SOUT_DSI2 0x4 -#define RDMA1_SOUT_DSI3 0x5 -#define RDMA2_SOUT_DPI0 0x2 -#define RDMA2_SOUT_DPI1 0x3 -#define RDMA2_SOUT_DSI1 0x1 -#define RDMA2_SOUT_DSI2 0x4 -#define RDMA2_SOUT_DSI3 0x5 -#define DPI0_SEL_IN_RDMA1 0x1 -#define DPI0_SEL_IN_RDMA2 0x3 -#define DPI1_SEL_IN_RDMA1 (0x1 << 8) -#define DPI1_SEL_IN_RDMA2 (0x3 << 8) -#define DSI0_SEL_IN_RDMA1 0x1 -#define DSI0_SEL_IN_RDMA2 0x4 -#define DSI1_SEL_IN_RDMA1 0x1 -#define DSI1_SEL_IN_RDMA2 0x4 -#define DSI2_SEL_IN_RDMA1 (0x1 << 16) -#define DSI2_SEL_IN_RDMA2 (0x4 << 16) -#define DSI3_SEL_IN_RDMA1 (0x1 << 16) -#define DSI3_SEL_IN_RDMA2 (0x4 << 16) -#define COLOR1_SEL_IN_OVL1 0x1 - -#define OVL_MOUT_EN_RDMA 0x1 -#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 -#define BLS_TO_DPI_RDMA1_TO_DSI 0x2 -#define DSI_SEL_IN_BLS 0x0 -#define DPI_SEL_IN_BLS 0x0 -#define DSI_SEL_IN_RDMA 0x1 - -struct mtk_mmsys_driver_data { - const char *clk_driver; -}; +#include "mtk-mmsys.h" +#include "mt8183-mmsys.h" static const struct mtk_mmsys_driver_data mt2701_mmsys_driver_data = { .clk_driver = "clk-mt2701-mm", + .routes = mmsys_default_routing_table, + .num_routes = ARRAY_SIZE(mmsys_default_routing_table), }; static const struct mtk_mmsys_driver_data mt2712_mmsys_driver_data = { .clk_driver = "clk-mt2712-mm", + .routes = mmsys_default_routing_table, + .num_routes = ARRAY_SIZE(mmsys_default_routing_table), }; static const struct mtk_mmsys_driver_data mt6779_mmsys_driver_data = { @@ -95,186 +35,35 @@ static const struct mtk_mmsys_driver_data mt6797_mmsys_driver_data = { static const struct mtk_mmsys_driver_data mt8173_mmsys_driver_data = { .clk_driver = "clk-mt8173-mm", + .routes = mmsys_default_routing_table, + .num_routes = ARRAY_SIZE(mmsys_default_routing_table), }; static const struct mtk_mmsys_driver_data mt8183_mmsys_driver_data = { .clk_driver = "clk-mt8183-mm", + .routes = mmsys_mt8183_routing_table, + .num_routes = ARRAY_SIZE(mmsys_mt8183_routing_table), }; -static unsigned int mtk_mmsys_ddp_mout_en(enum mtk_ddp_comp_id cur, - enum mtk_ddp_comp_id next, - unsigned int *addr) -{ - unsigned int value; - - if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { - *addr = DISP_REG_CONFIG_DISP_OVL0_MOUT_EN; - value = OVL0_MOUT_EN_COLOR0; - } else if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_RDMA0) { - *addr = DISP_REG_CONFIG_DISP_OVL_MOUT_EN; - value = OVL_MOUT_EN_RDMA; - } else if (cur == DDP_COMPONENT_OD0 && next == DDP_COMPONENT_RDMA0) { - *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; - value = OD_MOUT_EN_RDMA0; - } else if (cur == DDP_COMPONENT_UFOE && next == DDP_COMPONENT_DSI0) { - *addr = DISP_REG_CONFIG_DISP_UFOE_MOUT_EN; - value = UFOE_MOUT_EN_DSI0; - } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { - *addr = DISP_REG_CONFIG_DISP_OVL1_MOUT_EN; - value = OVL1_MOUT_EN_COLOR1; - } else if (cur == DDP_COMPONENT_GAMMA && next == DDP_COMPONENT_RDMA1) { - *addr = DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN; - value = GAMMA_MOUT_EN_RDMA1; - } else if (cur == DDP_COMPONENT_OD1 && next == DDP_COMPONENT_RDMA1) { - *addr = DISP_REG_CONFIG_DISP_OD_MOUT_EN; - value = OD1_MOUT_EN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI0) { - *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; - value = RDMA0_SOUT_DPI0; - } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DPI1) { - *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; - value = RDMA0_SOUT_DPI1; - } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI1) { - *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; - value = RDMA0_SOUT_DSI1; - } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI2) { - *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; - value = RDMA0_SOUT_DSI2; - } else if (cur == DDP_COMPONENT_RDMA0 && next == DDP_COMPONENT_DSI3) { - *addr = DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN; - value = RDMA0_SOUT_DSI3; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) { - *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN; - value = RDMA1_SOUT_DSI1; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) { - *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN; - value = RDMA1_SOUT_DSI2; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) { - *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN; - value = RDMA1_SOUT_DSI3; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) { - *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN; - value = RDMA1_SOUT_DPI0; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) { - *addr = DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN; - value = RDMA1_SOUT_DPI1; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) { - *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT; - value = RDMA2_SOUT_DPI0; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) { - *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT; - value = RDMA2_SOUT_DPI1; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) { - *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT; - value = RDMA2_SOUT_DSI1; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) { - *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT; - value = RDMA2_SOUT_DSI2; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) { - *addr = DISP_REG_CONFIG_DISP_RDMA2_SOUT; - value = RDMA2_SOUT_DSI3; - } else { - value = 0; - } - - return value; -} - -static unsigned int mtk_mmsys_ddp_sel_in(enum mtk_ddp_comp_id cur, - enum mtk_ddp_comp_id next, - unsigned int *addr) -{ - unsigned int value; - - if (cur == DDP_COMPONENT_OVL0 && next == DDP_COMPONENT_COLOR0) { - *addr = DISP_REG_CONFIG_DISP_COLOR0_SEL_IN; - value = COLOR0_SEL_IN_OVL0; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI0) { - *addr = DISP_REG_CONFIG_DPI_SEL_IN; - value = DPI0_SEL_IN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DPI1) { - *addr = DISP_REG_CONFIG_DPI_SEL_IN; - value = DPI1_SEL_IN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI0) { - *addr = DISP_REG_CONFIG_DSIE_SEL_IN; - value = DSI0_SEL_IN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI1) { - *addr = DISP_REG_CONFIG_DSIO_SEL_IN; - value = DSI1_SEL_IN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI2) { - *addr = DISP_REG_CONFIG_DSIE_SEL_IN; - value = DSI2_SEL_IN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA1 && next == DDP_COMPONENT_DSI3) { - *addr = DISP_REG_CONFIG_DSIO_SEL_IN; - value = DSI3_SEL_IN_RDMA1; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI0) { - *addr = DISP_REG_CONFIG_DPI_SEL_IN; - value = DPI0_SEL_IN_RDMA2; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DPI1) { - *addr = DISP_REG_CONFIG_DPI_SEL_IN; - value = DPI1_SEL_IN_RDMA2; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI0) { - *addr = DISP_REG_CONFIG_DSIE_SEL_IN; - value = DSI0_SEL_IN_RDMA2; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI1) { - *addr = DISP_REG_CONFIG_DSIO_SEL_IN; - value = DSI1_SEL_IN_RDMA2; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI2) { - *addr = DISP_REG_CONFIG_DSIE_SEL_IN; - value = DSI2_SEL_IN_RDMA2; - } else if (cur == DDP_COMPONENT_RDMA2 && next == DDP_COMPONENT_DSI3) { - *addr = DISP_REG_CONFIG_DSIE_SEL_IN; - value = DSI3_SEL_IN_RDMA2; - } else if (cur == DDP_COMPONENT_OVL1 && next == DDP_COMPONENT_COLOR1) { - *addr = DISP_REG_CONFIG_DISP_COLOR1_SEL_IN; - value = COLOR1_SEL_IN_OVL1; - } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) { - *addr = DISP_REG_CONFIG_DSI_SEL; - value = DSI_SEL_IN_BLS; - } else { - value = 0; - } - - return value; -} - -static void mtk_mmsys_ddp_sout_sel(void __iomem *config_regs, - enum mtk_ddp_comp_id cur, - enum mtk_ddp_comp_id next) -{ - if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DSI0) { - writel_relaxed(BLS_TO_DSI_RDMA1_TO_DPI1, - config_regs + DISP_REG_CONFIG_OUT_SEL); - } else if (cur == DDP_COMPONENT_BLS && next == DDP_COMPONENT_DPI0) { - writel_relaxed(BLS_TO_DPI_RDMA1_TO_DSI, - config_regs + DISP_REG_CONFIG_OUT_SEL); - writel_relaxed(DSI_SEL_IN_RDMA, - config_regs + DISP_REG_CONFIG_DSI_SEL); - writel_relaxed(DPI_SEL_IN_BLS, - config_regs + DISP_REG_CONFIG_DPI_SEL); - } -} +struct mtk_mmsys { + void __iomem *regs; + const struct mtk_mmsys_driver_data *data; +}; void mtk_mmsys_ddp_connect(struct device *dev, enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next) { - void __iomem *config_regs = dev_get_drvdata(dev); - unsigned int addr, value, reg; - - value = mtk_mmsys_ddp_mout_en(cur, next, &addr); - if (value) { - reg = readl_relaxed(config_regs + addr) | value; - writel_relaxed(reg, config_regs + addr); - } - - mtk_mmsys_ddp_sout_sel(config_regs, cur, next); - - value = mtk_mmsys_ddp_sel_in(cur, next, &addr); - if (value) { - reg = readl_relaxed(config_regs + addr) | value; - writel_relaxed(reg, config_regs + addr); - } + struct mtk_mmsys *mmsys = dev_get_drvdata(dev); + const struct mtk_mmsys_routes *routes = mmsys->data->routes; + u32 reg; + int i; + + for (i = 0; i < mmsys->data->num_routes; i++) + if (cur == routes[i].from_comp && next == routes[i].to_comp) { + reg = readl_relaxed(mmsys->regs + routes[i].addr) | routes[i].val; + writel_relaxed(reg, mmsys->regs + routes[i].addr); + } } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_connect); @@ -282,44 +71,42 @@ void mtk_mmsys_ddp_disconnect(struct device *dev, enum mtk_ddp_comp_id cur, enum mtk_ddp_comp_id next) { - void __iomem *config_regs = dev_get_drvdata(dev); - unsigned int addr, value, reg; - - value = mtk_mmsys_ddp_mout_en(cur, next, &addr); - if (value) { - reg = readl_relaxed(config_regs + addr) & ~value; - writel_relaxed(reg, config_regs + addr); - } - - value = mtk_mmsys_ddp_sel_in(cur, next, &addr); - if (value) { - reg = readl_relaxed(config_regs + addr) & ~value; - writel_relaxed(reg, config_regs + addr); - } + struct mtk_mmsys *mmsys = dev_get_drvdata(dev); + const struct mtk_mmsys_routes *routes = mmsys->data->routes; + u32 reg; + int i; + + for (i = 0; i < mmsys->data->num_routes; i++) + if (cur == routes[i].from_comp && next == routes[i].to_comp) { + reg = readl_relaxed(mmsys->regs + routes[i].addr) & ~routes[i].val; + writel_relaxed(reg, mmsys->regs + routes[i].addr); + } } EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect); static int mtk_mmsys_probe(struct platform_device *pdev) { - const struct mtk_mmsys_driver_data *data; struct device *dev = &pdev->dev; struct platform_device *clks; struct platform_device *drm; - void __iomem *config_regs; + struct mtk_mmsys *mmsys; int ret; - config_regs = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(config_regs)) { - ret = PTR_ERR(config_regs); + mmsys = devm_kzalloc(dev, sizeof(*mmsys), GFP_KERNEL); + if (!mmsys) + return -ENOMEM; + + mmsys->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(mmsys->regs)) { + ret = PTR_ERR(mmsys->regs); dev_err(dev, "Failed to ioremap mmsys registers: %d\n", ret); return ret; } - platform_set_drvdata(pdev, config_regs); - - data = of_device_get_match_data(&pdev->dev); + mmsys->data = of_device_get_match_data(&pdev->dev); + platform_set_drvdata(pdev, mmsys); - clks = platform_device_register_data(&pdev->dev, data->clk_driver, + clks = platform_device_register_data(&pdev->dev, mmsys->data->clk_driver, PLATFORM_DEVID_AUTO, NULL, 0); if (IS_ERR(clks)) return PTR_ERR(clks); diff --git a/drivers/soc/mediatek/mtk-mmsys.h b/drivers/soc/mediatek/mtk-mmsys.h new file mode 100644 index 000000000000..a760a34e6eca --- /dev/null +++ b/drivers/soc/mediatek/mtk-mmsys.h @@ -0,0 +1,215 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __SOC_MEDIATEK_MTK_MMSYS_H +#define __SOC_MEDIATEK_MTK_MMSYS_H + +#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x040 +#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN 0x044 +#define DISP_REG_CONFIG_DISP_OD_MOUT_EN 0x048 +#define DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN 0x04c +#define DISP_REG_CONFIG_DISP_UFOE_MOUT_EN 0x050 +#define DISP_REG_CONFIG_DISP_COLOR0_SEL_IN 0x084 +#define DISP_REG_CONFIG_DISP_COLOR1_SEL_IN 0x088 +#define DISP_REG_CONFIG_DSIE_SEL_IN 0x0a4 +#define DISP_REG_CONFIG_DSIO_SEL_IN 0x0a8 +#define DISP_REG_CONFIG_DPI_SEL_IN 0x0ac +#define DISP_REG_CONFIG_DISP_RDMA2_SOUT 0x0b8 +#define DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN 0x0c4 +#define DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN 0x0c8 +#define DISP_REG_CONFIG_MMSYS_CG_CON0 0x100 + +#define DISP_REG_CONFIG_DISP_OVL_MOUT_EN 0x030 +#define DISP_REG_CONFIG_OUT_SEL 0x04c +#define DISP_REG_CONFIG_DSI_SEL 0x050 +#define DISP_REG_CONFIG_DPI_SEL 0x064 + +#define OVL0_MOUT_EN_COLOR0 0x1 +#define OD_MOUT_EN_RDMA0 0x1 +#define OD1_MOUT_EN_RDMA1 BIT(16) +#define UFOE_MOUT_EN_DSI0 0x1 +#define COLOR0_SEL_IN_OVL0 0x1 +#define OVL1_MOUT_EN_COLOR1 0x1 +#define GAMMA_MOUT_EN_RDMA1 0x1 +#define RDMA0_SOUT_DPI0 0x2 +#define RDMA0_SOUT_DPI1 0x3 +#define RDMA0_SOUT_DSI1 0x1 +#define RDMA0_SOUT_DSI2 0x4 +#define RDMA0_SOUT_DSI3 0x5 +#define RDMA1_SOUT_DPI0 0x2 +#define RDMA1_SOUT_DPI1 0x3 +#define RDMA1_SOUT_DSI1 0x1 +#define RDMA1_SOUT_DSI2 0x4 +#define RDMA1_SOUT_DSI3 0x5 +#define RDMA2_SOUT_DPI0 0x2 +#define RDMA2_SOUT_DPI1 0x3 +#define RDMA2_SOUT_DSI1 0x1 +#define RDMA2_SOUT_DSI2 0x4 +#define RDMA2_SOUT_DSI3 0x5 +#define DPI0_SEL_IN_RDMA1 0x1 +#define DPI0_SEL_IN_RDMA2 0x3 +#define DPI1_SEL_IN_RDMA1 (0x1 << 8) +#define DPI1_SEL_IN_RDMA2 (0x3 << 8) +#define DSI0_SEL_IN_RDMA1 0x1 +#define DSI0_SEL_IN_RDMA2 0x4 +#define DSI1_SEL_IN_RDMA1 0x1 +#define DSI1_SEL_IN_RDMA2 0x4 +#define DSI2_SEL_IN_RDMA1 (0x1 << 16) +#define DSI2_SEL_IN_RDMA2 (0x4 << 16) +#define DSI3_SEL_IN_RDMA1 (0x1 << 16) +#define DSI3_SEL_IN_RDMA2 (0x4 << 16) +#define COLOR1_SEL_IN_OVL1 0x1 + +#define OVL_MOUT_EN_RDMA 0x1 +#define BLS_TO_DSI_RDMA1_TO_DPI1 0x8 +#define BLS_TO_DPI_RDMA1_TO_DSI 0x2 +#define DSI_SEL_IN_BLS 0x0 +#define DPI_SEL_IN_BLS 0x0 +#define DSI_SEL_IN_RDMA 0x1 + +struct mtk_mmsys_routes { + u32 from_comp; + u32 to_comp; + u32 addr; + u32 val; +}; + +struct mtk_mmsys_driver_data { + const char *clk_driver; + const struct mtk_mmsys_routes *routes; + const unsigned int num_routes; +}; + +/* + * Routes in mt8173, mt2701, mt2712 are different. That means + * in the same register address, it controls different input/output + * selection for each SoC. But, right now, they use the same table as + * default routes meet their requirements. But we don't have the complete + * route information for these three SoC, so just keep them in the same + * table. After we've more information, we could separate mt2701, mt2712 + * to an independent table. + */ +static const struct mtk_mmsys_routes mmsys_default_routing_table[] = { + { + DDP_COMPONENT_BLS, DDP_COMPONENT_DSI0, + DISP_REG_CONFIG_OUT_SEL, BLS_TO_DSI_RDMA1_TO_DPI1 + }, { + DDP_COMPONENT_BLS, DDP_COMPONENT_DSI0, + DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_BLS + }, { + DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_OUT_SEL, BLS_TO_DPI_RDMA1_TO_DSI + }, { + DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DSI_SEL, DSI_SEL_IN_RDMA + }, { + DDP_COMPONENT_BLS, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DPI_SEL, DPI_SEL_IN_BLS + }, { + DDP_COMPONENT_GAMMA, DDP_COMPONENT_RDMA1, + DISP_REG_CONFIG_DISP_GAMMA_MOUT_EN, GAMMA_MOUT_EN_RDMA1 + }, { + DDP_COMPONENT_OD0, DDP_COMPONENT_RDMA0, + DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD_MOUT_EN_RDMA0 + }, { + DDP_COMPONENT_OD1, DDP_COMPONENT_RDMA1, + DISP_REG_CONFIG_DISP_OD_MOUT_EN, OD1_MOUT_EN_RDMA1 + }, { + DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, + DISP_REG_CONFIG_DISP_OVL0_MOUT_EN, OVL0_MOUT_EN_COLOR0 + }, { + DDP_COMPONENT_OVL0, DDP_COMPONENT_COLOR0, + DISP_REG_CONFIG_DISP_COLOR0_SEL_IN, COLOR0_SEL_IN_OVL0 + }, { + DDP_COMPONENT_OVL0, DDP_COMPONENT_RDMA0, + DISP_REG_CONFIG_DISP_OVL_MOUT_EN, OVL_MOUT_EN_RDMA + }, { + DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1, + DISP_REG_CONFIG_DISP_OVL1_MOUT_EN, OVL1_MOUT_EN_COLOR1 + }, { + DDP_COMPONENT_OVL1, DDP_COMPONENT_COLOR1, + DISP_REG_CONFIG_DISP_COLOR1_SEL_IN, COLOR1_SEL_IN_OVL1 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DPI0 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DPI1, + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DPI1 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI1, + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI1 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI2, + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI2 + }, { + DDP_COMPONENT_RDMA0, DDP_COMPONENT_DSI3, + DISP_REG_CONFIG_DISP_RDMA0_SOUT_EN, RDMA0_SOUT_DSI3 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DPI0 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI1, + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DPI1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DPI1, + DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI0, + DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI1, + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI1, + DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI2, + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI2 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI2, + DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI3, + DISP_REG_CONFIG_DISP_RDMA1_SOUT_EN, RDMA1_SOUT_DSI3 + }, { + DDP_COMPONENT_RDMA1, DDP_COMPONENT_DSI3, + DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_RDMA1 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DPI0 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI0, + DISP_REG_CONFIG_DPI_SEL_IN, DPI0_SEL_IN_RDMA2 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI1, + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DPI1 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DPI1, + DISP_REG_CONFIG_DPI_SEL_IN, DPI1_SEL_IN_RDMA2 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI0, + DISP_REG_CONFIG_DSIE_SEL_IN, DSI0_SEL_IN_RDMA2 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI1, + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI1 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI1, + DISP_REG_CONFIG_DSIO_SEL_IN, DSI1_SEL_IN_RDMA2 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI2, + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI2 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI2, + DISP_REG_CONFIG_DSIE_SEL_IN, DSI2_SEL_IN_RDMA2 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI3, + DISP_REG_CONFIG_DISP_RDMA2_SOUT, RDMA2_SOUT_DSI3 + }, { + DDP_COMPONENT_RDMA2, DDP_COMPONENT_DSI3, + DISP_REG_CONFIG_DSIO_SEL_IN, DSI3_SEL_IN_RDMA2 + } +}; + +#endif /* __SOC_MEDIATEK_MTK_MMSYS_H */ diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c index f531b119da7a..2e4bcc300576 100644 --- a/drivers/soc/mediatek/mtk-mutex.c +++ b/drivers/soc/mediatek/mtk-mutex.c @@ -14,6 +14,8 @@ #define MT2701_MUTEX0_MOD0 0x2c #define MT2701_MUTEX0_SOF0 0x30 +#define MT8183_MUTEX0_MOD0 0x30 +#define MT8183_MUTEX0_SOF0 0x2c #define DISP_REG_MUTEX_EN(n) (0x20 + 0x20 * (n)) #define DISP_REG_MUTEX(n) (0x24 + 0x20 * (n)) @@ -37,6 +39,18 @@ #define MT8167_MUTEX_MOD_DISP_DITHER 15 #define MT8167_MUTEX_MOD_DISP_UFOE 16 +#define MT8183_MUTEX_MOD_DISP_RDMA0 0 +#define MT8183_MUTEX_MOD_DISP_RDMA1 1 +#define MT8183_MUTEX_MOD_DISP_OVL0 9 +#define MT8183_MUTEX_MOD_DISP_OVL0_2L 10 +#define MT8183_MUTEX_MOD_DISP_OVL1_2L 11 +#define MT8183_MUTEX_MOD_DISP_WDMA0 12 +#define MT8183_MUTEX_MOD_DISP_COLOR0 13 +#define MT8183_MUTEX_MOD_DISP_CCORR0 14 +#define MT8183_MUTEX_MOD_DISP_AAL0 15 +#define MT8183_MUTEX_MOD_DISP_GAMMA0 16 +#define MT8183_MUTEX_MOD_DISP_DITHER0 17 + #define MT8173_MUTEX_MOD_DISP_OVL0 11 #define MT8173_MUTEX_MOD_DISP_OVL1 12 #define MT8173_MUTEX_MOD_DISP_RDMA0 13 @@ -87,6 +101,11 @@ #define MT2712_MUTEX_SOF_DSI3 6 #define MT8167_MUTEX_SOF_DPI0 2 #define MT8167_MUTEX_SOF_DPI1 3 +#define MT8183_MUTEX_SOF_DSI0 1 +#define MT8183_MUTEX_SOF_DPI0 2 + +#define MT8183_MUTEX_EOF_DSI0 (MT8183_MUTEX_SOF_DSI0 << 6) +#define MT8183_MUTEX_EOF_DPI0 (MT8183_MUTEX_SOF_DPI0 << 6) struct mtk_mutex { int id; @@ -181,6 +200,20 @@ static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = { [DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1, }; +static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = { + [DDP_COMPONENT_AAL0] = MT8183_MUTEX_MOD_DISP_AAL0, + [DDP_COMPONENT_CCORR] = MT8183_MUTEX_MOD_DISP_CCORR0, + [DDP_COMPONENT_COLOR0] = MT8183_MUTEX_MOD_DISP_COLOR0, + [DDP_COMPONENT_DITHER] = MT8183_MUTEX_MOD_DISP_DITHER0, + [DDP_COMPONENT_GAMMA] = MT8183_MUTEX_MOD_DISP_GAMMA0, + [DDP_COMPONENT_OVL0] = MT8183_MUTEX_MOD_DISP_OVL0, + [DDP_COMPONENT_OVL_2L0] = MT8183_MUTEX_MOD_DISP_OVL0_2L, + [DDP_COMPONENT_OVL_2L1] = MT8183_MUTEX_MOD_DISP_OVL1_2L, + [DDP_COMPONENT_RDMA0] = MT8183_MUTEX_MOD_DISP_RDMA0, + [DDP_COMPONENT_RDMA1] = MT8183_MUTEX_MOD_DISP_RDMA1, + [DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0, +}; + static const unsigned int mt2712_mutex_sof[MUTEX_SOF_DSI3 + 1] = { [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0, @@ -198,6 +231,13 @@ static const unsigned int mt8167_mutex_sof[MUTEX_SOF_DSI3 + 1] = { [MUTEX_SOF_DPI1] = MT8167_MUTEX_SOF_DPI1, }; +/* Add EOF setting so overlay hardware can receive frame done irq */ +static const unsigned int mt8183_mutex_sof[MUTEX_SOF_DSI3 + 1] = { + [MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE, + [MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0 | MT8183_MUTEX_EOF_DSI0, + [MUTEX_SOF_DPI0] = MT8183_MUTEX_SOF_DPI0 | MT8183_MUTEX_EOF_DPI0, +}; + static const struct mtk_mutex_data mt2701_mutex_driver_data = { .mutex_mod = mt2701_mutex_mod, .mutex_sof = mt2712_mutex_sof, @@ -227,6 +267,14 @@ static const struct mtk_mutex_data mt8173_mutex_driver_data = { .mutex_sof_reg = MT2701_MUTEX0_SOF0, }; +static const struct mtk_mutex_data mt8183_mutex_driver_data = { + .mutex_mod = mt8183_mutex_mod, + .mutex_sof = mt8183_mutex_sof, + .mutex_mod_reg = MT8183_MUTEX0_MOD0, + .mutex_sof_reg = MT8183_MUTEX0_SOF0, + .no_clk = true, +}; + struct mtk_mutex *mtk_mutex_get(struct device *dev) { struct mtk_mutex_ctx *mtx = dev_get_drvdata(dev); @@ -457,11 +505,13 @@ static const struct of_device_id mutex_driver_dt_match[] = { .data = &mt8167_mutex_driver_data}, { .compatible = "mediatek,mt8173-disp-mutex", .data = &mt8173_mutex_driver_data}, + { .compatible = "mediatek,mt8183-disp-mutex", + .data = &mt8183_mutex_driver_data}, {}, }; MODULE_DEVICE_TABLE(of, mutex_driver_dt_match); -struct platform_driver mtk_mutex_driver = { +static struct platform_driver mtk_mutex_driver = { .probe = mtk_mutex_probe, .remove = mtk_mutex_remove, .driver = { diff --git a/drivers/soc/mediatek/mtk-pm-domains.c b/drivers/soc/mediatek/mtk-pm-domains.c index b7f697666bdd..0af00efa0ef8 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.c +++ b/drivers/soc/mediatek/mtk-pm-domains.c @@ -438,7 +438,11 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no goto err_unprepare_subsys_clocks; } - pd->genpd.name = node->name; + if (!pd->data->name) + pd->genpd.name = node->name; + else + pd->genpd.name = pd->data->name; + pd->genpd.power_off = scpsys_power_off; pd->genpd.power_on = scpsys_power_on; @@ -487,8 +491,9 @@ static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *paren child_pd = scpsys_add_one_domain(scpsys, child); if (IS_ERR(child_pd)) { - dev_err_probe(scpsys->dev, PTR_ERR(child_pd), - "%pOF: failed to get child domain id\n", child); + ret = PTR_ERR(child_pd); + dev_err_probe(scpsys->dev, ret, "%pOF: failed to get child domain id\n", + child); goto err_put_node; } diff --git a/drivers/soc/mediatek/mtk-pm-domains.h b/drivers/soc/mediatek/mtk-pm-domains.h index 141dc76054e6..21a4e113bbec 100644 --- a/drivers/soc/mediatek/mtk-pm-domains.h +++ b/drivers/soc/mediatek/mtk-pm-domains.h @@ -76,6 +76,7 @@ struct scpsys_bus_prot_data { /** * struct scpsys_domain_data - scp domain data for power on/off flow + * @name: The name of the power domain. * @sta_mask: The mask for power on/off status bit. * @ctl_offs: The offset for main power control register. * @sram_pdn_bits: The mask for sram power control bits. @@ -85,6 +86,7 @@ struct scpsys_bus_prot_data { * @bp_smi: bus protection for smi subsystem */ struct scpsys_domain_data { + const char *name; u32 sta_mask; int ctl_offs; u32 sram_pdn_bits; diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 5d34e8b9c988..e4de75f35c33 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -25,10 +25,12 @@ /* macro for wrapper status */ #define PWRAP_GET_WACS_RDATA(x) (((x) >> 0) & 0x0000ffff) +#define PWRAP_GET_WACS_ARB_FSM(x) (((x) >> 1) & 0x00000007) #define PWRAP_GET_WACS_FSM(x) (((x) >> 16) & 0x00000007) #define PWRAP_GET_WACS_REQ(x) (((x) >> 19) & 0x00000001) -#define PWRAP_STATE_SYNC_IDLE0 (1 << 20) -#define PWRAP_STATE_INIT_DONE0 (1 << 21) +#define PWRAP_STATE_SYNC_IDLE0 BIT(20) +#define PWRAP_STATE_INIT_DONE0 BIT(21) +#define PWRAP_STATE_INIT_DONE1 BIT(15) /* macro for WACS FSM */ #define PWRAP_WACS_FSM_IDLE 0x00 @@ -74,6 +76,7 @@ #define PWRAP_CAP_DCM BIT(2) #define PWRAP_CAP_INT1_EN BIT(3) #define PWRAP_CAP_WDT_SRC1 BIT(4) +#define PWRAP_CAP_ARB BIT(5) /* defines for slave device wrapper registers */ enum dew_regs { @@ -340,6 +343,8 @@ enum pwrap_regs { PWRAP_DCM_DBC_PRD, PWRAP_EINT_STA0_ADR, PWRAP_EINT_STA1_ADR, + PWRAP_SWINF_2_WDATA_31_0, + PWRAP_SWINF_2_RDATA_31_0, /* MT2701 only regs */ PWRAP_ADC_CMD_ADDR, @@ -627,6 +632,17 @@ static int mt6797_regs[] = { [PWRAP_DCM_DBC_PRD] = 0x1D4, }; +static int mt6873_regs[] = { + [PWRAP_INIT_DONE2] = 0x0, + [PWRAP_TIMER_EN] = 0x3E0, + [PWRAP_INT_EN] = 0x448, + [PWRAP_WACS2_CMD] = 0xC80, + [PWRAP_SWINF_2_WDATA_31_0] = 0xC84, + [PWRAP_SWINF_2_RDATA_31_0] = 0xC94, + [PWRAP_WACS2_VLDCLR] = 0xCA4, + [PWRAP_WACS2_RDATA] = 0xCA8, +}; + static int mt7622_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -1045,6 +1061,7 @@ enum pwrap_type { PWRAP_MT6765, PWRAP_MT6779, PWRAP_MT6797, + PWRAP_MT6873, PWRAP_MT7622, PWRAP_MT8135, PWRAP_MT8173, @@ -1106,18 +1123,25 @@ static void pwrap_writel(struct pmic_wrapper *wrp, u32 val, enum pwrap_regs reg) writel(val, wrp->base + wrp->master->regs[reg]); } -static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp) +static u32 pwrap_get_fsm_state(struct pmic_wrapper *wrp) { - u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); + u32 val; - return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_IDLE; + val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) + return PWRAP_GET_WACS_ARB_FSM(val); + else + return PWRAP_GET_WACS_FSM(val); } -static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp) +static bool pwrap_is_fsm_idle(struct pmic_wrapper *wrp) { - u32 val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); + return pwrap_get_fsm_state(wrp) == PWRAP_WACS_FSM_IDLE; +} - return PWRAP_GET_WACS_FSM(val) == PWRAP_WACS_FSM_WFVLDCLR; +static bool pwrap_is_fsm_vldclr(struct pmic_wrapper *wrp) +{ + return pwrap_get_fsm_state(wrp) == PWRAP_WACS_FSM_WFVLDCLR; } /* @@ -1165,6 +1189,7 @@ static int pwrap_wait_for_state(struct pmic_wrapper *wrp, static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) { int ret; + u32 val; ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_idle); if (ret) { @@ -1172,13 +1197,21 @@ static int pwrap_read16(struct pmic_wrapper *wrp, u32 adr, u32 *rdata) return ret; } - pwrap_writel(wrp, (adr >> 1) << 16, PWRAP_WACS2_CMD); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) + val = adr; + else + val = (adr >> 1) << 16; + pwrap_writel(wrp, val, PWRAP_WACS2_CMD); ret = pwrap_wait_for_state(wrp, pwrap_is_fsm_vldclr); if (ret) return ret; - *rdata = PWRAP_GET_WACS_RDATA(pwrap_readl(wrp, PWRAP_WACS2_RDATA)); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) + val = pwrap_readl(wrp, PWRAP_SWINF_2_RDATA_31_0); + else + val = pwrap_readl(wrp, PWRAP_WACS2_RDATA); + *rdata = PWRAP_GET_WACS_RDATA(val); pwrap_writel(wrp, 1, PWRAP_WACS2_VLDCLR); @@ -1228,8 +1261,13 @@ static int pwrap_write16(struct pmic_wrapper *wrp, u32 adr, u32 wdata) return ret; } - pwrap_writel(wrp, (1 << 31) | ((adr >> 1) << 16) | wdata, - PWRAP_WACS2_CMD); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) { + pwrap_writel(wrp, wdata, PWRAP_SWINF_2_WDATA_31_0); + pwrap_writel(wrp, BIT(29) | adr, PWRAP_WACS2_CMD); + } else { + pwrap_writel(wrp, BIT(31) | ((adr >> 1) << 16) | wdata, + PWRAP_WACS2_CMD); + } return 0; } @@ -1485,6 +1523,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) case PWRAP_MT7622: pwrap_writel(wrp, 0, PWRAP_CIPHER_EN); break; + case PWRAP_MT6873: case PWRAP_MT8183: break; } @@ -1921,6 +1960,19 @@ static const struct pmic_wrapper_type pwrap_mt6797 = { .init_soc_specific = NULL, }; +static const struct pmic_wrapper_type pwrap_mt6873 = { + .regs = mt6873_regs, + .type = PWRAP_MT6873, + .arb_en_all = 0x777f, + .int_en_all = BIT(4) | BIT(5), + .int1_en_all = 0, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .caps = PWRAP_CAP_ARB, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = NULL, +}; + static const struct pmic_wrapper_type pwrap_mt7622 = { .regs = mt7622_regs, .type = PWRAP_MT7622, @@ -1999,6 +2051,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = { .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797, }, { + .compatible = "mediatek,mt6873-pwrap", + .data = &pwrap_mt6873, + }, { .compatible = "mediatek,mt7622-pwrap", .data = &pwrap_mt7622, }, { @@ -2022,6 +2077,7 @@ MODULE_DEVICE_TABLE(of, of_pwrap_match_tbl); static int pwrap_probe(struct platform_device *pdev) { int ret, irq; + u32 mask_done; struct pmic_wrapper *wrp; struct device_node *np = pdev->dev.of_node; const struct of_device_id *of_slave_id = NULL; @@ -2116,14 +2172,21 @@ static int pwrap_probe(struct platform_device *pdev) } } - if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & PWRAP_STATE_INIT_DONE0)) { + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) + mask_done = PWRAP_STATE_INIT_DONE1; + else + mask_done = PWRAP_STATE_INIT_DONE0; + + if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & mask_done)) { dev_dbg(wrp->dev, "initialization isn't finished\n"); ret = -ENODEV; goto err_out2; } /* Initialize watchdog, may not be done by the bootloader */ - pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); + if (!HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) + pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT); + /* * Since STAUPD was not used on mt8173 platform, * so STAUPD of WDT_SRC which should be turned off @@ -2132,7 +2195,11 @@ static int pwrap_probe(struct platform_device *pdev) if (HAS_CAP(wrp->master->caps, PWRAP_CAP_WDT_SRC1)) pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN_1); - pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_ARB)) + pwrap_writel(wrp, 0x3, PWRAP_TIMER_EN); + else + pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN); + pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); /* * We add INT1 interrupt to handle starvation and request exception diff --git a/drivers/soc/renesas/rmobile-sysc.c b/drivers/soc/renesas/rmobile-sysc.c index 9046b8c933cb..204e6135180b 100644 --- a/drivers/soc/renesas/rmobile-sysc.c +++ b/drivers/soc/renesas/rmobile-sysc.c @@ -14,8 +14,6 @@ #include <linux/delay.h> #include <linux/of.h> #include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/platform_device.h> #include <linux/pm.h> #include <linux/pm_clock.h> #include <linux/pm_domain.h> @@ -344,6 +342,8 @@ static int __init rmobile_init_pm_domains(void) of_node_put(np); break; } + + fwnode_dev_initialized(&np->fwnode, true); } put_special_pds(); diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index df9a5ca8c99c..6bd22359d411 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -39,6 +39,7 @@ #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/reboot.h> +#include <linux/regmap.h> #include <linux/reset.h> #include <linux/seq_file.h> #include <linux/slab.h> @@ -102,6 +103,9 @@ #define PMC_PWR_DET_VALUE 0xe4 +#define PMC_USB_DEBOUNCE_DEL 0xec +#define PMC_USB_AO 0xf0 + #define PMC_SCRATCH41 0x140 #define PMC_WAKE2_MASK 0x160 @@ -133,6 +137,13 @@ #define IO_DPD2_STATUS 0x1c4 #define SEL_DPD_TIM 0x1c8 +#define PMC_UTMIP_UHSIC_TRIGGERS 0x1ec +#define PMC_UTMIP_UHSIC_SAVED_STATE 0x1f0 + +#define PMC_UTMIP_TERM_PAD_CFG 0x1f8 +#define PMC_UTMIP_UHSIC_SLEEP_CFG 0x1fc +#define PMC_UTMIP_UHSIC_FAKE 0x218 + #define PMC_SCRATCH54 0x258 #define PMC_SCRATCH54_DATA_SHIFT 8 #define PMC_SCRATCH54_ADDR_SHIFT 0 @@ -145,8 +156,18 @@ #define PMC_SCRATCH55_CHECKSUM_SHIFT 16 #define PMC_SCRATCH55_I2CSLV1_SHIFT 0 +#define PMC_UTMIP_UHSIC_LINE_WAKEUP 0x26c + +#define PMC_UTMIP_BIAS_MASTER_CNTRL 0x270 +#define PMC_UTMIP_MASTER_CONFIG 0x274 +#define PMC_UTMIP_UHSIC2_TRIGGERS 0x27c +#define PMC_UTMIP_MASTER2_CONFIG 0x29c + #define GPU_RG_CNTRL 0x2d4 +#define PMC_UTMIP_PAD_CFG0 0x4c0 +#define PMC_UTMIP_UHSIC_SLEEP_CFG1 0x4d0 +#define PMC_UTMIP_SLEEPWALK_P3 0x4e0 /* Tegra186 and later */ #define WAKE_AOWAKE_CNTRL(x) (0x000 + ((x) << 2)) #define WAKE_AOWAKE_CNTRL_LEVEL (1 << 3) @@ -237,6 +258,7 @@ struct tegra_powergate { unsigned int id; struct clk **clks; unsigned int num_clks; + unsigned long *clk_rates; struct reset_control *reset; }; @@ -317,6 +339,8 @@ struct tegra_pmc_soc { bool invert); int (*irq_set_wake)(struct irq_data *data, unsigned int on); int (*irq_set_type)(struct irq_data *data, unsigned int type); + int (*powergate_set)(struct tegra_pmc *pmc, unsigned int id, + bool new_state); const char * const *reset_sources; unsigned int num_reset_sources; @@ -334,6 +358,7 @@ struct tegra_pmc_soc { const struct pmc_clk_init_data *pmc_clks_data; unsigned int num_pmc_clks; bool has_blink_output; + bool has_usb_sleepwalk; }; /** @@ -517,6 +542,63 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name) return -ENODEV; } +static int tegra20_powergate_set(struct tegra_pmc *pmc, unsigned int id, + bool new_state) +{ + unsigned int retries = 100; + bool status; + int ret; + + /* + * As per TRM documentation, the toggle command will be dropped by PMC + * if there is contention with a HW-initiated toggling (i.e. CPU core + * power-gated), the command should be retried in that case. + */ + do { + tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); + + /* wait for PMC to execute the command */ + ret = readx_poll_timeout(tegra_powergate_state, id, status, + status == new_state, 1, 10); + } while (ret == -ETIMEDOUT && retries--); + + return ret; +} + +static inline bool tegra_powergate_toggle_ready(struct tegra_pmc *pmc) +{ + return !(tegra_pmc_readl(pmc, PWRGATE_TOGGLE) & PWRGATE_TOGGLE_START); +} + +static int tegra114_powergate_set(struct tegra_pmc *pmc, unsigned int id, + bool new_state) +{ + bool status; + int err; + + /* wait while PMC power gating is contended */ + err = readx_poll_timeout(tegra_powergate_toggle_ready, pmc, status, + status == true, 1, 100); + if (err) + return err; + + tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); + + /* wait for PMC to accept the command */ + err = readx_poll_timeout(tegra_powergate_toggle_ready, pmc, status, + status == true, 1, 100); + if (err) + return err; + + /* wait for PMC to execute the command */ + err = readx_poll_timeout(tegra_powergate_state, id, status, + status == new_state, 10, 100000); + if (err) + return err; + + return 0; +} + /** * tegra_powergate_set() - set the state of a partition * @pmc: power management controller @@ -526,7 +608,6 @@ static int tegra_powergate_lookup(struct tegra_pmc *pmc, const char *name) static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id, bool new_state) { - bool status; int err; if (id == TEGRA_POWERGATE_3D && pmc->soc->has_gpu_clamps) @@ -539,10 +620,7 @@ static int tegra_powergate_set(struct tegra_pmc *pmc, unsigned int id, return 0; } - tegra_pmc_writel(pmc, PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE); - - err = readx_poll_timeout(tegra_powergate_state, id, status, - status == new_state, 10, 100000); + err = pmc->soc->powergate_set(pmc, id, new_state); mutex_unlock(&pmc->powergates_lock); @@ -586,6 +664,57 @@ out: return 0; } +static int tegra_powergate_prepare_clocks(struct tegra_powergate *pg) +{ + unsigned long safe_rate = 100 * 1000 * 1000; + unsigned int i; + int err; + + for (i = 0; i < pg->num_clks; i++) { + pg->clk_rates[i] = clk_get_rate(pg->clks[i]); + + if (!pg->clk_rates[i]) { + err = -EINVAL; + goto out; + } + + if (pg->clk_rates[i] <= safe_rate) + continue; + + /* + * We don't know whether voltage state is okay for the + * current clock rate, hence it's better to temporally + * switch clock to a safe rate which is suitable for + * all voltages, before enabling the clock. + */ + err = clk_set_rate(pg->clks[i], safe_rate); + if (err) + goto out; + } + + return 0; + +out: + while (i--) + clk_set_rate(pg->clks[i], pg->clk_rates[i]); + + return err; +} + +static int tegra_powergate_unprepare_clocks(struct tegra_powergate *pg) +{ + unsigned int i; + int err; + + for (i = 0; i < pg->num_clks; i++) { + err = clk_set_rate(pg->clks[i], pg->clk_rates[i]); + if (err) + return err; + } + + return 0; +} + static void tegra_powergate_disable_clocks(struct tegra_powergate *pg) { unsigned int i; @@ -636,9 +765,13 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, usleep_range(10, 20); + err = tegra_powergate_prepare_clocks(pg); + if (err) + goto powergate_off; + err = tegra_powergate_enable_clocks(pg); if (err) - goto disable_clks; + goto unprepare_clks; usleep_range(10, 20); @@ -662,12 +795,19 @@ static int tegra_powergate_power_up(struct tegra_powergate *pg, if (disable_clocks) tegra_powergate_disable_clocks(pg); + err = tegra_powergate_unprepare_clocks(pg); + if (err) + return err; + return 0; disable_clks: tegra_powergate_disable_clocks(pg); usleep_range(10, 20); +unprepare_clks: + tegra_powergate_unprepare_clocks(pg); + powergate_off: tegra_powergate_set(pg->pmc, pg->id, false); @@ -678,10 +818,14 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg) { int err; - err = tegra_powergate_enable_clocks(pg); + err = tegra_powergate_prepare_clocks(pg); if (err) return err; + err = tegra_powergate_enable_clocks(pg); + if (err) + goto unprepare_clks; + usleep_range(10, 20); err = reset_control_assert(pg->reset); @@ -698,6 +842,10 @@ static int tegra_powergate_power_down(struct tegra_powergate *pg) if (err) goto assert_resets; + err = tegra_powergate_unprepare_clocks(pg); + if (err) + return err; + return 0; assert_resets: @@ -709,6 +857,9 @@ assert_resets: disable_clks: tegra_powergate_disable_clocks(pg); +unprepare_clks: + tegra_powergate_unprepare_clocks(pg); + return err; } @@ -739,7 +890,8 @@ static int tegra_genpd_power_off(struct generic_pm_domain *domain) err = reset_control_acquire(pg->reset); if (err < 0) { - pr_err("failed to acquire resets: %d\n", err); + dev_err(dev, "failed to acquire resets for PM domain %s: %d\n", + pg->genpd.name, err); return err; } @@ -826,6 +978,12 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, if (!pg) return -ENOMEM; + pg->clk_rates = kzalloc(sizeof(*pg->clk_rates), GFP_KERNEL); + if (!pg->clk_rates) { + kfree(pg->clks); + return -ENOMEM; + } + pg->id = id; pg->clks = &clk; pg->num_clks = 1; @@ -837,6 +995,7 @@ int tegra_powergate_sequence_power_up(unsigned int id, struct clk *clk, dev_err(pmc->dev, "failed to turn on partition %d: %d\n", id, err); + kfree(pg->clk_rates); kfree(pg); return err; @@ -987,6 +1146,12 @@ static int tegra_powergate_of_get_clks(struct tegra_powergate *pg, if (!pg->clks) return -ENOMEM; + pg->clk_rates = kcalloc(count, sizeof(*pg->clk_rates), GFP_KERNEL); + if (!pg->clk_rates) { + kfree(pg->clks); + return -ENOMEM; + } + for (i = 0; i < count; i++) { pg->clks[i] = of_clk_get(np, i); if (IS_ERR(pg->clks[i])) { @@ -1003,6 +1168,7 @@ err: while (i--) clk_put(pg->clks[i]); + kfree(pg->clk_rates); kfree(pg->clks); return err; @@ -2443,6 +2609,67 @@ static void tegra_pmc_clock_register(struct tegra_pmc *pmc, err); } +static const struct regmap_range pmc_usb_sleepwalk_ranges[] = { + regmap_reg_range(PMC_USB_DEBOUNCE_DEL, PMC_USB_AO), + regmap_reg_range(PMC_UTMIP_UHSIC_TRIGGERS, PMC_UTMIP_UHSIC_SAVED_STATE), + regmap_reg_range(PMC_UTMIP_TERM_PAD_CFG, PMC_UTMIP_UHSIC_FAKE), + regmap_reg_range(PMC_UTMIP_UHSIC_LINE_WAKEUP, PMC_UTMIP_UHSIC_LINE_WAKEUP), + regmap_reg_range(PMC_UTMIP_BIAS_MASTER_CNTRL, PMC_UTMIP_MASTER_CONFIG), + regmap_reg_range(PMC_UTMIP_UHSIC2_TRIGGERS, PMC_UTMIP_MASTER2_CONFIG), + regmap_reg_range(PMC_UTMIP_PAD_CFG0, PMC_UTMIP_UHSIC_SLEEP_CFG1), + regmap_reg_range(PMC_UTMIP_SLEEPWALK_P3, PMC_UTMIP_SLEEPWALK_P3), +}; + +static const struct regmap_access_table pmc_usb_sleepwalk_table = { + .yes_ranges = pmc_usb_sleepwalk_ranges, + .n_yes_ranges = ARRAY_SIZE(pmc_usb_sleepwalk_ranges), +}; + +static int tegra_pmc_regmap_readl(void *context, unsigned int offset, unsigned int *value) +{ + struct tegra_pmc *pmc = context; + + *value = tegra_pmc_readl(pmc, offset); + return 0; +} + +static int tegra_pmc_regmap_writel(void *context, unsigned int offset, unsigned int value) +{ + struct tegra_pmc *pmc = context; + + tegra_pmc_writel(pmc, value, offset); + return 0; +} + +static const struct regmap_config usb_sleepwalk_regmap_config = { + .name = "usb_sleepwalk", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .fast_io = true, + .rd_table = &pmc_usb_sleepwalk_table, + .wr_table = &pmc_usb_sleepwalk_table, + .reg_read = tegra_pmc_regmap_readl, + .reg_write = tegra_pmc_regmap_writel, +}; + +static int tegra_pmc_regmap_init(struct tegra_pmc *pmc) +{ + struct regmap *regmap; + int err; + + if (pmc->soc->has_usb_sleepwalk) { + regmap = devm_regmap_init(pmc->dev, NULL, pmc, &usb_sleepwalk_regmap_config); + if (IS_ERR(regmap)) { + err = PTR_ERR(regmap); + dev_err(pmc->dev, "failed to allocate register map (%d)\n", err); + return err; + } + } + + return 0; +} + static int tegra_pmc_probe(struct platform_device *pdev) { void __iomem *base; @@ -2548,6 +2775,10 @@ static int tegra_pmc_probe(struct platform_device *pdev) if (err) goto cleanup_restart_handler; + err = tegra_pmc_regmap_init(pmc); + if (err < 0) + goto cleanup_restart_handler; + err = tegra_powergate_init(pmc, pdev->dev.of_node); if (err < 0) goto cleanup_powergates; @@ -2699,6 +2930,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, + .powergate_set = tegra20_powergate_set, .reset_sources = NULL, .num_reset_sources = 0, .reset_levels = NULL, @@ -2706,6 +2938,7 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = true, + .has_usb_sleepwalk = false, }; static const char * const tegra30_powergates[] = { @@ -2757,6 +2990,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, + .powergate_set = tegra20_powergate_set, .reset_sources = tegra30_reset_sources, .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources), .reset_levels = NULL, @@ -2764,6 +2998,7 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .pmc_clks_data = tegra_pmc_clks_data, .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), .has_blink_output = true, + .has_usb_sleepwalk = false, }; static const char * const tegra114_powergates[] = { @@ -2811,6 +3046,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, + .powergate_set = tegra114_powergate_set, .reset_sources = tegra30_reset_sources, .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources), .reset_levels = NULL, @@ -2818,6 +3054,7 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .pmc_clks_data = tegra_pmc_clks_data, .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), .has_blink_output = true, + .has_usb_sleepwalk = false, }; static const char * const tegra124_powergates[] = { @@ -2925,6 +3162,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, + .powergate_set = tegra114_powergate_set, .reset_sources = tegra30_reset_sources, .num_reset_sources = ARRAY_SIZE(tegra30_reset_sources), .reset_levels = NULL, @@ -2932,6 +3170,7 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { .pmc_clks_data = tegra_pmc_clks_data, .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), .has_blink_output = true, + .has_usb_sleepwalk = true, }; static const char * const tegra210_powergates[] = { @@ -3048,6 +3287,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, + .powergate_set = tegra114_powergate_set, .irq_set_wake = tegra210_pmc_irq_set_wake, .irq_set_type = tegra210_pmc_irq_set_type, .reset_sources = tegra210_reset_sources, @@ -3059,6 +3299,7 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .pmc_clks_data = tegra_pmc_clks_data, .num_pmc_clks = ARRAY_SIZE(tegra_pmc_clks_data), .has_blink_output = true, + .has_usb_sleepwalk = true, }; #define TEGRA186_IO_PAD_TABLE(_pad) \ @@ -3214,6 +3455,7 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = false, + .has_usb_sleepwalk = false, }; #define TEGRA194_IO_PAD_TABLE(_pad) \ @@ -3347,6 +3589,7 @@ static const struct tegra_pmc_soc tegra194_pmc_soc = { .pmc_clks_data = NULL, .num_pmc_clks = 0, .has_blink_output = false, + .has_usb_sleepwalk = false, }; static const struct tegra_pmc_regs tegra234_pmc_regs = { diff --git a/drivers/soc/tegra/regulators-tegra30.c b/drivers/soc/tegra/regulators-tegra30.c index 7f21f31de09d..0e776b20f625 100644 --- a/drivers/soc/tegra/regulators-tegra30.c +++ b/drivers/soc/tegra/regulators-tegra30.c @@ -178,7 +178,7 @@ static int tegra30_voltage_update(struct tegra_regulator_coupler *tegra, * survive the voltage drop if it's running on a higher frequency. */ if (!cpu_min_uV_consumers) - cpu_min_uV = cpu_uV; + cpu_min_uV = max(cpu_uV, cpu_min_uV); /* * Bootloader shall set up voltages correctly, but if it diff --git a/drivers/soc/ti/omap_prm.c b/drivers/soc/ti/omap_prm.c index bf1468e5bccb..ea64e187854e 100644 --- a/drivers/soc/ti/omap_prm.c +++ b/drivers/soc/ti/omap_prm.c @@ -88,6 +88,7 @@ struct omap_reset_data { #define OMAP_PRM_HAS_RSTCTRL BIT(0) #define OMAP_PRM_HAS_RSTST BIT(1) #define OMAP_PRM_HAS_NO_CLKDM BIT(2) +#define OMAP_PRM_RET_WHEN_IDLE BIT(3) #define OMAP_PRM_HAS_RESETS (OMAP_PRM_HAS_RSTCTRL | OMAP_PRM_HAS_RSTST) @@ -174,7 +175,8 @@ static const struct omap_prm_data omap4_prm_data[] = { .name = "core", .base = 0x4a306700, .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, .rstctrl = 0x210, .rstst = 0x214, .clkdm_name = "ducati", - .rstmap = rst_map_012 + .rstmap = rst_map_012, + .flags = OMAP_PRM_RET_WHEN_IDLE, }, { .name = "ivahd", .base = 0x4a306f00, @@ -199,7 +201,8 @@ static const struct omap_prm_data omap4_prm_data[] = { }, { .name = "l4per", .base = 0x4a307400, - .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton + .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_reton, + .flags = OMAP_PRM_RET_WHEN_IDLE, }, { .name = "cefuse", .base = 0x4a307600, @@ -332,7 +335,7 @@ static const struct omap_prm_data dra7_prm_data[] = { { .name = "l3init", .base = 0x4ae07300, .pwrstctrl = 0x0, .pwrstst = 0x4, .dmap = &omap_prm_alwon, - .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_012, + .rstctrl = 0x10, .rstst = 0x14, .rstmap = rst_map_01, .clkdm_name = "pcie" }, { @@ -517,7 +520,7 @@ static int omap_prm_domain_power_on(struct generic_pm_domain *domain) { struct omap_prm_domain *prmd; int ret; - u32 v; + u32 v, mode; prmd = genpd_to_prm_domain(domain); if (!prmd->cap) @@ -530,7 +533,12 @@ static int omap_prm_domain_power_on(struct generic_pm_domain *domain) else v = readl_relaxed(prmd->prm->base + prmd->pwrstctrl); - writel_relaxed(v | OMAP_PRMD_ON_ACTIVE, + if (prmd->prm->data->flags & OMAP_PRM_RET_WHEN_IDLE) + mode = OMAP_PRMD_RETENTION; + else + mode = OMAP_PRMD_ON_ACTIVE; + + writel_relaxed((v & ~PRM_POWERSTATE_MASK) | mode, prmd->prm->base + prmd->pwrstctrl); /* wait for the transition bit to get cleared */ @@ -830,8 +838,12 @@ static int omap_reset_deassert(struct reset_controller_dev *rcdev, reset->prm->data->name, id); exit: - if (reset->clkdm) + if (reset->clkdm) { + /* At least dra7 iva needs a delay before clkdm idle */ + if (has_rstst) + udelay(1); pdata->clkdm_allow_idle(reset->clkdm); + } return ret; } diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index 59e45dc03a97..f27072837247 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -2734,7 +2734,7 @@ static int vchiq_probe(struct platform_device *pdev) return -ENOENT; } - drvdata->fw = rpi_firmware_get(fw_node); + drvdata->fw = devm_rpi_firmware_get(&pdev->dev, fw_node); of_node_put(fw_node); if (!drvdata->fw) return -EPROBE_DEFER; diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile index 56263ae3b1d7..3aa33ea9e6a6 100644 --- a/drivers/tee/optee/Makefile +++ b/drivers/tee/optee/Makefile @@ -6,3 +6,6 @@ optee-objs += rpc.o optee-objs += supp.o optee-objs += shm_pool.o optee-objs += device.o + +# for tracing framework to find optee_trace.h +CFLAGS_call.o := -I$(src) diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c index 7a77e375b503..6132cc8d014c 100644 --- a/drivers/tee/optee/call.c +++ b/drivers/tee/optee/call.c @@ -14,6 +14,8 @@ #include <linux/uaccess.h> #include "optee_private.h" #include "optee_smc.h" +#define CREATE_TRACE_POINTS +#include "optee_trace.h" struct optee_call_waiter { struct list_head list_node; @@ -138,9 +140,11 @@ u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) while (true) { struct arm_smccc_res res; + trace_optee_invoke_fn_begin(¶m); optee->invoke_fn(param.a0, param.a1, param.a2, param.a3, param.a4, param.a5, param.a6, param.a7, &res); + trace_optee_invoke_fn_end(¶m, &res); if (res.a0 == OPTEE_SMC_RETURN_ETHREAD_LIMIT) { /* diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index cf4718c6d35d..63542c1cc291 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -79,16 +79,6 @@ int optee_from_msg_param(struct tee_param *params, size_t num_params, return rc; p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa; p->u.memref.shm = shm; - - /* Check that the memref is covered by the shm object */ - if (p->u.memref.size) { - size_t o = p->u.memref.shm_offs + - p->u.memref.size - 1; - - rc = tee_shm_get_pa(shm, o, NULL); - if (rc) - return rc; - } break; case OPTEE_MSG_ATTR_TYPE_RMEM_INPUT: case OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT: diff --git a/drivers/tee/optee/optee_trace.h b/drivers/tee/optee/optee_trace.h new file mode 100644 index 000000000000..7c954eefa4bf --- /dev/null +++ b/drivers/tee/optee/optee_trace.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * optee trace points + * + * Copyright (C) 2021 Synaptics Incorporated + * Author: Jisheng Zhang <jszhang@kernel.org> + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM optee + +#if !defined(_TRACE_OPTEE_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_OPTEE_H + +#include <linux/arm-smccc.h> +#include <linux/tracepoint.h> +#include "optee_private.h" + +TRACE_EVENT(optee_invoke_fn_begin, + TP_PROTO(struct optee_rpc_param *param), + TP_ARGS(param), + + TP_STRUCT__entry( + __field(void *, param) + __array(u32, args, 8) + ), + + TP_fast_assign( + __entry->param = param; + BUILD_BUG_ON(sizeof(*param) < sizeof(__entry->args)); + memcpy(__entry->args, param, sizeof(__entry->args)); + ), + + TP_printk("param=%p (%x, %x, %x, %x, %x, %x, %x, %x)", __entry->param, + __entry->args[0], __entry->args[1], __entry->args[2], + __entry->args[3], __entry->args[4], __entry->args[5], + __entry->args[6], __entry->args[7]) +); + +TRACE_EVENT(optee_invoke_fn_end, + TP_PROTO(struct optee_rpc_param *param, struct arm_smccc_res *res), + TP_ARGS(param, res), + + TP_STRUCT__entry( + __field(void *, param) + __array(unsigned long, rets, 4) + ), + + TP_fast_assign( + __entry->param = param; + BUILD_BUG_ON(sizeof(*res) < sizeof(__entry->rets)); + memcpy(__entry->rets, res, sizeof(__entry->rets)); + ), + + TP_printk("param=%p ret (%lx, %lx, %lx, %lx)", __entry->param, + __entry->rets[0], __entry->rets[1], __entry->rets[2], + __entry->rets[3]) +); +#endif /* _TRACE_OPTEE_H */ + +#undef TRACE_INCLUDE_PATH +#define TRACE_INCLUDE_PATH . +#undef TRACE_INCLUDE_FILE +#define TRACE_INCLUDE_FILE optee_trace + +/* This part must be outside protection */ +#include <trace/define_trace.h> |