1 // SPDX-License-Identifier: GPL-2.0-only
3 * Shared helpers to register GPIO-connected buttons and LEDs
8 #include <linux/gpio/machine.h>
9 #include <linux/gpio/property.h>
10 #include <linux/input.h>
11 #include <linux/leds.h>
12 #include <linux/platform_device.h>
13 #include <linux/slab.h>
15 #include "geode-common.h"
17 static const struct software_node geode_gpiochip_node
= {
18 .name
= "cs5535-gpio",
21 static const struct property_entry geode_gpio_keys_props
[] = {
22 PROPERTY_ENTRY_U32("poll-interval", 20),
26 static const struct software_node geode_gpio_keys_node
= {
27 .name
= "geode-gpio-keys",
28 .properties
= geode_gpio_keys_props
,
31 static struct property_entry geode_restart_key_props
[] = {
32 { /* Placeholder for GPIO property */ },
33 PROPERTY_ENTRY_U32("linux,code", KEY_RESTART
),
34 PROPERTY_ENTRY_STRING("label", "Reset button"),
35 PROPERTY_ENTRY_U32("debounce-interval", 100),
39 static const struct software_node geode_restart_key_node
= {
40 .parent
= &geode_gpio_keys_node
,
41 .properties
= geode_restart_key_props
,
44 static const struct software_node
*geode_gpio_keys_swnodes
[] __initconst
= {
46 &geode_gpio_keys_node
,
47 &geode_restart_key_node
,
52 * Creates gpio-keys-polled device for the restart key.
54 * Note that it needs to be called first, before geode_create_leds(),
55 * because it registers gpiochip software node used by both gpio-keys and
58 int __init
geode_create_restart_key(unsigned int pin
)
60 struct platform_device_info keys_info
= {
61 .name
= "gpio-keys-polled",
64 struct platform_device
*pd
;
67 geode_restart_key_props
[0] = PROPERTY_ENTRY_GPIO("gpios",
69 pin
, GPIO_ACTIVE_LOW
);
71 err
= software_node_register_node_group(geode_gpio_keys_swnodes
);
73 pr_err("failed to register gpio-keys software nodes: %d\n", err
);
77 keys_info
.fwnode
= software_node_fwnode(&geode_gpio_keys_node
);
79 pd
= platform_device_register_full(&keys_info
);
80 err
= PTR_ERR_OR_ZERO(pd
);
82 pr_err("failed to create gpio-keys device: %d\n", err
);
83 software_node_unregister_node_group(geode_gpio_keys_swnodes
);
90 static const struct software_node geode_gpio_leds_node
= {
96 int __init
geode_create_leds(const char *label
, const struct geode_led
*leds
,
99 const struct software_node
*group
[MAX_LEDS
+ 2] = { 0 };
100 struct software_node
*swnodes
;
101 struct property_entry
*props
;
102 struct platform_device_info led_info
= {
104 .id
= PLATFORM_DEVID_NONE
,
106 struct platform_device
*led_dev
;
107 const char *node_name
;
111 if (n_leds
> MAX_LEDS
) {
112 pr_err("%s: too many LEDs\n", __func__
);
116 swnodes
= kcalloc(n_leds
, sizeof(*swnodes
), GFP_KERNEL
);
121 * Each LED is represented by 3 properties: "gpios",
122 * "linux,default-trigger", and am empty terminator.
124 props
= kcalloc(n_leds
* 3, sizeof(*props
), GFP_KERNEL
);
127 goto err_free_swnodes
;
130 group
[0] = &geode_gpio_leds_node
;
131 for (i
= 0; i
< n_leds
; i
++) {
132 node_name
= kasprintf(GFP_KERNEL
, "%s:%d", label
, i
);
139 PROPERTY_ENTRY_GPIO("gpios", &geode_gpiochip_node
,
140 leds
[i
].pin
, GPIO_ACTIVE_LOW
);
142 PROPERTY_ENTRY_STRING("linux,default-trigger",
144 "default-on" : "default-off");
145 /* props[i * 3 + 2] is an empty terminator */
147 swnodes
[i
] = SOFTWARE_NODE(node_name
, &props
[i
* 3],
148 &geode_gpio_leds_node
);
149 group
[i
+ 1] = &swnodes
[i
];
152 err
= software_node_register_node_group(group
);
154 pr_err("failed to register LED software nodes: %d\n", err
);
158 led_info
.fwnode
= software_node_fwnode(&geode_gpio_leds_node
);
160 led_dev
= platform_device_register_full(&led_info
);
161 err
= PTR_ERR_OR_ZERO(led_dev
);
163 pr_err("failed to create LED device: %d\n", err
);
164 goto err_unregister_group
;
169 err_unregister_group
:
170 software_node_unregister_node_group(group
);
173 kfree(swnodes
[i
].name
);