]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 May 2016 01:37:06 +0000 (18:37 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 17 May 2016 01:37:06 +0000 (18:37 -0700)
Pull LED updates from Jacek Anaszewski:
 "In this merge cycle we had an interaction with MTD subsystem, that
  included converting drivers/mtd/nand/nand_base.c to use newly
  introduced MTD (NAND/NOR) LED trigger instead of implementing it on
  its own.

  Related MTD patches are intended to be merged through the LED tree,
  before MTD tree is merged, since further MTD development is based on
  those modifications.

  Summary:

  LEDs:
   - Introduce a kernel panic LED trigger

   - Introduce a MTD (NAND/NOR) trigger

   - led-tca6507: silence an uninitialized variable warning

   - ledtrig-ide-disk: Move ide_blink_delay to ledtrig_ide_activity()

   - leds-ss4200: Add depend on x86 arch

   - leds-ss4200: add DMI data for FSC SCALEO Home Server

   - leds-triggers: Allow to switch the trigger to "panic" on a kernel panic

   - devicetree: leds: Introduce "panic-indicator" optional property

   - leds-gpio: Support the "panic-indicator" firmware property

  MTD:
   - Uninline mtd_write_oob and move it to mtdcore.c

   - Remove the "nand-disk" LED trigger

   - Hook I/O activity to the MTD LED trigger"

* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/j.anaszewski/linux-leds:
  leds: gpio: Support the "panic-indicator" firmware property
  devicetree: leds: Introduce "panic-indicator" optional property
  leds: triggers: Allow to switch the trigger to "panic" on a kernel panic
  leds: ss4200: add DMI data for FSC SCALEO Home Server
  leds: ss4200: Add depend on x86 arch
  leds: ledtrig-ide-disk: Move ide_blink_delay to ledtrig_ide_activity()
  leds: tca6507: silence an uninitialized variable warning
  mtd: Hook I/O activity to the MTD LED trigger
  mtd: nand: Remove the "nand-disk" LED trigger
  leds: trigger: Introduce a MTD (NAND/NOR) trigger
  mtd: Uninline mtd_write_oob and move it to mtdcore.c
  leds: trigger: Introduce a kernel panic LED trigger

17 files changed:
Documentation/devicetree/bindings/leds/common.txt
Documentation/devicetree/bindings/leds/leds-gpio.txt
drivers/leds/Kconfig
drivers/leds/led-triggers.c
drivers/leds/leds-gpio.c
drivers/leds/leds-ss4200.c
drivers/leds/leds-tca6507.c
drivers/leds/leds.h
drivers/leds/trigger/Kconfig
drivers/leds/trigger/Makefile
drivers/leds/trigger/ledtrig-ide-disk.c
drivers/leds/trigger/ledtrig-mtd.c [new file with mode: 0644]
drivers/leds/trigger/ledtrig-panic.c [new file with mode: 0644]
drivers/mtd/mtdcore.c
drivers/mtd/nand/nand_base.c
include/linux/leds.h
include/linux/mtd/mtd.h

index 68419843e32fc83c28ba7ecb5b0a25c2f4c2efb4..af10678ea2f651a8b0c47881ab389685af180ece 100644 (file)
@@ -37,6 +37,9 @@ Optional properties for child nodes:
                      property is mandatory for the LEDs in the non-flash modes
                      (e.g. torch or indicator).
 
+- panic-indicator : This property specifies that the LED should be used,
+                   if at all possible, as a panic indicator.
+
 Required properties for flash LED child nodes:
 - flash-max-microamp : Maximum flash LED supply current in microamperes.
 - flash-max-timeout-us : Maximum timeout in microseconds after which the flash
index fea1ebfe24a9573f2023b9ada78cec925d35e799..cbbeb1850910ed602e883b64e61254c91ad7ceda 100644 (file)
@@ -23,6 +23,8 @@ LED sub-node properties:
   property is not present.
 - retain-state-suspended: (optional) The suspend state can be retained.Such
   as charge-led gpio.
+- panic-indicator : (optional)
+  see Documentation/devicetree/bindings/leds/common.txt
 
 Examples:
 
index 225147863e024fcb93ac6b011976255af1486f29..5ae28340a98b4f53d288194a9d1bed1a08518a35 100644 (file)
@@ -413,10 +413,11 @@ config LEDS_INTEL_SS4200
        tristate "LED driver for Intel NAS SS4200 series"
        depends on LEDS_CLASS
        depends on PCI && DMI
+       depends on X86
        help
          This option enables support for the Intel SS4200 series of
-         Network Attached Storage servers.  You may control the hard
-         drive or power LEDs on the front panel.  Using this driver
+         Network Attached Storage servers. You may control the hard
+         drive or power LEDs on the front panel. Using this driver
          can stop the front LED from blinking after startup.
 
 config LEDS_LT3593
index 2181581795d306c125f0cd0a7a9e14e744d07326..55fa65e1ae030dc2840d7d53e74975f4c6eaf311 100644 (file)
@@ -26,7 +26,7 @@
  * Nests outside led_cdev->trigger_lock
  */
 static DECLARE_RWSEM(triggers_list_lock);
-static LIST_HEAD(trigger_list);
+LIST_HEAD(trigger_list);
 
  /* Used by LED Class */
 
index 61143f55597e42f9b45fe4efe33a1c51614b22b4..8229f063b483c77cf993891cb2bc2e7e9239ee6a 100644 (file)
@@ -127,6 +127,8 @@ static int create_gpio_led(const struct gpio_led *template,
        led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
        if (!template->retain_state_suspended)
                led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
+       if (template->panic_indicator)
+               led_dat->cdev.flags |= LED_PANIC_INDICATOR;
 
        ret = gpiod_direction_output(led_dat->gpiod, state);
        if (ret < 0)
@@ -200,6 +202,8 @@ static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
 
                if (fwnode_property_present(child, "retain-state-suspended"))
                        led.retain_state_suspended = 1;
+               if (fwnode_property_present(child, "panic-indicator"))
+                       led.panic_indicator = 1;
 
                ret = create_gpio_led(&led, &priv->leds[priv->num_leds],
                                      dev, NULL);
index 046cb70087452ef8cea540b073ae0fa71ceeef94..732eb86bc1a5ca2307971ed4e9eb0cf80227e6a2 100644 (file)
@@ -101,6 +101,19 @@ static struct dmi_system_id nas_led_whitelist[] __initdata = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
                }
        },
