ARM: mali400: r5p2_rel0: fix Makefile & Kconfig
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / hwspinlock / sprd_hwspinlock.c
1 /*
2  * SCI hardware spinlock driver
3  *
4  * Copyright (C) 2012 Spreadtrum  - http://www.spreadtrum.com
5  * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
6  *
7  * Contact: steve.zhan <steve.zhan@spreadtrum.com>
8  *        
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * version 2 as published by the Free Software Foundation.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * General Public License for more details.
17  */
18
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/device.h>
22 #include <linux/delay.h>
23 #include <linux/io.h>
24 #include <linux/bitops.h>
25 #include <linux/pm_runtime.h>
26 #include <linux/slab.h>
27 #include <linux/spinlock.h>
28 #include <linux/hwspinlock.h>
29 #include <linux/platform_device.h>
30 #include <linux/of.h>
31 #include <linux/of_device.h>
32
33 #include <soc/sprd/sci.h>
34 #include <soc/sprd/sci_glb_regs.h>
35 #include <soc/sprd/arch_lock.h>
36 #include "hwspinlock_internal.h"
37
38 /* hwspinlock reg */
39 #define HWSPINLOCK_CLEAR                        (0x0)
40 #define HWSPINLOCK_RECCTRL                      (0x4)
41 #define HWSPINLOCK_TTLSTS                       (0x8)
42 #define HWSPINLOCK_CLEAREN                      (0xc)
43 #define HWSPINLOCK_FLAG0                        (0x10)
44 #define HWSPINLOCK_FLAG1                        (0x14)
45 #define HWSPINLOCK_FLAG2                        (0x18)
46 #define HWSPINLOCK_FLAG3                        (0x1c)
47 #define HWSPINLOCK_MASTERID(_X_)        (0x80 + 0x4*(_X_))
48 #define HWSPINLOCK_TOKEN_V0(_X_)        (0x80 + 0x4*(_X_))
49 #define HWSPINLOCK_TOKEN_V1(_X_)        (0x800 + 0x4*(_X_))
50 #define HWSPINLOCK_VERID                        (0xFFC)
51
52 /* RECCTRL */
53 #define HWSPINLOCK_ID                           BIT(0)
54 #define HWSPINLOCK_USER_BITS            BIT(1)
55
56 /* first processor */
57 #define THIS_PROCESSOR_KEY                      (HWSPINLOCK_WRITE_KEY)
58
59 /* spinlock enable */
60 #define HWSPINLOCK_ENABLE_CLEAR         (0x454e434c)
61
62 /* hwspinlock controller */
63 #define AON_HWSPLOCK                            (1)
64 #define AP_HWSPLOCK                                     (0)
65
66 struct sprd_hwspinlock_dev {
67         unsigned int hwspinlock_vid;
68         unsigned long hwspinlock_base;
69         unsigned int hwspinlock_cnt;
70         struct hwspinlock_device bank;
71 };
72
73 /* array[0] stands for lock0 */
74 unsigned char hwlocks_implemented[HWSPINLOCK_ID_TOTAL_NUMS];
75 unsigned char local_hwlocks_status[HWSPINLOCK_ID_TOTAL_NUMS];
76 struct hwspinlock *hwlocks[HWSPINLOCK_ID_TOTAL_NUMS];
77 int hwspinlock_vid_early;
78
79 static struct sprd_hwspinlock_dev *hwlock_to_sprdlock_dev(struct hwspinlock *hwlock)
80 {
81         struct hwspinlock_device *hwbank;
82         int lock_id;
83         
84         if(!hwlock)
85                 return NULL;
86
87         lock_id = hwlock_to_id(hwlock);
88         hwbank = container_of(hwlock,struct hwspinlock_device,lock[lock_id]);
89         if(hwbank)
90                 return container_of(hwbank,struct sprd_hwspinlock_dev,bank);
91         else
92                 return NULL;
93 }
94
95 #ifdef  CONFIG_ARCH_WHALE
96 int sprd_hwlock_init(void)
97 {
98         return 0;
99 }
100 #else
101 int sprd_hwlock_init(void)
102 {
103         writel_relaxed(BIT_SPINLOCK_EB, (void __iomem *)(REG_GLB_SET(REG_AP_AHB_AHB_EB)));
104         writel_relaxed(BIT_SPLK_EB, (void __iomem *)(REG_GLB_SET(REG_AON_APB_APB_EB0)));
105         return 0;
106 }
107 #endif
108
109 static void inline sprd_hwlocks_implemented(int hwlock_id)
110 {
111         if (hwlock_id == AON_HWSPLOCK){
112                 hwlocks_implemented[HWLOCK_ADI] = 1;
113                 hwlocks_implemented[HWLOCK_GLB] = 1;
114                 hwlocks_implemented[HWLOCK_AGPIO] = 1;
115                 hwlocks_implemented[HWLOCK_AEIC] = 1;
116                 hwlocks_implemented[HWLOCK_ADC] = 1;
117                 hwlocks_implemented[HWLOCK_EFUSE] = 1;
118         }else if (hwlock_id == AP_HWSPLOCK){
119                 /* Caution: ap hwspinlock id need add 31 */
120                 /* hwlocks_implemented[HWLOCK_ADI+31] = 1; */
121         }
122 }
123
124 #ifdef CONFIG_SEC_DEBUG_REG_ACCESS
125 extern unsigned char *sec_debug_local_hwlocks_status;
126 #endif
127 int sprd_record_hwlock_sts(unsigned int lock_id, unsigned int sts)
128 {
129         if(lock_id >= HWSPINLOCK_ID_TOTAL_NUMS){
130                 printk(KERN_ERR "Hwspinlock id is wrong!\n");
131                 return -ENXIO;
132         }
133
134         local_hwlocks_status[lock_id] = sts;
135
136 #ifdef CONFIG_SEC_DEBUG_REG_ACCESS
137         if (sec_debug_local_hwlocks_status)
138                 sec_debug_local_hwlocks_status[lock_id] = sts;
139 #endif
140         return sts;
141 }
142
143 int sprd_hwspinlock_isbusy(unsigned int lock_id)
144 {
145         unsigned int status = 0;
146         struct sprd_hwspinlock_dev *sprd_hwlock;
147
148         if (!hwlocks[lock_id]){
149                 printk(KERN_ERR "This hwspinlock is not register!\n");
150                 return -ENODEV;
151         }
152
153         sprd_hwlock = hwlock_to_sprdlock_dev(hwlocks[lock_id]);
154         if (!sprd_hwlock){
155                 printk(KERN_ERR "Can't find hwspinlock device!\n");
156                 return -ENODEV;
157         }
158
159         status = readl_relaxed((void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_TTLSTS));
160         if (status < 0)
161                 return -EIO;
162         return ((status & (1 << lock_id)) ? 1 : 0);
163 }
164
165 int sprd_hwspinlocks_isbusy(void)
166 {
167         int id;
168
169         for(id = 0; id < HWSPINLOCK_ID_TOTAL_NUMS; id++){
170                 if(sprd_hwspinlock_isbusy(id) > 0)
171                         return 1;
172         }
173         return 0;
174 }
175
176 int sprd_hwspinlock_master_id(unsigned int lock_id)
177 {
178         unsigned int master_id = 0;
179         struct sprd_hwspinlock_dev *sprd_hwlock;
180
181         if(!hwlocks[lock_id]){
182                 printk(KERN_ERR "This hwspinlock is not register!\n");
183                 return -ENODEV;
184         }
185
186         sprd_hwlock = hwlock_to_sprdlock_dev(hwlocks[lock_id]);
187         if (!sprd_hwlock){
188                 printk(KERN_ERR "Can't find hwspinlock device!\n");
189                 return -ENODEV;
190         }
191         
192         master_id = readl_relaxed((void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_MASTERID(lock_id)));
193         return master_id;
194 }
195
196 void hwspinlock_clear(unsigned int lock_id)
197 {
198         struct sprd_hwspinlock_dev *sprd_hwlock;
199
200         if(!hwlocks[lock_id]){
201                 printk(KERN_ERR "This hwspinlock is not register!\n");
202                 return;
203         }
204
205         sprd_hwlock = hwlock_to_sprdlock_dev(hwlocks[lock_id]);
206         if (!sprd_hwlock){
207                 printk(KERN_ERR "Can't find hwspinlock device!\n");
208                 return;
209         }
210         /*setting the abnormal clear bit to 1 makes the corresponding
211          *lock to Not Taken state
212          */
213         writel_relaxed(HWSPINLOCK_ENABLE_CLEAR,(void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_CLEAREN));
214         writel_relaxed((1 << lock_id), (void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_CLEAR));
215         writel_relaxed(~HWSPINLOCK_ENABLE_CLEAR, (void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_CLEAREN));
216 }
217
218 void hwspinlock_clear_all(void)
219 {
220         unsigned int lock_id = 0;
221         do {
222                 hwspinlock_clear(lock_id);
223         } while (lock_id++ < HWSPINLOCK_ID_TOTAL_NUMS);
224 }
225
226 static int sprd_check_hwspinlock_vid(struct hwspinlock *lock)
227 {
228         struct sprd_hwspinlock_dev *sprd_hwlock;
229
230         sprd_hwlock = hwlock_to_sprdlock_dev(lock);
231         if (!sprd_hwlock){
232                 printk(KERN_ERR "%s:Can't find hwspinlock device!\n",__func__);
233                 return -ENODEV;
234         }
235
236         /* for sharkl/sharkl64/whale project */
237         if (sprd_hwlock->hwspinlock_vid == 0x100 || sprd_hwlock->hwspinlock_vid == 0x200
238                 || sprd_hwlock->hwspinlock_vid == 0x300){
239                 return 1;
240         } else {
241                 pr_debug("Warning:hwlock version id is 0x%x!\n",sprd_hwlock->hwspinlock_vid);
242                 return 0;
243         }
244 }
245
246 static unsigned long sprd_hwspinlock_addr(unsigned int lock_id)
247 {
248         unsigned long addr;
249         struct hwspinlock *lock;
250
251         if(lock_id >= HWSPINLOCK_ID_TOTAL_NUMS){
252                 printk(KERN_ERR "Hwspinlock id is wrong!\n");
253                 return 0;
254         }
255
256         lock = hwlocks[lock_id];
257         if (!lock){
258                 printk(KERN_ERR "Call %s: can't find hwspinlock!\n",__func__);
259                 return 0;
260         }
261         else
262                 addr = (unsigned long)lock->priv;
263
264         return addr;
265 }
266
267 static int sprd_init_hwlocks(int hwlock_id)
268 {
269         struct hwspinlock **plock;
270         int i;
271
272         sprd_hwlocks_implemented(hwlock_id);
273
274         if (hwlock_id == AON_HWSPLOCK)
275                 i = 0;
276         else if (hwlock_id == AP_HWSPLOCK)
277                 i = 31;
278         else
279                 i = HWSPINLOCK_ID_TOTAL_NUMS;
280
281         for (; i < HWSPINLOCK_ID_TOTAL_NUMS; ++i) {
282                 if (hwlocks_implemented[i]) {
283                         plock = &hwlocks[i];
284                         *plock = hwspin_lock_request_specific(i);
285                         if (WARN_ON(IS_ERR_OR_NULL(*plock)))
286                                 *plock = NULL;
287                         else
288                                 pr_info("early alloc hwspinlock id %d\n",
289                                         hwspin_lock_get_id(*plock));
290                 }
291         }
292         return 0;
293 }
294
295 static unsigned int do_lock_key(struct hwspinlock *lock)
296 {
297         unsigned int key = THIS_PROCESSOR_KEY;
298         return key;
299 }
300
301 static int __hwspinlock_trylock(struct hwspinlock *lock)
302 {
303         void __iomem *addr = lock->priv;
304
305         if (sprd_check_hwspinlock_vid(lock)) {
306                 if (!readl_relaxed(addr))
307                         goto __locked;
308         } else {
309                 unsigned int key = do_lock_key(lock);
310                 if (!(key ^ HWSPINLOCK_NOTTAKEN_V0))
311                         BUG_ON(1);
312                 if (HWSPINLOCK_NOTTAKEN_V0 == readl_relaxed(addr)) {
313                         writel_relaxed(key, addr);
314                         if (key == readl_relaxed(addr))
315                                 goto __locked;
316                 }
317         }
318
319         pr_debug("Hwspinlock [%d] lock failed!\n",hwlock_to_id(lock));
320         return 0;
321
322 __locked:
323         sprd_record_hwlock_sts(hwlock_to_id(lock), 1);
324         return 1;
325 }
326
327 static void __hwspinlock_unlock(struct hwspinlock *lock)
328 {
329         void __iomem *lock_addr = lock->priv;
330         int unlock_key;
331
332         if (sprd_check_hwspinlock_vid(lock)) {
333                 unlock_key = HWSPINLOCK_NOTTAKEN_V1;
334         } else {
335                 unlock_key = HWSPINLOCK_NOTTAKEN_V0;
336                 if (!(readl_relaxed(lock_addr) ^ unlock_key))
337                         BUG_ON(1);
338         }
339
340         writel_relaxed(unlock_key, lock_addr);
341         sprd_record_hwlock_sts(hwlock_to_id(lock), 0);
342 }
343
344 /*
345  * relax the  interconnect while spinning on it.
346  *
347  * The specs recommended that the retry delay time will be
348  * just over half of the time that a requester would be
349  * expected to hold the lock.
350  *
351  * The number below is taken from an hardware specs example,
352  * obviously it is somewhat arbitrary.
353  */
354 static void __hwspinlock_relax(struct hwspinlock *lock)
355 {
356         ndelay(10);
357 }
358
359 static const struct hwspinlock_ops sprd_hwspinlock_ops = {
360         .trylock = __hwspinlock_trylock,
361         .unlock = __hwspinlock_unlock,
362         .relax = __hwspinlock_relax,
363 };
364
365 static int sprd_hwspinlock_probe(struct platform_device *pdev)
366 {
367         struct hwspinlock *hwlock;
368         struct sprd_hwspinlock_dev *sprd_hwlock;
369         static int hwspinlock_exist_cnt = 0;
370         u32 num_locks = 0;
371         int i, ret, hwlock_id;
372
373         ret = of_alias_get_id(pdev->dev.of_node, "hwspinlock");
374         if (IS_ERR_VALUE(ret)) {
375                 printk(KERN_ERR "Hwspinlock get alias failed!\n");
376                 return ret;
377         }
378         hwlock_id = ret;
379
380         ret = of_property_read_u32(pdev->dev.of_node,"hwspinlock_cnt",&num_locks);
381         if(ret){
382                 printk(KERN_ERR "Hwspinlock get count failed!\n");
383                 num_locks = 32;
384         }
385
386         sprd_hwlock = devm_kzalloc(&pdev->dev, sizeof(struct sprd_hwspinlock_dev) 
387                                         + num_locks * sizeof(*hwlock), GFP_KERNEL);
388         if (!sprd_hwlock) {
389                 printk(KERN_ERR "Hwspinlock device alloc memory failed!\n");
390                 return -ENOMEM;
391         }
392
393         /* intial the hwspinlock */
394         sprd_hwlock_init();
395         sprd_hwlock->hwspinlock_cnt = num_locks;
396         if (hwlock_id == 1)
397                 sprd_hwlock->hwspinlock_base = SPRD_HWSPINLOCK1_BASE;
398         else if (hwlock_id == 0)
399                 sprd_hwlock->hwspinlock_base = SPRD_HWSPINLOCK0_BASE;
400         else {
401                 printk(KERN_ERR "Hwspinlock id is wrong!\n");
402                 return -ENODEV;
403         }
404         sprd_hwlock->hwspinlock_vid = readl_relaxed((void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_VERID));
405
406         for (i = 0, hwlock = &sprd_hwlock->bank.lock[0]; i < num_locks; i++, hwlock++) {
407                 if (sprd_hwlock->hwspinlock_vid == 0x100 || sprd_hwlock->hwspinlock_vid == 0x200
408                         || sprd_hwlock->hwspinlock_vid == 0x300)
409                         hwlock->priv = (void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_TOKEN_V1(i));
410                 else
411                         hwlock->priv = (void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_TOKEN_V0(i));
412         }
413
414         /*
415          * runtime PM will make sure the clock of this module is
416          * enabled if at least one lock is requested
417          */
418         platform_set_drvdata(pdev, sprd_hwlock);
419         pm_runtime_enable(&pdev->dev);
420
421         ret = hwspin_lock_register(&sprd_hwlock->bank, &pdev->dev, &sprd_hwspinlock_ops,
422                                    hwspinlock_exist_cnt, num_locks);
423         if (ret){
424                 printk(KERN_ERR "Hwspinlock register failed!\n");
425                 goto reg_fail;
426         }
427
428         hwspinlock_exist_cnt += num_locks;
429         /* inital the hwlocks */
430         sprd_init_hwlocks(hwlock_id);
431 #ifdef  CONFIG_ARCH_WHALE
432         /* record master user bits */
433         writel_relaxed(HWSPINLOCK_USER_BITS, (void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_RECCTRL));
434 #endif
435
436         printk("sprd hwspinlock probe ok: hwspinlock name = %s, hwspinlock_vid = 0x%x,"
437                         "hwspinlock_exist_cnt = %d\n", pdev->name,sprd_hwlock->hwspinlock_vid,hwspinlock_exist_cnt); 
438
439         return 0;
440
441 reg_fail:
442         pm_runtime_disable(&pdev->dev);
443         return ret;
444 }
445
446 static int sprd_hwspinlock_remove(struct platform_device *pdev)
447 {
448         struct sprd_hwspinlock_dev *sprd_hwlock = platform_get_drvdata(pdev);
449         int ret;
450
451         ret = hwspin_lock_unregister(&sprd_hwlock->bank);
452         if (ret) {
453                 dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
454                 return ret;
455         }
456
457         pm_runtime_disable(&pdev->dev);
458         return 0;
459 }
460
461 static const struct of_device_id sprd_hwspinlock_of_match[] = {
462         { .compatible = "sprd,sprd-hwspinlock", },
463         { /* sentinel */ }
464 };
465
466 static struct platform_driver sprd_hwspinlock_driver = {
467         .probe = sprd_hwspinlock_probe,
468         .remove = sprd_hwspinlock_remove,
469         .driver = {
470                 .name = "sprd_hwspinlock",
471                 .owner = THIS_MODULE,
472                 .of_match_table = of_match_ptr(sprd_hwspinlock_of_match),
473         },
474 };
475
476 static int __init sprd_hwspinlock_init(void)
477 {
478         return platform_driver_register(&sprd_hwspinlock_driver);
479 }
480
481 /* board init code might need to reserve hwspinlocks for predefined purposes */
482 postcore_initcall(sprd_hwspinlock_init);
483
484 static void __exit sprd_hwspinlock_exit(void)
485 {
486         platform_driver_unregister(&sprd_hwspinlock_driver);
487 }
488
489 module_exit(sprd_hwspinlock_exit);
490
491 static int remove_node(struct device_node *np)
492 {
493         struct property *ps;
494
495         ps = kzalloc(sizeof(*ps), GFP_KERNEL);
496         if (!ps)
497                 return -1;
498
499         ps->value = kstrdup("no", GFP_KERNEL);
500         ps->length = strlen(ps->value);
501         ps->name = kstrdup("status", GFP_KERNEL);
502         of_update_property(np, ps);
503         printk("After register,hwspinlock1 node available=%d\n",of_device_is_available(np));
504
505         return 0;
506 }
507
508 int __init early_hwspinlocks_init(void)
509 {
510         struct device_node *np;
511         struct platform_device *pdev;
512         int ret;
513
514         np = of_find_node_by_name(NULL, "hwspinlock1");
515         if (!np) {
516                 pr_warn("Can't get the hwspinlock1 node!\n");
517                 return -ENODEV;
518         }
519
520         pdev = of_platform_device_create(np, 0, NULL);
521         if (!pdev) {
522                 pr_warn("register hwspinlock1 failed!\n");
523                 return -ENODEV;
524         }
525
526         pr_info("SPRD register hwspinlock1 ok,hwspinlock1's name is %s!\n",pdev->name);
527         ret = remove_node(np);
528         return ret;
529 }
530
531 MODULE_LICENSE("GPL v2");
532 MODULE_DESCRIPTION("Hardware spinlock driver for Spreadtrum");
533 MODULE_AUTHOR("baolin.wang <baolin.wang@spreadtrum.com>");