aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Wood <brian.j.wood@intel.com>2015-10-20 15:40:06 -0700
committerBruce Beare <bruce.j.beare@intel.com>2015-10-23 20:15:17 -0700
commit85763d0bbafce79b499831872120ba7ecf08a00f (patch)
treeab1c0620b3882665ab5e0e1a1901848a73dba1c1
parentb4e573b8c3fd17c2eaac2e7b96e8dc9e82c9a03f (diff)
downloadedison-v3.10-85763d0bbafce79b499831872120ba7ecf08a00f.tar.gz
Adding GPIO request/free support for Intel Edison LED driver
This commit adds in support for request/free GPIO operations in the LED driver so that the GPIO pin can be freed for use by 3rd party libraries (like MRAA) that wish to control the GPIO pins directly for the LED. Also adding support for debug kernel configuration option (to print helpful debugging messages). Change-Id: If20f78721239fdfe605aeeb2095d123a4cc69807 Signed-off-by: Brian Wood <brian.j.wood@intel.com>
-rw-r--r--arch/x86/configs/i386_brillo_edison_defconfig1
-rw-r--r--drivers/leds/Kconfig15
-rw-r--r--drivers/leds/leds-edison-gpio-flash.c337
3 files changed, 255 insertions, 98 deletions
diff --git a/arch/x86/configs/i386_brillo_edison_defconfig b/arch/x86/configs/i386_brillo_edison_defconfig
index 695aec094c8..2027b36eaa4 100644
--- a/arch/x86/configs/i386_brillo_edison_defconfig
+++ b/arch/x86/configs/i386_brillo_edison_defconfig
@@ -2841,6 +2841,7 @@ CONFIG_LEDS_GPIO=y
# CONFIG_LEDS_BD2802 is not set
# CONFIG_LEDS_INTEL_SS4200 is not set
CONFIG_LEDS_INTEL_GPIO_FLASH=y
+# CONFIG_LEDS_INTEL_GPIO_FLASH_DEBUG is not set
# CONFIG_LEDS_LT3593 is not set
# CONFIG_LEDS_TCA6507 is not set
# CONFIG_LEDS_LM355x is not set
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index d5de750a515..17028bec910 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -360,13 +360,22 @@ config LEDS_INTEL_SS4200
can stop the front LED from blinking after startup.
config LEDS_INTEL_GPIO_FLASH
- tristate "Support for GPIO Flash LEDs"
+ tristate "LED driver for Intel Edison"
help
This driver supports the leds functionality of GPIO Flash LED. It
- includes flash mode and torch mode.
+ can be set to either on/off or delay_on/delay_off for flashing.
To compile this driver as a module, choose M here: the module will
- be called leds-gpio-flash.
+ be called leds-edison-gpio-flash.
+
+config LEDS_INTEL_GPIO_FLASH_DEBUG
+ bool "Enable Debug Support for Intel Edison LED driver"
+ depends on LEDS_INTEL_GPIO_FLASH
+ help
+ This option enables debugging support in the Intel Edison
+ LED driver. These kernel debugging messages can be quite
+ verbose, but are helpful when debugging and provides quite
+ a bit of information for generating bug reports.
config LEDS_LT3593
tristate "LED driver for LT3593 controllers"
diff --git a/drivers/leds/leds-edison-gpio-flash.c b/drivers/leds/leds-edison-gpio-flash.c
index 595bafeb5c1..9ca19b13598 100644
--- a/drivers/leds/leds-edison-gpio-flash.c
+++ b/drivers/leds/leds-edison-gpio-flash.c
@@ -31,42 +31,204 @@
#define LED_TRIGGER_DEFAULT "none"
#define LED_MAX_BRIGHTNESS 1
-#define GPIO_PIN_NUM 243 /* temporary hardcoded value for development */
-#define GPIO_PIN_MUX_NUM 261 /* " " " " " " */
-#define GPIO_LABEL "DS2"
-#define GPIO_LABEL_MUX "DS2_MUX"
+#define GPIO_TRI_STATE_ALL 214 /* hardcoded value for development */
+#define GPIO_PIN_NUM 243 /* " " " " */
+#define GPIO_PIN_MUX_NUM 261 /* " " " " */
+#define GPIO_LABEL "DS2"
+#define GPIO_LABEL_MUX "DS2_MUX"
+#define GPIO_LABEL_TRI_STATE "DS2_TRI_STATE"
#define GPIO_OUT_LOW (0 << 1)
#define GPIO_OUT_HIGH (1 << 1)
+#undef LED_DBG
+#ifdef CONFIG_LEDS_INTEL_GPIO_FLASH_DEBUG
+#define LED_DBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define LED_DBG(fmt, args...)
+#endif
+
struct led_gpio_flash_data {
struct led_classdev cdev;
int gpio_pin_num; /* record single GPIO number, hard coded
- * value for now (will change)
+ * value for now (may change to dynamic)
*/
+ int gpio_pin_state; /* current GPIO state, 1 locked/0 free */
int gpio_pin_mux_num;
+ int gpio_pin_mux_state;
+ int gpio_pin_tri_state_num;
+ int gpio_pin_tri_state_state;
+ int blinking; /* blinking state, 1 enabled/0 disabled */
struct work_struct led_flash_work;
};
-/* Workqueue handler function */
+/* GPIO request/free */
+static int led_gpio_request(struct led_classdev *led_cdev)
+{
+
+ int rc;
+ struct led_gpio_flash_data *flash_led =
+ container_of(led_cdev, struct led_gpio_flash_data, cdev);
+
+ /* Reserve the GPIO's for LED */
+
+ /* Test if GPIO_TRI_STATE_ALL is available, if not we know MRAA
+ * has exported for SPI use
+ */
+ flash_led->gpio_pin_tri_state_state =
+ gpio_request(flash_led->gpio_pin_tri_state_num,
+ GPIO_LABEL_TRI_STATE);
+ if (flash_led->gpio_pin_tri_state_state == -EBUSY) {
+ /* GPIO is exported by MRAA */
+ pr_info("%s: GPIO_TRI_STATE_ALL (%d) is busy/exported "
+ "by someone, we need to set direction to input\n",
+ __func__, flash_led->gpio_pin_tri_state_num);
+ /* Set direction for pin */
+ rc = gpio_direction_input(flash_led->gpio_pin_tri_state_num);
+ if (rc)
+ pr_err("%s: Setting GPIO %d direction to input failed! "
+ ",rc=%d\n", __func__,
+ flash_led->gpio_pin_tri_state_num, rc);
+ else
+ pr_info("%s: Setting GPIO %d direction to input "
+ "succeeded, rc=%d.\n", __func__,
+ flash_led->gpio_pin_tri_state_num, rc);
+
+ } /* else: GPIO is unchanged from defaults, no need to adjust */
+
+ /* Request the output enable pinmux for the DS2 LED GPIO */
+ rc = gpio_request(flash_led->gpio_pin_mux_num, GPIO_LABEL_MUX);
+ if (rc) {
+ pr_err("%s: Failed to request gpio %d,rc = %d\n",
+ __func__, flash_led->gpio_pin_mux_num, rc);
+ /* Reset blink values to 0 since we've failed */
+ flash_led->cdev.blink_delay_on =
+ flash_led->cdev.blink_delay_off =
+ flash_led->blinking = LED_OFF;
+ goto error;
+ }
+ /* Make sure the direction is out */
+ rc = gpio_direction_output(flash_led->gpio_pin_mux_num, 0);
+ if (rc)
+ pr_err("%s: Setting GPIO %d direction to out failed!, rc=%d\n",
+ __func__, flash_led->gpio_pin_mux_num, rc);
+ else
+ LED_DBG("%s: Setting GPIO %d direction to out succeeded, "
+ "rc=%d.\n", __func__, flash_led->gpio_pin_mux_num, rc);
+
+ /* Request the DS2 LED GPIO */
+ rc = gpio_request(flash_led->gpio_pin_num, GPIO_LABEL);
+ if (rc) {
+ pr_err("%s: Failed to request gpio %d,rc = %d\n",
+ __func__, flash_led->gpio_pin_num, rc);
+ goto error2;
+ }
+ /* Make sure the direction is out */
+ rc = gpio_direction_output(flash_led->gpio_pin_num, 1);
+ if (rc)
+ pr_err("%s: Setting GPIO %d direction to out failed!, "
+ "rc=%d.\n", __func__, flash_led->gpio_pin_num, rc);
+ else
+ LED_DBG("%s: Setting GPIO %d direction to out succeeded, "
+ "rc=%d.\n", __func__, flash_led->gpio_pin_num, rc);
+
+ /* If GPIO value is 0 set to 1 so light is off initially */
+ rc = gpio_get_value_cansleep(flash_led->gpio_pin_num);
+ LED_DBG("%s: GPIO (%d) initial value=%d, "
+ "changing value to %d\n",
+ __func__, flash_led->gpio_pin_num, rc, 1);
+ if (!rc)
+ gpio_set_value_cansleep(flash_led->gpio_pin_num, 1);
+ LED_DBG("%s: GPIO value=%d\n",
+ __func__, gpio_get_value_cansleep(flash_led->gpio_pin_num));
+
+ /* GPIO's reserved for use by driver */
+ flash_led->gpio_pin_state = flash_led->gpio_pin_mux_state = 1;
+
+ return 0;
+
+error:
+ pr_err("%s: Failed to request pinmux GPIO=%d\n",
+ __func__, GPIO_PIN_MUX_NUM);
+ return rc;
+
+error2:
+ pr_err("%s: Failed to request GPIO=%d\n",
+ __func__, GPIO_PIN_NUM);
+ gpio_free(flash_led->gpio_pin_mux_num);
+ return rc;
+}
+
+static int led_gpio_free(struct led_classdev *led_cdev)
+{
+ int rc;
+ struct led_gpio_flash_data *flash_led =
+ container_of(led_cdev, struct led_gpio_flash_data, cdev);
+
+ /* Free the GPIO's for use outside driver */
+ gpio_free(flash_led->gpio_pin_num);
+ gpio_free(flash_led->gpio_pin_mux_num);
+ if (!flash_led->gpio_pin_tri_state_state) {
+ LED_DBG("%s: Freeing GPIO_TRI_STATE_ALL=%d\n",
+ __func__, GPIO_TRI_STATE_ALL);
+ gpio_free(flash_led->gpio_pin_tri_state_num);
+ } else {
+ pr_info("%s: GPIO_TRI_STATE_ALL (%d) is being reset "
+ "back to output direction\n",
+ __func__, flash_led->gpio_pin_tri_state_num);
+ /* Set direction for pin */
+ rc = gpio_direction_output(flash_led->gpio_pin_tri_state_num, 0);
+ if (rc)
+ pr_err("%s: Setting GPIO %d direction to output failed! "
+ ",rc=%d\n", __func__,
+ flash_led->gpio_pin_tri_state_num, rc);
+ else
+ pr_info("%s: Setting GPIO %d direction to output "
+ "succeeded, rc=%d.\n", __func__,
+ flash_led->gpio_pin_tri_state_num, rc);
+
+ }
+ LED_DBG("%s: Freeing GPIO=%d and GPIO_PIN_MUX=%d\n",
+ __func__, GPIO_PIN_NUM, GPIO_PIN_MUX_NUM);
+
+ flash_led->gpio_pin_state = flash_led->gpio_pin_mux_state =
+ flash_led->gpio_pin_tri_state_state = 0;
+
+ return 0;
+}
+
+/* Workqueue handler */
static void ledwq_work_handler(struct work_struct *ws)
{
- int ret = 0;
+ int ret = 0, rc = 0;
struct led_gpio_flash_data *flash_led =
container_of(ws, struct led_gpio_flash_data, led_flash_work);
- pr_debug("%s: Use the workqueue for flashing the LED\n", __func__);
+ LED_DBG("%s: Use the workqueue for flashing the LED\n", __func__);
+
+ if (!flash_led->gpio_pin_state && !flash_led->gpio_pin_mux_state) {
+ rc = led_gpio_request(&flash_led->cdev);
+ if (rc) {
+ pr_err("%s: GPIO request failed LED blinking "
+ "disabled, rc=%d\n", __func__, rc);
+ return;
+ }
+ }
- while(1) {
+ flash_led->blinking = 1;
+
+ while (1) {
if (ret) {
- pr_debug("ON\n");
+ LED_DBG("ON\n");
gpio_set_value_cansleep(flash_led->gpio_pin_num, 0);
ret = 0;
+ set_current_state(TASK_INTERRUPTIBLE);
msleep(flash_led->cdev.blink_delay_on);
} else { /* ret == 0 */
- pr_debug("OFF\n");
+ LED_DBG("OFF\n");
gpio_set_value_cansleep(flash_led->gpio_pin_num, 1);
ret = 1;
+ set_current_state(TASK_INTERRUPTIBLE);
msleep(flash_led->cdev.blink_delay_off);
}
/* Code below is an alternate timer code flow that would use
@@ -78,11 +240,15 @@ static void ledwq_work_handler(struct work_struct *ws)
schedule_timeout (1000/(flash_led->cdev.brightness+1));
*/
if (!flash_led->cdev.blink_delay_on ||
- !flash_led->cdev.blink_delay_off)
- break;
+ !flash_led->cdev.blink_delay_off ||
+ !flash_led->blinking) {
+ led_gpio_free(&flash_led->cdev);
+ return;
+ }
}
}
+/* LED blink setup */
static int led_gpio_blink_set(struct led_classdev *led_cdev,
unsigned long *delay_on,
unsigned long *delay_off)
@@ -91,40 +257,42 @@ static int led_gpio_blink_set(struct led_classdev *led_cdev,
container_of(led_cdev, struct led_gpio_flash_data, cdev);
flash_led->cdev.brightness = 0;
- pr_debug("%s: Reset brightness=%d, setup flashing LED "
+ LED_DBG("%s: Reset brightness=%d, setup flashing LED "
"delay_on/delay_off\n",
__func__, flash_led->cdev.brightness);
- pr_debug("%s: delay_on=%lu, delay_off=%lu\n",
+ LED_DBG("%s: delay_on=%lu, delay_off=%lu\n",
__func__, *delay_on, *delay_off);
- pr_debug("%s: Prepare and queue work\n", __func__);
+ LED_DBG("%s: Cancel any pending queued LED blinking work\n", __func__);
+ flash_led->blinking = LED_OFF;
+ cancel_work_sync(&flash_led->led_flash_work);
+ LED_DBG("%s: Prepare and queue work\n", __func__);
schedule_work(&flash_led->led_flash_work);
-
return 0;
}
static ssize_t led_delay_on_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
- return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
+ return sprintf(buf, "%lu\n", led_cdev->blink_delay_on);
}
static ssize_t led_delay_on_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
- unsigned long state;
- ssize_t ret = -EINVAL;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ unsigned long state;
+ ssize_t ret = -EINVAL;
- ret = kstrtoul(buf, 10, &state);
- if (ret)
- return ret;
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
- led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
- led_cdev->blink_delay_on = state;
+ led_blink_set(led_cdev, &state, &led_cdev->blink_delay_off);
+ led_cdev->blink_delay_on = state;
return size;
}
@@ -132,26 +300,26 @@ return size;
static ssize_t led_delay_off_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
- return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
+ return sprintf(buf, "%lu\n", led_cdev->blink_delay_off);
}
static ssize_t led_delay_off_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t size)
{
- struct led_classdev *led_cdev = dev_get_drvdata(dev);
- unsigned long state;
- ssize_t ret = -EINVAL;
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ unsigned long state;
+ ssize_t ret = -EINVAL;
- ret = kstrtoul(buf, 10, &state);
- if (ret)
- return ret;
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
- led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
- led_cdev->blink_delay_off = state;
+ led_blink_set(led_cdev, &led_cdev->blink_delay_on, &state);
+ led_cdev->blink_delay_off = state;
- return size;
+ return size;
}
static DEVICE_ATTR(delay_on, 0644, led_delay_on_show, led_delay_on_store);
@@ -163,14 +331,26 @@ static void led_gpio_brightness_set(struct led_classdev *led_cdev,
{
struct led_gpio_flash_data *flash_led =
container_of(led_cdev, struct led_gpio_flash_data, cdev);
+ int rc;
int brightness = value;
/* Reset blink*/
flash_led->cdev.blink_delay_on =
- flash_led->cdev.blink_delay_off = LED_OFF;
+ flash_led->cdev.blink_delay_off =
+ flash_led->blinking = LED_OFF;
if (brightness >= 1) { /* Turn on LED */
- pr_debug("%s: Turning on LED, brightness=%d\n", __func__, brightness);
+ if (!flash_led->gpio_pin_state &&
+ !flash_led->gpio_pin_mux_state) {
+ rc = led_gpio_request(&flash_led->cdev);
+ if (rc) {
+ pr_err("%s: GPIO request failed LED disabled, "
+ "rc=%d\n", __func__, rc);
+ goto err;
+ }
+ }
+ LED_DBG("%s: Turning on LED, brightness=%d\n",
+ __func__, brightness);
gpio_set_value_cansleep(flash_led->gpio_pin_num, 0);
/* if 0 we failed to set */
if (gpio_get_value_cansleep(flash_led->gpio_pin_num)) {
@@ -178,13 +358,14 @@ static void led_gpio_brightness_set(struct led_classdev *led_cdev,
flash_led->gpio_pin_num);
goto err;
}
- pr_debug("%s: GPIO value=%d\n", __func__,
+ LED_DBG("%s: GPIO value=%d\n", __func__,
gpio_get_value_cansleep(flash_led->gpio_pin_num));
flash_led->cdev.brightness = 1;
- pr_debug("%s: Stored new value for brightness=%d\n", __func__,
+ LED_DBG("%s: Stored new value for brightness=%d\n", __func__,
flash_led->cdev.brightness);
} else { /* brightness <= 0, Turn off LED */
- pr_debug("%s: Turning off LED, brightness=%d\n", __func__, brightness);
+ LED_DBG("%s: Turning off LED, brightness=%d\n",
+ __func__, brightness);
gpio_set_value_cansleep(flash_led->gpio_pin_num, 1);
/* if nonzero we failed to set */
if (gpio_get_value_cansleep(flash_led->gpio_pin_num)) {
@@ -192,11 +373,13 @@ static void led_gpio_brightness_set(struct led_classdev *led_cdev,
flash_led->gpio_pin_num);
goto err;
}
- pr_debug("%s: GPIO value=%d\n", __func__,
+ LED_DBG("%s: GPIO value=%d\n", __func__,
gpio_get_value_cansleep(flash_led->gpio_pin_num));
+ if (flash_led->gpio_pin_state && flash_led->gpio_pin_mux_state)
+ led_gpio_free(&flash_led->cdev);
flash_led->cdev.brightness = 0;
- pr_debug("%s: Stored new value for brightness=%d\n", __func__,
- flash_led->cdev.brightness);
+ LED_DBG("%s: Stored new value for brightness=%d\n",
+ __func__, flash_led->cdev.brightness);
}
err:
@@ -208,7 +391,8 @@ static enum led_brightness led_gpio_brightness_get(struct led_classdev
{
struct led_gpio_flash_data *flash_led =
container_of(led_cdev, struct led_gpio_flash_data, cdev);
- pr_debug("%s: returning brightness=%d\n", __func__, flash_led->cdev.brightness);
+ LED_DBG("%s: returning brightness=%d\n",
+ __func__, flash_led->cdev.brightness);
return flash_led->cdev.brightness;
}
@@ -216,7 +400,7 @@ int led_gpio_flash_probe(struct platform_device *pdev)
{
int rc = 0;
struct led_gpio_flash_data *flash_led = NULL;
-
+
flash_led = devm_kzalloc(&pdev->dev, sizeof(struct led_gpio_flash_data),
GFP_KERNEL);
if (flash_led == NULL) {
@@ -228,53 +412,15 @@ int led_gpio_flash_probe(struct platform_device *pdev)
INIT_WORK(&flash_led->led_flash_work, ledwq_work_handler);
flash_led->gpio_pin_num = GPIO_PIN_NUM;
flash_led->gpio_pin_mux_num = GPIO_PIN_MUX_NUM;
+ flash_led->gpio_pin_tri_state_num = GPIO_TRI_STATE_ALL;
+ flash_led->gpio_pin_state = flash_led->gpio_pin_mux_state =
+ flash_led->gpio_pin_tri_state_state = 0;
+ flash_led->blinking = LED_OFF;
flash_led->cdev.default_trigger = LED_TRIGGER_DEFAULT;
dev_dbg(&pdev->dev, "%s: GPIO LED number=%d, GPIO LED pin mux number=%d, "
"default trigger=%s\n", __func__, flash_led->gpio_pin_num,
flash_led->gpio_pin_mux_num, flash_led->cdev.default_trigger);
- /* Request the output enable pinmux for the DS2 LED GPIO */
- rc = gpio_request(flash_led->gpio_pin_mux_num, GPIO_LABEL_MUX);
- if (rc) {
- dev_err(&pdev->dev, "%s: Failed to request gpio %d,rc = %d\n",
- __func__, flash_led->gpio_pin_mux_num, rc);
- goto error;
- }
- /* Make sure the direction is out */
- rc = gpio_direction_output(flash_led->gpio_pin_mux_num, 0);
- if (rc)
- dev_err(&pdev->dev, "%s: Setting GPIO %d direction to out failed!, rc=%d\n",
- __func__, flash_led->gpio_pin_mux_num, rc);
- else
- dev_dbg(&pdev->dev, "%s: Setting GPIO %d direction to out succeeded, "
- "rc=%d.\n", __func__, flash_led->gpio_pin_mux_num, rc);
-
- /* Request the DS2 LED GPIO */
- rc = gpio_request(flash_led->gpio_pin_num, GPIO_LABEL);
- if (rc) {
- dev_err(&pdev->dev, "%s: Failed to request gpio %d,rc = %d\n",
- __func__, flash_led->gpio_pin_num, rc);
- goto error;
- }
- /* Make sure the direction is out */
- rc = gpio_direction_output(flash_led->gpio_pin_num, 1);
- if (rc)
- dev_err(&pdev->dev, "%s: Setting GPIO %d direction to out failed!, "
- "rc=%d.\n", __func__, flash_led->gpio_pin_num, rc);
- else
- dev_dbg(&pdev->dev, "%s: Setting GPIO %d direction to out succeeded, "
- "rc=%d.\n", __func__, flash_led->gpio_pin_num, rc);
-
- /* If GPIO value is 0 set to 1 so light is off initially */
- rc = gpio_get_value_cansleep(flash_led->gpio_pin_num);
- dev_dbg(&pdev->dev, "%s: GPIO (%d) initial value=%d, "
- "changing value to %d\n",
- __func__, flash_led->gpio_pin_num, rc, 1);
- if (!rc)
- gpio_set_value_cansleep(flash_led->gpio_pin_num, 1);
- dev_dbg(&pdev->dev, "%s: GPIO value=%d\n",
- __func__, gpio_get_value_cansleep(flash_led->gpio_pin_num));
-
flash_led->cdev.name = "DS2_Green_LED";
dev_dbg(&pdev->dev, "%s: cdev name=%s\n",
__func__, flash_led->cdev.name);
@@ -318,15 +464,16 @@ int led_gpio_flash_remove(struct platform_device *pdev)
{
struct led_gpio_flash_data *flash_led =
(struct led_gpio_flash_data *)platform_get_drvdata(pdev);
- gpio_free(flash_led->gpio_pin_num);
- gpio_free(flash_led->gpio_pin_mux_num);
+
+ if (flash_led->gpio_pin_state && flash_led->gpio_pin_mux_state)
+ led_gpio_free(&flash_led->cdev);
device_remove_file(flash_led->cdev.dev, &dev_attr_delay_off);
device_remove_file(flash_led->cdev.dev, &dev_attr_delay_on);
led_classdev_unregister(&flash_led->cdev);
devm_kfree(&pdev->dev, flash_led);
- pr_debug("%s: Unregistering Intel LED GPIO driver", __func__);
+ LED_DBG("%s: Unregistering Intel LED GPIO driver", __func__);
return 0;
}
@@ -341,13 +488,13 @@ static struct platform_driver led_gpio_flash_driver = {
static int __init led_gpio_flash_init(void)
{
- pr_debug("%s: Registering Intel LED GPIO driver\n", __func__);
+ LED_DBG("%s: Registering Intel LED GPIO driver\n", __func__);
return platform_driver_register(&led_gpio_flash_driver);
}
static void __exit led_gpio_flash_exit(void)
{
- pr_debug("%s: Unregistering Intel LED GPIO driver\n", __func__);
+ LED_DBG("%s: Unregistering Intel LED GPIO driver\n", __func__);
return platform_driver_unregister(&led_gpio_flash_driver);
}