Commit ae46654b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC driver updates from Olof Johansson:
 "This branch contains platform-related driver updates for ARM and ARM64.

  Among them:

   - Reset driver updates:
     + New API for dealing with arrays of resets
     + Make unimplemented {de,}assert return success on shared resets
     + MSDKv1 driver
     + Removal of obsolete Gemini reset driver
     + Misc updates for sunxi and Uniphier

   - SoC drivers:
     + Platform SoC driver registration on Tegra
     + Shuffle of Qualcomm drivers into a submenu
     + Allwinner A64 support for SRAM
     + Renesas R-Car R3 support
     + Power domains for Rockchip RK3366

   - Misc updates and smaller fixes for TEE and memory driver
     subsystems"

* tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (54 commits)
  firmware: arm_scpi: fix endianness of dev_id in struct dev_pstate_set
  soc/tegra: fuse: Add missing semi-colon
  soc/tegra: Restrict SoC device registration to Tegra
  drivers: soc: sunxi: add support for A64 and its SRAM C
  drivers: soc: sunxi: add support for remapping func value to reg value
  drivers: soc: sunxi: fix error processing on base address when claiming
  dt-bindings: add binding for Allwinner A64 SRAM controller and SRAM C
  bus: sunxi-rsb: Enable by default for ARM64
  soc/tegra: Register SoC device
  firmware: tegra: set drvdata earlier
  memory: Convert to using %pOF instead of full_name
  soc: Convert to using %pOF instead of full_name
  bus: Convert to using %pOF instead of full_name
  firmware: Convert to using %pOF instead of full_name
  soc: mediatek: add SCPSYS power domain driver for MediaTek MT7622 SoC
  soc: mediatek: add header files required for MT7622 SCPSYS dt-binding
  soc: mediatek: reduce code duplication of scpsys_probe across all SoCs
  dt-bindings: soc: update the binding document for SCPSYS on MediaTek MT7622 SoC
  reset: uniphier: add analog amplifiers reset control
  reset: uniphier: add video input subsystem reset control
  ...
