1*835a0c10SLee Jones // SPDX-License-Identifier: GPL-2.0 2*835a0c10SLee Jones /* 3*835a0c10SLee Jones * Siemens SIMATIC IPC driver for GPIO based LEDs 4*835a0c10SLee Jones * 5*835a0c10SLee Jones * Copyright (c) Siemens AG, 2023 6*835a0c10SLee Jones * 7*835a0c10SLee Jones * Author: 8*835a0c10SLee Jones * Henning Schild <henning.schild@siemens.com> 9*835a0c10SLee Jones */ 10*835a0c10SLee Jones 11*835a0c10SLee Jones #include <linux/gpio/machine.h> 12*835a0c10SLee Jones #include <linux/gpio/consumer.h> 13*835a0c10SLee Jones #include <linux/leds.h> 14*835a0c10SLee Jones #include <linux/module.h> 15*835a0c10SLee Jones #include <linux/platform_device.h> 16*835a0c10SLee Jones #include <linux/platform_data/x86/simatic-ipc-base.h> 17*835a0c10SLee Jones 18*835a0c10SLee Jones #include "simatic-ipc-leds-gpio.h" 19*835a0c10SLee Jones 20*835a0c10SLee Jones static struct platform_device *simatic_leds_pdev; 21*835a0c10SLee Jones 22*835a0c10SLee Jones static const struct gpio_led simatic_ipc_gpio_leds[] = { 23*835a0c10SLee Jones { .name = "red:" LED_FUNCTION_STATUS "-1" }, 24*835a0c10SLee Jones { .name = "green:" LED_FUNCTION_STATUS "-1" }, 25*835a0c10SLee Jones { .name = "red:" LED_FUNCTION_STATUS "-2" }, 26*835a0c10SLee Jones { .name = "green:" LED_FUNCTION_STATUS "-2" }, 27*835a0c10SLee Jones { .name = "red:" LED_FUNCTION_STATUS "-3" }, 28*835a0c10SLee Jones { .name = "green:" LED_FUNCTION_STATUS "-3" }, 29*835a0c10SLee Jones }; 30*835a0c10SLee Jones 31*835a0c10SLee Jones static const struct gpio_led_platform_data simatic_ipc_gpio_leds_pdata = { 32*835a0c10SLee Jones .num_leds = ARRAY_SIZE(simatic_ipc_gpio_leds), 33*835a0c10SLee Jones .leds = simatic_ipc_gpio_leds, 34*835a0c10SLee Jones }; 35*835a0c10SLee Jones 36*835a0c10SLee Jones void simatic_ipc_leds_gpio_remove(struct platform_device *pdev, 37*835a0c10SLee Jones struct gpiod_lookup_table *table, 38*835a0c10SLee Jones struct gpiod_lookup_table *table_extra) 39*835a0c10SLee Jones { 40*835a0c10SLee Jones gpiod_remove_lookup_table(table); 41*835a0c10SLee Jones gpiod_remove_lookup_table(table_extra); 42*835a0c10SLee Jones platform_device_unregister(simatic_leds_pdev); 43*835a0c10SLee Jones } 44*835a0c10SLee Jones EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_remove); 45*835a0c10SLee Jones 46*835a0c10SLee Jones int simatic_ipc_leds_gpio_probe(struct platform_device *pdev, 47*835a0c10SLee Jones struct gpiod_lookup_table *table, 48*835a0c10SLee Jones struct gpiod_lookup_table *table_extra) 49*835a0c10SLee Jones { 50*835a0c10SLee Jones const struct simatic_ipc_platform *plat = pdev->dev.platform_data; 51*835a0c10SLee Jones struct device *dev = &pdev->dev; 52*835a0c10SLee Jones struct gpio_desc *gpiod; 53*835a0c10SLee Jones int err; 54*835a0c10SLee Jones 55*835a0c10SLee Jones switch (plat->devmode) { 56*835a0c10SLee Jones case SIMATIC_IPC_DEVICE_127E: 57*835a0c10SLee Jones case SIMATIC_IPC_DEVICE_227G: 58*835a0c10SLee Jones case SIMATIC_IPC_DEVICE_BX_21A: 59*835a0c10SLee Jones case SIMATIC_IPC_DEVICE_BX_59A: 60*835a0c10SLee Jones break; 61*835a0c10SLee Jones default: 62*835a0c10SLee Jones return -ENODEV; 63*835a0c10SLee Jones } 64*835a0c10SLee Jones 65*835a0c10SLee Jones gpiod_add_lookup_table(table); 66*835a0c10SLee Jones simatic_leds_pdev = platform_device_register_resndata(NULL, 67*835a0c10SLee Jones "leds-gpio", PLATFORM_DEVID_NONE, NULL, 0, 68*835a0c10SLee Jones &simatic_ipc_gpio_leds_pdata, 69*835a0c10SLee Jones sizeof(simatic_ipc_gpio_leds_pdata)); 70*835a0c10SLee Jones if (IS_ERR(simatic_leds_pdev)) { 71*835a0c10SLee Jones err = PTR_ERR(simatic_leds_pdev); 72*835a0c10SLee Jones goto out; 73*835a0c10SLee Jones } 74*835a0c10SLee Jones 75*835a0c10SLee Jones if (!table_extra) 76*835a0c10SLee Jones return 0; 77*835a0c10SLee Jones 78*835a0c10SLee Jones table_extra->dev_id = dev_name(dev); 79*835a0c10SLee Jones gpiod_add_lookup_table(table_extra); 80*835a0c10SLee Jones 81*835a0c10SLee Jones /* PM_BIOS_BOOT_N */ 82*835a0c10SLee Jones gpiod = gpiod_get_index(dev, NULL, 6, GPIOD_OUT_LOW); 83*835a0c10SLee Jones if (IS_ERR(gpiod)) { 84*835a0c10SLee Jones err = PTR_ERR(gpiod); 85*835a0c10SLee Jones goto out; 86*835a0c10SLee Jones } 87*835a0c10SLee Jones gpiod_put(gpiod); 88*835a0c10SLee Jones 89*835a0c10SLee Jones /* PM_WDT_OUT */ 90*835a0c10SLee Jones gpiod = gpiod_get_index(dev, NULL, 7, GPIOD_OUT_LOW); 91*835a0c10SLee Jones if (IS_ERR(gpiod)) { 92*835a0c10SLee Jones err = PTR_ERR(gpiod); 93*835a0c10SLee Jones goto out; 94*835a0c10SLee Jones } 95*835a0c10SLee Jones gpiod_put(gpiod); 96*835a0c10SLee Jones 97*835a0c10SLee Jones return 0; 98*835a0c10SLee Jones out: 99*835a0c10SLee Jones simatic_ipc_leds_gpio_remove(pdev, table, table_extra); 100*835a0c10SLee Jones 101*835a0c10SLee Jones return err; 102*835a0c10SLee Jones } 103*835a0c10SLee Jones EXPORT_SYMBOL_GPL(simatic_ipc_leds_gpio_probe); 104*835a0c10SLee Jones 105*835a0c10SLee Jones MODULE_DESCRIPTION("Siemens SIMATIC IPC core driver for GPIO based LEDs"); 106*835a0c10SLee Jones MODULE_LICENSE("GPL v2"); 107*835a0c10SLee Jones MODULE_SOFTDEP("pre: platform:leds-gpio"); 108*835a0c10SLee Jones MODULE_AUTHOR("Henning Schild <henning.schild@siemens.com>"); 109