aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/amba/bus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/amba/bus.c')
-rw-r--r--drivers/amba/bus.c88
1 files changed, 69 insertions, 19 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index f60b2b6a0931..d31590e7011b 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -122,6 +122,31 @@ static int __init amba_init(void)
122 122
123postcore_initcall(amba_init); 123postcore_initcall(amba_init);
124 124
125static int amba_get_enable_pclk(struct amba_device *pcdev)
126{
127 struct clk *pclk = clk_get(&pcdev->dev, "apb_pclk");
128 int ret;
129
130 pcdev->pclk = pclk;
131
132 if (IS_ERR(pclk))
133 return PTR_ERR(pclk);
134
135 ret = clk_enable(pclk);
136 if (ret)
137 clk_put(pclk);
138
139 return ret;
140}
141
142static void amba_put_disable_pclk(struct amba_device *pcdev)
143{
144 struct clk *pclk = pcdev->pclk;
145
146 clk_disable(pclk);
147 clk_put(pclk);
148}
149
125/* 150/*
126 * These are the device model conversion veneers; they convert the 151 * These are the device model conversion veneers; they convert the
127 * device model structures to our more specific structures. 152 * device model structures to our more specific structures.
@@ -130,17 +155,33 @@ static int amba_probe(struct device *dev)
130{ 155{
131 struct amba_device *pcdev = to_amba_device(dev); 156 struct amba_device *pcdev = to_amba_device(dev);
132 struct amba_driver *pcdrv = to_amba_driver(dev->driver); 157 struct amba_driver *pcdrv = to_amba_driver(dev->driver);
133 struct amba_id *id; 158 struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
159 int ret;
134 160
135 id = amba_lookup(pcdrv->id_table, pcdev); 161 do {
162 ret = amba_get_enable_pclk(pcdev);
163 if (ret)
164 break;
165
166 ret = pcdrv->probe(pcdev, id);
167 if (ret == 0)
168 break;
136 169
137 return pcdrv->probe(pcdev, id); 170 amba_put_disable_pclk(pcdev);
171 } while (0);
172
173 return ret;
138} 174}
139 175
140static int amba_remove(struct device *dev) 176static int amba_remove(struct device *dev)
141{ 177{
178 struct amba_device *pcdev = to_amba_device(dev);
142 struct amba_driver *drv = to_amba_driver(dev->driver); 179 struct amba_driver *drv = to_amba_driver(dev->driver);
143 return drv->remove(to_amba_device(dev)); 180 int ret = drv->remove(pcdev);
181
182 amba_put_disable_pclk(pcdev);
183
184 return ret;
144} 185}
145 186
146static void amba_shutdown(struct device *dev) 187static void amba_shutdown(struct device *dev)
@@ -203,7 +244,6 @@ static void amba_device_release(struct device *dev)
203 */ 244 */
204int amba_device_register(struct amba_device *dev, struct resource *parent) 245int amba_device_register(struct amba_device *dev, struct resource *parent)
205{ 246{
206 u32 pid, cid;
207 u32 size; 247 u32 size;
208 void __iomem *tmp; 248 void __iomem *tmp;
209 int i, ret; 249 int i, ret;
@@ -241,25 +281,35 @@ int amba_device_register(struct amba_device *dev, struct resource *parent)
241 goto err_release; 281 goto err_release;
242 } 282 }
243 283
244 /* 284 ret = amba_get_enable_pclk(dev);
245 * Read pid and cid based on size of resource 285 if (ret == 0) {
246 * they are located at end of region 286 u32 pid, cid;
247 */
248 for (pid = 0, i = 0; i < 4; i++)
249 pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) << (i * 8);
250 for (cid = 0, i = 0; i < 4; i++)
251 cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) << (i * 8);
252 287
253 iounmap(tmp); 288 /*
289 * Read pid and cid based on size of resource
290 * they are located at end of region
291 */
292 for (pid = 0, i = 0; i < 4; i++)
293 pid |= (readl(tmp + size - 0x20 + 4 * i) & 255) <<
294 (i * 8);
295 for (cid = 0, i = 0; i < 4; i++)
296 cid |= (readl(tmp + size - 0x10 + 4 * i) & 255) <<
297 (i * 8);
254 298
255 if (cid == 0xb105f00d) 299 amba_put_disable_pclk(dev);
256 dev->periphid = pid;
257 300
258 if (!dev->periphid) { 301 if (cid == 0xb105f00d)
259 ret = -ENODEV; 302 dev->periphid = pid;
260 goto err_release; 303
304 if (!dev->periphid)
305 ret = -ENODEV;
261 } 306 }
262 307
308 iounmap(tmp);
309
310 if (ret)
311 goto err_release;
312
263 ret = device_add(&dev->dev); 313 ret = device_add(&dev->dev);
264 if (ret) 314 if (ret)
265 goto err_release; 315 goto err_release;