parents 7f1b9be1 a48a7b6b
......@@ -61,3 +61,32 @@ Board compatible values (alphabetically, grouped by SoC):
- "amlogic,q201" (Meson gxm s912)
- "kingnovel,r-box-pro" (Meson gxm S912)
- "nexbox,a1" (Meson gxm s912)
Amlogic Meson Firmware registers Interface
------------------------------------------
The Meson SoCs have a register bank with status and data shared with the
secure firmware.
Required properties:
- compatible: For Meson GX SoCs, must be "amlogic,meson-gx-ao-secure", "syscon"
Properties should indentify components of this register interface :
Meson GX SoC Information
------------------------
A firmware register encodes the SoC type, package and revision information on
the Meson GX SoCs.
If present, the following property should be added :
Optional properties:
- amlogic,has-chip-id: If present, the interface gives the current SoC version.
Example
-------
ao-secure@140 {
compatible = "amlogic,meson-gx-ao-secure", "syscon";
reg = <0x0 0x140 0x0 0x140>;
amlogic,has-chip-id;
};
......@@ -17,6 +17,7 @@ Required properties:
- "renesas,r8a7794-sysc" (R-Car E2)
- "renesas,r8a7795-sysc" (R-Car H3)
- "renesas,r8a7796-sysc" (R-Car M3-W)
- "renesas,r8a77995-sysc" (R-Car D3)
- reg: Address start and address range for the device.
- #power-domain-cells: Must be 1.
......
......@@ -26,6 +26,7 @@ Required properties:
- "renesas,r8a7794-rst" (R-Car E2)
- "renesas,r8a7795-rst" (R-Car H3)
- "renesas,r8a7796-rst" (R-Car M3-W)
- "renesas,r8a77995-rst" (R-Car D3)
- reg: Address start and address range for the device.
......
......@@ -6,7 +6,6 @@ System reset
Required properties:
- compatible: should be one of the following:
"socionext,uniphier-sld3-reset" - for sLD3 SoC
"socionext,uniphier-ld4-reset" - for LD4 SoC
"socionext,uniphier-pro4-reset" - for Pro4 SoC
"socionext,uniphier-sld8-reset" - for sLD8 SoC
......@@ -37,7 +36,6 @@ Media I/O (MIO) reset, SD reset
Required properties:
- compatible: should be one of the following:
"socionext,uniphier-sld3-mio-reset" - for sLD3 SoC
"socionext,uniphier-ld4-mio-reset" - for LD4 SoC
"socionext,uniphier-pro4-mio-reset" - for Pro4 SoC
"socionext,uniphier-sld8-mio-reset" - for sLD8 SoC
......@@ -92,3 +90,28 @@ Example:
other nodes ...
};
Analog signal amplifier reset
-----------------------------
Required properties:
- compatible: should be one of the following:
"socionext,uniphier-ld11-adamv-reset" - for LD11 SoC
"socionext,uniphier-ld20-adamv-reset" - for LD20 SoC
- #reset-cells: should be 1.
Example:
adamv@57920000 {
compatible = "socionext,uniphier-ld11-adamv",
"simple-mfd", "syscon";
reg = <0x57920000 0x1000>;
adamv_rst: reset {
compatible = "socionext,uniphier-ld11-adamv-reset";
#reset-cells = <1>;
};
other nodes ...
};
......@@ -12,11 +12,13 @@ power/power_domain.txt. It provides the power domains defined in
- include/dt-bindings/power/mt8173-power.h
- include/dt-bindings/power/mt6797-power.h
- include/dt-bindings/power/mt2701-power.h
- include/dt-bindings/power/mt7622-power.h
Required properties:
- compatible: Should be one of:
- "mediatek,mt2701-scpsys"
- "mediatek,mt6797-scpsys"
- "mediatek,mt7622-scpsys"
- "mediatek,mt8173-scpsys"
- #power-domain-cells: Must be 1
- reg: Address range of the SCPSYS unit
......@@ -26,6 +28,7 @@ Required properties:
enabled before enabling certain power domains.
Required clocks for MT2701: "mm", "mfg", "ethif"
Required clocks for MT6797: "mm", "mfg", "vdec"
Required clocks for MT7622: "hif_sel"
Required clocks for MT8173: "mm", "mfg", "venc", "venc_lt"
Optional properties:
......
......@@ -7,6 +7,7 @@ Required properties for power domain controller:
- compatible: Should be one of the following.
"rockchip,rk3288-power-controller" - for RK3288 SoCs.
"rockchip,rk3328-power-controller" - for RK3328 SoCs.
"rockchip,rk3366-power-controller" - for RK3366 SoCs.
"rockchip,rk3368-power-controller" - for RK3368 SoCs.
"rockchip,rk3399-power-controller" - for RK3399 SoCs.
- #power-domain-cells: Number of cells in a power-domain specifier.
......@@ -18,6 +19,7 @@ Required properties for power domain sub nodes:
- reg: index of the power domain, should use macros in:
"include/dt-bindings/power/rk3288-power.h" - for RK3288 type power domain.
"include/dt-bindings/power/rk3328-power.h" - for RK3328 type power domain.
"include/dt-bindings/power/rk3366-power.h" - for RK3366 type power domain.
"include/dt-bindings/power/rk3368-power.h" - for RK3368 type power domain.
"include/dt-bindings/power/rk3399-power.h" - for RK3399 type power domain.
- clocks (optional): phandles to clocks which need to be enabled while power domain
......@@ -93,6 +95,7 @@ power domain to use.
The index should use macros in:
"include/dt-bindings/power/rk3288-power.h" - for rk3288 type power domain.
"include/dt-bindings/power/rk3328-power.h" - for rk3328 type power domain.
"include/dt-bindings/power/rk3366-power.h" - for rk3366 type power domain.
"include/dt-bindings/power/rk3368-power.h" - for rk3368 type power domain.
"include/dt-bindings/power/rk3399-power.h" - for rk3399 type power domain.
......
......@@ -9,7 +9,9 @@ Controller Node
---------------
Required properties:
- compatible : "allwinner,sun4i-a10-sram-controller"
- compatible : should be:
- "allwinner,sun4i-a10-sram-controller"
- "allwinner,sun50i-a64-sram-controller"
- reg : sram controller register offset + length
SRAM nodes
......@@ -22,10 +24,13 @@ Each SRAM will have SRAM sections that are going to be handled by the
SRAM controller as subnodes. These sections are represented following
once again the representation described in the mmio-sram binding.
The valid sections compatible are:
The valid sections compatible for A10 are:
- allwinner,sun4i-a10-sram-a3-a4
- allwinner,sun4i-a10-sram-d
The valid sections compatible for A64 are:
- allwinner,sun50i-a64-sram-c
Devices using SRAM sections
---------------------------
......
......@@ -12867,6 +12867,13 @@ L: linux-mmc@vger.kernel.org
S: Maintained
F: drivers/mmc/host/dw_mmc*
SYNOPSYS HSDK RESET CONTROLLER DRIVER
M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
S: Supported
F: drivers/reset/reset-hsdk-v1.c
F: include/dt-bindings/reset/snps,hsdk-v1-reset.h
F: Documentation/devicetree/bindings/reset/snps,hsdk-v1-reset.txt
SYSTEM CONFIGURATION (SYSCON)
M: Lee Jones <lee.jones@linaro.org>
M: Arnd Bergmann <arnd@arndb.de>
......
......@@ -30,6 +30,7 @@ static void __init mediatek_timer_init(void)
if (of_machine_is_compatible("mediatek,mt6589") ||
of_machine_is_compatible("mediatek,mt7623") ||
of_machine_is_compatible("mediatek,mt7623a") ||
of_machine_is_compatible("mediatek,mt8135") ||
of_machine_is_compatible("mediatek,mt8127")) {
/* turn on GPT6 which ungates arch timer clocks */
......@@ -49,6 +50,7 @@ static const char * const mediatek_board_dt_compat[] = {
"mediatek,mt6589",
"mediatek,mt6592",
"mediatek,mt7623",
"mediatek,mt7623a",
"mediatek,mt8127",
"mediatek,mt8135",
NULL,
......
......@@ -59,6 +59,7 @@ static const struct of_device_id mtk_tz_smp_boot_infos[] __initconst = {
static const struct of_device_id mtk_smp_boot_infos[] __initconst = {
{ .compatible = "mediatek,mt6589", .data = &mtk_mt6589_boot },
{ .compatible = "mediatek,mt7623", .data = &mtk_mt7623_boot },
{ .compatible = "mediatek,mt7623a", .data = &mtk_mt7623_boot },
};
static void __iomem *mtk_smp_base;
......
......@@ -84,35 +84,8 @@ static void __init tegra_dt_init_irq(void)
static void __init tegra_dt_init(void)
{
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
struct device *parent = NULL;
struct device *parent = tegra_soc_device_register();
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
goto out;
soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d",
tegra_sku_info.revision);
soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr->family);
kfree(soc_dev_attr->revision);
kfree(soc_dev_attr->soc_id);
kfree(soc_dev_attr);
goto out;
}
parent = soc_device_to_device(soc_dev);
/*
* Finished with the static registrations now; fill in the missing
* devices
*/
out:
of_platform_default_populate(NULL, NULL, parent);
}
......
......@@ -132,7 +132,7 @@ config SIMPLE_PM_BUS
config SUNXI_RSB
tristate "Allwinner sunXi Reduced Serial Bus Driver"
default MACH_SUN8I || MACH_SUN9I
default MACH_SUN8I || MACH_SUN9I || ARM64
depends on ARCH_SUNXI
select REGMAP
help
......
......@@ -2124,8 +2124,8 @@ int notrace __cci_control_port_by_device(struct device_node *dn, bool enable)
return -ENODEV;
port = __cci_ace_get_port(dn, ACE_LITE_PORT);
if (WARN_ONCE(port < 0, "node %s ACE lite port look-up failure\n",
dn->full_name))
if (WARN_ONCE(port < 0, "node %pOF ACE lite port look-up failure\n",
dn))
return -ENODEV;
cci_port_control(port, enable);
return 0;
......@@ -2200,14 +2200,14 @@ static int cci_probe_ports(struct device_node *np)
if (of_property_read_string(cp, "interface-type",
&match_str)) {
WARN(1, "node %s missing interface-type property\n",
cp->full_name);
WARN(1, "node %pOF missing interface-type property\n",
cp);
continue;
}
is_ace = strcmp(match_str, "ace") == 0;
if (!is_ace && strcmp(match_str, "ace-lite")) {
WARN(1, "node %s containing invalid interface-type property, skipping it\n",
cp->full_name);
WARN(1, "node %pOF containing invalid interface-type property, skipping it\n",
cp);
continue;
}
......
......@@ -156,8 +156,8 @@ static int __init weim_parse_dt(struct platform_device *pdev,
ret = weim_timing_setup(child, base, devtype);
if (ret)
dev_warn(&pdev->dev, "%s set timing failed.\n",
child->full_name);
dev_warn(&pdev->dev, "%pOF set timing failed.\n",
child);
else
have_child = 1;
}
......@@ -166,8 +166,8 @@ static int __init weim_parse_dt(struct platform_device *pdev,
ret = of_platform_default_populate(pdev->dev.of_node,
NULL, &pdev->dev);
if (ret)
dev_err(&pdev->dev, "%s fail to create devices.\n",
pdev->dev.of_node->full_name);
dev_err(&pdev->dev, "%pOF fail to create devices.\n",
pdev->dev.of_node);
return ret;
}
......
......@@ -556,20 +556,20 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb)
/* Runtime addresses for all slaves should be set first */
for_each_available_child_of_node(np, child) {
dev_dbg(dev, "setting child %s runtime address\n",
child->full_name);
dev_dbg(dev, "setting child %pOF runtime address\n",
child);
ret = of_property_read_u32(child, "reg", &hwaddr);
if (ret) {
dev_err(dev, "%s: invalid 'reg' property: %d\n",
child->full_name, ret);
dev_err(dev, "%pOF: invalid 'reg' property: %d\n",
child, ret);
continue;
}
rtaddr = sunxi_rsb_get_rtaddr(hwaddr);
if (!rtaddr) {
dev_err(dev, "%s: unknown hardware device address\n",
child->full_name);
dev_err(dev, "%pOF: unknown hardware device address\n",
child);
continue;
}
......@@ -586,15 +586,15 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb)
/* send command */
ret = _sunxi_rsb_run_xfer(rsb);
if (ret)
dev_warn(dev, "%s: set runtime address failed: %d\n",
child->full_name, ret);
dev_warn(dev, "%pOF: set runtime address failed: %d\n",
child, ret);
}
/* Then we start adding devices and probing them */
for_each_available_child_of_node(np, child) {
struct sunxi_rsb_device *rdev;
dev_dbg(dev, "adding child %s\n", child->full_name);
dev_dbg(dev, "adding child %pOF\n", child);
ret = of_property_read_u32(child, "reg", &hwaddr);
if (ret)
......@@ -606,8 +606,8 @@ static int of_rsb_register_devices(struct sunxi_rsb *rsb)
rdev = sunxi_rsb_device_create(rsb, child, hwaddr, rtaddr);
if (IS_ERR(rdev))
dev_err(dev, "failed to add child device %s: %ld\n",
child->full_name, PTR_ERR(rdev));
dev_err(dev, "failed to add child device %pOF: %ld\n",
child, PTR_ERR(rdev));
}
return 0;
......
......@@ -357,7 +357,7 @@ struct sensor_value {
} __packed;
struct dev_pstate_set {
u16 dev_id;
__le16 dev_id;
u8 pstate;
} __packed;
......@@ -965,7 +965,7 @@ static int scpi_probe(struct platform_device *pdev)
count = of_count_phandle_with_args(np, "mboxes", "#mbox-cells");
if (count < 0) {
dev_err(dev, "no mboxes property in '%s'\n", np->full_name);
dev_err(dev, "no mboxes property in '%pOF'\n", np);
return -ENODEV;
}
......
......@@ -280,8 +280,8 @@ static int psci_dt_cpu_init_idle(struct device_node *cpu_node, int cpu)
"arm,psci-suspend-param",
&state);
if (ret) {
pr_warn(" * %s missing arm,psci-suspend-param property\n",
state_node->full_name);
pr_warn(" * %pOF missing arm,psci-suspend-param property\n",
state_node);
of_node_put(state_node);
goto free_mem;
}
......
......@@ -806,6 +806,8 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "firmware: %s\n", tag);
platform_set_drvdata(pdev, bpmp);
err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev);
if (err < 0)
goto free_mrq;
......@@ -822,8 +824,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
if (err < 0)
goto free_mrq;
platform_set_drvdata(pdev, bpmp);
return 0;
free_mrq:
......
......@@ -159,8 +159,8 @@ static int atmel_ebi_xslate_smc_timings(struct atmel_ebi_dev *ebid,
out:
if (ret) {
dev_err(ebid->ebi->dev,
"missing or invalid timings definition in %s",
np->full_name);
"missing or invalid timings definition in %pOF",
np);
return ret;
}
......@@ -270,8 +270,8 @@ static int atmel_ebi_xslate_smc_config(struct atmel_ebi_dev *ebid,
return -EINVAL;
if ((ret > 0 && !required) || (!ret && required)) {
dev_err(ebid->ebi->dev, "missing atmel,smc- properties in %s",
np->full_name);
dev_err(ebid->ebi->dev, "missing atmel,smc- properties in %pOF",
np);
return -EINVAL;
}
......@@ -314,8 +314,7 @@ static int atmel_ebi_dev_setup(struct atmel_ebi *ebi, struct device_node *np,
if (cs >= AT91_MATRIX_EBI_NUM_CS ||
!(ebi->caps->available_cs & BIT(cs))) {
dev_err(dev, "invalid reg property in %s\n",
np->full_name);
dev_err(dev, "invalid reg property in %pOF\n", np);
return -EINVAL;
}
......@@ -324,7 +323,7 @@ static int atmel_ebi_dev_setup(struct atmel_ebi *ebi, struct device_node *np,
}
if (!numcs) {
dev_err(dev, "invalid reg property in %s\n", np->full_name);
dev_err(dev, "invalid reg property in %pOF\n", np);
return -EINVAL;
}
......@@ -576,8 +575,8 @@ static int atmel_ebi_probe(struct platform_device *pdev)
ret = atmel_ebi_dev_setup(ebi, child, reg_cells);
if (ret) {
dev_err(dev, "failed to configure EBI bus for %s, disabling the device",
child->full_name);
dev_err(dev, "failed to configure EBI bus for %pOF, disabling the device",
child);
ret = atmel_ebi_dev_disable(ebi, child);
if (ret)
......
......@@ -322,8 +322,8 @@ static int jz4780_nemc_probe(struct platform_device *pdev)
bank = of_read_number(prop, 1);
if (bank < 1 || bank >= JZ4780_NEMC_NUM_BANKS) {
dev_err(nemc->dev,
"%s requests invalid bank %u\n",
child->full_name, bank);
"%pOF requests invalid bank %u\n",
child, bank);
/* Will continue the outer loop below. */
referenced = 0;
......@@ -334,12 +334,12 @@ static int jz4780_nemc_probe(struct platform_device *pdev)
}
if (!referenced) {
dev_err(nemc->dev, "%s has no addresses\n",
child->full_name);
dev_err(nemc->dev, "%pOF has no addresses\n",
child);
continue;
} else if (nemc->banks_present & referenced) {
dev_err(nemc->dev, "%s conflicts with another node\n",
child->full_name);
dev_err(nemc->dev, "%pOF conflicts with another node\n",
child);
continue;
}
......
......@@ -105,8 +105,8 @@ static int get_timing_param_ps(struct devbus *devbus,
err = of_property_read_u32(node, name, &time_ps);
if (err < 0) {
dev_err(devbus->dev, "%s has no '%s' property\n",
name, node->full_name);
dev_err(devbus->dev, "%pOF has no '%s' property\n",
node, name);
return err;
}
......@@ -127,8 +127,8 @@ static int devbus_get_timing_params(struct devbus *devbus,
err = of_property_read_u32(node, "devbus,bus-width", &r->bus_width);
if (err < 0) {
dev_err(devbus->dev,
"%s has no 'devbus,bus-width' property\n",
node->full_name);
"%pOF has no 'devbus,bus-width' property\n",
node);
return err;
}
......@@ -180,8 +180,8 @@ static int devbus_get_timing_params(struct devbus *devbus,
&w->sync_enable);
if (err < 0) {
dev_err(devbus->dev,
"%s has no 'devbus,sync-enable' property\n",
node->full_name);
"%pOF has no 'devbus,sync-enable' property\n",
node);
return err;
}
}
......
......@@ -1930,8 +1930,8 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
struct omap_onenand_platform_data *gpmc_onenand_data;
if (of_property_read_u32(child, "reg", &val) < 0) {
dev_err(&pdev->dev, "%s has no 'reg' property\n",
child->full_name);
dev_err(&pdev->dev, "%pOF has no 'reg' property\n",
child);
return -ENODEV;
}
......@@ -1979,14 +1979,14 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
struct gpmc_device *gpmc = platform_get_drvdata(pdev);
if (of_property_read_u32(child, "reg", &cs) < 0) {
dev_err(&pdev->dev, "%s has no 'reg' property\n",
child->full_name);
dev_err(&pdev->dev, "%pOF has no 'reg' property\n",
child);
return -ENODEV;
}
if (of_address_to_resource(child, 0, &res) < 0) {
dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
child->full_name);
dev_err(&pdev->dev, "%pOF has malformed 'reg' property\n",
child);
return -ENODEV;
}
......@@ -2084,8 +2084,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
ret = of_property_read_u32(child, "bank-width",
&gpmc_s.device_width);
if (ret < 0) {
dev_err(&pdev->dev, "%s has no 'bank-width' property\n",
child->full_name);
dev_err(&pdev->dev, "%pOF has no 'bank-width' property\n",
child);
goto err;
}
}
......
......@@ -34,12 +34,11 @@ config RESET_BERLIN
help
This enables the reset controller driver for Marvell Berlin SoCs.
config RESET_GEMINI
bool "Gemini Reset Driver" if COMPILE_TEST
default ARCH_GEMINI
select MFD_SYSCON
config RESET_HSDK_V1
bool "HSDK v1 Reset Driver"
default n
help
This enables the reset controller driver for Cortina Systems Gemini.
This enables the reset controller driver for HSDK v1.
config RESET_IMX7
bool "i.MX7 Reset Driver" if COMPILE_TEST
......
......@@ -5,7 +5,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
obj-$(CONFIG_RESET_GEMINI) += reset-gemini.o
obj-$(CONFIG_RESET_HSDK_V1) += reset-hsdk-v1.o
obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
......
......@@ -43,10 +43,23 @@ struct reset_control {
unsigned int id;
struct kref refcnt;
bool shared;
bool array;
atomic_t deassert_count;
atomic_t triggered_count;
};
/**
* struct reset_control_array - an array of reset controls
* @base: reset control for compatibility with reset control API functions
* @num_rstcs: number of reset controls
* @rstc: array of reset controls
*/
struct reset_control_array {
struct reset_control base;
unsigned int num_rstcs;
struct reset_control *rstc[];
};
/**
* of_reset_simple_xlate - translate reset_spec to the reset line number
* @rcdev: a pointer to the reset controller device
......@@ -135,6 +148,65 @@ int devm_reset_controller_register(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_reset_controller_register);
static inline struct reset_control_array *
rstc_to_array(struct reset_control *rstc) {
return container_of(rstc, struct reset_control_array, base);
}
static int reset_control_array_reset(struct reset_control_array *resets)
{
int ret, i;
for (i = 0; i < resets->num_rstcs; i++) {
ret = reset_control_reset(resets->rstc[i]);
if (ret)
return ret;
}
return 0;
}
static int reset_control_array_assert(struct reset_control_array *resets)
{
int ret, i;
for (i = 0; i < resets->num_rstcs; i++) {
ret = reset_control_assert(resets->rstc[i]);
if (ret)
goto err;
}
return 0;
err:
while (i--)
reset_control_deassert(resets->rstc[i]);
return ret;
}
static int reset_control_array_deassert(struct reset_control_array *resets)
{
int ret, i;
for (i = 0; i < resets->num_rstcs; i++) {
ret = reset_control_deassert(resets->rstc[i]);
if (ret)
goto err;
}
return 0;
err:
while (i--)
reset_control_assert(resets->rstc[i]);
return ret;
}
static inline bool reset_control_is_array(struct reset_control *rstc)
{
return rstc->array;
}
/**
* reset_control_reset - reset the controlled device
* @rstc: reset controller
......@@ -158,6 +230,9 @@ int reset_control_reset(struct reset_control *rstc)
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
if (reset_control_is_array(rstc))
return reset_control_array_reset(rstc_to_array(rstc));
if (!rstc->rcdev->ops->reset)
return -ENOTSUPP;
......@@ -202,8 +277,8 @@ int reset_control_assert(struct reset_control *rstc)
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
if (!rstc->rcdev->ops->assert)
return -ENOTSUPP;
if (reset_control_is_array(rstc))
return reset_control_array_assert(rstc_to_array(rstc));
if (rstc->shared) {
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
......@@ -214,6 +289,21 @@ int reset_control_assert(struct reset_control *rstc)
if (atomic_dec_return(&rstc->deassert_count) != 0)
return 0;
/*
* Shared reset controls allow the reset line to be in any state
* after this call, so doing nothing is a valid option.
*/
if (!rstc->rcdev->ops->assert)
return 0;
} else {
/*
* If the reset controller does not implement .assert(), there
* is no way to guarantee that the reset line is asserted after
* this call.
*/
if (!rstc->rcdev->ops->assert)
return -ENOTSUPP;
}
return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
......@@ -240,8 +330,8 @@ int reset_control_deassert(struct reset_control *rstc)
if (WARN_ON(IS_ERR(rstc)))
return -EINVAL;
if (!rstc->rcdev->ops->deassert)
return -ENOTSUPP;
if (reset_control_is_array(rstc))
return reset_control_array_deassert(rstc_to_array(rstc));
if (rstc->shared) {
if (WARN_ON(atomic_read(&rstc->triggered_count) != 0))
......@@ -251,6 +341,16 @@ int reset_control_deassert(struct reset_control *rstc)
return 0;
}
/*
* If the reset controller does not implement .deassert(), we assume
* that it handles self-deasserting reset lines via .reset(). In that
* case, the reset lines are deasserted by default. If that is not the
* case, the reset controller driver should implement .deassert() and
* return -ENOTSUPP.
*/
if (!rstc->rcdev->ops->deassert)
return 0;
return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
}
EXPORT_SYMBOL_GPL(reset_control_deassert);
......@@ -266,7 +366,7 @@ int reset_control_status(struct reset_control *rstc)
if (!rstc)
return 0;
if (WARN_ON(IS_ERR(rstc)))
if (WARN_ON(IS_ERR(rstc)) || reset_control_is_array(rstc))
return -EINVAL;
if (rstc->rcdev->ops->status)
......@@ -404,6 +504,16 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id,
}
EXPORT_SYMBOL_GPL(__reset_control_get);
static void reset_control_array_put(struct reset_control_array *resets)
{
int i;
mutex_lock(&reset_list_mutex);
for (i = 0; i < resets->num_rstcs; i++)
__reset_control_put_internal(resets->rstc[i]);
mutex_unlock(&reset_list_mutex);
}
/**
* reset_control_put - free the reset controller
* @rstc: reset controller
......@@ -413,6 +523,11 @@ void reset_control_put(struct reset_control *rstc)
if (IS_ERR_OR_NULL(rstc))
return;
if (reset_control_is_array(rstc)) {
reset_control_array_put(rstc_to_array(rstc));
return;
}
mutex_lock(&reset_list_mutex);
__reset_control_put_internal(rstc);
mutex_unlock(&reset_list_mutex);
......@@ -472,3 +587,116 @@ int device_reset(struct device *dev)
return ret;
}
EXPORT_SYMBOL_GPL(device_reset);
/**
* APIs to manage an array of reset controls.
*/
/**
* of_reset_control_get_count - Count number of resets available with a device
*
* @node: device node that contains 'resets'.
*
* Returns positive reset count on success, or error number on failure and
* on count being zero.
*/
static int of_reset_control_get_count(struct device_node *node)
{
int count;
if (!node)
return -EINVAL;
count = of_count_phandle_with_args(node, "resets", "#reset-cells");
if (count == 0)
count = -ENOENT;
return count;
}
/**
* of_reset_control_array_get - Get a list of reset controls using
* device node.
*
* @np: device node for the device that requests the reset controls array
* @shared: whether reset controls are shared or not
* @optional: whether it is optional to get the reset controls
*
* Returns pointer to allocated reset_control_array on success or
* error on failure
*/
struct reset_control *
of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
{
struct reset_control_array *resets;
struct reset_control *rstc;
int num, i;
num = of_reset_control_get_count(np);
if (num < 0)
return optional ? NULL : ERR_PTR(num);
resets = kzalloc(sizeof(*resets) + sizeof(resets->rstc[0]) * num,
GFP_KERNEL);
if (!resets)
return ERR_PTR(-ENOMEM);
for (i = 0; i < num; i++) {
rstc = __of_reset_control_get(np, NULL, i, shared, optional);
if (IS_ERR(rstc))
goto err_rst;
resets->rstc[i] = rstc;
}
resets->num_rstcs = num;
resets->base.array = true;
return &resets->base;
err_rst:
mutex_lock(&reset_list_mutex);
while (--i >= 0)
__reset_control_put_internal(resets->rstc[i]);
mutex_unlock(&reset_list_mutex);
kfree(resets);
return rstc;
}
EXPORT_SYMBOL_GPL(of_reset_control_array_get);
/**
* devm_reset_control_array_get - Resource managed reset control array get
*
* @dev: device that requests the list of reset controls
* @shared: whether reset controls are shared or not
* @optional: whether it is optional to get the reset controls
*
* The reset control array APIs are intended for a list of resets
* that just have to be asserted or deasserted, without any
* requirements on the order.
*
* Returns pointer to allocated reset_control_array on success or
* error on failure
*/
struct reset_control *
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
{
struct reset_control **devres;
struct reset_control *rstc;
devres = devres_alloc(devm_reset_control_release, sizeof(*devres),
GFP_KERNEL);
if (!devres)
return ERR_PTR(-ENOMEM);
rstc = of_reset_control_array_get(dev->of_node, shared, optional);
if (IS_ERR(rstc)) {
devres_free(devres);
return rstc;
}
*devres = rstc;
devres_add(dev, devres);
return rstc;
}
EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
/*
* Cortina Gemini Reset controller driver
* Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
*
* 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/err.h>
#include <linux/init.h>
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <dt-bindings/reset/cortina,gemini-reset.h>
/**
* struct gemini_reset - gemini reset controller
* @map: regmap to access the containing system controller
* @rcdev: reset controller device
*/
struct gemini_reset {
struct regmap *map;
struct reset_controller_dev rcdev;
};
#define GEMINI_GLOBAL_SOFT_RESET 0x0c
#define to_gemini_reset(p) \
container_of((p), struct gemini_reset, rcdev)
/*
* This is a self-deasserting reset controller.
*/
static int gemini_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct gemini_reset *gr = to_gemini_reset(rcdev);
/* Manual says to always set BIT 30 (CPU1) to 1 */
return regmap_write(gr->map,
GEMINI_GLOBAL_SOFT_RESET,
BIT(GEMINI_RESET_CPU1) | BIT(id));
}
static int gemini_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct gemini_reset *gr = to_gemini_reset(rcdev);
u32 val;
int ret;
ret = regmap_read(gr->map, GEMINI_GLOBAL_SOFT_RESET, &val);
if (ret)
return ret;
return !!(val & BIT(id));
}
static const struct reset_control_ops gemini_reset_ops = {
.reset = gemini_reset,
.status = gemini_reset_status,
};
static int gemini_reset_probe(struct platform_device *pdev)
{
struct gemini_reset *gr;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
int ret;
gr = devm_kzalloc(dev, sizeof(*gr), GFP_KERNEL);
if (!gr)
return -ENOMEM;
gr->map = syscon_node_to_regmap(np);
if (IS_ERR(gr->map)) {
ret = PTR_ERR(gr->map);
dev_err(dev, "unable to get regmap (%d)", ret);
return ret;
}
gr->rcdev.owner = THIS_MODULE;
gr->rcdev.nr_resets = 32;
gr->rcdev.ops = &gemini_reset_ops;
gr->rcdev.of_node = pdev->dev.of_node;
ret = devm_reset_controller_register(&pdev->dev, &gr->rcdev);
if (ret)
return ret;
dev_info(dev, "registered Gemini reset controller\n");
return 0;
}
static const struct of_device_id gemini_reset_dt_ids[] = {
{ .compatible = "cortina,gemini-syscon", },
{ /* sentinel */ },
};
static struct platform_driver gemini_reset_driver = {
.probe = gemini_reset_probe,
.driver = {
.name = "gemini-reset",
.of_match_table = gemini_reset_dt_ids,
.suppress_bind_attrs = true,
},
};
builtin_platform_driver(gemini_reset_driver);
/*
* Copyright (C) 2017 Synopsys.
*
* Synopsys HSDKv1 SDP reset driver.
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/types.h>
#define to_hsdkv1_rst(p) container_of((p), struct hsdkv1_rst, rcdev)
struct hsdkv1_rst {
void __iomem *regs_ctl;
void __iomem *regs_rst;
spinlock_t lock;
struct reset_controller_dev rcdev;
};
static const u32 rst_map[] = {
BIT(16), /* APB_RST */
BIT(17), /* AXI_RST */
BIT(18), /* ETH_RST */
BIT(19), /* USB_RST */
BIT(20), /* SDIO_RST */
BIT(21), /* HDMI_RST */
BIT(22), /* GFX_RST */
BIT(25), /* DMAC_RST */
BIT(31), /* EBI_RST */
};
#define HSDK_MAX_RESETS ARRAY_SIZE(rst_map)
#define CGU_SYS_RST_CTRL 0x0
#define CGU_IP_SW_RESET 0x0
#define CGU_IP_SW_RESET_DELAY_SHIFT 16
#define CGU_IP_SW_RESET_DELAY_MASK GENMASK(31, CGU_IP_SW_RESET_DELAY_SHIFT)
#define CGU_IP_SW_RESET_DELAY 0
#define CGU_IP_SW_RESET_RESET BIT(0)
#define SW_RESET_TIMEOUT 10000
static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id)
{
writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL);
}
static int hsdkv1_reset_do(struct hsdkv1_rst *rst)
{
u32 reg;
reg = readl(rst->regs_rst + CGU_IP_SW_RESET);
reg &= ~CGU_IP_SW_RESET_DELAY_MASK;
reg |= CGU_IP_SW_RESET_DELAY << CGU_IP_SW_RESET_DELAY_SHIFT;
reg |= CGU_IP_SW_RESET_RESET;
writel(reg, rst->regs_rst + CGU_IP_SW_RESET);
/* wait till reset bit is back to 0 */
return readl_poll_timeout_atomic(rst->regs_rst + CGU_IP_SW_RESET, reg,
!(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT);
}
static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev);
unsigned long flags;
int ret;
spin_lock_irqsave(&rst->lock, flags);
hsdkv1_reset_config(rst, id);
ret = hsdkv1_reset_do(rst);
spin_unlock_irqrestore(&rst->lock, flags);
return ret;
}
static const struct reset_control_ops hsdkv1_reset_ops = {
.reset = hsdkv1_reset_reset,
};
static int hsdkv1_reset_probe(struct platform_device *pdev)
{
struct hsdkv1_rst *rst;
struct resource *mem;
rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rst->regs_ctl = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rst->regs_ctl))
return PTR_ERR(rst->regs_ctl);
mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
rst->regs_rst = devm_ioremap_resource(&pdev->dev, mem);
if (IS_ERR(rst->regs_rst))
return PTR_ERR(rst->regs_rst);
spin_lock_init(&rst->lock);
rst->rcdev.owner = THIS_MODULE;
rst->rcdev.ops = &hsdkv1_reset_ops;
rst->rcdev.of_node = pdev->dev.of_node;
rst->rcdev.nr_resets = HSDK_MAX_RESETS;
rst->rcdev.of_reset_n_cells = 1;
return reset_controller_register(&rst->rcdev);
}
static const struct of_device_id hsdkv1_reset_dt_match[] = {
{ .compatible = "snps,hsdk-v1.0-reset" },
{ },
};
static struct platform_driver hsdkv1_reset_driver = {
.probe = hsdkv1_reset_probe,
.driver = {
.name = "hsdk-v1.0-reset",
.of_match_table = hsdkv1_reset_dt_match,
},
};
builtin_platform_driver(hsdkv1_reset_driver);
MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>");
MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver");
MODULE_LICENSE("GPL v2");
......@@ -107,7 +107,7 @@ static int sunxi_reset_init(struct device_node *np)
spin_lock_init(&data->lock);
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = size * 32;
data->rcdev.nr_resets = size * 8;
data->rcdev.ops = &sunxi_reset_ops;
data->rcdev.of_node = np;
......@@ -162,7 +162,7 @@ static int sunxi_reset_probe(struct platform_device *pdev)
spin_lock_init(&data->lock);
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = resource_size(res) * 32;
data->rcdev.nr_resets = resource_size(res) * 8;
data->rcdev.ops = &sunxi_reset_ops;
data->rcdev.of_node = pdev->dev.of_node;
......
......@@ -50,59 +50,35 @@ struct uniphier_reset_data {
}
/* System reset data */
#define UNIPHIER_SLD3_SYS_RESET_NAND(id) \
UNIPHIER_RESETX((id), 0x2004, 2)
#define UNIPHIER_LD11_SYS_RESET_NAND(id) \
UNIPHIER_RESETX((id), 0x200c, 0)
#define UNIPHIER_LD11_SYS_RESET_EMMC(id) \
UNIPHIER_RESETX((id), 0x200c, 2)
#define UNIPHIER_SLD3_SYS_RESET_STDMAC(id) \
UNIPHIER_RESETX((id), 0x2000, 10)
#define UNIPHIER_LD11_SYS_RESET_STDMAC(id) \
UNIPHIER_RESETX((id), 0x200c, 8)
#define UNIPHIER_PRO4_SYS_RESET_GIO(id) \
UNIPHIER_RESETX((id), 0x2000, 6)
#define UNIPHIER_LD20_SYS_RESET_GIO(id) \
UNIPHIER_RESETX((id), 0x200c, 5)
#define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch) \
UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
UNIPHIER_SLD3_SYS_RESET_NAND(2),
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* Ether, HSC, MIO */
static const struct uniphier_reset_data uniphier_ld4_sys_reset_data[] = {
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (Ether, HSC, MIO) */
UNIPHIER_RESET_END,
};
static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
UNIPHIER_SLD3_SYS_RESET_NAND(2),
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, MIO, RLE */
UNIPHIER_PRO4_SYS_RESET_GIO(12), /* Ether, SATA, USB3 */
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, MIO, RLE) */
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (Ether, SATA, USB3) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
UNIPHIER_RESET_END,
};
static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
UNIPHIER_SLD3_SYS_RESET_NAND(2),
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC */
UNIPHIER_PRO4_SYS_RESET_GIO(12), /* PCIe, USB3 */
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC) */
UNIPHIER_RESETX(12, 0x2000, 6), /* GIO (PCIe, USB3) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
UNIPHIER_RESET_END,
};
static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
UNIPHIER_SLD3_SYS_RESET_NAND(2),
UNIPHIER_SLD3_SYS_RESET_STDMAC(8), /* HSC, RLE */
UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
UNIPHIER_RESETX(2, 0x2000, 2), /* NAND */
UNIPHIER_RESETX(8, 0x2000, 10), /* STDMAC (HSC, RLE) */
UNIPHIER_RESETX(14, 0x2000, 17), /* USB30 */
UNIPHIER_RESETX(15, 0x2004, 17), /* USB31 */
UNIPHIER_RESETX(16, 0x2014, 4), /* USB30-PHY0 */
UNIPHIER_RESETX(17, 0x2014, 0), /* USB30-PHY1 */
UNIPHIER_RESETX(18, 0x2014, 2), /* USB30-PHY2 */
......@@ -114,21 +90,27 @@ static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
};
static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
UNIPHIER_LD11_SYS_RESET_NAND(2),
UNIPHIER_LD11_SYS_RESET_EMMC(4),
UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC, MIO */
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC, MIO) */
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */
UNIPHIER_RESET_END,
};
static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
UNIPHIER_LD11_SYS_RESET_NAND(2),
UNIPHIER_LD11_SYS_RESET_EMMC(4),
UNIPHIER_LD11_SYS_RESET_STDMAC(8), /* HSC */
UNIPHIER_LD20_SYS_RESET_GIO(12), /* PCIe, USB3 */
UNIPHIER_RESETX(2, 0x200c, 0), /* NAND */
UNIPHIER_RESETX(4, 0x200c, 2), /* eMMC */
UNIPHIER_RESETX(8, 0x200c, 8), /* STDMAC (HSC) */
UNIPHIER_RESETX(12, 0x200c, 5), /* GIO (PCIe, USB3) */
UNIPHIER_RESETX(16, 0x200c, 12), /* USB30-PHY0 */
UNIPHIER_RESETX(17, 0x200c, 13), /* USB30-PHY1 */
UNIPHIER_RESETX(18, 0x200c, 14), /* USB30-PHY2 */
UNIPHIER_RESETX(19, 0x200c, 15), /* USB30-PHY3 */
UNIPHIER_RESETX(40, 0x2008, 0), /* AIO */
UNIPHIER_RESETX(41, 0x2008, 1), /* EVEA */
UNIPHIER_RESETX(42, 0x2010, 2), /* EXIV */
UNIPHIER_RESET_END,
};
......@@ -151,7 +133,7 @@ static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
#define UNIPHIER_MIO_RESET_DMAC(id) \
UNIPHIER_RESETX((id), 0x110, 17)
static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
static const struct uniphier_reset_data uniphier_ld4_mio_reset_data[] = {
UNIPHIER_MIO_RESET_SD(0, 0),
UNIPHIER_MIO_RESET_SD(1, 1),
UNIPHIER_MIO_RESET_SD(2, 2),
......@@ -163,11 +145,9 @@ static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
UNIPHIER_MIO_RESET_USB2(8, 0),
UNIPHIER_MIO_RESET_USB2(9, 1),
UNIPHIER_MIO_RESET_USB2(10, 2),
UNIPHIER_MIO_RESET_USB2(11, 3),
UNIPHIER_MIO_RESET_USB2_BRIDGE(12, 0),
UNIPHIER_MIO_RESET_USB2_BRIDGE(13, 1),
UNIPHIER_MIO_RESET_USB2_BRIDGE(14, 2),
UNIPHIER_MIO_RESET_USB2_BRIDGE(15, 3),
UNIPHIER_RESET_END,
};
......@@ -216,6 +196,12 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
UNIPHIER_RESET_END,
};
/* Analog signal amplifiers reset data */
static const struct uniphier_reset_data uniphier_ld11_adamv_reset_data[] = {
UNIPHIER_RESETX(0, 0x10, 6), /* EVEA */
UNIPHIER_RESET_END,
};
/* core implementaton */
struct uniphier_reset_priv {
struct reset_controller_dev rcdev;
......@@ -345,13 +331,9 @@ static int uniphier_reset_probe(struct platform_device *pdev)
static const struct of_device_id uniphier_reset_match[] = {
/* System reset */
{
.compatible = "socionext,uniphier-sld3-reset",
.data = uniphier_sld3_sys_reset_data,
},
{
.compatible = "socionext,uniphier-ld4-reset",
.data = uniphier_sld3_sys_reset_data,
.data = uniphier_ld4_sys_reset_data,
},
{
.compatible = "socionext,uniphier-pro4-reset",
......@@ -359,7 +341,7 @@ static const struct of_device_id uniphier_reset_match[] = {
},
{
.compatible = "socionext,uniphier-sld8-reset",
.data = uniphier_sld3_sys_reset_data,
.data = uniphier_ld4_sys_reset_data,
},
{
.compatible = "socionext,uniphier-pro5-reset",
......@@ -378,21 +360,17 @@ static const struct of_device_id uniphier_reset_match[] = {
.data = uniphier_ld20_sys_reset_data,
},
/* Media I/O reset, SD reset */
{
.compatible = "socionext,uniphier-sld3-mio-reset",
.data = uniphier_sld3_mio_reset_data,
},
{
.compatible = "socionext,uniphier-ld4-mio-reset",
.data = uniphier_sld3_mio_reset_data,
.data = uniphier_ld4_mio_reset_data,
},
{
.compatible = "socionext,uniphier-pro4-mio-reset",
.data = uniphier_sld3_mio_reset_data,
.data = uniphier_ld4_mio_reset_data,
},
{
.compatible = "socionext,uniphier-sld8-mio-reset",
.data = uniphier_sld3_mio_reset_data,
.data = uniphier_ld4_mio_reset_data,
},
{
.compatible = "socionext,uniphier-pro5-sd-reset",
......@@ -404,7 +382,7 @@ static const struct of_device_id uniphier_reset_match[] = {
},
{
.compatible = "socionext,uniphier-ld11-mio-reset",
.data = uniphier_sld3_mio_reset_data,
.data = uniphier_ld4_mio_reset_data,
},
{
.compatible = "socionext,uniphier-ld11-sd-reset",
......@@ -443,6 +421,15 @@ static const struct of_device_id uniphier_reset_match[] = {
.compatible = "socionext,uniphier-ld20-peri-reset",
.data = uniphier_pro4_peri_reset_data,
},
/* Analog signal amplifiers reset */
{
.compatible = "socionext,uniphier-ld11-adamv-reset",
.data = uniphier_ld11_adamv_reset_data,
},
{
.compatible = "socionext,uniphier-ld20-adamv-reset",
.data = uniphier_ld11_adamv_reset_data,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, uniphier_reset_match);
......
......@@ -55,7 +55,7 @@ static int zx2967_reset_deassert(struct reset_controller_dev *rcdev,
return zx2967_reset_act(rcdev, id, false);
}
static struct reset_control_ops zx2967_reset_ops = {
static const struct reset_control_ops zx2967_reset_ops = {
.assert = zx2967_reset_assert,
.deassert = zx2967_reset_deassert,
};
......
menu "SOC (System On Chip) specific Drivers"
source "drivers/soc/actions/Kconfig"
source "drivers/soc/amlogic/Kconfig"
source "drivers/soc/atmel/Kconfig"
source "drivers/soc/bcm/Kconfig"
source "drivers/soc/fsl/Kconfig"
......
......@@ -10,6 +10,7 @@ obj-$(CONFIG_MACH_DOVE) += dove/
obj-y += fsl/
obj-$(CONFIG_ARCH_MXC) += imx/
obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
obj-$(CONFIG_ARCH_MESON) += amlogic/
obj-$(CONFIG_ARCH_QCOM) += qcom/
obj-y += renesas/
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
......
menu "Amlogic SoC drivers"
config MESON_GX_SOCINFO
bool "Amlogic Meson GX SoC Information driver"
depends on ARCH_MESON || COMPILE_TEST
default ARCH_MESON
select SOC_BUS
help
Say yes to support decoding of Amlogic Meson GX SoC family
information about the type, package and version.
endmenu
obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
/*
* Copyright (c) 2017 BayLibre, SAS
* Author: Neil Armstrong <narmstrong@baylibre.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <linux/bitfield.h>
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#define AO_SEC_SD_CFG8 0xe0
#define AO_SEC_SOCINFO_OFFSET AO_SEC_SD_CFG8
#define SOCINFO_MAJOR GENMASK(31, 24)
#define SOCINFO_MINOR GENMASK(23, 16)
#define SOCINFO_PACK GENMASK(15, 8)
#define SOCINFO_MISC GENMASK(7, 0)
static const struct meson_gx_soc_id {
const char *name;
unsigned int id;
} soc_ids[] = {
{ "GXBB", 0x1f },
{ "GXTVBB", 0x20 },
{ "GXL", 0x21 },
{ "GXM", 0x22 },
{ "TXL", 0x23 },
};
static const struct meson_gx_package_id {
const char *name;
unsigned int major_id;
unsigned int pack_id;
} soc_packages[] = {
{ "S905", 0x1f, 0 },
{ "S905M", 0x1f, 0x20 },
{ "S905D", 0x21, 0 },
{ "S905X", 0x21, 0x80 },
{ "S905L", 0x21, 0xc0 },
{ "S905M2", 0x21, 0xe0 },
{ "S912", 0x22, 0 },
};
static inline unsigned int socinfo_to_major(u32 socinfo)
{
return FIELD_GET(SOCINFO_MAJOR, socinfo);
}
static inline unsigned int socinfo_to_minor(u32 socinfo)
{
return FIELD_GET(SOCINFO_MINOR, socinfo);
}
static inline unsigned int socinfo_to_pack(u32 socinfo)
{
return FIELD_GET(SOCINFO_PACK, socinfo);
}
static inline unsigned int socinfo_to_misc(u32 socinfo)
{
return FIELD_GET(SOCINFO_MISC, socinfo);
}
static const char *socinfo_to_package_id(u32 socinfo)
{
unsigned int pack = socinfo_to_pack(socinfo) & 0xf0;
unsigned int major = socinfo_to_major(socinfo);
int i;
for (i = 0 ; i < ARRAY_SIZE(soc_packages) ; ++i) {
if (soc_packages[i].major_id == major &&
soc_packages[i].pack_id == pack)
return soc_packages[i].name;
}
return "Unknown";
}
static const char *socinfo_to_soc_id(u32 socinfo)
{
unsigned int id = socinfo_to_major(socinfo);
int i;
for (i = 0 ; i < ARRAY_SIZE(soc_ids) ; ++i) {
if (soc_ids[i].id == id)
return soc_ids[i].name;
}
return "Unknown";
}
int __init meson_gx_socinfo_init(void)
{
struct soc_device_attribute *soc_dev_attr;
struct soc_device *soc_dev;
struct device_node *np;
struct regmap *regmap;
unsigned int socinfo;
struct device *dev;
int ret;
/* look up for chipid node */
np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gx-ao-secure");
if (!np)
return -ENODEV;
/* check if interface is enabled */
if (!of_device_is_available(np))
return -ENODEV;
/* check if chip-id is available */
if (!of_property_read_bool(np, "amlogic,has-chip-id"))
return -ENODEV;
/* node should be a syscon */
regmap = syscon_node_to_regmap(np);
of_node_put(np);
if (IS_ERR(regmap)) {
pr_err("%s: failed to get regmap\n", __func__);
return -ENODEV;
}
ret = regmap_read(regmap, AO_SEC_SOCINFO_OFFSET, &socinfo);
if (ret < 0)
return ret;
if (!socinfo) {
pr_err("%s: invalid chipid value\n", __func__);
return -EINVAL;
}
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENODEV;
soc_dev_attr->family = "Amlogic Meson";
np = of_find_node_by_path("/");
of_property_read_string(np, "model", &soc_dev_attr->machine);
of_node_put(np);
soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%x:%x - %x:%x",
socinfo_to_major(socinfo),
socinfo_to_minor(socinfo),
socinfo_to_pack(socinfo),
socinfo_to_misc(socinfo));
soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%s (%s)",
socinfo_to_soc_id(socinfo),
socinfo_to_package_id(socinfo));
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr->revision);
kfree_const(soc_dev_attr->soc_id);
kfree(soc_dev_attr);
return PTR_ERR(soc_dev);
}
dev = soc_device_to_device(soc_dev);
dev_info(dev, "Amlogic Meson %s Revision %x:%x (%x:%x) Detected\n",
soc_dev_attr->soc_id,
socinfo_to_major(socinfo),
socinfo_to_minor(socinfo),
socinfo_to_pack(socinfo),
socinfo_to_misc(socinfo));
return 0;
}
device_initcall(meson_gx_socinfo_init);
......@@ -177,8 +177,8 @@ static int fsl_bman_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "Can't get %s property 'IORESOURCE_MEM'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'IORESOURCE_MEM'\n",
node);
return -ENXIO;
}
bm_ccsr_start = devm_ioremap(dev, res->start, resource_size(res));
......@@ -205,14 +205,14 @@ static int fsl_bman_probe(struct platform_device *pdev)
err_irq = platform_get_irq(pdev, 0);
if (err_irq <= 0) {
dev_info(dev, "Can't get %s IRQ\n", node->full_name);
dev_info(dev, "Can't get %pOF IRQ\n", node);
return -ENODEV;
}
ret = devm_request_irq(dev, err_irq, bman_isr, IRQF_SHARED, "bman-err",
dev);
if (ret) {
dev_err(dev, "devm_request_irq() failed %d for '%s'\n",
ret, node->full_name);
dev_err(dev, "devm_request_irq() failed %d for '%pOF'\n",
ret, node);
return ret;
}
/* Disable Buffer Pool State Change */
......
......@@ -103,16 +103,14 @@ static int bman_portal_probe(struct platform_device *pdev)
addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
DPAA_PORTAL_CE);
if (!addr_phys[0]) {
dev_err(dev, "Can't get %s property 'reg::CE'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
return -ENXIO;
}
addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
DPAA_PORTAL_CI);
if (!addr_phys[1]) {
dev_err(dev, "Can't get %s property 'reg::CI'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
return -ENXIO;
}
......@@ -120,7 +118,7 @@ static int bman_portal_probe(struct platform_device *pdev)
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(dev, "Can't get %s IRQ'\n", node->full_name);
dev_err(dev, "Can't get %pOF IRQ'\n", node);
return -ENXIO;
}
pcfg->irq = irq;
......
......@@ -695,8 +695,8 @@ static int fsl_qman_probe(struct platform_device *pdev)
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(dev, "Can't get %s property 'IORESOURCE_MEM'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'IORESOURCE_MEM'\n",
node);
return -ENXIO;
}
qm_ccsr_start = devm_ioremap(dev, res->start, resource_size(res));
......@@ -740,15 +740,15 @@ static int fsl_qman_probe(struct platform_device *pdev)
err_irq = platform_get_irq(pdev, 0);
if (err_irq <= 0) {
dev_info(dev, "Can't get %s property 'interrupts'\n",
node->full_name);
dev_info(dev, "Can't get %pOF property 'interrupts'\n",
node);
return -ENODEV;
}
ret = devm_request_irq(dev, err_irq, qman_isr, IRQF_SHARED, "qman-err",
dev);
if (ret) {
dev_err(dev, "devm_request_irq() failed %d for '%s'\n",
ret, node->full_name);
dev_err(dev, "devm_request_irq() failed %d for '%pOF'\n",
ret, node);
return ret;
}
......
......@@ -237,30 +237,27 @@ static int qman_portal_probe(struct platform_device *pdev)
addr_phys[0] = platform_get_resource(pdev, IORESOURCE_MEM,
DPAA_PORTAL_CE);
if (!addr_phys[0]) {
dev_err(dev, "Can't get %s property 'reg::CE'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node);
return -ENXIO;
}
addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM,
DPAA_PORTAL_CI);
if (!addr_phys[1]) {
dev_err(dev, "Can't get %s property 'reg::CI'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node);
return -ENXIO;
}
err = of_property_read_u32(node, "cell-index", &val);
if (err) {
dev_err(dev, "Can't get %s property 'cell-index'\n",
node->full_name);
dev_err(dev, "Can't get %pOF property 'cell-index'\n", node);
return err;
}
pcfg->channel = val;
pcfg->cpu = -1;
irq = platform_get_irq(pdev, 0);
if (irq <= 0) {
dev_err(dev, "Can't get %s IRQ\n", node->full_name);
dev_err(dev, "Can't get %pOF IRQ\n", node);
return -ENXIO;
}
pcfg->irq = irq;
......
......@@ -304,8 +304,8 @@ static int __init qe_add_gpiochips(void)
goto err;
continue;
err:
pr_err("%s: registration failed with status %d\n",
np->full_name, ret);
pr_err("%pOF: registration failed with status %d\n",
np, ret);
kfree(qe_gc);
/* try others anyway */
}
......
......@@ -1067,7 +1067,7 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
.init_soc_specific = pwrap_mt2701_init_soc_specific,
};
static struct pmic_wrapper_type pwrap_mt8135 = {
static const struct pmic_wrapper_type pwrap_mt8135 = {
.regs = mt8135_regs,
.type = PWRAP_MT8135,
.arb_en_all = 0x1ff,
......@@ -1079,7 +1079,7 @@ static struct pmic_wrapper_type pwrap_mt8135 = {
.init_soc_specific = pwrap_mt8135_init_soc_specific,
};
static struct pmic_wrapper_type pwrap_mt8173 = {
static const struct pmic_wrapper_type pwrap_mt8173 = {
.regs = mt8173_regs,
.type = PWRAP_MT8173,
.arb_en_all = 0x3f,
......@@ -1091,7 +1091,7 @@ static struct pmic_wrapper_type pwrap_mt8173 = {
.init_soc_specific = pwrap_mt8173_init_soc_specific,
};
static struct of_device_id of_pwrap_match_tbl[] = {
static const struct of_device_id of_pwrap_match_tbl[] = {
{
.compatible = "mediatek,mt2701-pwrap",
.data = &pwrap_mt2701,
......@@ -1233,8 +1233,8 @@ static int pwrap_probe(struct platform_device *pdev)
ret = of_platform_populate(np, NULL, NULL, wrp->dev);
if (ret) {
dev_dbg(wrp->dev, "failed to create child devices at %s\n",
np->full_name);
dev_dbg(wrp->dev, "failed to create child devices at %pOF\n",
np);
goto err_out2;
}
......
......@@ -22,6 +22,7 @@
#include <dt-bindings/power/mt2701-power.h>
#include <dt-bindings/power/mt6797-power.h>
#include <dt-bindings/power/mt7622-power.h>
#include <dt-bindings/power/mt8173-power.h>
#define SPM_VDE_PWR_CON 0x0210
......@@ -39,6 +40,11 @@
#define SPM_MFG_2D_PWR_CON 0x02c0
#define SPM_MFG_ASYNC_PWR_CON 0x02c4
#define SPM_USB_PWR_CON 0x02cc
#define SPM_ETHSYS_PWR_CON 0x02e0 /* MT7622 */
#define SPM_HIF0_PWR_CON 0x02e4 /* MT7622 */
#define SPM_HIF1_PWR_CON 0x02e8 /* MT7622 */
#define SPM_WB_PWR_CON 0x02ec /* MT7622 */
#define SPM_PWR_STATUS 0x060c
#define SPM_PWR_STATUS_2ND 0x0610
......@@ -64,6 +70,10 @@
#define PWR_STATUS_MFG_ASYNC BIT(23)
#define PWR_STATUS_AUDIO BIT(24)
#define PWR_STATUS_USB BIT(25)
#define PWR_STATUS_ETHSYS BIT(24) /* MT7622 */
#define PWR_STATUS_HIF0 BIT(25) /* MT7622 */
#define PWR_STATUS_HIF1 BIT(26) /* MT7622 */
#define PWR_STATUS_WB BIT(27) /* MT7622 */
enum clk_id {
CLK_NONE,
......@@ -73,6 +83,7 @@ enum clk_id {
CLK_VENC_LT,
CLK_ETHIF,
CLK_VDEC,
CLK_HIFSEL,
CLK_MAX,
};
......@@ -84,6 +95,7 @@ static const char * const clk_names[] = {
"venc_lt",
"ethif",
"vdec",
"hif_sel",
NULL,
};
......@@ -124,6 +136,19 @@ struct scp {
struct scp_ctrl_reg ctrl_reg;
};
struct scp_subdomain {
int origin;
int subdomain;
};
struct scp_soc_data {
const struct scp_domain_data *domains;
int num_domains;
const struct scp_subdomain *subdomains;
int num_subdomains;
const struct scp_ctrl_reg regs;
};
static int scpsys_domain_is_on(struct scp_domain *scpd)
{
struct scp *scp = scpd->scp;
......@@ -357,7 +382,7 @@ static void init_clks(struct platform_device *pdev, struct clk **clk)
static struct scp *init_scp(struct platform_device *pdev,
const struct scp_domain_data *scp_domain_data, int num,
struct scp_ctrl_reg *scp_ctrl_reg)
const struct scp_ctrl_reg *scp_ctrl_reg)
{
struct genpd_onecell_data *pd_data;
struct resource *res;
......@@ -565,26 +590,6 @@ static const struct scp_domain_data scp_domain_data_mt2701[] = {
},
};
#define NUM_DOMAINS_MT2701 ARRAY_SIZE(scp_domain_data_mt2701)
static int __init scpsys_probe_mt2701(struct platform_device *pdev)
{
struct scp *scp;
struct scp_ctrl_reg scp_reg;
scp_reg.pwr_sta_offs = SPM_PWR_STATUS;
scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND;
scp = init_scp(pdev, scp_domain_data_mt2701, NUM_DOMAINS_MT2701,
&scp_reg);
if (IS_ERR(scp))
return PTR_ERR(scp);
mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT2701);
return 0;
}
/*
* MT6797 power domain support
*/
......@@ -649,51 +654,62 @@ static const struct scp_domain_data scp_domain_data_mt6797[] = {
},
};
#define NUM_DOMAINS_MT6797 ARRAY_SIZE(scp_domain_data_mt6797)
#define SPM_PWR_STATUS_MT6797 0x0180
#define SPM_PWR_STATUS_2ND_MT6797 0x0184
static int __init scpsys_probe_mt6797(struct platform_device *pdev)
{
struct scp *scp;
struct genpd_onecell_data *pd_data;
int ret;
struct scp_ctrl_reg scp_reg;
scp_reg.pwr_sta_offs = SPM_PWR_STATUS_MT6797;
scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797;
scp = init_scp(pdev, scp_domain_data_mt6797, NUM_DOMAINS_MT6797,
&scp_reg);
if (IS_ERR(scp))
return PTR_ERR(scp);
mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT6797);
pd_data = &scp->pd_data;
ret = pm_genpd_add_subdomain(pd_data->domains[MT6797_POWER_DOMAIN_MM],
pd_data->domains[MT6797_POWER_DOMAIN_VDEC]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
ret = pm_genpd_add_subdomain(pd_data->domains[MT6797_POWER_DOMAIN_MM],
pd_data->domains[MT6797_POWER_DOMAIN_ISP]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
ret = pm_genpd_add_subdomain(pd_data->domains[MT6797_POWER_DOMAIN_MM],
pd_data->domains[MT6797_POWER_DOMAIN_VENC]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
static const struct scp_subdomain scp_subdomain_mt6797[] = {
{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VDEC},
{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_ISP},
{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_VENC},
{MT6797_POWER_DOMAIN_MM, MT6797_POWER_DOMAIN_MJC},
};
ret = pm_genpd_add_subdomain(pd_data->domains[MT6797_POWER_DOMAIN_MM],
pd_data->domains[MT6797_POWER_DOMAIN_MJC]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
/*
* MT7622 power domain support
*/
return 0;
}
static const struct scp_domain_data scp_domain_data_mt7622[] = {
[MT7622_POWER_DOMAIN_ETHSYS] = {
.name = "ethsys",
.sta_mask = PWR_STATUS_ETHSYS,
.ctl_offs = SPM_ETHSYS_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_NONE},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_ETHSYS,
.active_wakeup = true,
},
[MT7622_POWER_DOMAIN_HIF0] = {
.name = "hif0",
.sta_mask = PWR_STATUS_HIF0,
.ctl_offs = SPM_HIF0_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_HIFSEL},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF0,
.active_wakeup = true,
},
[MT7622_POWER_DOMAIN_HIF1] = {
.name = "hif1",
.sta_mask = PWR_STATUS_HIF1,
.ctl_offs = SPM_HIF1_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.clk_id = {CLK_HIFSEL},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_HIF1,
.active_wakeup = true,
},
[MT7622_POWER_DOMAIN_WB] = {
.name = "wb",
.sta_mask = PWR_STATUS_WB,
.ctl_offs = SPM_WB_PWR_CON,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.clk_id = {CLK_NONE},
.bus_prot_mask = MT7622_TOP_AXI_PROT_EN_WB,
.active_wakeup = true,
},
};
/*
* MT8173 power domain support
......@@ -789,39 +805,50 @@ static const struct scp_domain_data scp_domain_data_mt8173[] = {
},
};
#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173)
static int __init scpsys_probe_mt8173(struct platform_device *pdev)
{
struct scp *scp;
struct genpd_onecell_data *pd_data;
int ret;
struct scp_ctrl_reg scp_reg;
scp_reg.pwr_sta_offs = SPM_PWR_STATUS;
scp_reg.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND;
scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173,
&scp_reg);
if (IS_ERR(scp))
return PTR_ERR(scp);
mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173);
static const struct scp_subdomain scp_subdomain_mt8173[] = {
{MT8173_POWER_DOMAIN_MFG_ASYNC, MT8173_POWER_DOMAIN_MFG_2D},
{MT8173_POWER_DOMAIN_MFG_2D, MT8173_POWER_DOMAIN_MFG},
};
pd_data = &scp->pd_data;
static const struct scp_soc_data mt2701_data = {
.domains = scp_domain_data_mt2701,
.num_domains = ARRAY_SIZE(scp_domain_data_mt2701),
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
}
};
ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
static const struct scp_soc_data mt6797_data = {
.domains = scp_domain_data_mt6797,
.num_domains = ARRAY_SIZE(scp_domain_data_mt6797),
.subdomains = scp_subdomain_mt6797,
.num_subdomains = ARRAY_SIZE(scp_subdomain_mt6797),
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS_MT6797,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797
}
};
ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D],
pd_data->domains[MT8173_POWER_DOMAIN_MFG]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
static const struct scp_soc_data mt7622_data = {
.domains = scp_domain_data_mt7622,
.num_domains = ARRAY_SIZE(scp_domain_data_mt7622),
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
}
};
return 0;
}
static const struct scp_soc_data mt8173_data = {
.domains = scp_domain_data_mt8173,
.num_domains = ARRAY_SIZE(scp_domain_data_mt8173),
.subdomains = scp_subdomain_mt8173,
.num_subdomains = ARRAY_SIZE(scp_subdomain_mt8173),
.regs = {
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND
}
};
/*
* scpsys driver init
......@@ -830,13 +857,16 @@ static int __init scpsys_probe_mt8173(struct platform_device *pdev)
static const struct of_device_id of_scpsys_match_tbl[] = {
{
.compatible = "mediatek,mt2701-scpsys",
.data = scpsys_probe_mt2701,
.data = &mt2701_data,
}, {
.compatible = "mediatek,mt6797-scpsys",
.data = scpsys_probe_mt6797,
.data = &mt6797_data,
}, {
.compatible = "mediatek,mt7622-scpsys",
.data = &mt7622_data,
}, {
.compatible = "mediatek,mt8173-scpsys",
.data = scpsys_probe_mt8173,
.data = &mt8173_data,
}, {
/* sentinel */
}
......@@ -844,16 +874,33 @@ static const struct of_device_id of_scpsys_match_tbl[] = {
static int scpsys_probe(struct platform_device *pdev)
{
int (*probe)(struct platform_device *);
const struct of_device_id *of_id;
const struct of_device_id *match;
const struct scp_subdomain *sd;
const struct scp_soc_data *soc;
struct scp *scp;
struct genpd_onecell_data *pd_data;
int i, ret;
of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node);
if (!of_id || !of_id->data)
return -EINVAL;
match = of_match_device(of_scpsys_match_tbl, &pdev->dev);
soc = (const struct scp_soc_data *)match->data;
scp = init_scp(pdev, soc->domains, soc->num_domains, &soc->regs);
if (IS_ERR(scp))
return PTR_ERR(scp);
probe = of_id->data;
mtk_register_power_domains(pdev, scp, soc->num_domains);
return probe(pdev);
pd_data = &scp->pd_data;
for (i = 0, sd = soc->subdomains ; i < soc->num_subdomains ; i++) {
ret = pm_genpd_add_subdomain(pd_data->domains[sd->origin],
pd_data->domains[sd->subdomain]);
if (ret && IS_ENABLED(CONFIG_PM))
dev_err(&pdev->dev, "Failed to add subdomain: %d\n",
ret);
}
return 0;
}
static struct platform_driver scpsys_drv = {
......
#
# QCOM Soc drivers
#
menu "Qualcomm SoC drivers"
config QCOM_GLINK_SSR
tristate "Qualcomm Glink SSR driver"
depends on RPMSG
......@@ -83,3 +85,5 @@ config QCOM_WCNSS_CTRL
help
Client driver for the WCNSS_CTRL SMD channel, used to download nv
firmware to a newly booted WCNSS chip.
endmenu
......@@ -178,14 +178,13 @@ int qcom_mdt_load(struct device *dev, const struct firmware *fw,
if (phdr->p_filesz) {
sprintf(fw_name + fw_name_len - 3, "b%02d", i);
ret = request_firmware(&seg_fw, fw_name, dev);
ret = request_firmware_into_buf(&seg_fw, fw_name, dev,
ptr, phdr->p_filesz);
if (ret) {
dev_err(dev, "failed to load %s\n", fw_name);
break;
}
memcpy(ptr, seg_fw->data, seg_fw->size);
release_firmware(seg_fw);
}
......
......@@ -496,7 +496,8 @@ static int qcom_smsm_probe(struct platform_device *pdev)
if (!smsm->hosts)
return -ENOMEM;
local_node = of_find_node_with_property(pdev->dev.of_node, "#qcom,smem-state-cells");
local_node = of_find_node_with_property(of_node_get(pdev->dev.of_node),
"#qcom,smem-state-cells");
if (!local_node) {
dev_err(&pdev->dev, "no state entry\n");
return -EINVAL;
......
......@@ -347,6 +347,7 @@ static const struct of_device_id wcnss_ctrl_of_match[] = {
{ .compatible = "qcom,wcnss", },
{}
};
MODULE_DEVICE_TABLE(of, wcnss_ctrl_of_match);
static struct rpmsg_driver wcnss_ctrl_driver = {
.probe = wcnss_ctrl_probe,
......
......@@ -3,7 +3,7 @@ config SOC_RENESAS
default y if ARCH_RENESAS
select SOC_BUS
select RST_RCAR if ARCH_RCAR_GEN1 || ARCH_RCAR_GEN2 || \
ARCH_R8A7795 || ARCH_R8A7796
ARCH_R8A7795 || ARCH_R8A7796 || ARCH_R8A77995
select SYSC_R8A7743 if ARCH_R8A7743
select SYSC_R8A7745 if ARCH_R8A7745
select SYSC_R8A7779 if ARCH_R8A7779
......@@ -13,6 +13,7 @@ config SOC_RENESAS
select SYSC_R8A7794 if ARCH_R8A7794
select SYSC_R8A7795 if ARCH_R8A7795
select SYSC_R8A7796 if ARCH_R8A7796
select SYSC_R8A77995 if ARCH_R8A77995
if SOC_RENESAS
......@@ -53,6 +54,10 @@ config SYSC_R8A7796
bool "R-Car M3-W System Controller support" if COMPILE_TEST
select SYSC_RCAR
config SYSC_R8A77995
bool "R-Car D3 System Controller support" if COMPILE_TEST
select SYSC_RCAR
# Family
config RST_RCAR
bool "R-Car Reset Controller support" if COMPILE_TEST
......
......@@ -11,6 +11,7 @@ obj-$(CONFIG_SYSC_R8A7792) += r8a7792-sysc.o
obj-$(CONFIG_SYSC_R8A7794) += r8a7794-sysc.o
obj-$(CONFIG_SYSC_R8A7795) += r8a7795-sysc.o
obj-$(CONFIG_SYSC_R8A7796) += r8a7796-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
# Family
obj-$(CONFIG_RST_RCAR) += rcar-rst.o
......
/*
* 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>
#include <linux/kernel.h>
#include <linux/sys_soc.h>
#include <dt-bindings/power/r8a77995-sysc.h>
#include "rcar-sysc.h"
static struct rcar_sysc_area r8a77995_areas[] __initdata = {
{ "always-on", 0, 0, R8A77995_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
{ "ca53-scu", 0x140, 0, R8A77995_PD_CA53_SCU, R8A77995_PD_ALWAYS_ON,
PD_SCU },
{ "ca53-cpu0", 0x200, 0, R8A77995_PD_CA53_CPU0, R8A77995_PD_CA53_SCU,
PD_CPU_NOCR },
};
const struct rcar_sysc_info r8a77995_sysc_info __initconst = {
.areas = r8a77995_areas,
.num_areas = ARRAY_SIZE(r8a77995_areas),
};
......@@ -41,6 +41,7 @@ static const struct of_device_id rcar_rst_matches[] __initconst = {
/* R-Car Gen3 is handled like R-Car Gen2 */
{ .compatible = "renesas,r8a7795-rst", .data = &rcar_rst_gen2 },
{ .compatible = "renesas,r8a7796-rst", .data = &rcar_rst_gen2 },
{ .compatible = "renesas,r8a77995-rst", .data = &rcar_rst_gen2 },
{ /* sentinel */ }
};
......@@ -61,7 +62,7 @@ static int __init rcar_rst_init(void)
base = of_iomap(np, 0);
if (!base) {
pr_warn("%s: Cannot map regs\n", np->full_name);
pr_warn("%pOF: Cannot map regs\n", np);
error = -ENOMEM;
goto out_put;
}
......@@ -70,7 +71,7 @@ static int __init rcar_rst_init(void)
cfg = match->data;
saved_mode = ioread32(base + cfg->modemr);
pr_debug("%s: MODE = 0x%08x\n", np->full_name, saved_mode);
pr_debug("%pOF: MODE = 0x%08x\n", np, saved_mode);
out_put:
of_node_put(np);
......
......@@ -283,6 +283,9 @@ static const struct of_device_id rcar_sysc_matches[] = {
#endif
#ifdef CONFIG_SYSC_R8A7796
{ .compatible = "renesas,r8a7796-sysc", .data = &r8a7796_sysc_info },
#endif
#ifdef CONFIG_SYSC_R8A77995
{ .compatible = "renesas,r8a77995-sysc", .data = &r8a77995_sysc_info },
#endif
{ /* sentinel */ }
};
......@@ -323,7 +326,7 @@ static int __init rcar_sysc_pd_init(void)
base = of_iomap(np, 0);
if (!base) {
pr_warn("%s: Cannot map regs\n", np->full_name);
pr_warn("%pOF: Cannot map regs\n", np);
error = -ENOMEM;
goto out_put;
}
......@@ -348,13 +351,13 @@ static int __init rcar_sysc_pd_init(void)
*/
syscimr = ioread32(base + SYSCIMR);
syscimr |= syscier;
pr_debug("%s: syscimr = 0x%08x\n", np->full_name, syscimr);
pr_debug("%pOF: syscimr = 0x%08x\n", np, syscimr);
iowrite32(syscimr, base + SYSCIMR);
/*
* SYSC needs all interrupt sources enabled to control power.
*/
pr_debug("%s: syscier = 0x%08x\n", np->full_name, syscier);
pr_debug("%pOF: syscier = 0x%08x\n", np, syscier);
iowrite32(syscier, base + SYSCIER);
for (i = 0; i < info->num_areas; i++) {
......
......@@ -58,6 +58,7 @@ extern const struct rcar_sysc_info r8a7792_sysc_info;
extern const struct rcar_sysc_info r8a7794_sysc_info;
extern const struct rcar_sysc_info r8a7795_sysc_info;
extern const struct rcar_sysc_info r8a7796_sysc_info;
extern const struct rcar_sysc_info r8a77995_sysc_info;
/*
......
......@@ -144,6 +144,11 @@ static const struct renesas_soc soc_rcar_m3_w __initconst __maybe_unused = {
.id = 0x52,
};
static const struct renesas_soc soc_rcar_d3 __initconst __maybe_unused = {
.family = &fam_rcar_gen3,
.id = 0x58,
};
static const struct renesas_soc soc_shmobile_ag5 __initconst __maybe_unused = {
.family = &fam_shmobile,
.id = 0x37,
......@@ -199,6 +204,9 @@ static const struct of_device_id renesas_socs[] __initconst = {
#ifdef CONFIG_ARCH_R8A7796
{ .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w },
#endif
#ifdef CONFIG_ARCH_R8A77995
{ .compatible = "renesas,r8a77995", .data = &soc_rcar_d3 },
#endif
#ifdef CONFIG_ARCH_SH73A0
{ .compatible = "renesas,sh73a0", .data = &soc_shmobile_ag5 },
#endif
......
......@@ -54,6 +54,17 @@ static const struct rockchip_grf_info rk3288_grf __initconst = {
.num_values = ARRAY_SIZE(rk3288_defaults),
};
#define RK3328_GRF_SOC_CON4 0x410
static const struct rockchip_grf_value rk3328_defaults[] __initconst = {
{ "jtag switching", RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, 1, 12) },
};
static const struct rockchip_grf_info rk3328_grf __initconst = {
.values = rk3328_defaults,
.num_values = ARRAY_SIZE(rk3328_defaults),
};
#define RK3368_GRF_SOC_CON15 0x43c
static const struct rockchip_grf_value rk3368_defaults[] __initconst = {
......@@ -83,6 +94,9 @@ static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
}, {
.compatible = "rockchip,rk3288-grf",
.data = (void *)&rk3288_grf,
}, {
.compatible = "rockchip,rk3328-grf",
.data = (void *)&rk3328_grf,
}, {
.compatible = "rockchip,rk3368-grf",
.data = (void *)&rk3368_grf,
......
......@@ -20,6 +20,7 @@
#include <linux/mfd/syscon.h>
#include <dt-bindings/power/rk3288-power.h>
#include <dt-bindings/power/rk3328-power.h>
#include <dt-bindings/power/rk3366-power.h>
#include <dt-bindings/power/rk3368-power.h>
#include <dt-bindings/power/rk3399-power.h>
......@@ -730,6 +731,16 @@ static const struct rockchip_domain_info rk3328_pm_domains[] = {
[RK3328_PD_VPU] = DOMAIN_RK3328(-1, 9, 9, false),
};
static const struct rockchip_domain_info rk3366_pm_domains[] = {
[RK3366_PD_PERI] = DOMAIN_RK3368(10, 10, 6, true),
[RK3366_PD_VIO] = DOMAIN_RK3368(14, 14, 8, false),
[RK3366_PD_VIDEO] = DOMAIN_RK3368(13, 13, 7, false),
[RK3366_PD_RKVDEC] = DOMAIN_RK3368(11, 11, 7, false),
[RK3366_PD_WIFIBT] = DOMAIN_RK3368(8, 8, 9, false),
[RK3366_PD_VPU] = DOMAIN_RK3368(12, 12, 7, false),
[RK3366_PD_GPU] = DOMAIN_RK3368(15, 15, 2, false),
};
static const struct rockchip_domain_info rk3368_pm_domains[] = {
[RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true),
[RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false),
......@@ -794,6 +805,23 @@ static const struct rockchip_pmu_info rk3328_pmu = {
.domain_info = rk3328_pm_domains,
};
static const struct rockchip_pmu_info rk3366_pmu = {
.pwr_offset = 0x0c,
.status_offset = 0x10,
.req_offset = 0x3c,
.idle_offset = 0x40,
.ack_offset = 0x40,
.core_pwrcnt_offset = 0x48,
.gpu_pwrcnt_offset = 0x50,
.core_power_transition_time = 24,
.gpu_power_transition_time = 24,
.num_domains = ARRAY_SIZE(rk3366_pm_domains),
.domain_info = rk3366_pm_domains,
};
static const struct rockchip_pmu_info rk3368_pmu = {
.pwr_offset = 0x0c,
.status_offset = 0x10,
......@@ -833,6 +861,10 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
.compatible = "rockchip,rk3328-power-controller",
.data = (void *)&rk3328_pmu,
},
{
.compatible = "rockchip,rk3366-power-controller",
.data = (void *)&rk3366_pmu,
},
{
.compatible = "rockchip,rk3368-power-controller",
.data = (void *)&rk3368_pmu,
......
......@@ -147,7 +147,7 @@ static __init const char *exynos_get_domain_name(struct device_node *node)
const char *name;
if (of_property_read_string(node, "label", &name) < 0)
name = strrchr(node->full_name, '/') + 1;
name = kbasename(node->full_name);
return kstrdup_const(name, GFP_KERNEL);
}
......@@ -237,11 +237,11 @@ static __init int exynos4_pm_init_power_domain(void)
continue;
if (of_genpd_add_subdomain(&parent, &child))
pr_warn("%s failed to add subdomain: %s\n",
parent.np->full_name, child.np->full_name);
pr_warn("%pOF failed to add subdomain: %pOF\n",
parent.np, child.np);
else
pr_info("%s has as child subdomain: %s.\n",
parent.np->full_name, child.np->full_name);
pr_info("%pOF has as child subdomain: %pOF.\n",
parent.np, child.np);
}
return 0;
......
......@@ -23,6 +23,7 @@
struct sunxi_sram_func {
char *func;
u8 val;
u32 reg_val;
};
struct sunxi_sram_data {
......@@ -39,10 +40,11 @@ struct sunxi_sram_desc {
bool claimed;
};
#define SUNXI_SRAM_MAP(_val, _func) \
#define SUNXI_SRAM_MAP(_reg_val, _val, _func) \
{ \
.func = _func, \
.val = _val, \
.reg_val = _reg_val, \
}
#define SUNXI_SRAM_DATA(_name, _reg, _off, _width, ...) \
......@@ -57,14 +59,20 @@ struct sunxi_sram_desc {
static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
.data = SUNXI_SRAM_DATA("A3-A4", 0x4, 0x4, 2,
SUNXI_SRAM_MAP(0, "cpu"),
SUNXI_SRAM_MAP(1, "emac")),
SUNXI_SRAM_MAP(0, 0, "cpu"),
SUNXI_SRAM_MAP(1, 1, "emac")),
};
static struct sunxi_sram_desc sun4i_a10_sram_d = {
.data = SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
SUNXI_SRAM_MAP(0, "cpu"),
SUNXI_SRAM_MAP(1, "usb-otg")),
SUNXI_SRAM_MAP(0, 0, "cpu"),
SUNXI_SRAM_MAP(1, 1, "usb-otg")),
};
static struct sunxi_sram_desc sun50i_a64_sram_c = {
.data = SUNXI_SRAM_DATA("C", 0x4, 24, 1,
SUNXI_SRAM_MAP(0, 1, "cpu"),
SUNXI_SRAM_MAP(1, 0, "de2")),
};
static const struct of_device_id sunxi_sram_dt_ids[] = {
......@@ -76,6 +84,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
.compatible = "allwinner,sun4i-a10-sram-d",
.data = &sun4i_a10_sram_d.data,
},
{
.compatible = "allwinner,sun50i-a64-sram-c",
.data = &sun50i_a64_sram_c.data,
},
{}
};
......@@ -121,7 +133,8 @@ static int sunxi_sram_show(struct seq_file *s, void *data)
for (func = sram_data->func; func->func; func++) {
seq_printf(s, "\t\t%s%c\n", func->func,
func->val == val ? '*' : ' ');
func->reg_val == val ?
'*' : ' ');
}
}
......@@ -149,10 +162,13 @@ static inline struct sunxi_sram_desc *to_sram_desc(const struct sunxi_sram_data
}
static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *node,
unsigned int *value)
unsigned int *reg_value)
{
const struct of_device_id *match;
const struct sunxi_sram_data *data;
struct sunxi_sram_func *func;
struct of_phandle_args args;
u8 val;
int ret;
ret = of_parse_phandle_with_fixed_args(node, "allwinner,sram", 1, 0,
......@@ -165,8 +181,7 @@ static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *nod
goto err;
}
if (value)
*value = args.args[0];
val = args.args[0];
match = of_match_node(sunxi_sram_dt_ids, args.np);
if (!match) {
......@@ -174,6 +189,26 @@ static const struct sunxi_sram_data *sunxi_sram_of_parse(struct device_node *nod
goto err;
}
data = match->data;
if (!data) {
ret = -EINVAL;
goto err;
};
for (func = data->func; func->func; func++) {
if (val == func->val) {
if (reg_value)
*reg_value = func->reg_val;
break;
}
}
if (!func->func) {
ret = -EINVAL;
goto err;
}
of_node_put(args.np);
return match->data;
......@@ -190,6 +225,9 @@ int sunxi_sram_claim(struct device *dev)
u32 val, mask;
if (IS_ERR(base))
return PTR_ERR(base);
if (!base)
return -EPROBE_DEFER;
if (!dev || !dev->of_node)
......@@ -267,6 +305,7 @@ static int sunxi_sram_probe(struct platform_device *pdev)
static const struct of_device_id sunxi_sram_dt_match[] = {
{ .compatible = "allwinner,sun4i-a10-sram-controller" },
{ .compatible = "allwinner,sun50i-a64-sram-controller" },
{ },
};
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
......
......@@ -107,6 +107,11 @@ config ARCH_TEGRA_186_SOC
endif
endif
config SOC_TEGRA_FUSE
def_bool y
depends on ARCH_TEGRA
select SOC_BUS
config SOC_TEGRA_FLOWCTRL
bool
......
......@@ -19,10 +19,12 @@
#include <linux/device.h>
#include <linux/kobject.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#include <soc/tegra/common.h>
#include <soc/tegra/fuse.h>
......@@ -210,6 +212,31 @@ static void tegra_enable_fuse_clk(void __iomem *base)
writel(reg, base + 0x14);
}
struct device * __init tegra_soc_device_register(void)
{
struct soc_device_attribute *attr;
struct soc_device *dev;
attr = kzalloc(sizeof(*attr), GFP_KERNEL);
if (!attr)
return NULL;
attr->family = kasprintf(GFP_KERNEL, "Tegra");
attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_sku_info.revision);
attr->soc_id = kasprintf(GFP_KERNEL, "%u", tegra_get_chip_id());
dev = soc_device_register(attr);
if (IS_ERR(dev)) {
kfree(attr->soc_id);
kfree(attr->revision);
kfree(attr->family);
kfree(attr);
return ERR_CAST(dev);
}
return soc_device_to_device(dev);
}
static int __init tegra_init_fuse(void)
{
const struct of_device_id *match;
......@@ -311,6 +338,31 @@ static int __init tegra_init_fuse(void)
pr_debug("Tegra CPU Speedo ID %d, SoC Speedo ID %d\n",
tegra_sku_info.cpu_speedo_id, tegra_sku_info.soc_speedo_id);
return 0;
}
early_initcall(tegra_init_fuse);
#ifdef CONFIG_ARM64
static int __init tegra_init_soc(void)
{
struct device_node *np;
struct device *soc;
/* make sure we're running on Tegra */
np = of_find_matching_node(NULL, tegra_fuse_match);
if (!np)
return 0;
of_node_put(np);
soc = tegra_soc_device_register();
if (IS_ERR(soc)) {
pr_err("failed to register SoC device: %ld\n", PTR_ERR(soc));
return PTR_ERR(soc);
}
return 0;
}
device_initcall(tegra_init_soc);
#endif
......@@ -918,10 +918,8 @@ static void tegra_powergate_init(struct tegra_pmc *pmc,
if (!np)
return;
for_each_child_of_node(np, child) {
for_each_child_of_node(np, child)
tegra_powergate_add(pmc, child);
of_node_put(child);
}
of_node_put(np);
}
......
......@@ -224,13 +224,14 @@ static void optee_release(struct tee_context *ctx)
if (!IS_ERR(shm)) {
arg = tee_shm_get_va(shm, 0);
/*
* If va2pa fails for some reason, we can't call
* optee_close_session(), only free the memory. Secure OS
* will leak sessions and finally refuse more sessions, but
* we will at least let normal world reclaim its memory.
* If va2pa fails for some reason, we can't call into
* secure world, only free the memory. Secure OS will leak
* sessions and finally refuse more sessions, but we will
* at least let normal world reclaim its memory.
*/
if (!IS_ERR(arg))
tee_shm_va2pa(shm, arg, &parg);
if (tee_shm_va2pa(shm, arg, &parg))
arg = NULL; /* prevent usage of parg below */
}
list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
......@@ -258,7 +259,7 @@ static void optee_release(struct tee_context *ctx)
}
}
static struct tee_driver_ops optee_ops = {
static const struct tee_driver_ops optee_ops = {
.get_version = optee_get_version,
.open = optee_open,
.release = optee_release,
......@@ -268,13 +269,13 @@ static struct tee_driver_ops optee_ops = {
.cancel_req = optee_cancel_req,
};
static struct tee_desc optee_desc = {
static const struct tee_desc optee_desc = {
.name = DRIVER_NAME "-clnt",
.ops = &optee_ops,
.owner = THIS_MODULE,
};
static struct tee_driver_ops optee_supp_ops = {
static const struct tee_driver_ops optee_supp_ops = {
.get_version = optee_get_version,
.open = optee_open,
.release = optee_release,
......@@ -282,7 +283,7 @@ static struct tee_driver_ops optee_supp_ops = {
.supp_send = optee_supp_send,
};
static struct tee_desc optee_supp_desc = {
static const struct tee_desc optee_supp_desc = {
.name = DRIVER_NAME "-supp",
.ops = &optee_supp_ops,
.owner = THIS_MODULE,
......
......@@ -298,7 +298,7 @@ struct optee_smc_disable_shm_cache_result {
OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
/*
* Resume from RPC (for example after processing an IRQ)
* Resume from RPC (for example after processing a foreign interrupt)
*
* Call register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
......@@ -383,19 +383,19 @@ struct optee_smc_disable_shm_cache_result {
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
/*
* Deliver an IRQ in normal world.
* Deliver foreign interrupt to normal world.
*
* "Call" register usage:
* a0 OPTEE_SMC_RETURN_RPC_IRQ
* a0 OPTEE_SMC_RETURN_RPC_FOREIGN_INTR
* a1-7 Resume information, must be preserved
*
* "Return" register usage:
* a0 SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
* a1-7 Preserved
*/
#define OPTEE_SMC_RPC_FUNC_IRQ 4
#define OPTEE_SMC_RETURN_RPC_IRQ \
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_IRQ)
#define OPTEE_SMC_RPC_FUNC_FOREIGN_INTR 4
#define OPTEE_SMC_RETURN_RPC_FOREIGN_INTR \
OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FOREIGN_INTR)
/*
* Do an RPC request. The supplied struct optee_msg_arg tells which
......
......@@ -140,11 +140,8 @@ static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
msec_to_wait = arg->params[0].u.value.a;
/* set task's state to interruptible sleep */
set_current_state(TASK_INTERRUPTIBLE);
/* take a nap */
msleep(msec_to_wait);
/* Go to interruptible sleep */
msleep_interruptible(msec_to_wait);
arg->ret = TEEC_SUCCESS;
return;
......@@ -374,11 +371,11 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param)
shm = reg_pair_to_ptr(param->a1, param->a2);
tee_shm_free(shm);
break;
case OPTEE_SMC_RPC_FUNC_IRQ:
case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR:
/*
* An IRQ was raised while secure world was executing,
* since all IRQs are handled in Linux a dummy RPC is
* performed to let Linux take the IRQ through the normal
* A foreign interrupt was raised while secure world was
* executing, since they are handled in Linux a dummy RPC is
* performed to let Linux take the interrupt through the normal
* vector.
*/
break;
......
......@@ -90,8 +90,13 @@ static int tee_ioctl_version(struct tee_context *ctx,
struct tee_ioctl_version_data vers;
ctx->teedev->desc->ops->get_version(ctx->teedev, &vers);
if (ctx->teedev->desc->flags & TEE_DESC_PRIVILEGED)
vers.gen_caps |= TEE_GEN_CAP_PRIVILEGED;
if (copy_to_user(uvers, &vers, sizeof(vers)))
return -EFAULT;
return 0;
}
......
......@@ -80,7 +80,7 @@ static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
size, vma->vm_page_prot);
}
static struct dma_buf_ops tee_shm_dma_buf_ops = {
static const struct dma_buf_ops tee_shm_dma_buf_ops = {
.map_dma_buf = tee_shm_op_map_dma_buf,
.unmap_dma_buf = tee_shm_op_unmap_dma_buf,
.release = tee_shm_op_release,
......
/*
* Copyright (C) 2017 MediaTek 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.
*
* 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 http://www.gnu.org/licenses/gpl-2.0.html for more details.
*/
#ifndef _DT_BINDINGS_POWER_MT7622_POWER_H
#define _DT_BINDINGS_POWER_MT7622_POWER_H
#define MT7622_POWER_DOMAIN_ETHSYS 0
#define MT7622_POWER_DOMAIN_HIF0 1
#define MT7622_POWER_DOMAIN_HIF1 2
#define MT7622_POWER_DOMAIN_WB 3
#endif /* _DT_BINDINGS_POWER_MT7622_POWER_H */
/*
* 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.
*/
#ifndef __DT_BINDINGS_POWER_R8A77995_SYSC_H__
#define __DT_BINDINGS_POWER_R8A77995_SYSC_H__
/*
* These power domain indices match the numbers of the interrupt bits
* representing the power areas in the various Interrupt Registers
* (e.g. SYSCISR, Interrupt Status Register)
*/
#define R8A77995_PD_CA53_CPU0 5
#define R8A77995_PD_CA53_SCU 21
/* Always-on power area */
#define R8A77995_PD_ALWAYS_ON 32
#endif /* __DT_BINDINGS_POWER_R8A77995_SYSC_H__ */
#ifndef __DT_BINDINGS_POWER_RK3366_POWER_H__
#define __DT_BINDINGS_POWER_RK3366_POWER_H__
/* VD_CORE */
#define RK3366_PD_A53_0 0
#define RK3366_PD_A53_1 1
#define RK3366_PD_A53_2 2
#define RK3366_PD_A53_3 3
/* VD_LOGIC */
#define RK3366_PD_BUS 4
#define RK3366_PD_PERI 5
#define RK3366_PD_VIO 6
#define RK3366_PD_VIDEO 7
#define RK3366_PD_RKVDEC 8
#define RK3366_PD_WIFIBT 9
#define RK3366_PD_VPU 10
#define RK3366_PD_GPU 11
#define RK3366_PD_ALIVE 12
/* VD_PMU */
#define RK3366_PD_PMU 13
#endif
/**
* This header provides index for the HSDK v1 reset controller.
*/
#ifndef _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1
#define _DT_BINDINGS_RESET_CONTROLLER_HSDK_V1
#define HSDK_V1_APB_RESET 0
#define HSDK_V1_AXI_RESET 1
#define HSDK_V1_ETH_RESET 2
#define HSDK_V1_USB_RESET 3
#define HSDK_V1_SDIO_RESET 4
#define HSDK_V1_HDMI_RESET 5
#define HSDK_V1_GFX_RESET 6
#define HSDK_V1_DMAC_RESET 7
#define HSDK_V1_EBI_RESET 8
#endif /*_DT_BINDINGS_RESET_CONTROLLER_HSDK_V1*/
......@@ -25,6 +25,11 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
int __must_check device_reset(struct device *dev);
struct reset_control *devm_reset_control_array_get(struct device *dev,
bool shared, bool optional);
struct reset_control *of_reset_control_array_get(struct device_node *np,
bool shared, bool optional);
static inline int device_reset_optional(struct device *dev)
{
return device_reset(dev);
......@@ -89,6 +94,18 @@ static inline struct reset_control *__devm_reset_control_get(
return optional ? NULL : ERR_PTR(-ENOTSUPP);
}
static inline struct reset_control *
devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
{
return optional ? NULL : ERR_PTR(-ENOTSUPP);
}
static inline struct reset_control *
of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
{
return optional ? NULL : ERR_PTR(-ENOTSUPP);
}
#endif /* CONFIG_RESET_CONTROLLER */
/**
......@@ -374,4 +391,55 @@ static inline struct reset_control *devm_reset_control_get_by_index(
{
return devm_reset_control_get_exclusive_by_index(dev, index);
}
/*
* APIs to manage a list of reset controllers
*/
static inline struct reset_control *
devm_reset_control_array_get_exclusive(struct device *dev)
{
return devm_reset_control_array_get(dev, false, false);
}
static inline struct reset_control *
devm_reset_control_array_get_shared(struct device *dev)
{
return devm_reset_control_array_get(dev, true, false);
}
static inline struct reset_control *
devm_reset_control_array_get_optional_exclusive(struct device *dev)
{
return devm_reset_control_array_get(dev, false, true);
}
static inline struct reset_control *
devm_reset_control_array_get_optional_shared(struct device *dev)
{
return devm_reset_control_array_get(dev, true, true);
}
static inline struct reset_control *
of_reset_control_array_get_exclusive(struct device_node *node)
{
return of_reset_control_array_get(node, false, false);
}
static inline struct reset_control *
of_reset_control_array_get_shared(struct device_node *node)
{
return of_reset_control_array_get(node, true, false);
}
static inline struct reset_control *
of_reset_control_array_get_optional_exclusive(struct device_node *node)
{
return of_reset_control_array_get(node, false, true);
}
static inline struct reset_control *
of_reset_control_array_get_optional_shared(struct device_node *node)
{
return of_reset_control_array_get(node, true, true);
}
#endif
......@@ -20,6 +20,13 @@
#define MT8173_TOP_AXI_PROT_EN_MFG_M1 BIT(22)
#define MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT BIT(23)
#define MT7622_TOP_AXI_PROT_EN_ETHSYS (BIT(3) | BIT(17))
#define MT7622_TOP_AXI_PROT_EN_HIF0 (BIT(24) | BIT(25))
#define MT7622_TOP_AXI_PROT_EN_HIF1 (BIT(26) | BIT(27) | \
BIT(28))
#define MT7622_TOP_AXI_PROT_EN_WB (BIT(2) | BIT(6) | \
BIT(7) | BIT(8))
int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask);
int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask);
......
......@@ -28,6 +28,7 @@
#define TEE_SHM_MAPPED 0x1 /* Memory mapped by the kernel */
#define TEE_SHM_DMA_BUF 0x2 /* Memory with dma-buf handle */
struct device;
struct tee_device;
struct tee_shm;
struct tee_shm_pool;
......
......@@ -65,6 +65,8 @@ int tegra_fuse_readl(unsigned long offset, u32 *value);
extern struct tegra_sku_info tegra_sku_info;
struct device *tegra_soc_device_register(void);
#endif /* __ASSEMBLY__ */
#endif /* __SOC_TEGRA_FUSE_H__ */
......@@ -49,6 +49,7 @@
#define TEE_MAX_ARG_SIZE 1024
#define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */
#define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */
/*
* TEE Implementation ID
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment