This source file includes following definitions.
- u8500_hsem_trylock
- u8500_hsem_unlock
- u8500_hsem_relax
- u8500_hsem_probe
- u8500_hsem_remove
- u8500_hsem_init
- u8500_hsem_exit
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 #include <linux/module.h>
  17 #include <linux/delay.h>
  18 #include <linux/io.h>
  19 #include <linux/pm_runtime.h>
  20 #include <linux/slab.h>
  21 #include <linux/spinlock.h>
  22 #include <linux/hwspinlock.h>
  23 #include <linux/platform_device.h>
  24 
  25 #include "hwspinlock_internal.h"
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 #define U8500_MAX_SEMAPHORE             32      
  35 #define RESET_SEMAPHORE                 (0)     
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 #define HSEM_MASTER_ID                  0x01
  44 
  45 #define HSEM_REGISTER_OFFSET            0x08
  46 
  47 #define HSEM_CTRL_REG                   0x00
  48 #define HSEM_ICRALL                     0x90
  49 #define HSEM_PROTOCOL_1                 0x01
  50 
  51 static int u8500_hsem_trylock(struct hwspinlock *lock)
  52 {
  53         void __iomem *lock_addr = lock->priv;
  54 
  55         writel(HSEM_MASTER_ID, lock_addr);
  56 
  57         
  58 
  59 
  60 
  61         return (HSEM_MASTER_ID == (0x0F & readl(lock_addr)));
  62 }
  63 
  64 static void u8500_hsem_unlock(struct hwspinlock *lock)
  65 {
  66         void __iomem *lock_addr = lock->priv;
  67 
  68         
  69         writel(RESET_SEMAPHORE, lock_addr);
  70 }
  71 
  72 
  73 
  74 
  75 static void u8500_hsem_relax(struct hwspinlock *lock)
  76 {
  77         ndelay(50);
  78 }
  79 
  80 static const struct hwspinlock_ops u8500_hwspinlock_ops = {
  81         .trylock        = u8500_hsem_trylock,
  82         .unlock         = u8500_hsem_unlock,
  83         .relax          = u8500_hsem_relax,
  84 };
  85 
  86 static int u8500_hsem_probe(struct platform_device *pdev)
  87 {
  88         struct hwspinlock_pdata *pdata = pdev->dev.platform_data;
  89         struct hwspinlock_device *bank;
  90         struct hwspinlock *hwlock;
  91         struct resource *res;
  92         void __iomem *io_base;
  93         int i, ret, num_locks = U8500_MAX_SEMAPHORE;
  94         ulong val;
  95 
  96         if (!pdata)
  97                 return -ENODEV;
  98 
  99         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 100         if (!res)
 101                 return -ENODEV;
 102 
 103         io_base = ioremap(res->start, resource_size(res));
 104         if (!io_base)
 105                 return -ENOMEM;
 106 
 107         
 108         val = readl(io_base + HSEM_CTRL_REG);
 109         writel((val & ~HSEM_PROTOCOL_1), io_base + HSEM_CTRL_REG);
 110 
 111         
 112         writel(0xFFFF, io_base + HSEM_ICRALL);
 113 
 114         bank = kzalloc(struct_size(bank, lock, num_locks), GFP_KERNEL);
 115         if (!bank) {
 116                 ret = -ENOMEM;
 117                 goto iounmap_base;
 118         }
 119 
 120         platform_set_drvdata(pdev, bank);
 121 
 122         for (i = 0, hwlock = &bank->lock[0]; i < num_locks; i++, hwlock++)
 123                 hwlock->priv = io_base + HSEM_REGISTER_OFFSET + sizeof(u32) * i;
 124 
 125         
 126         pm_runtime_enable(&pdev->dev);
 127 
 128         ret = hwspin_lock_register(bank, &pdev->dev, &u8500_hwspinlock_ops,
 129                                                 pdata->base_id, num_locks);
 130         if (ret)
 131                 goto reg_fail;
 132 
 133         return 0;
 134 
 135 reg_fail:
 136         pm_runtime_disable(&pdev->dev);
 137         kfree(bank);
 138 iounmap_base:
 139         iounmap(io_base);
 140         return ret;
 141 }
 142 
 143 static int u8500_hsem_remove(struct platform_device *pdev)
 144 {
 145         struct hwspinlock_device *bank = platform_get_drvdata(pdev);
 146         void __iomem *io_base = bank->lock[0].priv - HSEM_REGISTER_OFFSET;
 147         int ret;
 148 
 149         
 150         writel(0xFFFF, io_base + HSEM_ICRALL);
 151 
 152         ret = hwspin_lock_unregister(bank);
 153         if (ret) {
 154                 dev_err(&pdev->dev, "%s failed: %d\n", __func__, ret);
 155                 return ret;
 156         }
 157 
 158         pm_runtime_disable(&pdev->dev);
 159         iounmap(io_base);
 160         kfree(bank);
 161 
 162         return 0;
 163 }
 164 
 165 static struct platform_driver u8500_hsem_driver = {
 166         .probe          = u8500_hsem_probe,
 167         .remove         = u8500_hsem_remove,
 168         .driver         = {
 169                 .name   = "u8500_hsem",
 170         },
 171 };
 172 
 173 static int __init u8500_hsem_init(void)
 174 {
 175         return platform_driver_register(&u8500_hsem_driver);
 176 }
 177 
 178 postcore_initcall(u8500_hsem_init);
 179 
 180 static void __exit u8500_hsem_exit(void)
 181 {
 182         platform_driver_unregister(&u8500_hsem_driver);
 183 }
 184 module_exit(u8500_hsem_exit);
 185 
 186 MODULE_LICENSE("GPL v2");
 187 MODULE_DESCRIPTION("Hardware Spinlock driver for u8500");
 188 MODULE_AUTHOR("Mathieu Poirier <mathieu.poirier@linaro.org>");