aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 07:55:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-07 07:55:16 -0400
commit5e090ed7af10729a396a25df43d69a236e789736 (patch)
tree09ba2dd9974b5224721fbc413bcf6ac9b2ac73f9 /drivers/char
parent84424026c0a910886064049d414a12a4f4dd125e (diff)
parent54d69df5849ec2e660aa12ac75562618c10fb499 (diff)
Merge tag 'soc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull late ARM soc platform updates from Olof Johansson: "This branch contains updates to OMAP and Marvell platforms (kirkwood, dove, mvebu) that came in after we had done the big multiplatform merges, so they were kept separate from the rest, and not separated into the traditional topics of cleanup/driver/platform features. For OMAP, the updates are: - Runtime PM conversions for the GPMC and RNG IP blocks - Preparation patches for the OMAP common clock framework conversion - clkdev alias additions required by other drivers - Performance Monitoring Unit (PMU) support for OMAP2, 3, and non-4430 OMAP4 - OMAP hwmod code and data improvements - Preparation patches for the IOMMU runtime PM conversion - Preparation patches for OMAP4 full-chip retention support For Kirkwood/Dove/mvebu: - New driver for "address decoder controller" for mvebu, which is a piece of hardware that configures addressable devices and peripherals. First user is the boot rom aperture on armada XP since it is needed for SMP support. - New device tree bindings for peripherals such as gpio-fan, iconnect nand, mv_cesa and the above address decoder controller. - Some defconfig updates, mostly to enable new DT boards and a few drivers. - New drivers using the pincontrol subsystem for dove, kirkwood and mvebu - New clean gpio driver for mvebu" * tag 'soc-late' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (98 commits) ARM: mvebu: fix build breaks from multi-platform conversion ARM: OMAP4460/4470: PMU: Enable PMU for OMAP4460/70 ARM: OMAP2+: PMU: Add runtime PM support ARM: OMAP4430: PMU: prepare to create PMU device via HWMOD ARM: OMAP2+: PMU: Convert OMAP2/3 devices to use HWMOD ARM: OMAP3: hwmod data: Add debugss HWMOD data ARM: OMAP2+: clockdomain/hwmod: add workaround for EMU clockdomain idle problems ARM: OMAP: Add a timer attribute for timers that can interrupt the DSP hwrng: OMAP: remove SoC restrictions from driver registration ARM: OMAP: split OMAP1, OMAP2+ RNG device registration hwrng: OMAP: convert to use runtime PM hwrng: OMAP: store per-device data in per-device variables, not file statics ARM: OMAP2xxx: hwmod/CM: add RNG integration data ARM: OMAP2+: gpmc: minimal driver support ARM: OMAP2+: gpmc: Adapt to HWMOD ARM: OMAP2/3: hwmod data: add gpmc ARM: OMAP4: hwmod data: add mmu hwmod for ipu and dsp ARM: OMAP3: hwmod data: add mmu data for iva and isp ARM: OMAP: iommu: fix including iommu.h without IOMMU_API selected ARM: OMAP4: hwmod data: add missing HWMOD_NO_IDLEST flags to some PRCM IP blocks ...
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/hw_random/omap-rng.c121
1 files changed, 70 insertions, 51 deletions
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 4fbdceb6f773..a5effd813abd 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -18,11 +18,12 @@
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/init.h> 19#include <linux/init.h>
20#include <linux/random.h> 20#include <linux/random.h>
21#include <linux/clk.h>
22#include <linux/err.h> 21#include <linux/err.h>
23#include <linux/platform_device.h> 22#include <linux/platform_device.h>
24#include <linux/hw_random.h> 23#include <linux/hw_random.h>
25#include <linux/delay.h> 24#include <linux/delay.h>
25#include <linux/slab.h>
26#include <linux/pm_runtime.h>
26 27
27#include <asm/io.h> 28#include <asm/io.h>
28 29
@@ -46,26 +47,36 @@
46#define RNG_SYSSTATUS 0x44 /* System status 47#define RNG_SYSSTATUS 0x44 /* System status
47 [0] = RESETDONE */ 48 [0] = RESETDONE */
48 49
49static void __iomem *rng_base; 50/**
50static struct clk *rng_ick; 51 * struct omap_rng_private_data - RNG IP block-specific data
51static struct platform_device *rng_dev; 52 * @base: virtual address of the beginning of the RNG IP block registers
53 * @mem_res: struct resource * for the IP block registers physical memory
54 */
55struct omap_rng_private_data {
56 void __iomem *base;
57 struct resource *mem_res;
58};
52 59
53static inline u32 omap_rng_read_reg(int reg) 60static inline u32 omap_rng_read_reg(struct omap_rng_private_data *priv, int reg)
54{ 61{
55 return __raw_readl(rng_base + reg); 62 return __raw_readl(priv->base + reg);
56} 63}
57 64
58static inline void omap_rng_write_reg(int reg, u32 val) 65static inline void omap_rng_write_reg(struct omap_rng_private_data *priv,
66 int reg, u32 val)
59{ 67{
60 __raw_writel(val, rng_base + reg); 68 __raw_writel(val, priv->base + reg);
61} 69}
62 70
63static int omap_rng_data_present(struct hwrng *rng, int wait) 71static int omap_rng_data_present(struct hwrng *rng, int wait)
64{ 72{
73 struct omap_rng_private_data *priv;
65 int data, i; 74 int data, i;
66 75
76 priv = (struct omap_rng_private_data *)rng->priv;
77
67 for (i = 0; i < 20; i++) { 78 for (i = 0; i < 20; i++) {
68 data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; 79 data = omap_rng_read_reg(priv, RNG_STAT_REG) ? 0 : 1;
69 if (data || !wait) 80 if (data || !wait)
70 break; 81 break;
71 /* RNG produces data fast enough (2+ MBit/sec, even 82 /* RNG produces data fast enough (2+ MBit/sec, even
@@ -80,9 +91,13 @@ static int omap_rng_data_present(struct hwrng *rng, int wait)
80 91
81static int omap_rng_data_read(struct hwrng *rng, u32 *data) 92static int omap_rng_data_read(struct hwrng *rng, u32 *data)
82{ 93{
83 *data = omap_rng_read_reg(RNG_OUT_REG); 94 struct omap_rng_private_data *priv;
95
96 priv = (struct omap_rng_private_data *)rng->priv;
97
98 *data = omap_rng_read_reg(priv, RNG_OUT_REG);
84 99
85 return 4; 100 return sizeof(u32);
86} 101}
87 102
88static struct hwrng omap_rng_ops = { 103static struct hwrng omap_rng_ops = {
@@ -93,69 +108,68 @@ static struct hwrng omap_rng_ops = {
93 108
94static int __devinit omap_rng_probe(struct platform_device *pdev) 109static int __devinit omap_rng_probe(struct platform_device *pdev)
95{ 110{
96 struct resource *res; 111 struct omap_rng_private_data *priv;
97 int ret; 112 int ret;
98 113
99 /* 114 priv = kzalloc(sizeof(struct omap_rng_private_data), GFP_KERNEL);
100 * A bit ugly, and it will never actually happen but there can 115 if (!priv) {
101 * be only one RNG and this catches any bork 116 dev_err(&pdev->dev, "could not allocate memory\n");
102 */ 117 return -ENOMEM;
103 if (rng_dev) 118 };
104 return -EBUSY;
105
106 if (cpu_is_omap24xx()) {
107 rng_ick = clk_get(&pdev->dev, "ick");
108 if (IS_ERR(rng_ick)) {
109 dev_err(&pdev->dev, "Could not get rng_ick\n");
110 ret = PTR_ERR(rng_ick);
111 return ret;
112 } else
113 clk_enable(rng_ick);
114 }
115 119
116 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 120 omap_rng_ops.priv = (unsigned long)priv;
121 dev_set_drvdata(&pdev->dev, priv);
117 122
118 rng_base = devm_request_and_ioremap(&pdev->dev, res); 123 priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
119 if (!rng_base) { 124 if (!priv->mem_res) {
125 ret = -ENOENT;
126 goto err_ioremap;
127 }
128
129 priv->base = devm_request_and_ioremap(&pdev->dev, priv->mem_res);
130 if (!priv->base) {
120 ret = -ENOMEM; 131 ret = -ENOMEM;
121 goto err_ioremap; 132 goto err_ioremap;
122 } 133 }
123 dev_set_drvdata(&pdev->dev, res); 134 dev_set_drvdata(&pdev->dev, priv);
135
136 pm_runtime_enable(&pdev->dev);
137 pm_runtime_get_sync(&pdev->dev);
124 138
125 ret = hwrng_register(&omap_rng_ops); 139 ret = hwrng_register(&omap_rng_ops);
126 if (ret) 140 if (ret)
127 goto err_register; 141 goto err_register;
128 142
129 dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", 143 dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n",
130 omap_rng_read_reg(RNG_REV_REG)); 144 omap_rng_read_reg(priv, RNG_REV_REG));
131 omap_rng_write_reg(RNG_MASK_REG, 0x1);
132 145
133 rng_dev = pdev; 146 omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
134 147
135 return 0; 148 return 0;
136 149
137err_register: 150err_register:
138 rng_base = NULL; 151 priv->base = NULL;
152 pm_runtime_disable(&pdev->dev);
139err_ioremap: 153err_ioremap:
140 if (cpu_is_omap24xx()) { 154 kfree(priv);
141 clk_disable(rng_ick); 155
142 clk_put(rng_ick);
143 }
144 return ret; 156 return ret;
145} 157}
146 158
147static int __exit omap_rng_remove(struct platform_device *pdev) 159static int __exit omap_rng_remove(struct platform_device *pdev)
148{ 160{
161 struct omap_rng_private_data *priv = dev_get_drvdata(&pdev->dev);
162
149 hwrng_unregister(&omap_rng_ops); 163 hwrng_unregister(&omap_rng_ops);
150 164
151 omap_rng_write_reg(RNG_MASK_REG, 0x0); 165 omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
152 166
153 if (cpu_is_omap24xx()) { 167 pm_runtime_put_sync(&pdev->dev);
154 clk_disable(rng_ick); 168 pm_runtime_disable(&pdev->dev);
155 clk_put(rng_ick); 169
156 } 170 release_mem_region(priv->mem_res->start, resource_size(priv->mem_res));
157 171
158 rng_base = NULL; 172 kfree(priv);
159 173
160 return 0; 174 return 0;
161} 175}
@@ -164,13 +178,21 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
164 178
165static int omap_rng_suspend(struct device *dev) 179static int omap_rng_suspend(struct device *dev)
166{ 180{
167 omap_rng_write_reg(RNG_MASK_REG, 0x0); 181 struct omap_rng_private_data *priv = dev_get_drvdata(dev);
182
183 omap_rng_write_reg(priv, RNG_MASK_REG, 0x0);
184 pm_runtime_put_sync(dev);
185
168 return 0; 186 return 0;
169} 187}
170 188
171static int omap_rng_resume(struct device *dev) 189static int omap_rng_resume(struct device *dev)
172{ 190{
173 omap_rng_write_reg(RNG_MASK_REG, 0x1); 191 struct omap_rng_private_data *priv = dev_get_drvdata(dev);
192
193 pm_runtime_get_sync(dev);
194 omap_rng_write_reg(priv, RNG_MASK_REG, 0x1);
195
174 return 0; 196 return 0;
175} 197}
176 198
@@ -198,9 +220,6 @@ static struct platform_driver omap_rng_driver = {
198 220
199static int __init omap_rng_init(void) 221static int __init omap_rng_init(void)
200{ 222{
201 if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
202 return -ENODEV;
203
204 return platform_driver_register(&omap_rng_driver); 223 return platform_driver_register(&omap_rng_driver);
205} 224}
206 225