2017-11-03 04:38:07 +03:00
/*
* drivers / leds / leds - apu . c
* Copyright ( C ) 2017 Alan Mizrahi , alan at mizrahi dot com dot ve
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in the
* documentation and / or other materials provided with the distribution .
* 3. Neither the names of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission .
*
* Alternatively , this software may be distributed under the terms of the
* GNU General Public License ( " GPL " ) version 2 as published by the Free
* Software Foundation .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS "
* AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT , INDIRECT , INCIDENTAL , SPECIAL , EXEMPLARY , OR
* CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS
* INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
* CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE )
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*/
# include <linux/dmi.h>
# include <linux/err.h>
# include <linux/init.h>
# include <linux/io.h>
# include <linux/kernel.h>
# include <linux/leds.h>
# include <linux/module.h>
# include <linux/platform_device.h>
# define APU1_FCH_ACPI_MMIO_BASE 0xFED80000
# define APU1_FCH_GPIO_BASE (APU1_FCH_ACPI_MMIO_BASE + 0x01BD)
# define APU1_LEDON 0x08
# define APU1_LEDOFF 0xC8
# define APU1_NUM_GPIO 3
# define APU1_IOSIZE sizeof(u8)
/* LED access parameters */
struct apu_param {
void __iomem * addr ; /* for ioread/iowrite */
} ;
/* LED private data */
struct apu_led_priv {
struct led_classdev cdev ;
struct apu_param param ;
} ;
# define cdev_to_priv(c) container_of(c, struct apu_led_priv, cdev)
/* LED profile */
struct apu_led_profile {
const char * name ;
enum led_brightness brightness ;
unsigned long offset ; /* for devm_ioremap */
} ;
/* Supported platform types */
enum apu_led_platform_types {
APU1_LED_PLATFORM ,
} ;
struct apu_led_pdata {
struct platform_device * pdev ;
struct apu_led_priv * pled ;
const struct apu_led_profile * profile ;
enum apu_led_platform_types platform ;
int num_led_instances ;
int iosize ; /* for devm_ioremap() */
spinlock_t lock ;
} ;
static struct apu_led_pdata * apu_led ;
static const struct apu_led_profile apu1_led_profile [ ] = {
{ " apu:green:1 " , LED_ON , APU1_FCH_GPIO_BASE + 0 * APU1_IOSIZE } ,
{ " apu:green:2 " , LED_OFF , APU1_FCH_GPIO_BASE + 1 * APU1_IOSIZE } ,
{ " apu:green:3 " , LED_OFF , APU1_FCH_GPIO_BASE + 2 * APU1_IOSIZE } ,
} ;
static const struct dmi_system_id apu_led_dmi_table [ ] __initconst = {
{
. ident = " apu " ,
. matches = {
DMI_MATCH ( DMI_SYS_VENDOR , " PC Engines " ) ,
DMI_MATCH ( DMI_PRODUCT_NAME , " APU " )
}
} ,
{ }
} ;
MODULE_DEVICE_TABLE ( dmi , apu_led_dmi_table ) ;
static void apu1_led_brightness_set ( struct led_classdev * led , enum led_brightness value )
{
struct apu_led_priv * pled = cdev_to_priv ( led ) ;
spin_lock ( & apu_led - > lock ) ;
iowrite8 ( value ? APU1_LEDON : APU1_LEDOFF , pled - > param . addr ) ;
spin_unlock ( & apu_led - > lock ) ;
}
static int apu_led_config ( struct device * dev , struct apu_led_pdata * apuld )
{
int i ;
int err ;
treewide: devm_kzalloc() -> devm_kcalloc()
The devm_kzalloc() function has a 2-factor argument form, devm_kcalloc().
This patch replaces cases of:
devm_kzalloc(handle, a * b, gfp)
with:
devm_kcalloc(handle, a * b, gfp)
as well as handling cases of:
devm_kzalloc(handle, a * b * c, gfp)
with:
devm_kzalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kcalloc(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kzalloc(handle, 4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kcalloc..." instead of "= devm_kcalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kzalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kzalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kzalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kzalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kzalloc(HANDLE,
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kzalloc(HANDLE,
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kzalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kzalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kzalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kzalloc(HANDLE, C1 * C2, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kzalloc
+ devm_kcalloc
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:07:58 +03:00
apu_led - > pled = devm_kcalloc ( dev ,
apu_led - > num_led_instances , sizeof ( struct apu_led_priv ) ,
2017-11-03 04:38:07 +03:00
GFP_KERNEL ) ;
if ( ! apu_led - > pled )
return - ENOMEM ;
for ( i = 0 ; i < apu_led - > num_led_instances ; i + + ) {
struct apu_led_priv * pled = & apu_led - > pled [ i ] ;
struct led_classdev * led_cdev = & pled - > cdev ;
led_cdev - > name = apu_led - > profile [ i ] . name ;
led_cdev - > brightness = apu_led - > profile [ i ] . brightness ;
led_cdev - > max_brightness = 1 ;
led_cdev - > flags = LED_CORE_SUSPENDRESUME ;
if ( apu_led - > platform = = APU1_LED_PLATFORM )
led_cdev - > brightness_set = apu1_led_brightness_set ;
pled - > param . addr = devm_ioremap ( dev ,
apu_led - > profile [ i ] . offset , apu_led - > iosize ) ;
if ( ! pled - > param . addr ) {
err = - ENOMEM ;
goto error ;
}
err = led_classdev_register ( dev , led_cdev ) ;
if ( err )
goto error ;
led_cdev - > brightness_set ( led_cdev , apu_led - > profile [ i ] . brightness ) ;
}
return 0 ;
error :
while ( i - - > 0 )
led_classdev_unregister ( & apu_led - > pled [ i ] . cdev ) ;
return err ;
}
static int __init apu_led_probe ( struct platform_device * pdev )
{
apu_led = devm_kzalloc ( & pdev - > dev , sizeof ( * apu_led ) , GFP_KERNEL ) ;
if ( ! apu_led )
return - ENOMEM ;
apu_led - > pdev = pdev ;
2019-07-15 17:57:28 +03:00
apu_led - > profile = apu1_led_profile ;
apu_led - > platform = APU1_LED_PLATFORM ;
apu_led - > num_led_instances = ARRAY_SIZE ( apu1_led_profile ) ;
apu_led - > iosize = APU1_IOSIZE ;
2017-11-03 04:38:07 +03:00
spin_lock_init ( & apu_led - > lock ) ;
return apu_led_config ( & pdev - > dev , apu_led ) ;
}
static struct platform_driver apu_led_driver = {
. driver = {
. name = KBUILD_MODNAME ,
} ,
} ;
static int __init apu_led_init ( void )
{
struct platform_device * pdev ;
int err ;
if ( ! dmi_match ( DMI_SYS_VENDOR , " PC Engines " ) ) {
pr_err ( " No PC Engines board detected \n " ) ;
return - ENODEV ;
}
2019-07-15 17:57:28 +03:00
if ( ! ( dmi_match ( DMI_PRODUCT_NAME , " APU " ) ) ) {
2017-11-03 04:38:07 +03:00
pr_err ( " Unknown PC Engines board: %s \n " ,
dmi_get_system_info ( DMI_PRODUCT_NAME ) ) ;
return - ENODEV ;
}
pdev = platform_device_register_simple ( KBUILD_MODNAME , - 1 , NULL , 0 ) ;
if ( IS_ERR ( pdev ) ) {
pr_err ( " Device allocation failed \n " ) ;
return PTR_ERR ( pdev ) ;
}
err = platform_driver_probe ( & apu_led_driver , apu_led_probe ) ;
if ( err ) {
pr_err ( " Probe platform driver failed \n " ) ;
platform_device_unregister ( pdev ) ;
}
return err ;
}
static void __exit apu_led_exit ( void )
{
int i ;
for ( i = 0 ; i < apu_led - > num_led_instances ; i + + )
led_classdev_unregister ( & apu_led - > pled [ i ] . cdev ) ;
platform_device_unregister ( apu_led - > pdev ) ;
platform_driver_unregister ( & apu_led_driver ) ;
}
module_init ( apu_led_init ) ;
module_exit ( apu_led_exit ) ;
MODULE_AUTHOR ( " Alan Mizrahi " ) ;
2019-07-15 17:57:28 +03:00
MODULE_DESCRIPTION ( " PC Engines APU1 front LED driver " ) ;
2017-11-03 04:38:07 +03:00
MODULE_LICENSE ( " GPL v2 " ) ;
MODULE_ALIAS ( " platform:leds_apu " ) ;