197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa/* 297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * LEDs driver for the Cobalt Raq series. 397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * 4ada8e9514b5880f81cdbbd212d121380ceef7accYoichi Yuasa * Copyright (C) 2007 Yoichi Yuasa <yuasa@linux-mips.org> 597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * 697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * This program is free software; you can redistribute it and/or modify 797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * it under the terms of the GNU General Public License as published by 897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * the Free Software Foundation; either version 2 of the License, or 997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * (at your option) any later version. 1097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * 1197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * This program is distributed in the hope that it will be useful, 1297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * but WITHOUT ANY WARRANTY; without even the implied warranty of 1397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * GNU General Public License for more details. 1597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * 1697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * You should have received a copy of the GNU General Public License 1797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa * along with this program; if not, write to the Free Software 184d404fd5c51772720e9c72aa3185bd5119bc6e69Németh Márton * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 1997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa */ 2097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/init.h> 2197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/io.h> 2297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/ioport.h> 2397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/leds.h> 2497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/platform_device.h> 2597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/spinlock.h> 2697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#include <linux/types.h> 27d131c4962854b900ded69348acfd96007fcc893fPaul Gortmaker#include <linux/export.h> 2897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 2997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#define LED_WEB 0x04 3097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa#define LED_POWER_OFF 0x08 3197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 3297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic void __iomem *led_port; 3397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic u8 led_value; 3497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic DEFINE_SPINLOCK(led_value_lock); 3597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 3697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic void raq_web_led_set(struct led_classdev *led_cdev, 374d404fd5c51772720e9c72aa3185bd5119bc6e69Németh Márton enum led_brightness brightness) 3897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa{ 3997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa unsigned long flags; 4097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 4197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa spin_lock_irqsave(&led_value_lock, flags); 4297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 4397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (brightness) 4497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_value |= LED_WEB; 4597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa else 4697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_value &= ~LED_WEB; 4797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa writeb(led_value, led_port); 4897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 4997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa spin_unlock_irqrestore(&led_value_lock, flags); 5097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa} 5197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 5297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic struct led_classdev raq_web_led = { 53db3f520738a8c5bf593e13d4ac71f8da9ffcb964Olaf Hering .name = "raq::web", 5497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .brightness_set = raq_web_led_set, 5597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa}; 5697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 5797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic void raq_power_off_led_set(struct led_classdev *led_cdev, 584d404fd5c51772720e9c72aa3185bd5119bc6e69Németh Márton enum led_brightness brightness) 5997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa{ 6097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa unsigned long flags; 6197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 6297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa spin_lock_irqsave(&led_value_lock, flags); 6397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 6497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (brightness) 6597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_value |= LED_POWER_OFF; 6697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa else 6797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_value &= ~LED_POWER_OFF; 6897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa writeb(led_value, led_port); 6997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 7097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa spin_unlock_irqrestore(&led_value_lock, flags); 7197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa} 7297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 7397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic struct led_classdev raq_power_off_led = { 74db3f520738a8c5bf593e13d4ac71f8da9ffcb964Olaf Hering .name = "raq::power-off", 7597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .brightness_set = raq_power_off_led_set, 7697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .default_trigger = "power-off", 7797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa}; 7897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 7997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic int __devinit cobalt_raq_led_probe(struct platform_device *pdev) 8097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa{ 8197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa struct resource *res; 8297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa int retval; 8397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 8497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 8597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (!res) 8697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa return -EBUSY; 8797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 88d3aad6399a240300534d83ffdacfc40e6ed4fa73H Hartley Sweeten led_port = ioremap(res->start, resource_size(res)); 8997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (!led_port) 9097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa return -ENOMEM; 9197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 9297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa retval = led_classdev_register(&pdev->dev, &raq_power_off_led); 9397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (retval) 9497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa goto err_iounmap; 9597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 9697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa retval = led_classdev_register(&pdev->dev, &raq_web_led); 9797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (retval) 9897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa goto err_unregister; 9997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 10097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa return 0; 10197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 10297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasaerr_unregister: 10397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_classdev_unregister(&raq_power_off_led); 10497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 10597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasaerr_iounmap: 10697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa iounmap(led_port); 10797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_port = NULL; 10897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 10997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa return retval; 11097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa} 11197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 11297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic int __devexit cobalt_raq_led_remove(struct platform_device *pdev) 11397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa{ 11497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_classdev_unregister(&raq_power_off_led); 11597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_classdev_unregister(&raq_web_led); 11697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 11797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa if (led_port) { 11897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa iounmap(led_port); 11997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa led_port = NULL; 12097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa } 12197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 12297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa return 0; 12397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa} 12497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 12597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic struct platform_driver cobalt_raq_led_driver = { 12697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .probe = cobalt_raq_led_probe, 12797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .remove = __devexit_p(cobalt_raq_led_remove), 12897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .driver = { 12997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .name = "cobalt-raq-leds", 13097da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa .owner = THIS_MODULE, 13197da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa }, 13297da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa}; 13397da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 13497da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasastatic int __init cobalt_raq_led_init(void) 13597da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa{ 13697da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa return platform_driver_register(&cobalt_raq_led_driver); 13797da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa} 13897da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasa 13997da7aaf46fedcf1a38a88e5ffc2c40df23e8013Yoichi Yuasamodule_init(cobalt_raq_led_init); 140