+       {
+               /*
+                * FUJITSU SIEMENS SCALEO Home Server/SS4200-E
+                * BIOS V090L 12/19/2007
+                */
+               .callback = ss4200_led_dmi_callback,
+               .ident = "Fujitsu Siemens SCALEO Home Server",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SCALEO Home Server"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
+               }
+       },
        {}
 };
 
index c548ea10f0f036648d1d357f998641551ff3f2a6..45222a7f4f75636d628596d90d9bdb29acf0b453 100644 (file)
@@ -327,6 +327,8 @@ static void set_times(struct tca6507_chip *tca, int bank)
        int result;
 
        result = choose_times(tca->bank[bank].ontime, &c1, &c2);
+       if (result < 0)
+               return;
        dev_dbg(&tca->client->dev,
                "Chose on  times %d(%d) %d(%d) for %dms\n",
                c1, time_codes[c1],
index db3f20da7221738920bf49bd35fbc13b1768e65d..7d38e6b9a740b2eecbf7d080895204d354c1a71a 100644 (file)
@@ -30,5 +30,6 @@ void led_set_brightness_nosleep(struct led_classdev *led_cdev,
 
 extern struct rw_semaphore leds_list_lock;
 extern struct list_head leds_list;
+extern struct list_head trigger_list;
 
 #endif /* __LEDS_H_INCLUDED */
index 5bda6a9b56bbd90b4a3749f87bc0c6fda8dd5034..9893d911390daa4dd77986065ebde50b517d6b72 100644 (file)
@@ -41,6 +41,14 @@ config LEDS_TRIGGER_IDE_DISK
          This allows LEDs to be controlled by IDE disk activity.
          If unsure, say Y.
 
+config LEDS_TRIGGER_MTD
+       bool "LED MTD (NAND/NOR) Trigger"
+       depends on MTD
+       depends on LEDS_TRIGGERS
+       help
+         This allows LEDs to be controlled by MTD activity.
+         If unsure, say N.
+
 config LEDS_TRIGGER_HEARTBEAT
        tristate "LED Heartbeat Trigger"
        depends on LEDS_TRIGGERS
@@ -108,4 +116,14 @@ config LEDS_TRIGGER_CAMERA
          This enables direct flash/torch on/off by the driver, kernel space.
          If unsure, say Y.
 
+config LEDS_TRIGGER_PANIC
+       bool "LED Panic Trigger"
+       depends on LEDS_TRIGGERS
+       help
+         This allows LEDs to be configured to blink on a kernel panic.
+         Enabling this option will allow to mark certain LEDs as panic indicators,
+         allowing to blink them on a kernel panic, even if they are set to
+         a different trigger.
+         If unsure, say Y.
+
 endif # LEDS_TRIGGERS
index 1abf48dacf7ebfcfb8208f7ae7bdf29d7c11ba32..8cc64a4f4e255c1dd9fafde1ccd72d5a08ccbd5b 100644 (file)
@@ -1,6 +1,7 @@
 obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
 obj-$(CONFIG_LEDS_TRIGGER_ONESHOT)     += ledtrig-oneshot.o
 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK)    += ledtrig-ide-disk.o
+obj-$(CONFIG_LEDS_TRIGGER_MTD)         += ledtrig-mtd.o
 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT)   += ledtrig-heartbeat.o
 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT)   += ledtrig-backlight.o
 obj-$(CONFIG_LEDS_TRIGGER_GPIO)                += ledtrig-gpio.o
