2 * SCI hardware spinlock driver
4 * Copyright (C) 2012 Spreadtrum - http://www.spreadtrum.com
5 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
7 * Contact: steve.zhan <steve.zhan@spreadtrum.com>
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.
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.
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/device.h>
22 #include <linux/delay.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>
31 #include <linux/of_device.h>
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"
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)
53 #define HWSPINLOCK_ID BIT(0)
54 #define HWSPINLOCK_USER_BITS BIT(1)
57 #define THIS_PROCESSOR_KEY (HWSPINLOCK_WRITE_KEY)
60 #define HWSPINLOCK_ENABLE_CLEAR (0x454e434c)
62 /* hwspinlock controller */
63 #define AON_HWSPLOCK (1)
64 #define AP_HWSPLOCK (0)
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;
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;
79 static struct sprd_hwspinlock_dev *hwlock_to_sprdlock_dev(struct hwspinlock *hwlock)
81 struct hwspinlock_device *hwbank;
87 lock_id = hwlock_to_id(hwlock);
88 hwbank = container_of(hwlock,struct hwspinlock_device,lock[lock_id]);
90 return container_of(hwbank,struct sprd_hwspinlock_dev,bank);
95 #ifdef CONFIG_ARCH_WHALE
96 int sprd_hwlock_init(void)
101 int sprd_hwlock_init(void)
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)));
109 static void inline sprd_hwlocks_implemented(int hwlock_id)
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; */
124 #ifdef CONFIG_SEC_DEBUG_REG_ACCESS
125 extern unsigned char *sec_debug_local_hwlocks_status;
127 int sprd_record_hwlock_sts(unsigned int lock_id, unsigned int sts)
129 if(lock_id >= HWSPINLOCK_ID_TOTAL_NUMS){
130 printk(KERN_ERR "Hwspinlock id is wrong!\n");
134 local_hwlocks_status[lock_id] = sts;
136 #ifdef CONFIG_SEC_DEBUG_REG_ACCESS
137 if (sec_debug_local_hwlocks_status)
138 sec_debug_local_hwlocks_status[lock_id] = sts;
143 int sprd_hwspinlock_isbusy(unsigned int lock_id)
145 unsigned int status = 0;
146 struct sprd_hwspinlock_dev *sprd_hwlock;
148 if (!hwlocks[lock_id]){
149 printk(KERN_ERR "This hwspinlock is not register!\n");
153 sprd_hwlock = hwlock_to_sprdlock_dev(hwlocks[lock_id]);
155 printk(KERN_ERR "Can't find hwspinlock device!\n");
159 status = readl_relaxed((void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_TTLSTS));
162 return ((status & (1 << lock_id)) ? 1 : 0);
165 int sprd_hwspinlocks_isbusy(void)
169 for(id = 0; id < HWSPINLOCK_ID_TOTAL_NUMS; id++){
170 if(sprd_hwspinlock_isbusy(id) > 0)
176 int sprd_hwspinlock_master_id(unsigned int lock_id)
178 unsigned int master_id = 0;
179 struct sprd_hwspinlock_dev *sprd_hwlock;
181 if(!hwlocks[lock_id]){
182 printk(KERN_ERR "This hwspinlock is not register!\n");
186 sprd_hwlock = hwlock_to_sprdlock_dev(hwlocks[lock_id]);
188 printk(KERN_ERR "Can't find hwspinlock device!\n");
192 master_id = readl_relaxed((void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_MASTERID(lock_id)));
196 void hwspinlock_clear(unsigned int lock_id)
198 struct sprd_hwspinlock_dev *sprd_hwlock;
200 if(!hwlocks[lock_id]){
201 printk(KERN_ERR "This hwspinlock is not register!\n");
205 sprd_hwlock = hwlock_to_sprdlock_dev(hwlocks[lock_id]);
207 printk(KERN_ERR "Can't find hwspinlock device!\n");
210 /*setting the abnormal clear bit to 1 makes the corresponding
211 *lock to Not Taken state
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));
218 void hwspinlock_clear_all(void)
220 unsigned int lock_id = 0;
222 hwspinlock_clear(lock_id);
223 } while (lock_id++ < HWSPINLOCK_ID_TOTAL_NUMS);
226 static int sprd_check_hwspinlock_vid(struct hwspinlock *lock)
228 struct sprd_hwspinlock_dev *sprd_hwlock;
230 sprd_hwlock = hwlock_to_sprdlock_dev(lock);
232 printk(KERN_ERR "%s:Can't find hwspinlock device!\n",__func__);
236 /* for sharkl/sharkl64/whale project */
237 if (sprd_hwlock->hwspinlock_vid == 0x100 || sprd_hwlock->hwspinlock_vid == 0x200
238 || sprd_hwlock->hwspinlock_vid == 0x300){
241 pr_debug("Warning:hwlock version id is 0x%x!\n",sprd_hwlock->hwspinlock_vid);
246 static unsigned long sprd_hwspinlock_addr(unsigned int lock_id)
249 struct hwspinlock *lock;
251 if(lock_id >= HWSPINLOCK_ID_TOTAL_NUMS){
252 printk(KERN_ERR "Hwspinlock id is wrong!\n");
256 lock = hwlocks[lock_id];
258 printk(KERN_ERR "Call %s: can't find hwspinlock!\n",__func__);
262 addr = (unsigned long)lock->priv;
267 static int sprd_init_hwlocks(int hwlock_id)
269 struct hwspinlock **plock;
272 sprd_hwlocks_implemented(hwlock_id);
274 if (hwlock_id == AON_HWSPLOCK)
276 else if (hwlock_id == AP_HWSPLOCK)
279 i = HWSPINLOCK_ID_TOTAL_NUMS;
281 for (; i < HWSPINLOCK_ID_TOTAL_NUMS; ++i) {
282 if (hwlocks_implemented[i]) {
284 *plock = hwspin_lock_request_specific(i);
285 if (WARN_ON(IS_ERR_OR_NULL(*plock)))
288 pr_info("early alloc hwspinlock id %d\n",
289 hwspin_lock_get_id(*plock));
295 static unsigned int do_lock_key(struct hwspinlock *lock)
297 unsigned int key = THIS_PROCESSOR_KEY;
301 static int __hwspinlock_trylock(struct hwspinlock *lock)
303 void __iomem *addr = lock->priv;
305 if (sprd_check_hwspinlock_vid(lock)) {
306 if (!readl_relaxed(addr))
309 unsigned int key = do_lock_key(lock);
310 if (!(key ^ HWSPINLOCK_NOTTAKEN_V0))
312 if (HWSPINLOCK_NOTTAKEN_V0 == readl_relaxed(addr)) {
313 writel_relaxed(key, addr);
314 if (key == readl_relaxed(addr))
319 pr_debug("Hwspinlock [%d] lock failed!\n",hwlock_to_id(lock));
323 sprd_record_hwlock_sts(hwlock_to_id(lock), 1);
327 static void __hwspinlock_unlock(struct hwspinlock *lock)
329 void __iomem *lock_addr = lock->priv;
332 if (sprd_check_hwspinlock_vid(lock)) {
333 unlock_key = HWSPINLOCK_NOTTAKEN_V1;
335 unlock_key = HWSPINLOCK_NOTTAKEN_V0;
336 if (!(readl_relaxed(lock_addr) ^ unlock_key))
340 writel_relaxed(unlock_key, lock_addr);
341 sprd_record_hwlock_sts(hwlock_to_id(lock), 0);
345 * relax the interconnect while spinning on it.
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.
351 * The number below is taken from an hardware specs example,
352 * obviously it is somewhat arbitrary.
354 static void __hwspinlock_relax(struct hwspinlock *lock)
359 static const struct hwspinlock_ops sprd_hwspinlock_ops = {
360 .trylock = __hwspinlock_trylock,
361 .unlock = __hwspinlock_unlock,
362 .relax = __hwspinlock_relax,
365 static int sprd_hwspinlock_probe(struct platform_device *pdev)
367 struct hwspinlock *hwlock;
368 struct sprd_hwspinlock_dev *sprd_hwlock;
369 static int hwspinlock_exist_cnt = 0;
371 int i, ret, hwlock_id;
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");
380 ret = of_property_read_u32(pdev->dev.of_node,"hwspinlock_cnt",&num_locks);
382 printk(KERN_ERR "Hwspinlock get count failed!\n");
386 sprd_hwlock = devm_kzalloc(&pdev->dev, sizeof(struct sprd_hwspinlock_dev)
387 + num_locks * sizeof(*hwlock), GFP_KERNEL);
389 printk(KERN_ERR "Hwspinlock device alloc memory failed!\n");
393 /* intial the hwspinlock */
395 sprd_hwlock->hwspinlock_cnt = num_locks;
397 sprd_hwlock->hwspinlock_base = SPRD_HWSPINLOCK1_BASE;
398 else if (hwlock_id == 0)
399 sprd_hwlock->hwspinlock_base = SPRD_HWSPINLOCK0_BASE;
401 printk(KERN_ERR "Hwspinlock id is wrong!\n");
404 sprd_hwlock->hwspinlock_vid = readl_relaxed((void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_VERID));
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));
411 hwlock->priv = (void __iomem *)(sprd_hwlock->hwspinlock_base + HWSPINLOCK_TOKEN_V0(i));
415 * runtime PM will make sure the clock of this module is
416 * enabled if at least one lock is requested
418 platform_set_drvdata(pdev, sprd_hwlock);
419 pm_runtime_enable(&pdev->dev);
421 ret = hwspin_lock_register(&sprd_hwlock->bank, &pdev->dev, &sprd_hwspinlock_ops,
422 hwspinlock_exist_cnt, num_locks);
424 printk(KERN_ERR "Hwspinlock register failed!\n");
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));
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);
442 pm_runtime_disable(&pdev->dev);
446 static int sprd_hwspinlock_remove(struct platform_device *pdev)
448 struct sprd_hwspinlock_dev *sprd_hwlock = platform_get_drvdata(pdev);
451 ret = hwspin_lock_unregister(&sprd_hwlock->bank);
453 dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
457 pm_runtime_disable(&pdev->dev);
461 static const struct of_device_id sprd_hwspinlock_of_match[] = {
462 { .compatible = "sprd,sprd-hwspinlock", },
466 static struct platform_driver sprd_hwspinlock_driver = {
467 .probe = sprd_hwspinlock_probe,
468 .remove = sprd_hwspinlock_remove,
470 .name = "sprd_hwspinlock",
471 .owner = THIS_MODULE,
472 .of_match_table = of_match_ptr(sprd_hwspinlock_of_match),
476 static int __init sprd_hwspinlock_init(void)
478 return platform_driver_register(&sprd_hwspinlock_driver);
481 /* board init code might need to reserve hwspinlocks for predefined purposes */
482 postcore_initcall(sprd_hwspinlock_init);
484 static void __exit sprd_hwspinlock_exit(void)
486 platform_driver_unregister(&sprd_hwspinlock_driver);
489 module_exit(sprd_hwspinlock_exit);
491 static int remove_node(struct device_node *np)
495 ps = kzalloc(sizeof(*ps), GFP_KERNEL);
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));
508 int __init early_hwspinlocks_init(void)
510 struct device_node *np;
511 struct platform_device *pdev;
514 np = of_find_node_by_name(NULL, "hwspinlock1");
516 pr_warn("Can't get the hwspinlock1 node!\n");
520 pdev = of_platform_device_create(np, 0, NULL);
522 pr_warn("register hwspinlock1 failed!\n");
526 pr_info("SPRD register hwspinlock1 ok,hwspinlock1's name is %s!\n",pdev->name);
527 ret = remove_node(np);
531 MODULE_LICENSE("GPL v2");
532 MODULE_DESCRIPTION("Hardware spinlock driver for Spreadtrum");
533 MODULE_AUTHOR("baolin.wang <baolin.wang@spreadtrum.com>");