diff options
Diffstat (limited to 'drivers/soc')
42 files changed, 1528 insertions, 559 deletions
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 113e884697fd..446166ba0bec 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -18,7 +18,7 @@ obj-y += qcom/ obj-y += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_SOC_SAMSUNG) += samsung/ -obj-$(CONFIG_ARCH_SUNXI) += sunxi/ +obj-y += sunxi/ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_SOC_TI) += ti/ obj-$(CONFIG_ARCH_U8500) += ux500/ diff --git a/drivers/soc/actions/Kconfig b/drivers/soc/actions/Kconfig index 9d68b5a771c3..1a0b9649efb4 100644 --- a/drivers/soc/actions/Kconfig +++ b/drivers/soc/actions/Kconfig @@ -10,7 +10,7 @@ config OWL_PM_DOMAINS select PM_GENERIC_DOMAINS help Say 'y' here to enable support for Smart Power System (SPS) - power-gating on Actions Semiconductor S500 SoC. + power-gating on Actions Semiconductor S500, S700 and S900 SoCs. If unsure, say 'n'. endif diff --git a/drivers/soc/actions/Makefile b/drivers/soc/actions/Makefile index 1e101b06bab1..4db9e7b050e5 100644 --- a/drivers/soc/actions/Makefile +++ b/drivers/soc/actions/Makefile @@ -1,2 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0+ + obj-$(CONFIG_OWL_PM_DOMAINS_HELPER) += owl-sps-helper.o obj-$(CONFIG_OWL_PM_DOMAINS) += owl-sps.o diff --git a/drivers/soc/actions/owl-sps-helper.c b/drivers/soc/actions/owl-sps-helper.c index 9d7a2c2b44ec..291a206d6f04 100644 --- a/drivers/soc/actions/owl-sps-helper.c +++ b/drivers/soc/actions/owl-sps-helper.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Actions Semi Owl Smart Power System (SPS) shared helpers * @@ -5,11 +6,6 @@ * Author: Actions Semi, Inc. * * Copyright (c) 2017 Andreas Färber - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. */ #include <linux/delay.h> diff --git a/drivers/soc/actions/owl-sps.c b/drivers/soc/actions/owl-sps.c index 032921d8d41f..73a9e0bb7e8e 100644 --- a/drivers/soc/actions/owl-sps.c +++ b/drivers/soc/actions/owl-sps.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Actions Semi Owl Smart Power System (SPS) * @@ -5,11 +6,6 @@ * Author: Actions Semi, Inc. * * Copyright (c) 2017 Andreas Färber - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. */ #include <linux/of_address.h> @@ -18,6 +14,7 @@ #include <linux/soc/actions/owl-sps.h> #include <dt-bindings/power/owl-s500-powergate.h> #include <dt-bindings/power/owl-s700-powergate.h> +#include <dt-bindings/power/owl-s900-powergate.h> struct owl_sps_domain_info { const char *name; @@ -244,9 +241,66 @@ static const struct owl_sps_info s700_sps_info = { .domains = s700_sps_domains, }; +static const struct owl_sps_domain_info s900_sps_domains[] = { + [S900_PD_GPU_B] = { + .name = "GPU_B", + .pwr_bit = 3, + }, + [S900_PD_VCE] = { + .name = "VCE", + .pwr_bit = 4, + }, + [S900_PD_SENSOR] = { + .name = "SENSOR", + .pwr_bit = 5, + }, + [S900_PD_VDE] = { + .name = "VDE", + .pwr_bit = 6, + }, + [S900_PD_HDE] = { + .name = "HDE", + .pwr_bit = 7, + }, + [S900_PD_USB3] = { + .name = "USB3", + .pwr_bit = 8, + }, + [S900_PD_DDR0] = { + .name = "DDR0", + .pwr_bit = 9, + }, + [S900_PD_DDR1] = { + .name = "DDR1", + .pwr_bit = 10, + }, + [S900_PD_DE] = { + .name = "DE", + .pwr_bit = 13, + }, + [S900_PD_NAND] = { + .name = "NAND", + .pwr_bit = 14, + }, + [S900_PD_USB2_H0] = { + .name = "USB2_H0", + .pwr_bit = 15, + }, + [S900_PD_USB2_H1] = { + .name = "USB2_H1", + .pwr_bit = 16, + }, +}; + +static const struct owl_sps_info s900_sps_info = { + .num_domains = ARRAY_SIZE(s900_sps_domains), + .domains = s900_sps_domains, +}; + static const struct of_device_id owl_sps_of_matches[] = { { .compatible = "actions,s500-sps", .data = &s500_sps_info }, { .compatible = "actions,s700-sps", .data = &s700_sps_info }, + { .compatible = "actions,s900-sps", .data = &s900_sps_info }, { } }; diff --git a/drivers/soc/amlogic/Kconfig b/drivers/soc/amlogic/Kconfig index b04f6e4aedbc..2f282b472912 100644 --- a/drivers/soc/amlogic/Kconfig +++ b/drivers/soc/amlogic/Kconfig @@ -1,5 +1,12 @@ menu "Amlogic SoC drivers" +config MESON_CANVAS + tristate "Amlogic Meson Canvas driver" + depends on ARCH_MESON || COMPILE_TEST + default n + help + Say yes to support the canvas IP for Amlogic SoCs. + config MESON_GX_SOCINFO bool "Amlogic Meson GX SoC Information driver" depends on ARCH_MESON || COMPILE_TEST diff --git a/drivers/soc/amlogic/Makefile b/drivers/soc/amlogic/Makefile index 8fa321893928..0ab16d35ac36 100644 --- a/drivers/soc/amlogic/Makefile +++ b/drivers/soc/amlogic/Makefile @@ -1,3 +1,4 @@ +obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o diff --git a/drivers/soc/amlogic/meson-canvas.c b/drivers/soc/amlogic/meson-canvas.c new file mode 100644 index 000000000000..fce33ca76bb6 --- /dev/null +++ b/drivers/soc/amlogic/meson-canvas.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 BayLibre, SAS + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + * Copyright (C) 2014 Endless Mobile + */ + +#include <linux/kernel.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/soc/amlogic/meson-canvas.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/io.h> + +#define NUM_CANVAS 256 + +/* DMC Registers */ +#define DMC_CAV_LUT_DATAL 0x00 + #define CANVAS_WIDTH_LBIT 29 + #define CANVAS_WIDTH_LWID 3 +#define DMC_CAV_LUT_DATAH 0x04 + #define CANVAS_WIDTH_HBIT 0 + #define CANVAS_HEIGHT_BIT 9 + #define CANVAS_WRAP_BIT 22 + #define CANVAS_BLKMODE_BIT 24 + #define CANVAS_ENDIAN_BIT 26 +#define DMC_CAV_LUT_ADDR 0x08 + #define CANVAS_LUT_WR_EN BIT(9) + #define CANVAS_LUT_RD_EN BIT(8) + +struct meson_canvas { + struct device *dev; + void __iomem *reg_base; + spinlock_t lock; /* canvas device lock */ + u8 used[NUM_CANVAS]; +}; + +static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val) +{ + writel_relaxed(val, canvas->reg_base + reg); +} + +static u32 canvas_read(struct meson_canvas *canvas, u32 reg) +{ + return readl_relaxed(canvas->reg_base + reg); +} + +struct meson_canvas *meson_canvas_get(struct device *dev) +{ + struct device_node *canvas_node; + struct platform_device *canvas_pdev; + + canvas_node = of_parse_phandle(dev->of_node, "amlogic,canvas", 0); + if (!canvas_node) + return ERR_PTR(-ENODEV); + + canvas_pdev = of_find_device_by_node(canvas_node); + if (!canvas_pdev) + return ERR_PTR(-EPROBE_DEFER); + + return dev_get_drvdata(&canvas_pdev->dev); +} +EXPORT_SYMBOL_GPL(meson_canvas_get); + +int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, + u32 addr, u32 stride, u32 height, + unsigned int wrap, + unsigned int blkmode, + unsigned int endian) +{ + unsigned long flags; + + spin_lock_irqsave(&canvas->lock, flags); + if (!canvas->used[canvas_index]) { + dev_err(canvas->dev, + "Trying to setup non allocated canvas %u\n", + canvas_index); + spin_unlock_irqrestore(&canvas->lock, flags); + return -EINVAL; + } + + canvas_write(canvas, DMC_CAV_LUT_DATAL, + ((addr + 7) >> 3) | + (((stride + 7) >> 3) << CANVAS_WIDTH_LBIT)); + + canvas_write(canvas, DMC_CAV_LUT_DATAH, + ((((stride + 7) >> 3) >> CANVAS_WIDTH_LWID) << + CANVAS_WIDTH_HBIT) | + (height << CANVAS_HEIGHT_BIT) | + (wrap << CANVAS_WRAP_BIT) | + (blkmode << CANVAS_BLKMODE_BIT) | + (endian << CANVAS_ENDIAN_BIT)); + + canvas_write(canvas, DMC_CAV_LUT_ADDR, + CANVAS_LUT_WR_EN | canvas_index); + + /* Force a read-back to make sure everything is flushed. */ + canvas_read(canvas, DMC_CAV_LUT_DATAH); + spin_unlock_irqrestore(&canvas->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(meson_canvas_config); + +int meson_canvas_alloc(struct meson_canvas *canvas, u8 *canvas_index) +{ + int i; + unsigned long flags; + + spin_lock_irqsave(&canvas->lock, flags); + for (i = 0; i < NUM_CANVAS; ++i) { + if (!canvas->used[i]) { + canvas->used[i] = 1; + spin_unlock_irqrestore(&canvas->lock, flags); + *canvas_index = i; + return 0; + } + } + spin_unlock_irqrestore(&canvas->lock, flags); + + dev_err(canvas->dev, "No more canvas available\n"); + return -ENODEV; +} +EXPORT_SYMBOL_GPL(meson_canvas_alloc); + +int meson_canvas_free(struct meson_canvas *canvas, u8 canvas_index) +{ + unsigned long flags; + + spin_lock_irqsave(&canvas->lock, flags); + if (!canvas->used[canvas_index]) { + dev_err(canvas->dev, + "Trying to free unused canvas %u\n", canvas_index); + spin_unlock_irqrestore(&canvas->lock, flags); + return -EINVAL; + } + canvas->used[canvas_index] = 0; + spin_unlock_irqrestore(&canvas->lock, flags); + + return 0; +} +EXPORT_SYMBOL_GPL(meson_canvas_free); + +static int meson_canvas_probe(struct platform_device *pdev) +{ + struct resource *res; + struct meson_canvas *canvas; + struct device *dev = &pdev->dev; + + canvas = devm_kzalloc(dev, sizeof(*canvas), GFP_KERNEL); + if (!canvas) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + canvas->reg_base = devm_ioremap_resource(dev, res); + if (IS_ERR(canvas->reg_base)) + return PTR_ERR(canvas->reg_base); + + canvas->dev = dev; + spin_lock_init(&canvas->lock); + dev_set_drvdata(dev, canvas); + + return 0; +} + +static const struct of_device_id canvas_dt_match[] = { + { .compatible = "amlogic,canvas" }, + {} +}; +MODULE_DEVICE_TABLE(of, canvas_dt_match); + +static struct platform_driver meson_canvas_driver = { + .probe = meson_canvas_probe, + .driver = { + .name = "amlogic-canvas", + .of_match_table = canvas_dt_match, + }, +}; +module_platform_driver(meson_canvas_driver); + +MODULE_DESCRIPTION("Amlogic Canvas driver"); +MODULE_AUTHOR("Maxime Jourdan <mjourdan@baylibre.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c index b3da635970ea..aa3729ecaa9e 100644 --- a/drivers/soc/imx/gpc.c +++ b/drivers/soc/imx/gpc.c @@ -1,13 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> * Copyright 2011-2013 Freescale Semiconductor, Inc. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html */ #include <linux/clk.h> @@ -69,7 +63,7 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) u32 val; /* Read ISO and ISO2SW power down delays */ - regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val); + regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val); iso = val & 0x3f; iso2sw = (val >> 8) & 0x3f; @@ -247,6 +241,7 @@ builtin_platform_driver(imx_pgc_power_domain_driver) #define GPC_PGC_DOMAIN_ARM 0 #define GPC_PGC_DOMAIN_PU 1 #define GPC_PGC_DOMAIN_DISPLAY 2 +#define GPC_PGC_DOMAIN_PCI 3 static struct genpd_power_state imx6_pm_domain_pu_state = { .power_off_latency_ns = 25000, @@ -254,12 +249,13 @@ static struct genpd_power_state imx6_pm_domain_pu_state = { }; static struct imx_pm_domain imx_gpc_domains[] = { - { + [GPC_PGC_DOMAIN_ARM] { .base = { .name = "ARM", .flags = GENPD_FLAG_ALWAYS_ON, }, - }, { + }, + [GPC_PGC_DOMAIN_PU] { .base = { .name = "PU", .power_off = imx6_pm_domain_power_off, @@ -269,7 +265,8 @@ static struct imx_pm_domain imx_gpc_domains[] = { }, .reg_offs = 0x260, .cntr_pdn_bit = 0, - }, { + }, + [GPC_PGC_DOMAIN_DISPLAY] { .base = { .name = "DISPLAY", .power_off = imx6_pm_domain_power_off, @@ -277,7 +274,8 @@ static struct imx_pm_domain imx_gpc_domains[] = { }, .reg_offs = 0x240, .cntr_pdn_bit = 4, - }, { + }, + [GPC_PGC_DOMAIN_PCI] { .base = { .name = "PCI", .power_off = imx6_pm_domain_power_off, @@ -348,8 +346,8 @@ static const struct regmap_config imx_gpc_regmap_config = { }; static struct generic_pm_domain *imx_gpc_onecell_domains[] = { - &imx_gpc_domains[0].base, - &imx_gpc_domains[1].base, + &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base, + &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base, }; static struct genpd_onecell_data imx_gpc_onecell_data = { diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c index 6ef18cf8f243..e7b5994fee9d 100644 --- a/drivers/soc/imx/gpcv2.c +++ b/drivers/soc/imx/gpcv2.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2017 Impinj, Inc * Author: Andrey Smirnov <andrew.smirnov@gmail.com> @@ -5,29 +6,23 @@ * Based on the code of analogus driver: * * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html */ +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <dt-bindings/power/imx7-power.h> -#define GPC_LPCR_A7_BSC 0x000 +#define GPC_LPCR_A_CORE_BSC 0x000 #define GPC_PGC_CPU_MAPPING 0x0ec -#define USB_HSIC_PHY_A7_DOMAIN BIT(6) -#define USB_OTG2_PHY_A7_DOMAIN BIT(5) -#define USB_OTG1_PHY_A7_DOMAIN BIT(4) -#define PCIE_PHY_A7_DOMAIN BIT(3) -#define MIPI_PHY_A7_DOMAIN BIT(2) +#define USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) +#define USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) +#define USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) +#define PCIE_PHY_A_CORE_DOMAIN BIT(3) +#define MIPI_PHY_A_CORE_DOMAIN BIT(2) #define GPC_PU_PGC_SW_PUP_REQ 0x0f8 #define GPC_PU_PGC_SW_PDN_REQ 0x104 @@ -53,7 +48,7 @@ #define GPC_PGC_CTRL_PCR BIT(0) -struct imx7_pgc_domain { +struct imx_pgc_domain { struct generic_pm_domain genpd; struct regmap *regmap; struct regulator *regulator; @@ -69,11 +64,16 @@ struct imx7_pgc_domain { struct device *dev; }; -static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, +struct imx_pgc_domain_data { + const struct imx_pgc_domain *domains; + size_t domains_num; +}; + +static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, bool on) { - struct imx7_pgc_domain *domain = container_of(genpd, - struct imx7_pgc_domain, + struct imx_pgc_domain *domain = container_of(genpd, + struct imx_pgc_domain, genpd); unsigned int offset = on ? GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ; @@ -150,24 +150,24 @@ unmap: return ret; } -static int imx7_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd) +static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd) { - return imx7_gpc_pu_pgc_sw_pxx_req(genpd, true); + return imx_gpc_pu_pgc_sw_pxx_req(genpd, true); } -static int imx7_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd) +static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd) { - return imx7_gpc_pu_pgc_sw_pxx_req(genpd, false); + return imx_gpc_pu_pgc_sw_pxx_req(genpd, false); } -static const struct imx7_pgc_domain imx7_pgc_domains[] = { +static const struct imx_pgc_domain imx7_pgc_domains[] = { [IMX7_POWER_DOMAIN_MIPI_PHY] = { .genpd = { .name = "mipi-phy", }, .bits = { .pxx = MIPI_PHY_SW_Pxx_REQ, - .map = MIPI_PHY_A7_DOMAIN, + .map = MIPI_PHY_A_CORE_DOMAIN, }, .voltage = 1000000, .pgc = PGC_MIPI, @@ -179,7 +179,7 @@ static const struct imx7_pgc_domain imx7_pgc_domains[] = { }, .bits = { .pxx = PCIE_PHY_SW_Pxx_REQ, - .map = PCIE_PHY_A7_DOMAIN, + .map = PCIE_PHY_A_CORE_DOMAIN, }, .voltage = 1000000, .pgc = PGC_PCIE, @@ -191,16 +191,21 @@ static const struct imx7_pgc_domain imx7_pgc_domains[] = { }, .bits = { .pxx = USB_HSIC_PHY_SW_Pxx_REQ, - .map = USB_HSIC_PHY_A7_DOMAIN, + .map = USB_HSIC_PHY_A_CORE_DOMAIN, }, .voltage = 1200000, .pgc = PGC_USB_HSIC, }, }; -static int imx7_pgc_domain_probe(struct platform_device *pdev) +static const struct imx_pgc_domain_data imx7_pgc_domain_data = { + .domains = imx7_pgc_domains, + .domains_num = ARRAY_SIZE(imx7_pgc_domains), +}; + +static int imx_pgc_domain_probe(struct platform_device *pdev) { - struct imx7_pgc_domain *domain = pdev->dev.platform_data; + struct imx_pgc_domain *domain = pdev->dev.platform_data; int ret; domain->dev = &pdev->dev; @@ -233,9 +238,9 @@ static int imx7_pgc_domain_probe(struct platform_device *pdev) return ret; } -static int imx7_pgc_domain_remove(struct platform_device *pdev) +static int imx_pgc_domain_remove(struct platform_device *pdev) { - struct imx7_pgc_domain *domain = pdev->dev.platform_data; + struct imx_pgc_domain *domain = pdev->dev.platform_data; of_genpd_del_provider(domain->dev->of_node); pm_genpd_remove(&domain->genpd); @@ -243,25 +248,26 @@ static int imx7_pgc_domain_remove(struct platform_device *pdev) return 0; } -static const struct platform_device_id imx7_pgc_domain_id[] = { - { "imx7-pgc-domain", }, +static const struct platform_device_id imx_pgc_domain_id[] = { + { "imx-pgc-domain", }, { }, }; -static struct platform_driver imx7_pgc_domain_driver = { +static struct platform_driver imx_pgc_domain_driver = { .driver = { - .name = "imx7-pgc", + .name = "imx-pgc", }, - .probe = imx7_pgc_domain_probe, - .remove = imx7_pgc_domain_remove, - .id_table = imx7_pgc_domain_id, + .probe = imx_pgc_domain_probe, + .remove = imx_pgc_domain_remove, + .id_table = imx_pgc_domain_id, }; -builtin_platform_driver(imx7_pgc_domain_driver) +builtin_platform_driver(imx_pgc_domain_driver) static int imx_gpcv2_probe(struct platform_device *pdev) { + static const struct imx_pgc_domain_data *domain_data; static const struct regmap_range yes_ranges[] = { - regmap_reg_range(GPC_LPCR_A7_BSC, + regmap_reg_range(GPC_LPCR_A_CORE_BSC, GPC_M4_PU_PDN_FLG), regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI), GPC_PGC_SR(PGC_MIPI)), @@ -307,9 +313,11 @@ static int imx_gpcv2_probe(struct platform_device *pdev) return ret; } + domain_data = of_device_get_match_data(&pdev->dev); + for_each_child_of_node(pgc_np, np) { struct platform_device *pd_pdev; - struct imx7_pgc_domain *domain; + struct imx_pgc_domain *domain; u32 domain_index; ret = of_property_read_u32(np, "reg", &domain_index); @@ -319,14 +327,14 @@ static int imx_gpcv2_probe(struct platform_device *pdev) return ret; } - if (domain_index >= ARRAY_SIZE(imx7_pgc_domains)) { + if (domain_index >= domain_data->domains_num) { dev_warn(dev, "Domain index %d is out of bounds\n", domain_index); continue; } - pd_pdev = platform_device_alloc("imx7-pgc-domain", + pd_pdev = platform_device_alloc("imx-pgc-domain", domain_index); if (!pd_pdev) { dev_err(dev, "Failed to allocate platform device\n"); @@ -335,8 +343,8 @@ static int imx_gpcv2_probe(struct platform_device *pdev) } ret = platform_device_add_data(pd_pdev, - &imx7_pgc_domains[domain_index], - sizeof(imx7_pgc_domains[domain_index])); + &domain_data->domains[domain_index], + sizeof(domain_data->domains[domain_index])); if (ret) { platform_device_put(pd_pdev); of_node_put(np); @@ -345,8 +353,8 @@ static int imx_gpcv2_probe(struct platform_device *pdev) domain = pd_pdev->dev.platform_data; domain->regmap = regmap; - domain->genpd.power_on = imx7_gpc_pu_pgc_sw_pup_req; - domain->genpd.power_off = imx7_gpc_pu_pgc_sw_pdn_req; + domain->genpd.power_on = imx_gpc_pu_pgc_sw_pup_req; + domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req; pd_pdev->dev.parent = dev; pd_pdev->dev.of_node = np; @@ -363,7 +371,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev) } static const struct of_device_id imx_gpcv2_dt_ids[] = { - { .compatible = "fsl,imx7d-gpc" }, + { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, }, { } }; diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index 4e931fdf4d09..8236a6c87e19 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -76,6 +76,13 @@ #define PWRAP_SLV_CAP_SECURITY BIT(2) #define HAS_CAP(_c, _x) (((_c) & (_x)) == (_x)) +/* Group of bits used for shown pwrap capability */ +#define PWRAP_CAP_BRIDGE BIT(0) +#define PWRAP_CAP_RESET BIT(1) +#define PWRAP_CAP_DCM BIT(2) +#define PWRAP_CAP_INT1_EN BIT(3) +#define PWRAP_CAP_WDT_SRC1 BIT(4) + /* defines for slave device wrapper registers */ enum dew_regs { PWRAP_DEW_BASE, @@ -91,6 +98,27 @@ enum dew_regs { PWRAP_DEW_CIPHER_MODE, PWRAP_DEW_CIPHER_SWRST, + /* MT6323 only regs */ + PWRAP_DEW_CIPHER_EN, + PWRAP_DEW_RDDMY_NO, + + /* MT6358 only regs */ + PWRAP_SMT_CON1, + PWRAP_DRV_CON1, + PWRAP_FILTER_CON0, + PWRAP_GPIO_PULLEN0_CLR, + PWRAP_RG_SPI_CON0, + PWRAP_RG_SPI_RECORD0, + PWRAP_RG_SPI_CON2, + PWRAP_RG_SPI_CON3, + PWRAP_RG_SPI_CON4, + PWRAP_RG_SPI_CON5, + PWRAP_RG_SPI_CON6, + PWRAP_RG_SPI_CON7, + PWRAP_RG_SPI_CON8, + PWRAP_RG_SPI_CON13, + PWRAP_SPISLV_KEY, + /* MT6397 only regs */ PWRAP_DEW_EVENT_OUT_EN, PWRAP_DEW_EVENT_SRC_EN, @@ -100,10 +128,6 @@ enum dew_regs { PWRAP_DEW_EVENT_TEST, PWRAP_DEW_CIPHER_LOAD, PWRAP_DEW_CIPHER_START, - - /* MT6323 only regs */ - PWRAP_DEW_CIPHER_EN, - PWRAP_DEW_RDDMY_NO, }; static const u32 mt6323_regs[] = { @@ -123,6 +147,64 @@ static const u32 mt6323_regs[] = { [PWRAP_DEW_RDDMY_NO] = 0x01a4, }; +static const u32 mt6351_regs[] = { + [PWRAP_DEW_DIO_EN] = 0x02F2, + [PWRAP_DEW_READ_TEST] = 0x02F4, + [PWRAP_DEW_WRITE_TEST] = 0x02F6, + [PWRAP_DEW_CRC_EN] = 0x02FA, + [PWRAP_DEW_CRC_VAL] = 0x02FC, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0300, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x0302, + [PWRAP_DEW_CIPHER_EN] = 0x0304, + [PWRAP_DEW_CIPHER_RDY] = 0x0306, + [PWRAP_DEW_CIPHER_MODE] = 0x0308, + [PWRAP_DEW_CIPHER_SWRST] = 0x030A, + [PWRAP_DEW_RDDMY_NO] = 0x030C, +}; + +static const u32 mt6357_regs[] = { + [PWRAP_DEW_DIO_EN] = 0x040A, + [PWRAP_DEW_READ_TEST] = 0x040C, + [PWRAP_DEW_WRITE_TEST] = 0x040E, + [PWRAP_DEW_CRC_EN] = 0x0412, + [PWRAP_DEW_CRC_VAL] = 0x0414, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0418, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x041A, + [PWRAP_DEW_CIPHER_EN] = 0x041C, + [PWRAP_DEW_CIPHER_RDY] = 0x041E, + [PWRAP_DEW_CIPHER_MODE] = 0x0420, + [PWRAP_DEW_CIPHER_SWRST] = 0x0422, + [PWRAP_DEW_RDDMY_NO] = 0x0424, +}; + +static const u32 mt6358_regs[] = { + [PWRAP_SMT_CON1] = 0x0030, + [PWRAP_DRV_CON1] = 0x0038, + [PWRAP_FILTER_CON0] = 0x0040, + [PWRAP_GPIO_PULLEN0_CLR] = 0x0098, + [PWRAP_RG_SPI_CON0] = 0x0408, + [PWRAP_RG_SPI_RECORD0] = 0x040a, + [PWRAP_DEW_DIO_EN] = 0x040c, + [PWRAP_DEW_READ_TEST] = 0x040e, + [PWRAP_DEW_WRITE_TEST] = 0x0410, + [PWRAP_DEW_CRC_EN] = 0x0414, + [PWRAP_DEW_CIPHER_KEY_SEL] = 0x041a, + [PWRAP_DEW_CIPHER_IV_SEL] = 0x041c, + [PWRAP_DEW_CIPHER_EN] = 0x041e, + [PWRAP_DEW_CIPHER_RDY] = 0x0420, + [PWRAP_DEW_CIPHER_MODE] = 0x0422, + [PWRAP_DEW_CIPHER_SWRST] = 0x0424, + [PWRAP_RG_SPI_CON2] = 0x0432, + [PWRAP_RG_SPI_CON3] = 0x0434, + [PWRAP_RG_SPI_CON4] = 0x0436, + [PWRAP_RG_SPI_CON5] = 0x0438, + [PWRAP_RG_SPI_CON6] = 0x043a, + [PWRAP_RG_SPI_CON7] = 0x043c, + [PWRAP_RG_SPI_CON8] = 0x043e, + [PWRAP_RG_SPI_CON13] = 0x0448, + [PWRAP_SPISLV_KEY] = 0x044a, +}; + static const u32 mt6397_regs[] = { [PWRAP_DEW_BASE] = 0xbc00, [PWRAP_DEW_EVENT_OUT_EN] = 0xbc00, @@ -146,21 +228,6 @@ static const u32 mt6397_regs[] = { [PWRAP_DEW_CIPHER_SWRST] = 0xbc24, }; -static const u32 mt6351_regs[] = { - [PWRAP_DEW_DIO_EN] = 0x02F2, - [PWRAP_DEW_READ_TEST] = 0x02F4, - [PWRAP_DEW_WRITE_TEST] = 0x02F6, - [PWRAP_DEW_CRC_EN] = 0x02FA, - [PWRAP_DEW_CRC_VAL] = 0x02FC, - [PWRAP_DEW_CIPHER_KEY_SEL] = 0x0300, - [PWRAP_DEW_CIPHER_IV_SEL] = 0x0302, - [PWRAP_DEW_CIPHER_EN] = 0x0304, - [PWRAP_DEW_CIPHER_RDY] = 0x0306, - [PWRAP_DEW_CIPHER_MODE] = 0x0308, - [PWRAP_DEW_CIPHER_SWRST] = 0x030A, - [PWRAP_DEW_RDDMY_NO] = 0x030C, -}; - enum pwrap_regs { PWRAP_MUX_SEL, PWRAP_WRAP_EN, @@ -221,6 +288,8 @@ enum pwrap_regs { PWRAP_CIPHER_SWRST, PWRAP_DCM_EN, PWRAP_DCM_DBC_PRD, + PWRAP_EINT_STA0_ADR, + PWRAP_EINT_STA1_ADR, /* MT2701 only regs */ PWRAP_ADC_CMD_ADDR, @@ -230,8 +299,6 @@ enum pwrap_regs { PWRAP_ADC_RDATA_ADDR2, /* MT7622 only regs */ - PWRAP_EINT_STA0_ADR, - PWRAP_EINT_STA1_ADR, PWRAP_STA, PWRAP_CLR, PWRAP_DVFS_ADR8, @@ -293,6 +360,27 @@ enum pwrap_regs { PWRAP_DVFS_WDATA7, PWRAP_SPMINF_STA, PWRAP_CIPHER_EN, + + /* MT8183 only regs */ + PWRAP_SI_SAMPLE_CTRL, + PWRAP_CSLEXT_WRITE, + PWRAP_CSLEXT_READ, + PWRAP_EXT_CK_WRITE, + PWRAP_STAUPD_CTRL, + PWRAP_WACS_P2P_EN, + PWRAP_INIT_DONE_P2P, + PWRAP_WACS_MD32_EN, + PWRAP_INIT_DONE_MD32, + PWRAP_INT1_EN, + PWRAP_INT1_FLG, + PWRAP_INT1_CLR, + PWRAP_WDT_SRC_EN_1, + PWRAP_INT_GPS_AUXADC_CMD_ADDR, + PWRAP_INT_GPS_AUXADC_CMD, + PWRAP_INT_GPS_AUXADC_RDATA_ADDR, + PWRAP_EXT_GPS_AUXADC_RDATA_ADDR, + PWRAP_GPSINF_0_STA, + PWRAP_GPSINF_1_STA, }; static int mt2701_regs[] = { @@ -381,6 +469,38 @@ static int mt2701_regs[] = { [PWRAP_ADC_RDATA_ADDR2] = 0x154, }; +static int mt6765_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_RDDMY] = 0x20, + [PWRAP_CSHEXT_WRITE] = 0x24, + [PWRAP_CSHEXT_READ] = 0x28, + [PWRAP_CSLEXT_START] = 0x2C, + [PWRAP_CSLEXT_END] = 0x30, + [PWRAP_STAUPD_PRD] = 0x3C, + [PWRAP_HARB_HPRIO] = 0x68, + [PWRAP_HIPRIO_ARB_EN] = 0x6C, + [PWRAP_MAN_EN] = 0x7C, + [PWRAP_MAN_CMD] = 0x80, + [PWRAP_WACS0_EN] = 0x8C, + [PWRAP_WACS1_EN] = 0x94, + [PWRAP_WACS2_EN] = 0x9C, + [PWRAP_INIT_DONE2] = 0xA0, + [PWRAP_WACS2_CMD] = 0xC20, + [PWRAP_WACS2_RDATA] = 0xC24, + [PWRAP_WACS2_VLDCLR] = 0xC28, + [PWRAP_INT_EN] = 0xB4, + [PWRAP_INT_FLG_RAW] = 0xB8, + [PWRAP_INT_FLG] = 0xBC, + [PWRAP_INT_CLR] = 0xC0, + [PWRAP_TIMER_EN] = 0xE8, + [PWRAP_WDT_UNIT] = 0xF0, + [PWRAP_WDT_SRC_EN] = 0xF4, + [PWRAP_DCM_EN] = 0x1DC, + [PWRAP_DCM_DBC_PRD] = 0x1E0, +}; + static int mt6797_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -526,6 +646,79 @@ static int mt7622_regs[] = { [PWRAP_SPI2_CTRL] = 0x244, }; +static int mt8135_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_SIDLY] = 0xc, + [PWRAP_CSHEXT] = 0x10, + [PWRAP_CSHEXT_WRITE] = 0x14, + [PWRAP_CSHEXT_READ] = 0x18, + [PWRAP_CSLEXT_START] = 0x1c, + [PWRAP_CSLEXT_END] = 0x20, + [PWRAP_STAUPD_PRD] = 0x24, + [PWRAP_STAUPD_GRPEN] = 0x28, + [PWRAP_STAUPD_MAN_TRIG] = 0x2c, + [PWRAP_STAUPD_STA] = 0x30, + [PWRAP_EVENT_IN_EN] = 0x34, + [PWRAP_EVENT_DST_EN] = 0x38, + [PWRAP_WRAP_STA] = 0x3c, + [PWRAP_RRARB_INIT] = 0x40, + [PWRAP_RRARB_EN] = 0x44, + [PWRAP_RRARB_STA0] = 0x48, + [PWRAP_RRARB_STA1] = 0x4c, + [PWRAP_HARB_INIT] = 0x50, + [PWRAP_HARB_HPRIO] = 0x54, + [PWRAP_HIPRIO_ARB_EN] = 0x58, + [PWRAP_HARB_STA0] = 0x5c, + [PWRAP_HARB_STA1] = 0x60, + [PWRAP_MAN_EN] = 0x64, + [PWRAP_MAN_CMD] = 0x68, + [PWRAP_MAN_RDATA] = 0x6c, + [PWRAP_MAN_VLDCLR] = 0x70, + [PWRAP_WACS0_EN] = 0x74, + [PWRAP_INIT_DONE0] = 0x78, + [PWRAP_WACS0_CMD] = 0x7c, + [PWRAP_WACS0_RDATA] = 0x80, + [PWRAP_WACS0_VLDCLR] = 0x84, + [PWRAP_WACS1_EN] = 0x88, + [PWRAP_INIT_DONE1] = 0x8c, + [PWRAP_WACS1_CMD] = 0x90, + [PWRAP_WACS1_RDATA] = 0x94, + [PWRAP_WACS1_VLDCLR] = 0x98, + [PWRAP_WACS2_EN] = 0x9c, + [PWRAP_INIT_DONE2] = 0xa0, + [PWRAP_WACS2_CMD] = 0xa4, + [PWRAP_WACS2_RDATA] = 0xa8, + [PWRAP_WACS2_VLDCLR] = 0xac, + [PWRAP_INT_EN] = 0xb0, + [PWRAP_INT_FLG_RAW] = 0xb4, + [PWRAP_INT_FLG] = 0xb8, + [PWRAP_INT_CLR] = 0xbc, + [PWRAP_SIG_ADR] = 0xc0, + [PWRAP_SIG_MODE] = 0xc4, + [PWRAP_SIG_VALUE] = 0xc8, + [PWRAP_SIG_ERRVAL] = 0xcc, + [PWRAP_CRC_EN] = 0xd0, + [PWRAP_EVENT_STA] = 0xd4, + [PWRAP_EVENT_STACLR] = 0xd8, + [PWRAP_TIMER_EN] = 0xdc, + [PWRAP_TIMER_STA] = 0xe0, + [PWRAP_WDT_UNIT] = 0xe4, + [PWRAP_WDT_SRC_EN] = 0xe8, + [PWRAP_WDT_FLG] = 0xec, + [PWRAP_DEBUG_INT_SEL] = 0xf0, + [PWRAP_CIPHER_KEY_SEL] = 0x134, + [PWRAP_CIPHER_IV_SEL] = 0x138, + [PWRAP_CIPHER_LOAD] = 0x13c, + [PWRAP_CIPHER_START] = 0x140, + [PWRAP_CIPHER_RDY] = 0x144, + [PWRAP_CIPHER_MODE] = 0x148, + [PWRAP_CIPHER_SWRST] = 0x14c, + [PWRAP_DCM_EN] = 0x15c, + [PWRAP_DCM_DBC_PRD] = 0x160, +}; + static int mt8173_regs[] = { [PWRAP_MUX_SEL] = 0x0, [PWRAP_WRAP_EN] = 0x4, @@ -608,92 +801,74 @@ static int mt8173_regs[] = { [PWRAP_DCM_DBC_PRD] = 0x148, }; -static int mt8135_regs[] = { - [PWRAP_MUX_SEL] = 0x0, - [PWRAP_WRAP_EN] = 0x4, - [PWRAP_DIO_EN] = 0x8, - [PWRAP_SIDLY] = 0xc, - [PWRAP_CSHEXT] = 0x10, - [PWRAP_CSHEXT_WRITE] = 0x14, - [PWRAP_CSHEXT_READ] = 0x18, - [PWRAP_CSLEXT_START] = 0x1c, - [PWRAP_CSLEXT_END] = 0x20, - [PWRAP_STAUPD_PRD] = 0x24, - [PWRAP_STAUPD_GRPEN] = 0x28, - [PWRAP_STAUPD_MAN_TRIG] = 0x2c, - [PWRAP_STAUPD_STA] = 0x30, - [PWRAP_EVENT_IN_EN] = 0x34, - [PWRAP_EVENT_DST_EN] = 0x38, - [PWRAP_WRAP_STA] = 0x3c, - [PWRAP_RRARB_INIT] = 0x40, - [PWRAP_RRARB_EN] = 0x44, - [PWRAP_RRARB_STA0] = 0x48, - [PWRAP_RRARB_STA1] = 0x4c, - [PWRAP_HARB_INIT] = 0x50, - [PWRAP_HARB_HPRIO] = 0x54, - [PWRAP_HIPRIO_ARB_EN] = 0x58, - [PWRAP_HARB_STA0] = 0x5c, - [PWRAP_HARB_STA1] = 0x60, - [PWRAP_MAN_EN] = 0x64, - [PWRAP_MAN_CMD] = 0x68, - [PWRAP_MAN_RDATA] = 0x6c, - [PWRAP_MAN_VLDCLR] = 0x70, - [PWRAP_WACS0_EN] = 0x74, - [PWRAP_INIT_DONE0] = 0x78, - [PWRAP_WACS0_CMD] = 0x7c, - [PWRAP_WACS0_RDATA] = 0x80, - [PWRAP_WACS0_VLDCLR] = 0x84, - [PWRAP_WACS1_EN] = 0x88, - [PWRAP_INIT_DONE1] = 0x8c, - [PWRAP_WACS1_CMD] = 0x90, - [PWRAP_WACS1_RDATA] = 0x94, - [PWRAP_WACS1_VLDCLR] = 0x98, - [PWRAP_WACS2_EN] = 0x9c, - [PWRAP_INIT_DONE2] = 0xa0, - [PWRAP_WACS2_CMD] = 0xa4, - [PWRAP_WACS2_RDATA] = 0xa8, - [PWRAP_WACS2_VLDCLR] = 0xac, - [PWRAP_INT_EN] = 0xb0, - [PWRAP_INT_FLG_RAW] = 0xb4, - [PWRAP_INT_FLG] = 0xb8, - [PWRAP_INT_CLR] = 0xbc, - [PWRAP_SIG_ADR] = 0xc0, - [PWRAP_SIG_MODE] = 0xc4, - [PWRAP_SIG_VALUE] = 0xc8, - [PWRAP_SIG_ERRVAL] = 0xcc, - [PWRAP_CRC_EN] = 0xd0, - [PWRAP_EVENT_STA] = 0xd4, - [PWRAP_EVENT_STACLR] = 0xd8, - [PWRAP_TIMER_EN] = 0xdc, - [PWRAP_TIMER_STA] = 0xe0, - [PWRAP_WDT_UNIT] = 0xe4, - [PWRAP_WDT_SRC_EN] = 0xe8, - [PWRAP_WDT_FLG] = 0xec, - [PWRAP_DEBUG_INT_SEL] = 0xf0, - [PWRAP_CIPHER_KEY_SEL] = 0x134, - [PWRAP_CIPHER_IV_SEL] = 0x138, - [PWRAP_CIPHER_LOAD] = 0x13c, - [PWRAP_CIPHER_START] = 0x140, - [PWRAP_CIPHER_RDY] = 0x144, - [PWRAP_CIPHER_MODE] = 0x148, - [PWRAP_CIPHER_SWRST] = 0x14c, - [PWRAP_DCM_EN] = 0x15c, - [PWRAP_DCM_DBC_PRD] = 0x160, +static int mt8183_regs[] = { + [PWRAP_MUX_SEL] = 0x0, + [PWRAP_WRAP_EN] = 0x4, + [PWRAP_DIO_EN] = 0x8, + [PWRAP_SI_SAMPLE_CTRL] = 0xC, + [PWRAP_RDDMY] = 0x14, + [PWRAP_CSHEXT_WRITE] = 0x18, + [PWRAP_CSHEXT_READ] = 0x1C, + [PWRAP_CSLEXT_WRITE] = 0x20, + [PWRAP_CSLEXT_READ] = 0x24, + [PWRAP_EXT_CK_WRITE] = 0x28, + [PWRAP_STAUPD_CTRL] = 0x30, + [PWRAP_STAUPD_GRPEN] = 0x34, + [PWRAP_EINT_STA0_ADR] = 0x38, + [PWRAP_HARB_HPRIO] = 0x5C, + [PWRAP_HIPRIO_ARB_EN] = 0x60, + [PWRAP_MAN_EN] = 0x70, + [PWRAP_MAN_CMD] = 0x74, + [PWRAP_WACS0_EN] = 0x80, + [PWRAP_INIT_DONE0] = 0x84, + [PWRAP_WACS1_EN] = 0x88, + [PWRAP_INIT_DONE1] = 0x8C, + [PWRAP_WACS2_EN] = 0x90, + [PWRAP_INIT_DONE2] = 0x94, + [PWRAP_WACS_P2P_EN] = 0xA0, + [PWRAP_INIT_DONE_P2P] = 0xA4, + [PWRAP_WACS_MD32_EN] = 0xA8, + [PWRAP_INIT_DONE_MD32] = 0xAC, + [PWRAP_INT_EN] = 0xB0, + [PWRAP_INT_FLG] = 0xB8, + [PWRAP_INT_CLR] = 0xBC, + [PWRAP_INT1_EN] = 0xC0, + [PWRAP_INT1_FLG] = 0xC8, + [PWRAP_INT1_CLR] = 0xCC, + [PWRAP_SIG_ADR] = 0xD0, + [PWRAP_CRC_EN] = 0xE0, + [PWRAP_TIMER_EN] = 0xE4, + [PWRAP_WDT_UNIT] = 0xEC, + [PWRAP_WDT_SRC_EN] = 0xF0, + [PWRAP_WDT_SRC_EN_1] = 0xF4, + [PWRAP_INT_GPS_AUXADC_CMD_ADDR] = 0x1DC, + [PWRAP_INT_GPS_AUXADC_CMD] = 0x1E0, + [PWRAP_INT_GPS_AUXADC_RDATA_ADDR] = 0x1E4, + [PWRAP_EXT_GPS_AUXADC_RDATA_ADDR] = 0x1E8, + [PWRAP_GPSINF_0_STA] = 0x1EC, + [PWRAP_GPSINF_1_STA] = 0x1F0, + [PWRAP_WACS2_CMD] = 0xC20, + [PWRAP_WACS2_RDATA] = 0xC24, + [PWRAP_WACS2_VLDCLR] = 0xC28, }; enum pmic_type { PMIC_MT6323, PMIC_MT6351, + PMIC_MT6357, + PMIC_MT6358, PMIC_MT6380, PMIC_MT6397, }; enum pwrap_type { PWRAP_MT2701, + PWRAP_MT6765, PWRAP_MT6797, PWRAP_MT7622, PWRAP_MT8135, PWRAP_MT8173, + PWRAP_MT8183, }; struct pmic_wrapper; @@ -731,9 +906,11 @@ struct pmic_wrapper_type { enum pwrap_type type; u32 arb_en_all; u32 int_en_all; + u32 int1_en_all; u32 spi_w; u32 wdt_src; - unsigned int has_bridge:1; + /* Flags indicating the capability for the target pwrap */ + u32 caps; int (*init_reg_clock)(struct pmic_wrapper *wrp); int (*init_soc_specific)(struct pmic_wrapper *wrp); }; @@ -1096,7 +1273,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) ret = pwrap_read(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_RDY], &rdata); if (ret) - return 0; + return false; return rdata == 1; } @@ -1117,6 +1294,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_CIPHER_START); break; case PWRAP_MT2701: + case PWRAP_MT6765: case PWRAP_MT6797: case PWRAP_MT8173: pwrap_writel(wrp, 1, PWRAP_CIPHER_EN); @@ -1124,6 +1302,8 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) case PWRAP_MT7622: pwrap_writel(wrp, 0, PWRAP_CIPHER_EN); break; + case PWRAP_MT8183: + break; } /* Config cipher mode @PMIC */ @@ -1141,6 +1321,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp) break; case PMIC_MT6323: case PMIC_MT6351: + case PMIC_MT6357: pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN], 0x1); break; @@ -1276,6 +1457,23 @@ static int pwrap_mt7622_init_soc_specific(struct pmic_wrapper *wrp) return 0; } +static int pwrap_mt8183_init_soc_specific(struct pmic_wrapper *wrp) +{ + pwrap_writel(wrp, 0xf5, PWRAP_STAUPD_GRPEN); + + pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CRC_EN], 0x1); + pwrap_writel(wrp, 1, PWRAP_CRC_EN); + pwrap_writel(wrp, 0x416, PWRAP_SIG_ADR); + pwrap_writel(wrp, 0x42e, PWRAP_EINT_STA0_ADR); + + pwrap_writel(wrp, 1, PWRAP_WACS_P2P_EN); + pwrap_writel(wrp, 1, PWRAP_WACS_MD32_EN); + pwrap_writel(wrp, 1, PWRAP_INIT_DONE_P2P); + pwrap_writel(wrp, 1, PWRAP_INIT_DONE_MD32); + + return 0; +} + static int pwrap_init(struct pmic_wrapper *wrp) { int ret; @@ -1348,7 +1546,7 @@ static int pwrap_init(struct pmic_wrapper *wrp) pwrap_writel(wrp, 1, PWRAP_INIT_DONE0); pwrap_writel(wrp, 1, PWRAP_INIT_DONE1); - if (wrp->master->has_bridge) { + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_BRIDGE)) { writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE3); writel(1, wrp->bridge_base + PWRAP_MT8135_BRIDGE_INIT_DONE4); } @@ -1362,11 +1560,15 @@ static irqreturn_t pwrap_interrupt(int irqno, void *dev_id) struct pmic_wrapper *wrp = dev_id; rdata = pwrap_readl(wrp, PWRAP_INT_FLG); - dev_err(wrp->dev, "unexpected interrupt int=0x%x\n", rdata); - pwrap_writel(wrp, 0xffffffff, PWRAP_INT_CLR); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_INT1_EN)) { + rdata = pwrap_readl(wrp, PWRAP_INT1_FLG); + dev_err(wrp->dev, "unexpected interrupt int1=0x%x\n", rdata); + pwrap_writel(wrp, 0xffffffff, PWRAP_INT1_CLR); + } + return IRQ_HANDLED; } @@ -1398,6 +1600,33 @@ static const struct pwrap_slv_type pmic_mt6323 = { .pwrap_write = pwrap_write16, }; +static const struct pwrap_slv_type pmic_mt6351 = { + .dew_regs = mt6351_regs, + .type = PMIC_MT6351, + .regmap = &pwrap_regmap_config16, + .caps = 0, + .pwrap_read = pwrap_read16, + .pwrap_write = pwrap_write16, +}; + +static const struct pwrap_slv_type pmic_mt6357 = { + .dew_regs = mt6357_regs, + .type = PMIC_MT6357, + .regmap = &pwrap_regmap_config16, + .caps = 0, + .pwrap_read = pwrap_read16, + .pwrap_write = pwrap_write16, +}; + +static const struct pwrap_slv_type pmic_mt6358 = { + .dew_regs = mt6358_regs, + .type = PMIC_MT6358, + .regmap = &pwrap_regmap_config16, + .caps = PWRAP_SLV_CAP_SPI | PWRAP_SLV_CAP_DUALIO, + .pwrap_read = pwrap_read16, + .pwrap_write = pwrap_write16, +}; + static const struct pwrap_slv_type pmic_mt6380 = { .dew_regs = NULL, .type = PMIC_MT6380, @@ -1417,20 +1646,20 @@ static const struct pwrap_slv_type pmic_mt6397 = { .pwrap_write = pwrap_write16, }; -static const struct pwrap_slv_type pmic_mt6351 = { - .dew_regs = mt6351_regs, - .type = PMIC_MT6351, - .regmap = &pwrap_regmap_config16, - .caps = 0, - .pwrap_read = pwrap_read16, - .pwrap_write = pwrap_write16, -}; - static const struct of_device_id of_slave_match_tbl[] = { { .compatible = "mediatek,mt6323", .data = &pmic_mt6323, }, { + .compatible = "mediatek,mt6351", + .data = &pmic_mt6351, + }, { + .compatible = "mediatek,mt6357", + .data = &pmic_mt6357, + }, { + .compatible = "mediatek,mt6358", + .data = &pmic_mt6358, + }, { /* The MT6380 PMIC only implements a regulator, so we bind it * directly instead of using a MFD. */ @@ -1440,9 +1669,6 @@ static const struct of_device_id of_slave_match_tbl[] = { .compatible = "mediatek,mt6397", .data = &pmic_mt6397, }, { - .compatible = "mediatek,mt6351", - .data = &pmic_mt6351, - }, { /* sentinel */ } }; @@ -1453,21 +1679,35 @@ static const struct pmic_wrapper_type pwrap_mt2701 = { .type = PWRAP_MT2701, .arb_en_all = 0x3f, .int_en_all = ~(u32)(BIT(31) | BIT(2)), + .int1_en_all = 0, .spi_w = PWRAP_MAN_CMD_SPI_WRITE_NEW, .wdt_src = PWRAP_WDT_SRC_MASK_ALL, - .has_bridge = 0, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, .init_reg_clock = pwrap_mt2701_init_reg_clock, .init_soc_specific = pwrap_mt2701_init_soc_specific, }; +static const struct pmic_wrapper_type pwrap_mt6765 = { + .regs = mt6765_regs, + .type = PWRAP_MT6765, + .arb_en_all = 0x3fd35, + .int_en_all = 0xffffffff, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = NULL, +}; + static const struct pmic_wrapper_type pwrap_mt6797 = { .regs = mt6797_regs, .type = PWRAP_MT6797, .arb_en_all = 0x01fff, .int_en_all = 0xffffffc6, + .int1_en_all = 0, .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .wdt_src = PWRAP_WDT_SRC_MASK_ALL, - .has_bridge = 0, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, .init_reg_clock = pwrap_common_init_reg_clock, .init_soc_specific = NULL, }; @@ -1477,9 +1717,10 @@ static const struct pmic_wrapper_type pwrap_mt7622 = { .type = PWRAP_MT7622, .arb_en_all = 0xff, .int_en_all = ~(u32)BIT(31), + .int1_en_all = 0, .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .wdt_src = PWRAP_WDT_SRC_MASK_ALL, - .has_bridge = 0, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, .init_reg_clock = pwrap_common_init_reg_clock, .init_soc_specific = pwrap_mt7622_init_soc_specific, }; @@ -1489,9 +1730,10 @@ static const struct pmic_wrapper_type pwrap_mt8135 = { .type = PWRAP_MT8135, .arb_en_all = 0x1ff, .int_en_all = ~(u32)(BIT(31) | BIT(1)), + .int1_en_all = 0, .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .wdt_src = PWRAP_WDT_SRC_MASK_ALL, - .has_bridge = 1, + .caps = PWRAP_CAP_BRIDGE | PWRAP_CAP_RESET | PWRAP_CAP_DCM, .init_reg_clock = pwrap_common_init_reg_clock, .init_soc_specific = pwrap_mt8135_init_soc_specific, }; @@ -1501,18 +1743,35 @@ static const struct pmic_wrapper_type pwrap_mt8173 = { .type = PWRAP_MT8173, .arb_en_all = 0x3f, .int_en_all = ~(u32)(BIT(31) | BIT(1)), + .int1_en_all = 0, .spi_w = PWRAP_MAN_CMD_SPI_WRITE, .wdt_src = PWRAP_WDT_SRC_MASK_NO_STAUPD, - .has_bridge = 0, + .caps = PWRAP_CAP_RESET | PWRAP_CAP_DCM, .init_reg_clock = pwrap_common_init_reg_clock, .init_soc_specific = pwrap_mt8173_init_soc_specific, }; +static const struct pmic_wrapper_type pwrap_mt8183 = { + .regs = mt8183_regs, + .type = PWRAP_MT8183, + .arb_en_all = 0x3fa75, + .int_en_all = 0xffffffff, + .int1_en_all = 0xeef7ffff, + .spi_w = PWRAP_MAN_CMD_SPI_WRITE, + .wdt_src = PWRAP_WDT_SRC_MASK_ALL, + .caps = PWRAP_CAP_INT1_EN | PWRAP_CAP_WDT_SRC1, + .init_reg_clock = pwrap_common_init_reg_clock, + .init_soc_specific = pwrap_mt8183_init_soc_specific, +}; + static const struct of_device_id of_pwrap_match_tbl[] = { { .compatible = "mediatek,mt2701-pwrap", .data = &pwrap_mt2701, }, { + .compatible = "mediatek,mt6765-pwrap", + .data = &pwrap_mt6765, + }, { .compatible = "mediatek,mt6797-pwrap", .data = &pwrap_mt6797, }, { @@ -1525,6 +1784,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = { .compatible = "mediatek,mt8173-pwrap", .data = &pwrap_mt8173, }, { + .compatible = "mediatek,mt8183-pwrap", + .data = &pwrap_mt8183, + }, { /* sentinel */ } }; @@ -1561,14 +1823,16 @@ static int pwrap_probe(struct platform_device *pdev) if (IS_ERR(wrp->base)) return PTR_ERR(wrp->base); - wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); - if (IS_ERR(wrp->rstc)) { - ret = PTR_ERR(wrp->rstc); - dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); - return ret; + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_RESET)) { + wrp->rstc = devm_reset_control_get(wrp->dev, "pwrap"); + if (IS_ERR(wrp->rstc)) { + ret = PTR_ERR(wrp->rstc); + dev_dbg(wrp->dev, "cannot get pwrap reset: %d\n", ret); + return ret; + } } - if (wrp->master->has_bridge) { + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_BRIDGE)) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pwrap-bridge"); wrp->bridge_base = devm_ioremap_resource(wrp->dev, res); @@ -1608,8 +1872,10 @@ static int pwrap_probe(struct platform_device *pdev) goto err_out1; /* Enable internal dynamic clock */ - pwrap_writel(wrp, 1, PWRAP_DCM_EN); - pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_DCM)) { + pwrap_writel(wrp, 1, PWRAP_DCM_EN); + pwrap_writel(wrp, 0, PWRAP_DCM_DBC_PRD); + } /* * The PMIC could already be initialized by the bootloader. @@ -1636,8 +1902,17 @@ static int pwrap_probe(struct platform_device *pdev) * so STAUPD of WDT_SRC which should be turned off */ pwrap_writel(wrp, wrp->master->wdt_src, PWRAP_WDT_SRC_EN); + 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); pwrap_writel(wrp, wrp->master->int_en_all, PWRAP_INT_EN); + /* + * We add INT1 interrupt to handle starvation and request exception + * If we support it, we should enable it here. + */ + if (HAS_CAP(wrp->master->caps, PWRAP_CAP_INT1_EN)) + pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN); irq = platform_get_irq(pdev, 0); ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index ba79b609aca2..684cb51694d1 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -33,7 +33,7 @@ config QCOM_GLINK_SSR config QCOM_GSBI tristate "QCOM General Serial Bus Interface" - depends on ARCH_QCOM + depends on ARCH_QCOM || COMPILE_TEST select MFD_SYSCON help Say y here to enable GSBI support. The GSBI provides control @@ -42,7 +42,7 @@ config QCOM_GSBI config QCOM_LLCC tristate "Qualcomm Technologies, Inc. LLCC driver" - depends on ARCH_QCOM + depends on ARCH_QCOM || COMPILE_TEST help Qualcomm Technologies, Inc. platform specific Last Level Cache Controller(LLCC) driver. This provides interfaces @@ -73,7 +73,8 @@ config QCOM_PM config QCOM_QMI_HELPERS tristate - depends on ARCH_QCOM && NET + depends on ARCH_QCOM || COMPILE_TEST + depends on NET help Helper library for handling QMI encoded messages. QMI encoded messages are used in communication between the majority of QRTR @@ -94,7 +95,7 @@ config QCOM_RMTFS_MEM config QCOM_RPMH bool "Qualcomm RPM-Hardened (RPMH) Communication" - depends on ARCH_QCOM && ARM64 && OF || COMPILE_TEST + depends on ARCH_QCOM && ARM64 || COMPILE_TEST help Support for communication with the hardened-RPM blocks in Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an @@ -104,7 +105,7 @@ config QCOM_RPMH config QCOM_SMEM tristate "Qualcomm Shared Memory Manager (SMEM)" - depends on ARCH_QCOM + depends on ARCH_QCOM || COMPILE_TEST depends on HWSPINLOCK help Say y here to enable support for the Qualcomm Shared Memory Manager. @@ -113,8 +114,8 @@ config QCOM_SMEM config QCOM_SMD_RPM tristate "Qualcomm Resource Power Manager (RPM) over SMD" - depends on ARCH_QCOM - depends on RPMSG && OF + depends on ARCH_QCOM || COMPILE_TEST + depends on RPMSG help If you say yes to this option, support will be included for the Resource Power Manager system found in the Qualcomm 8974 based @@ -134,6 +135,7 @@ config QCOM_SMP2P depends on MAILBOX depends on QCOM_SMEM select QCOM_SMEM_STATE + select IRQ_DOMAIN help Say yes here to support the Qualcomm Shared Memory Point to Point protocol. @@ -142,13 +144,14 @@ config QCOM_SMSM tristate "Qualcomm Shared Memory State Machine" depends on QCOM_SMEM select QCOM_SMEM_STATE + select IRQ_DOMAIN help Say yes here to support the Qualcomm Shared Memory State Machine. The state machine is represented by bits in shared memory. config QCOM_WCNSS_CTRL tristate "Qualcomm WCNSS control driver" - depends on ARCH_QCOM + depends on ARCH_QCOM || COMPILE_TEST depends on RPMSG help Client driver for the WCNSS_CTRL SMD channel, used to download nv @@ -156,7 +159,7 @@ config QCOM_WCNSS_CTRL config QCOM_APR tristate "Qualcomm APR Bus (Asynchronous Packet Router)" - depends on ARCH_QCOM + depends on ARCH_QCOM || COMPILE_TEST depends on RPMSG help Enable APR IPC protocol support between diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c index 57af8a537332..716762d59c1f 100644 --- a/drivers/soc/qcom/apr.c +++ b/drivers/soc/qcom/apr.c @@ -87,7 +87,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, } if (hdr->pkt_size < APR_HDR_SIZE || hdr->pkt_size != len) { - dev_err(apr->dev, "APR: Wrong paket size\n"); + dev_err(apr->dev, "APR: Wrong packet size\n"); return -EINVAL; } @@ -219,9 +219,9 @@ static int apr_add_device(struct device *dev, struct device_node *np, adev->domain_id = id->domain_id; adev->version = id->svc_version; if (np) - strncpy(adev->name, np->name, APR_NAME_SIZE); + strscpy(adev->name, np->name, APR_NAME_SIZE); else - strncpy(adev->name, id->name, APR_NAME_SIZE); + strscpy(adev->name, id->name, APR_NAME_SIZE); dev_set_name(&adev->dev, "aprsvc:%s:%x:%x", adev->name, id->domain_id, id->svc_id); diff --git a/drivers/soc/qcom/llcc-slice.c b/drivers/soc/qcom/llcc-slice.c index 54063a31132f..192ca761b2cb 100644 --- a/drivers/soc/qcom/llcc-slice.c +++ b/drivers/soc/qcom/llcc-slice.c @@ -13,6 +13,7 @@ #include <linux/mutex.h> #include <linux/of_device.h> #include <linux/regmap.h> +#include <linux/sizes.h> #include <linux/slab.h> #include <linux/soc/qcom/llcc-qcom.h> @@ -106,22 +107,24 @@ static int llcc_update_act_ctrl(u32 sid, u32 slice_status; int ret; - act_ctrl_reg = drv_data->bcast_off + LLCC_TRP_ACT_CTRLn(sid); - status_reg = drv_data->bcast_off + LLCC_TRP_STATUSn(sid); + act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); + status_reg = LLCC_TRP_STATUSn(sid); /* Set the ACTIVE trigger */ act_ctrl_reg_val |= ACT_CTRL_ACT_TRIG; - ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); + ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg, + act_ctrl_reg_val); if (ret) return ret; /* Clear the ACTIVE trigger */ act_ctrl_reg_val &= ~ACT_CTRL_ACT_TRIG; - ret = regmap_write(drv_data->regmap, act_ctrl_reg, act_ctrl_reg_val); + ret = regmap_write(drv_data->bcast_regmap, act_ctrl_reg, + act_ctrl_reg_val); if (ret) return ret; - ret = regmap_read_poll_timeout(drv_data->regmap, status_reg, + ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg, slice_status, !(slice_status & status), 0, LLCC_STATUS_READ_DELAY); return ret; @@ -223,19 +226,16 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev) u32 attr0_val; u32 max_cap_cacheline; u32 sz; - int ret; + int ret = 0; const struct llcc_slice_config *llcc_table; struct llcc_slice_desc desc; - u32 bcast_off = drv_data->bcast_off; sz = drv_data->cfg_size; llcc_table = drv_data->cfg; for (i = 0; i < sz; i++) { - attr1_cfg = bcast_off + - LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); - attr0_cfg = bcast_off + - LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id); + attr1_cfg = LLCC_TRP_ATTR1_CFGn(llcc_table[i].slice_id); + attr0_cfg = LLCC_TRP_ATTR0_CFGn(llcc_table[i].slice_id); attr1_val = llcc_table[i].cache_mode; attr1_val |= llcc_table[i].probe_target_ways << @@ -260,10 +260,12 @@ static int qcom_llcc_cfg_program(struct platform_device *pdev) attr0_val = llcc_table[i].res_ways & ATTR0_RES_WAYS_MASK; attr0_val |= llcc_table[i].bonus_ways << ATTR0_BONUS_WAYS_SHIFT; - ret = regmap_write(drv_data->regmap, attr1_cfg, attr1_val); + ret = regmap_write(drv_data->bcast_regmap, attr1_cfg, + attr1_val); if (ret) return ret; - ret = regmap_write(drv_data->regmap, attr0_cfg, attr0_val); + ret = regmap_write(drv_data->bcast_regmap, attr0_cfg, + attr0_val); if (ret) return ret; if (llcc_table[i].activate_on_init) { @@ -279,24 +281,37 @@ int qcom_llcc_probe(struct platform_device *pdev, { u32 num_banks; struct device *dev = &pdev->dev; - struct resource *res; - void __iomem *base; + struct resource *llcc_banks_res, *llcc_bcast_res; + void __iomem *llcc_banks_base, *llcc_bcast_base; int ret, i; + struct platform_device *llcc_edac; drv_data = devm_kzalloc(dev, sizeof(*drv_data), GFP_KERNEL); if (!drv_data) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); + llcc_banks_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "llcc_base"); + llcc_banks_base = devm_ioremap_resource(&pdev->dev, llcc_banks_res); + if (IS_ERR(llcc_banks_base)) + return PTR_ERR(llcc_banks_base); - drv_data->regmap = devm_regmap_init_mmio(dev, base, - &llcc_regmap_config); + drv_data->regmap = devm_regmap_init_mmio(dev, llcc_banks_base, + &llcc_regmap_config); if (IS_ERR(drv_data->regmap)) return PTR_ERR(drv_data->regmap); + llcc_bcast_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "llcc_broadcast_base"); + llcc_bcast_base = devm_ioremap_resource(&pdev->dev, llcc_bcast_res); + if (IS_ERR(llcc_bcast_base)) + return PTR_ERR(llcc_bcast_base); + + drv_data->bcast_regmap = devm_regmap_init_mmio(dev, llcc_bcast_base, + &llcc_regmap_config); + if (IS_ERR(drv_data->bcast_regmap)) + return PTR_ERR(drv_data->bcast_regmap); + ret = regmap_read(drv_data->regmap, LLCC_COMMON_STATUS0, &num_banks); if (ret) @@ -318,8 +333,6 @@ int qcom_llcc_probe(struct platform_device *pdev, for (i = 0; i < num_banks; i++) drv_data->offsets[i] = i * BANK_OFFSET_STRIDE; - drv_data->bcast_off = num_banks * BANK_OFFSET_STRIDE; - drv_data->bitmap = devm_kcalloc(dev, BITS_TO_LONGS(drv_data->max_slices), sizeof(unsigned long), GFP_KERNEL); @@ -331,7 +344,20 @@ int qcom_llcc_probe(struct platform_device *pdev, mutex_init(&drv_data->lock); platform_set_drvdata(pdev, drv_data); - return qcom_llcc_cfg_program(pdev); + ret = qcom_llcc_cfg_program(pdev); + if (ret) + return ret; + + drv_data->ecc_irq = platform_get_irq(pdev, 0); + if (drv_data->ecc_irq >= 0) { + llcc_edac = platform_device_register_data(&pdev->dev, + "qcom_llcc_edac", -1, drv_data, + sizeof(*drv_data)); + if (IS_ERR(llcc_edac)) + dev_err(dev, "Failed to register llcc edac driver\n"); + } + + return ret; } EXPORT_SYMBOL_GPL(qcom_llcc_probe); diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index feed3db21c10..ee89ffb6dde8 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -513,7 +513,7 @@ EXPORT_SYMBOL(geni_se_resources_on); */ int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl) { - unsigned long freq = 0; + long freq = 0; int i; if (se->clk_perf_tbl) { @@ -529,7 +529,7 @@ int geni_se_clk_tbl_get(struct geni_se *se, unsigned long **tbl) for (i = 0; i < MAX_CLK_PERF_LEVEL; i++) { freq = clk_round_rate(se->clk, freq + 1); - if (!freq || freq == se->clk_perf_tbl[i - 1]) + if (freq <= 0 || freq == se->clk_perf_tbl[i - 1]) break; se->clk_perf_tbl[i] = freq; } @@ -544,16 +544,17 @@ EXPORT_SYMBOL(geni_se_clk_tbl_get); * @se: Pointer to the concerned serial engine. * @req_freq: Requested clock frequency. * @index: Index of the resultant frequency in the table. - * @res_freq: Resultant frequency which matches or is closer to the - * requested frequency. + * @res_freq: Resultant frequency of the source clock. * @exact: Flag to indicate exact multiple requirement of the requested * frequency. * - * This function is called by the protocol drivers to determine the matching - * or exact multiple of the requested frequency, as provided by the serial - * engine clock in order to meet the performance requirements. If there is - * no matching or exact multiple of the requested frequency found, then it - * selects the closest floor frequency, if exact flag is not set. + * This function is called by the protocol drivers to determine the best match + * of the requested frequency as provided by the serial engine clock in order + * to meet the performance requirements. + * + * If we return success: + * - if @exact is true then @res_freq / <an_integer> == @req_freq + * - if @exact is false then @res_freq / <an_integer> <= @req_freq * * Return: 0 on success, standard Linux error codes on failure. */ @@ -564,6 +565,9 @@ int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq, unsigned long *tbl; int num_clk_levels; int i; + unsigned long best_delta; + unsigned long new_delta; + unsigned int divider; num_clk_levels = geni_se_clk_tbl_get(se, &tbl); if (num_clk_levels < 0) @@ -572,18 +576,21 @@ int geni_se_clk_freq_match(struct geni_se *se, unsigned long req_freq, if (num_clk_levels == 0) return -EINVAL; - *res_freq = 0; + best_delta = ULONG_MAX; for (i = 0; i < num_clk_levels; i++) { - if (!(tbl[i] % req_freq)) { + divider = DIV_ROUND_UP(tbl[i], req_freq); + new_delta = req_freq - tbl[i] / divider; + if (new_delta < best_delta) { + /* We have a new best! */ *index = i; *res_freq = tbl[i]; - return 0; - } - if (!(*res_freq) || ((tbl[i] > *res_freq) && - (tbl[i] < req_freq))) { - *index = i; - *res_freq = tbl[i]; + /* If the new best is exact then we're done */ + if (new_delta == 0) + return 0; + + /* Record how close we got */ + best_delta = new_delta; } } diff --git a/drivers/soc/qcom/rmtfs_mem.c b/drivers/soc/qcom/rmtfs_mem.c index 8a3678c2e83c..97bb5989aa21 100644 --- a/drivers/soc/qcom/rmtfs_mem.c +++ b/drivers/soc/qcom/rmtfs_mem.c @@ -212,6 +212,11 @@ static int qcom_rmtfs_mem_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to parse qcom,vmid\n"); goto remove_cdev; } else if (!ret) { + if (!qcom_scm_is_available()) { + ret = -EPROBE_DEFER; + goto remove_cdev; + } + perms[0].vmid = QCOM_SCM_VMID_HLOS; perms[0].perm = QCOM_SCM_PERM_RW; perms[1].vmid = vmid; diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index ee75da66d64b..75bd9a83aef0 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -121,6 +121,7 @@ static int tcs_invalidate(struct rsc_drv *drv, int type) return -EAGAIN; } write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); + write_tcs_reg_sync(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, m, 0); } bitmap_zero(tcs->slots, MAX_TCS_SLOTS); spin_unlock(&tcs->lock); @@ -239,6 +240,7 @@ static irqreturn_t tcs_tx_done(int irq, void *p) skip: /* Reclaim the TCS */ write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); + write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, i, 0); write_tcs_reg(drv, RSC_DRV_IRQ_CLEAR, 0, BIT(i)); spin_lock(&drv->lock); clear_bit(i, drv->tcs_in_use); diff --git a/drivers/soc/qcom/smem.c b/drivers/soc/qcom/smem.c index bf4bd71ab53f..f80d040601fd 100644 --- a/drivers/soc/qcom/smem.c +++ b/drivers/soc/qcom/smem.c @@ -18,6 +18,7 @@ #include <linux/of.h> #include <linux/of_address.h> #include <linux/platform_device.h> +#include <linux/sizes.h> #include <linux/slab.h> #include <linux/soc/qcom/smem.h> @@ -277,7 +278,7 @@ struct qcom_smem { u32 item_count; unsigned num_regions; - struct smem_region regions[0]; + struct smem_region regions[]; }; static void * @@ -489,7 +490,7 @@ static void *qcom_smem_get_global(struct qcom_smem *smem, size_t *size) { struct smem_header *header; - struct smem_region *area; + struct smem_region *region; struct smem_global_entry *entry; u32 aux_base; unsigned i; @@ -502,12 +503,12 @@ static void *qcom_smem_get_global(struct qcom_smem *smem, aux_base = le32_to_cpu(entry->aux_base) & AUX_BASE_MASK; for (i = 0; i < smem->num_regions; i++) { - area = &smem->regions[i]; + region = &smem->regions[i]; - if (area->aux_base == aux_base || !aux_base) { + if (region->aux_base == aux_base || !aux_base) { if (size != NULL) *size = le32_to_cpu(entry->size); - return area->virt_base + le32_to_cpu(entry->offset); + return region->virt_base + le32_to_cpu(entry->offset); } } @@ -722,12 +723,59 @@ static u32 qcom_smem_get_item_count(struct qcom_smem *smem) return le16_to_cpu(info->num_items); } +/* + * Validate the partition header for a partition whose partition + * table entry is supplied. Returns a pointer to its header if + * valid, or a null pointer otherwise. + */ +static struct smem_partition_header * +qcom_smem_partition_header(struct qcom_smem *smem, + struct smem_ptable_entry *entry, u16 host0, u16 host1) +{ + struct smem_partition_header *header; + u32 size; + + header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); + + if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { + dev_err(smem->dev, "bad partition magic %02x %02x %02x %02x\n", + header->magic[0], header->magic[1], + header->magic[2], header->magic[3]); + return NULL; + } + + if (host0 != le16_to_cpu(header->host0)) { + dev_err(smem->dev, "bad host0 (%hu != %hu)\n", + host0, le16_to_cpu(header->host0)); + return NULL; + } + if (host1 != le16_to_cpu(header->host1)) { + dev_err(smem->dev, "bad host1 (%hu != %hu)\n", + host1, le16_to_cpu(header->host1)); + return NULL; + } + + size = le32_to_cpu(header->size); + if (size != le32_to_cpu(entry->size)) { + dev_err(smem->dev, "bad partition size (%u != %u)\n", + size, le32_to_cpu(entry->size)); + return NULL; + } + + if (le32_to_cpu(header->offset_free_uncached) > size) { + dev_err(smem->dev, "bad partition free uncached (%u > %u)\n", + le32_to_cpu(header->offset_free_uncached), size); + return NULL; + } + + return header; +} + static int qcom_smem_set_global_partition(struct qcom_smem *smem) { struct smem_partition_header *header; struct smem_ptable_entry *entry; struct smem_ptable *ptable; - u32 host0, host1, size; bool found = false; int i; @@ -742,10 +790,15 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem) for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { entry = &ptable->entry[i]; - host0 = le16_to_cpu(entry->host0); - host1 = le16_to_cpu(entry->host1); + if (!le32_to_cpu(entry->offset)) + continue; + if (!le32_to_cpu(entry->size)) + continue; + + if (le16_to_cpu(entry->host0) != SMEM_GLOBAL_HOST) + continue; - if (host0 == SMEM_GLOBAL_HOST && host0 == host1) { + if (le16_to_cpu(entry->host1) == SMEM_GLOBAL_HOST) { found = true; break; } @@ -756,36 +809,10 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem) return -EINVAL; } - if (!le32_to_cpu(entry->offset) || !le32_to_cpu(entry->size)) { - dev_err(smem->dev, "Invalid entry for global partition\n"); + header = qcom_smem_partition_header(smem, entry, + SMEM_GLOBAL_HOST, SMEM_GLOBAL_HOST); + if (!header) return -EINVAL; - } - - header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); - host0 = le16_to_cpu(header->host0); - host1 = le16_to_cpu(header->host1); - - if (memcmp(header->magic, SMEM_PART_MAGIC, sizeof(header->magic))) { - dev_err(smem->dev, "Global partition has invalid magic\n"); - return -EINVAL; - } - - if (host0 != SMEM_GLOBAL_HOST && host1 != SMEM_GLOBAL_HOST) { - dev_err(smem->dev, "Global partition hosts are invalid\n"); - return -EINVAL; - } - - if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { - dev_err(smem->dev, "Global partition has invalid size\n"); - return -EINVAL; - } - - size = le32_to_cpu(header->offset_free_uncached); - if (size > le32_to_cpu(header->size)) { - dev_err(smem->dev, - "Global partition has invalid free pointer\n"); - return -EINVAL; - } smem->global_partition = header; smem->global_cacheline = le32_to_cpu(entry->cacheline); @@ -793,14 +820,14 @@ static int qcom_smem_set_global_partition(struct qcom_smem *smem) return 0; } -static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, - unsigned int local_host) +static int +qcom_smem_enumerate_partitions(struct qcom_smem *smem, u16 local_host) { struct smem_partition_header *header; struct smem_ptable_entry *entry; struct smem_ptable *ptable; unsigned int remote_host; - u32 host0, host1; + u16 host0, host1; int i; ptable = qcom_smem_get_ptable(smem); @@ -809,71 +836,33 @@ static int qcom_smem_enumerate_partitions(struct qcom_smem *smem, for (i = 0; i < le32_to_cpu(ptable->num_entries); i++) { entry = &ptable->entry[i]; - host0 = le16_to_cpu(entry->host0); - host1 = le16_to_cpu(entry->host1); - - if (host0 != local_host && host1 != local_host) - continue; - if (!le32_to_cpu(entry->offset)) continue; - if (!le32_to_cpu(entry->size)) continue; + host0 = le16_to_cpu(entry->host0); + host1 = le16_to_cpu(entry->host1); if (host0 == local_host) remote_host = host1; - else + else if (host1 == local_host) remote_host = host0; + else + continue; if (remote_host >= SMEM_HOST_COUNT) { - dev_err(smem->dev, - "Invalid remote host %d\n", - remote_host); + dev_err(smem->dev, "bad host %hu\n", remote_host); return -EINVAL; } if (smem->partitions[remote_host]) { - dev_err(smem->dev, - "Already found a partition for host %d\n", - remote_host); - return -EINVAL; - } - - header = smem->regions[0].virt_base + le32_to_cpu(entry->offset); - host0 = le16_to_cpu(header->host0); - host1 = le16_to_cpu(header->host1); - - if (memcmp(header->magic, SMEM_PART_MAGIC, - sizeof(header->magic))) { - dev_err(smem->dev, - "Partition %d has invalid magic\n", i); + dev_err(smem->dev, "duplicate host %hu\n", remote_host); return -EINVAL; } - if (host0 != local_host && host1 != local_host) { - dev_err(smem->dev, - "Partition %d hosts are invalid\n", i); + header = qcom_smem_partition_header(smem, entry, host0, host1); + if (!header) return -EINVAL; - } - - if (host0 != remote_host && host1 != remote_host) { - dev_err(smem->dev, - "Partition %d hosts are invalid\n", i); - return -EINVAL; - } - - if (le32_to_cpu(header->size) != le32_to_cpu(entry->size)) { - dev_err(smem->dev, - "Partition %d has invalid size\n", i); - return -EINVAL; - } - - if (le32_to_cpu(header->offset_free_uncached) > le32_to_cpu(header->size)) { - dev_err(smem->dev, - "Partition %d has invalid free pointer\n", i); - return -EINVAL; - } smem->partitions[remote_host] = header; smem->cacheline[remote_host] = le32_to_cpu(entry->cacheline); @@ -887,6 +876,7 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev, { struct device_node *np; struct resource r; + resource_size_t size; int ret; np = of_parse_phandle(dev->of_node, name, 0); @@ -899,12 +889,13 @@ static int qcom_smem_map_memory(struct qcom_smem *smem, struct device *dev, of_node_put(np); if (ret) return ret; + size = resource_size(&r); - smem->regions[i].aux_base = (u32)r.start; - smem->regions[i].size = resource_size(&r); - smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, resource_size(&r)); + smem->regions[i].virt_base = devm_ioremap_wc(dev, r.start, size); if (!smem->regions[i].virt_base) return -ENOMEM; + smem->regions[i].aux_base = (u32)r.start; + smem->regions[i].size = size; return 0; } @@ -962,6 +953,7 @@ static int qcom_smem_probe(struct platform_device *pdev) return -EINVAL; } + BUILD_BUG_ON(SMEM_HOST_APPS >= SMEM_HOST_COUNT); ret = qcom_smem_enumerate_partitions(smem, SMEM_HOST_APPS); if (ret < 0 && ret != -ENOENT) return ret; diff --git a/drivers/soc/qcom/spm.c b/drivers/soc/qcom/spm.c index f9d7a85b2822..53807e839664 100644 --- a/drivers/soc/qcom/spm.c +++ b/drivers/soc/qcom/spm.c @@ -219,6 +219,9 @@ static int __init qcom_cpuidle_init(struct device_node *cpu_node, int cpu) cpumask_t mask; bool use_scm_power_down = false; + if (!qcom_scm_is_available()) + return -EPROBE_DEFER; + for (i = 0; ; i++) { state_node = of_parse_phandle(cpu_node, "cpu-idle-states", i); if (!state_node) diff --git a/drivers/soc/qcom/wcnss_ctrl.c b/drivers/soc/qcom/wcnss_ctrl.c index df3ccb30bc2d..373400dd816d 100644 --- a/drivers/soc/qcom/wcnss_ctrl.c +++ b/drivers/soc/qcom/wcnss_ctrl.c @@ -281,7 +281,7 @@ struct rpmsg_endpoint *qcom_wcnss_open_channel(void *wcnss, const char *name, rp struct rpmsg_channel_info chinfo; struct wcnss_ctrl *_wcnss = wcnss; - strncpy(chinfo.name, name, sizeof(chinfo.name)); + strscpy(chinfo.name, name, sizeof(chinfo.name)); chinfo.src = RPMSG_ADDR_ANY; chinfo.dst = RPMSG_ADDR_ANY; diff --git a/drivers/soc/renesas/Kconfig b/drivers/soc/renesas/Kconfig index 1d824cbd462d..407f02c80e8b 100644 --- a/drivers/soc/renesas/Kconfig +++ b/drivers/soc/renesas/Kconfig @@ -1,14 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 config SOC_RENESAS bool "Renesas SoC driver support" if COMPILE_TEST && !ARCH_RENESAS default y if ARCH_RENESAS select SOC_BUS select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \ - ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77965 || \ - ARCH_R8A77970 || ARCH_R8A77980 || ARCH_R8A77990 || \ - ARCH_R8A77995 - select SYSC_R8A7743 if ARCH_R8A7743 + ARCH_R8A774A1 || ARCH_R8A774C0 || ARCH_R8A7795 || \ + ARCH_R8A7796 || ARCH_R8A77965 || ARCH_R8A77970 || \ + ARCH_R8A77980 || ARCH_R8A77990 || ARCH_R8A77995 + select SYSC_R8A7743 if ARCH_R8A7743 || ARCH_R8A7744 select SYSC_R8A7745 if ARCH_R8A7745 select SYSC_R8A77470 if ARCH_R8A77470 + select SYSC_R8A774A1 if ARCH_R8A774A1 + select SYSC_R8A774C0 if ARCH_R8A774C0 select SYSC_R8A7779 if ARCH_R8A7779 select SYSC_R8A7790 if ARCH_R8A7790 select SYSC_R8A7791 if ARCH_R8A7791 || ARCH_R8A7793 @@ -37,6 +40,14 @@ config SYSC_R8A77470 bool "RZ/G1C System Controller support" if COMPILE_TEST select SYSC_RCAR +config SYSC_R8A774A1 + bool "RZ/G2M System Controller support" if COMPILE_TEST + select SYSC_RCAR + +config SYSC_R8A774C0 + bool "RZ/G2E System Controller support" if COMPILE_TEST + select SYSC_RCAR + config SYSC_R8A7779 bool "R-Car H1 System Controller support" if COMPILE_TEST select SYSC_RCAR diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile index c37b0803c1b6..3bdd7dbc38a9 100644 --- a/drivers/soc/renesas/Makefile +++ b/drivers/soc/renesas/Makefile @@ -6,6 +6,8 @@ obj-$(CONFIG_SOC_RENESAS) += renesas-soc.o obj-$(CONFIG_SYSC_R8A7743) += r8a7743-sysc.o obj-$(CONFIG_SYSC_R8A7745) += r8a7745-sysc.o obj-$(CONFIG_SYSC_R8A77470) += r8a77470-sysc.o +obj-$(CONFIG_SYSC_R8A774A1) += r8a774a1-sysc.o +obj-$(CONFIG_SYSC_R8A774C0) += r8a774c0-sysc.o obj-$(CONFIG_SYSC_R8A7779) += r8a7779-sysc.o obj-$(CONFIG_SYSC_R8A7790) += r8a7790-sysc.o obj-$(CONFIG_SYSC_R8A7791) += r8a7791-sysc.o diff --git a/drivers/soc/renesas/r8a7743-sysc.c b/drivers/soc/renesas/r8a7743-sysc.c index 9583a327d90c..edf6436e879f 100644 --- a/drivers/soc/renesas/r8a7743-sysc.c +++ b/drivers/soc/renesas/r8a7743-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas RZ/G1M System Controller * * Copyright (C) 2016 Cogent Embedded Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7745-sysc.c b/drivers/soc/renesas/r8a7745-sysc.c index d17887c08aa1..65dc6b09cc85 100644 --- a/drivers/soc/renesas/r8a7745-sysc.c +++ b/drivers/soc/renesas/r8a7745-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas RZ/G1E System Controller * * Copyright (C) 2016 Cogent Embedded Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation; of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a774a1-sysc.c b/drivers/soc/renesas/r8a774a1-sysc.c new file mode 100644 index 000000000000..9db51ff6f5ed --- /dev/null +++ b/drivers/soc/renesas/r8a774a1-sysc.c @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G2M System Controller + * Copyright (C) 2018 Renesas Electronics Corp. + * + * Based on Renesas R-Car M3-W System Controller + * Copyright (C) 2016 Glider bvba + */ + +#include <linux/bug.h> +#include <linux/kernel.h> + +#include <dt-bindings/power/r8a774a1-sysc.h> + +#include "rcar-sysc.h" + +static const struct rcar_sysc_area r8a774a1_areas[] __initconst = { + { "always-on", 0, 0, R8A774A1_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca57-scu", 0x1c0, 0, R8A774A1_PD_CA57_SCU, R8A774A1_PD_ALWAYS_ON, + PD_SCU }, + { "ca57-cpu0", 0x80, 0, R8A774A1_PD_CA57_CPU0, R8A774A1_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca57-cpu1", 0x80, 1, R8A774A1_PD_CA57_CPU1, R8A774A1_PD_CA57_SCU, + PD_CPU_NOCR }, + { "ca53-scu", 0x140, 0, R8A774A1_PD_CA53_SCU, R8A774A1_PD_ALWAYS_ON, + PD_SCU }, + { "ca53-cpu0", 0x200, 0, R8A774A1_PD_CA53_CPU0, R8A774A1_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu1", 0x200, 1, R8A774A1_PD_CA53_CPU1, R8A774A1_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu2", 0x200, 2, R8A774A1_PD_CA53_CPU2, R8A774A1_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu3", 0x200, 3, R8A774A1_PD_CA53_CPU3, R8A774A1_PD_CA53_SCU, + PD_CPU_NOCR }, + { "a3vc", 0x380, 0, R8A774A1_PD_A3VC, R8A774A1_PD_ALWAYS_ON }, + { "a2vc0", 0x3c0, 0, R8A774A1_PD_A2VC0, R8A774A1_PD_A3VC }, + { "a2vc1", 0x3c0, 1, R8A774A1_PD_A2VC1, R8A774A1_PD_A3VC }, + { "3dg-a", 0x100, 0, R8A774A1_PD_3DG_A, R8A774A1_PD_ALWAYS_ON }, + { "3dg-b", 0x100, 1, R8A774A1_PD_3DG_B, R8A774A1_PD_3DG_A }, +}; + +const struct rcar_sysc_info r8a774a1_sysc_info __initconst = { + .areas = r8a774a1_areas, + .num_areas = ARRAY_SIZE(r8a774a1_areas), +}; diff --git a/drivers/soc/renesas/r8a774c0-sysc.c b/drivers/soc/renesas/r8a774c0-sysc.c new file mode 100644 index 000000000000..e1ac4c0f6640 --- /dev/null +++ b/drivers/soc/renesas/r8a774c0-sysc.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Renesas RZ/G2E System Controller + * Copyright (C) 2018 Renesas Electronics Corp. + * + * Based on Renesas R-Car E3 System Controller + */ + +#include <linux/bug.h> +#include <linux/kernel.h> +#include <linux/sys_soc.h> + +#include <dt-bindings/power/r8a774c0-sysc.h> + +#include "rcar-sysc.h" + +static struct rcar_sysc_area r8a774c0_areas[] __initdata = { + { "always-on", 0, 0, R8A774C0_PD_ALWAYS_ON, -1, PD_ALWAYS_ON }, + { "ca53-scu", 0x140, 0, R8A774C0_PD_CA53_SCU, R8A774C0_PD_ALWAYS_ON, + PD_SCU }, + { "ca53-cpu0", 0x200, 0, R8A774C0_PD_CA53_CPU0, R8A774C0_PD_CA53_SCU, + PD_CPU_NOCR }, + { "ca53-cpu1", 0x200, 1, R8A774C0_PD_CA53_CPU1, R8A774C0_PD_CA53_SCU, + PD_CPU_NOCR }, + { "a3vc", 0x380, 0, R8A774C0_PD_A3VC, R8A774C0_PD_ALWAYS_ON }, + { "a2vc1", 0x3c0, 1, R8A774C0_PD_A2VC1, R8A774C0_PD_A3VC }, + { "3dg-a", 0x100, 0, R8A774C0_PD_3DG_A, R8A774C0_PD_ALWAYS_ON }, + { "3dg-b", 0x100, 1, R8A774C0_PD_3DG_B, R8A774C0_PD_3DG_A }, +}; + +static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas, + unsigned int num_areas, u8 id, + int new_parent) +{ + unsigned int i; + + for (i = 0; i < num_areas; i++) + if (areas[i].isr_bit == id) { + areas[i].parent = new_parent; + return; + } +} + +/* Fixups for RZ/G2E ES1.0 revision */ +static const struct soc_device_attribute r8a774c0[] __initconst = { + { .soc_id = "r8a774c0", .revision = "ES1.0" }, + { /* sentinel */ } +}; + +static int __init r8a774c0_sysc_init(void) +{ + if (soc_device_match(r8a774c0)) { + rcar_sysc_fix_parent(r8a774c0_areas, + ARRAY_SIZE(r8a774c0_areas), + R8A774C0_PD_3DG_A, R8A774C0_PD_3DG_B); + rcar_sysc_fix_parent(r8a774c0_areas, + ARRAY_SIZE(r8a774c0_areas), + R8A774C0_PD_3DG_B, R8A774C0_PD_ALWAYS_ON); + } + + return 0; +} + +const struct rcar_sysc_info r8a774c0_sysc_info __initconst = { + .init = r8a774c0_sysc_init, + .areas = r8a774c0_areas, + .num_areas = ARRAY_SIZE(r8a774c0_areas), +}; diff --git a/drivers/soc/renesas/r8a7779-sysc.c b/drivers/soc/renesas/r8a7779-sysc.c index 9e8e6b7faa04..517aa40fa6e6 100644 --- a/drivers/soc/renesas/r8a7779-sysc.c +++ b/drivers/soc/renesas/r8a7779-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car H1 System Controller * * Copyright (C) 2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7790-sysc.c b/drivers/soc/renesas/r8a7790-sysc.c index 7a567ad0ff73..9b5a6bb62152 100644 --- a/drivers/soc/renesas/r8a7790-sysc.c +++ b/drivers/soc/renesas/r8a7790-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car H2 System Controller * * Copyright (C) 2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7791-sysc.c b/drivers/soc/renesas/r8a7791-sysc.c index 03b9f41a34e6..acf545cdebfb 100644 --- a/drivers/soc/renesas/r8a7791-sysc.c +++ b/drivers/soc/renesas/r8a7791-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car M2-W/N System Controller * * Copyright (C) 2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7792-sysc.c b/drivers/soc/renesas/r8a7792-sysc.c index ca7467d7b7ec..05b78525cc43 100644 --- a/drivers/soc/renesas/r8a7792-sysc.c +++ b/drivers/soc/renesas/r8a7792-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car V2H (R8A7792) System Controller * * Copyright (C) 2016 Cogent Embedded Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7794-sysc.c b/drivers/soc/renesas/r8a7794-sysc.c index c4da2941e06c..0d42637fa662 100644 --- a/drivers/soc/renesas/r8a7794-sysc.c +++ b/drivers/soc/renesas/r8a7794-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car E2 System Controller * * Copyright (C) 2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7795-sysc.c b/drivers/soc/renesas/r8a7795-sysc.c index 7412666187b3..cda27a67de98 100644 --- a/drivers/soc/renesas/r8a7795-sysc.c +++ b/drivers/soc/renesas/r8a7795-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car H3 System Controller * * Copyright (C) 2016-2017 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a7796-sysc.c b/drivers/soc/renesas/r8a7796-sysc.c index f700c842b9e1..1b06f868b6e8 100644 --- a/drivers/soc/renesas/r8a7796-sysc.c +++ b/drivers/soc/renesas/r8a7796-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car M3-W System Controller * * Copyright (C) 2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a77970-sysc.c b/drivers/soc/renesas/r8a77970-sysc.c index caf894f193ed..35b30d6a8958 100644 --- a/drivers/soc/renesas/r8a77970-sysc.c +++ b/drivers/soc/renesas/r8a77970-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car V3M System Controller * * Copyright (C) 2017 Cogent Embedded Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/r8a77995-sysc.c b/drivers/soc/renesas/r8a77995-sysc.c index 1b2ef415bbe1..6243aaaf60fb 100644 --- a/drivers/soc/renesas/r8a77995-sysc.c +++ b/drivers/soc/renesas/r8a77995-sysc.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas R-Car D3 System Controller * * Copyright (C) 2017 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #include <linux/bug.h> diff --git a/drivers/soc/renesas/rcar-rst.c b/drivers/soc/renesas/rcar-rst.c index d9c1034e70e9..d183c381e8db 100644 --- a/drivers/soc/renesas/rcar-rst.c +++ b/drivers/soc/renesas/rcar-rst.c @@ -1,11 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car Gen1 RESET/WDT, R-Car Gen2, Gen3, and RZ/G RST Driver * * Copyright (C) 2016 Glider bvba - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. */ #include <linux/err.h> @@ -41,10 +38,14 @@ static const struct rst_config rcar_rst_gen3 __initconst = { }; static const struct of_device_id rcar_rst_matches[] __initconst = { - /* RZ/G is handled like R-Car Gen2 */ + /* RZ/G1 is handled like R-Car Gen2 */ { .compatible = "renesas,r8a7743-rst", .data = &rcar_rst_gen2 }, + { .compatible = "renesas,r8a7744-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a7745-rst", .data = &rcar_rst_gen2 }, { .compatible = "renesas,r8a77470-rst", .data = &rcar_rst_gen2 }, + /* RZ/G2 is handled like R-Car Gen3 */ + { .compatible = "renesas,r8a774a1-rst", .data = &rcar_rst_gen3 }, + { .compatible = "renesas,r8a774c0-rst", .data = &rcar_rst_gen3 }, /* R-Car Gen1 */ { .compatible = "renesas,r8a7778-reset-wdt", .data = &rcar_rst_gen1 }, { .compatible = "renesas,r8a7779-reset-wdt", .data = &rcar_rst_gen1 }, diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c index 029188e8be6e..af53363eda03 100644 --- a/drivers/soc/renesas/rcar-sysc.c +++ b/drivers/soc/renesas/rcar-sysc.c @@ -1,12 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 /* * R-Car SYSC Power management support * * Copyright (C) 2014 Magnus Damm * Copyright (C) 2015-2017 Glider bvba - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. */ #include <linux/clk/renesas.h> @@ -268,6 +265,8 @@ finalize: static const struct of_device_id rcar_sysc_matches[] __initconst = { #ifdef CONFIG_SYSC_R8A7743 { .compatible = "renesas,r8a7743-sysc", .data = &r8a7743_sysc_info }, + /* RZ/G1N is identical to RZ/G2M w.r.t. power domains. */ + { .compatible = "renesas,r8a7744-sysc", .data = &r8a7743_sysc_info }, #endif #ifdef CONFIG_SYSC_R8A7745 { .compatible = "renesas,r8a7745-sysc", .data = &r8a7745_sysc_info }, @@ -275,6 +274,12 @@ static const struct of_device_id rcar_sysc_matches[] __initconst = { #ifdef CONFIG_SYSC_R8A77470 { .compatible = "renesas,r8a77470-sysc", .data = &r8a77470_sysc_info }, #endif +#ifdef CONFIG_SYSC_R8A774A1 + { .compatible = "renesas,r8a774a1-sysc", .data = &r8a774a1_sysc_info }, +#endif +#ifdef CONFIG_SYSC_R8A774C0 + { .compatible = "renesas,r8a774c0-sysc", .data = &r8a774c0_sysc_info }, +#endif #ifdef CONFIG_SYSC_R8A7779 { .compatible = "renesas,r8a7779-sysc", .data = &r8a7779_sysc_info }, #endif diff --git a/drivers/soc/renesas/rcar-sysc.h b/drivers/soc/renesas/rcar-sysc.h index a22e7cf25e30..485520a5b295 100644 --- a/drivers/soc/renesas/rcar-sysc.h +++ b/drivers/soc/renesas/rcar-sysc.h @@ -1,11 +1,8 @@ -/* +/* SPDX-License-Identifier: GPL-2.0 + * * Renesas R-Car System Controller * * Copyright (C) 2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. */ #ifndef __SOC_RENESAS_RCAR_SYSC_H__ #define __SOC_RENESAS_RCAR_SYSC_H__ @@ -52,6 +49,8 @@ struct rcar_sysc_info { extern const struct rcar_sysc_info r8a7743_sysc_info; extern const struct rcar_sysc_info r8a7745_sysc_info; extern const struct rcar_sysc_info r8a77470_sysc_info; +extern const struct rcar_sysc_info r8a774a1_sysc_info; +extern const struct rcar_sysc_info r8a774c0_sysc_info; extern const struct rcar_sysc_info r8a7779_sysc_info; extern const struct rcar_sysc_info r8a7790_sysc_info; extern const struct rcar_sysc_info r8a7791_sysc_info; diff --git a/drivers/soc/renesas/renesas-soc.c b/drivers/soc/renesas/renesas-soc.c index d44d0e687ab8..4af96e668a2f 100644 --- a/drivers/soc/renesas/renesas-soc.c +++ b/drivers/soc/renesas/renesas-soc.c @@ -1,16 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Renesas SoC Identification * * Copyright (C) 2014-2016 Glider bvba - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #include <linux/io.h> @@ -46,15 +38,24 @@ static const struct renesas_family fam_rmobile __initconst __maybe_unused = { .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ }; -static const struct renesas_family fam_rza __initconst __maybe_unused = { - .name = "RZ/A", +static const struct renesas_family fam_rza1 __initconst __maybe_unused = { + .name = "RZ/A1", +}; + +static const struct renesas_family fam_rza2 __initconst __maybe_unused = { + .name = "RZ/A2", }; -static const struct renesas_family fam_rzg __initconst __maybe_unused = { - .name = "RZ/G", +static const struct renesas_family fam_rzg1 __initconst __maybe_unused = { + .name = "RZ/G1", .reg = 0xff000044, /* PRR (Product Register) */ }; +static const struct renesas_family fam_rzg2 __initconst __maybe_unused = { + .name = "RZ/G2", + .reg = 0xfff00044, /* PRR (Product Register) */ +}; + static const struct renesas_family fam_shmobile __initconst __maybe_unused = { .name = "SH-Mobile", .reg = 0xe600101c, /* CCCR (Common Chip Code Register) */ @@ -67,7 +68,12 @@ struct renesas_soc { }; static const struct renesas_soc soc_rz_a1h __initconst __maybe_unused = { - .family = &fam_rza, + .family = &fam_rza1, +}; + +static const struct renesas_soc soc_rz_a2m __initconst __maybe_unused = { + .family = &fam_rza2, + .id = 0x3b, }; static const struct renesas_soc soc_rmobile_ape6 __initconst __maybe_unused = { @@ -81,30 +87,40 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = { }; static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = { - .family = &fam_rzg, + .family = &fam_rzg1, .id = 0x45, }; static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = { - .family = &fam_rzg, + .family = &fam_rzg1, .id = 0x47, }; static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = { - .family = &fam_rzg, + .family = &fam_rzg1, .id = 0x4b, }; static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = { - .family = &fam_rzg, + .family = &fam_rzg1, .id = 0x4c, }; static const struct renesas_soc soc_rz_g1c __initconst __maybe_unused = { - .family = &fam_rzg, + .family = &fam_rzg1, .id = 0x53, }; +static const struct renesas_soc soc_rz_g2m __initconst __maybe_unused = { + .family = &fam_rzg2, + .id = 0x52, +}; + +static const struct renesas_soc soc_rz_g2e __initconst __maybe_unused = { + .family = &fam_rzg2, + .id = 0x57, +}; + static const struct renesas_soc soc_rcar_m1a __initconst __maybe_unused = { .family = &fam_rcar_gen1, }; @@ -184,6 +200,9 @@ static const struct of_device_id renesas_socs[] __initconst = { #ifdef CONFIG_ARCH_R7S72100 { .compatible = "renesas,r7s72100", .data = &soc_rz_a1h }, #endif +#ifdef CONFIG_ARCH_R7S9210 + { .compatible = "renesas,r7s9210", .data = &soc_rz_a2m }, +#endif #ifdef CONFIG_ARCH_R8A73A4 { .compatible = "renesas,r8a73a4", .data = &soc_rmobile_ape6 }, #endif @@ -205,6 +224,12 @@ static const struct of_device_id renesas_socs[] __initconst = { #ifdef CONFIG_ARCH_R8A77470 { .compatible = "renesas,r8a77470", .data = &soc_rz_g1c }, #endif +#ifdef CONFIG_ARCH_R8A774A1 + { .compatible = "renesas,r8a774a1", .data = &soc_rz_g2m }, +#endif +#ifdef CONFIG_ARCH_R8A774C0 + { .compatible = "renesas,r8a774c0", .data = &soc_rz_g2e }, +#endif #ifdef CONFIG_ARCH_R8A7778 { .compatible = "renesas,r8a7778", .data = &soc_rcar_m1a }, #endif @@ -262,7 +287,7 @@ static int __init renesas_soc_init(void) void __iomem *chipid = NULL; struct soc_device *soc_dev; struct device_node *np; - unsigned int product; + unsigned int product, eshi = 0, eslo; match = of_match_node(renesas_socs, of_root); if (!match) @@ -271,6 +296,31 @@ static int __init renesas_soc_init(void) soc = match->data; family = soc->family; + np = of_find_compatible_node(NULL, NULL, "renesas,bsid"); + if (np) { + chipid = of_iomap(np, 0); + of_node_put(np); + + if (chipid) { + product = readl(chipid); + iounmap(chipid); + + if (soc->id && ((product >> 16) & 0xff) != soc->id) { + pr_warn("SoC mismatch (product = 0x%x)\n", + product); + return -ENODEV; + } + } + + /* + * TODO: Upper 4 bits of BSID are for chip version, but the + * format is not known at this time so we don't know how to + * specify eshi and eslo + */ + + goto done; + } + /* Try PRR first, then hardcoded fallback */ np = of_find_compatible_node(NULL, NULL, "renesas,prr"); if (np) { @@ -289,8 +339,11 @@ static int __init renesas_soc_init(void) pr_warn("SoC mismatch (product = 0x%x)\n", product); return -ENODEV; } + eshi = ((product >> 4) & 0x0f) + 1; + eslo = product & 0xf; } +done: soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); if (!soc_dev_attr) return -ENOMEM; @@ -302,10 +355,9 @@ static int __init renesas_soc_init(void) soc_dev_attr->family = kstrdup_const(family->name, GFP_KERNEL); soc_dev_attr->soc_id = kstrdup_const(strchr(match->compatible, ',') + 1, GFP_KERNEL); - if (chipid) - soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", - ((product >> 4) & 0x0f) + 1, - product & 0xf); + if (eshi) + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "ES%u.%u", eshi, + eslo); pr_info("Detected Renesas %s %s %s\n", soc_dev_attr->family, soc_dev_attr->soc_id, soc_dev_attr->revision ?: ""); diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index 2d6f3fcf3211..ab719fa90150 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -33,6 +33,9 @@ #include <linux/of_address.h> #include <linux/of_clk.h> #include <linux/of_platform.h> +#include <linux/pinctrl/pinctrl.h> +#include <linux/pinctrl/pinconf.h> +#include <linux/pinctrl/pinconf-generic.h> #include <linux/platform_device.h> #include <linux/pm_domain.h> #include <linux/reboot.h> @@ -45,6 +48,8 @@ #include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> +#include <dt-bindings/pinctrl/pinctrl-tegra-io-pad.h> + #define PMC_CNTRL 0x0 #define PMC_CNTRL_INTR_POLARITY BIT(17) /* inverts INTR polarity */ #define PMC_CNTRL_CPU_PWRREQ_OE BIT(16) /* CPU pwr req enable */ @@ -65,6 +70,8 @@ #define PWRGATE_STATUS 0x38 +#define PMC_IMPL_E_33V_PWR 0x40 + #define PMC_PWR_DET 0x48 #define PMC_SCRATCH0_MODE_RECOVERY BIT(31) @@ -135,6 +142,7 @@ struct tegra_io_pad_soc { enum tegra_io_pad id; unsigned int dpd; unsigned int voltage; + const char *name; }; struct tegra_pmc_regs { @@ -154,10 +162,14 @@ struct tegra_pmc_soc { bool has_tsense_reset; bool has_gpu_clamps; bool needs_mbist_war; + bool has_impl_33v_pwr; const struct tegra_io_pad_soc *io_pads; unsigned int num_io_pads; + const struct pinctrl_pin_desc *pin_descs; + unsigned int num_pin_descs; + const struct tegra_pmc_regs *regs; void (*init)(struct tegra_pmc *pmc); void (*setup_irq_polarity)(struct tegra_pmc *pmc, @@ -216,6 +228,8 @@ struct tegra_pmc { DECLARE_BITMAP(powergates_available, TEGRA_POWERGATE_MAX); struct mutex powergates_lock; + + struct pinctrl_dev *pctl_dev; }; static struct tegra_pmc *pmc = &(struct tegra_pmc) { @@ -919,11 +933,12 @@ tegra_io_pad_find(struct tegra_pmc *pmc, enum tegra_io_pad id) return NULL; } -static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request, - unsigned long *status, u32 *mask) +static int tegra_io_pad_get_dpd_register_bit(enum tegra_io_pad id, + unsigned long *request, + unsigned long *status, + u32 *mask) { const struct tegra_io_pad_soc *pad; - unsigned long rate, value; pad = tegra_io_pad_find(pmc, id); if (!pad) { @@ -944,6 +959,19 @@ static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request, *request = pmc->soc->regs->dpd2_req; } + return 0; +} + +static int tegra_io_pad_prepare(enum tegra_io_pad id, unsigned long *request, + unsigned long *status, u32 *mask) +{ + unsigned long rate, value; + int err; + + err = tegra_io_pad_get_dpd_register_bit(id, request, status, mask); + if (err) + return err; + if (pmc->clk) { rate = clk_get_rate(pmc->clk); if (!rate) { @@ -1058,8 +1086,22 @@ unlock: } EXPORT_SYMBOL(tegra_io_pad_power_disable); -int tegra_io_pad_set_voltage(enum tegra_io_pad id, - enum tegra_io_pad_voltage voltage) +static int tegra_io_pad_is_powered(enum tegra_io_pad id) +{ + unsigned long request, status; + u32 mask, value; + int err; + + err = tegra_io_pad_get_dpd_register_bit(id, &request, &status, &mask); + if (err) + return err; + + value = tegra_pmc_readl(status); + + return !(value & mask); +} + +static int tegra_io_pad_set_voltage(enum tegra_io_pad id, int voltage) { const struct tegra_io_pad_soc *pad; u32 value; @@ -1073,20 +1115,31 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id, mutex_lock(&pmc->powergates_lock); - /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */ - value = tegra_pmc_readl(PMC_PWR_DET); - value |= BIT(pad->voltage); - tegra_pmc_writel(value, PMC_PWR_DET); + if (pmc->soc->has_impl_33v_pwr) { + value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR); - /* update I/O voltage */ - value = tegra_pmc_readl(PMC_PWR_DET_VALUE); + if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) + value &= ~BIT(pad->voltage); + else + value |= BIT(pad->voltage); - if (voltage == TEGRA_IO_PAD_1800000UV) - value &= ~BIT(pad->voltage); - else + tegra_pmc_writel(value, PMC_IMPL_E_33V_PWR); + } else { + /* write-enable PMC_PWR_DET_VALUE[pad->voltage] */ + value = tegra_pmc_readl(PMC_PWR_DET); value |= BIT(pad->voltage); + tegra_pmc_writel(value, PMC_PWR_DET); - tegra_pmc_writel(value, PMC_PWR_DET_VALUE); + /* update I/O voltage */ + value = tegra_pmc_readl(PMC_PWR_DET_VALUE); + + if (voltage == TEGRA_IO_PAD_VOLTAGE_1V8) + value &= ~BIT(pad->voltage); + else + value |= BIT(pad->voltage); + + tegra_pmc_writel(value, PMC_PWR_DET_VALUE); + } mutex_unlock(&pmc->powergates_lock); @@ -1094,9 +1147,8 @@ int tegra_io_pad_set_voltage(enum tegra_io_pad id, return 0; } -EXPORT_SYMBOL(tegra_io_pad_set_voltage); -int tegra_io_pad_get_voltage(enum tegra_io_pad id) +static int tegra_io_pad_get_voltage(enum tegra_io_pad id) { const struct tegra_io_pad_soc *pad; u32 value; @@ -1108,14 +1160,16 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id) if (pad->voltage == UINT_MAX) return -ENOTSUPP; - value = tegra_pmc_readl(PMC_PWR_DET_VALUE); + if (pmc->soc->has_impl_33v_pwr) + value = tegra_pmc_readl(PMC_IMPL_E_33V_PWR); + else + value = tegra_pmc_readl(PMC_PWR_DET_VALUE); if ((value & BIT(pad->voltage)) == 0) - return TEGRA_IO_PAD_1800000UV; + return TEGRA_IO_PAD_VOLTAGE_1V8; - return TEGRA_IO_PAD_3300000UV; + return TEGRA_IO_PAD_VOLTAGE_3V3; } -EXPORT_SYMBOL(tegra_io_pad_get_voltage); /** * tegra_io_rail_power_on() - enable power to I/O rail @@ -1288,7 +1342,7 @@ static void tegra_pmc_init_tsense_reset(struct tegra_pmc *pmc) if (!pmc->soc->has_tsense_reset) return; - np = of_find_node_by_name(pmc->dev->of_node, "i2c-thermtrip"); + np = of_get_child_by_name(pmc->dev->of_node, "i2c-thermtrip"); if (!np) { dev_warn(dev, "i2c-thermtrip node not found, %s.\n", disabled); return; @@ -1353,6 +1407,142 @@ out: of_node_put(np); } +static int tegra_io_pad_pinctrl_get_groups_count(struct pinctrl_dev *pctl_dev) +{ + return pmc->soc->num_io_pads; +} + +static const char *tegra_io_pad_pinctrl_get_group_name( + struct pinctrl_dev *pctl, unsigned int group) +{ + return pmc->soc->io_pads[group].name; +} + +static int tegra_io_pad_pinctrl_get_group_pins(struct pinctrl_dev *pctl_dev, + unsigned int group, + const unsigned int **pins, + unsigned int *num_pins) +{ + *pins = &pmc->soc->io_pads[group].id; + *num_pins = 1; + return 0; +} + +static const struct pinctrl_ops tegra_io_pad_pinctrl_ops = { + .get_groups_count = tegra_io_pad_pinctrl_get_groups_count, + .get_group_name = tegra_io_pad_pinctrl_get_group_name, + .get_group_pins = tegra_io_pad_pinctrl_get_group_pins, + .dt_node_to_map = pinconf_generic_dt_node_to_map_pin, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +static int tegra_io_pad_pinconf_get(struct pinctrl_dev *pctl_dev, + unsigned int pin, unsigned long *config) +{ + const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin); + enum pin_config_param param = pinconf_to_config_param(*config); + int ret; + u32 arg; + + if (!pad) + return -EINVAL; + + switch (param) { + case PIN_CONFIG_POWER_SOURCE: + ret = tegra_io_pad_get_voltage(pad->id); + if (ret < 0) + return ret; + arg = ret; + break; + case PIN_CONFIG_LOW_POWER_MODE: + ret = tegra_io_pad_is_powered(pad->id); + if (ret < 0) + return ret; + arg = !ret; + break; + default: + return -EINVAL; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static int tegra_io_pad_pinconf_set(struct pinctrl_dev *pctl_dev, + unsigned int pin, unsigned long *configs, + unsigned int num_configs) +{ + const struct tegra_io_pad_soc *pad = tegra_io_pad_find(pmc, pin); + enum pin_config_param param; + unsigned int i; + int err; + u32 arg; + + if (!pad) + return -EINVAL; + + for (i = 0; i < num_configs; ++i) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + switch (param) { + case PIN_CONFIG_LOW_POWER_MODE: + if (arg) + err = tegra_io_pad_power_disable(pad->id); + else + err = tegra_io_pad_power_enable(pad->id); + if (err) + return err; + break; + case PIN_CONFIG_POWER_SOURCE: + if (arg != TEGRA_IO_PAD_VOLTAGE_1V8 && + arg != TEGRA_IO_PAD_VOLTAGE_3V3) + return -EINVAL; + err = tegra_io_pad_set_voltage(pad->id, arg); + if (err) + return err; + break; + default: + return -EINVAL; + } + } + + return 0; +} + +static const struct pinconf_ops tegra_io_pad_pinconf_ops = { + .pin_config_get = tegra_io_pad_pinconf_get, + .pin_config_set = tegra_io_pad_pinconf_set, + .is_generic = true, +}; + +static struct pinctrl_desc tegra_pmc_pctl_desc = { + .pctlops = &tegra_io_pad_pinctrl_ops, + .confops = &tegra_io_pad_pinconf_ops, +}; + +static int tegra_pmc_pinctrl_init(struct tegra_pmc *pmc) +{ + int err = 0; + + if (!pmc->soc->num_pin_descs) + return 0; + + tegra_pmc_pctl_desc.name = dev_name(pmc->dev); + tegra_pmc_pctl_desc.pins = pmc->soc->pin_descs; + tegra_pmc_pctl_desc.npins = pmc->soc->num_pin_descs; + + pmc->pctl_dev = devm_pinctrl_register(pmc->dev, &tegra_pmc_pctl_desc, + pmc); + if (IS_ERR(pmc->pctl_dev)) { + err = PTR_ERR(pmc->pctl_dev); + dev_err(pmc->dev, "unable to register pinctrl, %d\n", err); + } + + return err; +} + static int tegra_pmc_probe(struct platform_device *pdev) { void __iomem *base; @@ -1430,18 +1620,27 @@ static int tegra_pmc_probe(struct platform_device *pdev) err = register_restart_handler(&tegra_pmc_restart_handler); if (err) { - debugfs_remove(pmc->debugfs); dev_err(&pdev->dev, "unable to register restart handler, %d\n", err); - return err; + goto cleanup_debugfs; } + err = tegra_pmc_pinctrl_init(pmc); + if (err) + goto cleanup_restart_handler; + mutex_lock(&pmc->powergates_lock); iounmap(pmc->base); pmc->base = base; mutex_unlock(&pmc->powergates_lock); return 0; + +cleanup_restart_handler: + unregister_restart_handler(&tegra_pmc_restart_handler); +cleanup_debugfs: + debugfs_remove(pmc->debugfs); + return err; } #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM) @@ -1531,6 +1730,8 @@ static const struct tegra_pmc_soc tegra20_pmc_soc = { .has_gpu_clamps = false, .num_io_pads = 0, .io_pads = NULL, + .num_pin_descs = 0, + .pin_descs = NULL, .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, @@ -1567,8 +1768,11 @@ static const struct tegra_pmc_soc tegra30_pmc_soc = { .cpu_powergates = tegra30_cpu_powergates, .has_tsense_reset = true, .has_gpu_clamps = false, + .has_impl_33v_pwr = false, .num_io_pads = 0, .io_pads = NULL, + .num_pin_descs = 0, + .pin_descs = NULL, .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, @@ -1609,8 +1813,11 @@ static const struct tegra_pmc_soc tegra114_pmc_soc = { .cpu_powergates = tegra114_cpu_powergates, .has_tsense_reset = true, .has_gpu_clamps = false, + .has_impl_33v_pwr = false, .num_io_pads = 0, .io_pads = NULL, + .num_pin_descs = 0, + .pin_descs = NULL, .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, @@ -1649,37 +1856,59 @@ static const u8 tegra124_cpu_powergates[] = { TEGRA_POWERGATE_CPU3, }; +#define TEGRA_IO_PAD(_id, _dpd, _voltage, _name) \ + ((struct tegra_io_pad_soc) { \ + .id = (_id), \ + .dpd = (_dpd), \ + .voltage = (_voltage), \ + .name = (_name), \ + }) + +#define TEGRA_IO_PIN_DESC(_id, _dpd, _voltage, _name) \ + ((struct pinctrl_pin_desc) { \ + .number = (_id), \ + .name = (_name) \ + }) + +#define TEGRA124_IO_PAD_TABLE(_pad) \ + /* .id .dpd .voltage .name */ \ + _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ + _pad(TEGRA_IO_PAD_BB, 15, UINT_MAX, "bb"), \ + _pad(TEGRA_IO_PAD_CAM, 36, UINT_MAX, "cam"), \ + _pad(TEGRA_IO_PAD_COMP, 22, UINT_MAX, "comp"), \ + _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ + _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csb"), \ + _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "cse"), \ + _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ + _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \ + _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \ + _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \ + _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \ + _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ + _pad(TEGRA_IO_PAD_HV, 38, UINT_MAX, "hv"), \ + _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \ + _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ + _pad(TEGRA_IO_PAD_NAND, 13, UINT_MAX, "nand"), \ + _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \ + _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \ + _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ + _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ + _pad(TEGRA_IO_PAD_SDMMC1, 33, UINT_MAX, "sdmmc1"), \ + _pad(TEGRA_IO_PAD_SDMMC3, 34, UINT_MAX, "sdmmc3"), \ + _pad(TEGRA_IO_PAD_SDMMC4, 35, UINT_MAX, "sdmmc4"), \ + _pad(TEGRA_IO_PAD_SYS_DDC, 58, UINT_MAX, "sys_ddc"), \ + _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ + _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ + _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ + _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ + _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb_bias") + static const struct tegra_io_pad_soc tegra124_io_pads[] = { - { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_BB, .dpd = 15, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_COMP, .dpd = 22, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HV, .dpd = 38, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_NAND, .dpd = 13, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 35, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SYS_DDC, .dpd = 58, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX }, + TEGRA124_IO_PAD_TABLE(TEGRA_IO_PAD) +}; + +static const struct pinctrl_pin_desc tegra124_pin_descs[] = { + TEGRA124_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) }; static const struct tegra_pmc_soc tegra124_pmc_soc = { @@ -1689,8 +1918,11 @@ static const struct tegra_pmc_soc tegra124_pmc_soc = { .cpu_powergates = tegra124_cpu_powergates, .has_tsense_reset = true, .has_gpu_clamps = true, + .has_impl_33v_pwr = false, .num_io_pads = ARRAY_SIZE(tegra124_io_pads), .io_pads = tegra124_io_pads, + .num_pin_descs = ARRAY_SIZE(tegra124_pin_descs), + .pin_descs = tegra124_pin_descs, .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, @@ -1730,45 +1962,53 @@ static const u8 tegra210_cpu_powergates[] = { TEGRA_POWERGATE_CPU3, }; +#define TEGRA210_IO_PAD_TABLE(_pad) \ + /* .id .dpd .voltage .name */ \ + _pad(TEGRA_IO_PAD_AUDIO, 17, 5, "audio"), \ + _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 18, "audio-hv"), \ + _pad(TEGRA_IO_PAD_CAM, 36, 10, "cam"), \ + _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ + _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ + _pad(TEGRA_IO_PAD_CSIC, 42, UINT_MAX, "csic"), \ + _pad(TEGRA_IO_PAD_CSID, 43, UINT_MAX, "csid"), \ + _pad(TEGRA_IO_PAD_CSIE, 44, UINT_MAX, "csie"), \ + _pad(TEGRA_IO_PAD_CSIF, 45, UINT_MAX, "csif"), \ + _pad(TEGRA_IO_PAD_DBG, 25, 19, "dbg"), \ + _pad(TEGRA_IO_PAD_DEBUG_NONAO, 26, UINT_MAX, "debug-nonao"), \ + _pad(TEGRA_IO_PAD_DMIC, 50, 20, "dmic"), \ + _pad(TEGRA_IO_PAD_DP, 51, UINT_MAX, "dp"), \ + _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ + _pad(TEGRA_IO_PAD_DSIB, 39, UINT_MAX, "dsib"), \ + _pad(TEGRA_IO_PAD_DSIC, 40, UINT_MAX, "dsic"), \ + _pad(TEGRA_IO_PAD_DSID, 41, UINT_MAX, "dsid"), \ + _pad(TEGRA_IO_PAD_EMMC, 35, UINT_MAX, "emmc"), \ + _pad(TEGRA_IO_PAD_EMMC2, 37, UINT_MAX, "emmc2"), \ + _pad(TEGRA_IO_PAD_GPIO, 27, 21, "gpio"), \ + _pad(TEGRA_IO_PAD_HDMI, 28, UINT_MAX, "hdmi"), \ + _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ + _pad(TEGRA_IO_PAD_LVDS, 57, UINT_MAX, "lvds"), \ + _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ + _pad(TEGRA_IO_PAD_PEX_BIAS, 4, UINT_MAX, "pex-bias"), \ + _pad(TEGRA_IO_PAD_PEX_CLK1, 5, UINT_MAX, "pex-clk1"), \ + _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ + _pad(TEGRA_IO_PAD_PEX_CNTRL, UINT_MAX, 11, "pex-cntrl"), \ + _pad(TEGRA_IO_PAD_SDMMC1, 33, 12, "sdmmc1"), \ + _pad(TEGRA_IO_PAD_SDMMC3, 34, 13, "sdmmc3"), \ + _pad(TEGRA_IO_PAD_SPI, 46, 22, "spi"), \ + _pad(TEGRA_IO_PAD_SPI_HV, 47, 23, "spi-hv"), \ + _pad(TEGRA_IO_PAD_UART, 14, 2, "uart"), \ + _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ + _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ + _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ + _pad(TEGRA_IO_PAD_USB3, 18, UINT_MAX, "usb3"), \ + _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias") + static const struct tegra_io_pad_soc tegra210_io_pads[] = { - { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = 5 }, - { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = 18 }, - { .id = TEGRA_IO_PAD_CAM, .dpd = 36, .voltage = 10 }, - { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIC, .dpd = 42, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSID, .dpd = 43, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIE, .dpd = 44, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIF, .dpd = 45, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = 19 }, - { .id = TEGRA_IO_PAD_DEBUG_NONAO, .dpd = 26, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DMIC, .dpd = 50, .voltage = 20 }, - { .id = TEGRA_IO_PAD_DP, .dpd = 51, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSIB, .dpd = 39, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSIC, .dpd = 40, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSID, .dpd = 41, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_EMMC, .dpd = 35, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_EMMC2, .dpd = 37, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_GPIO, .dpd = 27, .voltage = 21 }, - { .id = TEGRA_IO_PAD_HDMI, .dpd = 28, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_LVDS, .dpd = 57, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_BIAS, .dpd = 4, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 5, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = UINT_MAX, .voltage = 11 }, - { .id = TEGRA_IO_PAD_SDMMC1, .dpd = 33, .voltage = 12 }, - { .id = TEGRA_IO_PAD_SDMMC3, .dpd = 34, .voltage = 13 }, - { .id = TEGRA_IO_PAD_SPI, .dpd = 46, .voltage = 22 }, - { .id = TEGRA_IO_PAD_SPI_HV, .dpd = 47, .voltage = 23 }, - { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = 2 }, - { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB3, .dpd = 18, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX }, + TEGRA210_IO_PAD_TABLE(TEGRA_IO_PAD) +}; + +static const struct pinctrl_pin_desc tegra210_pin_descs[] = { + TEGRA210_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) }; static const struct tegra_pmc_soc tegra210_pmc_soc = { @@ -1778,52 +2018,64 @@ static const struct tegra_pmc_soc tegra210_pmc_soc = { .cpu_powergates = tegra210_cpu_powergates, .has_tsense_reset = true, .has_gpu_clamps = true, + .has_impl_33v_pwr = false, .needs_mbist_war = true, .num_io_pads = ARRAY_SIZE(tegra210_io_pads), .io_pads = tegra210_io_pads, + .num_pin_descs = ARRAY_SIZE(tegra210_pin_descs), + .pin_descs = tegra210_pin_descs, .regs = &tegra20_pmc_regs, .init = tegra20_pmc_init, .setup_irq_polarity = tegra20_pmc_setup_irq_polarity, }; +#define TEGRA186_IO_PAD_TABLE(_pad) \ + /* .id .dpd .voltage .name */ \ + _pad(TEGRA_IO_PAD_CSIA, 0, UINT_MAX, "csia"), \ + _pad(TEGRA_IO_PAD_CSIB, 1, UINT_MAX, "csib"), \ + _pad(TEGRA_IO_PAD_DSI, 2, UINT_MAX, "dsi"), \ + _pad(TEGRA_IO_PAD_MIPI_BIAS, 3, UINT_MAX, "mipi-bias"), \ + _pad(TEGRA_IO_PAD_PEX_CLK_BIAS, 4, UINT_MAX, "pex-clk-bias"), \ + _pad(TEGRA_IO_PAD_PEX_CLK3, 5, UINT_MAX, "pex-clk3"), \ + _pad(TEGRA_IO_PAD_PEX_CLK2, 6, UINT_MAX, "pex-clk2"), \ + _pad(TEGRA_IO_PAD_PEX_CLK1, 7, UINT_MAX, "pex-clk1"), \ + _pad(TEGRA_IO_PAD_USB0, 9, UINT_MAX, "usb0"), \ + _pad(TEGRA_IO_PAD_USB1, 10, UINT_MAX, "usb1"), \ + _pad(TEGRA_IO_PAD_USB2, 11, UINT_MAX, "usb2"), \ + _pad(TEGRA_IO_PAD_USB_BIAS, 12, UINT_MAX, "usb-bias"), \ + _pad(TEGRA_IO_PAD_UART, 14, UINT_MAX, "uart"), \ + _pad(TEGRA_IO_PAD_AUDIO, 17, UINT_MAX, "audio"), \ + _pad(TEGRA_IO_PAD_HSIC, 19, UINT_MAX, "hsic"), \ + _pad(TEGRA_IO_PAD_DBG, 25, UINT_MAX, "dbg"), \ + _pad(TEGRA_IO_PAD_HDMI_DP0, 28, UINT_MAX, "hdmi-dp0"), \ + _pad(TEGRA_IO_PAD_HDMI_DP1, 29, UINT_MAX, "hdmi-dp1"), \ + _pad(TEGRA_IO_PAD_PEX_CNTRL, 32, UINT_MAX, "pex-cntrl"), \ + _pad(TEGRA_IO_PAD_SDMMC2_HV, 34, 5, "sdmmc2-hv"), \ + _pad(TEGRA_IO_PAD_SDMMC4, 36, UINT_MAX, "sdmmc4"), \ + _pad(TEGRA_IO_PAD_CAM, 38, UINT_MAX, "cam"), \ + _pad(TEGRA_IO_PAD_DSIB, 40, UINT_MAX, "dsib"), \ + _pad(TEGRA_IO_PAD_DSIC, 41, UINT_MAX, "dsic"), \ + _pad(TEGRA_IO_PAD_DSID, 42, UINT_MAX, "dsid"), \ + _pad(TEGRA_IO_PAD_CSIC, 43, UINT_MAX, "csic"), \ + _pad(TEGRA_IO_PAD_CSID, 44, UINT_MAX, "csid"), \ + _pad(TEGRA_IO_PAD_CSIE, 45, UINT_MAX, "csie"), \ + _pad(TEGRA_IO_PAD_CSIF, 46, UINT_MAX, "csif"), \ + _pad(TEGRA_IO_PAD_SPI, 47, UINT_MAX, "spi"), \ + _pad(TEGRA_IO_PAD_UFS, 49, UINT_MAX, "ufs"), \ + _pad(TEGRA_IO_PAD_DMIC_HV, 52, 2, "dmic-hv"), \ + _pad(TEGRA_IO_PAD_EDP, 53, UINT_MAX, "edp"), \ + _pad(TEGRA_IO_PAD_SDMMC1_HV, 55, 4, "sdmmc1-hv"), \ + _pad(TEGRA_IO_PAD_SDMMC3_HV, 56, 6, "sdmmc3-hv"), \ + _pad(TEGRA_IO_PAD_CONN, 60, UINT_MAX, "conn"), \ + _pad(TEGRA_IO_PAD_AUDIO_HV, 61, 1, "audio-hv"), \ + _pad(TEGRA_IO_PAD_AO_HV, UINT_MAX, 0, "ao-hv") + static const struct tegra_io_pad_soc tegra186_io_pads[] = { - { .id = TEGRA_IO_PAD_CSIA, .dpd = 0, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIB, .dpd = 1, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSI, .dpd = 2, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_MIPI_BIAS, .dpd = 3, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK_BIAS, .dpd = 4, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK3, .dpd = 5, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK2, .dpd = 6, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CLK1, .dpd = 7, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB0, .dpd = 9, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB1, .dpd = 10, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB2, .dpd = 11, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_USB_BIAS, .dpd = 12, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_UART, .dpd = 14, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_AUDIO, .dpd = 17, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HSIC, .dpd = 19, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DBG, .dpd = 25, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HDMI_DP0, .dpd = 28, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_HDMI_DP1, .dpd = 29, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_PEX_CNTRL, .dpd = 32, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC2_HV, .dpd = 34, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC4, .dpd = 36, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CAM, .dpd = 38, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSIB, .dpd = 40, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSIC, .dpd = 41, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DSID, .dpd = 42, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIC, .dpd = 43, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSID, .dpd = 44, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIE, .dpd = 45, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CSIF, .dpd = 46, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SPI, .dpd = 47, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_UFS, .dpd = 49, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_DMIC_HV, .dpd = 52, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_EDP, .dpd = 53, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC1_HV, .dpd = 55, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_SDMMC3_HV, .dpd = 56, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_CONN, .dpd = 60, .voltage = UINT_MAX }, - { .id = TEGRA_IO_PAD_AUDIO_HV, .dpd = 61, .voltage = UINT_MAX }, + TEGRA186_IO_PAD_TABLE(TEGRA_IO_PAD) +}; + +static const struct pinctrl_pin_desc tegra186_pin_descs[] = { + TEGRA186_IO_PAD_TABLE(TEGRA_IO_PIN_DESC) }; static const struct tegra_pmc_regs tegra186_pmc_regs = { @@ -1876,8 +2128,11 @@ static const struct tegra_pmc_soc tegra186_pmc_soc = { .cpu_powergates = NULL, .has_tsense_reset = false, .has_gpu_clamps = false, + .has_impl_33v_pwr = true, .num_io_pads = ARRAY_SIZE(tegra186_io_pads), .io_pads = tegra186_io_pads, + .num_pin_descs = ARRAY_SIZE(tegra186_pin_descs), + .pin_descs = tegra186_pin_descs, .regs = &tegra186_pmc_regs, .init = NULL, .setup_irq_polarity = tegra186_pmc_setup_irq_polarity, diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c index 224d7ddeeb76..23f09dce23e0 100644 --- a/drivers/soc/ti/knav_dma.c +++ b/drivers/soc/ti/knav_dma.c @@ -438,7 +438,7 @@ void *knav_dma_open_channel(struct device *dev, const char *name, chan_num = of_channel_match_helper(dev->of_node, name, &instance); if (chan_num < 0) { - dev_err(kdev->dev, "No DMA instace with name %s\n", name); + dev_err(kdev->dev, "No DMA instance with name %s\n", name); return (void *)-EINVAL; } @@ -461,7 +461,7 @@ void *knav_dma_open_channel(struct device *dev, const char *name, } } if (!found) { - dev_err(kdev->dev, "No DMA instace with name %s\n", instance); + dev_err(kdev->dev, "No DMA instance with name %s\n", instance); return (void *)-EINVAL; } diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h index 3efc47e82973..7c128132799e 100644 --- a/drivers/soc/ti/knav_qmss.h +++ b/drivers/soc/ti/knav_qmss.h @@ -240,14 +240,14 @@ struct knav_pool { }; /** - * struct knav_queue_inst: qmss queue instace properties + * struct knav_queue_inst: qmss queue instance properties * @descs: descriptor pointer * @desc_head, desc_tail, desc_count: descriptor counters * @acc: accumulator channel pointer * @kdev: qmss device pointer * @range: range info * @qmgr: queue manager info - * @id: queue instace id + * @id: queue instance id * @irq_num: irq line number * @notify_needed: notifier needed based on queue type * @num_notifiers: total notifiers @@ -274,7 +274,7 @@ struct knav_queue_inst { /** * struct knav_queue: qmss queue properties * @reg_push, reg_pop, reg_peek: push, pop queue registers - * @inst: qmss queue instace properties + * @inst: qmss queue instance properties * @notifier_fn: notifier function * @notifier_fn_arg: notifier function argument * @notifier_enabled: notier enabled for a give queue |