2011-02-17 18:52:03 +01:00
|
|
|
/*
|
|
|
|
* Hardware spinlocks internal header
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
|
|
|
|
*
|
|
|
|
* Contact: Ohad Ben-Cohen <ohad@wizery.com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms of the GNU General Public License version 2 as published
|
|
|
|
* by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __HWSPINLOCK_HWSPINLOCK_H
|
|
|
|
#define __HWSPINLOCK_HWSPINLOCK_H
|
|
|
|
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/device.h>
|
|
|
|
|
hwspinlock/core: register a bank of hwspinlocks in a single API call
Hardware Spinlock devices usually contain numerous locks (known
devices today support between 32 to 256 locks).
Originally hwspinlock core required drivers to register (and later,
when needed, unregister) each lock separately.
That worked, but required hwspinlocks drivers to do a bit extra work
when they were probed/removed.
This patch changes hwspin_lock_{un}register() to allow a bank of
hwspinlocks to be {un}registered in a single invocation.
A new 'struct hwspinlock_device', which contains an array of 'struct
hwspinlock's is now being passed to the core upon registration (so
instead of wrapping each struct hwspinlock, a priv member has been added
to allow drivers to piggyback their private data with each hwspinlock).
While at it, several per-lock members were moved to be per-device:
1. struct device *dev
2. struct hwspinlock_ops *ops
In addition, now that the array of locks is handled by the core,
there's no reason to maintain a per-lock 'int id' member: the id of the
lock anyway equals to its index in the bank's array plus the bank's
base_id.
Remove this per-lock id member too, and instead use a simple pointers
arithmetic to derive it.
As a result of this change, hwspinlocks drivers are now simpler and smaller
(about %20 code reduction) and the memory footprint of the hwspinlock
framework is reduced.
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2011-09-06 14:39:21 +02:00
|
|
|
struct hwspinlock_device;
|
|
|
|
|
2011-02-17 18:52:03 +01:00
|
|
|
/**
|
|
|
|
* struct hwspinlock_ops - platform-specific hwspinlock handlers
|
|
|
|
*
|
|
|
|
* @trylock: make a single attempt to take the lock. returns 0 on
|
|
|
|
* failure and true on success. may _not_ sleep.
|
|
|
|
* @unlock: release the lock. always succeed. may _not_ sleep.
|
|
|
|
* @relax: optional, platform-specific relax handler, called by hwspinlock
|
|
|
|
* core while spinning on a lock, between two successive
|
|
|
|
* invocations of @trylock. may _not_ sleep.
|
|
|
|
*/
|
|
|
|
struct hwspinlock_ops {
|
|
|
|
int (*trylock)(struct hwspinlock *lock);
|
|
|
|
void (*unlock)(struct hwspinlock *lock);
|
|
|
|
void (*relax)(struct hwspinlock *lock);
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct hwspinlock - this struct represents a single hwspinlock instance
|
hwspinlock/core: register a bank of hwspinlocks in a single API call
Hardware Spinlock devices usually contain numerous locks (known
devices today support between 32 to 256 locks).
Originally hwspinlock core required drivers to register (and later,
when needed, unregister) each lock separately.
That worked, but required hwspinlocks drivers to do a bit extra work
when they were probed/removed.
This patch changes hwspin_lock_{un}register() to allow a bank of
hwspinlocks to be {un}registered in a single invocation.
A new 'struct hwspinlock_device', which contains an array of 'struct
hwspinlock's is now being passed to the core upon registration (so
instead of wrapping each struct hwspinlock, a priv member has been added
to allow drivers to piggyback their private data with each hwspinlock).
While at it, several per-lock members were moved to be per-device:
1. struct device *dev
2. struct hwspinlock_ops *ops
In addition, now that the array of locks is handled by the core,
there's no reason to maintain a per-lock 'int id' member: the id of the
lock anyway equals to its index in the bank's array plus the bank's
base_id.
Remove this per-lock id member too, and instead use a simple pointers
arithmetic to derive it.
As a result of this change, hwspinlocks drivers are now simpler and smaller
(about %20 code reduction) and the memory footprint of the hwspinlock
framework is reduced.
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2011-09-06 14:39:21 +02:00
|
|
|
* @bank: the hwspinlock_device structure which owns this lock
|
2011-02-17 18:52:03 +01:00
|
|
|
* @lock: initialized and used by hwspinlock core
|
hwspinlock/core: register a bank of hwspinlocks in a single API call
Hardware Spinlock devices usually contain numerous locks (known
devices today support between 32 to 256 locks).
Originally hwspinlock core required drivers to register (and later,
when needed, unregister) each lock separately.
That worked, but required hwspinlocks drivers to do a bit extra work
when they were probed/removed.
This patch changes hwspin_lock_{un}register() to allow a bank of
hwspinlocks to be {un}registered in a single invocation.
A new 'struct hwspinlock_device', which contains an array of 'struct
hwspinlock's is now being passed to the core upon registration (so
instead of wrapping each struct hwspinlock, a priv member has been added
to allow drivers to piggyback their private data with each hwspinlock).
While at it, several per-lock members were moved to be per-device:
1. struct device *dev
2. struct hwspinlock_ops *ops
In addition, now that the array of locks is handled by the core,
there's no reason to maintain a per-lock 'int id' member: the id of the
lock anyway equals to its index in the bank's array plus the bank's
base_id.
Remove this per-lock id member too, and instead use a simple pointers
arithmetic to derive it.
As a result of this change, hwspinlocks drivers are now simpler and smaller
(about %20 code reduction) and the memory footprint of the hwspinlock
framework is reduced.
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2011-09-06 14:39:21 +02:00
|
|
|
* @priv: private data, owned by the underlying platform-specific hwspinlock drv
|
2011-02-17 18:52:03 +01:00
|
|
|
*/
|
|
|
|
struct hwspinlock {
|
hwspinlock/core: register a bank of hwspinlocks in a single API call
Hardware Spinlock devices usually contain numerous locks (known
devices today support between 32 to 256 locks).
Originally hwspinlock core required drivers to register (and later,
when needed, unregister) each lock separately.
That worked, but required hwspinlocks drivers to do a bit extra work
when they were probed/removed.
This patch changes hwspin_lock_{un}register() to allow a bank of
hwspinlocks to be {un}registered in a single invocation.
A new 'struct hwspinlock_device', which contains an array of 'struct
hwspinlock's is now being passed to the core upon registration (so
instead of wrapping each struct hwspinlock, a priv member has been added
to allow drivers to piggyback their private data with each hwspinlock).
While at it, several per-lock members were moved to be per-device:
1. struct device *dev
2. struct hwspinlock_ops *ops
In addition, now that the array of locks is handled by the core,
there's no reason to maintain a per-lock 'int id' member: the id of the
lock anyway equals to its index in the bank's array plus the bank's
base_id.
Remove this per-lock id member too, and instead use a simple pointers
arithmetic to derive it.
As a result of this change, hwspinlocks drivers are now simpler and smaller
(about %20 code reduction) and the memory footprint of the hwspinlock
framework is reduced.
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2011-09-06 14:39:21 +02:00
|
|
|
struct hwspinlock_device *bank;
|
|
|
|
spinlock_t lock;
|
|
|
|
void *priv;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* struct hwspinlock_device - a device which usually spans numerous hwspinlocks
|
|
|
|
* @dev: underlying device, will be used to invoke runtime PM api
|
|
|
|
* @ops: platform-specific hwspinlock handlers
|
|
|
|
* @base_id: id index of the first lock in this device
|
|
|
|
* @num_locks: number of locks in this device
|
|
|
|
* @lock: dynamically allocated array of 'struct hwspinlock'
|
|
|
|
*/
|
|
|
|
struct hwspinlock_device {
|
2011-02-17 18:52:03 +01:00
|
|
|
struct device *dev;
|
|
|
|
const struct hwspinlock_ops *ops;
|
hwspinlock/core: register a bank of hwspinlocks in a single API call
Hardware Spinlock devices usually contain numerous locks (known
devices today support between 32 to 256 locks).
Originally hwspinlock core required drivers to register (and later,
when needed, unregister) each lock separately.
That worked, but required hwspinlocks drivers to do a bit extra work
when they were probed/removed.
This patch changes hwspin_lock_{un}register() to allow a bank of
hwspinlocks to be {un}registered in a single invocation.
A new 'struct hwspinlock_device', which contains an array of 'struct
hwspinlock's is now being passed to the core upon registration (so
instead of wrapping each struct hwspinlock, a priv member has been added
to allow drivers to piggyback their private data with each hwspinlock).
While at it, several per-lock members were moved to be per-device:
1. struct device *dev
2. struct hwspinlock_ops *ops
In addition, now that the array of locks is handled by the core,
there's no reason to maintain a per-lock 'int id' member: the id of the
lock anyway equals to its index in the bank's array plus the bank's
base_id.
Remove this per-lock id member too, and instead use a simple pointers
arithmetic to derive it.
As a result of this change, hwspinlocks drivers are now simpler and smaller
(about %20 code reduction) and the memory footprint of the hwspinlock
framework is reduced.
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2011-09-06 14:39:21 +02:00
|
|
|
int base_id;
|
|
|
|
int num_locks;
|
|
|
|
struct hwspinlock lock[0];
|
2011-02-17 18:52:03 +01:00
|
|
|
};
|
|
|
|
|
hwspinlock/core: register a bank of hwspinlocks in a single API call
Hardware Spinlock devices usually contain numerous locks (known
devices today support between 32 to 256 locks).
Originally hwspinlock core required drivers to register (and later,
when needed, unregister) each lock separately.
That worked, but required hwspinlocks drivers to do a bit extra work
when they were probed/removed.
This patch changes hwspin_lock_{un}register() to allow a bank of
hwspinlocks to be {un}registered in a single invocation.
A new 'struct hwspinlock_device', which contains an array of 'struct
hwspinlock's is now being passed to the core upon registration (so
instead of wrapping each struct hwspinlock, a priv member has been added
to allow drivers to piggyback their private data with each hwspinlock).
While at it, several per-lock members were moved to be per-device:
1. struct device *dev
2. struct hwspinlock_ops *ops
In addition, now that the array of locks is handled by the core,
there's no reason to maintain a per-lock 'int id' member: the id of the
lock anyway equals to its index in the bank's array plus the bank's
base_id.
Remove this per-lock id member too, and instead use a simple pointers
arithmetic to derive it.
As a result of this change, hwspinlocks drivers are now simpler and smaller
(about %20 code reduction) and the memory footprint of the hwspinlock
framework is reduced.
Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
2011-09-06 14:39:21 +02:00
|
|
|
static inline int hwlock_to_id(struct hwspinlock *hwlock)
|
|
|
|
{
|
|
|
|
int local_id = hwlock - &hwlock->bank->lock[0];
|
|
|
|
|
|
|
|
return hwlock->bank->base_id + local_id;
|
|
|
|
}
|
|
|
|
|
2011-02-17 18:52:03 +01:00
|
|
|
#endif /* __HWSPINLOCK_HWSPINLOCK_H */
|