| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright 2007-2008 Extreme Engineering Solutions, Inc. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Author: Nate Case <ncase@xes-inc.com> |
|---|
| 5 | | - * |
|---|
| 6 | | - * This file is subject to the terms and conditions of version 2 of |
|---|
| 7 | | - * the GNU General Public License. See the file COPYING in the main |
|---|
| 8 | | - * directory of this archive for more details. |
|---|
| 9 | 6 | * |
|---|
| 10 | 7 | * LED driver for various PCA955x I2C LED drivers |
|---|
| 11 | 8 | * |
|---|
| .. | .. |
|---|
| 40 | 37 | * bits the chip supports. |
|---|
| 41 | 38 | */ |
|---|
| 42 | 39 | |
|---|
| 43 | | -#include <linux/acpi.h> |
|---|
| 44 | 40 | #include <linux/ctype.h> |
|---|
| 45 | 41 | #include <linux/delay.h> |
|---|
| 46 | 42 | #include <linux/err.h> |
|---|
| 47 | | -#include <linux/gpio.h> |
|---|
| 43 | +#include <linux/gpio/driver.h> |
|---|
| 48 | 44 | #include <linux/i2c.h> |
|---|
| 49 | 45 | #include <linux/leds.h> |
|---|
| 50 | 46 | #include <linux/module.h> |
|---|
| 51 | | -#include <linux/of_device.h> |
|---|
| 52 | 47 | #include <linux/of.h> |
|---|
| 48 | +#include <linux/property.h> |
|---|
| 53 | 49 | #include <linux/slab.h> |
|---|
| 54 | 50 | #include <linux/string.h> |
|---|
| 55 | 51 | |
|---|
| .. | .. |
|---|
| 69 | 65 | pca9550, |
|---|
| 70 | 66 | pca9551, |
|---|
| 71 | 67 | pca9552, |
|---|
| 68 | + ibm_pca9552, |
|---|
| 72 | 69 | pca9553, |
|---|
| 73 | 70 | }; |
|---|
| 74 | 71 | |
|---|
| .. | .. |
|---|
| 94 | 91 | .slv_addr = /* 1100xxx */ 0x60, |
|---|
| 95 | 92 | .slv_addr_shift = 3, |
|---|
| 96 | 93 | }, |
|---|
| 94 | + [ibm_pca9552] = { |
|---|
| 95 | + .bits = 16, |
|---|
| 96 | + .slv_addr = /* 0110xxx */ 0x30, |
|---|
| 97 | + .slv_addr_shift = 3, |
|---|
| 98 | + }, |
|---|
| 97 | 99 | [pca9553] = { |
|---|
| 98 | 100 | .bits = 4, |
|---|
| 99 | 101 | .slv_addr = /* 110001x */ 0x62, |
|---|
| .. | .. |
|---|
| 105 | 107 | { "pca9550", pca9550 }, |
|---|
| 106 | 108 | { "pca9551", pca9551 }, |
|---|
| 107 | 109 | { "pca9552", pca9552 }, |
|---|
| 110 | + { "ibm-pca9552", ibm_pca9552 }, |
|---|
| 108 | 111 | { "pca9553", pca9553 }, |
|---|
| 109 | 112 | { } |
|---|
| 110 | 113 | }; |
|---|
| 111 | 114 | MODULE_DEVICE_TABLE(i2c, pca955x_id); |
|---|
| 112 | | - |
|---|
| 113 | | -static const struct acpi_device_id pca955x_acpi_ids[] = { |
|---|
| 114 | | - { "PCA9550", pca9550 }, |
|---|
| 115 | | - { "PCA9551", pca9551 }, |
|---|
| 116 | | - { "PCA9552", pca9552 }, |
|---|
| 117 | | - { "PCA9553", pca9553 }, |
|---|
| 118 | | - { } |
|---|
| 119 | | -}; |
|---|
| 120 | | -MODULE_DEVICE_TABLE(acpi, pca955x_acpi_ids); |
|---|
| 121 | 115 | |
|---|
| 122 | 116 | struct pca955x { |
|---|
| 123 | 117 | struct mutex lock; |
|---|
| .. | .. |
|---|
| 373 | 367 | } |
|---|
| 374 | 368 | #endif /* CONFIG_LEDS_PCA955X_GPIO */ |
|---|
| 375 | 369 | |
|---|
| 376 | | -#if IS_ENABLED(CONFIG_OF) |
|---|
| 377 | 370 | static struct pca955x_platform_data * |
|---|
| 378 | | -pca955x_pdata_of_init(struct i2c_client *client, struct pca955x_chipdef *chip) |
|---|
| 371 | +pca955x_get_pdata(struct i2c_client *client, struct pca955x_chipdef *chip) |
|---|
| 379 | 372 | { |
|---|
| 380 | | - struct device_node *np = client->dev.of_node; |
|---|
| 381 | | - struct device_node *child; |
|---|
| 382 | 373 | struct pca955x_platform_data *pdata; |
|---|
| 374 | + struct fwnode_handle *child; |
|---|
| 383 | 375 | int count; |
|---|
| 384 | 376 | |
|---|
| 385 | | - count = of_get_child_count(np); |
|---|
| 377 | + count = device_get_child_node_count(&client->dev); |
|---|
| 386 | 378 | if (!count || count > chip->bits) |
|---|
| 387 | 379 | return ERR_PTR(-ENODEV); |
|---|
| 388 | 380 | |
|---|
| .. | .. |
|---|
| 396 | 388 | if (!pdata->leds) |
|---|
| 397 | 389 | return ERR_PTR(-ENOMEM); |
|---|
| 398 | 390 | |
|---|
| 399 | | - for_each_child_of_node(np, child) { |
|---|
| 391 | + device_for_each_child_node(&client->dev, child) { |
|---|
| 400 | 392 | const char *name; |
|---|
| 401 | 393 | u32 reg; |
|---|
| 402 | 394 | int res; |
|---|
| 403 | 395 | |
|---|
| 404 | | - res = of_property_read_u32(child, "reg", ®); |
|---|
| 396 | + res = fwnode_property_read_u32(child, "reg", ®); |
|---|
| 405 | 397 | if ((res != 0) || (reg >= chip->bits)) |
|---|
| 406 | 398 | continue; |
|---|
| 407 | 399 | |
|---|
| 408 | | - if (of_property_read_string(child, "label", &name)) |
|---|
| 409 | | - name = child->name; |
|---|
| 400 | + res = fwnode_property_read_string(child, "label", &name); |
|---|
| 401 | + if ((res != 0) && is_of_node(child)) |
|---|
| 402 | + name = to_of_node(child)->name; |
|---|
| 410 | 403 | |
|---|
| 411 | 404 | snprintf(pdata->leds[reg].name, sizeof(pdata->leds[reg].name), |
|---|
| 412 | 405 | "%s", name); |
|---|
| 413 | 406 | |
|---|
| 414 | 407 | pdata->leds[reg].type = PCA955X_TYPE_LED; |
|---|
| 415 | | - of_property_read_u32(child, "type", &pdata->leds[reg].type); |
|---|
| 416 | | - of_property_read_string(child, "linux,default-trigger", |
|---|
| 408 | + fwnode_property_read_u32(child, "type", &pdata->leds[reg].type); |
|---|
| 409 | + fwnode_property_read_string(child, "linux,default-trigger", |
|---|
| 417 | 410 | &pdata->leds[reg].default_trigger); |
|---|
| 418 | 411 | } |
|---|
| 419 | 412 | |
|---|
| .. | .. |
|---|
| 426 | 419 | { .compatible = "nxp,pca9550", .data = (void *)pca9550 }, |
|---|
| 427 | 420 | { .compatible = "nxp,pca9551", .data = (void *)pca9551 }, |
|---|
| 428 | 421 | { .compatible = "nxp,pca9552", .data = (void *)pca9552 }, |
|---|
| 422 | + { .compatible = "ibm,pca9552", .data = (void *)ibm_pca9552 }, |
|---|
| 429 | 423 | { .compatible = "nxp,pca9553", .data = (void *)pca9553 }, |
|---|
| 430 | 424 | {}, |
|---|
| 431 | 425 | }; |
|---|
| 432 | | - |
|---|
| 433 | 426 | MODULE_DEVICE_TABLE(of, of_pca955x_match); |
|---|
| 434 | | -#else |
|---|
| 435 | | -static struct pca955x_platform_data * |
|---|
| 436 | | -pca955x_pdata_of_init(struct i2c_client *client, struct pca955x_chipdef *chip) |
|---|
| 437 | | -{ |
|---|
| 438 | | - return ERR_PTR(-ENODEV); |
|---|
| 439 | | -} |
|---|
| 440 | | -#endif |
|---|
| 441 | 427 | |
|---|
| 442 | 428 | static int pca955x_probe(struct i2c_client *client, |
|---|
| 443 | 429 | const struct i2c_device_id *id) |
|---|
| .. | .. |
|---|
| 450 | 436 | struct pca955x_platform_data *pdata; |
|---|
| 451 | 437 | int ngpios = 0; |
|---|
| 452 | 438 | |
|---|
| 453 | | - if (id) { |
|---|
| 454 | | - chip = &pca955x_chipdefs[id->driver_data]; |
|---|
| 455 | | - } else { |
|---|
| 456 | | - const struct acpi_device_id *acpi_id; |
|---|
| 457 | | - |
|---|
| 458 | | - acpi_id = acpi_match_device(pca955x_acpi_ids, &client->dev); |
|---|
| 459 | | - if (!acpi_id) |
|---|
| 460 | | - return -ENODEV; |
|---|
| 461 | | - chip = &pca955x_chipdefs[acpi_id->driver_data]; |
|---|
| 462 | | - } |
|---|
| 463 | | - adapter = to_i2c_adapter(client->dev.parent); |
|---|
| 439 | + chip = &pca955x_chipdefs[id->driver_data]; |
|---|
| 440 | + adapter = client->adapter; |
|---|
| 464 | 441 | pdata = dev_get_platdata(&client->dev); |
|---|
| 465 | 442 | if (!pdata) { |
|---|
| 466 | | - pdata = pca955x_pdata_of_init(client, chip); |
|---|
| 443 | + pdata = pca955x_get_pdata(client, chip); |
|---|
| 467 | 444 | if (IS_ERR(pdata)) |
|---|
| 468 | 445 | return PTR_ERR(pdata); |
|---|
| 469 | 446 | } |
|---|
| .. | .. |
|---|
| 602 | 579 | static struct i2c_driver pca955x_driver = { |
|---|
| 603 | 580 | .driver = { |
|---|
| 604 | 581 | .name = "leds-pca955x", |
|---|
| 605 | | - .acpi_match_table = ACPI_PTR(pca955x_acpi_ids), |
|---|
| 606 | | - .of_match_table = of_match_ptr(of_pca955x_match), |
|---|
| 582 | + .of_match_table = of_pca955x_match, |
|---|
| 607 | 583 | }, |
|---|
| 608 | 584 | .probe = pca955x_probe, |
|---|
| 609 | 585 | .id_table = pca955x_id, |
|---|