|
12 | 12 |
|
13 | 13 | #include <linux/dmi.h> |
14 | 14 | #include <linux/err.h> |
| 15 | +#include <linux/gpio/machine.h> |
| 16 | +#include <linux/gpio/property.h> |
| 17 | +#include <linux/input-event-codes.h> |
15 | 18 | #include <linux/kernel.h> |
16 | | -#include <linux/leds.h> |
17 | 19 | #include <linux/module.h> |
18 | 20 | #include <linux/platform_device.h> |
19 | | -#include <linux/gpio_keys.h> |
20 | | -#include <linux/gpio/machine.h> |
21 | | -#include <linux/input.h> |
| 21 | +#include <linux/property.h> |
22 | 22 | #include <linux/platform_data/gpio/gpio-amd-fch.h> |
23 | 23 |
|
24 | 24 | /* |
@@ -72,60 +72,91 @@ static const struct amd_fch_gpio_pdata board_apu2 = { |
72 | 72 | .gpio_names = apu2_gpio_names, |
73 | 73 | }; |
74 | 74 |
|
| 75 | +static const struct software_node apu2_gpiochip_node = { |
| 76 | + .name = AMD_FCH_GPIO_DRIVER_NAME, |
| 77 | +}; |
| 78 | + |
75 | 79 | /* GPIO LEDs device */ |
| 80 | +static const struct software_node apu2_leds_node = { |
| 81 | + .name = "apu2-leds", |
| 82 | +}; |
76 | 83 |
|
77 | | -static const struct gpio_led apu2_leds[] = { |
78 | | - { .name = "apu:green:1" }, |
79 | | - { .name = "apu:green:2" }, |
80 | | - { .name = "apu:green:3" }, |
| 84 | +static const struct property_entry apu2_led1_props[] = { |
| 85 | + PROPERTY_ENTRY_STRING("label", "apu:green:1"), |
| 86 | + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, |
| 87 | + APU2_GPIO_LINE_LED1, GPIO_ACTIVE_LOW), |
| 88 | + { } |
81 | 89 | }; |
82 | 90 |
|
83 | | -static const struct gpio_led_platform_data apu2_leds_pdata = { |
84 | | - .num_leds = ARRAY_SIZE(apu2_leds), |
85 | | - .leds = apu2_leds, |
| 91 | +static const struct software_node apu2_led1_swnode = { |
| 92 | + .name = "led-1", |
| 93 | + .parent = &apu2_leds_node, |
| 94 | + .properties = apu2_led1_props, |
86 | 95 | }; |
87 | 96 |
|
88 | | -static struct gpiod_lookup_table gpios_led_table = { |
89 | | - .dev_id = "leds-gpio", |
90 | | - .table = { |
91 | | - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED1, |
92 | | - NULL, 0, GPIO_ACTIVE_LOW), |
93 | | - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED2, |
94 | | - NULL, 1, GPIO_ACTIVE_LOW), |
95 | | - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3, |
96 | | - NULL, 2, GPIO_ACTIVE_LOW), |
97 | | - {} /* Terminating entry */ |
98 | | - } |
| 97 | +static const struct property_entry apu2_led2_props[] = { |
| 98 | + PROPERTY_ENTRY_STRING("label", "apu:green:2"), |
| 99 | + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, |
| 100 | + APU2_GPIO_LINE_LED2, GPIO_ACTIVE_LOW), |
| 101 | + { } |
| 102 | +}; |
| 103 | + |
| 104 | +static const struct software_node apu2_led2_swnode = { |
| 105 | + .name = "led-2", |
| 106 | + .parent = &apu2_leds_node, |
| 107 | + .properties = apu2_led2_props, |
| 108 | +}; |
| 109 | + |
| 110 | +static const struct property_entry apu2_led3_props[] = { |
| 111 | + PROPERTY_ENTRY_STRING("label", "apu:green:3"), |
| 112 | + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, |
| 113 | + APU2_GPIO_LINE_LED3, GPIO_ACTIVE_LOW), |
| 114 | + { } |
| 115 | +}; |
| 116 | + |
| 117 | +static const struct software_node apu2_led3_swnode = { |
| 118 | + .name = "led-3", |
| 119 | + .parent = &apu2_leds_node, |
| 120 | + .properties = apu2_led3_props, |
99 | 121 | }; |
100 | 122 |
|
101 | 123 | /* GPIO keyboard device */ |
| 124 | +static const struct property_entry apu2_keys_props[] = { |
| 125 | + PROPERTY_ENTRY_U32("poll-interval", 100), |
| 126 | + { } |
| 127 | +}; |
102 | 128 |
|
103 | | -static struct gpio_keys_button apu2_keys_buttons[] = { |
104 | | - { |
105 | | - .code = KEY_RESTART, |
106 | | - .active_low = 1, |
107 | | - .desc = "front button", |
108 | | - .type = EV_KEY, |
109 | | - .debounce_interval = 10, |
110 | | - .value = 1, |
111 | | - }, |
| 129 | +static const struct software_node apu2_keys_node = { |
| 130 | + .name = "apu2-keys", |
| 131 | + .properties = apu2_keys_props, |
112 | 132 | }; |
113 | 133 |
|
114 | | -static const struct gpio_keys_platform_data apu2_keys_pdata = { |
115 | | - .buttons = apu2_keys_buttons, |
116 | | - .nbuttons = ARRAY_SIZE(apu2_keys_buttons), |
117 | | - .poll_interval = 100, |
118 | | - .rep = 0, |
119 | | - .name = "apu2-keys", |
| 134 | +static const struct property_entry apu2_front_button_props[] = { |
| 135 | + PROPERTY_ENTRY_STRING("label", "front button"), |
| 136 | + PROPERTY_ENTRY_U32("linux,code", KEY_RESTART), |
| 137 | + PROPERTY_ENTRY_GPIO("gpios", &apu2_gpiochip_node, |
| 138 | + APU2_GPIO_LINE_MODESW, GPIO_ACTIVE_LOW), |
| 139 | + PROPERTY_ENTRY_U32("debounce-interval", 10), |
| 140 | + { } |
120 | 141 | }; |
121 | 142 |
|
122 | | -static struct gpiod_lookup_table gpios_key_table = { |
123 | | - .dev_id = "gpio-keys-polled", |
124 | | - .table = { |
125 | | - GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW, |
126 | | - NULL, 0, GPIO_ACTIVE_LOW), |
127 | | - {} /* Terminating entry */ |
128 | | - } |
| 143 | +static const struct software_node apu2_front_button_swnode = { |
| 144 | + .name = "front-button", |
| 145 | + .parent = &apu2_keys_node, |
| 146 | + .properties = apu2_front_button_props, |
| 147 | +}; |
| 148 | + |
| 149 | +static const struct software_node *apu2_swnodes[] = { |
| 150 | + &apu2_gpiochip_node, |
| 151 | + /* LEDs nodes */ |
| 152 | + &apu2_leds_node, |
| 153 | + &apu2_led1_swnode, |
| 154 | + &apu2_led2_swnode, |
| 155 | + &apu2_led3_swnode, |
| 156 | + /* Keys nodes */ |
| 157 | + &apu2_keys_node, |
| 158 | + &apu2_front_button_swnode, |
| 159 | + NULL |
129 | 160 | }; |
130 | 161 |
|
131 | 162 | /* Board setup */ |
@@ -222,66 +253,79 @@ static struct platform_device *apu_gpio_pdev; |
222 | 253 | static struct platform_device *apu_leds_pdev; |
223 | 254 | static struct platform_device *apu_keys_pdev; |
224 | 255 |
|
225 | | -static struct platform_device * __init apu_create_pdev( |
226 | | - const char *name, |
227 | | - const void *pdata, |
228 | | - size_t sz) |
| 256 | +static struct platform_device * __init apu_create_pdev(const char *name, |
| 257 | + const void *data, size_t size, |
| 258 | + const struct software_node *swnode) |
229 | 259 | { |
| 260 | + struct platform_device_info pdev_info = { |
| 261 | + .name = name, |
| 262 | + .id = PLATFORM_DEVID_NONE, |
| 263 | + .data = data, |
| 264 | + .size_data = size, |
| 265 | + .fwnode = software_node_fwnode(swnode), |
| 266 | + }; |
230 | 267 | struct platform_device *pdev; |
| 268 | + int err; |
231 | 269 |
|
232 | | - pdev = platform_device_register_resndata(NULL, |
233 | | - name, |
234 | | - PLATFORM_DEVID_NONE, |
235 | | - NULL, |
236 | | - 0, |
237 | | - pdata, |
238 | | - sz); |
| 270 | + pdev = platform_device_register_full(&pdev_info); |
239 | 271 |
|
240 | | - if (IS_ERR(pdev)) |
241 | | - pr_err("failed registering %s: %ld\n", name, PTR_ERR(pdev)); |
| 272 | + err = PTR_ERR_OR_ZERO(pdev); |
| 273 | + if (err) |
| 274 | + pr_err("failed registering %s: %d\n", name, err); |
242 | 275 |
|
243 | 276 | return pdev; |
244 | 277 | } |
245 | 278 |
|
246 | 279 | static int __init apu_board_init(void) |
247 | 280 | { |
248 | 281 | const struct dmi_system_id *id; |
| 282 | + int err; |
249 | 283 |
|
250 | 284 | id = dmi_first_match(apu_gpio_dmi_table); |
251 | 285 | if (!id) { |
252 | 286 | pr_err("failed to detect APU board via DMI\n"); |
253 | 287 | return -ENODEV; |
254 | 288 | } |
255 | 289 |
|
256 | | - gpiod_add_lookup_table(&gpios_led_table); |
257 | | - gpiod_add_lookup_table(&gpios_key_table); |
| 290 | + err = software_node_register_node_group(apu2_swnodes); |
| 291 | + if (err) { |
| 292 | + pr_err("failed to register software nodes: %d\n", err); |
| 293 | + return err; |
| 294 | + } |
258 | 295 |
|
259 | | - apu_gpio_pdev = apu_create_pdev( |
260 | | - AMD_FCH_GPIO_DRIVER_NAME, |
261 | | - id->driver_data, |
262 | | - sizeof(struct amd_fch_gpio_pdata)); |
| 296 | + apu_gpio_pdev = apu_create_pdev(AMD_FCH_GPIO_DRIVER_NAME, |
| 297 | + id->driver_data, sizeof(struct amd_fch_gpio_pdata), NULL); |
| 298 | + err = PTR_ERR_OR_ZERO(apu_gpio_pdev); |
| 299 | + if (err) |
| 300 | + goto err_unregister_swnodes; |
263 | 301 |
|
264 | | - apu_leds_pdev = apu_create_pdev( |
265 | | - "leds-gpio", |
266 | | - &apu2_leds_pdata, |
267 | | - sizeof(apu2_leds_pdata)); |
| 302 | + apu_leds_pdev = apu_create_pdev("leds-gpio", NULL, 0, &apu2_leds_node); |
| 303 | + err = PTR_ERR_OR_ZERO(apu_leds_pdev); |
| 304 | + if (err) |
| 305 | + goto err_unregister_gpio; |
268 | 306 |
|
269 | | - apu_keys_pdev = apu_create_pdev( |
270 | | - "gpio-keys-polled", |
271 | | - &apu2_keys_pdata, |
272 | | - sizeof(apu2_keys_pdata)); |
| 307 | + apu_keys_pdev = apu_create_pdev("gpio-keys-polled", NULL, 0, &apu2_keys_node); |
| 308 | + err = PTR_ERR_OR_ZERO(apu_keys_pdev); |
| 309 | + if (err) |
| 310 | + goto err_unregister_leds; |
273 | 311 |
|
274 | 312 | return 0; |
| 313 | + |
| 314 | +err_unregister_leds: |
| 315 | + platform_device_unregister(apu_leds_pdev); |
| 316 | +err_unregister_gpio: |
| 317 | + platform_device_unregister(apu_gpio_pdev); |
| 318 | +err_unregister_swnodes: |
| 319 | + software_node_unregister_node_group(apu2_swnodes); |
| 320 | + return err; |
275 | 321 | } |
276 | 322 |
|
277 | 323 | static void __exit apu_board_exit(void) |
278 | 324 | { |
279 | | - gpiod_remove_lookup_table(&gpios_led_table); |
280 | | - gpiod_remove_lookup_table(&gpios_key_table); |
281 | | - |
282 | 325 | platform_device_unregister(apu_keys_pdev); |
283 | 326 | platform_device_unregister(apu_leds_pdev); |
284 | 327 | platform_device_unregister(apu_gpio_pdev); |
| 328 | + software_node_unregister_node_group(apu2_swnodes); |
285 | 329 | } |
286 | 330 |
|
287 | 331 | module_init(apu_board_init); |
|
0 commit comments