@@ -8,3 +9,4 @@ obj-$(CONFIG_LEDS_TRIGGER_CPU)          += ledtrig-cpu.o
 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON)  += ledtrig-default-on.o
 obj-$(CONFIG_LEDS_TRIGGER_TRANSIENT)   += ledtrig-transient.o
 obj-$(CONFIG_LEDS_TRIGGER_CAMERA)      += ledtrig-camera.o
+obj-$(CONFIG_LEDS_TRIGGER_PANIC)       += ledtrig-panic.o
index c02a3ac3cd2bf124777e44741142a35a90d2f19d..15123d3892403afd09fb890b00db6ee89288bae4 100644 (file)
 #define BLINK_DELAY 30
 
 DEFINE_LED_TRIGGER(ledtrig_ide);
-static unsigned long ide_blink_delay = BLINK_DELAY;
 
 void ledtrig_ide_activity(void)
 {
+       unsigned long ide_blink_delay = BLINK_DELAY;
+
        led_trigger_blink_oneshot(ledtrig_ide,
                                  &ide_blink_delay, &ide_blink_delay, 0);
 }
diff --git a/drivers/leds/trigger/ledtrig-mtd.c b/drivers/leds/trigger/ledtrig-mtd.c
new file mode 100644 (file)
index 0000000..99b5b0a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * LED MTD trigger
+ *
+ * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
+ *
+ * Based on LED IDE-Disk Activity Trigger
+ *
+ * Copyright 2006 Openedhand Ltd.
+ *
+ * Author: Richard Purdie <rpurdie@openedhand.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/leds.h>
+
+#define BLINK_DELAY 30
+
+DEFINE_LED_TRIGGER(ledtrig_mtd);
+DEFINE_LED_TRIGGER(ledtrig_nand);
+
+void ledtrig_mtd_activity(void)
+{
+       unsigned long blink_delay = BLINK_DELAY;
+
+       led_trigger_blink_oneshot(ledtrig_mtd,
+                                 &blink_delay, &blink_delay, 0);
+       led_trigger_blink_oneshot(ledtrig_nand,
+                                 &blink_delay, &blink_delay, 0);
+}
+EXPORT_SYMBOL(ledtrig_mtd_activity);
+
+static int __init ledtrig_mtd_init(void)
+{
+       led_trigger_register_simple("mtd", &ledtrig_mtd);
+       led_trigger_register_simple("nand-disk", &ledtrig_nand);
+
+       return 0;
+}
+device_initcall(ledtrig_mtd_init);
diff --git a/drivers/leds/trigger/ledtrig-panic.c b/drivers/leds/trigger/ledtrig-panic.c
new file mode 100644 (file)
index 0000000..d735526
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Kernel Panic LED Trigger
+ *
+ * Copyright 2016 Ezequiel Garcia <ezequiel@vanguardiasur.com.ar>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/leds.h>
+#include "../leds.h"
+
+static struct led_trigger *trigger;
+
+/*
+ * This is called in a special context by the atomic panic
+ * notifier. This means the trigger can be changed without
+ * worrying about locking.
+ */
+static void led_trigger_set_panic(struct led_classdev *led_cdev)
+{
+       struct led_trigger *trig;
+
+       list_for_each_entry(trig, &trigger_list, next_trig) {
+               if (strcmp("panic", trig->name))
+                       continue;
+               if (led_cdev->trigger)
+                       list_del(&led_cdev->trig_list);
+               list_add_tail(&led_cdev->trig_list, &trig->led_cdevs);
+
+               /* Avoid the delayed blink path */
+               led_cdev->blink_delay_on = 0;
+               led_cdev->blink_delay_off = 0;
+
+               led_cdev->trigger = trig;
+               if (trig->activate)
+                       trig->activate(led_cdev);
+               break;
+       }
+}
+
+static int led_trigger_panic_notifier(struct notifier_block *nb,
+                                     unsigned long code, void *unused)
+{
+       struct led_classdev *led_cdev;
+
+       list_for_each_entry(led_cdev, &leds_list, node)
+               if (led_cdev->flags & LED_PANIC_INDICATOR)
+                       led_trigger_set_panic(led_cdev);
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block led_trigger_panic_nb = {
+       .notifier_call = led_trigger_panic_notifier,
+};
+
+static long led_panic_blink(int state)
+{
+       led_trigger_event(trigger, state ? LED_FULL : LED_OFF);
+       return 0;
+}
+
+static int __init ledtrig_panic_init(void)
+{
+       atomic_notifier_chain_register(&panic_notifier_list,
+                                      &led_trigger_panic_nb);
+
+       led_trigger_register_simple("panic", &trigger);
+       panic_blink = led_panic_blink;
+       return 0;
+}
+device_initcall(ledtrig_panic_init);
index 309625130b21b751e5fa42bb4693800a8327001b..bee180bd11e79fe236e0287647986fe81fea864c 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/slab.h>
 #include <linux/reboot.h>
 #include <linux/kconfig.h>
+#include <linux/leds.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -862,6 +863,7 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
                mtd_erase_callback(instr);
                return 0;
        }
