~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/platform/geode/geode-common.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * Shared helpers to register GPIO-connected buttons and LEDs
  4  * on AMD Geode boards.
  5  */
  6 
  7 #include <linux/err.h>
  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>
 14 
 15 #include "geode-common.h"
 16 
 17 static const struct software_node geode_gpiochip_node = {
 18         .name = "cs5535-gpio",
 19 };
 20 
 21 static const struct property_entry geode_gpio_keys_props[] = {
 22         PROPERTY_ENTRY_U32("poll-interval", 20),
 23         { }
 24 };
 25 
 26 static const struct software_node geode_gpio_keys_node = {
 27         .name = "geode-gpio-keys",
 28         .properties = geode_gpio_keys_props,
 29 };
 30 
 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),
 36         { }
 37 };
 38 
 39 static const struct software_node geode_restart_key_node = {
 40         .parent = &geode_gpio_keys_node,
 41         .properties = geode_restart_key_props,
 42 };
 43 
 44 static const struct software_node *geode_gpio_keys_swnodes[] __initconst = {
 45         &geode_gpiochip_node,
 46         &geode_gpio_keys_node,
 47         &geode_restart_key_node,
 48         NULL
 49 };
 50 
 51 /*
 52  * Creates gpio-keys-polled device for the restart key.
 53  *
 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
 56  * leds-gpio devices.
 57  */
 58 int __init geode_create_restart_key(unsigned int pin)
 59 {
 60         struct platform_device_info keys_info = {
 61                 .name   = "gpio-keys-polled",
 62                 .id     = 1,
 63         };
 64         struct platform_device *pd;
 65         int err;
 66 
 67         geode_restart_key_props[0] = PROPERTY_ENTRY_GPIO("gpios",
 68                                                          &geode_gpiochip_node,
 69                                                          pin, GPIO_ACTIVE_LOW);
 70 
 71         err = software_node_register_node_group(geode_gpio_keys_swnodes);
 72         if (err) {
 73                 pr_err("failed to register gpio-keys software nodes: %d\n", err);
 74                 return err;
 75         }
 76 
 77         keys_info.fwnode = software_node_fwnode(&geode_gpio_keys_node);
 78 
 79         pd = platform_device_register_full(&keys_info);
 80         err = PTR_ERR_OR_ZERO(pd);
 81         if (err) {
 82                 pr_err("failed to create gpio-keys device: %d\n", err);
 83                 software_node_unregister_node_group(geode_gpio_keys_swnodes);
 84                 return err;
 85         }
 86 
 87         return 0;
 88 }
 89 
 90 static const struct software_node geode_gpio_leds_node = {
 91         .name = "geode-leds",
 92 };
 93 
 94 #define MAX_LEDS        3
 95 
 96 int __init geode_create_leds(const char *label, const struct geode_led *leds,
 97                               unsigned int n_leds)
 98 {
 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 = {
103                 .name   = "leds-gpio",
104                 .id     = PLATFORM_DEVID_NONE,
105         };
106         struct platform_device *led_dev;
107         const char *node_name;
108         int err;
109         int i;
110 
111         if (n_leds > MAX_LEDS) {
112                 pr_err("%s: too many LEDs\n", __func__);
113                 return -EINVAL;
114         }
115 
116         swnodes = kcalloc(n_leds, sizeof(*swnodes), GFP_KERNEL);
117         if (!swnodes)
118                 return -ENOMEM;
119 
120         /*
121          * Each LED is represented by 3 properties: "gpios",
122          * "linux,default-trigger", and am empty terminator.
123          */
124         props = kcalloc(n_leds * 3, sizeof(*props), GFP_KERNEL);
125         if (!props) {
126                 err = -ENOMEM;
127                 goto err_free_swnodes;
128         }
129 
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);
133                 if (!node_name) {
134                         err = -ENOMEM;
135                         goto err_free_names;
136                 }
137 
138                 props[i * 3 + 0] =
139                         PROPERTY_ENTRY_GPIO("gpios", &geode_gpiochip_node,
140                                             leds[i].pin, GPIO_ACTIVE_LOW);
141                 props[i * 3 + 1] =
142                         PROPERTY_ENTRY_STRING("linux,default-trigger",
143                                               leds[i].default_on ?
144                                               "default-on" : "default-off");
145                 /* props[i * 3 + 2] is an empty terminator */
146 
147                 swnodes[i] = SOFTWARE_NODE(node_name, &props[i * 3],
148                                            &geode_gpio_leds_node);
149                 group[i + 1] = &swnodes[i];
150         }
151 
152         err = software_node_register_node_group(group);
153         if (err) {
154                 pr_err("failed to register LED software nodes: %d\n", err);
155                 goto err_free_names;
156         }
157 
158         led_info.fwnode = software_node_fwnode(&geode_gpio_leds_node);
159 
160         led_dev = platform_device_register_full(&led_info);
161         err = PTR_ERR_OR_ZERO(led_dev);
162         if (err) {
163                 pr_err("failed to create LED device: %d\n", err);
164                 goto err_unregister_group;
165         }
166 
167         return 0;
168 
169 err_unregister_group:
170         software_node_unregister_node_group(group);
171 err_free_names:
172         while (--i >= 0)
173                 kfree(swnodes[i].name);
174         kfree(props);
175 err_free_swnodes:
176         kfree(swnodes);
177         return err;
178 }
179 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php