162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * LED Driver for SGI Octane machines 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <asm/io.h> 762306a36Sopenharmony_ci#include <linux/module.h> 862306a36Sopenharmony_ci#include <linux/kernel.h> 962306a36Sopenharmony_ci#include <linux/platform_device.h> 1062306a36Sopenharmony_ci#include <linux/leds.h> 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#define IP30_LED_SYSTEM 0 1362306a36Sopenharmony_ci#define IP30_LED_FAULT 1 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistruct ip30_led { 1662306a36Sopenharmony_ci struct led_classdev cdev; 1762306a36Sopenharmony_ci u32 __iomem *reg; 1862306a36Sopenharmony_ci}; 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic void ip30led_set(struct led_classdev *led_cdev, 2162306a36Sopenharmony_ci enum led_brightness value) 2262306a36Sopenharmony_ci{ 2362306a36Sopenharmony_ci struct ip30_led *led = container_of(led_cdev, struct ip30_led, cdev); 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci writel(value, led->reg); 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic int ip30led_create(struct platform_device *pdev, int num) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci struct ip30_led *data; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); 3362306a36Sopenharmony_ci if (!data) 3462306a36Sopenharmony_ci return -ENOMEM; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci data->reg = devm_platform_ioremap_resource(pdev, num); 3762306a36Sopenharmony_ci if (IS_ERR(data->reg)) 3862306a36Sopenharmony_ci return PTR_ERR(data->reg); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci switch (num) { 4162306a36Sopenharmony_ci case IP30_LED_SYSTEM: 4262306a36Sopenharmony_ci data->cdev.name = "white:power"; 4362306a36Sopenharmony_ci break; 4462306a36Sopenharmony_ci case IP30_LED_FAULT: 4562306a36Sopenharmony_ci data->cdev.name = "red:fault"; 4662306a36Sopenharmony_ci break; 4762306a36Sopenharmony_ci default: 4862306a36Sopenharmony_ci return -EINVAL; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci data->cdev.brightness = readl(data->reg); 5262306a36Sopenharmony_ci data->cdev.max_brightness = 1; 5362306a36Sopenharmony_ci data->cdev.brightness_set = ip30led_set; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci return devm_led_classdev_register(&pdev->dev, &data->cdev); 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic int ip30led_probe(struct platform_device *pdev) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci int ret; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci ret = ip30led_create(pdev, IP30_LED_SYSTEM); 6362306a36Sopenharmony_ci if (ret < 0) 6462306a36Sopenharmony_ci return ret; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci return ip30led_create(pdev, IP30_LED_FAULT); 6762306a36Sopenharmony_ci} 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic struct platform_driver ip30led_driver = { 7062306a36Sopenharmony_ci .probe = ip30led_probe, 7162306a36Sopenharmony_ci .driver = { 7262306a36Sopenharmony_ci .name = "ip30-leds", 7362306a36Sopenharmony_ci }, 7462306a36Sopenharmony_ci}; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cimodule_platform_driver(ip30led_driver); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ciMODULE_AUTHOR("Thomas Bogendoerfer <tbogendoerfer@suse.de>"); 7962306a36Sopenharmony_ciMODULE_DESCRIPTION("SGI Octane LED driver"); 8062306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 8162306a36Sopenharmony_ciMODULE_ALIAS("platform:ip30-leds"); 82