root/drivers/hwspinlock/sirf_hwspinlock.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sirf_hwspinlock_trylock
  2. sirf_hwspinlock_unlock
  3. sirf_hwspinlock_probe
  4. sirf_hwspinlock_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * SIRF hardware spinlock driver
   4  *
   5  * Copyright (c) 2015 Cambridge Silicon Radio Limited, a CSR plc group company.
   6  */
   7 
   8 #include <linux/kernel.h>
   9 #include <linux/module.h>
  10 #include <linux/device.h>
  11 #include <linux/io.h>
  12 #include <linux/pm_runtime.h>
  13 #include <linux/slab.h>
  14 #include <linux/spinlock.h>
  15 #include <linux/hwspinlock.h>
  16 #include <linux/platform_device.h>
  17 #include <linux/of.h>
  18 #include <linux/of_address.h>
  19 
  20 #include "hwspinlock_internal.h"
  21 
  22 struct sirf_hwspinlock {
  23         void __iomem *io_base;
  24         struct hwspinlock_device bank;
  25 };
  26 
  27 /* Number of Hardware Spinlocks*/
  28 #define HW_SPINLOCK_NUMBER      30
  29 
  30 /* Hardware spinlock register offsets */
  31 #define HW_SPINLOCK_BASE        0x404
  32 #define HW_SPINLOCK_OFFSET(x)   (HW_SPINLOCK_BASE + 0x4 * (x))
  33 
  34 static int sirf_hwspinlock_trylock(struct hwspinlock *lock)
  35 {
  36         void __iomem *lock_addr = lock->priv;
  37 
  38         /* attempt to acquire the lock by reading value == 1 from it */
  39         return !!readl(lock_addr);
  40 }
  41 
  42 static void sirf_hwspinlock_unlock(struct hwspinlock *lock)
  43 {
  44         void __iomem *lock_addr = lock->priv;
  45 
  46         /* release the lock by writing 0 to it */
  47         writel(0, lock_addr);
  48 }
  49 
  50 static const struct hwspinlock_ops sirf_hwspinlock_ops = {
  51         .trylock = sirf_hwspinlock_trylock,
  52         .unlock = sirf_hwspinlock_unlock,
  53 };
  54 
  55 static int sirf_hwspinlock_probe(struct platform_device *pdev)
  56 {
  57         struct sirf_hwspinlock *hwspin;
  58         struct hwspinlock *hwlock;
  59         int idx, ret;
  60 
  61         if (!pdev->dev.of_node)
  62                 return -ENODEV;
  63 
  64         hwspin = devm_kzalloc(&pdev->dev,
  65                               struct_size(hwspin, bank.lock,
  66                                           HW_SPINLOCK_NUMBER),
  67                               GFP_KERNEL);
  68         if (!hwspin)
  69                 return -ENOMEM;
  70 
  71         /* retrieve io base */
  72         hwspin->io_base = of_iomap(pdev->dev.of_node, 0);
  73         if (!hwspin->io_base)
  74                 return -ENOMEM;
  75 
  76         for (idx = 0; idx < HW_SPINLOCK_NUMBER; idx++) {
  77                 hwlock = &hwspin->bank.lock[idx];
  78                 hwlock->priv = hwspin->io_base + HW_SPINLOCK_OFFSET(idx);
  79         }
  80 
  81         platform_set_drvdata(pdev, hwspin);
  82 
  83         pm_runtime_enable(&pdev->dev);
  84 
  85         ret = hwspin_lock_register(&hwspin->bank, &pdev->dev,
  86                                    &sirf_hwspinlock_ops, 0,
  87                                    HW_SPINLOCK_NUMBER);
  88         if (ret)
  89                 goto reg_failed;
  90 
  91         return 0;
  92 
  93 reg_failed:
  94         pm_runtime_disable(&pdev->dev);
  95         iounmap(hwspin->io_base);
  96 
  97         return ret;
  98 }
  99 
 100 static int sirf_hwspinlock_remove(struct platform_device *pdev)
 101 {
 102         struct sirf_hwspinlock *hwspin = platform_get_drvdata(pdev);
 103         int ret;
 104 
 105         ret = hwspin_lock_unregister(&hwspin->bank);
 106         if (ret) {
 107                 dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
 108                 return ret;
 109         }
 110 
 111         pm_runtime_disable(&pdev->dev);
 112 
 113         iounmap(hwspin->io_base);
 114 
 115         return 0;
 116 }
 117 
 118 static const struct of_device_id sirf_hwpinlock_ids[] = {
 119         { .compatible = "sirf,hwspinlock", },
 120         {},
 121 };
 122 MODULE_DEVICE_TABLE(of, sirf_hwpinlock_ids);
 123 
 124 static struct platform_driver sirf_hwspinlock_driver = {
 125         .probe = sirf_hwspinlock_probe,
 126         .remove = sirf_hwspinlock_remove,
 127         .driver = {
 128                 .name = "atlas7_hwspinlock",
 129                 .of_match_table = of_match_ptr(sirf_hwpinlock_ids),
 130         },
 131 };
 132 
 133 module_platform_driver(sirf_hwspinlock_driver);
 134 
 135 MODULE_LICENSE("GPL v2");
 136 MODULE_DESCRIPTION("SIRF Hardware spinlock driver");
 137 MODULE_AUTHOR("Wei Chen <wei.chen@csr.com>");

/* [<][>][^][v][top][bottom][index][help] */