aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/processor_core.c1
-rw-r--r--drivers/ata/ahci_platform.c1
-rw-r--r--drivers/bus/Kconfig10
-rw-r--r--drivers/bus/Makefile1
-rw-r--r--drivers/bus/sun50i-de2.c48
-rw-r--r--drivers/bus/ti-sysc.c64
-rw-r--r--drivers/clk/davinci/psc-da830.c3
-rw-r--r--drivers/clk/davinci/psc-da850.c3
-rw-r--r--drivers/clk/davinci/psc-dm365.c3
-rw-r--r--drivers/clk/davinci/psc-dm644x.c3
-rw-r--r--drivers/clk/davinci/psc-dm646x.c3
-rw-r--r--drivers/clk/samsung/Makefile1
-rw-r--r--drivers/clk/samsung/clk-exynos5440.c167
-rw-r--r--drivers/clk/ti/clk-7xx.c1
-rw-r--r--drivers/cpufreq/Kconfig.arm14
-rw-r--r--drivers/cpufreq/Makefile1
-rw-r--r--drivers/cpufreq/exynos5440-cpufreq.c452
-rw-r--r--drivers/crypto/caam/sg_sw_qm2.h2
-rw-r--r--drivers/crypto/caam/sg_sw_sec4.h2
-rw-r--r--drivers/firmware/arm_scmi/perf.c5
-rw-r--r--drivers/firmware/efi/efi-bgrt.c2
-rw-r--r--drivers/firmware/psci_checker.c83
-rw-r--r--drivers/firmware/raspberrypi.c29
-rw-r--r--drivers/hwmon/Kconfig10
-rw-r--r--drivers/hwmon/Makefile1
-rw-r--r--drivers/hwmon/raspberrypi-hwmon.c166
-rw-r--r--drivers/infiniband/Kconfig2
-rw-r--r--drivers/infiniband/hw/hfi1/affinity.c24
-rw-r--r--drivers/input/serio/ams_delta_serio.c198
-rw-r--r--drivers/memory/tegra/mc.c16
-rw-r--r--drivers/memory/ti-emif-pm.c33
-rw-r--r--drivers/mtd/ubi/cdev.c11
-rw-r--r--drivers/mtd/ubi/kapi.c2
-rw-r--r--drivers/mtd/ubi/ubi-media.h6
-rw-r--r--drivers/mtd/ubi/ubi.h4
-rw-r--r--drivers/mtd/ubi/vmt.c12
-rw-r--r--drivers/mtd/ubi/vtbl.c23
-rw-r--r--drivers/net/ethernet/smsc/smc911x.c13
-rw-r--r--drivers/net/ethernet/smsc/smc91x.c9
-rw-r--r--drivers/net/ethernet/smsc/smc91x.h1
-rw-r--r--drivers/pwm/Kconfig2
-rw-r--r--drivers/pwm/pwm-berlin.c45
-rw-r--r--drivers/pwm/pwm-cros-ec.c9
-rw-r--r--drivers/pwm/pwm-fsl-ftm.c57
-rw-r--r--drivers/pwm/pwm-imx.c5
-rw-r--r--drivers/pwm/pwm-mediatek.c19
-rw-r--r--drivers/pwm/pwm-meson.c3
-rw-r--r--drivers/pwm/pwm-mxs.c8
-rw-r--r--drivers/pwm/pwm-omap-dmtimer.c5
-rw-r--r--drivers/pwm/pwm-stm32-lp.c4
-rw-r--r--drivers/pwm/pwm-tiehrpwm.c14
-rw-r--r--drivers/reset/Kconfig19
-rw-r--r--drivers/reset/Makefile2
-rw-r--r--drivers/reset/reset-qcom-aoss.c133
-rw-r--r--drivers/reset/reset-simple.c1
-rw-r--r--drivers/reset/reset-uniphier-usb3.c171
-rw-r--r--drivers/reset/reset-uniphier.c9
-rw-r--r--drivers/soc/bcm/brcmstb/pm/pm-arm.c16
-rw-r--r--drivers/soc/fsl/Kconfig15
-rw-r--r--drivers/soc/fsl/Makefile1
-rw-r--r--drivers/soc/fsl/dpio/Makefile (renamed from drivers/staging/fsl-mc/bus/dpio/Makefile)0
-rw-r--r--drivers/soc/fsl/dpio/dpio-cmd.h (renamed from drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h)0
-rw-r--r--drivers/soc/fsl/dpio/dpio-driver.c (renamed from drivers/staging/fsl-mc/bus/dpio/dpio-driver.c)2
-rw-r--r--drivers/soc/fsl/dpio/dpio-service.c (renamed from drivers/staging/fsl-mc/bus/dpio/dpio-service.c)2
-rw-r--r--drivers/soc/fsl/dpio/dpio.c (renamed from drivers/staging/fsl-mc/bus/dpio/dpio.c)0
-rw-r--r--drivers/soc/fsl/dpio/dpio.h (renamed from drivers/staging/fsl-mc/bus/dpio/dpio.h)0
-rw-r--r--drivers/soc/fsl/dpio/qbman-portal.c (renamed from drivers/staging/fsl-mc/bus/dpio/qbman-portal.c)2
-rw-r--r--drivers/soc/fsl/dpio/qbman-portal.h (renamed from drivers/staging/fsl-mc/bus/dpio/qbman-portal.h)2
-rw-r--r--drivers/soc/fsl/qbman/Kconfig2
-rw-r--r--drivers/soc/fsl/qe/Kconfig2
-rw-r--r--drivers/soc/fsl/qe/gpio.c28
-rw-r--r--drivers/soc/imx/gpc.c18
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c81
-rw-r--r--drivers/soc/renesas/Makefile3
-rw-r--r--drivers/soc/renesas/r9a06g032-smp.c96
-rw-r--r--drivers/soc/renesas/rcar-sysc.c64
-rw-r--r--drivers/soc/sunxi/sunxi_sram.c87
-rw-r--r--drivers/soc/ti/Kconfig14
-rw-r--r--drivers/soc/ti/pm33xx.c16
-rw-r--r--drivers/soc/ti/wkup_m3_ipc.c76
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c4
-rw-r--r--drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h22
-rw-r--r--drivers/staging/fsl-mc/Kconfig2
-rw-r--r--drivers/staging/fsl-mc/Makefile3
-rw-r--r--drivers/staging/fsl-mc/bus/Kconfig16
-rw-r--r--drivers/staging/fsl-mc/bus/Makefile9
-rw-r--r--drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt135
-rw-r--r--drivers/staging/fsl-mc/include/dpaa2-fd.h426
-rw-r--r--drivers/staging/fsl-mc/include/dpaa2-global.h177
-rw-r--r--drivers/staging/fsl-mc/include/dpaa2-io.h115
-rw-r--r--drivers/tee/optee/Kconfig8
-rw-r--r--drivers/tee/optee/core.c2
-rw-r--r--drivers/tee/optee/rpc.c2
-rw-r--r--drivers/usb/host/ehci-exynos.c7
-rw-r--r--drivers/usb/host/ohci-exynos.c6
-rw-r--r--drivers/video/console/Kconfig2
-rw-r--r--drivers/video/console/dummycon.c2
-rw-r--r--drivers/video/console/vgacon.c5
-rw-r--r--drivers/video/fbdev/amifb.c4
-rw-r--r--drivers/video/fbdev/core/fbcon.c70
-rw-r--r--drivers/video/fbdev/core/fbmem.c56
-rw-r--r--drivers/video/fbdev/core/modedb.c93
-rw-r--r--drivers/video/fbdev/efifb.c183
-rw-r--r--drivers/video/fbdev/fsl-diu-fb.c23
-rw-r--r--drivers/video/fbdev/goldfishfb.c15
-rw-r--r--drivers/video/fbdev/i740fb.c1
-rw-r--r--drivers/video/fbdev/metronomefb.c10
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c2
-rw-r--r--drivers/video/fbdev/omap2/omapfb/Makefile4
-rw-r--r--drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c17
-rw-r--r--drivers/video/fbdev/omap2/omapfb/dss/dispc.c4
-rw-r--r--drivers/video/fbdev/omap2/omapfb/omapfb-main.c1
-rw-r--r--drivers/video/fbdev/pm2fb.c2
-rw-r--r--drivers/video/fbdev/pxa3xx-gcu.c10
-rw-r--r--drivers/video/fbdev/pxafb.c97
-rw-r--r--drivers/video/fbdev/pxafb.h3
-rw-r--r--drivers/video/fbdev/simplefb.c2
-rw-r--r--drivers/video/fbdev/tdfxfb.c1
-rw-r--r--drivers/video/fbdev/tridentfb.c3
-rw-r--r--drivers/video/fbdev/udlfb.c230
-rw-r--r--drivers/video/fbdev/via/lcd.c1
-rw-r--r--drivers/video/fbdev/via/viafbdev.c3
-rw-r--r--drivers/xen/mcelog.c2
-rw-r--r--drivers/xen/xen-acpi-processor.c6
126 files changed, 2133 insertions, 2119 deletions
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index b933061b6b60..8c0a54d50d0e 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -205,6 +205,7 @@ phys_cpuid_t acpi_get_phys_id(acpi_handle handle, int type, u32 acpi_id)
return phys_id;
}
+EXPORT_SYMBOL_GPL(acpi_get_phys_id);
int acpi_map_cpuid(phys_cpuid_t phys_id, u32 acpi_id)
{
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 99f9a895a459..564570ea3e27 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -75,7 +75,6 @@ static const struct of_device_id ahci_of_match[] = {
{ .compatible = "generic-ahci", },
/* Keep the following compatibles for device tree compatibility */
{ .compatible = "snps,spear-ahci", },
- { .compatible = "snps,exynos5440-ahci", },
{ .compatible = "ibm,476gtr-ahci", },
{ .compatible = "snps,dwc-ahci", },
{ .compatible = "hisilicon,hisi-ahci", },
diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig
index d1c0b60e9326..1851112ccc29 100644
--- a/drivers/bus/Kconfig
+++ b/drivers/bus/Kconfig
@@ -103,6 +103,16 @@ config SIMPLE_PM_BUS
Controller (BSC, sometimes called "LBSC within Bus Bridge", or
"External Bus Interface") as found on several Renesas ARM SoCs.
+config SUN50I_DE2_BUS
+ bool "Allwinner A64 DE2 Bus Driver"
+ default ARM64
+ depends on ARCH_SUNXI
+ select SUNXI_SRAM
+ help
+ Say y here to enable support for Allwinner A64 DE2 bus driver. It's
+ mostly transparent, but a SRAM region needs to be claimed in the SRAM
+ controller to make the all blocks in the DE2 part accessible.
+
config SUNXI_RSB
tristate "Allwinner sunXi Reduced Serial Bus Driver"
default MACH_SUN8I || MACH_SUN9I || ARM64
diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
index b8f036cca7ff..ca300b1914ce 100644
--- a/drivers/bus/Makefile
+++ b/drivers/bus/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_OMAP_INTERCONNECT) += omap_l3_smx.o omap_l3_noc.o
obj-$(CONFIG_OMAP_OCP2SCP) += omap-ocp2scp.o
obj-$(CONFIG_QCOM_EBI2) += qcom-ebi2.o
+obj-$(CONFIG_SUN50I_DE2_BUS) += sun50i-de2.o
obj-$(CONFIG_SUNXI_RSB) += sunxi-rsb.o
obj-$(CONFIG_SIMPLE_PM_BUS) += simple-pm-bus.o
obj-$(CONFIG_TEGRA_ACONNECT) += tegra-aconnect.o
diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c
new file mode 100644
index 000000000000..672518741f86
--- /dev/null
+++ b/drivers/bus/sun50i-de2.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Allwinner A64 Display Engine 2.0 Bus Driver
+ *
+ * Copyright (C) 2018 Icenowy Zheng <icenowy@aosc.io>
+ */
+
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/soc/sunxi/sunxi_sram.h>
+
+static int sun50i_de2_bus_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ int ret;
+
+ ret = sunxi_sram_claim(&pdev->dev);
+ if (ret) {
+ dev_err(&pdev->dev, "Error couldn't map SRAM to device\n");
+ return ret;
+ }
+
+ of_platform_populate(np, NULL, NULL, &pdev->dev);
+
+ return 0;
+}
+
+static int sun50i_de2_bus_remove(struct platform_device *pdev)
+{
+ sunxi_sram_release(&pdev->dev);
+ return 0;
+}
+
+static const struct of_device_id sun50i_de2_bus_of_match[] = {
+ { .compatible = "allwinner,sun50i-a64-de2", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sun50i_de2_bus_driver = {
+ .probe = sun50i_de2_bus_probe,
+ .remove = sun50i_de2_bus_remove,
+ .driver = {
+ .name = "sun50i-de2-bus",
+ .of_match_table = sun50i_de2_bus_of_match,
+ },
+};
+
+builtin_platform_driver(sun50i_de2_bus_driver);
diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c
index 80d60f43db56..c9bac9dc4637 100644
--- a/drivers/bus/ti-sysc.c
+++ b/drivers/bus/ti-sysc.c
@@ -23,11 +23,14 @@
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/slab.h>
+#include <linux/iopoll.h>
#include <linux/platform_data/ti-sysc.h>
#include <dt-bindings/bus/ti-sysc.h>
+#define MAX_MODULE_SOFTRESET_WAIT 10000
+
static const char * const reg_names[] = { "rev", "sysc", "syss", };
enum sysc_clocks {
@@ -88,6 +91,11 @@ struct sysc {
struct delayed_work idle_work;
};
+void sysc_write(struct sysc *ddata, int offset, u32 value)
+{
+ writel_relaxed(value, ddata->module_va + offset);
+}
+
static u32 sysc_read(struct sysc *ddata, int offset)
{
if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) {
@@ -943,6 +951,36 @@ static void sysc_init_revision_quirks(struct sysc *ddata)
}
}
+static int sysc_reset(struct sysc *ddata)
+{
+ int offset = ddata->offsets[SYSC_SYSCONFIG];
+ int val;
+
+ if (ddata->legacy_mode || offset < 0 ||
+ ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
+ return 0;
+
+ /*
+ * Currently only support reset status in sysstatus.
+ * Warn and return error in all other cases
+ */
+ if (!ddata->cfg.syss_mask) {
+ dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n");
+ return -EINVAL;
+ }
+
+ val = sysc_read(ddata, offset);
+ val |= (0x1 << ddata->cap->regbits->srst_shift);
+ sysc_write(ddata, offset, val);
+
+ /* Poll on reset status */
+ offset = ddata->offsets[SYSC_SYSSTATUS];
+
+ return readl_poll_timeout(ddata->module_va + offset, val,
+ (val & ddata->cfg.syss_mask) == 0x0,
+ 100, MAX_MODULE_SOFTRESET_WAIT);
+}
+
/* At this point the module is configured enough to read the revision */
static int sysc_init_module(struct sysc *ddata)
{
@@ -960,6 +998,14 @@ static int sysc_init_module(struct sysc *ddata)
return 0;
}
+ error = sysc_reset(ddata);
+ if (error) {
+ dev_err(ddata->dev, "Reset failed with %d\n", error);
+ pm_runtime_put_sync(ddata->dev);
+
+ return error;
+ }
+
ddata->revision = sysc_read_revision(ddata);
pm_runtime_put_sync(ddata->dev);
@@ -1552,6 +1598,23 @@ static const struct sysc_capabilities sysc_omap4_usb_host_fs = {
.regbits = &sysc_regbits_omap4_usb_host_fs,
};
+static const struct sysc_regbits sysc_regbits_dra7_mcan = {
+ .dmadisable_shift = -ENODEV,
+ .midle_shift = -ENODEV,
+ .sidle_shift = -ENODEV,
+ .clkact_shift = -ENODEV,
+ .enwkup_shift = 4,
+ .srst_shift = 0,
+ .emufree_shift = -ENODEV,
+ .autoidle_shift = -ENODEV,
+};
+
+static const struct sysc_capabilities sysc_dra7_mcan = {
+ .type = TI_SYSC_DRA7_MCAN,
+ .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET,
+ .regbits = &sysc_regbits_dra7_mcan,
+};
+
static int sysc_init_pdata(struct sysc *ddata)
{
struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
@@ -1743,6 +1806,7 @@ static const struct of_device_id sysc_match[] = {
{ .compatible = "ti,sysc-mcasp", .data = &sysc_omap4_mcasp, },
{ .compatible = "ti,sysc-usb-host-fs",
.data = &sysc_omap4_usb_host_fs, },
+ { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
{ },
};
MODULE_DEVICE_TABLE(of, sysc_match);
diff --git a/drivers/clk/davinci/psc-da830.c b/drivers/clk/davinci/psc-da830.c
index 081b039fcb02..6481337382a6 100644
--- a/drivers/clk/davinci/psc-da830.c
+++ b/drivers/clk/davinci/psc-da830.c
@@ -14,6 +14,7 @@
#include "psc.h"
+LPSC_CLKDEV1(aemif_clkdev, NULL, "ti-aemif");
LPSC_CLKDEV1(spi0_clkdev, NULL, "spi_davinci.0");
LPSC_CLKDEV1(mmcsd_clkdev, NULL, "da830-mmc.0");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
@@ -22,7 +23,7 @@ static const struct davinci_lpsc_clk_info da830_psc0_info[] = {
LPSC(0, 0, tpcc, pll0_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
LPSC(1, 0, tptc0, pll0_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
LPSC(2, 0, tptc1, pll0_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
- LPSC(3, 0, aemif, pll0_sysclk3, NULL, LPSC_ALWAYS_ENABLED),
+ LPSC(3, 0, aemif, pll0_sysclk3, aemif_clkdev, LPSC_ALWAYS_ENABLED),
LPSC(4, 0, spi0, pll0_sysclk2, spi0_clkdev, 0),
LPSC(5, 0, mmcsd, pll0_sysclk2, mmcsd_clkdev, 0),
LPSC(6, 0, aintc, pll0_sysclk4, NULL, LPSC_ALWAYS_ENABLED),
diff --git a/drivers/clk/davinci/psc-da850.c b/drivers/clk/davinci/psc-da850.c
index d196dcbed560..5a18bca464cd 100644
--- a/drivers/clk/davinci/psc-da850.c
+++ b/drivers/clk/davinci/psc-da850.c
@@ -16,8 +16,7 @@
#include "psc.h"
-LPSC_CLKDEV2(emifa_clkdev, NULL, "ti-aemif",
- "aemif", "davinci_nand.0");
+LPSC_CLKDEV1(emifa_clkdev, NULL, "ti-aemif");
LPSC_CLKDEV1(spi0_clkdev, NULL, "spi_davinci.0");
LPSC_CLKDEV1(mmcsd0_clkdev, NULL, "da830-mmc.0");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
diff --git a/drivers/clk/davinci/psc-dm365.c b/drivers/clk/davinci/psc-dm365.c
index 8c73086cc676..c75424f4ea3b 100644
--- a/drivers/clk/davinci/psc-dm365.c
+++ b/drivers/clk/davinci/psc-dm365.c
@@ -21,7 +21,8 @@ LPSC_CLKDEV1(mmcsd1_clkdev, NULL, "da830-mmc.1");
LPSC_CLKDEV1(asp0_clkdev, NULL, "davinci-mcbsp");
LPSC_CLKDEV1(usb_clkdev, "usb", NULL);
LPSC_CLKDEV1(spi2_clkdev, NULL, "spi_davinci.2");
-LPSC_CLKDEV1(aemif_clkdev, "aemif", NULL);
+LPSC_CLKDEV2(aemif_clkdev, "aemif", NULL,
+ NULL, "ti-aemif");
LPSC_CLKDEV1(mmcsd0_clkdev, NULL, "da830-mmc.0");
LPSC_CLKDEV1(i2c_clkdev, NULL, "i2c_davinci.1");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
diff --git a/drivers/clk/davinci/psc-dm644x.c b/drivers/clk/davinci/psc-dm644x.c
index fc0230e3a3d6..0cea6e0bd5f0 100644
--- a/drivers/clk/davinci/psc-dm644x.c
+++ b/drivers/clk/davinci/psc-dm644x.c
@@ -21,7 +21,8 @@ LPSC_CLKDEV2(emac_clkdev, NULL, "davinci_emac.1",
"fck", "davinci_mdio.0");
LPSC_CLKDEV1(usb_clkdev, "usb", NULL);
LPSC_CLKDEV1(ide_clkdev, NULL, "palm_bk3710");
-LPSC_CLKDEV1(aemif_clkdev, "aemif", NULL);
+LPSC_CLKDEV2(aemif_clkdev, "aemif", NULL,
+ NULL, "ti-aemif");
LPSC_CLKDEV1(mmcsd_clkdev, NULL, "dm6441-mmc.0");
LPSC_CLKDEV1(asp0_clkdev, NULL, "davinci-mcbsp");
LPSC_CLKDEV1(i2c_clkdev, NULL, "i2c_davinci.1");
diff --git a/drivers/clk/davinci/psc-dm646x.c b/drivers/clk/davinci/psc-dm646x.c
index c3f82ed70a80..20012dc7471a 100644
--- a/drivers/clk/davinci/psc-dm646x.c
+++ b/drivers/clk/davinci/psc-dm646x.c
@@ -18,7 +18,8 @@
LPSC_CLKDEV1(ide_clkdev, NULL, "palm_bk3710");
LPSC_CLKDEV2(emac_clkdev, NULL, "davinci_emac.1",
"fck", "davinci_mdio.0");
-LPSC_CLKDEV1(aemif_clkdev, "aemif", NULL);
+LPSC_CLKDEV2(aemif_clkdev, "aemif", NULL,
+ NULL, "ti-aemif");
LPSC_CLKDEV1(mcasp0_clkdev, NULL, "davinci-mcasp.0");
LPSC_CLKDEV1(mcasp1_clkdev, NULL, "davinci-mcasp.1");
LPSC_CLKDEV1(uart0_clkdev, NULL, "serial8250.0");
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
index 513826393158..1a4e6b787978 100644
--- a/drivers/clk/samsung/Makefile
+++ b/drivers/clk/samsung/Makefile
@@ -14,7 +14,6 @@ obj-$(CONFIG_SOC_EXYNOS5410) += clk-exynos5410.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5420.o
obj-$(CONFIG_SOC_EXYNOS5420) += clk-exynos5-subcmu.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos5433.o
-obj-$(CONFIG_SOC_EXYNOS5440) += clk-exynos5440.o
obj-$(CONFIG_EXYNOS_AUDSS_CLK_CON) += clk-exynos-audss.o
obj-$(CONFIG_ARCH_EXYNOS) += clk-exynos-clkout.o
obj-$(CONFIG_EXYNOS_ARM64_COMMON_CLK) += clk-exynos7.o
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
deleted file mode 100644
index b08bd54c5e76..000000000000
--- a/drivers/clk/samsung/clk-exynos5440.c
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * Author: Thomas Abraham <thomas.ab@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Common Clock Framework support for Exynos5440 SoC.
-*/
-
-#include <dt-bindings/clock/exynos5440.h>
-#include <linux/clk-provider.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-
-#include "clk.h"
-#include "clk-pll.h"
-
-#define CLKEN_OV_VAL 0xf8
-#define CPU_CLK_STATUS 0xfc
-#define MISC_DOUT1 0x558
-
-static void __iomem *reg_base;
-
-/* parent clock name list */
-PNAME(mout_armclk_p) = { "cplla", "cpllb" };
-PNAME(mout_spi_p) = { "div125", "div200" };
-
-/* fixed rate clocks generated outside the soc */
-static struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
- FRATE(0, "xtal", NULL, 0, 0),
-};
-
-/* fixed rate clocks */
-static const struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initconst = {
- FRATE(0, "ppll", NULL, 0, 1000000000),
- FRATE(0, "usb_phy0", NULL, 0, 60000000),
- FRATE(0, "usb_phy1", NULL, 0, 60000000),
- FRATE(0, "usb_ohci12", NULL, 0, 12000000),
- FRATE(0, "usb_ohci48", NULL, 0, 48000000),
-};
-
-/* fixed factor clocks */
-static const struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initconst = {
- FFACTOR(0, "div250", "ppll", 1, 4, 0),
- FFACTOR(0, "div200", "ppll", 1, 5, 0),
- FFACTOR(0, "div125", "div250", 1, 2, 0),
-};
-
-/* mux clocks */
-static const struct samsung_mux_clock exynos5440_mux_clks[] __initconst = {
- MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
- MUX(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1),
-};
-
-/* divider clocks */
-static const struct samsung_div_clock exynos5440_div_clks[] __initconst = {
- DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
-};
-
-/* gate clocks */
-static const struct samsung_gate_clock exynos5440_gate_clks[] __initconst = {
- GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
- GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
- GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
- GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
- GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
- GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
- GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
- GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
- GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
- GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
- GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
- GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
- GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
- GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
- GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
- GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
- GATE(CLK_SATA_O, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
- GATE(CLK_USB_O, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
- GATE(CLK_GMAC0_O, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
- GATE(CLK_CS250_O, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
-};
-
-static const struct of_device_id ext_clk_match[] __initconst = {
- { .compatible = "samsung,clock-xtal", .data = (void *)0, },
- {},
-};
-
-static int exynos5440_clk_restart_notify(struct notifier_block *this,
- unsigned long code, void *unused)
-{
- u32 val, status;
-
- status = readl_relaxed(reg_base + 0xbc);
- val = readl_relaxed(reg_base + 0xcc);
- val = (val & 0xffff0000) | (status & 0xffff);
- writel_relaxed(val, reg_base + 0xcc);
-
- return NOTIFY_DONE;
-}
-
-/*
- * Exynos5440 Clock restart notifier, handles restart functionality
- */
-static struct notifier_block exynos5440_clk_restart_handler = {
- .notifier_call = exynos5440_clk_restart_notify,
- .priority = 128,
-};
-
-static const struct samsung_pll_clock exynos5440_plls[] __initconst = {
- PLL(pll_2550x, CLK_CPLLA, "cplla", "xtal", 0, 0x4c, NULL),
- PLL(pll_2550x, CLK_CPLLB, "cpllb", "xtal", 0, 0x50, NULL),
-};
-
-/*
- * Clock aliases for legacy clkdev look-up.
- */
-static const struct samsung_clock_alias exynos5440_aliases[] __initconst = {
- ALIAS(CLK_ARM_CLK, NULL, "armclk"),
-};
-
-/* register exynos5440 clocks */
-static void __init exynos5440_clk_init(struct device_node *np)
-{
- struct samsung_clk_provider *ctx;
-
- reg_base = of_iomap(np, 0);
- if (!reg_base) {
- pr_err("%s: failed to map clock controller registers,"
- " aborting clock initialization\n", __func__);
- return;
- }
-
- ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
-
- samsung_clk_of_register_fixed_ext(ctx, exynos5440_fixed_rate_ext_clks,
- ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
-
- samsung_clk_register_pll(ctx, exynos5440_plls,
- ARRAY_SIZE(exynos5440_plls), ctx->reg_base);
-
- samsung_clk_register_fixed_rate(ctx, exynos5440_fixed_rate_clks,
- ARRAY_SIZE(exynos5440_fixed_rate_clks));
- samsung_clk_register_fixed_factor(ctx, exynos5440_fixed_factor_clks,
- ARRAY_SIZE(exynos5440_fixed_factor_clks));
- samsung_clk_register_mux(ctx, exynos5440_mux_clks,
- ARRAY_SIZE(exynos5440_mux_clks));
- samsung_clk_register_div(ctx, exynos5440_div_clks,
- ARRAY_SIZE(exynos5440_div_clks));
- samsung_clk_register_gate(ctx, exynos5440_gate_clks,
- ARRAY_SIZE(exynos5440_gate_clks));
- samsung_clk_register_alias(ctx, exynos5440_aliases,
- ARRAY_SIZE(exynos5440_aliases));
-
- samsung_clk_of_add_provider(np, ctx);
-
- if (register_restart_handler(&exynos5440_clk_restart_handler))
- pr_warn("exynos5440 clock can't register restart handler\n");
-
- pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("arm_clk"));
- pr_info("exynos5440 clock initialization complete\n");
-}
-CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c
index fb249a1637a5..71a122b2dc67 100644
--- a/drivers/clk/ti/clk-7xx.c
+++ b/drivers/clk/ti/clk-7xx.c
@@ -708,6 +708,7 @@ static const struct omap_clkctrl_reg_data dra7_wkupaon_clkctrl_regs[] __initcons
{ DRA7_COUNTER_32K_CLKCTRL, NULL, 0, "wkupaon_iclk_mux" },
{ DRA7_UART10_CLKCTRL, dra7_uart10_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0060:24" },
{ DRA7_DCAN1_CLKCTRL, dra7_dcan1_bit_data, CLKF_SW_SUP, "wkupaon_cm:clk:0068:24" },
+ { DRA7_ADC_CLKCTRL, NULL, CLKF_SW_SUP, "mcan_clk"},
{ 0 },
};
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 52f5f1a2040c..0cd8eb76ad59 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -71,20 +71,6 @@ config ARM_BRCMSTB_AVS_CPUFREQ
Say Y, if you have a Broadcom SoC with AVS support for DFS or DVFS.
-config ARM_EXYNOS5440_CPUFREQ
- tristate "SAMSUNG EXYNOS5440"
- depends on SOC_EXYNOS5440
- depends on HAVE_CLK && OF
- select PM_OPP
- default y
- help
- This adds the CPUFreq driver for Samsung EXYNOS5440
- SoC. The nature of exynos5440 clock controller is
- different than previous exynos controllers so not using
- the common exynos framework.
-
- If in doubt, say N.
-
config ARM_HIGHBANK_CPUFREQ
tristate "Calxeda Highbank-based"
depends on ARCH_HIGHBANK && CPUFREQ_DT && REGULATOR
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index fb4a2ecac43b..c1ffeabe4ecf 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -56,7 +56,6 @@ obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o
obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o
-obj-$(CONFIG_ARM_EXYNOS5440_CPUFREQ) += exynos5440-cpufreq.o
obj-$(CONFIG_ARM_HIGHBANK_CPUFREQ) += highbank-cpufreq.o
obj-$(CONFIG_ARM_IMX6Q_CPUFREQ) += imx6q-cpufreq.o
obj-$(CONFIG_ARM_KIRKWOOD_CPUFREQ) += kirkwood-cpufreq.o
diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c
deleted file mode 100644
index 932caa386ece..000000000000
--- a/drivers/cpufreq/exynos5440-cpufreq.c
+++ /dev/null
@@ -1,452 +0,0 @@
-/*
- * Copyright (c) 2013 Samsung Electronics Co., Ltd.
- * http://www.samsung.com
- *
- * Amit Daniel Kachhap <amit.daniel@samsung.com>
- *
- * EXYNOS5440 - CPU frequency scaling support
- *
- * 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/clk.h>
-#include <linux/cpu.h>
-#include <linux/cpufreq.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/pm_opp.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-
-/* Register definitions */
-#define XMU_DVFS_CTRL 0x0060
-#define XMU_PMU_P0_7 0x0064
-#define XMU_C0_3_PSTATE 0x0090
-#define XMU_P_LIMIT 0x00a0
-#define XMU_P_STATUS 0x00a4
-#define XMU_PMUEVTEN 0x00d0
-#define XMU_PMUIRQEN 0x00d4
-#define XMU_PMUIRQ 0x00d8
-
-/* PMU mask and shift definations */
-#define P_VALUE_MASK 0x7
-
-#define XMU_DVFS_CTRL_EN_SHIFT 0
-
-#define P0_7_CPUCLKDEV_SHIFT 21
-#define P0_7_CPUCLKDEV_MASK 0x7
-#define P0_7_ATBCLKDEV_SHIFT 18
-#define P0_7_ATBCLKDEV_MASK 0x7
-#define P0_7_CSCLKDEV_SHIFT 15
-#define P0_7_CSCLKDEV_MASK 0x7
-#define P0_7_CPUEMA_SHIFT 28
-#define P0_7_CPUEMA_MASK 0xf
-#define P0_7_L2EMA_SHIFT 24
-#define P0_7_L2EMA_MASK 0xf
-#define P0_7_VDD_SHIFT 8
-#define P0_7_VDD_MASK 0x7f
-#define P0_7_FREQ_SHIFT 0
-#define P0_7_FREQ_MASK 0xff
-
-#define C0_3_PSTATE_VALID_SHIFT 8
-#define C0_3_PSTATE_CURR_SHIFT 4
-#define C0_3_PSTATE_NEW_SHIFT 0
-
-#define PSTATE_CHANGED_EVTEN_SHIFT 0
-
-#define PSTATE_CHANGED_IRQEN_SHIFT 0
-
-#define PSTATE_CHANGED_SHIFT 0
-
-/* some constant values for clock divider calculation */
-#define CPU_DIV_FREQ_MAX 500
-#define CPU_DBG_FREQ_MAX 375
-#define CPU_ATB_FREQ_MAX 500
-
-#define PMIC_LOW_VOLT 0x30
-#define PMIC_HIGH_VOLT 0x28
-
-#define CPUEMA_HIGH 0x2
-#define CPUEMA_MID 0x4
-#define CPUEMA_LOW 0x7
-
-#define L2EMA_HIGH 0x1
-#define L2EMA_MID 0x3
-#define L2EMA_LOW 0x4
-
-#define DIV_TAB_MAX 2
-/* frequency unit is 20MHZ */
-#define FREQ_UNIT 20
-#define MAX_VOLTAGE 1550000 /* In microvolt */
-#define VOLTAGE_STEP 12500 /* In microvolt */
-
-#define CPUFREQ_NAME "exynos5440_dvfs"
-#define DEF_TRANS_LATENCY 100000
-
-enum cpufreq_level_index {
- L0, L1, L2, L3, L4,
- L5, L6, L7, L8, L9,
-};
-#define CPUFREQ_LEVEL_END (L7 + 1)
-
-struct exynos_dvfs_data {
- void __iomem *base;
- struct resource *mem;
- int irq;
- struct clk *cpu_clk;
- unsigned int latency;
- struct cpufreq_frequency_table *freq_table;
- unsigned int freq_count;
- struct device *dev;
- bool dvfs_enabled;
- struct work_struct irq_work;
-};
-
-static struct exynos_dvfs_data *dvfs_info;
-static DEFINE_MUTEX(cpufreq_lock);
-static struct cpufreq_freqs freqs;
-
-static int init_div_table(void)
-{
- struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table;
- unsigned int tmp, clk_div, ema_div, freq, volt_id, idx;
- struct dev_pm_opp *opp;
-
- cpufreq_for_each_entry_idx(pos, freq_tbl, idx) {
- opp = dev_pm_opp_find_freq_exact(dvfs_info->dev,
- pos->frequency * 1000, true);
- if (IS_ERR(opp)) {
- dev_err(dvfs_info->dev,
- "failed to find valid OPP for %u KHZ\n",
- pos->frequency);
- return PTR_ERR(opp);
- }
-
- freq = pos->frequency / 1000; /* In MHZ */
- clk_div = ((freq / CPU_DIV_FREQ_MAX) & P0_7_CPUCLKDEV_MASK)
- << P0_7_CPUCLKDEV_SHIFT;
- clk_div |= ((freq / CPU_ATB_FREQ_MAX) & P0_7_ATBCLKDEV_MASK)
- << P0_7_ATBCLKDEV_SHIFT;
- clk_div |= ((freq / CPU_DBG_FREQ_MAX) & P0_7_CSCLKDEV_MASK)
- << P0_7_CSCLKDEV_SHIFT;
-
- /* Calculate EMA */
- volt_id = dev_pm_opp_get_voltage(opp);
-
- volt_id = (MAX_VOLTAGE - volt_id) / VOLTAGE_STEP;
- if (volt_id < PMIC_HIGH_VOLT) {
- ema_div = (CPUEMA_HIGH << P0_7_CPUEMA_SHIFT) |
- (L2EMA_HIGH << P0_7_L2EMA_SHIFT);
- } else if (volt_id > PMIC_LOW_VOLT) {
- ema_div = (CPUEMA_LOW << P0_7_CPUEMA_SHIFT) |
- (L2EMA_LOW << P0_7_L2EMA_SHIFT);
- } else {
- ema_div = (CPUEMA_MID << P0_7_CPUEMA_SHIFT) |
- (L2EMA_MID << P0_7_L2EMA_SHIFT);
- }
-
- tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT)
- | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT));
-
- __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * idx);
- dev_pm_opp_put(opp);
- }
-
- return 0;
-}
-
-static void exynos_enable_dvfs(unsigned int cur_frequency)
-{
- unsigned int tmp, cpu;
- struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
- struct cpufreq_frequency_table *pos;
- /* Disable DVFS */
- __raw_writel(0, dvfs_info->base + XMU_DVFS_CTRL);
-
- /* Enable PSTATE Change Event */
- tmp = __raw_readl(dvfs_info->base + XMU_PMUEVTEN);
- tmp |= (1 << PSTATE_CHANGED_EVTEN_SHIFT);
- __raw_writel(tmp, dvfs_info->base + XMU_PMUEVTEN);
-
- /* Enable PSTATE Change IRQ */
- tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQEN);
- tmp |= (1 << PSTATE_CHANGED_IRQEN_SHIFT);
- __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQEN);
-
- /* Set initial performance index */
- cpufreq_for_each_entry(pos, freq_table)
- if (pos->frequency == cur_frequency)
- break;
-
- if (pos->frequency == CPUFREQ_TABLE_END) {
- dev_crit(dvfs_info->dev, "Boot up frequency not supported\n");
- /* Assign the highest frequency */
- pos = freq_table;
- cur_frequency = pos->frequency;
- }
-
- dev_info(dvfs_info->dev, "Setting dvfs initial frequency = %uKHZ",
- cur_frequency);
-
- for (cpu = 0; cpu < CONFIG_NR_CPUS; cpu++) {
- tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
- tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
- tmp |= ((pos - freq_table) << C0_3_PSTATE_NEW_SHIFT);
- __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + cpu * 4);
- }
-
- /* Enable DVFS */
- __raw_writel(1 << XMU_DVFS_CTRL_EN_SHIFT,
- dvfs_info->base + XMU_DVFS_CTRL);
-}
-
-static int exynos_target(struct cpufreq_policy *policy, unsigned int index)
-{
- unsigned int tmp;
- int i;
- struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-
- mutex_lock(&cpufreq_lock);
-
- freqs.old = policy->cur;
- freqs.new = freq_table[index].frequency;
-
- cpufreq_freq_transition_begin(policy, &freqs);
-
- /* Set the target frequency in all C0_3_PSTATE register */
- for_each_cpu(i, policy->cpus) {
- tmp = __raw_readl(dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
- tmp &= ~(P_VALUE_MASK << C0_3_PSTATE_NEW_SHIFT);
- tmp |= (index << C0_3_PSTATE_NEW_SHIFT);
-
- __raw_writel(tmp, dvfs_info->base + XMU_C0_3_PSTATE + i * 4);
- }
- mutex_unlock(&cpufreq_lock);
- return 0;
-}
-
-static void exynos_cpufreq_work(struct work_struct *work)
-{
- unsigned int cur_pstate, index;
- struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
- struct cpufreq_frequency_table *freq_table = dvfs_info->freq_table;
-
- /* Ensure we can access cpufreq structures */
- if (unlikely(dvfs_info->dvfs_enabled == false))
- goto skip_work;
-
- mutex_lock(&cpufreq_lock);
- freqs.old = policy->cur;
-
- cur_pstate = __raw_readl(dvfs_info->base + XMU_P_STATUS);
- if (cur_pstate >> C0_3_PSTATE_VALID_SHIFT & 0x1)
- index = (cur_pstate >> C0_3_PSTATE_CURR_SHIFT) & P_VALUE_MASK;
- else
- index = (cur_pstate >> C0_3_PSTATE_NEW_SHIFT) & P_VALUE_MASK;
-
- if (likely(index < dvfs_info->freq_count)) {
- freqs.new = freq_table[index].frequency;
- } else {
- dev_crit(dvfs_info->dev, "New frequency out of range\n");
- freqs.new = freqs.old;
- }
- cpufreq_freq_transition_end(policy, &freqs, 0);
-
- cpufreq_cpu_put(policy);
- mutex_unlock(&cpufreq_lock);
-skip_work:
- enable_irq(dvfs_info->irq);
-}
-
-static irqreturn_t exynos_cpufreq_irq(int irq, void *id)
-{
- unsigned int tmp;
-
- tmp = __raw_readl(dvfs_info->base + XMU_PMUIRQ);
- if (tmp >> PSTATE_CHANGED_SHIFT & 0x1) {
- __raw_writel(tmp, dvfs_info->base + XMU_PMUIRQ);
- disable_irq_nosync(irq);
- schedule_work(&dvfs_info->irq_work);
- }
- return IRQ_HANDLED;
-}
-
-static void exynos_sort_descend_freq_table(void)
-{
- struct cpufreq_frequency_table *freq_tbl = dvfs_info->freq_table;
- int i = 0, index;
- unsigned int tmp_freq;
- /*
- * Exynos5440 clock controller state logic expects the cpufreq table to
- * be in descending order. But the OPP library constructs the table in
- * ascending order. So to make the table descending we just need to
- * swap the i element with the N - i element.
- */
- for (i = 0; i < dvfs_info->freq_count / 2; i++) {
- index = dvfs_info->freq_count - i - 1;
- tmp_freq = freq_tbl[i].frequency;
- freq_tbl[i].frequency = freq_tbl[index].frequency;
- freq_tbl[index].frequency = tmp_freq;
- }
-}
-
-static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- policy->clk = dvfs_info->cpu_clk;
- return cpufreq_generic_init(policy, dvfs_info->freq_table,
- dvfs_info->latency);
-}
-
-static struct cpufreq_driver exynos_driver = {
- .flags = CPUFREQ_STICKY | CPUFREQ_ASYNC_NOTIFICATION |
- CPUFREQ_NEED_INITIAL_FREQ_CHECK,
- .verify = cpufreq_generic_frequency_table_verify,
- .target_index = exynos_target,
- .get = cpufreq_generic_get,
- .init = exynos_cpufreq_cpu_init,
- .name = CPUFREQ_NAME,
- .attr = cpufreq_generic_attr,
-};
-
-static const struct of_device_id exynos_cpufreq_match[] = {
- {
- .compatible = "samsung,exynos5440-cpufreq",
- },
- {},
-};
-MODULE_DEVICE_TABLE(of, exynos_cpufreq_match);
-
-static int exynos_cpufreq_probe(struct platform_device *pdev)
-{
- int ret = -EINVAL;
- struct device_node *np;
- struct resource res;
- unsigned int cur_frequency;
-
- np = pdev->dev.of_node;
- if (!np)
- return -ENODEV;
-
- dvfs_info = devm_kzalloc(&pdev->dev, sizeof(*dvfs_info), GFP_KERNEL);
- if (!dvfs_info) {
- ret = -ENOMEM;
- goto err_put_node;
- }
-
- dvfs_info->dev = &pdev->dev;
-
- ret = of_address_to_resource(np, 0, &res);
- if (ret)
- goto err_put_node;
-
- dvfs_info->base = devm_ioremap_resource(dvfs_info->dev, &res);
- if (IS_ERR(dvfs_info->base)) {
- ret = PTR_ERR(dvfs_info->base);
- goto err_put_node;
- }
-
- dvfs_info->irq = irq_of_parse_and_map(np, 0);
- if (!dvfs_info->irq) {
- dev_err(dvfs_info->dev, "No cpufreq irq found\n");
- ret = -ENODEV;
- goto err_put_node;
- }
-
- ret = dev_pm_opp_of_add_table(dvfs_info->dev);
- if (ret) {
- dev_err(dvfs_info->dev, "failed to init OPP table: %d\n", ret);
- goto err_put_node;
- }
-
- ret = dev_pm_opp_init_cpufreq_table(dvfs_info->dev,
- &dvfs_info->freq_table);
- if (ret) {
- dev_err(dvfs_info->dev,
- "failed to init cpufreq table: %d\n", ret);
- goto err_free_opp;
- }
- dvfs_info->freq_count = dev_pm_opp_get_opp_count(dvfs_info->dev);
- exynos_sort_descend_freq_table();
-
- if (of_property_read_u32(np, "clock-latency", &dvfs_info->latency))
- dvfs_info->latency = DEF_TRANS_LATENCY;
-
- dvfs_info->cpu_clk = devm_clk_get(dvfs_info->dev, "armclk");
- if (IS_ERR(dvfs_info->cpu_clk)) {
- dev_err(dvfs_info->dev, "Failed to get cpu clock\n");
- ret = PTR_ERR(dvfs_info->cpu_clk);
- goto err_free_table;
- }
-
- cur_frequency = clk_get_rate(dvfs_info->cpu_clk);
- if (!cur_frequency) {
- dev_err(dvfs_info->dev, "Failed to get clock rate\n");
- ret = -EINVAL;
- goto err_free_table;
- }
- cur_frequency /= 1000;
-
- INIT_WORK(&dvfs_info->irq_work, exynos_cpufreq_work);
- ret = devm_request_irq(dvfs_info->dev, dvfs_info->irq,
- exynos_cpufreq_irq, IRQF_TRIGGER_NONE,
- CPUFREQ_NAME, dvfs_info);
- if (ret) {
- dev_err(dvfs_info->dev, "Failed to register IRQ\n");
- goto err_free_table;
- }
-
- ret = init_div_table();
- if (ret) {
- dev_err(dvfs_info->dev, "Failed to initialise div table\n");
- goto err_free_table;
- }
-
- exynos_enable_dvfs(cur_frequency);
- ret = cpufreq_register_driver(&exynos_driver);
- if (ret) {
- dev_err(dvfs_info->dev,
- "%s: failed to register cpufreq driver\n", __func__);
- goto err_free_table;
- }
-
- of_node_put(np);
- dvfs_info->dvfs_enabled = true;
- return 0;
-
-err_free_table:
- dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
-err_free_opp:
- dev_pm_opp_of_remove_table(dvfs_info->dev);
-err_put_node:
- of_node_put(np);
- dev_err(&pdev->dev, "%s: failed initialization\n", __func__);
- return ret;
-}
-
-static int exynos_cpufreq_remove(struct platform_device *pdev)
-{
- cpufreq_unregister_driver(&exynos_driver);
- dev_pm_opp_free_cpufreq_table(dvfs_info->dev, &dvfs_info->freq_table);
- dev_pm_opp_of_remove_table(dvfs_info->dev);
- return 0;
-}
-
-static struct platform_driver exynos_cpufreq_platdrv = {
- .driver = {
- .name = "exynos5440-cpufreq",
- .of_match_table = exynos_cpufreq_match,
- },
- .probe = exynos_cpufreq_probe,
- .remove = exynos_cpufreq_remove,
-};
-module_platform_driver(exynos_cpufreq_platdrv);
-
-MODULE_AUTHOR("Amit Daniel Kachhap <amit.daniel@samsung.com>");
-MODULE_DESCRIPTION("Exynos5440 cpufreq driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/crypto/caam/sg_sw_qm2.h b/drivers/crypto/caam/sg_sw_qm2.h
index 31b440757146..b5b4c12179df 100644
--- a/drivers/crypto/caam/sg_sw_qm2.h
+++ b/drivers/crypto/caam/sg_sw_qm2.h
@@ -35,7 +35,7 @@
#ifndef _SG_SW_QM2_H_
#define _SG_SW_QM2_H_
-#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
static inline void dma_to_qm_sg_one(struct dpaa2_sg_entry *qm_sg_ptr,
dma_addr_t dma, u32 len, u16 offset)
diff --git a/drivers/crypto/caam/sg_sw_sec4.h b/drivers/crypto/caam/sg_sw_sec4.h
index e586ffab8358..dbfa9fce33e0 100644
--- a/drivers/crypto/caam/sg_sw_sec4.h
+++ b/drivers/crypto/caam/sg_sw_sec4.h
@@ -12,7 +12,7 @@
#include "ctrl.h"
#include "regs.h"
#include "sg_sw_qm2.h"
-#include "../../../drivers/staging/fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
struct sec4_sg_entry {
u64 ptr;
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 2a219b1261b1..721e6c57beae 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -363,8 +363,6 @@ static int scmi_dvfs_device_opps_add(const struct scmi_handle *handle,
return domain;
dom = pi->dom_info + domain;
- if (!dom)
- return -EIO;
for (opp = dom->opp, idx = 0; idx < dom->opp_count; idx++, opp++) {
freq = opp->perf * dom->mult_factor;
@@ -394,9 +392,6 @@ static int scmi_dvfs_transition_latency_get(const struct scmi_handle *handle,
return domain;
dom = pi->dom_info + domain;
- if (!dom)
- return -EIO;
-
/* uS to nS */
return dom->opp[dom->opp_count - 1].trans_latency_us * 1000;
}
diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index 50793fda7819..b22ccfb0c991 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -20,7 +20,7 @@
#include <linux/efi-bgrt.h>
struct acpi_table_bgrt bgrt_tab;
-size_t __initdata bgrt_image_size;
+size_t bgrt_image_size;
struct bmp_header {
u16 id;
diff --git a/drivers/firmware/psci_checker.c b/drivers/firmware/psci_checker.c
index bb1c068bff19..346943657962 100644
--- a/drivers/firmware/psci_checker.c
+++ b/drivers/firmware/psci_checker.c
@@ -77,28 +77,6 @@ static int psci_ops_check(void)
return 0;
}
-static int find_cpu_groups(const struct cpumask *cpus,
- const struct cpumask **cpu_groups)
-{
- unsigned int nb = 0;
- cpumask_var_t tmp;
-
- if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
- return -ENOMEM;
- cpumask_copy(tmp, cpus);
-
- while (!cpumask_empty(tmp)) {
- const struct cpumask *cpu_group =
- topology_core_cpumask(cpumask_any(tmp));
-
- cpu_groups[nb++] = cpu_group;
- cpumask_andnot(tmp, tmp, cpu_group);
- }
-
- free_cpumask_var(tmp);
- return nb;
-}
-
/*
* offlined_cpus is a temporary array but passing it as an argument avoids
* multiple allocations.
@@ -166,29 +144,66 @@ static unsigned int down_and_up_cpus(const struct cpumask *cpus,
return err;
}
+static void free_cpu_groups(int num, cpumask_var_t **pcpu_groups)
+{
+ int i;
+ cpumask_var_t *cpu_groups = *pcpu_groups;
+
+ for (i = 0; i < num; ++i)
+ free_cpumask_var(cpu_groups[i]);
+ kfree(cpu_groups);
+}
+
+static int alloc_init_cpu_groups(cpumask_var_t **pcpu_groups)
+{
+ int num_groups = 0;
+ cpumask_var_t tmp, *cpu_groups;
+
+ if (!alloc_cpumask_var(&tmp, GFP_KERNEL))
+ return -ENOMEM;
+
+ cpu_groups = kcalloc(nb_available_cpus, sizeof(cpu_groups),
+ GFP_KERNEL);
+ if (!cpu_groups)
+ return -ENOMEM;
+
+ cpumask_copy(tmp, cpu_online_mask);
+
+ while (!cpumask_empty(tmp)) {
+ const struct cpumask *cpu_group =
+ topology_core_cpumask(cpumask_any(tmp));
+
+ if (!alloc_cpumask_var(&cpu_groups[num_groups], GFP_KERNEL)) {
+ free_cpu_groups(num_groups, &cpu_groups);
+ return -ENOMEM;
+ }
+ cpumask_copy(cpu_groups[num_groups++], cpu_group);
+ cpumask_andnot(tmp, tmp, cpu_group);
+ }
+
+ free_cpumask_var(tmp);
+ *pcpu_groups = cpu_groups;
+
+ return num_groups;
+}
+
static int hotplug_tests(void)
{
- int err;
- cpumask_var_t offlined_cpus;
- int i, nb_cpu_group;
- const struct cpumask **cpu_groups;
+ int i, nb_cpu_group, err = -ENOMEM;
+ cpumask_var_t offlined_cpus, *cpu_groups;
char *page_buf;
- err = -ENOMEM;
if (!alloc_cpumask_var(&offlined_cpus, GFP_KERNEL))
return err;
- /* We may have up to nb_available_cpus cpu_groups. */
- cpu_groups = kmalloc_array(nb_available_cpus, sizeof(*cpu_groups),
- GFP_KERNEL);
- if (!cpu_groups)
+
+ nb_cpu_group = alloc_init_cpu_groups(&cpu_groups);
+ if (nb_cpu_group < 0)
goto out_free_cpus;
page_buf = (char *)__get_free_page(GFP_KERNEL);
if (!page_buf)
goto out_free_cpu_groups;
err = 0;
- nb_cpu_group = find_cpu_groups(cpu_online_mask, cpu_groups);
-
/*
* Of course the last CPU cannot be powered down and cpu_down() should
* refuse doing that.
@@ -212,7 +227,7 @@ static int hotplug_tests(void)
free_page((unsigned long)page_buf);
out_free_cpu_groups:
- kfree(cpu_groups);
+ free_cpu_groups(nb_cpu_group, &cpu_groups);
out_free_cpus:
free_cpumask_var(offlined_cpus);
return err;
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 6692888f04cf..a200a2174611 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -21,6 +21,10 @@
#define MBOX_DATA28(msg) ((msg) & ~0xf)
#define MBOX_CHAN_PROPERTY 8
+#define MAX_RPI_FW_PROP_BUF_SIZE 32
+
+static struct platform_device *rpi_hwmon;
+
struct rpi_firmware {
struct mbox_client cl;
struct mbox_chan *chan; /* The property channel. */
@@ -143,18 +147,22 @@ int rpi_firmware_property(struct rpi_firmware *fw,
/* Single tags are very small (generally 8 bytes), so the
* stack should be safe.
*/
- u8 data[buf_size + sizeof(struct rpi_firmware_property_tag_header)];
+ u8 data[sizeof(struct rpi_firmware_property_tag_header) +
+ MAX_RPI_FW_PROP_BUF_SIZE];
struct rpi_firmware_property_tag_header *header =
(struct rpi_firmware_property_tag_header *)data;
int ret;
+ if (WARN_ON(buf_size > sizeof(data) - sizeof(*header)))
+ return -EINVAL;
+
header->tag = tag;
header->buf_size = buf_size;
header->req_resp_size = 0;
memcpy(data + sizeof(struct rpi_firmware_property_tag_header),
tag_data, buf_size);
- ret = rpi_firmware_property_list(fw, &data, sizeof(data));
+ ret = rpi_firmware_property_list(fw, &data, buf_size + sizeof(*header));
memcpy(tag_data,
data + sizeof(struct rpi_firmware_property_tag_header),
buf_size);
@@ -183,6 +191,20 @@ rpi_firmware_print_firmware_revision(struct rpi_firmware *fw)
}
}
+static void
+rpi_register_hwmon_driver(struct device *dev, struct rpi_firmware *fw)
+{
+ u32 packet;
+ int ret = rpi_firmware_property(fw, RPI_FIRMWARE_GET_THROTTLED,
+ &packet, sizeof(packet));
+
+ if (ret)
+ return;
+
+ rpi_hwmon = platform_device_register_data(dev, "raspberrypi-hwmon",
+ -1, NULL, 0);
+}
+
static int rpi_firmware_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -209,6 +231,7 @@ static int rpi_firmware_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, fw);
rpi_firmware_print_firmware_revision(fw);
+ rpi_register_hwmon_driver(dev, fw);
return 0;
}
@@ -217,6 +240,8 @@ static int rpi_firmware_remove(struct platform_device *pdev)
{
struct rpi_firmware *fw = platform_get_drvdata(pdev);
+ platform_device_unregister(rpi_hwmon);
+ rpi_hwmon = NULL;
mbox_free_channel(fw->chan);
return 0;
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index ccf42663a908..81da17a42dc9 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -1320,6 +1320,16 @@ config SENSORS_PWM_FAN
This driver can also be built as a module. If so, the module
will be called pwm-fan.
+config SENSORS_RASPBERRYPI_HWMON
+ tristate "Raspberry Pi voltage monitor"
+ depends on RASPBERRYPI_FIRMWARE || (COMPILE_TEST && !RASPBERRYPI_FIRMWARE)
+ help
+ If you say yes here you get support for voltage sensor on the
+ Raspberry Pi.
+
+ This driver can also be built as a module. If so, the module
+ will be called raspberrypi-hwmon.
+
config SENSORS_SHT15
tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
depends on GPIOLIB || COMPILE_TEST
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index 842c92f83ce6..93f7f41ea4ad 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -143,6 +143,7 @@ obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o
obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o
+obj-$(CONFIG_SENSORS_RASPBERRYPI_HWMON) += raspberrypi-hwmon.o
obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o
obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o
obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o
diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c
new file mode 100644
index 000000000000..fb4e4a6bb1f6
--- /dev/null
+++ b/drivers/hwmon/raspberrypi-hwmon.c
@@ -0,0 +1,166 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Raspberry Pi voltage sensor driver
+ *
+ * Based on firmware/raspberrypi.c by Noralf Trønnes
+ *
+ * Copyright (C) 2018 Stefan Wahren <stefan.wahren@i2se.com>
+ */
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/hwmon.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <soc/bcm2835/raspberrypi-firmware.h>
+
+#define UNDERVOLTAGE_STICKY_BIT BIT(16)
+
+struct rpi_hwmon_data {
+ struct device *hwmon_dev;
+ struct rpi_firmware *fw;
+ u32 last_throttled;
+ struct delayed_work get_values_poll_work;
+};
+
+static void rpi_firmware_get_throttled(struct rpi_hwmon_data *data)
+{
+ u32 new_uv, old_uv, value;
+ int ret;
+
+ /* Request firmware to clear sticky bits */
+ value = 0xffff;
+
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+ &value, sizeof(value));
+ if (ret) {
+ dev_err_once(data->hwmon_dev, "Failed to get throttled (%d)\n",
+ ret);
+ return;
+ }
+
+ new_uv = value & UNDERVOLTAGE_STICKY_BIT;
+ old_uv = data->last_throttled & UNDERVOLTAGE_STICKY_BIT;
+ data->last_throttled = value;
+
+ if (new_uv == old_uv)
+ return;
+
+ if (new_uv)
+ dev_crit(data->hwmon_dev, "Undervoltage detected!\n");
+ else
+ dev_info(data->hwmon_dev, "Voltage normalised\n");
+
+ sysfs_notify(&data->hwmon_dev->kobj, NULL, "in0_lcrit_alarm");
+}
+
+static void get_values_poll(struct work_struct *work)
+{
+ struct rpi_hwmon_data *data;
+
+ data = container_of(work, struct rpi_hwmon_data,
+ get_values_poll_work.work);
+
+ rpi_firmware_get_throttled(data);
+
+ /*
+ * We can't run faster than the sticky shift (100ms) since we get
+ * flipping in the sticky bits that are cleared.
+ */
+ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+}
+
+static int rpi_read(struct device *dev, enum hwmon_sensor_types type,
+ u32 attr, int channel, long *val)
+{
+ struct rpi_hwmon_data *data = dev_get_drvdata(dev);
+
+ *val = !!(data->last_throttled & UNDERVOLTAGE_STICKY_BIT);
+ return 0;
+}
+
+static umode_t rpi_is_visible(const void *_data, enum hwmon_sensor_types type,
+ u32 attr, int channel)
+{
+ return 0444;
+}
+
+static const u32 rpi_in_config[] = {
+ HWMON_I_LCRIT_ALARM,
+ 0
+};
+
+static const struct hwmon_channel_info rpi_in = {
+ .type = hwmon_in,
+ .config = rpi_in_config,
+};
+
+static const struct hwmon_channel_info *rpi_info[] = {
+ &rpi_in,
+ NULL
+};
+
+static const struct hwmon_ops rpi_hwmon_ops = {
+ .is_visible = rpi_is_visible,
+ .read = rpi_read,
+};
+
+static const struct hwmon_chip_info rpi_chip_info = {
+ .ops = &rpi_hwmon_ops,
+ .info = rpi_info,
+};
+
+static int rpi_hwmon_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rpi_hwmon_data *data;
+ int ret;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ /* Parent driver assure that firmware is correct */
+ data->fw = dev_get_drvdata(dev->parent);
+
+ /* Init throttled */
+ ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
+ &data->last_throttled,
+ sizeof(data->last_throttled));
+
+ data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
+ data,
+ &rpi_chip_info,
+ NULL);
+
+ INIT_DELAYED_WORK(&data->get_values_poll_work, get_values_poll);
+ platform_set_drvdata(pdev, data);
+
+ if (!PTR_ERR_OR_ZERO(data->hwmon_dev))
+ schedule_delayed_work(&data->get_values_poll_work, 2 * HZ);
+
+ return PTR_ERR_OR_ZERO(data->hwmon_dev);
+}
+
+static int rpi_hwmon_remove(struct platform_device *pdev)
+{
+ struct rpi_hwmon_data *data = platform_get_drvdata(pdev);
+
+ cancel_delayed_work_sync(&data->get_values_poll_work);
+
+ return 0;
+}
+
+static struct platform_driver rpi_hwmon_driver = {
+ .probe = rpi_hwmon_probe,
+ .remove = rpi_hwmon_remove,
+ .driver = {
+ .name = "raspberrypi-hwmon",
+ },
+};
+module_platform_driver(rpi_hwmon_driver);
+
+MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
+MODULE_DESCRIPTION("Raspberry Pi voltage sensor driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/infiniband/Kconfig b/drivers/infiniband/Kconfig
index d160d2d1f3a3..abb6660c099c 100644
--- a/drivers/infiniband/Kconfig
+++ b/drivers/infiniband/Kconfig
@@ -36,7 +36,7 @@ config INFINIBAND_USER_ACCESS
rdma-core <https://github.com/linux-rdma/rdma-core>.
config INFINIBAND_USER_ACCESS_UCM
- bool "Userspace CM (UCM, DEPRECATED)"
+ tristate "Userspace CM (UCM, DEPRECATED)"
depends on BROKEN || COMPILE_TEST
depends on INFINIBAND_USER_ACCESS
help
diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c
index fbe7198a715a..bedd5fba33b0 100644
--- a/drivers/infiniband/hw/hfi1/affinity.c
+++ b/drivers/infiniband/hw/hfi1/affinity.c
@@ -198,7 +198,7 @@ int node_affinity_init(void)
while ((dev = pci_get_device(ids->vendor, ids->device, dev))) {
node = pcibus_to_node(dev->bus);
if (node < 0)
- node = numa_node_id();
+ goto out;
hfi1_per_node_cntr[node]++;
}
@@ -206,6 +206,18 @@ int node_affinity_init(void)
}
return 0;
+
+out:
+ /*
+ * Invalid PCI NUMA node information found, note it, and populate
+ * our database 1:1.
+ */
+ pr_err("HFI: Invalid PCI NUMA node. Performance may be affected\n");
+ pr_err("HFI: System BIOS may need to be upgraded\n");
+ for (node = 0; node < node_affinity.num_possible_nodes; node++)
+ hfi1_per_node_cntr[node] = 1;
+
+ return 0;
}
static void node_affinity_destroy(struct hfi1_affinity_node *entry)
@@ -622,8 +634,14 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd)
int curr_cpu, possible, i, ret;
bool new_entry = false;
- if (node < 0)
- node = numa_node_id();
+ /*
+ * If the BIOS does not have the NUMA node information set, select
+ * NUMA 0 so we get consistent performance.
+ */
+ if (node < 0) {
+ dd_dev_err(dd, "Invalid PCI NUMA node. Performance may be affected\n");
+ node = 0;
+ }
dd->node = node;
local_mask = cpumask_of_node(dd->node);
diff --git a/drivers/input/serio/ams_delta_serio.c b/drivers/input/serio/ams_delta_serio.c
index 3df501c3421b..f8663d7891f2 100644
--- a/drivers/input/serio/ams_delta_serio.c
+++ b/drivers/input/serio/ams_delta_serio.c
@@ -20,32 +20,33 @@
* However, when used with the E3 mailboard that producecs non-standard
* scancodes, a custom key table must be prepared and loaded from userspace.
*/
-#include <linux/gpio.h>
#include <linux/irq.h>
+#include <linux/platform_data/ams-delta-fiq.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/serio.h>
#include <linux/slab.h>
#include <linux/module.h>
-#include <asm/mach-types.h>
-#include <mach/board-ams-delta.h>
-
-#include <mach/ams-delta-fiq.h>
+#define DRIVER_NAME "ams-delta-serio"
MODULE_AUTHOR("Matt Callow");
MODULE_DESCRIPTION("AMS Delta (E3) keyboard port driver");
MODULE_LICENSE("GPL");
-static struct serio *ams_delta_serio;
+struct ams_delta_serio {
+ struct serio *serio;
+ struct regulator *vcc;
+ unsigned int *fiq_buffer;
+};
-static int check_data(int data)
+static int check_data(struct serio *serio, int data)
{
int i, parity = 0;
/* check valid stop bit */
if (!(data & 0x400)) {
- dev_warn(&ams_delta_serio->dev,
- "invalid stop bit, data=0x%X\n",
- data);
+ dev_warn(&serio->dev, "invalid stop bit, data=0x%X\n", data);
return SERIO_FRAME;
}
/* calculate the parity */
@@ -55,9 +56,9 @@ static int check_data(int data)
}
/* it should be odd */
if (!(parity & 0x01)) {
- dev_warn(&ams_delta_serio->dev,
- "parity check failed, data=0x%X parity=0x%X\n",
- data, parity);
+ dev_warn(&serio->dev,
+ "parity check failed, data=0x%X parity=0x%X\n", data,
+ parity);
return SERIO_PARITY;
}
return 0;
@@ -65,127 +66,130 @@ static int check_data(int data)
static irqreturn_t ams_delta_serio_interrupt(int irq, void *dev_id)
{
- int *circ_buff = &fiq_buffer[FIQ_CIRC_BUFF];
+ struct ams_delta_serio *priv = dev_id;
+ int *circ_buff = &priv->fiq_buffer[FIQ_CIRC_BUFF];
int data, dfl;
u8 scancode;
- fiq_buffer[FIQ_IRQ_PEND] = 0;
+ priv->fiq_buffer[FIQ_IRQ_PEND] = 0;
/*
* Read data from the circular buffer, check it
* and then pass it on the serio
*/
- while (fiq_buffer[FIQ_KEYS_CNT] > 0) {
+ while (priv->fiq_buffer[FIQ_KEYS_CNT] > 0) {
- data = circ_buff[fiq_buffer[FIQ_HEAD_OFFSET]++];
- fiq_buffer[FIQ_KEYS_CNT]--;
- if (fiq_buffer[FIQ_HEAD_OFFSET] == fiq_buffer[FIQ_BUF_LEN])
- fiq_buffer[FIQ_HEAD_OFFSET] = 0;
+ data = circ_buff[priv->fiq_buffer[FIQ_HEAD_OFFSET]++];
+ priv->fiq_buffer[FIQ_KEYS_CNT]--;
+ if (priv->fiq_buffer[FIQ_HEAD_OFFSET] ==
+ priv->fiq_buffer[FIQ_BUF_LEN])
+ priv->fiq_buffer[FIQ_HEAD_OFFSET] = 0;
- dfl = check_data(data);
+ dfl = check_data(priv->serio, data);
scancode = (u8) (data >> 1) & 0xFF;
- serio_interrupt(ams_delta_serio, scancode, dfl);
+ serio_interrupt(priv->serio, scancode, dfl);
}
return IRQ_HANDLED;
}
static int ams_delta_serio_open(struct serio *serio)
{
- /* enable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 1);
+ struct ams_delta_serio *priv = serio->port_data;
- return 0;
+ /* enable keyboard */
+ return regulator_enable(priv->vcc);
}
static void ams_delta_serio_close(struct serio *serio)
{
+ struct ams_delta_serio *priv = serio->port_data;
+
/* disable keyboard */
- gpio_set_value(AMS_DELTA_GPIO_PIN_KEYBRD_PWR, 0);
+ regulator_disable(priv->vcc);
}
-static const struct gpio ams_delta_gpios[] __initconst_or_module = {
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATA,
- .flags = GPIOF_DIR_IN,
- .label = "serio-data",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_CLK,
- .flags = GPIOF_DIR_IN,
- .label = "serio-clock",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_PWR,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-power",
- },
- {
- .gpio = AMS_DELTA_GPIO_PIN_KEYBRD_DATAOUT,
- .flags = GPIOF_OUT_INIT_LOW,
- .label = "serio-dataout",
- },
-};
-
-static int __init ams_delta_serio_init(void)
+static int ams_delta_serio_init(struct platform_device *pdev)
{
- int err;
-
- if (!machine_is_ams_delta())
- return -ENODEV;
+ struct ams_delta_serio *priv;
+ struct serio *serio;
+ int irq, err;
- ams_delta_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
- if (!ams_delta_serio)
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
return -ENOMEM;
- ams_delta_serio->id.type = SERIO_8042;
- ams_delta_serio->open = ams_delta_serio_open;
- ams_delta_serio->close = ams_delta_serio_close;
- strlcpy(ams_delta_serio->name, "AMS DELTA keyboard adapter",
- sizeof(ams_delta_serio->name));
- strlcpy(ams_delta_serio->phys, "GPIO/serio0",
- sizeof(ams_delta_serio->phys));
-
- err = gpio_request_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
- if (err) {
- pr_err("ams_delta_serio: Couldn't request gpio pins\n");
- goto serio;
+ priv->fiq_buffer = pdev->dev.platform_data;
+ if (!priv->fiq_buffer)
+ return -EINVAL;
+
+ priv->vcc = devm_regulator_get(&pdev->dev, "vcc");
+ if (IS_ERR(priv->vcc)) {
+ err = PTR_ERR(priv->vcc);
+ dev_err(&pdev->dev, "regulator request failed (%d)\n", err);
+ /*
+ * When running on a non-dt platform and requested regulator
+ * is not available, devm_regulator_get() never returns
+ * -EPROBE_DEFER as it is not able to justify if the regulator
+ * may still appear later. On the other hand, the board can
+ * still set full constriants flag at late_initcall in order
+ * to instruct devm_regulator_get() to returnn a dummy one
+ * if sufficient. Hence, if we get -ENODEV here, let's convert
+ * it to -EPROBE_DEFER and wait for the board to decide or
+ * let Deferred Probe infrastructure handle this error.
+ */
+ if (err == -ENODEV)
+ err = -EPROBE_DEFER;
+ return err;
}
- err = request_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- ams_delta_serio_interrupt, IRQ_TYPE_EDGE_RISING,
- "ams-delta-serio", 0);
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0)
+ return -ENXIO;
+
+ err = devm_request_irq(&pdev->dev, irq, ams_delta_serio_interrupt,
+ IRQ_TYPE_EDGE_RISING, DRIVER_NAME, priv);
if (err < 0) {
- pr_err("ams_delta_serio: couldn't request gpio interrupt %d\n",
- gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK));
- goto gpio;
+ dev_err(&pdev->dev, "IRQ request failed (%d)\n", err);
+ return err;
}
- /*
- * Since GPIO register handling for keyboard clock pin is performed
- * at FIQ level, switch back from edge to simple interrupt handler
- * to avoid bad interaction.
- */
- irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
- handle_simple_irq);
- serio_register_port(ams_delta_serio);
- dev_info(&ams_delta_serio->dev, "%s\n", ams_delta_serio->name);
+ serio = kzalloc(sizeof(*serio), GFP_KERNEL);
+ if (!serio)
+ return -ENOMEM;
+
+ priv->serio = serio;
+
+ serio->id.type = SERIO_8042;
+ serio->open = ams_delta_serio_open;
+ serio->close = ams_delta_serio_close;
+ strlcpy(serio->name, "AMS DELTA keyboard adapter", sizeof(serio->name));
+ strlcpy(serio->phys, dev_name(&pdev->dev), sizeof(serio->phys));
+ serio->dev.parent = &pdev->dev;
+ serio->port_data = priv;
+
+ serio_register_port(serio);
+
+ platform_set_drvdata(pdev, priv);
+
+ dev_info(&serio->dev, "%s\n", serio->name);
return 0;
-gpio:
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
-serio:
- kfree(ams_delta_serio);
- return err;
}
-module_init(ams_delta_serio_init);
-static void __exit ams_delta_serio_exit(void)
+static int ams_delta_serio_exit(struct platform_device *pdev)
{
- serio_unregister_port(ams_delta_serio);
- free_irq(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK), 0);
- gpio_free_array(ams_delta_gpios,
- ARRAY_SIZE(ams_delta_gpios));
+ struct ams_delta_serio *priv = platform_get_drvdata(pdev);
+
+ serio_unregister_port(priv->serio);
+
+ return 0;
}
-module_exit(ams_delta_serio_exit);
+
+static struct platform_driver ams_delta_serio_driver = {
+ .probe = ams_delta_serio_init,
+ .remove = ams_delta_serio_exit,
+ .driver = {
+ .name = DRIVER_NAME
+ },
+};
+module_platform_driver(ams_delta_serio_driver);
diff --git a/drivers/memory/tegra/mc.c b/drivers/memory/tegra/mc.c
index bb93cc53554e..bd25faf6d13d 100644
--- a/drivers/memory/tegra/mc.c
+++ b/drivers/memory/tegra/mc.c
@@ -672,13 +672,6 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
- err = tegra_mc_reset_setup(mc);
- if (err < 0) {
- dev_err(&pdev->dev, "failed to register reset controller: %d\n",
- err);
- return err;
- }
-
mc->irq = platform_get_irq(pdev, 0);
if (mc->irq < 0) {
dev_err(&pdev->dev, "interrupt not specified\n");
@@ -697,13 +690,16 @@ static int tegra_mc_probe(struct platform_device *pdev)
return err;
}
+ err = tegra_mc_reset_setup(mc);
+ if (err < 0)
+ dev_err(&pdev->dev, "failed to register reset controller: %d\n",
+ err);
+
if (IS_ENABLED(CONFIG_TEGRA_IOMMU_SMMU)) {
mc->smmu = tegra_smmu_probe(&pdev->dev, mc->soc->smmu, mc);
- if (IS_ERR(mc->smmu)) {
+ if (IS_ERR(mc->smmu))
dev_err(&pdev->dev, "failed to probe SMMU: %ld\n",
PTR_ERR(mc->smmu));
- return PTR_ERR(mc->smmu);
- }
}
return 0;
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c
index 632651f4b6e8..2250d03ea17f 100644
--- a/drivers/memory/ti-emif-pm.c
+++ b/drivers/memory/ti-emif-pm.c
@@ -249,6 +249,34 @@ static const struct of_device_id ti_emif_of_match[] = {
};
MODULE_DEVICE_TABLE(of, ti_emif_of_match);
+#ifdef CONFIG_PM_SLEEP
+static int ti_emif_resume(struct device *dev)
+{
+ unsigned long tmp =
+ __raw_readl((void *)emif_instance->ti_emif_sram_virt);
+
+ /*
+ * Check to see if what we are copying is already present in the
+ * first byte at the destination, only copy if it is not which
+ * indicates we have lost context and sram no longer contains
+ * the PM code
+ */
+ if (tmp != ti_emif_sram)
+ ti_emif_push_sram(dev, emif_instance);
+
+ return 0;
+}
+
+static int ti_emif_suspend(struct device *dev)
+{
+ /*
+ * The contents will be present in DDR hence no need to
+ * explicitly save
+ */
+ return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
static int ti_emif_probe(struct platform_device *pdev)
{
int ret;
@@ -308,12 +336,17 @@ static int ti_emif_remove(struct platform_device *pdev)
return 0;
}
+static const struct dev_pm_ops ti_emif_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(ti_emif_suspend, ti_emif_resume)
+};
+
static struct platform_driver ti_emif_driver = {
.probe = ti_emif_probe,
.remove = ti_emif_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = of_match_ptr(ti_emif_of_match),
+ .pm = &ti_emif_pm_ops,
},
};
module_platform_driver(ti_emif_driver);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 45c329694a5e..22547d7a84ea 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -367,6 +367,10 @@ static ssize_t vol_cdev_write(struct file *file, const char __user *buf,
return count;
}
+ /*
+ * We voluntarily do not take into account the skip_check flag
+ * as we want to make sure what we wrote was correctly written.
+ */
err = ubi_check_volume(ubi, vol->vol_id);
if (err < 0)
return err;
@@ -622,6 +626,13 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
req->vol_type != UBI_STATIC_VOLUME)
goto bad;
+ if (req->flags & ~UBI_VOL_VALID_FLGS)
+ goto bad;
+
+ if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG &&
+ req->vol_type != UBI_STATIC_VOLUME)
+ goto bad;
+
if (req->alignment > ubi->leb_size)
goto bad;
diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c
index d4b2e8744498..e9e9ecbcedcc 100644
--- a/drivers/mtd/ubi/kapi.c
+++ b/drivers/mtd/ubi/kapi.c
@@ -202,7 +202,7 @@ struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode)
desc->mode = mode;
mutex_lock(&ubi->ckvol_mutex);
- if (!vol->checked) {
+ if (!vol->checked && !vol->skip_check) {
/* This is the first open - check the volume */
err = ubi_check_volume(ubi, vol_id);
if (err < 0) {
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index 195ff8ca8211..b5fe8f82281b 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -45,6 +45,11 @@ enum {
* Volume flags used in the volume table record.
*
* @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
+ * @UBI_VTBL_SKIP_CRC_CHECK_FLG: skip the CRC check done on a static volume at
+ * open time. Should only be set on volumes that
+ * are used by upper layers doing this kind of
+ * check. Main use-case for this flag is
+ * boot-time reduction
*
* %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
* table. UBI automatically re-sizes the volume which has this flag and makes
@@ -76,6 +81,7 @@ enum {
*/
enum {
UBI_VTBL_AUTORESIZE_FLG = 0x01,
+ UBI_VTBL_SKIP_CRC_CHECK_FLG = 0x02,
};
/*
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index f5ba97c46160..d47b9e436e67 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -327,6 +327,9 @@ struct ubi_eba_leb_desc {
* atomic LEB change
*
* @eba_tbl: EBA table of this volume (LEB->PEB mapping)
+ * @skip_check: %1 if CRC check of this static volume should be skipped.
+ * Directly reflects the presence of the
+ * %UBI_VTBL_SKIP_CRC_CHECK_FLG flag in the vtbl entry
* @checked: %1 if this static volume was checked
* @corrupted: %1 if the volume is corrupted (static volumes only)
* @upd_marker: %1 if the update marker is set for this volume
@@ -374,6 +377,7 @@ struct ubi_volume {
void *upd_buf;
struct ubi_eba_table *eba_tbl;
+ unsigned int skip_check:1;
unsigned int checked:1;
unsigned int corrupted:1;
unsigned int upd_marker:1;
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 0be516780e92..729588b94e41 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -174,6 +174,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vol->dev.class = &ubi_class;
vol->dev.groups = volume_dev_groups;
+ if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG)
+ vol->skip_check = 1;
+
spin_lock(&ubi->volumes_lock);
if (vol_id == UBI_VOL_NUM_AUTO) {
/* Find unused volume ID */
@@ -299,6 +302,10 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
vtbl_rec.vol_type = UBI_VID_DYNAMIC;
else
vtbl_rec.vol_type = UBI_VID_STATIC;
+
+ if (vol->skip_check)
+ vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG;
+
memcpy(vtbl_rec.name, vol->name, vol->name_len);
err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
@@ -733,6 +740,11 @@ static int self_check_volume(struct ubi_device *ubi, int vol_id)
ubi_err(ubi, "bad used_bytes");
goto fail;
}
+
+ if (vol->skip_check) {
+ ubi_err(ubi, "bad skip_check");
+ goto fail;
+ }
} else {
if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {
ubi_err(ubi, "bad used_ebs");
diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c
index 94d7a865b135..1bc82154bb18 100644
--- a/drivers/mtd/ubi/vtbl.c
+++ b/drivers/mtd/ubi/vtbl.c
@@ -560,6 +560,9 @@ static int init_volumes(struct ubi_device *ubi,
vol->name[vol->name_len] = '\0';
vol->vol_id = i;
+ if (vtbl[i].flags & UBI_VTBL_SKIP_CRC_CHECK_FLG)
+ vol->skip_check = 1;
+
if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
/* Auto re-size flag may be set only for one volume */
if (ubi->autoresize_vol_id != -1) {
@@ -579,6 +582,16 @@ static int init_volumes(struct ubi_device *ubi,
reserved_pebs += vol->reserved_pebs;
/*
+ * We use ubi->peb_count and not vol->reserved_pebs because
+ * we want to keep the code simple. Otherwise we'd have to
+ * resize/check the bitmap upon volume resize too.
+ * Allocating a few bytes more does not hurt.
+ */
+ err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
+ if (err)
+ return err;
+
+ /*
* In case of dynamic volume UBI knows nothing about how many
* data is stored there. So assume the whole volume is used.
*/
@@ -620,16 +633,6 @@ static int init_volumes(struct ubi_device *ubi,
(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
vol->used_bytes += av->last_data_size;
vol->last_eb_bytes = av->last_data_size;
-
- /*
- * We use ubi->peb_count and not vol->reserved_pebs because
- * we want to keep the code simple. Otherwise we'd have to
- * resize/check the bitmap upon volume resize too.
- * Allocating a few bytes more does not hurt.
- */
- err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
- if (err)
- return err;
}
/* And add the layout volume */
diff --git a/drivers/net/ethernet/smsc/smc911x.c b/drivers/net/ethernet/smsc/smc911x.c
index 05157442a980..b1b53f6c452f 100644
--- a/drivers/net/ethernet/smsc/smc911x.c
+++ b/drivers/net/ethernet/smsc/smc911x.c
@@ -74,7 +74,6 @@ static const char version[] =
#include <linux/skbuff.h>
#include <linux/dmaengine.h>
-#include <linux/dma/pxa-dma.h>
#include <asm/io.h>
@@ -1795,7 +1794,6 @@ static int smc911x_probe(struct net_device *dev)
#ifdef SMC_USE_DMA
struct dma_slave_config config;
dma_cap_mask_t mask;
- struct pxad_param param;
#endif
DBG(SMC_DEBUG_FUNC, dev, "--> %s\n", __func__);
@@ -1971,15 +1969,8 @@ static int smc911x_probe(struct net_device *dev)
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- param.prio = PXAD_PRIO_LOWEST;
- param.drcmr = -1UL;
-
- lp->rxdma =
- dma_request_slave_channel_compat(mask, pxad_filter_fn,
- &param, &dev->dev, "rx");
- lp->txdma =
- dma_request_slave_channel_compat(mask, pxad_filter_fn,
- &param, &dev->dev, "tx");
+ lp->rxdma = dma_request_channel(mask, NULL, NULL);
+ lp->txdma = dma_request_channel(mask, NULL, NULL);
lp->rxdma_active = 0;
lp->txdma_active = 0;
diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c
index 080428762858..b944828f9ea3 100644
--- a/drivers/net/ethernet/smsc/smc91x.c
+++ b/drivers/net/ethernet/smsc/smc91x.c
@@ -2019,17 +2019,10 @@ static int smc_probe(struct net_device *dev, void __iomem *ioaddr,
# endif
if (lp->cfg.flags & SMC91X_USE_DMA) {
dma_cap_mask_t mask;
- struct pxad_param param;
dma_cap_zero(mask);
dma_cap_set(DMA_SLAVE, mask);
- param.prio = PXAD_PRIO_LOWEST;
- param.drcmr = -1UL;
-
- lp->dma_chan =
- dma_request_slave_channel_compat(mask, pxad_filter_fn,
- &param, &dev->dev,
- "data");
+ lp->dma_chan = dma_request_channel(mask, NULL, NULL);
}
#endif
diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h
index b337ee97e0c0..a27352229fc2 100644
--- a/drivers/net/ethernet/smsc/smc91x.h
+++ b/drivers/net/ethernet/smsc/smc91x.h
@@ -301,7 +301,6 @@ struct smc_local {
* as RX which can overrun memory and lose packets.
*/
#include <linux/dma-mapping.h>
-#include <linux/dma/pxa-dma.h>
#ifdef SMC_insl
#undef SMC_insl
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index a4d262db9945..504d252716f2 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -286,7 +286,7 @@ config PWM_MTK_DISP
config PWM_MEDIATEK
tristate "MediaTek PWM support"
- depends on ARCH_MEDIATEK || COMPILE_TEST
+ depends on ARCH_MEDIATEK || RALINK || COMPILE_TEST
help
Generic PWM framework driver for Mediatek ARM SoC.
diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c
index 771859aca4be..7c8d6a168ceb 100644
--- a/drivers/pwm/pwm-berlin.c
+++ b/drivers/pwm/pwm-berlin.c
@@ -21,8 +21,18 @@
#define BERLIN_PWM_EN 0x0
#define BERLIN_PWM_ENABLE BIT(0)
#define BERLIN_PWM_CONTROL 0x4
-#define BERLIN_PWM_PRESCALE_MASK 0x7
-#define BERLIN_PWM_PRESCALE_MAX 4096
+/*
+ * The prescaler claims to support 8 different moduli, configured using the
+ * low three bits of PWM_CONTROL. (Sequentially, they are 1, 4, 8, 16, 64,
+ * 256, 1024, and 4096.) However, the moduli from 4 to 1024 appear to be
+ * implemented by internally shifting TCNT left without adding additional
+ * bits. So, the max TCNT that actually works for a modulus of 4 is 0x3fff;
+ * for 8, 0x1fff; and so on. This means that those moduli are entirely
+ * useless, as we could just do the shift ourselves. The 4096 modulus is
+ * implemented with a real prescaler, so we do use that, but we treat it
+ * as a flag instead of pretending the modulus is actually configurable.
+ */
+#define BERLIN_PWM_PRESCALE_4096 0x7
#define BERLIN_PWM_INVERT_POLARITY BIT(3)
#define BERLIN_PWM_DUTY 0x8
#define BERLIN_PWM_TCNT 0xc
@@ -46,10 +56,6 @@ static inline struct berlin_pwm_chip *to_berlin_pwm_chip(struct pwm_chip *chip)
return container_of(chip, struct berlin_pwm_chip, chip);
}
-static const u32 prescaler_table[] = {
- 1, 4, 8, 16, 64, 256, 1024, 4096
-};
-
static inline u32 berlin_pwm_readl(struct berlin_pwm_chip *chip,
unsigned int channel, unsigned long offset)
{
@@ -86,33 +92,32 @@ static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev,
int duty_ns, int period_ns)
{
struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip);
- unsigned int prescale;
+ bool prescale_4096 = false;
u32 value, duty, period;
- u64 cycles, tmp;
+ u64 cycles;
cycles = clk_get_rate(pwm->clk);
cycles *= period_ns;
do_div(cycles, NSEC_PER_SEC);
- for (prescale = 0; prescale < ARRAY_SIZE(prescaler_table); prescale++) {
- tmp = cycles;
- do_div(tmp, prescaler_table[prescale]);
+ if (cycles > BERLIN_PWM_MAX_TCNT) {
+ prescale_4096 = true;
+ cycles >>= 12; // Prescaled by 4096
- if (tmp <= BERLIN_PWM_MAX_TCNT)
- break;
+ if (cycles > BERLIN_PWM_MAX_TCNT)
+ return -ERANGE;
}
- if (tmp > BERLIN_PWM_MAX_TCNT)
- return -ERANGE;
-
- period = tmp;
- cycles = tmp * duty_ns;
+ period = cycles;
+ cycles *= duty_ns;
do_div(cycles, period_ns);
duty = cycles;
value = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL);
- value &= ~BERLIN_PWM_PRESCALE_MASK;
- value |= prescale;
+ if (prescale_4096)
+ value |= BERLIN_PWM_PRESCALE_4096;
+ else
+ value &= ~BERLIN_PWM_PRESCALE_4096;
berlin_pwm_writel(pwm, pwm_dev->hwpwm, value, BERLIN_PWM_CONTROL);
berlin_pwm_writel(pwm, pwm_dev->hwpwm, duty, BERLIN_PWM_DUTY);
diff --git a/drivers/pwm/pwm-cros-ec.c b/drivers/pwm/pwm-cros-ec.c
index 9c13694eaa24..98f6ac6cf6ab 100644
--- a/drivers/pwm/pwm-cros-ec.c
+++ b/drivers/pwm/pwm-cros-ec.c
@@ -1,11 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2016 Google, 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.
- *
* Expose a PWM controlled by the ChromeOS EC to the host processor.
+ *
+ * Copyright (C) 2016 Google, Inc.
*/
#include <linux/module.h>
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
index 557b4ea16796..883378d055c6 100644
--- a/drivers/pwm/pwm-fsl-ftm.c
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_address.h>
+#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pwm.h>
@@ -75,6 +76,10 @@ enum fsl_pwm_clk {
FSL_PWM_CLK_MAX
};
+struct fsl_ftm_soc {
+ bool has_enable_bits;
+};
+
struct fsl_pwm_chip {
struct pwm_chip chip;
@@ -87,7 +92,10 @@ struct fsl_pwm_chip {
int period_ns;
+ struct clk *ipg_clk;
struct clk *clk[FSL_PWM_CLK_MAX];
+
+ const struct fsl_ftm_soc *soc;
};
static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
@@ -97,16 +105,32 @@ static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
+ int ret;
struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
- return clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+ ret = clk_prepare_enable(fpc->ipg_clk);
+ if (!ret && fpc->soc->has_enable_bits) {
+ mutex_lock(&fpc->lock);
+ regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16),
+ BIT(pwm->hwpwm + 16));
+ mutex_unlock(&fpc->lock);
+ }
+
+ return ret;
}
static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct fsl_pwm_chip *fpc = to_fsl_chip(chip);
- clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+ if (fpc->soc->has_enable_bits) {
+ mutex_lock(&fpc->lock);
+ regmap_update_bits(fpc->regmap, FTM_SC, BIT(pwm->hwpwm + 16),
+ 0);
+ mutex_unlock(&fpc->lock);
+ }
+
+ clk_disable_unprepare(fpc->ipg_clk);
}
static int fsl_pwm_calculate_default_ps(struct fsl_pwm_chip *fpc,
@@ -363,7 +387,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
{
int ret;
- ret = clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+ ret = clk_prepare_enable(fpc->ipg_clk);
if (ret)
return ret;
@@ -371,7 +395,7 @@ static int fsl_pwm_init(struct fsl_pwm_chip *fpc)
regmap_write(fpc->regmap, FTM_OUTINIT, 0x00);
regmap_write(fpc->regmap, FTM_OUTMASK, 0xFF);
- clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+ clk_disable_unprepare(fpc->ipg_clk);
return 0;
}
@@ -408,6 +432,7 @@ static int fsl_pwm_probe(struct platform_device *pdev)
mutex_init(&fpc->lock);
+ fpc->soc = of_device_get_match_data(&pdev->dev);
fpc->chip.dev = &pdev->dev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -441,6 +466,15 @@ static int fsl_pwm_probe(struct platform_device *pdev)
if (IS_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]))
return PTR_ERR(fpc->clk[FSL_PWM_CLK_CNTEN]);
+ /*
+ * ipg_clk is the interface clock for the IP. If not provided, use the
+ * ftm_sys clock as the default.
+ */
+ fpc->ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+ if (IS_ERR(fpc->ipg_clk))
+ fpc->ipg_clk = fpc->clk[FSL_PWM_CLK_SYS];
+
+
fpc->chip.ops = &fsl_pwm_ops;
fpc->chip.of_xlate = of_pwm_xlate_with_flags;
fpc->chip.of_pwm_n_cells = 3;
@@ -480,7 +514,7 @@ static int fsl_pwm_suspend(struct device *dev)
if (!test_bit(PWMF_REQUESTED, &pwm->flags))
continue;
- clk_disable_unprepare(fpc->clk[FSL_PWM_CLK_SYS]);
+ clk_disable_unprepare(fpc->ipg_clk);
if (!pwm_is_enabled(pwm))
continue;
@@ -503,7 +537,7 @@ static int fsl_pwm_resume(struct device *dev)
if (!test_bit(PWMF_REQUESTED, &pwm->flags))
continue;
- clk_prepare_enable(fpc->clk[FSL_PWM_CLK_SYS]);
+ clk_prepare_enable(fpc->ipg_clk);
if (!pwm_is_enabled(pwm))
continue;
@@ -524,8 +558,17 @@ static const struct dev_pm_ops fsl_pwm_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(fsl_pwm_suspend, fsl_pwm_resume)
};
+static const struct fsl_ftm_soc vf610_ftm_pwm = {
+ .has_enable_bits = false,
+};
+
+static const struct fsl_ftm_soc imx8qm_ftm_pwm = {
+ .has_enable_bits = true,
+};
+
static const struct of_device_id fsl_pwm_dt_ids[] = {
- { .compatible = "fsl,vf610-ftm-pwm", },
+ { .compatible = "fsl,vf610-ftm-pwm", .data = &vf610_ftm_pwm },
+ { .compatible = "fsl,imx8qm-ftm-pwm", .data = &imx8qm_ftm_pwm },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids);
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 08cbe8120588..1d5242c9cde0 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -1,10 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* simple driver for PWM (Pulse Width Modulator) controller
*
- * 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.
- *
* Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
*/
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
index 328c124773b2..eb6674ce995f 100644
--- a/drivers/pwm/pwm-mediatek.c
+++ b/drivers/pwm/pwm-mediatek.c
@@ -57,6 +57,7 @@ static const char * const mtk_pwm_clk_name[MTK_CLK_MAX] = {
struct mtk_pwm_platform_data {
unsigned int num_pwms;
bool pwm45_fixup;
+ bool has_clks;
};
/**
@@ -86,6 +87,9 @@ static int mtk_pwm_clk_enable(struct pwm_chip *chip, struct pwm_device *pwm)
struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
int ret;
+ if (!pc->soc->has_clks)
+ return 0;
+
ret = clk_prepare_enable(pc->clks[MTK_CLK_TOP]);
if (ret < 0)
return ret;
@@ -112,6 +116,9 @@ static void mtk_pwm_clk_disable(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+ if (!pc->soc->has_clks)
+ return;
+
clk_disable_unprepare(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]);
clk_disable_unprepare(pc->clks[MTK_CLK_MAIN]);
clk_disable_unprepare(pc->clks[MTK_CLK_TOP]);
@@ -239,7 +246,7 @@ static int mtk_pwm_probe(struct platform_device *pdev)
if (IS_ERR(pc->regs))
return PTR_ERR(pc->regs);
- for (i = 0; i < data->num_pwms + 2; i++) {
+ for (i = 0; i < data->num_pwms + 2 && pc->soc->has_clks; i++) {
pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]);
if (IS_ERR(pc->clks[i])) {
dev_err(&pdev->dev, "clock: %s fail: %ld\n",
@@ -274,22 +281,32 @@ static int mtk_pwm_remove(struct platform_device *pdev)
static const struct mtk_pwm_platform_data mt2712_pwm_data = {
.num_pwms = 8,
.pwm45_fixup = false,
+ .has_clks = true,
};
static const struct mtk_pwm_platform_data mt7622_pwm_data = {
.num_pwms = 6,
.pwm45_fixup = false,
+ .has_clks = true,
};
static const struct mtk_pwm_platform_data mt7623_pwm_data = {
.num_pwms = 5,
.pwm45_fixup = true,
+ .has_clks = true,
+};
+
+static const struct mtk_pwm_platform_data mt7628_pwm_data = {
+ .num_pwms = 4,
+ .pwm45_fixup = true,
+ .has_clks = false,
};
static const struct of_device_id mtk_pwm_of_match[] = {
{ .compatible = "mediatek,mt2712-pwm", .data = &mt2712_pwm_data },
{ .compatible = "mediatek,mt7622-pwm", .data = &mt7622_pwm_data },
{ .compatible = "mediatek,mt7623-pwm", .data = &mt7623_pwm_data },
+ { .compatible = "mediatek,mt7628-pwm", .data = &mt7628_pwm_data },
{ },
};
MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c
index 822860b4801a..c1ed641b3e26 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -458,7 +458,6 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
struct meson_pwm_channel *channels)
{
struct device *dev = meson->chip.dev;
- struct device_node *np = dev->of_node;
struct clk_init_data init;
unsigned int i;
char name[255];
@@ -467,7 +466,7 @@ static int meson_pwm_init_channels(struct meson_pwm *meson,
for (i = 0; i < meson->chip.npwm; i++) {
struct meson_pwm_channel *channel = &channels[i];
- snprintf(name, sizeof(name), "%pOF#mux%u", np, i);
+ snprintf(name, sizeof(name), "%s#mux%u", dev_name(dev), i);
init.name = name;
init.ops = &clk_mux_ops;
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
index a6017ad9926c..04c0f6b95c1a 100644
--- a/drivers/pwm/pwm-mxs.c
+++ b/drivers/pwm/pwm-mxs.c
@@ -1,12 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2012 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>
diff --git a/drivers/pwm/pwm-omap-dmtimer.c b/drivers/pwm/pwm-omap-dmtimer.c
index 665da3c8fbce..f45798679e3c 100644
--- a/drivers/pwm/pwm-omap-dmtimer.c
+++ b/drivers/pwm/pwm-omap-dmtimer.c
@@ -264,8 +264,9 @@ static int pwm_omap_dmtimer_probe(struct platform_device *pdev)
timer_pdata = dev_get_platdata(&timer_pdev->dev);
if (!timer_pdata) {
- dev_err(&pdev->dev, "dmtimer pdata structure NULL\n");
- ret = -EINVAL;
+ dev_dbg(&pdev->dev,
+ "dmtimer pdata structure NULL, deferring probe\n");
+ ret = -EPROBE_DEFER;
goto put;
}
diff --git a/drivers/pwm/pwm-stm32-lp.c b/drivers/pwm/pwm-stm32-lp.c
index 7c13e2505080..0059b24cfdc3 100644
--- a/drivers/pwm/pwm-stm32-lp.c
+++ b/drivers/pwm/pwm-stm32-lp.c
@@ -217,10 +217,8 @@ static int stm32_pwm_lp_probe(struct platform_device *pdev)
static int stm32_pwm_lp_remove(struct platform_device *pdev)
{
struct stm32_pwm_lp *priv = platform_get_drvdata(pdev);
- unsigned int i;
- for (i = 0; i < priv->chip.npwm; i++)
- pwm_disable(&priv->chip.pwms[i]);
+ pwm_disable(&priv->chip.pwms[0]);
return pwmchip_remove(&priv->chip);
}
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 4c22cb395040..f7b8a86fa5c5 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -33,10 +33,6 @@
#define TBCTL 0x00
#define TBPRD 0x0A
-#define TBCTL_RUN_MASK (BIT(15) | BIT(14))
-#define TBCTL_STOP_NEXT 0
-#define TBCTL_STOP_ON_CYCLE BIT(14)
-#define TBCTL_FREE_RUN (BIT(15) | BIT(14))
#define TBCTL_PRDLD_MASK BIT(3)
#define TBCTL_PRDLD_SHDW 0
#define TBCTL_PRDLD_IMDT BIT(3)
@@ -360,7 +356,7 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
/* Channels polarity can be configured from action qualifier module */
configure_polarity(pc, pwm->hwpwm);
- /* Enable TBCLK before enabling PWM device */
+ /* Enable TBCLK */
ret = clk_enable(pc->tbclk);
if (ret) {
dev_err(chip->dev, "Failed to enable TBCLK for %s: %d\n",
@@ -368,9 +364,6 @@ static int ehrpwm_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
return ret;
}
- /* Enable time counter for free_run */
- ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_FREE_RUN);
-
return 0;
}
@@ -388,6 +381,8 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
aqcsfrc_mask = AQCSFRC_CSFA_MASK;
}
+ /* Update shadow register first before modifying active register */
+ ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val);
/*
* Changes to immediate action on Action Qualifier. This puts
* Action Qualifier control on PWM output from next TBCLK
@@ -400,9 +395,6 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
/* Disabling TBCLK on PWM disable */
clk_disable(pc->tbclk);
- /* Stop Time base counter */
- ehrpwm_modify(pc->mmio_base, TBCTL, TBCTL_RUN_MASK, TBCTL_STOP_NEXT);
-
/* Disable clock on PWM disable */
pm_runtime_put_sync(chip->dev);
}
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c0b292be1b72..a70262cb7e56 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -82,6 +82,15 @@ config RESET_PISTACHIO
help
This enables the reset driver for ImgTec Pistachio SoCs.
+config RESET_QCOM_AOSS
+ bool "Qcom AOSS Reset Driver"
+ depends on ARCH_QCOM || COMPILE_TEST
+ help
+ This enables the AOSS (always on subsystem) reset driver
+ for Qualcomm SDM845 SoCs. Say Y if you want to control
+ reset signals provided by AOSS for Modem, Venus, ADSP,
+ GPU, Camera, Wireless, Display subsystem. Otherwise, say N.
+
config RESET_SIMPLE
bool "Simple Reset Controller Driver" if COMPILE_TEST
default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
@@ -138,6 +147,16 @@ config RESET_UNIPHIER
Say Y if you want to control reset signals provided by System Control
block, Media I/O block, Peripheral Block.
+config RESET_UNIPHIER_USB3
+ tristate "USB3 reset driver for UniPhier SoCs"
+ depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
+ default ARCH_UNIPHIER
+ select RESET_SIMPLE
+ help
+ Support for the USB3 core reset on UniPhier SoCs.
+ Say Y if you want to control reset signals provided by
+ USB3 glue layer.
+
config RESET_ZYNQ
bool "ZYNQ Reset Driver" if COMPILE_TEST
default ARCH_ZYNQ
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index c1261dcfe9ad..0676b6b1976f 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -14,11 +14,13 @@ obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
obj-$(CONFIG_RESET_MESON) += reset-meson.o
obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
obj-$(CONFIG_RESET_PISTACHIO) += reset-pistachio.o
+obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
+obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
diff --git a/drivers/reset/reset-qcom-aoss.c b/drivers/reset/reset-qcom-aoss.c
new file mode 100644
index 000000000000..36db96750450
--- /dev/null
+++ b/drivers/reset/reset-qcom-aoss.c
@@ -0,0 +1,133 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <dt-bindings/reset/qcom,sdm845-aoss.h>
+
+struct qcom_aoss_reset_map {
+ unsigned int reg;
+};
+
+struct qcom_aoss_desc {
+ const struct qcom_aoss_reset_map *resets;
+ size_t num_resets;
+};
+
+struct qcom_aoss_reset_data {
+ struct reset_controller_dev rcdev;
+ void __iomem *base;
+ const struct qcom_aoss_desc *desc;
+};
+
+static const struct qcom_aoss_reset_map sdm845_aoss_resets[] = {
+ [AOSS_CC_MSS_RESTART] = {0x10000},
+ [AOSS_CC_CAMSS_RESTART] = {0x11000},
+ [AOSS_CC_VENUS_RESTART] = {0x12000},
+ [AOSS_CC_GPU_RESTART] = {0x13000},
+ [AOSS_CC_DISPSS_RESTART] = {0x14000},
+ [AOSS_CC_WCSS_RESTART] = {0x20000},
+ [AOSS_CC_LPASS_RESTART] = {0x30000},
+};
+
+static const struct qcom_aoss_desc sdm845_aoss_desc = {
+ .resets = sdm845_aoss_resets,
+ .num_resets = ARRAY_SIZE(sdm845_aoss_resets),
+};
+
+static inline struct qcom_aoss_reset_data *to_qcom_aoss_reset_data(
+ struct reset_controller_dev *rcdev)
+{
+ return container_of(rcdev, struct qcom_aoss_reset_data, rcdev);
+}
+
+static int qcom_aoss_control_assert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+ const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+ writel(1, data->base + map->reg);
+ /* Wait 6 32kHz sleep cycles for reset */
+ usleep_range(200, 300);
+ return 0;
+}
+
+static int qcom_aoss_control_deassert(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ struct qcom_aoss_reset_data *data = to_qcom_aoss_reset_data(rcdev);
+ const struct qcom_aoss_reset_map *map = &data->desc->resets[idx];
+
+ writel(0, data->base + map->reg);
+ /* Wait 6 32kHz sleep cycles for reset */
+ usleep_range(200, 300);
+ return 0;
+}
+
+static int qcom_aoss_control_reset(struct reset_controller_dev *rcdev,
+ unsigned long idx)
+{
+ qcom_aoss_control_assert(rcdev, idx);
+
+ return qcom_aoss_control_deassert(rcdev, idx);
+}
+
+static const struct reset_control_ops qcom_aoss_reset_ops = {
+ .reset = qcom_aoss_control_reset,
+ .assert = qcom_aoss_control_assert,
+ .deassert = qcom_aoss_control_deassert,
+};
+
+static int qcom_aoss_reset_probe(struct platform_device *pdev)
+{
+ struct qcom_aoss_reset_data *data;
+ struct device *dev = &pdev->dev;
+ const struct qcom_aoss_desc *desc;
+ struct resource *res;
+
+ desc = of_device_get_match_data(dev);
+ if (!desc)
+ return -EINVAL;
+
+ data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ data->desc = desc;
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ data->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(data->base))
+ return PTR_ERR(data->base);
+
+ data->rcdev.owner = THIS_MODULE;
+ data->rcdev.ops = &qcom_aoss_reset_ops;
+ data->rcdev.nr_resets = desc->num_resets;
+ data->rcdev.of_node = dev->of_node;
+
+ return devm_reset_controller_register(dev, &data->rcdev);
+}
+
+static const struct of_device_id qcom_aoss_reset_of_match[] = {
+ { .compatible = "qcom,sdm845-aoss-cc", .data = &sdm845_aoss_desc },
+ {}
+};
+
+static struct platform_driver qcom_aoss_reset_driver = {
+ .probe = qcom_aoss_reset_probe,
+ .driver = {
+ .name = "qcom_aoss_reset",
+ .of_match_table = qcom_aoss_reset_of_match,
+ },
+};
+
+builtin_platform_driver(qcom_aoss_reset_driver);
+
+MODULE_DESCRIPTION("Qualcomm AOSS Reset Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/reset/reset-simple.c b/drivers/reset/reset-simple.c
index f7ce8910a392..a91107fc9e27 100644
--- a/drivers/reset/reset-simple.c
+++ b/drivers/reset/reset-simple.c
@@ -87,6 +87,7 @@ const struct reset_control_ops reset_simple_ops = {
.deassert = reset_simple_deassert,
.status = reset_simple_status,
};
+EXPORT_SYMBOL_GPL(reset_simple_ops);
/**
* struct reset_simple_devdata - simple reset controller properties
diff --git a/drivers/reset/reset-uniphier-usb3.c b/drivers/reset/reset-uniphier-usb3.c
new file mode 100644
index 000000000000..ffa1b19b594d
--- /dev/null
+++ b/drivers/reset/reset-uniphier-usb3.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
+// Copyright 2018 Socionext Inc.
+// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "reset-simple.h"
+
+#define MAX_CLKS 2
+#define MAX_RSTS 2
+
+struct uniphier_usb3_reset_soc_data {
+ int nclks;
+ const char * const *clock_names;
+ int nrsts;
+ const char * const *reset_names;
+};
+
+struct uniphier_usb3_reset_priv {
+ struct clk_bulk_data clk[MAX_CLKS];
+ struct reset_control *rst[MAX_RSTS];
+ struct reset_simple_data rdata;
+ const struct uniphier_usb3_reset_soc_data *data;
+};
+
+static int uniphier_usb3_reset_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct uniphier_usb3_reset_priv *priv;
+ struct resource *res;
+ resource_size_t size;
+ const char *name;
+ int i, ret, nr;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->data = of_device_get_match_data(dev);
+ if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
+ priv->data->nrsts > MAX_RSTS))
+ return -EINVAL;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ size = resource_size(res);
+ priv->rdata.membase = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->rdata.membase))
+ return PTR_ERR(priv->rdata.membase);
+
+ for (i = 0; i < priv->data->nclks; i++)
+ priv->clk[i].id = priv->data->clock_names[i];
+ ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < priv->data->nrsts; i++) {
+ name = priv->data->reset_names[i];
+ priv->rst[i] = devm_reset_control_get_shared(dev, name);
+ if (IS_ERR(priv->rst[i]))
+ return PTR_ERR(priv->rst[i]);
+ }
+
+ ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
+ if (ret)
+ return ret;
+
+ for (nr = 0; nr < priv->data->nrsts; nr++) {
+ ret = reset_control_deassert(priv->rst[nr]);
+ if (ret)
+ goto out_rst_assert;
+ }
+
+ spin_lock_init(&priv->rdata.lock);
+ priv->rdata.rcdev.owner = THIS_MODULE;
+ priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
+ priv->rdata.rcdev.ops = &reset_simple_ops;
+ priv->rdata.rcdev.of_node = dev->of_node;
+ priv->rdata.active_low = true;
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
+ if (ret)
+ goto out_rst_assert;
+
+ return 0;
+
+out_rst_assert:
+ while (nr--)
+ reset_control_assert(priv->rst[nr]);
+
+ clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+ return ret;
+}
+
+static int uniphier_usb3_reset_remove(struct platform_device *pdev)
+{
+ struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < priv->data->nrsts; i++)
+ reset_control_assert(priv->rst[i]);
+
+ clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+ return 0;
+}
+
+static const char * const uniphier_pro4_clock_reset_names[] = {
+ "gio", "link",
+};
+
+static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
+ .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+ .clock_names = uniphier_pro4_clock_reset_names,
+ .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+ .reset_names = uniphier_pro4_clock_reset_names,
+};
+
+static const char * const uniphier_pxs2_clock_reset_names[] = {
+ "link",
+};
+
+static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
+ .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+ .clock_names = uniphier_pxs2_clock_reset_names,
+ .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+ .reset_names = uniphier_pxs2_clock_reset_names,
+};
+
+static const struct of_device_id uniphier_usb3_reset_match[] = {
+ {
+ .compatible = "socionext,uniphier-pro4-usb3-reset",
+ .data = &uniphier_pro4_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs2-usb3-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ {
+ .compatible = "socionext,uniphier-ld20-usb3-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ {
+ .compatible = "socionext,uniphier-pxs3-usb3-reset",
+ .data = &uniphier_pxs2_data,
+ },
+ { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
+
+static struct platform_driver uniphier_usb3_reset_driver = {
+ .probe = uniphier_usb3_reset_probe,
+ .remove = uniphier_usb3_reset_remove,
+ .driver = {
+ .name = "uniphier-usb3-reset",
+ .of_match_table = uniphier_usb3_reset_match,
+ },
+};
+module_platform_driver(uniphier_usb3_reset_driver);
+
+MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
+MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-uniphier.c b/drivers/reset/reset-uniphier.c
index e9030ff1bf2f..5605745663ae 100644
--- a/drivers/reset/reset-uniphier.c
+++ b/drivers/reset/reset-uniphier.c
@@ -202,6 +202,12 @@ static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
#define UNIPHIER_PERI_RESET_FI2C(id, ch) \
UNIPHIER_RESETX((id), 0x114, 24 + (ch))
+#define UNIPHIER_PERI_RESET_SCSSI(id) \
+ UNIPHIER_RESETX((id), 0x110, 17)
+
+#define UNIPHIER_PERI_RESET_MCSSI(id) \
+ UNIPHIER_RESETX((id), 0x114, 14)
+
static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
UNIPHIER_PERI_RESET_UART(0, 0),
UNIPHIER_PERI_RESET_UART(1, 1),
@@ -212,6 +218,7 @@ static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
UNIPHIER_PERI_RESET_I2C(6, 2),
UNIPHIER_PERI_RESET_I2C(7, 3),
UNIPHIER_PERI_RESET_I2C(8, 4),
+ UNIPHIER_PERI_RESET_SCSSI(11),
UNIPHIER_RESET_END,
};
@@ -227,6 +234,8 @@ static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
UNIPHIER_PERI_RESET_FI2C(8, 4),
UNIPHIER_PERI_RESET_FI2C(9, 5),
UNIPHIER_PERI_RESET_FI2C(10, 6),
+ UNIPHIER_PERI_RESET_SCSSI(11),
+ UNIPHIER_PERI_RESET_MCSSI(12),
UNIPHIER_RESET_END,
};
diff --git a/drivers/soc/bcm/brcmstb/pm/pm-arm.c b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
index dcf8c8065508..a5577dd5eb08 100644
--- a/drivers/soc/bcm/brcmstb/pm/pm-arm.c
+++ b/drivers/soc/bcm/brcmstb/pm/pm-arm.c
@@ -628,10 +628,26 @@ static const struct of_device_id ddr_shimphy_dt_ids[] = {
static const struct of_device_id brcmstb_memc_of_match[] = {
{
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
+ .data = &ddr_seq,
+ },
+ {
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
.data = &ddr_seq_b22,
},
{
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
+ .data = &ddr_seq_b22,
+ },
+ {
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
+ .data = &ddr_seq_b22,
+ },
+ {
+ .compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
+ .data = &ddr_seq_b22,
+ },
+ {
.compatible = "brcm,brcmstb-memc-ddr",
.data = &ddr_seq,
},
diff --git a/drivers/soc/fsl/Kconfig b/drivers/soc/fsl/Kconfig
index 7a9fb9baa66d..8f80e8bbf29e 100644
--- a/drivers/soc/fsl/Kconfig
+++ b/drivers/soc/fsl/Kconfig
@@ -1,7 +1,9 @@
#
-# Freescale SOC drivers
+# NXP/Freescale QorIQ series SOC drivers
#
+menu "NXP/Freescale QorIQ SoC drivers"
+
source "drivers/soc/fsl/qbman/Kconfig"
source "drivers/soc/fsl/qe/Kconfig"
@@ -16,3 +18,14 @@ config FSL_GUTS
Initially only reading SVR and registering soc device are supported.
Other guts accesses, such as reading RCW, should eventually be moved
into this driver as well.
+
+config FSL_MC_DPIO
+ tristate "QorIQ DPAA2 DPIO driver"
+ depends on FSL_MC_BUS
+ help
+ Driver for the DPAA2 DPIO object. A DPIO provides queue and
+ buffer management facilities for software to interact with
+ other DPAA2 objects. This driver does not expose the DPIO
+ objects individually, but groups them under a service layer
+ API.
+endmenu
diff --git a/drivers/soc/fsl/Makefile b/drivers/soc/fsl/Makefile
index 44b3bebef24a..803ef1bfb5ff 100644
--- a/drivers/soc/fsl/Makefile
+++ b/drivers/soc/fsl/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_FSL_DPAA) += qbman/
obj-$(CONFIG_QUICC_ENGINE) += qe/
obj-$(CONFIG_CPM) += qe/
obj-$(CONFIG_FSL_GUTS) += guts.o
+obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/staging/fsl-mc/bus/dpio/Makefile b/drivers/soc/fsl/dpio/Makefile
index b9ff24c76582..b9ff24c76582 100644
--- a/drivers/staging/fsl-mc/bus/dpio/Makefile
+++ b/drivers/soc/fsl/dpio/Makefile
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h b/drivers/soc/fsl/dpio/dpio-cmd.h
index ab8f82ee7ee5..ab8f82ee7ee5 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-cmd.h
+++ b/drivers/soc/fsl/dpio/dpio-cmd.h
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c b/drivers/soc/fsl/dpio/dpio-driver.c
index 11a90a90d827..b60b77bfaffa 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.c
+++ b/drivers/soc/fsl/dpio/dpio-driver.c
@@ -16,7 +16,7 @@
#include <linux/io.h>
#include <linux/fsl/mc.h>
-#include "../../include/dpaa2-io.h"
+#include <soc/fsl/dpaa2-io.h>
#include "qbman-portal.h"
#include "dpio.h"
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c b/drivers/soc/fsl/dpio/dpio-service.c
index 14ed2beb7432..9b17f72349ed 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-service.c
+++ b/drivers/soc/fsl/dpio/dpio-service.c
@@ -6,7 +6,7 @@
*/
#include <linux/types.h>
#include <linux/fsl/mc.h>
-#include "../../include/dpaa2-io.h"
+#include <soc/fsl/dpaa2-io.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.c b/drivers/soc/fsl/dpio/dpio.c
index ff37c80e11a0..ff37c80e11a0 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio.c
+++ b/drivers/soc/fsl/dpio/dpio.c
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio.h b/drivers/soc/fsl/dpio/dpio.h
index 49194c8e45f1..49194c8e45f1 100644
--- a/drivers/staging/fsl-mc/bus/dpio/dpio.h
+++ b/drivers/soc/fsl/dpio/dpio.h
diff --git a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c b/drivers/soc/fsl/dpio/qbman-portal.c
index 116fafb28640..cf1d448ea468 100644
--- a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.c
+++ b/drivers/soc/fsl/dpio/qbman-portal.c
@@ -8,7 +8,7 @@
#include <asm/cacheflush.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include "../../include/dpaa2-global.h"
+#include <soc/fsl/dpaa2-global.h>
#include "qbman-portal.h"
diff --git a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h b/drivers/soc/fsl/dpio/qbman-portal.h
index 69db3c818742..89d1dd9969b6 100644
--- a/drivers/staging/fsl-mc/bus/dpio/qbman-portal.h
+++ b/drivers/soc/fsl/dpio/qbman-portal.h
@@ -7,7 +7,7 @@
#ifndef __FSL_QBMAN_PORTAL_H
#define __FSL_QBMAN_PORTAL_H
-#include "../../include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-fd.h>
struct dpaa2_dq;
struct qbman_swp;
diff --git a/drivers/soc/fsl/qbman/Kconfig b/drivers/soc/fsl/qbman/Kconfig
index fb4e6bf0a0c4..d570cb5fd381 100644
--- a/drivers/soc/fsl/qbman/Kconfig
+++ b/drivers/soc/fsl/qbman/Kconfig
@@ -1,5 +1,5 @@
menuconfig FSL_DPAA
- bool "Freescale DPAA 1.x support"
+ bool "QorIQ DPAA1 framework support"
depends on (FSL_SOC_BOOKE || ARCH_LAYERSCAPE)
select GENERIC_ALLOCATOR
help
diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index 73a2e08b47ef..fabba17e9d65 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -3,7 +3,7 @@
#
config QUICC_ENGINE
- bool "Freescale QUICC Engine (QE) Support"
+ bool "QUICC Engine (QE) framework support"
depends on FSL_SOC && PPC32
select GENERIC_ALLOCATOR
select CRC32
diff --git a/drivers/soc/fsl/qe/gpio.c b/drivers/soc/fsl/qe/gpio.c
index 3b27075c21a7..819bed0f5667 100644
--- a/drivers/soc/fsl/qe/gpio.c
+++ b/drivers/soc/fsl/qe/gpio.c
@@ -83,6 +83,33 @@ static void qe_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
spin_unlock_irqrestore(&qe_gc->lock, flags);
}
+static void qe_gpio_set_multiple(struct gpio_chip *gc,
+ unsigned long *mask, unsigned long *bits)
+{
+ struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+ struct qe_gpio_chip *qe_gc = gpiochip_get_data(gc);
+ struct qe_pio_regs __iomem *regs = mm_gc->regs;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&qe_gc->lock, flags);
+
+ for (i = 0; i < gc->ngpio; i++) {
+ if (*mask == 0)
+ break;
+ if (__test_and_clear_bit(i, mask)) {
+ if (test_bit(i, bits))
+ qe_gc->cpdata |= (1U << (QE_PIO_PINS - 1 - i));
+ else
+ qe_gc->cpdata &= ~(1U << (QE_PIO_PINS - 1 - i));
+ }
+ }
+
+ out_be32(&regs->cpdata, qe_gc->cpdata);
+
+ spin_unlock_irqrestore(&qe_gc->lock, flags);
+}
+
static int qe_gpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
@@ -298,6 +325,7 @@ static int __init qe_add_gpiochips(void)
gc->direction_output = qe_gpio_dir_out;
gc->get = qe_gpio_get;
gc->set = qe_gpio_set;
+ gc->set_multiple = qe_gpio_set_multiple;
ret = of_mm_gpiochip_add_data(np, mm_gc, qe_gc);
if (ret)
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
index 546960a18d60..b3da635970ea 100644
--- a/drivers/soc/imx/gpc.c
+++ b/drivers/soc/imx/gpc.c
@@ -54,7 +54,6 @@ struct imx_pm_domain {
unsigned int reg_offs;
signed char cntr_pdn_bit;
unsigned int ipg_rate_mhz;
- unsigned int flags;
};
static inline struct imx_pm_domain *
@@ -69,9 +68,6 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
int iso, iso2sw;
u32 val;
- if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
- return -EBUSY;
-
/* Read ISO and ISO2SW power down delays */
regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
iso = val & 0x3f;
@@ -295,26 +291,31 @@ static struct imx_pm_domain imx_gpc_domains[] = {
struct imx_gpc_dt_data {
int num_domains;
bool err009619_present;
+ bool err006287_present;
};
static const struct imx_gpc_dt_data imx6q_dt_data = {
.num_domains = 2,
.err009619_present = false,
+ .err006287_present = false,
};
static const struct imx_gpc_dt_data imx6qp_dt_data = {
.num_domains = 2,
.err009619_present = true,
+ .err006287_present = false,
};
static const struct imx_gpc_dt_data imx6sl_dt_data = {
.num_domains = 3,
.err009619_present = false,
+ .err006287_present = true,
};
static const struct imx_gpc_dt_data imx6sx_dt_data = {
.num_domains = 4,
.err009619_present = false,
+ .err006287_present = false,
};
static const struct of_device_id imx_gpc_dt_ids[] = {
@@ -434,8 +435,13 @@ static int imx_gpc_probe(struct platform_device *pdev)
/* Disable PU power down in normal operation if ERR009619 is present */
if (of_id_data->err009619_present)
- imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
- PGC_DOMAIN_FLAG_NO_PD;
+ imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
+ GENPD_FLAG_ALWAYS_ON;
+
+ /* Keep DISP always on if ERR006287 is present */
+ if (of_id_data->err006287_present)
+ imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
+ GENPD_FLAG_ALWAYS_ON;
if (!pgc_node) {
ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 2afae64061d8..4e931fdf4d09 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -146,6 +146,21 @@ 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,
@@ -366,6 +381,39 @@ static int mt2701_regs[] = {
[PWRAP_ADC_RDATA_ADDR2] = 0x154,
};
+static int mt6797_regs[] = {
+ [PWRAP_MUX_SEL] = 0x0,
+ [PWRAP_WRAP_EN] = 0x4,
+ [PWRAP_DIO_EN] = 0x8,
+ [PWRAP_SIDLY] = 0xC,
+ [PWRAP_RDDMY] = 0x10,
+ [PWRAP_CSHEXT_WRITE] = 0x18,
+ [PWRAP_CSHEXT_READ] = 0x1C,
+ [PWRAP_CSLEXT_START] = 0x20,
+ [PWRAP_CSLEXT_END] = 0x24,
+ [PWRAP_STAUPD_PRD] = 0x28,
+ [PWRAP_HARB_HPRIO] = 0x50,
+ [PWRAP_HIPRIO_ARB_EN] = 0x54,
+ [PWRAP_MAN_EN] = 0x60,
+ [PWRAP_MAN_CMD] = 0x64,
+ [PWRAP_WACS0_EN] = 0x70,
+ [PWRAP_WACS1_EN] = 0x84,
+ [PWRAP_WACS2_EN] = 0x98,
+ [PWRAP_INIT_DONE2] = 0x9C,
+ [PWRAP_WACS2_CMD] = 0xA0,
+ [PWRAP_WACS2_RDATA] = 0xA4,
+ [PWRAP_WACS2_VLDCLR] = 0xA8,
+ [PWRAP_INT_EN] = 0xC0,
+ [PWRAP_INT_FLG_RAW] = 0xC4,
+ [PWRAP_INT_FLG] = 0xC8,
+ [PWRAP_INT_CLR] = 0xCC,
+ [PWRAP_TIMER_EN] = 0xF4,
+ [PWRAP_WDT_UNIT] = 0xFC,
+ [PWRAP_WDT_SRC_EN] = 0x100,
+ [PWRAP_DCM_EN] = 0x1CC,
+ [PWRAP_DCM_DBC_PRD] = 0x1D4,
+};
+
static int mt7622_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
@@ -635,12 +683,14 @@ static int mt8135_regs[] = {
enum pmic_type {
PMIC_MT6323,
+ PMIC_MT6351,
PMIC_MT6380,
PMIC_MT6397,
};
enum pwrap_type {
PWRAP_MT2701,
+ PWRAP_MT6797,
PWRAP_MT7622,
PWRAP_MT8135,
PWRAP_MT8173,
@@ -1067,6 +1117,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
pwrap_writel(wrp, 1, PWRAP_CIPHER_START);
break;
case PWRAP_MT2701:
+ case PWRAP_MT6797:
case PWRAP_MT8173:
pwrap_writel(wrp, 1, PWRAP_CIPHER_EN);
break;
@@ -1080,8 +1131,6 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_SWRST], 0x0);
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_KEY_SEL], 0x1);
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_IV_SEL], 0x2);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_LOAD], 0x1);
- pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_START], 0x1);
switch (wrp->slave->type) {
case PMIC_MT6397:
@@ -1091,6 +1140,7 @@ static int pwrap_init_cipher(struct pmic_wrapper *wrp)
0x1);
break;
case PMIC_MT6323:
+ case PMIC_MT6351:
pwrap_write(wrp, wrp->slave->dew_regs[PWRAP_DEW_CIPHER_EN],
0x1);
break;
@@ -1367,6 +1417,15 @@ 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",
@@ -1381,6 +1440,9 @@ static const struct of_device_id of_slave_match_tbl[] = {
.compatible = "mediatek,mt6397",
.data = &pmic_mt6397,
}, {
+ .compatible = "mediatek,mt6351",
+ .data = &pmic_mt6351,
+ }, {
/* sentinel */
}
};
@@ -1398,6 +1460,18 @@ static const struct pmic_wrapper_type pwrap_mt2701 = {
.init_soc_specific = pwrap_mt2701_init_soc_specific,
};
+static const struct pmic_wrapper_type pwrap_mt6797 = {
+ .regs = mt6797_regs,
+ .type = PWRAP_MT6797,
+ .arb_en_all = 0x01fff,
+ .int_en_all = 0xffffffc6,
+ .spi_w = PWRAP_MAN_CMD_SPI_WRITE,
+ .wdt_src = PWRAP_WDT_SRC_MASK_ALL,
+ .has_bridge = 0,
+ .init_reg_clock = pwrap_common_init_reg_clock,
+ .init_soc_specific = NULL,
+};
+
static const struct pmic_wrapper_type pwrap_mt7622 = {
.regs = mt7622_regs,
.type = PWRAP_MT7622,
@@ -1439,6 +1513,9 @@ static const struct of_device_id of_pwrap_match_tbl[] = {
.compatible = "mediatek,mt2701-pwrap",
.data = &pwrap_mt2701,
}, {
+ .compatible = "mediatek,mt6797-pwrap",
+ .data = &pwrap_mt6797,
+ }, {
.compatible = "mediatek,mt7622-pwrap",
.data = &pwrap_mt7622,
}, {
diff --git a/drivers/soc/renesas/Makefile b/drivers/soc/renesas/Makefile
index 7dc0f20d7907..c37b0803c1b6 100644
--- a/drivers/soc/renesas/Makefile
+++ b/drivers/soc/renesas/Makefile
@@ -18,6 +18,9 @@ obj-$(CONFIG_SYSC_R8A77970) += r8a77970-sysc.o
obj-$(CONFIG_SYSC_R8A77980) += r8a77980-sysc.o
obj-$(CONFIG_SYSC_R8A77990) += r8a77990-sysc.o
obj-$(CONFIG_SYSC_R8A77995) += r8a77995-sysc.o
+ifdef CONFIG_SMP
+obj-$(CONFIG_ARCH_R9A06G032) += r9a06g032-smp.o
+endif
# Family
obj-$(CONFIG_RST_RCAR) += rcar-rst.o
diff --git a/drivers/soc/renesas/r9a06g032-smp.c b/drivers/soc/renesas/r9a06g032-smp.c
new file mode 100644
index 000000000000..a1926e8d73f2
--- /dev/null
+++ b/drivers/soc/renesas/r9a06g032-smp.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * R9A06G032 Second CA7 enabler.
+ *
+ * Copyright (C) 2018 Renesas Electronics Europe Limited
+ *
+ * Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
+ * Derived from actions,s500-smp
+ */
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/smp.h>
+
+/*
+ * The second CPU is parked in ROM at boot time. It requires waking it after
+ * writing an address into the BOOTADDR register of sysctrl.
+ *
+ * So the default value of the "cpu-release-addr" corresponds to BOOTADDR...
+ *
+ * *However* the BOOTADDR register is not available when the kernel
+ * starts in NONSEC mode.
+ *
+ * So for NONSEC mode, the bootloader re-parks the second CPU into a pen
+ * in SRAM, and changes the "cpu-release-addr" of linux's DT to a SRAM address,
+ * which is not restricted.
+ */
+
+static void __iomem *cpu_bootaddr;
+
+static DEFINE_SPINLOCK(cpu_lock);
+
+static int
+r9a06g032_smp_boot_secondary(unsigned int cpu,
+ struct task_struct *idle)
+{
+ if (!cpu_bootaddr)
+ return -ENODEV;
+
+ spin_lock(&cpu_lock);
+
+ writel(__pa_symbol(secondary_startup), cpu_bootaddr);
+ arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+
+ spin_unlock(&cpu_lock);
+
+ return 0;
+}
+
+static void __init r9a06g032_smp_prepare_cpus(unsigned int max_cpus)
+{
+ struct device_node *dn;
+ int ret = -EINVAL, dns;
+ u32 bootaddr;
+
+ dn = of_get_cpu_node(1, NULL);
+ if (!dn) {
+ pr_err("CPU#1: missing device tree node\n");
+ return;
+ }
+ /*
+ * Determine the address from which the CPU is polling.
+ * The bootloader *does* change this property.
+ * Note: The property can be either 64 or 32 bits, so handle both cases
+ */
+ if (of_find_property(dn, "cpu-release-addr", &dns)) {
+ if (dns == sizeof(u64)) {
+ u64 temp;
+
+ ret = of_property_read_u64(dn,
+ "cpu-release-addr", &temp);
+ bootaddr = temp;
+ } else {
+ ret = of_property_read_u32(dn,
+ "cpu-release-addr",
+ &bootaddr);
+ }
+ }
+ of_node_put(dn);
+ if (ret) {
+ pr_err("CPU#1: invalid cpu-release-addr property\n");
+ return;
+ }
+ pr_info("CPU#1: cpu-release-addr %08x\n", bootaddr);
+
+ cpu_bootaddr = ioremap(bootaddr, sizeof(bootaddr));
+}
+
+static const struct smp_operations r9a06g032_smp_ops __initconst = {
+ .smp_prepare_cpus = r9a06g032_smp_prepare_cpus,
+ .smp_boot_secondary = r9a06g032_smp_boot_secondary,
+};
+
+CPU_METHOD_OF_DECLARE(r9a06g032_smp,
+ "renesas,r9a06g032-smp", &r9a06g032_smp_ops);
diff --git a/drivers/soc/renesas/rcar-sysc.c b/drivers/soc/renesas/rcar-sysc.c
index 50d03d8b4f9a..029188e8be6e 100644
--- a/drivers/soc/renesas/rcar-sysc.c
+++ b/drivers/soc/renesas/rcar-sysc.c
@@ -58,6 +58,12 @@
#define RCAR_PD_ALWAYS_ON 32 /* Always-on power area */
+struct rcar_sysc_ch {
+ u16 chan_offs;
+ u8 chan_bit;
+ u8 isr_bit;
+};
+
static void __iomem *rcar_sysc_base;
static DEFINE_SPINLOCK(rcar_sysc_lock); /* SMP CPUs + I/O devices */
@@ -143,12 +149,12 @@ static int rcar_sysc_power(const struct rcar_sysc_ch *sysc_ch, bool on)
return ret;
}
-int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
+static int rcar_sysc_power_down(const struct rcar_sysc_ch *sysc_ch)
{
return rcar_sysc_power(sysc_ch, false);
}
-int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
+static int rcar_sysc_power_up(const struct rcar_sysc_ch *sysc_ch)
{
return rcar_sysc_power(sysc_ch, true);
}
@@ -315,6 +321,8 @@ struct rcar_pm_domains {
struct generic_pm_domain *domains[RCAR_PD_ALWAYS_ON + 1];
};
+static struct genpd_onecell_data *rcar_sysc_onecell_data;
+
static int __init rcar_sysc_pd_init(void)
{
const struct rcar_sysc_info *info;
@@ -326,9 +334,6 @@ static int __init rcar_sysc_pd_init(void)
unsigned int i;
int error;
- if (rcar_sysc_base)
- return 0;
-
np = of_find_matching_node_and_match(NULL, rcar_sysc_matches, &match);
if (!np)
return -ENODEV;
@@ -361,6 +366,7 @@ static int __init rcar_sysc_pd_init(void)
domains->onecell_data.domains = domains->domains;
domains->onecell_data.num_domains = ARRAY_SIZE(domains->domains);
+ rcar_sysc_onecell_data = &domains->onecell_data;
for (i = 0, syscier = 0; i < info->num_areas; i++)
syscier |= BIT(info->areas[i].isr_bit);
@@ -448,27 +454,39 @@ void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
}
}
-void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
+#ifdef CONFIG_ARCH_R8A7779
+static int rcar_sysc_power_cpu(unsigned int idx, bool on)
{
- u32 syscimr;
+ struct generic_pm_domain *genpd;
+ struct rcar_sysc_pd *pd;
+ unsigned int i;
- if (!rcar_sysc_pd_init())
- return;
+ if (!rcar_sysc_onecell_data)
+ return -ENODEV;
- rcar_sysc_base = ioremap_nocache(base, PAGE_SIZE);
+ for (i = 0; i < rcar_sysc_onecell_data->num_domains; i++) {
+ genpd = rcar_sysc_onecell_data->domains[i];
+ if (!genpd)
+ continue;
- /*
- * Mask all interrupt sources to prevent the CPU from receiving them.
- * Make sure not to clear reserved bits that were set before.
- */
- syscimr = ioread32(rcar_sysc_base + SYSCIMR);
- syscimr |= syscier;
- pr_debug("%s: syscimr = 0x%08x\n", __func__, syscimr);
- iowrite32(syscimr, rcar_sysc_base + SYSCIMR);
+ pd = to_rcar_pd(genpd);
+ if (!(pd->flags & PD_CPU) || pd->ch.chan_bit != idx)
+ continue;
- /*
- * SYSC needs all interrupt sources enabled to control power.
- */
- pr_debug("%s: syscier = 0x%08x\n", __func__, syscier);
- iowrite32(syscier, rcar_sysc_base + SYSCIER);
+ return on ? rcar_sysc_power_up(&pd->ch)
+ : rcar_sysc_power_down(&pd->ch);
+ }
+
+ return -ENOENT;
+}
+
+int rcar_sysc_power_down_cpu(unsigned int cpu)
+{
+ return rcar_sysc_power_cpu(cpu, false);
+}
+
+int rcar_sysc_power_up_cpu(unsigned int cpu)
+{
+ return rcar_sysc_power_cpu(cpu, true);
}
+#endif /* CONFIG_ARCH_R8A7779 */
diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c
index 882be5ed7e84..b4b0f3480bd3 100644
--- a/drivers/soc/sunxi/sunxi_sram.c
+++ b/drivers/soc/sunxi/sunxi_sram.c
@@ -17,6 +17,7 @@
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/soc/sunxi/sunxi_sram.h>
@@ -63,6 +64,12 @@ static struct sunxi_sram_desc sun4i_a10_sram_a3_a4 = {
SUNXI_SRAM_MAP(1, 1, "emac")),
};
+static struct sunxi_sram_desc sun4i_a10_sram_c1 = {
+ .data = SUNXI_SRAM_DATA("C1", 0x0, 0x0, 31,
+ SUNXI_SRAM_MAP(0, 0, "cpu"),
+ SUNXI_SRAM_MAP(0x7fffffff, 1, "ve")),
+};
+
static struct sunxi_sram_desc sun4i_a10_sram_d = {
.data = SUNXI_SRAM_DATA("D", 0x4, 0x0, 1,
SUNXI_SRAM_MAP(0, 0, "cpu"),
@@ -81,6 +88,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = {
.data = &sun4i_a10_sram_a3_a4.data,
},
{
+ .compatible = "allwinner,sun4i-a10-sram-c1",
+ .data = &sun4i_a10_sram_c1.data,
+ },
+ {
.compatible = "allwinner,sun4i-a10-sram-d",
.data = &sun4i_a10_sram_d.data,
},
@@ -281,13 +292,51 @@ int sunxi_sram_release(struct device *dev)
}
EXPORT_SYMBOL(sunxi_sram_release);
+struct sunxi_sramc_variant {
+ bool has_emac_clock;
+};
+
+static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
+ /* Nothing special */
+};
+
+static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
+ .has_emac_clock = true,
+};
+
+#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
+static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
+ unsigned int reg)
+{
+ if (reg == SUNXI_SRAM_EMAC_CLOCK_REG)
+ return true;
+ return false;
+}
+
+static struct regmap_config sunxi_sram_emac_clock_regmap = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ /* last defined register */
+ .max_register = SUNXI_SRAM_EMAC_CLOCK_REG,
+ /* other devices have no business accessing other registers */
+ .readable_reg = sunxi_sram_regmap_accessible_reg,
+ .writeable_reg = sunxi_sram_regmap_accessible_reg,
+};
+
static int sunxi_sram_probe(struct platform_device *pdev)
{
struct resource *res;
struct dentry *d;
+ struct regmap *emac_clock;
+ const struct sunxi_sramc_variant *variant;
sram_dev = &pdev->dev;
+ variant = of_device_get_match_data(&pdev->dev);
+ if (!variant)
+ return -EINVAL;
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
@@ -300,12 +349,46 @@ static int sunxi_sram_probe(struct platform_device *pdev)
if (!d)
return -ENOMEM;
+ if (variant->has_emac_clock) {
+ emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
+ &sunxi_sram_emac_clock_regmap);
+
+ if (IS_ERR(emac_clock))
+ return PTR_ERR(emac_clock);
+ }
+
return 0;
}
static const struct of_device_id sunxi_sram_dt_match[] = {
- { .compatible = "allwinner,sun4i-a10-sram-controller" },
- { .compatible = "allwinner,sun50i-a64-sram-controller" },
+ {
+ .compatible = "allwinner,sun4i-a10-sram-controller",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun4i-a10-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun5i-a13-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun8i-a23-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun8i-h3-system-control",
+ .data = &sun4i_a10_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun50i-a64-sram-controller",
+ .data = &sun50i_a64_sramc_variant,
+ },
+ {
+ .compatible = "allwinner,sun50i-a64-system-control",
+ .data = &sun50i_a64_sramc_variant,
+ },
{ },
};
MODULE_DEVICE_TABLE(of, sunxi_sram_dt_match);
diff --git a/drivers/soc/ti/Kconfig b/drivers/soc/ti/Kconfig
index 92770d84a288..be4570baad96 100644
--- a/drivers/soc/ti/Kconfig
+++ b/drivers/soc/ti/Kconfig
@@ -1,3 +1,17 @@
+# 64-bit ARM SoCs from TI
+if ARM64
+
+if ARCH_K3
+
+config ARCH_K3_AM6_SOC
+ bool "K3 AM6 SoC"
+ help
+ Enable support for TI's AM6 SoC Family support
+
+endif
+
+endif
+
#
# TI SOC drivers
#
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index 652739c7f718..d0dab323651f 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -41,6 +41,8 @@ static struct am33xx_pm_sram_addr *pm_sram;
static struct device *pm33xx_dev;
static struct wkup_m3_ipc *m3_ipc;
+static unsigned long suspend_wfi_flags;
+
static u32 sram_suspend_address(unsigned long addr)
{
return ((unsigned long)am33xx_do_wfi_sram +
@@ -53,7 +55,7 @@ static int am33xx_pm_suspend(suspend_state_t suspend_state)
int i, ret = 0;
ret = pm_ops->soc_suspend((unsigned long)suspend_state,
- am33xx_do_wfi_sram);
+ am33xx_do_wfi_sram, suspend_wfi_flags);
if (ret) {
dev_err(pm33xx_dev, "PM: Kernel suspend failure\n");
@@ -227,6 +229,7 @@ static int am33xx_push_sram_idle(void)
ro_sram_data.amx3_pm_sram_data_virt = ocmcram_location_data;
ro_sram_data.amx3_pm_sram_data_phys =
gen_pool_virt_to_phys(sram_pool_data, ocmcram_location_data);
+ ro_sram_data.rtc_base_virt = pm_ops->get_rtc_base_addr();
/* Save physical address to calculate resume offset during pm init */
am33xx_do_wfi_sram_phys = gen_pool_virt_to_phys(sram_pool,
@@ -310,6 +313,17 @@ static int am33xx_pm_probe(struct platform_device *pdev)
suspend_set_ops(&am33xx_pm_ops);
#endif /* CONFIG_SUSPEND */
+ /*
+ * For a system suspend we must flush the caches, we want
+ * the DDR in self-refresh, we want to save the context
+ * of the EMIF, and we want the wkup_m3 to handle low-power
+ * transition.
+ */
+ suspend_wfi_flags |= WFI_FLAG_FLUSH_CACHE;
+ suspend_wfi_flags |= WFI_FLAG_SELF_REFRESH;
+ suspend_wfi_flags |= WFI_FLAG_SAVE_EMIF;
+ suspend_wfi_flags |= WFI_FLAG_WAKE_M3;
+
ret = pm_ops->init();
if (ret) {
dev_err(dev, "Unable to call core pm init!\n");
diff --git a/drivers/soc/ti/wkup_m3_ipc.c b/drivers/soc/ti/wkup_m3_ipc.c
index 369aef5e7228..f5cb8c0af09f 100644
--- a/drivers/soc/ti/wkup_m3_ipc.c
+++ b/drivers/soc/ti/wkup_m3_ipc.c
@@ -46,6 +46,7 @@
#define M3_BASELINE_VERSION 0x191
#define M3_STATUS_RESP_MASK (0xffff << 16)
#define M3_FW_VERSION_MASK 0xffff
+#define M3_WAKE_SRC_MASK 0xff
#define M3_STATE_UNKNOWN 0
#define M3_STATE_RESET 1
@@ -55,6 +56,23 @@
static struct wkup_m3_ipc *m3_ipc_state;
+static const struct wkup_m3_wakeup_src wakeups[] = {
+ {.irq_nr = 35, .src = "USB0_PHY"},
+ {.irq_nr = 36, .src = "USB1_PHY"},
+ {.irq_nr = 40, .src = "I2C0"},
+ {.irq_nr = 41, .src = "RTC Timer"},
+ {.irq_nr = 42, .src = "RTC Alarm"},
+ {.irq_nr = 43, .src = "Timer0"},
+ {.irq_nr = 44, .src = "Timer1"},
+ {.irq_nr = 45, .src = "UART"},
+ {.irq_nr = 46, .src = "GPIO0"},
+ {.irq_nr = 48, .src = "MPU_WAKE"},
+ {.irq_nr = 49, .src = "WDT0"},
+ {.irq_nr = 50, .src = "WDT1"},
+ {.irq_nr = 51, .src = "ADC_TSC"},
+ {.irq_nr = 0, .src = "Unknown"},
+};
+
static void am33xx_txev_eoi(struct wkup_m3_ipc *m3_ipc)
{
writel(AM33XX_M3_TXEV_ACK,
@@ -329,12 +347,45 @@ static int wkup_m3_finish_low_power(struct wkup_m3_ipc *m3_ipc)
return 0;
}
+/**
+ * wkup_m3_request_wake_src - Get the wakeup source info passed from wkup_m3
+ * @m3_ipc: Pointer to wkup_m3_ipc context
+ */
+static const char *wkup_m3_request_wake_src(struct wkup_m3_ipc *m3_ipc)
+{
+ unsigned int wakeup_src_idx;
+ int j, val;
+
+ val = wkup_m3_ctrl_ipc_read(m3_ipc, 6);
+
+ wakeup_src_idx = val & M3_WAKE_SRC_MASK;
+
+ for (j = 0; j < ARRAY_SIZE(wakeups) - 1; j++) {
+ if (wakeups[j].irq_nr == wakeup_src_idx)
+ return wakeups[j].src;
+ }
+ return wakeups[j].src;
+}
+
+/**
+ * wkup_m3_set_rtc_only - Set the rtc_only flag
+ * @wkup_m3_wakeup: struct wkup_m3_wakeup_src * gets assigned the
+ * wakeup src value
+ */
+static void wkup_m3_set_rtc_only(struct wkup_m3_ipc *m3_ipc)
+{
+ if (m3_ipc_state)
+ m3_ipc_state->is_rtc_only = true;
+}
+
static struct wkup_m3_ipc_ops ipc_ops = {
.set_mem_type = wkup_m3_set_mem_type,
.set_resume_address = wkup_m3_set_resume_address,
.prepare_low_power = wkup_m3_prepare_low_power,
.finish_low_power = wkup_m3_finish_low_power,
.request_pm_status = wkup_m3_request_pm_status,
+ .request_wake_src = wkup_m3_request_wake_src,
+ .set_rtc_only = wkup_m3_set_rtc_only,
};
/**
@@ -484,6 +535,30 @@ static int wkup_m3_ipc_remove(struct platform_device *pdev)
return 0;
}
+static int __maybe_unused wkup_m3_ipc_suspend(struct device *dev)
+{
+ /*
+ * Nothing needs to be done on suspend even with rtc_only flag set
+ */
+ return 0;
+}
+
+static int __maybe_unused wkup_m3_ipc_resume(struct device *dev)
+{
+ if (m3_ipc_state->is_rtc_only) {
+ rproc_shutdown(m3_ipc_state->rproc);
+ rproc_boot(m3_ipc_state->rproc);
+ }
+
+ m3_ipc_state->is_rtc_only = false;
+
+ return 0;
+}
+
+static const struct dev_pm_ops wkup_m3_ipc_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(wkup_m3_ipc_suspend, wkup_m3_ipc_resume)
+};
+
static const struct of_device_id wkup_m3_ipc_of_match[] = {
{ .compatible = "ti,am3352-wkup-m3-ipc", },
{ .compatible = "ti,am4372-wkup-m3-ipc", },
@@ -497,6 +572,7 @@ static struct platform_driver wkup_m3_ipc_driver = {
.driver = {
.name = "wkup_m3_ipc",
.of_match_table = wkup_m3_ipc_of_match,
+ .pm = &wkup_m3_ipc_pm_ops,
},
};
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 396fb3d56398..1abf76be2aa8 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -90,8 +90,6 @@ source "drivers/staging/clocking-wizard/Kconfig"
source "drivers/staging/fbtft/Kconfig"
-source "drivers/staging/fsl-mc/Kconfig"
-
source "drivers/staging/fsl-dpaa2/Kconfig"
source "drivers/staging/wilc1000/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index ad7b4ca412ef..ab0cbe8815b1 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -35,7 +35,6 @@ obj-$(CONFIG_GS_FPGABOOT) += gs_fpgaboot/
obj-$(CONFIG_UNISYSSPAR) += unisys/
obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clocking-wizard/
obj-$(CONFIG_FB_TFT) += fbtft/
-obj-$(CONFIG_FSL_MC_BUS) += fsl-mc/
obj-$(CONFIG_FSL_DPAA2) += fsl-dpaa2/
obj-$(CONFIG_WILC1000) += wilc1000/
obj-$(CONFIG_MOST) += most/
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
index e2dac44eccbe..9329fcad95ac 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
@@ -426,7 +426,7 @@ static int build_sg_fd(struct dpaa2_eth_priv *priv,
dpaa2_fd_set_format(fd, dpaa2_fd_sg);
dpaa2_fd_set_addr(fd, addr);
dpaa2_fd_set_len(fd, skb->len);
- dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
+ dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
enable_tx_tstamp(fd, sgt_buf);
@@ -479,7 +479,7 @@ static int build_single_fd(struct dpaa2_eth_priv *priv,
dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
dpaa2_fd_set_len(fd, skb->len);
dpaa2_fd_set_format(fd, dpaa2_fd_single);
- dpaa2_fd_set_ctrl(fd, DPAA2_FD_CTRL_PTA | DPAA2_FD_CTRL_PTV1);
+ dpaa2_fd_set_ctrl(fd, FD_CTRL_PTA | FD_CTRL_PTV1);
if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
enable_tx_tstamp(fd, buffer_start);
diff --git a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
index 506466778b2c..d54cb0b99d08 100644
--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
@@ -10,8 +10,8 @@
#include <linux/if_vlan.h>
#include <linux/fsl/mc.h>
-#include "../../fsl-mc/include/dpaa2-io.h"
-#include "../../fsl-mc/include/dpaa2-fd.h"
+#include <soc/fsl/dpaa2-io.h>
+#include <soc/fsl/dpaa2-fd.h>
#include "dpni.h"
#include "dpni-cmd.h"
@@ -97,21 +97,13 @@ struct dpaa2_eth_swa {
#define DPAA2_FD_FRC_FAICFDV 0x0400
/* Error bits in FD CTRL */
-#define DPAA2_FD_CTRL_UFD 0x00000004
-#define DPAA2_FD_CTRL_SBE 0x00000008
-#define DPAA2_FD_CTRL_FSE 0x00000020
-#define DPAA2_FD_CTRL_FAERR 0x00000040
-
-#define DPAA2_FD_RX_ERR_MASK (DPAA2_FD_CTRL_SBE | \
- DPAA2_FD_CTRL_FAERR)
-#define DPAA2_FD_TX_ERR_MASK (DPAA2_FD_CTRL_UFD | \
- DPAA2_FD_CTRL_SBE | \
- DPAA2_FD_CTRL_FSE | \
- DPAA2_FD_CTRL_FAERR)
+#define DPAA2_FD_RX_ERR_MASK (FD_CTRL_SBE | FD_CTRL_FAERR)
+#define DPAA2_FD_TX_ERR_MASK (FD_CTRL_UFD | \
+ FD_CTRL_SBE | \
+ FD_CTRL_FSE | \
+ FD_CTRL_FAERR)
/* Annotation bits in FD CTRL */
-#define DPAA2_FD_CTRL_PTA 0x00800000
-#define DPAA2_FD_CTRL_PTV1 0x00400000
#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128B */
/* Frame annotation status */
diff --git a/drivers/staging/fsl-mc/Kconfig b/drivers/staging/fsl-mc/Kconfig
deleted file mode 100644
index 3002229bec1b..000000000000
--- a/drivers/staging/fsl-mc/Kconfig
+++ /dev/null
@@ -1,2 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-source "drivers/staging/fsl-mc/bus/Kconfig"
diff --git a/drivers/staging/fsl-mc/Makefile b/drivers/staging/fsl-mc/Makefile
deleted file mode 100644
index 14683889dabd..000000000000
--- a/drivers/staging/fsl-mc/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-# Freescale Management Complex (MC) bus drivers
-obj-$(CONFIG_FSL_MC_BUS) += bus/
diff --git a/drivers/staging/fsl-mc/bus/Kconfig b/drivers/staging/fsl-mc/bus/Kconfig
deleted file mode 100644
index 342453035269..000000000000
--- a/drivers/staging/fsl-mc/bus/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# DPAA2 fsl-mc bus
-#
-# Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
-#
-
-config FSL_MC_DPIO
- tristate "QorIQ DPAA2 DPIO driver"
- depends on FSL_MC_BUS
- help
- Driver for the DPAA2 DPIO object. A DPIO provides queue and
- buffer management facilities for software to interact with
- other DPAA2 objects. This driver does not expose the DPIO
- objects individually, but groups them under a service layer
- API.
diff --git a/drivers/staging/fsl-mc/bus/Makefile b/drivers/staging/fsl-mc/bus/Makefile
deleted file mode 100644
index 21d8ebc8ce21..000000000000
--- a/drivers/staging/fsl-mc/bus/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Freescale Management Complex (MC) bus drivers
-#
-# Copyright (C) 2014 Freescale Semiconductor, Inc.
-#
-
-# MC DPIO driver
-obj-$(CONFIG_FSL_MC_DPIO) += dpio/
diff --git a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt b/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
deleted file mode 100644
index 72ba9da3d179..000000000000
--- a/drivers/staging/fsl-mc/bus/dpio/dpio-driver.txt
+++ /dev/null
@@ -1,135 +0,0 @@
-Copyright 2016 NXP
-
-Introduction
-------------
-
-A DPAA2 DPIO (Data Path I/O) is a hardware object that provides
-interfaces to enqueue and dequeue frames to/from network interfaces
-and other accelerators. A DPIO also provides hardware buffer
-pool management for network interfaces.
-
-This document provides an overview the Linux DPIO driver, its
-subcomponents, and its APIs.
-
-See Documentation/networking/dpaa2/overview.rst for a general overview of DPAA2
-and the general DPAA2 driver architecture in Linux.
-
-Driver Overview
----------------
-
-The DPIO driver is bound to DPIO objects discovered on the fsl-mc bus and
-provides services that:
- A) allow other drivers, such as the Ethernet driver, to enqueue and dequeue
- frames for their respective objects
- B) allow drivers to register callbacks for data availability notifications
- when data becomes available on a queue or channel
- C) allow drivers to manage hardware buffer pools
-
-The Linux DPIO driver consists of 3 primary components--
- DPIO object driver-- fsl-mc driver that manages the DPIO object
- DPIO service-- provides APIs to other Linux drivers for services
- QBman portal interface-- sends portal commands, gets responses
-
- fsl-mc other
- bus drivers
- | |
- +---+----+ +------+-----+
- |DPIO obj| |DPIO service|
- | driver |---| (DPIO) |
- +--------+ +------+-----+
- |
- +------+-----+
- | QBman |
- | portal i/f |
- +------------+
- |
- hardware
-
-The diagram below shows how the DPIO driver components fit with the other
-DPAA2 Linux driver components:
- +------------+
- | OS Network |
- | Stack |
- +------------+ +------------+
- | Allocator |. . . . . . . | Ethernet |
- |(DPMCP,DPBP)| | (DPNI) |
- +-.----------+ +---+---+----+
- . . ^ |
- . . <data avail, | |<enqueue,
- . . tx confirm> | | dequeue>
- +-------------+ . | |
- | DPRC driver | . +--------+ +------------+
- | (DPRC) | . . |DPIO obj| |DPIO service|
- +----------+--+ | driver |-| (DPIO) |
- | +--------+ +------+-----+
- |<dev add/remove> +------|-----+
- | | QBman |
- +----+--------------+ | portal i/f |
- | MC-bus driver | +------------+
- | | |
- | /soc/fsl-mc | |
- +-------------------+ |
- |
- =========================================|=========|========================
- +-+--DPIO---|-----------+
- | | |
- | QBman Portal |
- +-----------------------+
-
- ============================================================================
-
-
-DPIO Object Driver (dpio-driver.c)
-----------------------------------
-
- The dpio-driver component registers with the fsl-mc bus to handle objects of
- type "dpio". The implementation of probe() handles basic initialization
- of the DPIO including mapping of the DPIO regions (the QBman SW portal)
- and initializing interrupts and registering irq handlers. The dpio-driver
- registers the probed DPIO with dpio-service.
-
-DPIO service (dpio-service.c, dpaa2-io.h)
-------------------------------------------
-
- The dpio service component provides queuing, notification, and buffers
- management services to DPAA2 drivers, such as the Ethernet driver. A system
- will typically allocate 1 DPIO object per CPU to allow queuing operations
- to happen simultaneously across all CPUs.
-
- Notification handling
- dpaa2_io_service_register()
- dpaa2_io_service_deregister()
- dpaa2_io_service_rearm()
-
- Queuing
- dpaa2_io_service_pull_fq()
- dpaa2_io_service_pull_channel()
- dpaa2_io_service_enqueue_fq()
- dpaa2_io_service_enqueue_qd()
- dpaa2_io_store_create()
- dpaa2_io_store_destroy()
- dpaa2_io_store_next()
-
- Buffer pool management
- dpaa2_io_service_release()
- dpaa2_io_service_acquire()
-
-QBman portal interface (qbman-portal.c)
----------------------------------------
-
- The qbman-portal component provides APIs to do the low level hardware
- bit twiddling for operations such as:
- -initializing Qman software portals
- -building and sending portal commands
- -portal interrupt configuration and processing
-
- The qbman-portal APIs are not public to other drivers, and are
- only used by dpio-service.
-
-Other (dpaa2-fd.h, dpaa2-global.h)
-----------------------------------
-
- Frame descriptor and scatter-gather definitions and the APIs used to
- manipulate them are defined in dpaa2-fd.h.
-
- Dequeue result struct and parsing APIs are defined in dpaa2-global.h.
diff --git a/drivers/staging/fsl-mc/include/dpaa2-fd.h b/drivers/staging/fsl-mc/include/dpaa2-fd.h
deleted file mode 100644
index b55b89ba4eda..000000000000
--- a/drivers/staging/fsl-mc/include/dpaa2-fd.h
+++ /dev/null
@@ -1,426 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/*
- * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright 2016 NXP
- *
- */
-#ifndef __FSL_DPAA2_FD_H
-#define __FSL_DPAA2_FD_H
-
-#include <linux/kernel.h>
-
-/**
- * DOC: DPAA2 FD - Frame Descriptor APIs for DPAA2
- *
- * Frame Descriptors (FDs) are used to describe frame data in the DPAA2.
- * Frames can be enqueued and dequeued to Frame Queues (FQs) which are consumed
- * by the various DPAA accelerators (WRIOP, SEC, PME, DCE)
- *
- * There are three types of frames: single, scatter gather, and frame lists.
- *
- * The set of APIs in this file must be used to create, manipulate and
- * query Frame Descriptors.
- */
-
-/**
- * struct dpaa2_fd - Struct describing FDs
- * @words: for easier/faster copying the whole FD structure
- * @addr: address in the FD
- * @len: length in the FD
- * @bpid: buffer pool ID
- * @format_offset: format, offset, and short-length fields
- * @frc: frame context
- * @ctrl: control bits...including dd, sc, va, err, etc
- * @flc: flow context address
- *
- * This structure represents the basic Frame Descriptor used in the system.
- */
-struct dpaa2_fd {
- union {
- u32 words[8];
- struct dpaa2_fd_simple {
- __le64 addr;
- __le32 len;
- __le16 bpid;
- __le16 format_offset;
- __le32 frc;
- __le32 ctrl;
- __le64 flc;
- } simple;
- };
-};
-
-#define FD_SHORT_LEN_FLAG_MASK 0x1
-#define FD_SHORT_LEN_FLAG_SHIFT 14
-#define FD_SHORT_LEN_MASK 0x3FFFF
-#define FD_OFFSET_MASK 0x0FFF
-#define FD_FORMAT_MASK 0x3
-#define FD_FORMAT_SHIFT 12
-#define FD_BPID_MASK 0x3FFF
-#define SG_SHORT_LEN_FLAG_MASK 0x1
-#define SG_SHORT_LEN_FLAG_SHIFT 14
-#define SG_SHORT_LEN_MASK 0x1FFFF
-#define SG_OFFSET_MASK 0x0FFF
-#define SG_FORMAT_MASK 0x3
-#define SG_FORMAT_SHIFT 12
-#define SG_BPID_MASK 0x3FFF
-#define SG_FINAL_FLAG_MASK 0x1
-#define SG_FINAL_FLAG_SHIFT 15
-
-enum dpaa2_fd_format {
- dpaa2_fd_single = 0,
- dpaa2_fd_list,
- dpaa2_fd_sg
-};
-
-/**
- * dpaa2_fd_get_addr() - get the addr field of frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the address in the frame descriptor.
- */
-static inline dma_addr_t dpaa2_fd_get_addr(const struct dpaa2_fd *fd)
-{
- return (dma_addr_t)le64_to_cpu(fd->simple.addr);
-}
-
-/**
- * dpaa2_fd_set_addr() - Set the addr field of frame descriptor
- * @fd: the given frame descriptor
- * @addr: the address needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_addr(struct dpaa2_fd *fd, dma_addr_t addr)
-{
- fd->simple.addr = cpu_to_le64(addr);
-}
-
-/**
- * dpaa2_fd_get_frc() - Get the frame context in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the frame context field in the frame descriptor.
- */
-static inline u32 dpaa2_fd_get_frc(const struct dpaa2_fd *fd)
-{
- return le32_to_cpu(fd->simple.frc);
-}
-
-/**
- * dpaa2_fd_set_frc() - Set the frame context in the frame descriptor
- * @fd: the given frame descriptor
- * @frc: the frame context needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_frc(struct dpaa2_fd *fd, u32 frc)
-{
- fd->simple.frc = cpu_to_le32(frc);
-}
-
-/**
- * dpaa2_fd_get_ctrl() - Get the control bits in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the control bits field in the frame descriptor.
- */
-static inline u32 dpaa2_fd_get_ctrl(const struct dpaa2_fd *fd)
-{
- return le32_to_cpu(fd->simple.ctrl);
-}
-
-/**
- * dpaa2_fd_set_ctrl() - Set the control bits in the frame descriptor
- * @fd: the given frame descriptor
- * @ctrl: the control bits to be set in the frame descriptor
- */
-static inline void dpaa2_fd_set_ctrl(struct dpaa2_fd *fd, u32 ctrl)
-{
- fd->simple.ctrl = cpu_to_le32(ctrl);
-}
-
-/**
- * dpaa2_fd_get_flc() - Get the flow context in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the flow context in the frame descriptor.
- */
-static inline dma_addr_t dpaa2_fd_get_flc(const struct dpaa2_fd *fd)
-{
- return (dma_addr_t)le64_to_cpu(fd->simple.flc);
-}
-
-/**
- * dpaa2_fd_set_flc() - Set the flow context field of frame descriptor
- * @fd: the given frame descriptor
- * @flc_addr: the flow context needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_flc(struct dpaa2_fd *fd, dma_addr_t flc_addr)
-{
- fd->simple.flc = cpu_to_le64(flc_addr);
-}
-
-static inline bool dpaa2_fd_short_len(const struct dpaa2_fd *fd)
-{
- return !!((le16_to_cpu(fd->simple.format_offset) >>
- FD_SHORT_LEN_FLAG_SHIFT) & FD_SHORT_LEN_FLAG_MASK);
-}
-
-/**
- * dpaa2_fd_get_len() - Get the length in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the length field in the frame descriptor.
- */
-static inline u32 dpaa2_fd_get_len(const struct dpaa2_fd *fd)
-{
- if (dpaa2_fd_short_len(fd))
- return le32_to_cpu(fd->simple.len) & FD_SHORT_LEN_MASK;
-
- return le32_to_cpu(fd->simple.len);
-}
-
-/**
- * dpaa2_fd_set_len() - Set the length field of frame descriptor
- * @fd: the given frame descriptor
- * @len: the length needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_len(struct dpaa2_fd *fd, u32 len)
-{
- fd->simple.len = cpu_to_le32(len);
-}
-
-/**
- * dpaa2_fd_get_offset() - Get the offset field in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the offset.
- */
-static inline uint16_t dpaa2_fd_get_offset(const struct dpaa2_fd *fd)
-{
- return le16_to_cpu(fd->simple.format_offset) & FD_OFFSET_MASK;
-}
-
-/**
- * dpaa2_fd_set_offset() - Set the offset field of frame descriptor
- * @fd: the given frame descriptor
- * @offset: the offset needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_offset(struct dpaa2_fd *fd, uint16_t offset)
-{
- fd->simple.format_offset &= cpu_to_le16(~FD_OFFSET_MASK);
- fd->simple.format_offset |= cpu_to_le16(offset);
-}
-
-/**
- * dpaa2_fd_get_format() - Get the format field in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the format.
- */
-static inline enum dpaa2_fd_format dpaa2_fd_get_format(
- const struct dpaa2_fd *fd)
-{
- return (enum dpaa2_fd_format)((le16_to_cpu(fd->simple.format_offset)
- >> FD_FORMAT_SHIFT) & FD_FORMAT_MASK);
-}
-
-/**
- * dpaa2_fd_set_format() - Set the format field of frame descriptor
- * @fd: the given frame descriptor
- * @format: the format needs to be set in frame descriptor
- */
-static inline void dpaa2_fd_set_format(struct dpaa2_fd *fd,
- enum dpaa2_fd_format format)
-{
- fd->simple.format_offset &=
- cpu_to_le16(~(FD_FORMAT_MASK << FD_FORMAT_SHIFT));
- fd->simple.format_offset |= cpu_to_le16(format << FD_FORMAT_SHIFT);
-}
-
-/**
- * dpaa2_fd_get_bpid() - Get the bpid field in the frame descriptor
- * @fd: the given frame descriptor
- *
- * Return the buffer pool id.
- */
-static inline uint16_t dpaa2_fd_get_bpid(const struct dpaa2_fd *fd)
-{
- return le16_to_cpu(fd->simple.bpid) & FD_BPID_MASK;
-}
-
-/**
- * dpaa2_fd_set_bpid() - Set the bpid field of frame descriptor
- * @fd: the given frame descriptor
- * @bpid: buffer pool id to be set
- */
-static inline void dpaa2_fd_set_bpid(struct dpaa2_fd *fd, uint16_t bpid)
-{
- fd->simple.bpid &= cpu_to_le16(~(FD_BPID_MASK));
- fd->simple.bpid |= cpu_to_le16(bpid);
-}
-
-/**
- * struct dpaa2_sg_entry - the scatter-gathering structure
- * @addr: address of the sg entry
- * @len: length in this sg entry
- * @bpid: buffer pool id
- * @format_offset: format and offset fields
- */
-struct dpaa2_sg_entry {
- __le64 addr;
- __le32 len;
- __le16 bpid;
- __le16 format_offset;
-};
-
-enum dpaa2_sg_format {
- dpaa2_sg_single = 0,
- dpaa2_sg_frame_data,
- dpaa2_sg_sgt_ext
-};
-
-/* Accessors for SG entry fields */
-
-/**
- * dpaa2_sg_get_addr() - Get the address from SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the address.
- */
-static inline dma_addr_t dpaa2_sg_get_addr(const struct dpaa2_sg_entry *sg)
-{
- return (dma_addr_t)le64_to_cpu(sg->addr);
-}
-
-/**
- * dpaa2_sg_set_addr() - Set the address in SG entry
- * @sg: the given scatter-gathering object
- * @addr: the address to be set
- */
-static inline void dpaa2_sg_set_addr(struct dpaa2_sg_entry *sg, dma_addr_t addr)
-{
- sg->addr = cpu_to_le64(addr);
-}
-
-static inline bool dpaa2_sg_short_len(const struct dpaa2_sg_entry *sg)
-{
- return !!((le16_to_cpu(sg->format_offset) >> SG_SHORT_LEN_FLAG_SHIFT)
- & SG_SHORT_LEN_FLAG_MASK);
-}
-
-/**
- * dpaa2_sg_get_len() - Get the length in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the length.
- */
-static inline u32 dpaa2_sg_get_len(const struct dpaa2_sg_entry *sg)
-{
- if (dpaa2_sg_short_len(sg))
- return le32_to_cpu(sg->len) & SG_SHORT_LEN_MASK;
-
- return le32_to_cpu(sg->len);
-}
-
-/**
- * dpaa2_sg_set_len() - Set the length in SG entry
- * @sg: the given scatter-gathering object
- * @len: the length to be set
- */
-static inline void dpaa2_sg_set_len(struct dpaa2_sg_entry *sg, u32 len)
-{
- sg->len = cpu_to_le32(len);
-}
-
-/**
- * dpaa2_sg_get_offset() - Get the offset in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the offset.
- */
-static inline u16 dpaa2_sg_get_offset(const struct dpaa2_sg_entry *sg)
-{
- return le16_to_cpu(sg->format_offset) & SG_OFFSET_MASK;
-}
-
-/**
- * dpaa2_sg_set_offset() - Set the offset in SG entry
- * @sg: the given scatter-gathering object
- * @offset: the offset to be set
- */
-static inline void dpaa2_sg_set_offset(struct dpaa2_sg_entry *sg,
- u16 offset)
-{
- sg->format_offset &= cpu_to_le16(~SG_OFFSET_MASK);
- sg->format_offset |= cpu_to_le16(offset);
-}
-
-/**
- * dpaa2_sg_get_format() - Get the SG format in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the format.
- */
-static inline enum dpaa2_sg_format
- dpaa2_sg_get_format(const struct dpaa2_sg_entry *sg)
-{
- return (enum dpaa2_sg_format)((le16_to_cpu(sg->format_offset)
- >> SG_FORMAT_SHIFT) & SG_FORMAT_MASK);
-}
-
-/**
- * dpaa2_sg_set_format() - Set the SG format in SG entry
- * @sg: the given scatter-gathering object
- * @format: the format to be set
- */
-static inline void dpaa2_sg_set_format(struct dpaa2_sg_entry *sg,
- enum dpaa2_sg_format format)
-{
- sg->format_offset &= cpu_to_le16(~(SG_FORMAT_MASK << SG_FORMAT_SHIFT));
- sg->format_offset |= cpu_to_le16(format << SG_FORMAT_SHIFT);
-}
-
-/**
- * dpaa2_sg_get_bpid() - Get the buffer pool id in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return the bpid.
- */
-static inline u16 dpaa2_sg_get_bpid(const struct dpaa2_sg_entry *sg)
-{
- return le16_to_cpu(sg->bpid) & SG_BPID_MASK;
-}
-
-/**
- * dpaa2_sg_set_bpid() - Set the buffer pool id in SG entry
- * @sg: the given scatter-gathering object
- * @bpid: the bpid to be set
- */
-static inline void dpaa2_sg_set_bpid(struct dpaa2_sg_entry *sg, u16 bpid)
-{
- sg->bpid &= cpu_to_le16(~(SG_BPID_MASK));
- sg->bpid |= cpu_to_le16(bpid);
-}
-
-/**
- * dpaa2_sg_is_final() - Check final bit in SG entry
- * @sg: the given scatter-gathering object
- *
- * Return bool.
- */
-static inline bool dpaa2_sg_is_final(const struct dpaa2_sg_entry *sg)
-{
- return !!(le16_to_cpu(sg->format_offset) >> SG_FINAL_FLAG_SHIFT);
-}
-
-/**
- * dpaa2_sg_set_final() - Set the final bit in SG entry
- * @sg: the given scatter-gathering object
- * @final: the final boolean to be set
- */
-static inline void dpaa2_sg_set_final(struct dpaa2_sg_entry *sg, bool final)
-{
- sg->format_offset &= cpu_to_le16((~(SG_FINAL_FLAG_MASK
- << SG_FINAL_FLAG_SHIFT)) & 0xFFFF);
- sg->format_offset |= cpu_to_le16(final << SG_FINAL_FLAG_SHIFT);
-}
-
-#endif /* __FSL_DPAA2_FD_H */
diff --git a/drivers/staging/fsl-mc/include/dpaa2-global.h b/drivers/staging/fsl-mc/include/dpaa2-global.h
deleted file mode 100644
index 9bc0713346a8..000000000000
--- a/drivers/staging/fsl-mc/include/dpaa2-global.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/*
- * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright 2016 NXP
- *
- */
-#ifndef __FSL_DPAA2_GLOBAL_H
-#define __FSL_DPAA2_GLOBAL_H
-
-#include <linux/types.h>
-#include <linux/cpumask.h>
-#include "dpaa2-fd.h"
-
-struct dpaa2_dq {
- union {
- struct common {
- u8 verb;
- u8 reserved[63];
- } common;
- struct dq {
- u8 verb;
- u8 stat;
- __le16 seqnum;
- __le16 oprid;
- u8 reserved;
- u8 tok;
- __le32 fqid;
- u32 reserved2;
- __le32 fq_byte_cnt;
- __le32 fq_frm_cnt;
- __le64 fqd_ctx;
- u8 fd[32];
- } dq;
- struct scn {
- u8 verb;
- u8 stat;
- u8 state;
- u8 reserved;
- __le32 rid_tok;
- __le64 ctx;
- } scn;
- };
-};
-
-/* Parsing frame dequeue results */
-/* FQ empty */
-#define DPAA2_DQ_STAT_FQEMPTY 0x80
-/* FQ held active */
-#define DPAA2_DQ_STAT_HELDACTIVE 0x40
-/* FQ force eligible */
-#define DPAA2_DQ_STAT_FORCEELIGIBLE 0x20
-/* valid frame */
-#define DPAA2_DQ_STAT_VALIDFRAME 0x10
-/* FQ ODP enable */
-#define DPAA2_DQ_STAT_ODPVALID 0x04
-/* volatile dequeue */
-#define DPAA2_DQ_STAT_VOLATILE 0x02
-/* volatile dequeue command is expired */
-#define DPAA2_DQ_STAT_EXPIRED 0x01
-
-#define DQ_FQID_MASK 0x00FFFFFF
-#define DQ_FRAME_COUNT_MASK 0x00FFFFFF
-
-/**
- * dpaa2_dq_flags() - Get the stat field of dequeue response
- * @dq: the dequeue result.
- */
-static inline u32 dpaa2_dq_flags(const struct dpaa2_dq *dq)
-{
- return dq->dq.stat;
-}
-
-/**
- * dpaa2_dq_is_pull() - Check whether the dq response is from a pull
- * command.
- * @dq: the dequeue result
- *
- * Return 1 for volatile(pull) dequeue, 0 for static dequeue.
- */
-static inline int dpaa2_dq_is_pull(const struct dpaa2_dq *dq)
-{
- return (int)(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_VOLATILE);
-}
-
-/**
- * dpaa2_dq_is_pull_complete() - Check whether the pull command is completed.
- * @dq: the dequeue result
- *
- * Return boolean.
- */
-static inline bool dpaa2_dq_is_pull_complete(const struct dpaa2_dq *dq)
-{
- return !!(dpaa2_dq_flags(dq) & DPAA2_DQ_STAT_EXPIRED);
-}
-
-/**
- * dpaa2_dq_seqnum() - Get the seqnum field in dequeue response
- * @dq: the dequeue result
- *
- * seqnum is valid only if VALIDFRAME flag is TRUE
- *
- * Return seqnum.
- */
-static inline u16 dpaa2_dq_seqnum(const struct dpaa2_dq *dq)
-{
- return le16_to_cpu(dq->dq.seqnum);
-}
-
-/**
- * dpaa2_dq_odpid() - Get the odpid field in dequeue response
- * @dq: the dequeue result
- *
- * odpid is valid only if ODPVALID flag is TRUE.
- *
- * Return odpid.
- */
-static inline u16 dpaa2_dq_odpid(const struct dpaa2_dq *dq)
-{
- return le16_to_cpu(dq->dq.oprid);
-}
-
-/**
- * dpaa2_dq_fqid() - Get the fqid in dequeue response
- * @dq: the dequeue result
- *
- * Return fqid.
- */
-static inline u32 dpaa2_dq_fqid(const struct dpaa2_dq *dq)
-{
- return le32_to_cpu(dq->dq.fqid) & DQ_FQID_MASK;
-}
-
-/**
- * dpaa2_dq_byte_count() - Get the byte count in dequeue response
- * @dq: the dequeue result
- *
- * Return the byte count remaining in the FQ.
- */
-static inline u32 dpaa2_dq_byte_count(const struct dpaa2_dq *dq)
-{
- return le32_to_cpu(dq->dq.fq_byte_cnt);
-}
-
-/**
- * dpaa2_dq_frame_count() - Get the frame count in dequeue response
- * @dq: the dequeue result
- *
- * Return the frame count remaining in the FQ.
- */
-static inline u32 dpaa2_dq_frame_count(const struct dpaa2_dq *dq)
-{
- return le32_to_cpu(dq->dq.fq_frm_cnt) & DQ_FRAME_COUNT_MASK;
-}
-
-/**
- * dpaa2_dq_fd_ctx() - Get the frame queue context in dequeue response
- * @dq: the dequeue result
- *
- * Return the frame queue context.
- */
-static inline u64 dpaa2_dq_fqd_ctx(const struct dpaa2_dq *dq)
-{
- return le64_to_cpu(dq->dq.fqd_ctx);
-}
-
-/**
- * dpaa2_dq_fd() - Get the frame descriptor in dequeue response
- * @dq: the dequeue result
- *
- * Return the frame descriptor.
- */
-static inline const struct dpaa2_fd *dpaa2_dq_fd(const struct dpaa2_dq *dq)
-{
- return (const struct dpaa2_fd *)&dq->dq.fd[0];
-}
-
-#endif /* __FSL_DPAA2_GLOBAL_H */
diff --git a/drivers/staging/fsl-mc/include/dpaa2-io.h b/drivers/staging/fsl-mc/include/dpaa2-io.h
deleted file mode 100644
index ab51e40d11db..000000000000
--- a/drivers/staging/fsl-mc/include/dpaa2-io.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
-/*
- * Copyright 2014-2016 Freescale Semiconductor Inc.
- * Copyright NXP
- *
- */
-#ifndef __FSL_DPAA2_IO_H
-#define __FSL_DPAA2_IO_H
-
-#include <linux/types.h>
-#include <linux/cpumask.h>
-#include <linux/irqreturn.h>
-
-#include "dpaa2-fd.h"
-#include "dpaa2-global.h"
-
-struct dpaa2_io;
-struct dpaa2_io_store;
-struct device;
-
-/**
- * DOC: DPIO Service
- *
- * The DPIO service provides APIs for users to interact with the datapath
- * by enqueueing and dequeing frame descriptors.
- *
- * The following set of APIs can be used to enqueue and dequeue frames
- * as well as producing notification callbacks when data is available
- * for dequeue.
- */
-
-#define DPAA2_IO_ANY_CPU -1
-
-/**
- * struct dpaa2_io_desc - The DPIO descriptor
- * @receives_notifications: Use notificaton mode. Non-zero if the DPIO
- * has a channel.
- * @has_8prio: Set to non-zero for channel with 8 priority WQs. Ignored
- * unless receives_notification is TRUE.
- * @cpu: The cpu index that at least interrupt handlers will
- * execute on.
- * @stash_affinity: The stash affinity for this portal favour 'cpu'
- * @regs_cena: The cache enabled regs.
- * @regs_cinh: The cache inhibited regs
- * @dpio_id: The dpio index
- * @qman_version: The qman version
- *
- * Describes the attributes and features of the DPIO object.
- */
-struct dpaa2_io_desc {
- int receives_notifications;
- int has_8prio;
- int cpu;
- void *regs_cena;
- void __iomem *regs_cinh;
- int dpio_id;
- u32 qman_version;
-};
-
-struct dpaa2_io *dpaa2_io_create(const struct dpaa2_io_desc *desc);
-
-void dpaa2_io_down(struct dpaa2_io *d);
-
-irqreturn_t dpaa2_io_irq(struct dpaa2_io *obj);
-
-struct dpaa2_io *dpaa2_io_service_select(int cpu);
-
-/**
- * struct dpaa2_io_notification_ctx - The DPIO notification context structure
- * @cb: The callback to be invoked when the notification arrives
- * @is_cdan: Zero for FQDAN, non-zero for CDAN
- * @id: FQID or channel ID, needed for rearm
- * @desired_cpu: The cpu on which the notifications will show up. Use
- * DPAA2_IO_ANY_CPU if don't care
- * @dpio_id: The dpio index
- * @qman64: The 64-bit context value shows up in the FQDAN/CDAN.
- * @node: The list node
- * @dpio_private: The dpio object internal to dpio_service
- *
- * Used when a FQDAN/CDAN registration is made by drivers.
- */
-struct dpaa2_io_notification_ctx {
- void (*cb)(struct dpaa2_io_notification_ctx *ctx);
- int is_cdan;
- u32 id;
- int desired_cpu;
- int dpio_id;
- u64 qman64;
- struct list_head node;
- void *dpio_private;
-};
-
-int dpaa2_io_service_register(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx);
-void dpaa2_io_service_deregister(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx);
-int dpaa2_io_service_rearm(struct dpaa2_io *service,
- struct dpaa2_io_notification_ctx *ctx);
-
-int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid,
- struct dpaa2_io_store *s);
-
-int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
- u16 qdbin, const struct dpaa2_fd *fd);
-int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid,
- const u64 *buffers, unsigned int num_buffers);
-int dpaa2_io_service_acquire(struct dpaa2_io *d, u32 bpid,
- u64 *buffers, unsigned int num_buffers);
-
-struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames,
- struct device *dev);
-void dpaa2_io_store_destroy(struct dpaa2_io_store *s);
-struct dpaa2_dq *dpaa2_io_store_next(struct dpaa2_io_store *s, int *is_last);
-
-#endif /* __FSL_DPAA2_IO_H */
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
index 0126de898036..3c59e19029be 100644
--- a/drivers/tee/optee/Kconfig
+++ b/drivers/tee/optee/Kconfig
@@ -5,3 +5,11 @@ config OPTEE
help
This implements the OP-TEE Trusted Execution Environment (TEE)
driver.
+
+config OPTEE_SHM_NUM_PRIV_PAGES
+ int "Private Shared Memory Pages"
+ default 1
+ depends on OPTEE
+ help
+ This sets the number of private shared memory pages to be
+ used by OP-TEE TEE driver.
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index e5fd5ed217da..e1aafe842d66 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -32,7 +32,7 @@
#define DRIVER_NAME "optee"
-#define OPTEE_SHM_NUM_PRIV_PAGES 1
+#define OPTEE_SHM_NUM_PRIV_PAGES CONFIG_OPTEE_SHM_NUM_PRIV_PAGES
/**
* optee_from_msg_param() - convert from OPTEE_MSG parameters to
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
index 41aea12e2bcc..b45c73dd37a5 100644
--- a/drivers/tee/optee/rpc.c
+++ b/drivers/tee/optee/rpc.c
@@ -48,7 +48,7 @@ static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
goto bad;
- getnstimeofday64(&ts);
+ ktime_get_real_ts64(&ts);
arg->params[0].u.value.a = ts.tv_sec;
arg->params[0].u.value.b = ts.tv_nsec;
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index d9145a8f35d2..8e3bab1e0c1f 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -161,16 +161,10 @@ static int exynos_ehci_probe(struct platform_device *pdev)
}
exynos_ehci = to_exynos_ehci(hcd);
- if (of_device_is_compatible(pdev->dev.of_node,
- "samsung,exynos5440-ehci"))
- goto skip_phy;
-
err = exynos_ehci_get_phy(&pdev->dev, exynos_ehci);
if (err)
goto fail_clk;
-skip_phy:
-
exynos_ehci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ehci->clk)) {
@@ -304,7 +298,6 @@ static const struct dev_pm_ops exynos_ehci_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id exynos_ehci_match[] = {
{ .compatible = "samsung,exynos4210-ehci" },
- { .compatible = "samsung,exynos5440-ehci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ehci_match);
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index a39fae41bc70..c0c4dcca6f3c 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -130,15 +130,10 @@ static int exynos_ohci_probe(struct platform_device *pdev)
exynos_ohci = to_exynos_ohci(hcd);
- if (of_device_is_compatible(pdev->dev.of_node,
- "samsung,exynos5440-ohci"))
- goto skip_phy;
-
err = exynos_ohci_get_phy(&pdev->dev, exynos_ohci);
if (err)
goto fail_clk;
-skip_phy:
exynos_ohci->clk = devm_clk_get(&pdev->dev, "usbhost");
if (IS_ERR(exynos_ohci->clk)) {
@@ -270,7 +265,6 @@ static const struct dev_pm_ops exynos_ohci_pm_ops = {
#ifdef CONFIG_OF
static const struct of_device_id exynos_ohci_match[] = {
{ .compatible = "samsung,exynos4210-ohci" },
- { .compatible = "samsung,exynos5440-ohci" },
{},
};
MODULE_DEVICE_TABLE(of, exynos_ohci_match);
diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig
index e91edef98633..787792c3d08d 100644
--- a/drivers/video/console/Kconfig
+++ b/drivers/video/console/Kconfig
@@ -152,7 +152,7 @@ config FRAMEBUFFER_CONSOLE_ROTATION
config FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
bool "Framebuffer Console Deferred Takeover"
- depends on FRAMEBUFFER_CONSOLE=y && DUMMY_CONSOLE=y
+ depends on FB=y && FRAMEBUFFER_CONSOLE && DUMMY_CONSOLE
help
If enabled this defers the framebuffer console taking over the
console from the dummy console until the first text is displayed on
diff --git a/drivers/video/console/dummycon.c b/drivers/video/console/dummycon.c
index 0254251fdd79..45ad925ad5f8 100644
--- a/drivers/video/console/dummycon.c
+++ b/drivers/video/console/dummycon.c
@@ -38,13 +38,11 @@ void dummycon_register_output_notifier(struct notifier_block *nb)
if (dummycon_putc_called)
nb->notifier_call(nb, 0, NULL);
}
-EXPORT_SYMBOL_GPL(dummycon_register_output_notifier);
void dummycon_unregister_output_notifier(struct notifier_block *nb)
{
raw_notifier_chain_unregister(&dummycon_output_nh, nb);
}
-EXPORT_SYMBOL_GPL(dummycon_unregister_output_notifier);
static void dummycon_putc(struct vc_data *vc, int c, int ypos, int xpos)
{
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index f09e17b60e45..09731b2f6815 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -112,6 +112,11 @@ EXPORT_SYMBOL(vgacon_text_force);
static int __init text_mode(char *str)
{
vgacon_text_mode_force = true;
+
+ pr_warning("You have booted with nomodeset. This means your GPU drivers are DISABLED\n");
+ pr_warning("Any video related functionality will be severely degraded, and you may not even be able to suspend the system properly\n");
+ pr_warning("Unless you actually understand what nomodeset does, you should reboot without enabling it\n");
+
return 1;
}
diff --git a/drivers/video/fbdev/amifb.c b/drivers/video/fbdev/amifb.c
index cc11c6061298..0777aff211e5 100644
--- a/drivers/video/fbdev/amifb.c
+++ b/drivers/video/fbdev/amifb.c
@@ -2303,7 +2303,7 @@ static void ami_build_copper(struct fb_info *info)
ami_rebuild_copper(info->par);
}
-
+#ifndef MODULE
static void __init amifb_setup_mcap(char *spec)
{
char *p;
@@ -2368,7 +2368,7 @@ static int __init amifb_setup(char *options)
return 0;
}
-
+#endif
static int amifb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 5fb156bdcf4e..75ebbbf0a1fb 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -2234,8 +2234,8 @@ static int fbcon_switch(struct vc_data *vc)
*
* info->currcon = vc->vc_num;
*/
- for (i = 0; i < FB_MAX; i++) {
- if (registered_fb[i] != NULL && registered_fb[i]->fbcon_par) {
+ for_each_registered_fb(i) {
+ if (registered_fb[i]->fbcon_par) {
struct fbcon_ops *o = registered_fb[i]->fbcon_par;
o->currcon = vc->vc_num;
@@ -3124,11 +3124,9 @@ static int fbcon_fb_unregistered(struct fb_info *info)
if (idx == info_idx) {
info_idx = -1;
- for (i = 0; i < FB_MAX; i++) {
- if (registered_fb[i] != NULL) {
- info_idx = i;
- break;
- }
+ for_each_registered_fb(i) {
+ info_idx = i;
+ break;
}
}
@@ -3594,13 +3592,24 @@ static int fbcon_init_device(void)
}
#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
+static void fbcon_register_existing_fbs(struct work_struct *work)
+{
+ int i;
+
+ console_lock();
+
+ for_each_registered_fb(i)
+ fbcon_fb_registered(registered_fb[i]);
+
+ console_unlock();
+}
+
static struct notifier_block fbcon_output_nb;
+static DECLARE_WORK(fbcon_deferred_takeover_work, fbcon_register_existing_fbs);
static int fbcon_output_notifier(struct notifier_block *nb,
unsigned long action, void *data)
{
- int i;
-
WARN_CONSOLE_UNLOCKED();
pr_info("fbcon: Taking over console\n");
@@ -3609,45 +3618,37 @@ static int fbcon_output_notifier(struct notifier_block *nb,
deferred_takeover = false;
logo_shown = FBCON_LOGO_DONTSHOW;
- for (i = 0; i < FB_MAX; i++) {
- if (registered_fb[i])
- fbcon_fb_registered(registered_fb[i]);
- }
+ /* We may get called in atomic context */
+ schedule_work(&fbcon_deferred_takeover_work);
return NOTIFY_OK;
}
-
-static void fbcon_register_output_notifier(void)
-{
- fbcon_output_nb.notifier_call = fbcon_output_notifier;
- dummycon_register_output_notifier(&fbcon_output_nb);
-}
-#else
-static inline void fbcon_register_output_notifier(void) {}
#endif
static void fbcon_start(void)
{
+ WARN_CONSOLE_UNLOCKED();
+
+#ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER
+ if (conswitchp != &dummy_con)
+ deferred_takeover = false;
+
if (deferred_takeover) {
- fbcon_register_output_notifier();
+ fbcon_output_nb.notifier_call = fbcon_output_notifier;
+ dummycon_register_output_notifier(&fbcon_output_nb);
return;
}
+#endif
if (num_registered_fb) {
int i;
- console_lock();
-
- for (i = 0; i < FB_MAX; i++) {
- if (registered_fb[i] != NULL) {
- info_idx = i;
- break;
- }
+ for_each_registered_fb(i) {
+ info_idx = i;
+ break;
}
do_fbcon_takeover(0);
- console_unlock();
-
}
}
@@ -3669,15 +3670,12 @@ static void fbcon_exit(void)
kfree((void *)softback_buf);
softback_buf = 0UL;
- for (i = 0; i < FB_MAX; i++) {
+ for_each_registered_fb(i) {
int pending = 0;
mapped = 0;
info = registered_fb[i];
- if (info == NULL)
- continue;
-
if (info->queue.func)
pending = cancel_work_sync(&info->queue);
DPRINTK("fbcon: %s pending work\n", (pending ? "canceled" :
@@ -3733,8 +3731,8 @@ void __init fb_console_init(void)
for (i = 0; i < MAX_NR_CONSOLES; i++)
con2fb_map[i] = -1;
- console_unlock();
fbcon_start();
+ console_unlock();
}
#ifdef MODULE
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 609438d2465b..20405421a5ed 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1347,6 +1347,7 @@ static long fb_compat_ioctl(struct file *file, unsigned int cmd,
case FBIOGET_CON2FBMAP:
case FBIOPUT_CON2FBMAP:
arg = (unsigned long) compat_ptr(arg);
+ /* fall through */
case FBIOBLANK:
ret = do_fb_ioctl(info, cmd, arg);
break;
@@ -1593,10 +1594,8 @@ static int do_remove_conflicting_framebuffers(struct apertures_struct *a,
int i, ret;
/* check all firmware fbs and kick off if the base addr overlaps */
- for (i = 0 ; i < FB_MAX; i++) {
+ for_each_registered_fb(i) {
struct apertures_struct *gen_aper;
- if (!registered_fb[i])
- continue;
if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE))
continue;
@@ -1691,25 +1690,30 @@ static int do_register_framebuffer(struct fb_info *fb_info)
event.info = fb_info;
if (!lockless_register_fb)
console_lock();
+ else
+ atomic_inc(&ignore_console_lock_warning);
if (!lock_fb_info(fb_info)) {
- if (!lockless_register_fb)
- console_unlock();
- return -ENODEV;
+ ret = -ENODEV;
+ goto unlock_console;
}
+ ret = 0;
fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event);
unlock_fb_info(fb_info);
+unlock_console:
if (!lockless_register_fb)
console_unlock();
- return 0;
+ else
+ atomic_dec(&ignore_console_lock_warning);
+ return ret;
}
-static int do_unregister_framebuffer(struct fb_info *fb_info)
+static int unbind_console(struct fb_info *fb_info)
{
struct fb_event event;
- int i, ret = 0;
+ int ret;
+ int i = fb_info->node;
- i = fb_info->node;
if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info)
return -EINVAL;
@@ -1724,17 +1728,29 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
unlock_fb_info(fb_info);
console_unlock();
+ return ret;
+}
+
+static int __unlink_framebuffer(struct fb_info *fb_info);
+
+static int do_unregister_framebuffer(struct fb_info *fb_info)
+{
+ struct fb_event event;
+ int ret;
+
+ ret = unbind_console(fb_info);
+
if (ret)
return -EINVAL;
pm_vt_switch_unregister(fb_info->dev);
- unlink_framebuffer(fb_info);
+ __unlink_framebuffer(fb_info);
if (fb_info->pixmap.addr &&
(fb_info->pixmap.flags & FB_PIXMAP_DEFAULT))
kfree(fb_info->pixmap.addr);
fb_destroy_modelist(&fb_info->modelist);
- registered_fb[i] = NULL;
+ registered_fb[fb_info->node] = NULL;
num_registered_fb--;
fb_cleanup_device(fb_info);
event.info = fb_info;
@@ -1747,7 +1763,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info)
return 0;
}
-int unlink_framebuffer(struct fb_info *fb_info)
+static int __unlink_framebuffer(struct fb_info *fb_info)
{
int i;
@@ -1759,6 +1775,20 @@ int unlink_framebuffer(struct fb_info *fb_info)
device_destroy(fb_class, MKDEV(FB_MAJOR, i));
fb_info->dev = NULL;
}
+
+ return 0;
+}
+
+int unlink_framebuffer(struct fb_info *fb_info)
+{
+ int ret;
+
+ ret = __unlink_framebuffer(fb_info);
+ if (ret)
+ return ret;
+
+ unbind_console(fb_info);
+
return 0;
}
EXPORT_SYMBOL(unlink_framebuffer);
diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c
index 2510fa728d77..283d9307df21 100644
--- a/drivers/video/fbdev/core/modedb.c
+++ b/drivers/video/fbdev/core/modedb.c
@@ -628,45 +628,47 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
}
/**
- * fb_find_mode - finds a valid video mode
- * @var: frame buffer user defined part of display
- * @info: frame buffer info structure
- * @mode_option: string video mode to find
- * @db: video mode database
- * @dbsize: size of @db
- * @default_mode: default video mode to fall back to
- * @default_bpp: default color depth in bits per pixel
+ * fb_find_mode - finds a valid video mode
+ * @var: frame buffer user defined part of display
+ * @info: frame buffer info structure
+ * @mode_option: string video mode to find
+ * @db: video mode database
+ * @dbsize: size of @db
+ * @default_mode: default video mode to fall back to
+ * @default_bpp: default color depth in bits per pixel
*
- * Finds a suitable video mode, starting with the specified mode
- * in @mode_option with fallback to @default_mode. If
- * @default_mode fails, all modes in the video mode database will
- * be tried.
+ * Finds a suitable video mode, starting with the specified mode
+ * in @mode_option with fallback to @default_mode. If
+ * @default_mode fails, all modes in the video mode database will
+ * be tried.
*
- * Valid mode specifiers for @mode_option:
+ * Valid mode specifiers for @mode_option::
*
- * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
- * <name>[-<bpp>][@<refresh>]
+ * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][p][m]
+ *
+ * or ::
*
- * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
- * <name> a string.
+ * <name>[-<bpp>][@<refresh>]
*
- * If 'M' is present after yres (and before refresh/bpp if present),
- * the function will compute the timings using VESA(tm) Coordinated
- * Video Timings (CVT). If 'R' is present after 'M', will compute with
- * reduced blanking (for flatpanels). If 'i' is present, compute
- * interlaced mode. If 'm' is present, add margins equal to 1.8%
- * of xres rounded down to 8 pixels, and 1.8% of yres. The char
- * 'i' and 'm' must be after 'M' and 'R'. Example:
+ * with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
+ * <name> a string.
*
- * 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
+ * If 'M' is present after yres (and before refresh/bpp if present),
+ * the function will compute the timings using VESA(tm) Coordinated
+ * Video Timings (CVT). If 'R' is present after 'M', will compute with
+ * reduced blanking (for flatpanels). If 'i' or 'p' are present, compute
+ * interlaced or progressive mode. If 'm' is present, add margins equal
+ * to 1.8% of xres rounded down to 8 pixels, and 1.8% of yres. The char
+ * 'i', 'p' and 'm' must be after 'M' and 'R'. Example::
*
- * NOTE: The passed struct @var is _not_ cleared! This allows you
- * to supply values for e.g. the grayscale and accel_flags fields.
+ * 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
*
- * Returns zero for failure, 1 if using specified @mode_option,
- * 2 if using specified @mode_option with an ignored refresh rate,
- * 3 if default mode is used, 4 if fall back to any valid mode.
+ * NOTE: The passed struct @var is _not_ cleared! This allows you
+ * to supply values for e.g. the grayscale and accel_flags fields.
*
+ * Returns zero for failure, 1 if using specified @mode_option,
+ * 2 if using specified @mode_option with an ignored refresh rate,
+ * 3 if default mode is used, 4 if fall back to any valid mode.
*/
int fb_find_mode(struct fb_var_screeninfo *var,
@@ -697,7 +699,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
- int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
+ int yres_specified = 0, cvt = 0, rb = 0;
+ int interlace_specified = 0, interlace = 0;
int margins = 0;
u32 best, diff, tdiff;
@@ -748,9 +751,17 @@ int fb_find_mode(struct fb_var_screeninfo *var,
if (!cvt)
margins = 1;
break;
+ case 'p':
+ if (!cvt) {
+ interlace = 0;
+ interlace_specified = 1;
+ }
+ break;
case 'i':
- if (!cvt)
+ if (!cvt) {
interlace = 1;
+ interlace_specified = 1;
+ }
break;
default:
goto done;
@@ -819,11 +830,21 @@ done:
if ((name_matches(db[i], name, namelen) ||
(res_specified && res_matches(db[i], xres, yres))) &&
!fb_try_mode(var, info, &db[i], bpp)) {
- if (refresh_specified && db[i].refresh == refresh)
- return 1;
+ const int db_interlace = (db[i].vmode &
+ FB_VMODE_INTERLACED ? 1 : 0);
+ int score = abs(db[i].refresh - refresh);
+
+ if (interlace_specified)
+ score += abs(db_interlace - interlace);
+
+ if (!interlace_specified ||
+ db_interlace == interlace)
+ if (refresh_specified &&
+ db[i].refresh == refresh)
+ return 1;
- if (abs(db[i].refresh - refresh) < diff) {
- diff = abs(db[i].refresh - refresh);
+ if (score < diff) {
+ diff = score;
best = i;
}
}
diff --git a/drivers/video/fbdev/efifb.c b/drivers/video/fbdev/efifb.c
index c6f78d27947b..3946649b85c8 100644
--- a/drivers/video/fbdev/efifb.c
+++ b/drivers/video/fbdev/efifb.c
@@ -9,16 +9,39 @@
#include <linux/kernel.h>
#include <linux/efi.h>
+#include <linux/efi-bgrt.h>
#include <linux/errno.h>
#include <linux/fb.h>
#include <linux/pci.h>
#include <linux/platform_device.h>
+#include <linux/printk.h>
#include <linux/screen_info.h>
#include <video/vga.h>
#include <asm/efi.h>
#include <drm/drm_utils.h> /* For drm_get_panel_orientation_quirk */
#include <drm/drm_connector.h> /* For DRM_MODE_PANEL_ORIENTATION_* */
+struct bmp_file_header {
+ u16 id;
+ u32 file_size;
+ u32 reserved;
+ u32 bitmap_offset;
+} __packed;
+
+struct bmp_dib_header {
+ u32 dib_header_size;
+ s32 width;
+ s32 height;
+ u16 planes;
+ u16 bpp;
+ u32 compression;
+ u32 bitmap_size;
+ u32 horz_resolution;
+ u32 vert_resolution;
+ u32 colors_used;
+ u32 colors_important;
+} __packed;
+
static bool request_mem_succeeded = false;
static u64 mem_flags = EFI_MEMORY_WC | EFI_MEMORY_UC;
@@ -66,6 +89,164 @@ static int efifb_setcolreg(unsigned regno, unsigned red, unsigned green,
return 0;
}
+/*
+ * If fbcon deffered console takeover is configured, the intent is for the
+ * framebuffer to show the boot graphics (e.g. vendor logo) until there is some
+ * (error) message to display. But the boot graphics may have been destroyed by
+ * e.g. option ROM output, detect this and restore the boot graphics.
+ */
+#if defined CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER && \
+ defined CONFIG_ACPI_BGRT
+static void efifb_copy_bmp(u8 *src, u32 *dst, int width, struct screen_info *si)
+{
+ u8 r, g, b;
+
+ while (width--) {
+ b = *src++;
+ g = *src++;
+ r = *src++;
+ *dst++ = (r << si->red_pos) |
+ (g << si->green_pos) |
+ (b << si->blue_pos);
+ }
+}
+
+#ifdef CONFIG_X86
+/*
+ * On x86 some firmwares use a low non native resolution for the display when
+ * they have shown some text messages. While keeping the bgrt filled with info
+ * for the native resolution. If the bgrt image intended for the native
+ * resolution still fits, it will be displayed very close to the right edge of
+ * the display looking quite bad. This function checks for this.
+ */
+static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
+{
+ static const int default_resolutions[][2] = {
+ { 800, 600 },
+ { 1024, 768 },
+ { 1280, 1024 },
+ };
+ u32 i, right_margin;
+
+ for (i = 0; i < ARRAY_SIZE(default_resolutions); i++) {
+ if (default_resolutions[i][0] == si->lfb_width &&
+ default_resolutions[i][1] == si->lfb_height)
+ break;
+ }
+ /* If not a default resolution used for textmode, this should be fine */
+ if (i >= ARRAY_SIZE(default_resolutions))
+ return true;
+
+ /* If the right margin is 5 times smaller then the left one, reject */
+ right_margin = si->lfb_width - (bgrt_tab.image_offset_x + bmp_width);
+ if (right_margin < (bgrt_tab.image_offset_x / 5))
+ return false;
+
+ return true;
+}
+#else
+static bool efifb_bgrt_sanity_check(struct screen_info *si, u32 bmp_width)
+{
+ return true;
+}
+#endif
+
+static void efifb_show_boot_graphics(struct fb_info *info)
+{
+ u32 bmp_width, bmp_height, bmp_pitch, screen_pitch, dst_x, y, src_y;
+ struct screen_info *si = &screen_info;
+ struct bmp_file_header *file_header;
+ struct bmp_dib_header *dib_header;
+ void *bgrt_image = NULL;
+ u8 *dst = info->screen_base;
+
+ if (!bgrt_tab.image_address) {
+ pr_info("efifb: No BGRT, not showing boot graphics\n");
+ return;
+ }
+
+ /* Avoid flashing the logo if we're going to print std probe messages */
+ if (console_loglevel > CONSOLE_LOGLEVEL_QUIET)
+ return;
+
+ /* bgrt_tab.status is unreliable, so we don't check it */
+
+ if (si->lfb_depth != 32) {
+ pr_info("efifb: not 32 bits, not showing boot graphics\n");
+ return;
+ }
+
+ bgrt_image = memremap(bgrt_tab.image_address, bgrt_image_size,
+ MEMREMAP_WB);
+ if (!bgrt_image) {
+ pr_warn("efifb: Ignoring BGRT: failed to map image memory\n");
+ return;
+ }
+
+ if (bgrt_image_size < (sizeof(*file_header) + sizeof(*dib_header)))
+ goto error;
+
+ file_header = bgrt_image;
+ if (file_header->id != 0x4d42 || file_header->reserved != 0)
+ goto error;
+
+ dib_header = bgrt_image + sizeof(*file_header);
+ if (dib_header->dib_header_size != 40 || dib_header->width < 0 ||
+ dib_header->planes != 1 || dib_header->bpp != 24 ||
+ dib_header->compression != 0)
+ goto error;
+
+ bmp_width = dib_header->width;
+ bmp_height = abs(dib_header->height);
+ bmp_pitch = round_up(3 * bmp_width, 4);
+ screen_pitch = si->lfb_linelength;
+
+ if ((file_header->bitmap_offset + bmp_pitch * bmp_height) >
+ bgrt_image_size)
+ goto error;
+
+ if ((bgrt_tab.image_offset_x + bmp_width) > si->lfb_width ||
+ (bgrt_tab.image_offset_y + bmp_height) > si->lfb_height)
+ goto error;
+
+ if (!efifb_bgrt_sanity_check(si, bmp_width))
+ goto error;
+
+ pr_info("efifb: showing boot graphics\n");
+
+ for (y = 0; y < si->lfb_height; y++, dst += si->lfb_linelength) {
+ /* Only background? */
+ if (y < bgrt_tab.image_offset_y ||
+ y >= (bgrt_tab.image_offset_y + bmp_height)) {
+ memset(dst, 0, 4 * si->lfb_width);
+ continue;
+ }
+
+ src_y = y - bgrt_tab.image_offset_y;
+ /* Positive header height means upside down row order */
+ if (dib_header->height > 0)
+ src_y = (bmp_height - 1) - src_y;
+
+ memset(dst, 0, bgrt_tab.image_offset_x * 4);
+ dst_x = bgrt_tab.image_offset_x;
+ efifb_copy_bmp(bgrt_image + file_header->bitmap_offset +
+ src_y * bmp_pitch,
+ (u32 *)dst + dst_x, bmp_width, si);
+ dst_x += bmp_width;
+ memset((u32 *)dst + dst_x, 0, (si->lfb_width - dst_x) * 4);
+ }
+
+ memunmap(bgrt_image);
+ return;
+
+error:
+ memunmap(bgrt_image);
+ pr_warn("efifb: Ignoring BGRT: unexpected or invalid BMP data\n");
+}
+#else
+static inline void efifb_show_boot_graphics(struct fb_info *info) {}
+#endif
+
static void efifb_destroy(struct fb_info *info)
{
if (info->screen_base) {
@@ -311,6 +492,8 @@ static int efifb_probe(struct platform_device *dev)
goto err_release_fb;
}
+ efifb_show_boot_graphics(info);
+
pr_info("efifb: framebuffer at 0x%lx, using %dk, total %dk\n",
efifb_fix.smem_start, size_remap/1024, size_total/1024);
pr_info("efifb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
diff --git a/drivers/video/fbdev/fsl-diu-fb.c b/drivers/video/fbdev/fsl-diu-fb.c
index 1bfd13cbd4e3..bc9eb8afc313 100644
--- a/drivers/video/fbdev/fsl-diu-fb.c
+++ b/drivers/video/fbdev/fsl-diu-fb.c
@@ -360,6 +360,10 @@ struct mfb_info {
* @ad[]: Area Descriptors for each real AOI
* @gamma: gamma color table
* @cursor: hardware cursor data
+ * @blank_cursor: blank cursor for hiding cursor
+ * @next_cursor: scratch space to build load cursor
+ * @edid_data: EDID information buffer
+ * @has_edid: whether or not the EDID buffer is valid
*
* This data structure must be allocated with 32-byte alignment, so that the
* internal fields can be aligned properly.
@@ -381,6 +385,8 @@ struct fsl_diu_data {
__le16 cursor[MAX_CURS * MAX_CURS] __aligned(32);
/* Blank cursor data -- used to hide the cursor */
__le16 blank_cursor[MAX_CURS * MAX_CURS] __aligned(32);
+ /* Scratch cursor data -- used to build new cursor */
+ __le16 next_cursor[MAX_CURS * MAX_CURS] __aligned(32);
uint8_t edid_data[EDID_LENGTH];
bool has_edid;
} __aligned(32);
@@ -1056,13 +1062,17 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
* FB_CUR_SETSHAPE - the cursor bitmask has changed
*/
if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETIMAGE)) {
+ /*
+ * Determine the size of the cursor image data. Normally,
+ * it's 8x16.
+ */
unsigned int image_size =
- DIV_ROUND_UP(cursor->image.width, 8) * cursor->image.height;
+ DIV_ROUND_UP(cursor->image.width, 8) *
+ cursor->image.height;
unsigned int image_words =
DIV_ROUND_UP(image_size, sizeof(uint32_t));
unsigned int bg_idx = cursor->image.bg_color;
unsigned int fg_idx = cursor->image.fg_color;
- uint8_t buffer[image_size];
uint32_t *image, *source, *mask;
uint16_t fg, bg;
unsigned int i;
@@ -1070,13 +1080,6 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
if (info->state != FBINFO_STATE_RUNNING)
return 0;
- /*
- * Determine the size of the cursor image data. Normally,
- * it's 8x16.
- */
- image_size = DIV_ROUND_UP(cursor->image.width, 8) *
- cursor->image.height;
-
bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
((info->cmap.green[bg_idx] & 0xf8) << 2) |
((info->cmap.blue[bg_idx] & 0xf8) >> 3) |
@@ -1088,7 +1091,7 @@ static int fsl_diu_cursor(struct fb_info *info, struct fb_cursor *cursor)
1 << 15;
/* Use 32-bit operations on the data to improve performance */
- image = (uint32_t *)buffer;
+ image = (uint32_t *)data->next_cursor;
source = (uint32_t *)cursor->image.data;
mask = (uint32_t *)cursor->mask;
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index 3b70044773b6..4377e3442638 100644
--- a/drivers/video/fbdev/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>
+#include <linux/acpi.h>
enum {
FB_GET_WIDTH = 0x00,
@@ -124,6 +125,7 @@ static int goldfish_fb_check_var(struct fb_var_screeninfo *var,
static int goldfish_fb_set_par(struct fb_info *info)
{
struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+
if (fb->rotation != fb->fb.var.rotate) {
info->fix.line_length = info->var.xres * 2;
fb->rotation = fb->fb.var.rotate;
@@ -148,13 +150,14 @@ static int goldfish_fb_pan_display(struct fb_var_screeninfo *var,
wait_event_timeout(fb->wait,
fb->base_update_count != base_update_count, HZ / 15);
if (fb->base_update_count == base_update_count)
- pr_err("goldfish_fb_pan_display: timeout waiting for base update\n");
+ pr_err("%s: timeout waiting for base update\n", __func__);
return 0;
}
static int goldfish_fb_blank(int blank, struct fb_info *info)
{
struct goldfish_fb *fb = container_of(info, struct goldfish_fb, fb);
+
switch (blank) {
case FB_BLANK_NORMAL:
writel(1, fb->reg_base + FB_SET_BLANK);
@@ -234,7 +237,7 @@ static int goldfish_fb_probe(struct platform_device *pdev)
fb->fb.var.activate = FB_ACTIVATE_NOW;
fb->fb.var.height = readl(fb->reg_base + FB_GET_PHYS_HEIGHT);
fb->fb.var.width = readl(fb->reg_base + FB_GET_PHYS_WIDTH);
- fb->fb.var.pixclock = 10000;
+ fb->fb.var.pixclock = 0;
fb->fb.var.red.offset = 11;
fb->fb.var.red.length = 5;
@@ -301,6 +304,7 @@ static int goldfish_fb_remove(struct platform_device *pdev)
dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base,
fb->fb.fix.smem_start);
iounmap(fb->reg_base);
+ kfree(fb);
return 0;
}
@@ -310,12 +314,19 @@ static const struct of_device_id goldfish_fb_of_match[] = {
};
MODULE_DEVICE_TABLE(of, goldfish_fb_of_match);
+static const struct acpi_device_id goldfish_fb_acpi_match[] = {
+ { "GFSH0004", 0 },
+ { },
+};
+MODULE_DEVICE_TABLE(acpi, goldfish_fb_acpi_match);
+
static struct platform_driver goldfish_fb_driver = {
.probe = goldfish_fb_probe,
.remove = goldfish_fb_remove,
.driver = {
.name = "goldfish_fb",
.of_match_table = goldfish_fb_of_match,
+ .acpi_match_table = ACPI_PTR(goldfish_fb_acpi_match),
}
};
diff --git a/drivers/video/fbdev/i740fb.c b/drivers/video/fbdev/i740fb.c
index 7bc5f6056c77..f6d7b04d6dff 100644
--- a/drivers/video/fbdev/i740fb.c
+++ b/drivers/video/fbdev/i740fb.c
@@ -429,6 +429,7 @@ static int i740fb_decode_var(const struct fb_var_screeninfo *var,
break;
case 9 ... 15:
bpp = 15;
+ /* fall through */
case 16:
if ((1000000 / var->pixclock) > DACSPEED16) {
dev_err(info->device, "requested pixclock %i MHz out of range (max. %i MHz at 15/16bpp)\n",
diff --git a/drivers/video/fbdev/metronomefb.c b/drivers/video/fbdev/metronomefb.c
index 9085e9525341..bb4fee52e501 100644
--- a/drivers/video/fbdev/metronomefb.c
+++ b/drivers/video/fbdev/metronomefb.c
@@ -233,7 +233,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
/* check temperature range table checksum */
cksum_idx = sizeof(*wfm_hdr) + wfm_hdr->trc + 1;
- if (cksum_idx > size)
+ if (cksum_idx >= size)
return -EINVAL;
cksum = calc_cksum(sizeof(*wfm_hdr), cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
@@ -245,7 +245,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
/* check waveform mode table address checksum */
wmta = get_unaligned_le32(wfm_hdr->wmta) & 0x00FFFFFF;
cksum_idx = wmta + m*4 + 3;
- if (cksum_idx > size)
+ if (cksum_idx >= size)
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
@@ -257,7 +257,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
/* check waveform temperature table address checksum */
tta = get_unaligned_le32(mem + wmta + m * 4) & 0x00FFFFFF;
cksum_idx = tta + trn*4 + 3;
- if (cksum_idx > size)
+ if (cksum_idx >= size)
return -EINVAL;
cksum = calc_cksum(cksum_idx - 3, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
@@ -270,7 +270,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
metromem buffer. this does runlength decoding of the waveform */
wfm_idx = get_unaligned_le32(mem + tta + trn * 4) & 0x00FFFFFF;
owfm_idx = wfm_idx;
- if (wfm_idx > size)
+ if (wfm_idx >= size)
return -EINVAL;
while (wfm_idx < size) {
unsigned char rl;
@@ -292,7 +292,7 @@ static int load_waveform(u8 *mem, size_t size, int m, int t,
}
cksum_idx = wfm_idx;
- if (cksum_idx > size)
+ if (cksum_idx >= size)
return -EINVAL;
cksum = calc_cksum(owfm_idx, cksum_idx, mem);
if (cksum != mem[cksum_idx]) {
diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
index 585f39efcff6..1c75f4806ed3 100644
--- a/drivers/video/fbdev/omap/omapfb_main.c
+++ b/drivers/video/fbdev/omap/omapfb_main.c
@@ -958,7 +958,7 @@ int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
{
int r;
- if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+ if ((unsigned)omapfb_nb->plane_idx >= OMAPFB_PLANE_NUM)
return -EINVAL;
if (!notifier_inited) {
diff --git a/drivers/video/fbdev/omap2/omapfb/Makefile b/drivers/video/fbdev/omap2/omapfb/Makefile
index 602edfed09df..f54c3f56b641 100644
--- a/drivers/video/fbdev/omap2/omapfb/Makefile
+++ b/drivers/video/fbdev/omap2/omapfb/Makefile
@@ -2,5 +2,5 @@
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
obj-y += dss/
obj-y += displays/
-obj-$(CONFIG_FB_OMAP2) += omapfb.o
-omapfb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
+obj-$(CONFIG_FB_OMAP2) += omap2fb.o
+omap2fb-y := omapfb-main.o omapfb-sysfs.o omapfb-ioctl.o
diff --git a/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c
index 3079a3df8c37..47f0459e3551 100644
--- a/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c
+++ b/drivers/video/fbdev/omap2/omapfb/displays/encoder-tpd12s015.c
@@ -219,7 +219,7 @@ static int tpd_probe_of(struct platform_device *pdev)
static int tpd_probe(struct platform_device *pdev)
{
- struct omap_dss_device *in, *dssdev;
+ struct omap_dss_device *dssdev;
struct panel_drv_data *ddata;
int r;
struct gpio_desc *gpio;
@@ -238,25 +238,30 @@ static int tpd_probe(struct platform_device *pdev)
return -ENODEV;
}
-
gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 0,
GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->ct_cp_hpd_gpio = gpio;
gpio = devm_gpiod_get_index_optional(&pdev->dev, NULL, 1,
GPIOD_OUT_LOW);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->ls_oe_gpio = gpio;
gpio = devm_gpiod_get_index(&pdev->dev, NULL, 2,
GPIOD_IN);
- if (IS_ERR(gpio))
+ if (IS_ERR(gpio)) {
+ r = PTR_ERR(gpio);
goto err_gpio;
+ }
ddata->hpd_gpio = gpio;
@@ -268,8 +273,6 @@ static int tpd_probe(struct platform_device *pdev)
dssdev->owner = THIS_MODULE;
dssdev->port_num = 1;
- in = ddata->in;
-
r = omapdss_register_output(dssdev);
if (r) {
dev_err(&pdev->dev, "Failed to register output\n");
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
index fb605aefd9b1..a06d9c25765c 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/dispc.c
@@ -1858,7 +1858,7 @@ static s32 pixinc(int pixels, u8 ps)
return 1 - (-pixels + 1) * ps;
else
BUG();
- return 0;
+ return 0;
}
static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
@@ -1905,6 +1905,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
if (color_mode == OMAP_DSS_COLOR_YUV2 ||
color_mode == OMAP_DSS_COLOR_UYVY)
width = width >> 1;
+ /* fall through */
case OMAP_DSS_ROT_90:
case OMAP_DSS_ROT_270:
*offset1 = 0;
@@ -1927,6 +1928,7 @@ static void calc_vrfb_rotation_offset(u8 rotation, bool mirror,
if (color_mode == OMAP_DSS_COLOR_YUV2 ||
color_mode == OMAP_DSS_COLOR_UYVY)
width = width >> 1;
+ /* fall through */
case OMAP_DSS_ROT_90 + 4:
case OMAP_DSS_ROT_270 + 4:
*offset1 = 0;
diff --git a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
index 3e7887c53d7c..b8b5b4ac0e09 100644
--- a/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/fbdev/omap2/omapfb/omapfb-main.c
@@ -893,6 +893,7 @@ int omapfb_setup_overlay(struct fb_info *fbi, struct omap_overlay *ovl,
/ (var->bits_per_pixel >> 2);
break;
}
+ /* fall through */
default:
screen_width = fix->line_length / (var->bits_per_pixel >> 3);
break;
diff --git a/drivers/video/fbdev/pm2fb.c b/drivers/video/fbdev/pm2fb.c
index bd6c2f5f6095..1dcf02e12af4 100644
--- a/drivers/video/fbdev/pm2fb.c
+++ b/drivers/video/fbdev/pm2fb.c
@@ -233,8 +233,10 @@ static u32 to3264(u32 timing, int bpp, int is64)
switch (bpp) {
case 24:
timing *= 3;
+ /* fall through */
case 8:
timing >>= 1;
+ /* fall through */
case 16:
timing >>= 1;
case 32:
diff --git a/drivers/video/fbdev/pxa3xx-gcu.c b/drivers/video/fbdev/pxa3xx-gcu.c
index 0955622a1227..69cfb337c857 100644
--- a/drivers/video/fbdev/pxa3xx-gcu.c
+++ b/drivers/video/fbdev/pxa3xx-gcu.c
@@ -44,6 +44,7 @@
#include <linux/clk.h>
#include <linux/fs.h>
#include <linux/io.h>
+#include <linux/of.h>
#include "pxa3xx-gcu.h"
@@ -703,11 +704,20 @@ static int pxa3xx_gcu_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_OF
+static const struct of_device_id pxa3xx_gcu_of_match[] = {
+ { .compatible = "marvell,pxa300-gcu", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, pxa3xx_gcu_of_match);
+#endif
+
static struct platform_driver pxa3xx_gcu_driver = {
.probe = pxa3xx_gcu_probe,
.remove = pxa3xx_gcu_remove,
.driver = {
.name = DRV_NAME,
+ .of_match_table = of_match_ptr(pxa3xx_gcu_of_match),
},
};
diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c
index 76722a59f55e..bbed039617a4 100644
--- a/drivers/video/fbdev/pxafb.c
+++ b/drivers/video/fbdev/pxafb.c
@@ -56,6 +56,7 @@
#include <linux/freezer.h>
#include <linux/console.h>
#include <linux/of_graph.h>
+#include <linux/regulator/consumer.h>
#include <video/of_display_timing.h>
#include <video/videomode.h>
@@ -1423,6 +1424,21 @@ static inline void __pxafb_lcd_power(struct pxafb_info *fbi, int on)
if (fbi->lcd_power)
fbi->lcd_power(on, &fbi->fb.var);
+
+ if (fbi->lcd_supply && fbi->lcd_supply_enabled != on) {
+ int ret;
+
+ if (on)
+ ret = regulator_enable(fbi->lcd_supply);
+ else
+ ret = regulator_disable(fbi->lcd_supply);
+
+ if (ret < 0)
+ pr_warn("Unable to %s LCD supply regulator: %d\n",
+ on ? "enable" : "disable", ret);
+ else
+ fbi->lcd_supply_enabled = on;
+ }
}
static void pxafb_enable_controller(struct pxafb_info *fbi)
@@ -1799,19 +1815,17 @@ static struct pxafb_info *pxafb_init_fbinfo(struct device *dev,
void *addr;
/* Alloc the pxafb_info and pseudo_palette in one step */
- fbi = kmalloc(sizeof(struct pxafb_info) + sizeof(u32) * 16, GFP_KERNEL);
+ fbi = devm_kzalloc(dev, sizeof(struct pxafb_info) + sizeof(u32) * 16,
+ GFP_KERNEL);
if (!fbi)
- return NULL;
+ return ERR_PTR(-ENOMEM);
- memset(fbi, 0, sizeof(struct pxafb_info));
fbi->dev = dev;
fbi->inf = inf;
- fbi->clk = clk_get(dev, NULL);
- if (IS_ERR(fbi->clk)) {
- kfree(fbi);
- return NULL;
- }
+ fbi->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(fbi->clk))
+ return ERR_CAST(fbi->clk);
strcpy(fbi->fb.fix.id, PXA_NAME);
@@ -2128,8 +2142,9 @@ static int of_get_pxafb_display(struct device *dev, struct device_node *disp,
return -EINVAL;
ret = -ENOMEM;
- info->modes = kmalloc_array(timings->num_timings,
- sizeof(info->modes[0]), GFP_KERNEL);
+ info->modes = devm_kcalloc(dev, timings->num_timings,
+ sizeof(info->modes[0]),
+ GFP_KERNEL);
if (!info->modes)
goto out;
info->num_modes = timings->num_timings;
@@ -2288,10 +2303,9 @@ static int pxafb_probe(struct platform_device *dev)
}
fbi = pxafb_init_fbinfo(&dev->dev, inf);
- if (!fbi) {
- /* only reason for pxafb_init_fbinfo to fail is kmalloc */
+ if (IS_ERR(fbi)) {
dev_err(&dev->dev, "Failed to initialize framebuffer device\n");
- ret = -ENOMEM;
+ ret = PTR_ERR(fbi);
goto failed;
}
@@ -2301,25 +2315,26 @@ static int pxafb_probe(struct platform_device *dev)
fbi->backlight_power = inf->pxafb_backlight_power;
fbi->lcd_power = inf->pxafb_lcd_power;
+ fbi->lcd_supply = devm_regulator_get_optional(&dev->dev, "lcd");
+ if (IS_ERR(fbi->lcd_supply)) {
+ if (PTR_ERR(fbi->lcd_supply) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+
+ fbi->lcd_supply = NULL;
+ }
+
r = platform_get_resource(dev, IORESOURCE_MEM, 0);
if (r == NULL) {
dev_err(&dev->dev, "no I/O memory resource defined\n");
ret = -ENODEV;
- goto failed_fbi;
- }
-
- r = request_mem_region(r->start, resource_size(r), dev->name);
- if (r == NULL) {
- dev_err(&dev->dev, "failed to request I/O memory\n");
- ret = -EBUSY;
- goto failed_fbi;
+ goto failed;
}
- fbi->mmio_base = ioremap(r->start, resource_size(r));
- if (fbi->mmio_base == NULL) {
- dev_err(&dev->dev, "failed to map I/O memory\n");
+ fbi->mmio_base = devm_ioremap_resource(&dev->dev, r);
+ if (IS_ERR(fbi->mmio_base)) {
+ dev_err(&dev->dev, "failed to get I/O memory\n");
ret = -EBUSY;
- goto failed_free_res;
+ goto failed;
}
fbi->dma_buff_size = PAGE_ALIGN(sizeof(struct pxafb_dma_buff));
@@ -2328,7 +2343,7 @@ static int pxafb_probe(struct platform_device *dev)
if (fbi->dma_buff == NULL) {
dev_err(&dev->dev, "failed to allocate memory for DMA\n");
ret = -ENOMEM;
- goto failed_free_io;
+ goto failed;
}
ret = pxafb_init_video_memory(fbi);
@@ -2345,7 +2360,7 @@ static int pxafb_probe(struct platform_device *dev)
goto failed_free_mem;
}
- ret = request_irq(irq, pxafb_handle_irq, 0, "LCD", fbi);
+ ret = devm_request_irq(&dev->dev, irq, pxafb_handle_irq, 0, "LCD", fbi);
if (ret) {
dev_err(&dev->dev, "request_irq failed: %d\n", ret);
ret = -EBUSY;
@@ -2355,7 +2370,7 @@ static int pxafb_probe(struct platform_device *dev)
ret = pxafb_smart_init(fbi);
if (ret) {
dev_err(&dev->dev, "failed to initialize smartpanel\n");
- goto failed_free_irq;
+ goto failed_free_mem;
}
/*
@@ -2365,13 +2380,13 @@ static int pxafb_probe(struct platform_device *dev)
ret = pxafb_check_var(&fbi->fb.var, &fbi->fb);
if (ret) {
dev_err(&dev->dev, "failed to get suitable mode\n");
- goto failed_free_irq;
+ goto failed_free_mem;
}
ret = pxafb_set_par(&fbi->fb);
if (ret) {
dev_err(&dev->dev, "Failed to set parameters\n");
- goto failed_free_irq;
+ goto failed_free_mem;
}
platform_set_drvdata(dev, fbi);
@@ -2404,20 +2419,11 @@ static int pxafb_probe(struct platform_device *dev)
failed_free_cmap:
if (fbi->fb.cmap.len)
fb_dealloc_cmap(&fbi->fb.cmap);
-failed_free_irq:
- free_irq(irq, fbi);
failed_free_mem:
free_pages_exact(fbi->video_mem, fbi->video_mem_size);
failed_free_dma:
dma_free_coherent(&dev->dev, fbi->dma_buff_size,
fbi->dma_buff, fbi->dma_buff_phys);
-failed_free_io:
- iounmap(fbi->mmio_base);
-failed_free_res:
- release_mem_region(r->start, resource_size(r));
-failed_fbi:
- clk_put(fbi->clk);
- kfree(fbi);
failed:
return ret;
}
@@ -2425,8 +2431,6 @@ failed:
static int pxafb_remove(struct platform_device *dev)
{
struct pxafb_info *fbi = platform_get_drvdata(dev);
- struct resource *r;
- int irq;
struct fb_info *info;
if (!fbi)
@@ -2442,22 +2446,11 @@ static int pxafb_remove(struct platform_device *dev)
if (fbi->fb.cmap.len)
fb_dealloc_cmap(&fbi->fb.cmap);
- irq = platform_get_irq(dev, 0);
- free_irq(irq, fbi);
-
free_pages_exact(fbi->video_mem, fbi->video_mem_size);
dma_free_wc(&dev->dev, fbi->dma_buff_size, fbi->dma_buff,
fbi->dma_buff_phys);
- iounmap(fbi->mmio_base);
-
- r = platform_get_resource(dev, IORESOURCE_MEM, 0);
- release_mem_region(r->start, resource_size(r));
-
- clk_put(fbi->clk);
- kfree(fbi);
-
return 0;
}
diff --git a/drivers/video/fbdev/pxafb.h b/drivers/video/fbdev/pxafb.h
index 5dc414e26fc8..b641289c8a99 100644
--- a/drivers/video/fbdev/pxafb.h
+++ b/drivers/video/fbdev/pxafb.h
@@ -165,6 +165,9 @@ struct pxafb_info {
struct notifier_block freq_policy;
#endif
+ struct regulator *lcd_supply;
+ bool lcd_supply_enabled;
+
void (*lcd_power)(int, struct fb_var_screeninfo *);
void (*backlight_power)(int);
diff --git a/drivers/video/fbdev/simplefb.c b/drivers/video/fbdev/simplefb.c
index a3c44ecf4523..9a9d748b07f2 100644
--- a/drivers/video/fbdev/simplefb.c
+++ b/drivers/video/fbdev/simplefb.c
@@ -27,8 +27,8 @@
#include <linux/platform_data/simplefb.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
-#include <linux/clk-provider.h>
#include <linux/of.h>
+#include <linux/of_clk.h>
#include <linux/of_platform.h>
#include <linux/parser.h>
#include <linux/regulator/consumer.h>
diff --git a/drivers/video/fbdev/tdfxfb.c b/drivers/video/fbdev/tdfxfb.c
index dec1fed9880e..fbbf26b170f7 100644
--- a/drivers/video/fbdev/tdfxfb.c
+++ b/drivers/video/fbdev/tdfxfb.c
@@ -522,6 +522,7 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
case 32:
var->transp.offset = 24;
var->transp.length = 8;
+ /* fall through */
case 24:
var->red.offset = 16;
var->green.offset = 8;
diff --git a/drivers/video/fbdev/tridentfb.c b/drivers/video/fbdev/tridentfb.c
index 284706184b1b..f4b745590600 100644
--- a/drivers/video/fbdev/tridentfb.c
+++ b/drivers/video/fbdev/tridentfb.c
@@ -777,9 +777,6 @@ static int get_nativex(struct tridentfb_par *par)
case 3:
x = 800; y = 600;
break;
- case 4:
- x = 1400; y = 1050;
- break;
case 1:
default:
x = 640; y = 480;
diff --git a/drivers/video/fbdev/udlfb.c b/drivers/video/fbdev/udlfb.c
index f365d4862015..afbd6101c78e 100644
--- a/drivers/video/fbdev/udlfb.c
+++ b/drivers/video/fbdev/udlfb.c
@@ -25,8 +25,8 @@
#include <linux/fb.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
-#include <linux/prefetch.h>
#include <linux/delay.h>
+#include <asm/unaligned.h>
#include <video/udlfb.h>
#include "edid.h"
@@ -72,6 +72,13 @@ static bool fb_defio = 1; /* Detect mmap writes using page faults */
static bool shadow = 1; /* Optionally disable shadow framebuffer */
static int pixel_limit; /* Optionally force a pixel resolution limit */
+struct dlfb_deferred_free {
+ struct list_head list;
+ void *mem;
+};
+
+static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info, u32 new_len);
+
/* dlfb keeps a list of urbs for efficient bulk transfers */
static void dlfb_urb_completion(struct urb *urb);
static struct urb *dlfb_get_urb(struct dlfb_data *dlfb);
@@ -367,9 +374,6 @@ static int dlfb_trim_hline(const u8 *bback, const u8 **bfront, int *width_bytes)
int start = width;
int end = width;
- prefetch((void *) front);
- prefetch((void *) back);
-
for (j = 0; j < width; j++) {
if (back[j] != front[j]) {
start = j;
@@ -423,7 +427,9 @@ static void dlfb_compress_hline(
const uint16_t *const pixel_end,
uint32_t *device_address_ptr,
uint8_t **command_buffer_ptr,
- const uint8_t *const cmd_buffer_end)
+ const uint8_t *const cmd_buffer_end,
+ unsigned long back_buffer_offset,
+ int *ident_ptr)
{
const uint16_t *pixel = *pixel_start_ptr;
uint32_t dev_addr = *device_address_ptr;
@@ -436,7 +442,13 @@ static void dlfb_compress_hline(
const uint16_t *raw_pixel_start = NULL;
const uint16_t *cmd_pixel_start, *cmd_pixel_end = NULL;
- prefetchw((void *) cmd); /* pull in one cache line at least */
+ if (back_buffer_offset &&
+ *pixel == *(u16 *)((u8 *)pixel + back_buffer_offset)) {
+ pixel++;
+ dev_addr += BPP;
+ (*ident_ptr)++;
+ continue;
+ }
*cmd++ = 0xAF;
*cmd++ = 0x6B;
@@ -450,29 +462,39 @@ static void dlfb_compress_hline(
raw_pixels_count_byte = cmd++; /* we'll know this later */
raw_pixel_start = pixel;
- cmd_pixel_end = pixel + min(MAX_CMD_PIXELS + 1,
- min((int)(pixel_end - pixel),
- (int)(cmd_buffer_end - cmd) / BPP));
+ cmd_pixel_end = pixel + min3(MAX_CMD_PIXELS + 1UL,
+ (unsigned long)(pixel_end - pixel),
+ (unsigned long)(cmd_buffer_end - 1 - cmd) / BPP);
- prefetch_range((void *) pixel, (cmd_pixel_end - pixel) * BPP);
+ if (back_buffer_offset) {
+ /* note: the framebuffer may change under us, so we must test for underflow */
+ while (cmd_pixel_end - 1 > pixel &&
+ *(cmd_pixel_end - 1) == *(u16 *)((u8 *)(cmd_pixel_end - 1) + back_buffer_offset))
+ cmd_pixel_end--;
+ }
while (pixel < cmd_pixel_end) {
const uint16_t * const repeating_pixel = pixel;
+ u16 pixel_value = *pixel;
- *cmd++ = *pixel >> 8;
- *cmd++ = *pixel;
+ put_unaligned_be16(pixel_value, cmd);
+ if (back_buffer_offset)
+ *(u16 *)((u8 *)pixel + back_buffer_offset) = pixel_value;
+ cmd += 2;
pixel++;
if (unlikely((pixel < cmd_pixel_end) &&
- (*pixel == *repeating_pixel))) {
+ (*pixel == pixel_value))) {
/* go back and fill in raw pixel count */
*raw_pixels_count_byte = ((repeating_pixel -
raw_pixel_start) + 1) & 0xFF;
- while ((pixel < cmd_pixel_end)
- && (*pixel == *repeating_pixel)) {
+ do {
+ if (back_buffer_offset)
+ *(u16 *)((u8 *)pixel + back_buffer_offset) = pixel_value;
pixel++;
- }
+ } while ((pixel < cmd_pixel_end) &&
+ (*pixel == pixel_value));
/* immediately after raw data is repeat byte */
*cmd++ = ((pixel - repeating_pixel) - 1) & 0xFF;
@@ -486,13 +508,16 @@ static void dlfb_compress_hline(
if (pixel > raw_pixel_start) {
/* finalize last RAW span */
*raw_pixels_count_byte = (pixel-raw_pixel_start) & 0xFF;
+ } else {
+ /* undo unused byte */
+ cmd--;
}
*cmd_pixels_count_byte = (pixel - cmd_pixel_start) & 0xFF;
- dev_addr += (pixel - cmd_pixel_start) * BPP;
+ dev_addr += (u8 *)pixel - (u8 *)cmd_pixel_start;
}
- if (cmd_buffer_end <= MIN_RLX_CMD_BYTES + cmd) {
+ if (cmd_buffer_end - MIN_RLX_CMD_BYTES <= cmd) {
/* Fill leftover bytes with no-ops */
if (cmd_buffer_end > cmd)
memset(cmd, 0xAF, cmd_buffer_end - cmd);
@@ -520,6 +545,7 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
struct urb *urb = *urb_ptr;
u8 *cmd = *urb_buf_ptr;
u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length;
+ unsigned long back_buffer_offset = 0;
line_start = (u8 *) (front + byte_offset);
next_pixel = line_start;
@@ -530,6 +556,8 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
const u8 *back_start = (u8 *) (dlfb->backing_buffer
+ byte_offset);
+ back_buffer_offset = (unsigned long)back_start - (unsigned long)line_start;
+
*ident_ptr += dlfb_trim_hline(back_start, &next_pixel,
&byte_width);
@@ -538,16 +566,14 @@ static int dlfb_render_hline(struct dlfb_data *dlfb, struct urb **urb_ptr,
dev_addr += offset;
back_start += offset;
line_start += offset;
-
- memcpy((char *)back_start, (char *) line_start,
- byte_width);
}
while (next_pixel < line_end) {
dlfb_compress_hline((const uint16_t **) &next_pixel,
(const uint16_t *) line_end, &dev_addr,
- (u8 **) &cmd, (u8 *) cmd_end);
+ (u8 **) &cmd, (u8 *) cmd_end, back_buffer_offset,
+ ident_ptr);
if (cmd >= cmd_end) {
int len = cmd - (u8 *) urb->transfer_buffer;
@@ -610,8 +636,11 @@ static int dlfb_handle_damage(struct dlfb_data *dlfb, int x, int y,
}
if (cmd > (char *) urb->transfer_buffer) {
+ int len;
+ if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
+ *cmd++ = 0xAF;
/* Send partial buffer remaining before exiting */
- int len = cmd - (char *) urb->transfer_buffer;
+ len = cmd - (char *) urb->transfer_buffer;
ret = dlfb_submit_urb(dlfb, urb, len);
bytes_sent += len;
} else
@@ -735,8 +764,11 @@ static void dlfb_dpy_deferred_io(struct fb_info *info,
}
if (cmd > (char *) urb->transfer_buffer) {
+ int len;
+ if (cmd < (char *) urb->transfer_buffer + urb->transfer_buffer_length)
+ *cmd++ = 0xAF;
/* Send partial buffer remaining before exiting */
- int len = cmd - (char *) urb->transfer_buffer;
+ len = cmd - (char *) urb->transfer_buffer;
dlfb_submit_urb(dlfb, urb, len);
bytes_sent += len;
} else
@@ -917,19 +949,17 @@ static void dlfb_free(struct kref *kref)
{
struct dlfb_data *dlfb = container_of(kref, struct dlfb_data, kref);
+ while (!list_empty(&dlfb->deferred_free)) {
+ struct dlfb_deferred_free *d = list_entry(dlfb->deferred_free.next, struct dlfb_deferred_free, list);
+ list_del(&d->list);
+ vfree(d->mem);
+ kfree(d);
+ }
vfree(dlfb->backing_buffer);
kfree(dlfb->edid);
kfree(dlfb);
}
-static void dlfb_release_urb_work(struct work_struct *work)
-{
- struct urb_node *unode = container_of(work, struct urb_node,
- release_urb_work.work);
-
- up(&unode->dlfb->urbs.limit_sem);
-}
-
static void dlfb_free_framebuffer(struct dlfb_data *dlfb)
{
struct fb_info *info = dlfb->info;
@@ -1018,10 +1048,6 @@ static int dlfb_ops_check_var(struct fb_var_screeninfo *var,
struct fb_videomode mode;
struct dlfb_data *dlfb = info->par;
- /* TODO: support dynamically changing framebuffer size */
- if ((var->xres * var->yres * 2) > info->fix.smem_len)
- return -EINVAL;
-
/* set device-specific elements of var unrelated to mode */
dlfb_var_color_format(var);
@@ -1039,22 +1065,42 @@ static int dlfb_ops_set_par(struct fb_info *info)
int result;
u16 *pix_framebuffer;
int i;
+ struct fb_var_screeninfo fvs;
+ u32 line_length = info->var.xres * (info->var.bits_per_pixel / 8);
+
+ /* clear the activate field because it causes spurious miscompares */
+ fvs = info->var;
+ fvs.activate = 0;
+ fvs.vmode &= ~FB_VMODE_SMOOTH_XPAN;
+
+ if (!memcmp(&dlfb->current_mode, &fvs, sizeof(struct fb_var_screeninfo)))
+ return 0;
+
+ result = dlfb_realloc_framebuffer(dlfb, info, info->var.yres * line_length);
+ if (result)
+ return result;
result = dlfb_set_video_mode(dlfb, &info->var);
- if ((result == 0) && (dlfb->fb_count == 0)) {
+ if (result)
+ return result;
+
+ dlfb->current_mode = fvs;
+ info->fix.line_length = line_length;
+
+ if (dlfb->fb_count == 0) {
/* paint greenscreen */
pix_framebuffer = (u16 *) info->screen_base;
for (i = 0; i < info->fix.smem_len / 2; i++)
pix_framebuffer[i] = 0x37e6;
-
- dlfb_handle_damage(dlfb, 0, 0, info->var.xres, info->var.yres,
- info->screen_base);
}
- return result;
+ dlfb_handle_damage(dlfb, 0, 0, info->var.xres, info->var.yres,
+ info->screen_base);
+
+ return 0;
}
/* To fonzi the jukebox (e.g. make blanking changes take effect) */
@@ -1129,21 +1175,29 @@ static struct fb_ops dlfb_ops = {
};
+static void dlfb_deferred_vfree(struct dlfb_data *dlfb, void *mem)
+{
+ struct dlfb_deferred_free *d = kmalloc(sizeof(struct dlfb_deferred_free), GFP_KERNEL);
+ if (!d)
+ return;
+ d->mem = mem;
+ list_add(&d->list, &dlfb->deferred_free);
+}
+
/*
* Assumes &info->lock held by caller
* Assumes no active clients have framebuffer open
*/
-static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info)
+static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info, u32 new_len)
{
- int old_len = info->fix.smem_len;
- int new_len;
- unsigned char *old_fb = info->screen_base;
+ u32 old_len = info->fix.smem_len;
+ const void *old_fb = (const void __force *)info->screen_base;
unsigned char *new_fb;
unsigned char *new_back = NULL;
- new_len = info->fix.line_length * info->var.yres;
+ new_len = PAGE_ALIGN(new_len);
- if (PAGE_ALIGN(new_len) > old_len) {
+ if (new_len > old_len) {
/*
* Alloc system memory for virtual framebuffer
*/
@@ -1152,14 +1206,15 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
dev_err(info->dev, "Virtual framebuffer alloc failed\n");
return -ENOMEM;
}
+ memset(new_fb, 0xff, new_len);
if (info->screen_base) {
memcpy(new_fb, old_fb, old_len);
- vfree(info->screen_base);
+ dlfb_deferred_vfree(dlfb, (void __force *)info->screen_base);
}
- info->screen_base = new_fb;
- info->fix.smem_len = PAGE_ALIGN(new_len);
+ info->screen_base = (char __iomem *)new_fb;
+ info->fix.smem_len = new_len;
info->fix.smem_start = (unsigned long) new_fb;
info->flags = udlfb_info_flags;
@@ -1175,7 +1230,7 @@ static int dlfb_realloc_framebuffer(struct dlfb_data *dlfb, struct fb_info *info
dev_info(info->dev,
"No shadow/backing buffer allocated\n");
else {
- vfree(dlfb->backing_buffer);
+ dlfb_deferred_vfree(dlfb, dlfb->backing_buffer);
dlfb->backing_buffer = new_back;
}
}
@@ -1327,11 +1382,6 @@ static int dlfb_setup_modes(struct dlfb_data *dlfb,
* with mode size info, we can now alloc our framebuffer.
*/
memcpy(&info->fix, &dlfb_fix, sizeof(dlfb_fix));
- info->fix.line_length = info->var.xres *
- (info->var.bits_per_pixel / 8);
-
- result = dlfb_realloc_framebuffer(dlfb, info);
-
} else
result = -EINVAL;
@@ -1419,7 +1469,10 @@ static ssize_t edid_store(
if (!dlfb->edid || memcmp(src, dlfb->edid, src_size))
return -EINVAL;
- dlfb_ops_set_par(fb_info);
+ ret = dlfb_ops_set_par(fb_info);
+ if (ret)
+ return ret;
+
return src_size;
}
@@ -1579,6 +1632,7 @@ static int dlfb_usb_probe(struct usb_interface *intf,
}
kref_init(&dlfb->kref); /* matching kref_put in usb .disconnect fn */
+ INIT_LIST_HEAD(&dlfb->deferred_free);
dlfb->udev = usbdev;
usb_set_intfdata(intf, dlfb);
@@ -1649,7 +1703,8 @@ static void dlfb_init_framebuffer_work(struct work_struct *work)
dlfb->info = info;
info->par = dlfb;
info->pseudo_palette = dlfb->pseudo_palette;
- info->fbops = &dlfb_ops;
+ dlfb->ops = dlfb_ops;
+ info->fbops = &dlfb->ops;
retval = fb_alloc_cmap(&info->cmap, 256, 0);
if (retval < 0) {
@@ -1675,7 +1730,9 @@ static void dlfb_init_framebuffer_work(struct work_struct *work)
dlfb_select_std_channel(dlfb);
dlfb_ops_check_var(&info->var, info);
- dlfb_ops_set_par(info);
+ retval = dlfb_ops_set_par(info);
+ if (retval)
+ goto error;
retval = register_framebuffer(info);
if (retval < 0) {
@@ -1789,14 +1846,7 @@ static void dlfb_urb_completion(struct urb *urb)
dlfb->urbs.available++;
spin_unlock_irqrestore(&dlfb->urbs.lock, flags);
- /*
- * When using fb_defio, we deadlock if up() is called
- * while another is waiting. So queue to another process.
- */
- if (fb_defio)
- schedule_delayed_work(&unode->release_urb_work, 0);
- else
- up(&dlfb->urbs.limit_sem);
+ up(&dlfb->urbs.limit_sem);
}
static void dlfb_free_urb_list(struct dlfb_data *dlfb)
@@ -1805,23 +1855,17 @@ static void dlfb_free_urb_list(struct dlfb_data *dlfb)
struct list_head *node;
struct urb_node *unode;
struct urb *urb;
- int ret;
- unsigned long flags;
/* keep waiting and freeing, until we've got 'em all */
while (count--) {
+ down(&dlfb->urbs.limit_sem);
- /* Getting interrupted means a leak, but ok at disconnect */
- ret = down_interruptible(&dlfb->urbs.limit_sem);
- if (ret)
- break;
-
- spin_lock_irqsave(&dlfb->urbs.lock, flags);
+ spin_lock_irq(&dlfb->urbs.lock);
node = dlfb->urbs.list.next; /* have reserved one with sem */
list_del_init(node);
- spin_unlock_irqrestore(&dlfb->urbs.lock, flags);
+ spin_unlock_irq(&dlfb->urbs.lock);
unode = list_entry(node, struct urb_node, entry);
urb = unode->urb;
@@ -1838,25 +1882,27 @@ static void dlfb_free_urb_list(struct dlfb_data *dlfb)
static int dlfb_alloc_urb_list(struct dlfb_data *dlfb, int count, size_t size)
{
- int i = 0;
struct urb *urb;
struct urb_node *unode;
char *buf;
+ size_t wanted_size = count * size;
spin_lock_init(&dlfb->urbs.lock);
+retry:
dlfb->urbs.size = size;
INIT_LIST_HEAD(&dlfb->urbs.list);
- while (i < count) {
+ sema_init(&dlfb->urbs.limit_sem, 0);
+ dlfb->urbs.count = 0;
+ dlfb->urbs.available = 0;
+
+ while (dlfb->urbs.count * size < wanted_size) {
unode = kzalloc(sizeof(*unode), GFP_KERNEL);
if (!unode)
break;
unode->dlfb = dlfb;
- INIT_DELAYED_WORK(&unode->release_urb_work,
- dlfb_release_urb_work);
-
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
kfree(unode);
@@ -1864,11 +1910,16 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dlfb, int count, size_t size)
}
unode->urb = urb;
- buf = usb_alloc_coherent(dlfb->udev, MAX_TRANSFER, GFP_KERNEL,
+ buf = usb_alloc_coherent(dlfb->udev, size, GFP_KERNEL,
&urb->transfer_dma);
if (!buf) {
kfree(unode);
usb_free_urb(urb);
+ if (size > PAGE_SIZE) {
+ size /= 2;
+ dlfb_free_urb_list(dlfb);
+ goto retry;
+ }
break;
}
@@ -1879,14 +1930,12 @@ static int dlfb_alloc_urb_list(struct dlfb_data *dlfb, int count, size_t size)
list_add_tail(&unode->entry, &dlfb->urbs.list);
- i++;
+ up(&dlfb->urbs.limit_sem);
+ dlfb->urbs.count++;
+ dlfb->urbs.available++;
}
- sema_init(&dlfb->urbs.limit_sem, i);
- dlfb->urbs.count = i;
- dlfb->urbs.available = i;
-
- return i;
+ return dlfb->urbs.count;
}
static struct urb *dlfb_get_urb(struct dlfb_data *dlfb)
@@ -1894,7 +1943,6 @@ static struct urb *dlfb_get_urb(struct dlfb_data *dlfb)
int ret;
struct list_head *entry;
struct urb_node *unode;
- unsigned long flags;
/* Wait for an in-flight buffer to complete and get re-queued */
ret = down_timeout(&dlfb->urbs.limit_sem, GET_URB_TIMEOUT);
@@ -1906,14 +1954,14 @@ static struct urb *dlfb_get_urb(struct dlfb_data *dlfb)
return NULL;
}
- spin_lock_irqsave(&dlfb->urbs.lock, flags);
+ spin_lock_irq(&dlfb->urbs.lock);
BUG_ON(list_empty(&dlfb->urbs.list)); /* reserved one with limit_sem */
entry = dlfb->urbs.list.next;
list_del_init(entry);
dlfb->urbs.available--;
- spin_unlock_irqrestore(&dlfb->urbs.lock, flags);
+ spin_unlock_irq(&dlfb->urbs.lock);
unode = list_entry(entry, struct urb_node, entry);
return unode->urb;
diff --git a/drivers/video/fbdev/via/lcd.c b/drivers/video/fbdev/via/lcd.c
index 5d21ff436ec8..b9305d73a1e5 100644
--- a/drivers/video/fbdev/via/lcd.c
+++ b/drivers/video/fbdev/via/lcd.c
@@ -758,6 +758,7 @@ static void set_lcd_output_path(int set_iga, int output_interface)
viaparinfo->chip_info->gfx_chip_name))
viafb_write_reg_mask(CR97, VIACR, 0x84,
BIT7 + BIT2 + BIT1 + BIT0);
+ /* fall through */
case INTERFACE_DVP0:
case INTERFACE_DVP1:
case INTERFACE_DFP_HIGH:
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
index d2f785068ef4..7bb7e90b8f00 100644
--- a/drivers/video/fbdev/via/viafbdev.c
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -19,6 +19,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/compiler.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -1468,7 +1469,7 @@ static const struct file_operations viafb_vt1636_proc_fops = {
#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
+static int __maybe_unused viafb_sup_odev_proc_show(struct seq_file *m, void *v)
{
via_odev_to_seq(m, supported_odev_map[
viaparinfo->shared->chip_info.gfx_chip_name]);
diff --git a/drivers/xen/mcelog.c b/drivers/xen/mcelog.c
index 262835ace35d..b8bf61abb65b 100644
--- a/drivers/xen/mcelog.c
+++ b/drivers/xen/mcelog.c
@@ -288,7 +288,6 @@ static int mc_queue_handle(uint32_t flags)
int ret = 0;
mc_op.cmd = XEN_MC_fetch;
- mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
set_xen_guest_handle(mc_op.u.mc_fetch.data, &g_mi);
do {
mc_op.u.mc_fetch.flags = flags;
@@ -358,7 +357,6 @@ static int bind_virq_for_mce(void)
/* Fetch physical CPU Numbers */
mc_op.cmd = XEN_MC_physcpuinfo;
- mc_op.interface_version = XEN_MCA_INTERFACE_VERSION;
set_xen_guest_handle(mc_op.u.mc_physcpuinfo.info, g_physinfo);
ret = HYPERVISOR_mca(&mc_op);
if (ret) {
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c
index b29f4e40851f..fbb9137c7d02 100644
--- a/drivers/xen/xen-acpi-processor.c
+++ b/drivers/xen/xen-acpi-processor.c
@@ -362,6 +362,12 @@ read_acpi_id(acpi_handle handle, u32 lvl, void *context, void **rv)
default:
return AE_OK;
}
+ if (invalid_phys_cpuid(acpi_get_phys_id(handle,
+ acpi_type == ACPI_TYPE_DEVICE,
+ acpi_id))) {
+ pr_debug("CPU with ACPI ID %u is unavailable\n", acpi_id);
+ return AE_OK;
+ }
/* There are more ACPI Processor objects than in x2APIC or MADT.
* This can happen with incorrect ACPI SSDT declerations. */
if (acpi_id >= nr_acpi_bits) {