aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/agp/intel-agp.c16
-rw-r--r--drivers/char/agp/intel-agp.h3
-rw-r--r--drivers/char/agp/intel-gtt.c91
-rw-r--r--drivers/char/bsr.c6
-rw-r--r--drivers/char/hw_random/Kconfig26
-rw-r--r--drivers/char/hw_random/Makefile2
-rw-r--r--drivers/char/hw_random/bcm63xx-rng.c175
-rw-r--r--drivers/char/hw_random/exynos-rng.c182
-rw-r--r--drivers/char/hw_random/mxc-rnga.c21
-rw-r--r--drivers/char/hw_random/omap-rng.c13
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c16
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c13
-rw-r--r--drivers/char/mem.c11
-rw-r--r--drivers/char/sonypi.c13
-rw-r--r--drivers/char/tpm/tpm.c29
-rw-r--r--drivers/char/tpm/tpm.h2
-rw-r--r--drivers/char/tpm/tpm_atmel.c12
-rw-r--r--drivers/char/tpm/tpm_infineon.c6
-rw-r--r--drivers/char/tpm/tpm_nsc.c13
-rw-r--r--drivers/char/tpm/tpm_tis.c18
20 files changed, 528 insertions, 140 deletions
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 0a4185279417..b130df0a1958 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -12,6 +12,7 @@
#include <asm/smp.h>
#include "agp.h"
#include "intel-agp.h"
+#include <drm/intel-gtt.h>
int intel_agp_enabled;
EXPORT_SYMBOL(intel_agp_enabled);
@@ -747,7 +748,7 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
bridge->capndx = cap_ptr;
- if (intel_gmch_probe(pdev, bridge))
+ if (intel_gmch_probe(pdev, NULL, bridge))
goto found_gmch;
for (i = 0; intel_agp_chipsets[i].name != NULL; i++) {
@@ -824,7 +825,7 @@ static void __devexit agp_intel_remove(struct pci_dev *pdev)
agp_remove_bridge(bridge);
- intel_gmch_remove(pdev);
+ intel_gmch_remove();
agp_put_bridge(bridge);
}
@@ -902,17 +903,6 @@ static struct pci_device_id agp_intel_pci_table[] = {
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB),
ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB),
- ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB),
- ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB),
- ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB),
- ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB),
- ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB),
- ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB),
- ID(PCI_DEVICE_ID_INTEL_VALLEYVIEW_HB),
- ID(PCI_DEVICE_ID_INTEL_HASWELL_HB),
- ID(PCI_DEVICE_ID_INTEL_HASWELL_M_HB),
- ID(PCI_DEVICE_ID_INTEL_HASWELL_S_HB),
- ID(PCI_DEVICE_ID_INTEL_HASWELL_E_HB),
{ }
};
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h
index 8e2d9140f300..57226424690c 100644
--- a/drivers/char/agp/intel-agp.h
+++ b/drivers/char/agp/intel-agp.h
@@ -251,7 +251,4 @@
#define PCI_DEVICE_ID_INTEL_HASWELL_SDV 0x0c16 /* SDV */
#define PCI_DEVICE_ID_INTEL_HASWELL_E_HB 0x0c04
-int intel_gmch_probe(struct pci_dev *pdev,
- struct agp_bridge_data *bridge);
-void intel_gmch_remove(struct pci_dev *pdev);
#endif
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c
index 1237e7575c3f..9ed92ef5829b 100644
--- a/drivers/char/agp/intel-gtt.c
+++ b/drivers/char/agp/intel-gtt.c
@@ -66,7 +66,6 @@ static struct _intel_private {
struct pci_dev *bridge_dev;
u8 __iomem *registers;
phys_addr_t gtt_bus_addr;
- phys_addr_t gma_bus_addr;
u32 PGETBL_save;
u32 __iomem *gtt; /* I915G */
bool clear_fake_agp; /* on first access via agp, fill with scratch */
@@ -76,6 +75,7 @@ static struct _intel_private {
struct resource ifp_resource;
int resource_valid;
struct page *scratch_page;
+ int refcount;
} intel_private;
#define INTEL_GTT_GEN intel_private.driver->gen
@@ -648,6 +648,7 @@ static void intel_gtt_cleanup(void)
static int intel_gtt_init(void)
{
+ u32 gma_addr;
u32 gtt_map_size;
int ret;
@@ -694,6 +695,15 @@ static int intel_gtt_init(void)
return ret;
}
+ if (INTEL_GTT_GEN <= 2)
+ pci_read_config_dword(intel_private.pcidev, I810_GMADDR,
+ &gma_addr);
+ else
+ pci_read_config_dword(intel_private.pcidev, I915_GMADDR,
+ &gma_addr);
+
+ intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
+
return 0;
}
@@ -767,20 +777,10 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry,
writel(addr | pte_flags, intel_private.gtt + entry);
}
-static bool intel_enable_gtt(void)
+bool intel_enable_gtt(void)
{
- u32 gma_addr;
u8 __iomem *reg;
- if (INTEL_GTT_GEN <= 2)
- pci_read_config_dword(intel_private.pcidev, I810_GMADDR,
- &gma_addr);
- else
- pci_read_config_dword(intel_private.pcidev, I915_GMADDR,
- &gma_addr);
-
- intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK);
-
if (INTEL_GTT_GEN >= 6)
return true;
@@ -823,6 +823,7 @@ static bool intel_enable_gtt(void)
return true;
}
+EXPORT_SYMBOL(intel_enable_gtt);
static int i830_setup(void)
{
@@ -860,7 +861,7 @@ static int intel_fake_agp_configure(void)
return -EIO;
intel_private.clear_fake_agp = true;
- agp_bridge->gart_bus_addr = intel_private.gma_bus_addr;
+ agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr;
return 0;
}
@@ -1182,9 +1183,17 @@ static void gen6_write_entry(dma_addr_t addr, unsigned int entry,
static void valleyview_write_entry(dma_addr_t addr, unsigned int entry,
unsigned int flags)
{
+ unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT;
+ unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT;
u32 pte_flags;
- pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+ if (type_mask == AGP_USER_MEMORY)
+ pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID;
+ else {
+ pte_flags = GEN6_PTE_LLC | I810_PTE_VALID;
+ if (gfdt)
+ pte_flags |= GEN6_PTE_GFDT;
+ }
/* gen6 has bit11-4 for physical addr bit39-32 */
addr |= (addr >> 28) & 0xff0;
@@ -1244,6 +1253,7 @@ static int i9xx_setup(void)
switch (INTEL_GTT_GEN) {
case 5:
case 6:
+ case 7:
gtt_offset = MB(2);
break;
case 4:
@@ -1379,7 +1389,6 @@ static const struct intel_gtt_driver valleyview_gtt_driver = {
.write_entry = valleyview_write_entry,
.dma_mask_size = 40,
.check_flags = gen6_check_flags,
- .chipset_flush = i9xx_chipset_flush,
};
/* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of
@@ -1523,14 +1532,32 @@ static int find_gmch(u16 device)
return 1;
}
-int intel_gmch_probe(struct pci_dev *pdev,
- struct agp_bridge_data *bridge)
+int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev,
+ struct agp_bridge_data *bridge)
{
int i, mask;
- intel_private.driver = NULL;
+
+ /*
+ * Can be called from the fake agp driver but also directly from
+ * drm/i915.ko. Hence we need to check whether everything is set up
+ * already.
+ */
+ if (intel_private.driver) {
+ intel_private.refcount++;
+ return 1;
+ }
for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) {
- if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
+ if (gpu_pdev) {
+ if (gpu_pdev->device ==
+ intel_gtt_chipsets[i].gmch_chip_id) {
+ intel_private.pcidev = pci_dev_get(gpu_pdev);
+ intel_private.driver =
+ intel_gtt_chipsets[i].gtt_driver;
+
+ break;
+ }
+ } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) {
intel_private.driver =
intel_gtt_chipsets[i].gtt_driver;
break;
@@ -1540,13 +1567,17 @@ int intel_gmch_probe(struct pci_dev *pdev,
if (!intel_private.driver)
return 0;
- bridge->driver = &intel_fake_agp_driver;
- bridge->dev_private_data = &intel_private;
- bridge->dev = pdev;
+ intel_private.refcount++;
+
+ if (bridge) {
+ bridge->driver = &intel_fake_agp_driver;
+ bridge->dev_private_data = &intel_private;
+ bridge->dev = bridge_pdev;
+ }
- intel_private.bridge_dev = pci_dev_get(pdev);
+ intel_private.bridge_dev = pci_dev_get(bridge_pdev);
- dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
+ dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name);
mask = intel_private.driver->dma_mask_size;
if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask)))
@@ -1556,11 +1587,11 @@ int intel_gmch_probe(struct pci_dev *pdev,
pci_set_consistent_dma_mask(intel_private.pcidev,
DMA_BIT_MASK(mask));
- /*if (bridge->driver == &intel_810_driver)
- return 1;*/
+ if (intel_gtt_init() != 0) {
+ intel_gmch_remove();
- if (intel_gtt_init() != 0)
return 0;
+ }
return 1;
}
@@ -1579,12 +1610,16 @@ void intel_gtt_chipset_flush(void)
}
EXPORT_SYMBOL(intel_gtt_chipset_flush);
-void intel_gmch_remove(struct pci_dev *pdev)
+void intel_gmch_remove(void)
{
+ if (--intel_private.refcount)
+ return;
+
if (intel_private.pcidev)
pci_dev_put(intel_private.pcidev);
if (intel_private.bridge_dev)
pci_dev_put(intel_private.bridge_dev);
+ intel_private.driver = NULL;
}
EXPORT_SYMBOL(intel_gmch_remove);
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c
index 0c688232aab3..97467053a01b 100644
--- a/drivers/char/bsr.c
+++ b/drivers/char/bsr.c
@@ -297,7 +297,6 @@ static int __init bsr_init(void)
struct device_node *np;
dev_t bsr_dev;
int ret = -ENODEV;
- int result;
np = of_find_compatible_node(NULL, NULL, "ibm,bsr");
if (!np)
@@ -306,13 +305,14 @@ static int __init bsr_init(void)
bsr_class = class_create(THIS_MODULE, "bsr");
if (IS_ERR(bsr_class)) {
printk(KERN_ERR "class_create() failed for bsr_class\n");
+ ret = PTR_ERR(bsr_class);
goto out_err_1;
}
bsr_class->dev_attrs = bsr_dev_attrs;
- result = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
+ ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr");
bsr_major = MAJOR(bsr_dev);
- if (result < 0) {
+ if (ret < 0) {
printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n");
goto out_err_2;
}
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index f45dad39a18b..7c0d391996b5 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -73,6 +73,20 @@ config HW_RANDOM_ATMEL
If unsure, say Y.
+config HW_RANDOM_BCM63XX
+ tristate "Broadcom BCM63xx Random Number Generator support"
+ depends on HW_RANDOM && BCM63XX
+ default HW_RANDOM
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on the Broadcom BCM63xx SoCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bcm63xx-rng
+
+ If unusure, say Y.
+
+
config HW_RANDOM_GEODE
tristate "AMD Geode HW Random Number Generator support"
depends on HW_RANDOM && X86_32 && PCI
@@ -263,3 +277,15 @@ config HW_RANDOM_PSERIES
module will be called pseries-rng.
If unsure, say Y.
+
+config HW_RANDOM_EXYNOS
+ tristate "EXYNOS HW random number generator support"
+ depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK
+ ---help---
+ This driver provides kernel-side support for the Random Number
+ Generator hardware found on EXYNOS SOCs.
+
+ To compile this driver as a module, choose M here: the
+ module will be called exynos-rng.
+
+ If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index d901dfa30321..39a757ca15b6 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
+obj-$(CONFIG_HW_RANDOM_BCM63XX) += bcm63xx-rng.o
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o
n2-rng-y := n2-drv.o n2-asm.o
@@ -23,3 +24,4 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
+obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o
diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c
new file mode 100644
index 000000000000..aec6a4277caa
--- /dev/null
+++ b/drivers/char/hw_random/bcm63xx-rng.c
@@ -0,0 +1,175 @@
+/*
+ * Broadcom BCM63xx Random Number Generator support
+ *
+ * Copyright (C) 2011, Florian Fainelli <florian@openwrt.org>
+ * Copyright (C) 2009, Broadcom Corporation
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/hw_random.h>
+
+#include <bcm63xx_io.h>
+#include <bcm63xx_regs.h>
+
+struct bcm63xx_rng_priv {
+ struct clk *clk;
+ void __iomem *regs;
+};
+
+#define to_rng_priv(rng) ((struct bcm63xx_rng_priv *)rng->priv)
+
+static int bcm63xx_rng_init(struct hwrng *rng)
+{
+ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
+ u32 val;
+
+ val = bcm_readl(priv->regs + RNG_CTRL);
+ val |= RNG_EN;
+ bcm_writel(val, priv->regs + RNG_CTRL);
+
+ return 0;
+}
+
+static void bcm63xx_rng_cleanup(struct hwrng *rng)
+{
+ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
+ u32 val;
+
+ val = bcm_readl(priv->regs + RNG_CTRL);
+ val &= ~RNG_EN;
+ bcm_writel(val, priv->regs + RNG_CTRL);
+}
+
+static int bcm63xx_rng_data_present(struct hwrng *rng, int wait)
+{
+ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
+
+ return bcm_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK;
+}
+
+static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data)
+{
+ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
+
+ *data = bcm_readl(priv->regs + RNG_DATA);
+
+ return 4;
+}
+
+static int __devinit bcm63xx_rng_probe(struct platform_device *pdev)
+{
+ struct resource *r;
+ struct clk *clk;
+ int ret;
+ struct bcm63xx_rng_priv *priv;
+ struct hwrng *rng;
+
+ r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!r) {
+ dev_err(&pdev->dev, "no iomem resource\n");
+ ret = -ENXIO;
+ goto out;
+ }
+
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "no memory for private structure\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ rng = kzalloc(sizeof(*rng), GFP_KERNEL);
+ if (!rng) {
+ dev_err(&pdev->dev, "no memory for rng structure\n");
+ ret = -ENOMEM;
+ goto out_free_priv;
+ }
+
+ platform_set_drvdata(pdev, rng);
+ rng->priv = (unsigned long)priv;
+ rng->name = pdev->name;
+ rng->init = bcm63xx_rng_init;
+ rng->cleanup = bcm63xx_rng_cleanup;
+ rng->data_present = bcm63xx_rng_data_present;
+ rng->data_read = bcm63xx_rng_data_read;
+
+ clk = clk_get(&pdev->dev, "ipsec");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "no clock for device\n");
+ ret = PTR_ERR(clk);
+ goto out_free_rng;
+ }
+
+ priv->clk = clk;
+
+ if (!devm_request_mem_region(&pdev->dev, r->start,
+ resource_size(r), pdev->name)) {
+ dev_err(&pdev->dev, "request mem failed");
+ ret = -ENOMEM;
+ goto out_free_rng;
+ }
+
+ priv->regs = devm_ioremap_nocache(&pdev->dev, r->start,
+ resource_size(r));
+ if (!priv->regs) {
+ dev_err(&pdev->dev, "ioremap failed");
+ ret = -ENOMEM;
+ goto out_free_rng;
+ }
+
+ clk_enable(clk);
+
+ ret = hwrng_register(rng);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register rng device\n");
+ goto out_clk_disable;
+ }
+
+ dev_info(&pdev->dev, "registered RNG driver\n");
+
+ return 0;
+
+out_clk_disable:
+ clk_disable(clk);
+out_free_rng:
+ platform_set_drvdata(pdev, NULL);
+ kfree(rng);
+out_free_priv:
+ kfree(priv);
+out:
+ return ret;
+}
+
+static int __devexit bcm63xx_rng_remove(struct platform_device *pdev)
+{
+ struct hwrng *rng = platform_get_drvdata(pdev);
+ struct bcm63xx_rng_priv *priv = to_rng_priv(rng);
+
+ hwrng_unregister(rng);
+ clk_disable(priv->clk);
+ kfree(priv);
+ kfree(rng);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver bcm63xx_rng_driver = {
+ .probe = bcm63xx_rng_probe,
+ .remove = __devexit_p(bcm63xx_rng_remove),
+ .driver = {
+ .name = "bcm63xx-rng",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(bcm63xx_rng_driver);
+
+MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>");
+MODULE_DESCRIPTION("Broadcom BCM63xx RNG driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c
new file mode 100644
index 000000000000..232ba9ce579c
--- /dev/null
+++ b/drivers/char/hw_random/exynos-rng.c
@@ -0,0 +1,182 @@
+/*
+ * exynos-rng.c - Random Number Generator driver for the exynos
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Jonghwa Lee <jonghwa3.lee@smasung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/hw_random.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/pm_runtime.h>
+#include <linux/err.h>
+
+#define EXYNOS_PRNG_STATUS_OFFSET 0x10
+#define EXYNOS_PRNG_SEED_OFFSET 0x140
+#define EXYNOS_PRNG_OUT1_OFFSET 0x160
+#define SEED_SETTING_DONE BIT(1)
+#define PRNG_START 0x18
+#define PRNG_DONE BIT(5)
+#define EXYNOS_AUTOSUSPEND_DELAY 100
+
+struct exynos_rng {
+ struct device *dev;
+ struct hwrng rng;
+ void __iomem *mem;
+ struct clk *clk;
+};
+
+static u32 exynos_rng_readl(struct exynos_rng *rng, u32 offset)
+{
+ return __raw_readl(rng->mem + offset);
+}
+
+static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset)
+{
+ __raw_writel(val, rng->mem + offset);
+}
+
+static int exynos_init(struct hwrng *rng)
+{
+ struct exynos_rng *exynos_rng = container_of(rng,
+ struct exynos_rng, rng);
+ int i;
+ int ret = 0;
+
+ pm_runtime_get_sync(exynos_rng->dev);
+
+ for (i = 0 ; i < 5 ; i++)
+ exynos_rng_writel(exynos_rng, jiffies,
+ EXYNOS_PRNG_SEED_OFFSET + 4*i);
+
+ if (!(exynos_rng_readl(exynos_rng, EXYNOS_PRNG_STATUS_OFFSET)
+ & SEED_SETTING_DONE))
+ ret = -EIO;
+
+ pm_runtime_put_noidle(exynos_rng->dev);
+
+ return ret;
+}
+
+static int exynos_read(struct hwrng *rng, void *buf,
+ size_t max, bool wait)
+{
+ struct exynos_rng *exynos_rng = container_of(rng,
+ struct exynos_rng, rng);
+ u32 *data = buf;
+
+ pm_runtime_get_sync(exynos_rng->dev);
+
+ exynos_rng_writel(exynos_rng, PRNG_START, 0);
+
+ while (!(exynos_rng_readl(exynos_rng,
+ EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE))
+ cpu_relax();
+
+ exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET);
+
+ *data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET);
+
+ pm_runtime_mark_last_busy(exynos_rng->dev);
+ pm_runtime_autosuspend(exynos_rng->dev);
+
+ return 4;
+}
+
+static int __devinit exynos_rng_probe(struct platform_device *pdev)
+{
+ struct exynos_rng *exynos_rng;
+
+ exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng),
+ GFP_KERNEL);
+ if (!exynos_rng)
+ return -ENOMEM;
+
+ exynos_rng->dev = &pdev->dev;
+ exynos_rng->rng.name = "exynos";
+ exynos_rng->rng.init = exynos_init;
+ exynos_rng->rng.read = exynos_read;
+ exynos_rng->clk = devm_clk_get(&pdev->dev, "secss");
+ if (IS_ERR(exynos_rng->clk)) {
+ dev_err(&pdev->dev, "Couldn't get clock.\n");
+ return -ENOENT;
+ }
+
+ exynos_rng->mem = devm_request_and_ioremap(&pdev->dev,
+ platform_get_resource(pdev, IORESOURCE_MEM, 0));
+ if (!exynos_rng->mem)
+ return -EBUSY;
+
+ platform_set_drvdata(pdev, exynos_rng);
+
+ pm_runtime_set_autosuspend_delay(&pdev->dev, EXYNOS_AUTOSUSPEND_DELAY);
+ pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(&pdev->dev);
+
+ return hwrng_register(&exynos_rng->rng);
+}
+
+static int __devexit exynos_rng_remove(struct platform_device *pdev)
+{
+ struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
+
+ hwrng_unregister(&exynos_rng->rng);
+
+ return 0;
+}
+
+static int exynos_rng_runtime_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(exynos_rng->clk);
+
+ return 0;
+}
+
+static int exynos_rng_runtime_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct exynos_rng *exynos_rng = platform_get_drvdata(pdev);
+
+ return clk_prepare_enable(exynos_rng->clk);
+}
+
+
+UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend,
+ exynos_rng_runtime_resume, NULL);
+
+static struct platform_driver exynos_rng_driver = {
+ .driver = {
+ .name = "exynos-rng",
+ .owner = THIS_MODULE,
+ .pm = &exynos_rng_pm_ops,
+ },
+ .probe = exynos_rng_probe,
+ .remove = __devexit_p(exynos_rng_remove),
+};
+
+module_platform_driver(exynos_rng_driver);
+
+MODULE_DESCRIPTION("EXYNOS 4 H/W Random Number Generator driver");
+MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index 187c6be80f43..85074de5042e 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -24,6 +24,7 @@
#include <linux/ioport.h>
#include <linux/platform_device.h>
#include <linux/hw_random.h>
+#include <linux/delay.h>
#include <linux/io.h>
/* RNGA Registers */
@@ -60,16 +61,20 @@
static struct platform_device *rng_dev;
-static int mxc_rnga_data_present(struct hwrng *rng)
+static int mxc_rnga_data_present(struct hwrng *rng, int wait)
{
- int level;
void __iomem *rng_base = (void __iomem *)rng->priv;
-
- /* how many random numbers is in FIFO? [0-16] */
- level = ((__raw_readl(rng_base + RNGA_STATUS) &
- RNGA_STATUS_LEVEL_MASK) >> 8);
-
- return level > 0 ? 1 : 0;
+ int i;
+
+ for (i = 0; i < 20; i++) {
+ /* how many random numbers are in FIFO? [0-16] */
+ int level = (__raw_readl(rng_base + RNGA_STATUS) &
+ RNGA_STATUS_LEVEL_MASK) >> 8;
+ if (level || !wait)
+ return !!level;
+ udelay(10);
+ }
+ return 0;
}
static int mxc_rnga_data_read(struct hwrng *rng, u32 * data)
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 1412565c01af..d706bd0e9e80 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -162,22 +162,24 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
#ifdef CONFIG_PM
-static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
+static int omap_rng_suspend(struct device *dev)
{
omap_rng_write_reg(RNG_MASK_REG, 0x0);
return 0;
}
-static int omap_rng_resume(struct platform_device *pdev)
+static int omap_rng_resume(struct device *dev)
{
omap_rng_write_reg(RNG_MASK_REG, 0x1);
return 0;
}
+static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
+#define OMAP_RNG_PM (&omap_rng_pm)
+
#else
-#define omap_rng_suspend NULL
-#define omap_rng_resume NULL
+#define OMAP_RNG_PM NULL
#endif
@@ -188,11 +190,10 @@ static struct platform_driver omap_rng_driver = {
.driver = {
.name = "omap_rng",
.owner = THIS_MODULE,
+ .pm = OMAP_RNG_PM,
},
.probe = omap_rng_probe,
.remove = __exit_p(omap_rng_remove),
- .suspend = omap_rng_suspend,
- .resume = omap_rng_resume
};
static int __init omap_rng_init(void)
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 1e638fff40ea..83f85cf7fb1b 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2503,18 +2503,6 @@ static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
cleanup_one_si(info);
}
-#ifdef CONFIG_PM
-static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
- return 0;
-}
-
-static int ipmi_pci_resume(struct pci_dev *pdev)
-{
- return 0;
-}
-#endif
-
static struct pci_device_id ipmi_pci_devices[] = {
{ PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
{ PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
@@ -2527,10 +2515,6 @@ static struct pci_driver ipmi_pci_driver = {
.id_table = ipmi_pci_devices,
.probe = ipmi_pci_probe,
.remove = __devexit_p(ipmi_pci_remove),
-#ifdef CONFIG_PM
- .suspend = ipmi_pci_suspend,
- .resume = ipmi_pci_resume,
-#endif
};
#endif /* CONFIG_PCI */
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 7ed356e52035..37b8be7cba95 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -141,17 +141,6 @@
#define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80
-/* These are here until the real ones get into the watchdog.h interface. */
-#ifndef WDIOC_GETTIMEOUT
-#define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int)
-#endif
-#ifndef WDIOC_SET_PRETIMEOUT
-#define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int)
-#endif
-#ifndef WDIOC_GET_PRETIMEOUT
-#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
-#endif
-
static DEFINE_MUTEX(ipmi_watchdog_mutex);
static bool nowayout = WATCHDOG_NOWAYOUT;
@@ -732,7 +721,6 @@ static int ipmi_ioctl(struct file *file,
return -EFAULT;
return 0;
- case WDIOC_SET_PRETIMEOUT:
case WDIOC_SETPRETIMEOUT:
i = copy_from_user(&val, argp, sizeof(int));
if (i)
@@ -740,7 +728,6 @@ static int ipmi_ioctl(struct file *file,
pretimeout = val;
return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY);
- case WDIOC_GET_PRETIMEOUT:
case WDIOC_GETPRETIMEOUT:
i = copy_to_user(argp, &pretimeout, sizeof(pretimeout));
if (i)
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 67c3371723cc..e5eedfa24c91 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -27,14 +27,16 @@
#include <linux/splice.h>
#include <linux/pfn.h>
#include <linux/export.h>
+#include <linux/io.h>
#include <asm/uaccess.h>
-#include <asm/io.h>
#ifdef CONFIG_IA64
# include <linux/efi.h>
#endif
+#define DEVPORT_MINOR 4
+
static inline unsigned long size_inside_page(unsigned long start,
unsigned long size)
{
@@ -894,6 +896,13 @@ static int __init chr_dev_init(void)
for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) {
if (!devlist[minor].name)
continue;
+
+ /*
+ * Create /dev/port?
+ */
+ if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
+ continue;
+
device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
NULL, devlist[minor].name);
}
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 45713f0e7d61..f87780502b41 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1459,7 +1459,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
#ifdef CONFIG_PM
static int old_camera_power;
-static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+static int sonypi_suspend(struct device *dev)
{
old_camera_power = sonypi_device.camera_power;
sonypi_disable();
@@ -1467,14 +1467,16 @@ static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
return 0;
}
-static int sonypi_resume(struct platform_device *dev)
+static int sonypi_resume(struct device *dev)
{
sonypi_enable(old_camera_power);
return 0;
}
+
+static SIMPLE_DEV_PM_OPS(sonypi_pm, sonypi_suspend, sonypi_resume);
+#define SONYPI_PM (&sonypi_pm)
#else
-#define sonypi_suspend NULL
-#define sonypi_resume NULL
+#define SONYPI_PM NULL
#endif
static void sonypi_shutdown(struct platform_device *dev)
@@ -1486,12 +1488,11 @@ static struct platform_driver sonypi_driver = {
.driver = {
.name = "sonypi",
.owner = THIS_MODULE,
+ .pm = SONYPI_PM,
},
.probe = sonypi_probe,
.remove = __devexit_p(sonypi_remove),
.shutdown = sonypi_shutdown,
- .suspend = sonypi_suspend,
- .resume = sonypi_resume,
};
static struct platform_device *sonypi_platform_device;
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index ad7c7320dd1b..817f0ee202b6 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -827,10 +827,10 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend);
int tpm_do_selftest(struct tpm_chip *chip)
{
int rc;
- u8 digest[TPM_DIGEST_SIZE];
unsigned int loops;
unsigned int delay_msec = 1000;
unsigned long duration;
+ struct tpm_cmd_t cmd;
duration = tpm_calc_ordinal_duration(chip,
TPM_ORD_CONTINUE_SELFTEST);
@@ -845,7 +845,15 @@ int tpm_do_selftest(struct tpm_chip *chip)
return rc;
do {
- rc = __tpm_pcr_read(chip, 0, digest);
+ /* Attempt to read a PCR value */
+ cmd.header.in = pcrread_header;
+ cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
+ rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
+
+ if (rc < TPM_HEADER_SIZE)
+ return -EFAULT;
+
+ rc = be32_to_cpu(cmd.header.out.return_code);
if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
dev_info(chip->dev,
"TPM is disabled/deactivated (0x%X)\n", rc);
@@ -1274,7 +1282,7 @@ static struct tpm_input_header savestate_header = {
* We are about to suspend. Save the TPM state
* so that it can be restored.
*/
-int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
+int tpm_pm_suspend(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
struct tpm_cmd_t cmd;
@@ -1322,6 +1330,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
void tpm_dev_vendor_release(struct tpm_chip *chip)
{
+ if (!chip)
+ return;
+
if (chip->vendor.release)
chip->vendor.release(chip->dev);
@@ -1339,6 +1350,9 @@ void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
+ if (!chip)
+ return;
+
tpm_dev_vendor_release(chip);
chip->release(dev);
@@ -1405,15 +1419,12 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
"unable to misc_register %s, minor %d\n",
chip->vendor.miscdev.name,
chip->vendor.miscdev.minor);
- put_device(chip->dev);
- return NULL;
+ goto put_device;
}
if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
misc_deregister(&chip->vendor.miscdev);
- put_device(chip->dev);
-
- return NULL;
+ goto put_device;
}
chip->bios_dir = tpm_bios_log_setup(devname);
@@ -1425,6 +1436,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
return chip;
+put_device:
+ put_device(chip->dev);
out_free:
kfree(chip);
kfree(devname);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index b1c5280ac159..917f727e6740 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -299,7 +299,7 @@ extern ssize_t tpm_write(struct file *, const char __user *, size_t,
loff_t *);
extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
extern void tpm_remove_hardware(struct device *);
-extern int tpm_pm_suspend(struct device *, pm_message_t);
+extern int tpm_pm_suspend(struct device *);
extern int tpm_pm_resume(struct device *);
extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
wait_queue_head_t *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index c64a1bc65349..678d57019dc4 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -168,22 +168,14 @@ static void atml_plat_remove(void)
}
}
-static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg)
-{
- return tpm_pm_suspend(&dev->dev, msg);
-}
+static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume);
-static int tpm_atml_resume(struct platform_device *dev)
-{
- return tpm_pm_resume(&dev->dev);
-}
static struct platform_driver atml_drv = {
.driver = {
.name = "tpm_atmel",
.owner = THIS_MODULE,
+ .pm = &tpm_atml_pm,
},
- .suspend = tpm_atml_suspend,
- .resume = tpm_atml_resume,
};
static int __init init_atmel(void)
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
index 76da32e11f18..3251a44e8ceb 100644
--- a/drivers/char/tpm/tpm_infineon.c
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -4,8 +4,8 @@
* SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
* Specifications at www.trustedcomputinggroup.org
*
- * Copyright (C) 2005, Marcel Selhorst <m.selhorst@sirrix.com>
- * Sirrix AG - security technologies, http://www.sirrix.com and
+ * Copyright (C) 2005, Marcel Selhorst <tpmdd@selhorst.net>
+ * Sirrix AG - security technologies <tpmdd@sirrix.com> and
* Applied Data Security Group, Ruhr-University Bochum, Germany
* Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/
*
@@ -671,7 +671,7 @@ static void __exit cleanup_inf(void)
module_init(init_inf);
module_exit(cleanup_inf);
-MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>");
+MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
MODULE_VERSION("1.9.2");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 4d2464871ada..640c9a427b59 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -274,22 +274,13 @@ static void tpm_nsc_remove(struct device *dev)
}
}
-static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg)
-{
- return tpm_pm_suspend(&dev->dev, msg);
-}
-
-static int tpm_nsc_resume(struct platform_device *dev)
-{
- return tpm_pm_resume(&dev->dev);
-}
+static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume);
static struct platform_driver nsc_drv = {
- .suspend = tpm_nsc_suspend,
- .resume = tpm_nsc_resume,
.driver = {
.name = "tpm_nsc",
.owner = THIS_MODULE,
+ .pm = &tpm_nsc_pm,
},
};
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index d2a70cae76df..89682fa8801e 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -750,7 +750,7 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
{
- return tpm_pm_suspend(&dev->dev, msg);
+ return tpm_pm_suspend(&dev->dev);
}
static int tpm_tis_pnp_resume(struct pnp_dev *dev)
@@ -806,27 +806,25 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
#endif
-static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
-{
- return tpm_pm_suspend(&dev->dev, msg);
-}
-static int tpm_tis_resume(struct platform_device *dev)
+static int tpm_tis_resume(struct device *dev)
{
- struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+ struct tpm_chip *chip = dev_get_drvdata(dev);
if (chip->vendor.irq)
tpm_tis_reenable_interrupts(chip);
- return tpm_pm_resume(&dev->dev);
+ return tpm_pm_resume(dev);
}
+
+static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
+
static struct platform_driver tis_drv = {
.driver = {
.name = "tpm_tis",
.owner = THIS_MODULE,
+ .pm = &tpm_tis_pm,
},
- .suspend = tpm_tis_suspend,
- .resume = tpm_tis_resume,
};
static struct platform_device *pdev;