+       ledtrig_mtd_activity();
        return mtd->_erase(mtd, instr);
 }
 EXPORT_SYMBOL_GPL(mtd_erase);
@@ -925,6 +927,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
        if (!len)
                return 0;
 
+       ledtrig_mtd_activity();
        /*
         * In the absence of an error, drivers return a non-negative integer
         * representing the maximum number of bitflips that were corrected on
@@ -949,6 +952,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
                return -EROFS;
        if (!len)
                return 0;
+       ledtrig_mtd_activity();
        return mtd->_write(mtd, to, len, retlen, buf);
 }
 EXPORT_SYMBOL_GPL(mtd_write);
@@ -982,6 +986,8 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
        ops->retlen = ops->oobretlen = 0;
        if (!mtd->_read_oob)
                return -EOPNOTSUPP;
+
+       ledtrig_mtd_activity();
        /*
         * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics
         * similar to mtd->_read(), returning a non-negative integer
@@ -997,6 +1003,19 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
 }
 EXPORT_SYMBOL_GPL(mtd_read_oob);
 
+int mtd_write_oob(struct mtd_info *mtd, loff_t to,
+                               struct mtd_oob_ops *ops)
+{
+       ops->retlen = ops->oobretlen = 0;
+       if (!mtd->_write_oob)
+               return -EOPNOTSUPP;
+       if (!(mtd->flags & MTD_WRITEABLE))
+               return -EROFS;
+       ledtrig_mtd_activity();
+       return mtd->_write_oob(mtd, to, ops);
+}
+EXPORT_SYMBOL_GPL(mtd_write_oob);
+
 /*
  * Method to access the protection register area, present in some flash
  * devices. The user data is one time programmable but the factory data is read
index 557b8462f55ed6f46961d2201affedd2c2746401..ba4f603e05375b32de7bf01f3bde05967bc0268e 100644 (file)
@@ -43,7 +43,6 @@
 #include <linux/mtd/nand_bch.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
-#include <linux/leds.h>
 #include <linux/io.h>
 #include <linux/mtd/partitions.h>
 #include <linux/of_mtd.h>
@@ -97,12 +96,6 @@ static int nand_get_device(struct mtd_info *mtd, int new_state);
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
                             struct mtd_oob_ops *ops);
 
-/*
- * For devices which display every fart in the system on a separate LED. Is
- * compiled away when LED support is disabled.
- */
-DEFINE_LED_TRIGGER(nand_led_trigger);
-
 static int check_offs_len(struct mtd_info *mtd,
                                        loff_t ofs, uint64_t len)
 {
@@ -540,19 +533,16 @@ void nand_wait_ready(struct mtd_info *mtd)
        if (in_interrupt() || oops_in_progress)
                return panic_nand_wait_ready(mtd, timeo);
 
-       led_trigger_event(nand_led_trigger, LED_FULL);
        /* Wait until command is processed or timeout occurs */
        timeo = jiffies + msecs_to_jiffies(timeo);
        do {
                if (chip->dev_ready(mtd))
-                       goto out;
+                       return;
                cond_resched();
        } while (time_before(jiffies, timeo));
 
        if (!chip->dev_ready(mtd))
                pr_warn_ratelimited("timeout while waiting for chip to become ready\n");
-out:
-       led_trigger_event(nand_led_trigger, LED_OFF);
 }
 EXPORT_SYMBOL_GPL(nand_wait_ready);
 
