// SPDX-License-Identifier: GPL-2.0-only
/*
* Shared helpers to register GPIO - connected buttons and LEDs
* on AMD Geode boards .
*/
#include <linux/err.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/property.h>
#include <linux/input.h>
#include <linux/leds.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "geode-common.h"
static const struct software_node geode_gpiochip_node = {
.name = "cs5535-gpio" ,
};
static const struct property_entry geode_gpio_keys_props[] = {
PROPERTY_ENTRY_U32("poll-interval" , 20 ),
{ }
};
static const struct software_node geode_gpio_keys_node = {
.name = "geode-gpio-keys" ,
.properties = geode_gpio_keys_props,
};
static struct property_entry geode_restart_key_props[] = {
{ /* Placeholder for GPIO property */ },
PROPERTY_ENTRY_U32("linux,code" , KEY_RESTART),
PROPERTY_ENTRY_STRING("label" , "Reset button" ),
PROPERTY_ENTRY_U32("debounce-interval" , 100 ),
{ }
};
static const struct software_node geode_restart_key_node = {
.parent = &geode_gpio_keys_node,
.properties = geode_restart_key_props,
};
static const struct software_node *geode_gpio_keys_swnodes[] __initconst = {
&geode_gpiochip_node,
&geode_gpio_keys_node,
&geode_restart_key_node,
NULL
};
/*
* Creates gpio - keys - polled device for the restart key .
*
* Note that it needs to be called first , before geode_create_leds ( ) ,
* because it registers gpiochip software node used by both gpio - keys and
* leds - gpio devices .
*/
int __init geode_create_restart_key(unsigned int pin)
{
struct platform_device_info keys_info = {
.name = "gpio-keys-polled" ,
.id = 1 ,
};
struct platform_device *pd;
int err;
geode_restart_key_props[0 ] = PROPERTY_ENTRY_GPIO("gpios" ,
&geode_gpiochip_node,
pin, GPIO_ACTIVE_LOW);
err = software_node_register_node_group(geode_gpio_keys_swnodes);
if (err) {
pr_err("failed to register gpio-keys software nodes: %d\n" , err);
return err;
}
keys_info.fwnode = software_node_fwnode(&geode_gpio_keys_node);
pd = platform_device_register_full(&keys_info);
err = PTR_ERR_OR_ZERO(pd);
if (err) {
pr_err("failed to create gpio-keys device: %d\n" , err);
software_node_unregister_node_group(geode_gpio_keys_swnodes);
return err;
}
return 0 ;
}
static const struct software_node geode_gpio_leds_node = {
.name = "geode-leds" ,
};
#define MAX_LEDS 3
int __init geode_create_leds(const char *label, const struct geode_led *leds,
unsigned int n_leds)
{
const struct software_node *group[MAX_LEDS + 2 ] = { 0 };
struct software_node *swnodes;
struct property_entry *props;
struct platform_device_info led_info = {
.name = "leds-gpio" ,
.id = PLATFORM_DEVID_NONE,
};
struct platform_device *led_dev;
const char *node_name;
int err;
int i;
if (n_leds > MAX_LEDS) {
pr_err("%s: too many LEDs\n" , __func__);
return -EINVAL;
}
swnodes = kcalloc(n_leds, sizeof (*swnodes), GFP_KERNEL);
if (!swnodes)
return -ENOMEM;
/*
* Each LED is represented by 3 properties : " gpios " ,
* " linux , default - trigger " , and am empty terminator .
*/
props = kcalloc(n_leds * 3 , sizeof (*props), GFP_KERNEL);
if (!props) {
err = -ENOMEM;
goto err_free_swnodes;
}
group[0 ] = &geode_gpio_leds_node;
for (i = 0 ; i < n_leds; i++) {
node_name = kasprintf(GFP_KERNEL, "%s:%d" , label, i);
if (!node_name) {
err = -ENOMEM;
goto err_free_names;
}
props[i * 3 + 0 ] =
PROPERTY_ENTRY_GPIO("gpios" , &geode_gpiochip_node,
leds[i].pin, GPIO_ACTIVE_LOW);
props[i * 3 + 1 ] =
PROPERTY_ENTRY_STRING("linux,default-trigger" ,
leds[i].default_on ?
"default-on" : "default-off" );
/* props[i * 3 + 2] is an empty terminator */
swnodes[i] = SOFTWARE_NODE(node_name, &props[i * 3 ],
&geode_gpio_leds_node);
group[i + 1 ] = &swnodes[i];
}
err = software_node_register_node_group(group);
if (err) {
pr_err("failed to register LED software nodes: %d\n" , err);
goto err_free_names;
}
led_info.fwnode = software_node_fwnode(&geode_gpio_leds_node);
led_dev = platform_device_register_full(&led_info);
err = PTR_ERR_OR_ZERO(led_dev);
if (err) {
pr_err("failed to create LED device: %d\n" , err);
goto err_unregister_group;
}
return 0 ;
err_unregister_group:
software_node_unregister_node_group(group);
err_free_names:
while (--i >= 0 )
kfree(swnodes[i].name);
kfree(props);
err_free_swnodes:
kfree(swnodes);
return err;
}
Messung V0.5 in Prozent C=96 H=84 G=90
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-09-27)
¤
*© Formatika GbR, Deutschland