2018-05-11 20:03:19 +03:00
// SPDX-License-Identifier: GPL-2.0
2015-05-26 11:28:29 +03:00
/*
* SIRF hardware spinlock driver
*
* Copyright ( c ) 2015 Cambridge Silicon Radio Limited , a CSR plc group company .
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/device.h>
# include <linux/io.h>
# include <linux/slab.h>
# include <linux/spinlock.h>
# include <linux/hwspinlock.h>
# include <linux/platform_device.h>
# include <linux/of.h>
# include <linux/of_address.h>
# include "hwspinlock_internal.h"
struct sirf_hwspinlock {
void __iomem * io_base ;
struct hwspinlock_device bank ;
} ;
/* Number of Hardware Spinlocks*/
# define HW_SPINLOCK_NUMBER 30
/* Hardware spinlock register offsets */
# define HW_SPINLOCK_BASE 0x404
# define HW_SPINLOCK_OFFSET(x) (HW_SPINLOCK_BASE + 0x4 * (x))
static int sirf_hwspinlock_trylock ( struct hwspinlock * lock )
{
void __iomem * lock_addr = lock - > priv ;
/* attempt to acquire the lock by reading value == 1 from it */
return ! ! readl ( lock_addr ) ;
}
static void sirf_hwspinlock_unlock ( struct hwspinlock * lock )
{
void __iomem * lock_addr = lock - > priv ;
/* release the lock by writing 0 to it */
writel ( 0 , lock_addr ) ;
}
static const struct hwspinlock_ops sirf_hwspinlock_ops = {
. trylock = sirf_hwspinlock_trylock ,
. unlock = sirf_hwspinlock_unlock ,
} ;
static int sirf_hwspinlock_probe ( struct platform_device * pdev )
{
struct sirf_hwspinlock * hwspin ;
struct hwspinlock * hwlock ;
2020-01-08 06:23:45 +03:00
int idx ;
2015-05-26 11:28:29 +03:00
if ( ! pdev - > dev . of_node )
return - ENODEV ;
treewide: Use struct_size() for devm_kmalloc() and friends
Replaces open-coded struct size calculations with struct_size() for
devm_*, f2fs_*, and sock_* allocations. Automatically generated (and
manually adjusted) from the following Coccinelle script:
// Direct reference to struct field.
@@
identifier alloc =~ "devm_kmalloc|devm_kzalloc|sock_kmalloc|f2fs_kmalloc|f2fs_kzalloc";
expression HANDLE;
expression GFP;
identifier VAR, ELEMENT;
expression COUNT;
@@
- alloc(HANDLE, sizeof(*VAR) + COUNT * sizeof(*VAR->ELEMENT), GFP)
+ alloc(HANDLE, struct_size(VAR, ELEMENT, COUNT), GFP)
// mr = kzalloc(sizeof(*mr) + m * sizeof(mr->map[0]), GFP_KERNEL);
@@
identifier alloc =~ "devm_kmalloc|devm_kzalloc|sock_kmalloc|f2fs_kmalloc|f2fs_kzalloc";
expression HANDLE;
expression GFP;
identifier VAR, ELEMENT;
expression COUNT;
@@
- alloc(HANDLE, sizeof(*VAR) + COUNT * sizeof(VAR->ELEMENT[0]), GFP)
+ alloc(HANDLE, struct_size(VAR, ELEMENT, COUNT), GFP)
// Same pattern, but can't trivially locate the trailing element name,
// or variable name.
@@
identifier alloc =~ "devm_kmalloc|devm_kzalloc|sock_kmalloc|f2fs_kmalloc|f2fs_kzalloc";
expression HANDLE;
expression GFP;
expression SOMETHING, COUNT, ELEMENT;
@@
- alloc(HANDLE, sizeof(SOMETHING) + COUNT * sizeof(ELEMENT), GFP)
+ alloc(HANDLE, CHECKME_struct_size(&SOMETHING, ELEMENT, COUNT), GFP)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-05-09 02:08:53 +03:00
hwspin = devm_kzalloc ( & pdev - > dev ,
struct_size ( hwspin , bank . lock ,
HW_SPINLOCK_NUMBER ) ,
GFP_KERNEL ) ;
2015-05-26 11:28:29 +03:00
if ( ! hwspin )
return - ENOMEM ;
/* retrieve io base */
2020-01-08 06:23:44 +03:00
hwspin - > io_base = devm_platform_ioremap_resource ( pdev , 0 ) ;
if ( IS_ERR ( hwspin - > io_base ) )
return PTR_ERR ( hwspin - > io_base ) ;
2015-05-26 11:28:29 +03:00
for ( idx = 0 ; idx < HW_SPINLOCK_NUMBER ; idx + + ) {
hwlock = & hwspin - > bank . lock [ idx ] ;
hwlock - > priv = hwspin - > io_base + HW_SPINLOCK_OFFSET ( idx ) ;
}
platform_set_drvdata ( pdev , hwspin ) ;
2020-01-08 06:23:46 +03:00
return devm_hwspin_lock_register ( & pdev - > dev , & hwspin - > bank ,
& sirf_hwspinlock_ops , 0 ,
HW_SPINLOCK_NUMBER ) ;
2015-05-26 11:28:29 +03:00
}
static const struct of_device_id sirf_hwpinlock_ids [ ] = {
{ . compatible = " sirf,hwspinlock " , } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , sirf_hwpinlock_ids ) ;
static struct platform_driver sirf_hwspinlock_driver = {
. probe = sirf_hwspinlock_probe ,
. driver = {
. name = " atlas7_hwspinlock " ,
. of_match_table = of_match_ptr ( sirf_hwpinlock_ids ) ,
} ,
} ;
module_platform_driver ( sirf_hwspinlock_driver ) ;
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_DESCRIPTION ( " SIRF Hardware spinlock driver " ) ;
MODULE_AUTHOR ( " Wei Chen <wei.chen@csr.com> " ) ;