@@ -885,8 +875,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
        int status;
        unsigned long timeo = 400;
 
-       led_trigger_event(nand_led_trigger, LED_FULL);
-
        /*
         * Apply this short delay always to ensure that we do wait tWB in any
         * case on any machine.
@@ -910,7 +898,6 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
                        cond_resched();
                } while (time_before(jiffies, timeo));
        }
-       led_trigger_event(nand_led_trigger, LED_OFF);
 
        status = (int)chip->read_byte(mtd);
        /* This can happen if in case of timeout or buggy dev_ready */
@@ -4466,20 +4453,6 @@ void nand_release(struct mtd_info *mtd)
 }
 EXPORT_SYMBOL_GPL(nand_release);
 
-static int __init nand_base_init(void)
-{
-       led_trigger_register_simple("nand-disk", &nand_led_trigger);
-       return 0;
-}
-
-static void __exit nand_base_exit(void)
-{
-       led_trigger_unregister_simple(nand_led_trigger);
-}
-
-module_init(nand_base_init);
-module_exit(nand_base_exit);
-
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steven J. Hill <sjhill@realitydiluted.com>");
 MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
index f203a8f89d30d0f3e214b43d2c72efea1bdad9f9..d2b13066e78155ccacc072afcd75a2ae2bcb23fa 100644 (file)
@@ -50,6 +50,7 @@ struct led_classdev {
 #define LED_SYSFS_DISABLE      (1 << 22)
 #define LED_DEV_CAP_FLASH      (1 << 23)
 #define LED_HW_PLUGGABLE       (1 << 24)
+#define LED_PANIC_INDICATOR    (1 << 25)
 
        /* Set LED brightness level
         * Must not sleep. Use brightness_set_blocking for drivers
@@ -329,6 +330,12 @@ extern void ledtrig_ide_activity(void);
 static inline void ledtrig_ide_activity(void) {}
 #endif
 
+#ifdef CONFIG_LEDS_TRIGGER_MTD
+extern void ledtrig_mtd_activity(void);
+#else
+static inline void ledtrig_mtd_activity(void) {}
+#endif
+
 #if defined(CONFIG_LEDS_TRIGGER_CAMERA) || defined(CONFIG_LEDS_TRIGGER_CAMERA_MODULE)
 extern void ledtrig_flash_ctrl(bool on);
 extern void ledtrig_torch_ctrl(bool on);
@@ -358,6 +365,7 @@ struct gpio_led {
        unsigned        gpio;
        unsigned        active_low : 1;
        unsigned        retain_state_suspended : 1;
+       unsigned        panic_indicator : 1;
        unsigned        default_state : 2;
        /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
        struct gpio_desc *gpiod;
index 771272187316b3c1bc5e5f3cbd9b07072c7bd55c..ef9fea4fc40080dd5832d70405bbd87e2a605339 100644 (file)
@@ -283,17 +283,7 @@ int mtd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
                    const u_char *buf);
 
 int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
-
-static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to,
-                               struct mtd_oob_ops *ops)
-{
-       ops->retlen = ops->oobretlen = 0;
-       if (!mtd->_write_oob)
-               return -EOPNOTSUPP;
-       if (!(mtd->flags & MTD_WRITEABLE))
-               return -EROFS;
-       return mtd->_write_oob(mtd, to, ops);
-}
+int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
 
 int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
                           struct otp_info *buf);