summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/compat.h329
-rw-r--r--include/linux/err.h17
-rw-r--r--include/linux/list_sort.h11
-rw-r--r--include/linux/mtd/bbm.h73
-rw-r--r--include/linux/mtd/concat.h4
-rw-r--r--include/linux/mtd/flashchip.h105
-rw-r--r--include/linux/mtd/mtd.h285
-rw-r--r--include/linux/mtd/nand.h450
-rw-r--r--include/linux/mtd/partitions.h60
-rw-r--r--include/linux/mtd/ubi.h120
-rw-r--r--include/linux/rbtree.h147
-rw-r--r--include/linux/rbtree_augmented.h220
-rw-r--r--include/linux/usb/gadget.h6
13 files changed, 1448 insertions, 379 deletions
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 35e216e06e..7ff6064b18 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -1,6 +1,19 @@
#ifndef _LINUX_COMPAT_H_
#define _LINUX_COMPAT_H_
+#include <malloc.h>
+#include <linux/types.h>
+#include <linux/err.h>
+
+struct unused {};
+typedef struct unused unused_t;
+
+struct p_current{
+ int pid;
+};
+
+extern struct p_current *current;
+
#define ndelay(x) udelay(1)
#define dev_dbg(dev, fmt, args...) \
@@ -12,6 +25,7 @@
#define dev_err(dev, fmt, args...) \
printf(fmt, ##args)
#define printk printf
+#define printk_once printf
#define KERN_EMERG
#define KERN_ALERT
@@ -22,11 +36,20 @@
#define KERN_INFO
#define KERN_DEBUG
-#define kmalloc(size, flags) malloc(size)
-#define kzalloc(size, flags) calloc(size, 1)
-#define vmalloc(size) malloc(size)
-#define kfree(ptr) free(ptr)
-#define vfree(ptr) free(ptr)
+void *kmalloc(size_t size, int flags);
+void *kzalloc(size_t size, int flags);
+#define vmalloc(size) kmalloc(size, 0)
+#define __vmalloc(size, flags, pgsz) kmalloc(size, flags)
+#define kfree(ptr) free(ptr)
+#define vfree(ptr) free(ptr)
+
+struct kmem_cache { int sz; };
+
+struct kmem_cache *get_mem(int element_sz);
+#define kmem_cache_create(a, sz, c, d, e) get_mem(sz)
+void *kmem_cache_alloc(struct kmem_cache *obj, int flag);
+#define kmem_cache_free(obj, size) free(size)
+#define kmem_cache_destroy(obj) free(obj)
#define DECLARE_WAITQUEUE(...) do { } while (0)
#define add_wait_queue(...) do { } while (0)
@@ -76,4 +99,300 @@
*/
#define lower_32_bits(n) ((u32)(n))
+/* drivers/char/random.c */
+#define get_random_bytes(...)
+
+/* idr.c */
+#define GFP_ATOMIC ((gfp_t) 0)
+#define GFP_KERNEL ((gfp_t) 0)
+#define GFP_NOFS ((gfp_t) 0)
+#define GFP_USER ((gfp_t) 0)
+#define __GFP_NOWARN ((gfp_t) 0)
+
+/* include/linux/leds.h */
+struct led_trigger {};
+
+#define DEFINE_LED_TRIGGER(x) static struct led_trigger *x;
+enum led_brightness {
+ LED_OFF = 0,
+ LED_HALF = 127,
+ LED_FULL = 255,
+};
+
+static inline void led_trigger_register_simple(const char *name,
+ struct led_trigger **trigger) {}
+static inline void led_trigger_unregister_simple(struct led_trigger *trigger) {}
+static inline void led_trigger_event(struct led_trigger *trigger,
+ enum led_brightness event) {}
+
+/* include/linux/log2.h */
+static inline int is_power_of_2(unsigned long n)
+{
+ return (n != 0 && ((n & (n - 1)) == 0));
+}
+
+/* uapi/linux/limits.h */
+#define XATTR_LIST_MAX 65536 /* size of extended attribute namelist (64k) */
+
+/**
+ * The type used for indexing onto a disc or disc partition.
+ *
+ * Linux always considers sectors to be 512 bytes long independently
+ * of the devices real block size.
+ *
+ * blkcnt_t is the type of the inode's block count.
+ */
+#ifdef CONFIG_LBDAF
+typedef u64 sector_t;
+typedef u64 blkcnt_t;
+#else
+typedef unsigned long sector_t;
+typedef unsigned long blkcnt_t;
+#endif
+
+#define ENOTSUPP 524 /* Operation is not supported */
+
+/* from include/linux/kernel.h */
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
+/* module */
+#define THIS_MODULE 0
+#define try_module_get(...) 1
+#define module_put(...) do { } while (0)
+#define module_init(...)
+#define module_exit(...)
+#define EXPORT_SYMBOL(...)
+#define EXPORT_SYMBOL_GPL(...)
+#define module_param(...)
+#define module_param_call(...)
+#define MODULE_PARM_DESC(...)
+#define MODULE_VERSION(...)
+#define MODULE_DESCRIPTION(...)
+#define MODULE_AUTHOR(...)
+#define MODULE_LICENSE(...)
+#define MODULE_ALIAS(...)
+#define __module_get(...)
+
+/* character device */
+#define MKDEV(...) 0
+#define MAJOR(dev) 0
+#define MINOR(dev) 0
+
+#define alloc_chrdev_region(...) 0
+#define unregister_chrdev_region(...)
+
+#define class_create(...) __builtin_return_address(0)
+#define class_create_file(...) 0
+#define class_remove_file(...)
+#define class_destroy(...)
+#define misc_register(...) 0
+#define misc_deregister(...)
+
+#define blocking_notifier_call_chain(...) 0
+
+/*
+ * Multiplies an integer by a fraction, while avoiding unnecessary
+ * overflow or loss of precision.
+ */
+#define mult_frac(x, numer, denom)( \
+{ \
+ typeof(x) quot = (x) / (denom); \
+ typeof(x) rem = (x) % (denom); \
+ (quot * (numer)) + ((rem * (numer)) / (denom)); \
+} \
+)
+
+#define __initdata
+#define late_initcall(...)
+
+#define dev_set_name(...) do { } while (0)
+#define device_register(...) 0
+#define volume_sysfs_init(...) 0
+#define volume_sysfs_close(...) do { } while (0)
+
+#define init_waitqueue_head(...) do { } while (0)
+#define wait_event_interruptible(...) 0
+#define wake_up_interruptible(...) do { } while (0)
+#define print_hex_dump(...) do { } while (0)
+#define dump_stack(...) do { } while (0)
+
+#define task_pid_nr(x) 0
+#define set_freezable(...) do { } while (0)
+#define try_to_freeze(...) 0
+#define set_current_state(...) do { } while (0)
+#define kthread_should_stop(...) 0
+#define schedule() do { } while (0)
+
+#define setup_timer(timer, func, data) do {} while (0)
+#define del_timer_sync(timer) do {} while (0)
+#define schedule_work(work) do {} while (0)
+#define INIT_WORK(work, fun) do {} while (0)
+
+struct work_struct {};
+
+unsigned long copy_from_user(void *dest, const void *src,
+ unsigned long count);
+
+void *vzalloc(unsigned long size);
+
+typedef unused_t spinlock_t;
+typedef int wait_queue_head_t;
+
+#define spin_lock_init(lock) do {} while (0)
+#define spin_lock(lock) do {} while (0)
+#define spin_unlock(lock) do {} while (0)
+#define spin_lock_irqsave(lock, flags) do { debug("%lu\n", flags); } while (0)
+#define spin_unlock_irqrestore(lock, flags) do { flags = 0; } while (0)
+
+#define DEFINE_MUTEX(...)
+#define mutex_init(...)
+#define mutex_lock(...)
+#define mutex_unlock(...)
+
+#define init_rwsem(...) do { } while (0)
+#define down_read(...) do { } while (0)
+#define down_write(...) do { } while (0)
+#define down_write_trylock(...) 1
+#define up_read(...) do { } while (0)
+#define up_write(...) do { } while (0)
+
+#define cond_resched() do { } while (0)
+#define yield() do { } while (0)
+
+#define INT_MAX ((int)(~0U>>1))
+
+#define __user
+#define __init
+#define __exit
+#define __devinit
+#define __devinitdata
+#define __devinitconst
+#define __iomem
+
+#define kthread_create(...) __builtin_return_address(0)
+#define kthread_stop(...) do { } while (0)
+#define wake_up_process(...) do { } while (0)
+
+struct rw_semaphore { int i; };
+#define down_write(...) do { } while (0)
+#define up_write(...) do { } while (0)
+#define down_read(...) do { } while (0)
+#define up_read(...) do { } while (0)
+struct device {
+ struct device *parent;
+ struct class *class;
+ dev_t devt; /* dev_t, creates the sysfs "dev" */
+ void (*release)(struct device *dev);
+ /* This is used from drivers/usb/musb-new subsystem only */
+ void *driver_data; /* data private to the driver */
+ void *device_data; /* data private to the device */
+};
+struct mutex { int i; };
+struct kernel_param { int i; };
+
+struct cdev {
+ int owner;
+ dev_t dev;
+};
+#define cdev_init(...) do { } while (0)
+#define cdev_add(...) 0
+#define cdev_del(...) do { } while (0)
+
+#define MAX_ERRNO 4095
+
+#define prandom_u32(...) 0
+
+typedef struct {
+ uid_t val;
+} kuid_t;
+
+typedef struct {
+ gid_t val;
+} kgid_t;
+
+/* from include/linux/types.h */
+
+typedef int atomic_t;
+/**
+ * struct callback_head - callback structure for use with RCU and task_work
+ * @next: next update requests in a list
+ * @func: actual update function to call after the grace period.
+ */
+struct callback_head {
+ struct callback_head *next;
+ void (*func)(struct callback_head *head);
+};
+#define rcu_head callback_head
+enum writeback_sync_modes {
+ WB_SYNC_NONE, /* Don't wait on anything */
+ WB_SYNC_ALL, /* Wait on every mapping */
+};
+
+/* from include/linux/writeback.h */
+/*
+ * A control structure which tells the writeback code what to do. These are
+ * always on the stack, and hence need no locking. They are always initialised
+ * in a manner such that unspecified fields are set to zero.
+ */
+struct writeback_control {
+ long nr_to_write; /* Write this many pages, and decrement
+ this for each page written */
+ long pages_skipped; /* Pages which were not written */
+
+ /*
+ * For a_ops->writepages(): if start or end are non-zero then this is
+ * a hint that the filesystem need only write out the pages inside that
+ * byterange. The byte at `end' is included in the writeout request.
+ */
+ loff_t range_start;
+ loff_t range_end;
+
+ enum writeback_sync_modes sync_mode;
+
+ unsigned for_kupdate:1; /* A kupdate writeback */
+ unsigned for_background:1; /* A background writeback */
+ unsigned tagged_writepages:1; /* tag-and-write to avoid livelock */
+ unsigned for_reclaim:1; /* Invoked from the page allocator */
+ unsigned range_cyclic:1; /* range_start is cyclic */
+ unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */
+};
+
+void *kmemdup(const void *src, size_t len, gfp_t gfp);
+
+typedef int irqreturn_t;
+
+struct timer_list {};
+struct notifier_block {};
+
+typedef unsigned long dmaaddr_t;
+
+#define cpu_relax() do {} while (0)
+
+#define pm_runtime_get_sync(dev) do {} while (0)
+#define pm_runtime_put(dev) do {} while (0)
+#define pm_runtime_put_sync(dev) do {} while (0)
+#define pm_runtime_use_autosuspend(dev) do {} while (0)
+#define pm_runtime_set_autosuspend_delay(dev, delay) do {} while (0)
+#define pm_runtime_enable(dev) do {} while (0)
+
+#define IRQ_NONE 0
+#define IRQ_HANDLED 1
+
+#define dev_set_drvdata(dev, data) do {} while (0)
+
+#define enable_irq(...)
+#define disable_irq(...)
+#define disable_irq_wake(irq) do {} while (0)
+#define enable_irq_wake(irq) -EINVAL
+#define free_irq(irq, data) do {} while (0)
+#define request_irq(nr, f, flags, nm, data) 0
+
#endif
diff --git a/include/linux/err.h b/include/linux/err.h
index 96c0c72baa..5b3c8bcf70 100644
--- a/include/linux/err.h
+++ b/include/linux/err.h
@@ -1,12 +1,8 @@
#ifndef _LINUX_ERR_H
#define _LINUX_ERR_H
-/* XXX U-BOOT XXX */
-#if 0
#include <linux/compiler.h>
-#else
#include <linux/compat.h>
-#endif
#include <asm/errno.h>
@@ -40,6 +36,19 @@ static inline long IS_ERR(const void *ptr)
return IS_ERR_VALUE((unsigned long)ptr);
}
+/**
+ * ERR_CAST - Explicitly cast an error-valued pointer to another pointer type
+ * @ptr: The pointer to cast.
+ *
+ * Explicitly cast an error-valued pointer to another pointer type in such a
+ * way as to make it clear that's what's going on.
+ */
+static inline void * __must_check ERR_CAST(__force const void *ptr)
+{
+ /* cast away the const */
+ return (void *) ptr;
+}
+
#endif
#endif /* _LINUX_ERR_H */
diff --git a/include/linux/list_sort.h b/include/linux/list_sort.h
new file mode 100644
index 0000000000..1a2df2efb7
--- /dev/null
+++ b/include/linux/list_sort.h
@@ -0,0 +1,11 @@
+#ifndef _LINUX_LIST_SORT_H
+#define _LINUX_LIST_SORT_H
+
+#include <linux/types.h>
+
+struct list_head;
+
+void list_sort(void *priv, struct list_head *head,
+ int (*cmp)(void *priv, struct list_head *a,
+ struct list_head *b));
+#endif
diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h
index 25a3d3a3d1..be81d3824a 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -4,13 +4,14 @@
* NAND family Bad Block Management (BBM) header file
* - Bad Block Table (BBT) implementation
*
- * Copyright (c) 2005-2007 Samsung Electronics
+ * Copyright © 2005 Samsung Electronics
* Kyungmin Park <kyungmin.park@samsung.com>
*
- * Copyright (c) 2000-2005
+ * Copyright © 2000-2005
* Thomas Gleixner <tglx@linuxtronix.de>
*
* SPDX-License-Identifier: GPL-2.0+
+ *
*/
#ifndef __LINUX_MTD_BBM_H
#define __LINUX_MTD_BBM_H
@@ -22,22 +23,21 @@
/**
* struct nand_bbt_descr - bad block table descriptor
- * @param options options for this descriptor
- * @param pages the page(s) where we find the bbt, used with
- * option BBT_ABSPAGE when bbt is searched,
- * then we store the found bbts pages here.
- * Its an array and supports up to 8 chips now
- * @param offs offset of the pattern in the oob area of the page
- * @param veroffs offset of the bbt version counter in the oob are of the page
- * @param version version read from the bbt page during scan
- * @param len length of the pattern, if 0 no pattern check is performed
- * @param maxblocks maximum number of blocks to search for a bbt. This number of
- * blocks is reserved at the end of the device
- * where the tables are written.
- * @param reserved_block_code if non-0, this pattern denotes a reserved
- * (rather than bad) block in the stored bbt
- * @param pattern pattern to identify bad block table or factory marked
- * good / bad blocks, can be NULL, if len = 0
+ * @options: options for this descriptor
+ * @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE
+ * when bbt is searched, then we store the found bbts pages here.
+ * Its an array and supports up to 8 chips now
+ * @offs: offset of the pattern in the oob area of the page
+ * @veroffs: offset of the bbt version counter in the oob are of the page
+ * @version: version read from the bbt page during scan
+ * @len: length of the pattern, if 0 no pattern check is performed
+ * @maxblocks: maximum number of blocks to search for a bbt. This number of
+ * blocks is reserved at the end of the device where the tables are
+ * written.
+ * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than
+ * bad) block in the stored bbt
+ * @pattern: pattern to identify bad block table or factory marked good /
+ * bad blocks, can be NULL, if len = 0
*
* Descriptor for the bad block table marker and the descriptor for the
* pattern which identifies good and bad blocks. The assumption is made
@@ -81,10 +81,6 @@ struct nand_bbt_descr {
* with NAND_BBT_CREATE.
*/
#define NAND_BBT_CREATE_EMPTY 0x00000400
-/* Search good / bad pattern through all pages of a block */
-#define NAND_BBT_SCANALLPAGES 0x00000800
-/* Scan block empty during good / bad block scan */
-#define NAND_BBT_SCANEMPTY 0x00001000
/* Write bbt if neccecary */
#define NAND_BBT_WRITE 0x00002000
/* Read and write back block contents when writing bbt */
@@ -122,22 +118,27 @@ struct nand_bbt_descr {
/*
* Constants for oob configuration
*/
-#define ONENAND_BADBLOCK_POS 0
+#define NAND_SMALL_BADBLOCK_POS 5
+#define NAND_LARGE_BADBLOCK_POS 0
+#define ONENAND_BADBLOCK_POS 0
/*
* Bad block scanning errors
*/
-#define ONENAND_BBT_READ_ERROR 1
-#define ONENAND_BBT_READ_ECC_ERROR 2
-#define ONENAND_BBT_READ_FATAL_ERROR 4
+#define ONENAND_BBT_READ_ERROR 1
+#define ONENAND_BBT_READ_ECC_ERROR 2
+#define ONENAND_BBT_READ_FATAL_ERROR 4
/**
- * struct bbt_info - [GENERIC] Bad Block Table data structure
- * @param bbt_erase_shift [INTERN] number of address bits in a bbt entry
- * @param badblockpos [INTERN] position of the bad block marker in the oob area
- * @param bbt [INTERN] bad block table pointer
- * @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan
- * @param priv [OPTIONAL] pointer to private bbm date
+ * struct bbm_info - [GENERIC] Bad Block Table data structure
+ * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
+ * @badblockpos: [INTERN] position of the bad block marker in the oob area
+ * @options: options for this descriptor
+ * @bbt: [INTERN] bad block table pointer
+ * @isbad_bbt: function to determine if a block is bad
+ * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for
+ * initial bad block scan
+ * @priv: [OPTIONAL] pointer to private bbm date
*/
struct bbm_info {
int bbt_erase_shift;
@@ -146,7 +147,7 @@ struct bbm_info {
uint8_t *bbt;
- int (*isbad_bbt) (struct mtd_info * mtd, loff_t ofs, int allowbbt);
+ int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt);
/* TODO Add more NAND specific fileds */
struct nand_bbt_descr *badblock_pattern;
@@ -155,7 +156,7 @@ struct bbm_info {
};
/* OneNAND BBT interface */
-extern int onenand_scan_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int onenand_default_bbt (struct mtd_info *mtd);
+extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
+extern int onenand_default_bbt(struct mtd_info *mtd);
-#endif /* __LINUX_MTD_BBM_H */
+#endif /* __LINUX_MTD_BBM_H */
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h
index c92b4ddc9b..195a4a5426 100644
--- a/include/linux/mtd/concat.h
+++ b/include/linux/mtd/concat.h
@@ -12,7 +12,11 @@
struct mtd_info *mtd_concat_create(
struct mtd_info *subdev[], /* subdevices to concatenate */
int num_devs, /* number of subdevices */
+#ifndef __UBOOT__
const char *name); /* name for the new device */
+#else
+ char *name); /* name for the new device */
+#endif
void mtd_concat_destroy(struct mtd_info *mtd);
diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h
new file mode 100644
index 0000000000..7028ee1e77
--- /dev/null
+++ b/include/linux/mtd/flashchip.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright © 2000 Red Hat UK Limited
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+
+#ifndef __MTD_FLASHCHIP_H__
+#define __MTD_FLASHCHIP_H__
+
+#define __UBOOT__
+#ifndef __UBOOT__
+/* For spinlocks. sched.h includes spinlock.h from whichever directory it
+ * happens to be in - so we don't have to care whether we're on 2.2, which
+ * has asm/spinlock.h, or 2.4, which has linux/spinlock.h
+ */
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#endif
+
+typedef enum {
+ FL_READY,
+ FL_STATUS,
+ FL_CFI_QUERY,
+ FL_JEDEC_QUERY,
+ FL_ERASING,
+ FL_ERASE_SUSPENDING,
+ FL_ERASE_SUSPENDED,
+ FL_WRITING,
+ FL_WRITING_TO_BUFFER,
+ FL_OTP_WRITE,
+ FL_WRITE_SUSPENDING,
+ FL_WRITE_SUSPENDED,
+ FL_PM_SUSPENDED,
+ FL_SYNCING,
+ FL_UNLOADING,
+ FL_LOCKING,
+ FL_UNLOCKING,
+ FL_POINT,
+ FL_XIP_WHILE_ERASING,
+ FL_XIP_WHILE_WRITING,
+ FL_SHUTDOWN,
+ /* These 2 come from nand_state_t, which has been unified here */
+ FL_READING,
+ FL_CACHEDPRG,
+ /* These 4 come from onenand_state_t, which has been unified here */
+ FL_RESETING,
+ FL_OTPING,
+ FL_PREPARING_ERASE,
+ FL_VERIFYING_ERASE,
+
+ FL_UNKNOWN
+} flstate_t;
+
+
+
+/* NOTE: confusingly, this can be used to refer to more than one chip at a time,
+ if they're interleaved. This can even refer to individual partitions on
+ the same physical chip when present. */
+
+struct flchip {
+ unsigned long start; /* Offset within the map */
+ // unsigned long len;
+ /* We omit len for now, because when we group them together
+ we insist that they're all of the same size, and the chip size
+ is held in the next level up. If we get more versatile later,
+ it'll make it a damn sight harder to find which chip we want from
+ a given offset, and we'll want to add the per-chip length field
+ back in.
+ */
+ int ref_point_counter;
+ flstate_t state;
+ flstate_t oldstate;
+
+ unsigned int write_suspended:1;
+ unsigned int erase_suspended:1;
+ unsigned long in_progress_block_addr;
+
+ struct mutex mutex;
+#ifndef __UBOOT__
+ wait_queue_head_t wq; /* Wait on here when we're waiting for the chip
+ to be ready */
+#endif
+ int word_write_time;
+ int buffer_write_time;
+ int erase_time;
+
+ int word_write_time_max;
+ int buffer_write_time_max;
+ int erase_time_max;
+
+ void *priv;
+};
+
+/* This is used to handle contention on write/erase operations
+ between partitions of the same physical chip. */
+struct flchip_shared {
+ struct mutex lock;
+ struct flchip *writing;
+ struct flchip *erasing;
+};
+
+
+#endif /* __MTD_FLASHCHIP_H__ */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index a65b681551..1526d075c7 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -1,48 +1,45 @@
/*
- * Copyright (C) 1999-2003 David Woodhouse <dwmw2@infradead.org> et al.
+ * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org> et al.
*
* Released under GPL
+ *
*/
#ifndef __MTD_MTD_H__
#define __MTD_MTD_H__
+#define __UBOOT__
+#ifndef __UBOOT__
#include <linux/types.h>
-#include <div64.h>
+#include <linux/uio.h>
+#include <linux/notifier.h>
+#include <linux/device.h>
+
+#include <mtd/mtd-abi.h>
+
+#include <asm/div64.h>
+#else
+#include <linux/compat.h>
#include <mtd/mtd-abi.h>
#include <asm/errno.h>
+#include <div64.h>
-#define MTD_CHAR_MAJOR 90
-#define MTD_BLOCK_MAJOR 31
#define MAX_MTD_DEVICES 32
+#endif
#define MTD_ERASE_PENDING 0x01
#define MTD_ERASING 0x02
#define MTD_ERASE_SUSPEND 0x04
-#define MTD_ERASE_DONE 0x08
-#define MTD_ERASE_FAILED 0x10
+#define MTD_ERASE_DONE 0x08
+#define MTD_ERASE_FAILED 0x10
-#define MTD_FAIL_ADDR_UNKNOWN -1LL
+#define MTD_FAIL_ADDR_UNKNOWN -1LL
/*
- * Enumeration for NAND/OneNAND flash chip state
+ * If the erase fails, fail_addr might indicate exactly which block failed. If
+ * fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level
+ * or was not specific to any particular block.
*/
-enum {
- FL_READY,
- FL_READING,
- FL_WRITING,
- FL_ERASING,
- FL_SYNCING,
- FL_CACHEDPRG,
- FL_RESETING,
- FL_UNLOCKING,
- FL_LOCKING,
- FL_PM_SUSPENDED,
-};
-
-/* If the erase fails, fail_addr might indicate exactly which block failed. If
- fail_addr = MTD_FAIL_ADDR_UNKNOWN, the failure was not at the device level or was not
- specific to any particular block. */
struct erase_info {
struct mtd_info *mtd;
uint64_t addr;
@@ -50,8 +47,8 @@ struct erase_info {
uint64_t fail_addr;
u_long time;
u_long retries;
- u_int dev;
- u_int cell;
+ unsigned dev;
+ unsigned cell;
void (*callback) (struct erase_info *self);
u_long priv;
u_char state;
@@ -60,9 +57,9 @@ struct erase_info {
};
struct mtd_erase_region_info {
- uint64_t offset; /* At which this region starts, from the beginning of the MTD */
- u_int32_t erasesize; /* For this region */
- u_int32_t numblocks; /* Number of blocks of erasesize in this region */
+ uint64_t offset; /* At which this region starts, from the beginning of the MTD */
+ uint32_t erasesize; /* For this region */
+ uint32_t numblocks; /* Number of blocks of erasesize in this region */
unsigned long *lockmap; /* If keeping bitmap of locks */
};
@@ -81,7 +78,7 @@ struct mtd_erase_region_info {
* @datbuf: data buffer - if NULL only oob data are read/written
* @oobbuf: oob data buffer
*
- * Note, it is allowed to read more then one OOB area at one go, but not write.
+ * Note, it is allowed to read more than one OOB area at one go, but not write.
* The interface assumes that the OOB write requests program only one page's
* OOB area.
*/
@@ -109,26 +106,30 @@ struct mtd_oob_ops {
#endif
/*
- * ECC layout control structure. Exported to userspace for
- * diagnosis and to allow creation of raw images
+ * Internal ECC layout control structure. For historical reasons, there is a
+ * similar, smaller struct nand_ecclayout_user (in mtd-abi.h) that is retained
+ * for export to user-space via the ECCGETLAYOUT ioctl.
+ * nand_ecclayout should be expandable in the future simply by the above macros.
*/
struct nand_ecclayout {
- uint32_t eccbytes;
- uint32_t eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
- uint32_t oobavail;
+ __u32 eccbytes;
+ __u32 eccpos[MTD_MAX_ECCPOS_ENTRIES_LARGE];
+ __u32 oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES_LARGE];
};
+struct module; /* only needed for owner field in mtd_info */
+
struct mtd_info {
u_char type;
- u_int32_t flags;
- uint64_t size; /* Total size of the MTD */
+ uint32_t flags;
+ uint64_t size; // Total size of the MTD
/* "Major" erase size for the device. Naïve users may take this
* to be the only erase size available, or may use the more detailed
* information below if they desire
*/
- u_int32_t erasesize;
+ uint32_t erasesize;
/* Minimal writable flash unit size. In case of NOR flash it is 1 (even
* though individual bits can be cleared), in case of NAND flash it is
* one NAND page (or half, or one-fourths of it), in case of ECC-ed NOR
@@ -136,10 +137,31 @@ struct mtd_info {
* Any driver registering a struct mtd_info must ensure a writesize of
* 1 or larger.
*/
- u_int32_t writesize;
+ uint32_t writesize;
+
+ /*
+ * Size of the write buffer used by the MTD. MTD devices having a write
+ * buffer can write multiple writesize chunks at a time. E.g. while
+ * writing 4 * writesize bytes to a device with 2 * writesize bytes
+ * buffer the MTD driver can (but doesn't have to) do 2 writesize
+ * operations, but not 4. Currently, all NANDs have writebufsize
+ * equivalent to writesize (NAND page size). Some NOR flashes do have
+ * writebufsize greater than writesize.
+ */
+ uint32_t writebufsize;
- u_int32_t oobsize; /* Amount of OOB data per block (e.g. 16) */
- u_int32_t oobavail; /* Available OOB bytes per block */
+ uint32_t oobsize; // Amount of OOB data per block (e.g. 16)
+ uint32_t oobavail; // Available OOB bytes per block
+
+ /*
+ * If erasesize is a power of 2 then the shift is stored in
+ * erasesize_shift otherwise erasesize_shift is zero. Ditto writesize.
+ */
+ unsigned int erasesize_shift;
+ unsigned int writesize_shift;
+ /* Masks based on erasesize_shift and writesize_shift */
+ unsigned int erasesize_mask;
+ unsigned int writesize_mask;
/*
* read ops return -EUCLEAN if max number of bitflips corrected on any
@@ -150,13 +172,20 @@ struct mtd_info {
*/
unsigned int bitflip_threshold;
- /* Kernel-only stuff starts here. */
+ // Kernel-only stuff starts here.
+#ifndef __UBOOT__
const char *name;
+#else
+ char *name;
+#endif
int index;
/* ECC layout structure pointer - read only! */
struct nand_ecclayout *ecclayout;
+ /* the ecc step size. */
+ unsigned int ecc_step_size;
+
/* max number of correctible bit errors per ecc step */
unsigned int ecc_strength;
@@ -171,44 +200,51 @@ struct mtd_info {
* wrappers instead.
*/
int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
+#ifndef __UBOOT__
int (*_point) (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, void **virt, phys_addr_t *phys);
- void (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
+ size_t *retlen, void **virt, resource_size_t *phys);
+ int (*_unpoint) (struct mtd_info *mtd, loff_t from, size_t len);
+#endif
+ unsigned long (*_get_unmapped_area) (struct mtd_info *mtd,
+ unsigned long len,
+ unsigned long offset,
+ unsigned long flags);
int (*_read) (struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf);
+ size_t *retlen, u_char *buf);
int (*_write) (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf);
-
- /* In blackbox flight recorder like scenarios we want to make successful
- writes in interrupt context. panic_write() is only intended to be
- called when its known the kernel is about to panic and we need the
- write to succeed. Since the kernel is not going to be running for much
- longer, this function can break locks and delay to ensure the write
- succeeds (but not sleep). */
-
- int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
+ size_t *retlen, const u_char *buf);
+ int (*_panic_write) (struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf);
int (*_read_oob) (struct mtd_info *mtd, loff_t from,
- struct mtd_oob_ops *ops);
+ struct mtd_oob_ops *ops);
int (*_write_oob) (struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops);
- int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf,
- size_t len);
+ struct mtd_oob_ops *ops);
+ int (*_get_fact_prot_info) (struct mtd_info *mtd, size_t len,
+ size_t *retlen, struct otp_info *buf);
int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from,
- size_t len, size_t *retlen, u_char *buf);
- int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf,
- size_t len);
+ size_t len, size_t *retlen, u_char *buf);
+ int (*_get_user_prot_info) (struct mtd_info *mtd, size_t len,
+ size_t *retlen, struct otp_info *buf);
int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from,
- size_t len, size_t *retlen, u_char *buf);
- int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, u_char *buf);
+ size_t len, size_t *retlen, u_char *buf);
+ int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t to,
+ size_t len, size_t *retlen, u_char *buf);
int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from,
- size_t len);
+ size_t len);
+#ifndef __UBOOT__
+ int (*_writev) (struct mtd_info *mtd, const struct kvec *vecs,
+ unsigned long count, loff_t to, size_t *retlen);
+#endif
void (*_sync) (struct mtd_info *mtd);
int (*_lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
int (*_unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
+ int (*_is_locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len);
int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
+#ifndef __UBOOT__
+ int (*_suspend) (struct mtd_info *mtd);
+ void (*_resume) (struct mtd_info *mtd);
+#endif
/*
* If the driver is something smart, like UBI, it may need to maintain
* its own reference counting. The below functions are only for driver.
@@ -216,16 +252,12 @@ struct mtd_info {
int (*_get_device) (struct mtd_info *mtd);
void (*_put_device) (struct mtd_info *mtd);
-/* XXX U-BOOT XXX */
-#if 0
- /* kvec-based read/write methods.
- NB: The 'count' parameter is the number of _vectors_, each of
- which contains an (ofs, len) tuple.
- */
- int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen);
-#endif
-/* XXX U-BOOT XXX */
-#if 0
+#ifndef __UBOOT__
+ /* Backing device capabilities for this device
+ * - provides mmap capabilities
+ */
+ struct backing_dev_info *backing_dev_info;
+
struct notifier_block reboot_notifier; /* default mode before reboot */
#endif
@@ -237,10 +269,20 @@ struct mtd_info {
void *priv;
struct module *owner;
+#ifndef __UBOOT__
+ struct device dev;
+#endif
int usecount;
};
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
+#ifndef __UBOOT__
+int mtd_point(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
+ void **virt, resource_size_t *phys);
+int mtd_unpoint(struct mtd_info *mtd, loff_t from, size_t len);
+#endif
+unsigned long mtd_get_unmapped_area(struct mtd_info *mtd, unsigned long len,
+ unsigned long offset, unsigned long flags);
int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf);
int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
@@ -261,20 +303,19 @@ static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to,
return mtd->_write_oob(mtd, to, ops);
}
-int mtd_get_fact_prot_info(struct mtd_info *mtd, struct otp_info *buf,
- size_t len);
+int mtd_get_fact_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
+ struct otp_info *buf);
int mtd_read_fact_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
-int mtd_get_user_prot_info(struct mtd_info *mtd, struct otp_info *buf,
- size_t len);
+int mtd_get_user_prot_info(struct mtd_info *mtd, size_t len, size_t *retlen,
+ struct otp_info *buf);
int mtd_read_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
int mtd_write_user_prot_reg(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, u_char *buf);
int mtd_lock_user_prot_reg(struct mtd_info *mtd, loff_t from, size_t len);
-/* XXX U-BOOT XXX */
-#if 0
+#ifndef __UBOOT__
int mtd_writev(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen);
#endif
@@ -291,22 +332,59 @@ int mtd_is_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len);
int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs);
+#ifndef __UBOOT__
+static inline int mtd_suspend(struct mtd_info *mtd)
+{
+ return mtd->_suspend ? mtd->_suspend(mtd) : 0;
+}
+
+static inline void mtd_resume(struct mtd_info *mtd)
+{
+ if (mtd->_resume)
+ mtd->_resume(mtd);
+}
+#endif
+
static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
{
+ if (mtd->erasesize_shift)
+ return sz >> mtd->erasesize_shift;
do_div(sz, mtd->erasesize);
return sz;
}
static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
{
+ if (mtd->erasesize_shift)
+ return sz & mtd->erasesize_mask;
return do_div(sz, mtd->erasesize);
}
+static inline uint32_t mtd_div_by_ws(uint64_t sz, struct mtd_info *mtd)
+{
+ if (mtd->writesize_shift)
+ return sz >> mtd->writesize_shift;
+ do_div(sz, mtd->writesize);
+ return sz;
+}
+
+static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
+{
+ if (mtd->writesize_shift)
+ return sz & mtd->writesize_mask;
+ return do_div(sz, mtd->writesize);
+}
+
static inline int mtd_has_oob(const struct mtd_info *mtd)
{
return mtd->_read_oob && mtd->_write_oob;
}
+static inline int mtd_type_is_nand(const struct mtd_info *mtd)
+{
+ return mtd->type == MTD_NANDFLASH || mtd->type == MTD_MLCNANDFLASH;
+}
+
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
{
return !!mtd->_block_isbad;
@@ -314,27 +392,36 @@ static inline int mtd_can_have_bb(const struct mtd_info *mtd)
/* Kernel-side ioctl definitions */
-extern int add_mtd_device(struct mtd_info *mtd);
-extern int del_mtd_device (struct mtd_info *mtd);
-
+struct mtd_partition;
+struct mtd_part_parser_data;
+
+extern int mtd_device_parse_register(struct mtd_info *mtd,
+ const char * const *part_probe_types,
+ struct mtd_part_parser_data *parser_data,
+ const struct mtd_partition *defparts,
+ int defnr_parts);
+#define mtd_device_register(master, parts, nr_parts) \
+ mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
+extern int mtd_device_unregister(struct mtd_info *master);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
+extern int __get_mtd_device(struct mtd_info *mtd);
+extern void __put_mtd_device(struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device_nm(const char *name);
-
extern void put_mtd_device(struct mtd_info *mtd);
-extern void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
- const uint64_t length, uint64_t *len_incl_bad,
- int *truncated);
-/* XXX U-BOOT XXX */
-#if 0
+
+
+#ifndef __UBOOT__
struct mtd_notifier {
void (*add)(struct mtd_info *mtd);
void (*remove)(struct mtd_info *mtd);
struct list_head list;
};
+
extern void register_mtd_user (struct mtd_notifier *new);
extern int unregister_mtd_user (struct mtd_notifier *old);
#endif
+void *mtd_kmalloc_up_to(const struct mtd_info *mtd, size_t *size);
#ifdef CONFIG_MTD_PARTITIONS
void mtd_erase_callback(struct erase_info *instr);
@@ -346,6 +433,7 @@ static inline void mtd_erase_callback(struct erase_info *instr)
}
#endif
+#ifdef __UBOOT__
/*
* Debugging macro and defines
*/
@@ -372,7 +460,11 @@ static inline void mtd_erase_callback(struct erase_info *instr)
#define pr_info(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)
#define pr_warn(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)
#define pr_err(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)
-
+#define pr_crit(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_cont(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#define pr_notice(args...) MTDDEBUG(MTD_DEBUG_LEVEL0, args)
+#endif
+
static inline int mtd_is_bitflip(int err) {
return err == -EUCLEAN;
}
@@ -385,4 +477,11 @@ static inline int mtd_is_bitflip_or_eccerr(int err) {
return mtd_is_bitflip(err) || mtd_is_eccerr(err);
}
+#ifdef __UBOOT__
+/* drivers/mtd/mtdcore.h */
+int add_mtd_device(struct mtd_info *mtd);
+int del_mtd_device(struct mtd_info *mtd);
+int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
+int del_mtd_partitions(struct mtd_info *);
+#endif
#endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 991bd8e63e..67d2651481 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -5,9 +5,7 @@
* Steven J. Hill <sjhill@realitydiluted.com>
* Thomas Gleixner <tglx@linutronix.de>
*
- * 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.
+ * SPDX-License-Identifier: GPL-2.0+
*
* Info:
* Contains standard defines and IDs for NAND flash devices
@@ -18,21 +16,32 @@
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/wait.h>
+#include <linux/spinlock.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/mtd/bbm.h>
+#else
#include "config.h"
#include "linux/compat.h"
#include "linux/mtd/mtd.h"
+#include "linux/mtd/flashchip.h"
#include "linux/mtd/bbm.h"
-
+#endif
struct mtd_info;
struct nand_flash_dev;
/* Scan and identify a NAND device */
-extern int nand_scan (struct mtd_info *mtd, int max_chips);
-/* Separate phases of nand_scan(), allowing board driver to intervene
- * and override command or ECC setup according to flash type */
+extern int nand_scan(struct mtd_info *mtd, int max_chips);
+/*
+ * Separate phases of nand_scan(), allowing board driver to intervene
+ * and override command or ECC setup according to flash type.
+ */
extern int nand_scan_ident(struct mtd_info *mtd, int max_chips,
- const struct nand_flash_dev *table);
+ struct nand_flash_dev *table);
extern int nand_scan_tail(struct mtd_info *mtd);
/* Free resources held by the NAND device */
@@ -41,13 +50,24 @@ extern void nand_release(struct mtd_info *mtd);
/* Internal helper for board drivers which need to override command function */
extern void nand_wait_ready(struct mtd_info *mtd);
+#ifndef __UBOOT__
+/* locks all blocks present in the device */
+extern int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+
+/* unlocks specified locked blocks */
+extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+
+/* The maximum number of NAND chips in an array */
+#define NAND_MAX_CHIPS 8
+#else
/*
* This constant declares the max. oobsize / page, which
* is supported now. If you add a chip with bigger oobsize/page
* adjust this accordingly.
*/
-#define NAND_MAX_OOBSIZE 640
-#define NAND_MAX_PAGESIZE 8192
+#define NAND_MAX_OOBSIZE 744
+#define NAND_MAX_PAGESIZE 8192
+#endif
/*
* Constants for hardware specific CLE/ALE/NCE function
@@ -76,7 +96,6 @@ extern void nand_wait_ready(struct mtd_info *mtd);
#define NAND_CMD_READOOB 0x50
#define NAND_CMD_ERASE1 0x60
#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_STATUS_MULTI 0x71
#define NAND_CMD_SEQIN 0x80
#define NAND_CMD_RNDIN 0x85
#define NAND_CMD_READID 0x90
@@ -87,10 +106,8 @@ extern void nand_wait_ready(struct mtd_info *mtd);
#define NAND_CMD_RESET 0xff
#define NAND_CMD_LOCK 0x2a
-#define NAND_CMD_LOCK_TIGHT 0x2c
#define NAND_CMD_UNLOCK1 0x23
#define NAND_CMD_UNLOCK2 0x24
-#define NAND_CMD_LOCK_STATUS 0x7a
/* Extended commands for large page devices */
#define NAND_CMD_READSTART 0x30
@@ -164,21 +181,12 @@ typedef enum {
/* Chip has copy back function */
#define NAND_COPYBACK 0x00000010
/*
- * AND Chip which has 4 banks and a confusing page / block
- * assignment. See Renesas datasheet for further information.
+ * Chip requires ready check on read (for auto-incremented sequential read).
+ * True only for small page devices; large page devices do not support
+ * autoincrement.
*/
-#define NAND_IS_AND 0x00000020
-/*
- * Chip has a array of 4 pages which can be read without
- * additional ready /busy waits.
- */
-#define NAND_4PAGE_ARRAY 0x00000040
-/*
- * Chip requires that BBT is periodically rewritten to prevent
- * bits from adjacent blocks from 'leaking' in altering data.
- * This happens with the Renesas AG-AND chips, possibly others.
- */
-#define BBT_AUTO_REFRESH 0x00000080
+#define NAND_NEED_READRDY 0x00000100
+
/* Chip does not allow subpage writes */
#define NAND_NO_SUBPAGE_WRITE 0x00000200
@@ -189,16 +197,13 @@ typedef enum {
#define NAND_ROM 0x00000800
/* Device supports subpage reads */
-#define NAND_SUBPAGE_READ 0x00001000
+#define NAND_SUBPAGE_READ 0x00001000
/* Options valid for Samsung large page devices */
-#define NAND_SAMSUNG_LP_OPTIONS \
- (NAND_NO_PADDING | NAND_CACHEPRG | NAND_COPYBACK)
+#define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG
/* Macros to identify the above */
-#define NAND_MUST_PAD(chip) (!(chip->options & NAND_NO_PADDING))
#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
-#define NAND_HAS_COPYBACK(chip) ((chip->options & NAND_COPYBACK))
#define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
/* Non chip related options */
@@ -211,6 +216,13 @@ typedef enum {
#define NAND_OWN_BUFFERS 0x00020000
/* Chip may not exist, so silence any errors in scan */
#define NAND_SCAN_SILENT_NODEV 0x00040000
+/*
+ * Autodetect nand buswidth with readid/onfi.
+ * This suppose the driver will configure the hardware in 8 bits mode
+ * when calling nand_scan_ident, and update its configuration
+ * before calling nand_scan_tail.
+ */
+#define NAND_BUSWIDTH_AUTO 0x00080000
/* Options set by nand scan */
/* bbt has already been read */
@@ -221,10 +233,15 @@ typedef enum {
/* Cell info constants */
#define NAND_CI_CHIPNR_MSK 0x03
#define NAND_CI_CELLTYPE_MSK 0x0C
+#define NAND_CI_CELLTYPE_SHIFT 2
/* Keep gcc happy */
struct nand_chip;
+/* ONFI features */
+#define ONFI_FEATURE_16_BIT_BUS (1 << 0)
+#define ONFI_FEATURE_EXT_PARAM_PAGE (1 << 7)
+
/* ONFI timing mode, used in both asynchronous and synchronous mode */
#define ONFI_TIMING_MODE_0 (1 << 0)
#define ONFI_TIMING_MODE_1 (1 << 1)
@@ -237,9 +254,15 @@ struct nand_chip;
/* ONFI feature address */
#define ONFI_FEATURE_ADDR_TIMING_MODE 0x1
+/* Vendor-specific feature address (Micron) */
+#define ONFI_FEATURE_ADDR_READ_RETRY 0x89
+
/* ONFI subfeature parameters length */
#define ONFI_SUBFEATURE_PARAM_LEN 4
+/* ONFI optional commands SET/GET FEATURES supported? */
+#define ONFI_OPT_CMD_SET_GET_FEATURES (1 << 2)
+
struct nand_onfi_params {
/* rev info and features block */
/* 'O' 'N' 'F' 'I' */
@@ -247,7 +270,10 @@ struct nand_onfi_params {
__le16 revision;
__le16 features;
__le16 opt_cmd;
- u8 reserved[22];
+ u8 reserved0[2];
+ __le16 ext_param_page_length; /* since ONFI 2.1 */
+ u8 num_of_param_pages; /* since ONFI 2.1 */
+ u8 reserved1[17];
/* manufacturer information block */
char manufacturer[12];
@@ -291,19 +317,152 @@ struct nand_onfi_params {
__le16 io_pin_capacitance_typ;
__le16 input_pin_capacitance_typ;
u8 input_pin_capacitance_max;
- u8 driver_strenght_support;
+ u8 driver_strength_support;
__le16 t_int_r;
__le16 t_ald;
u8 reserved4[7];
/* vendor */
- u8 reserved5[90];
+ __le16 vendor_revision;
+ u8 vendor[88];
__le16 crc;
-} __attribute__((packed));
+} __packed;
#define ONFI_CRC_BASE 0x4F4E
+/* Extended ECC information Block Definition (since ONFI 2.1) */
+struct onfi_ext_ecc_info {
+ u8 ecc_bits;
+ u8 codeword_size;
+ __le16 bb_per_lun;
+ __le16 block_endurance;
+ u8 reserved[2];
+} __packed;
+
+#define ONFI_SECTION_TYPE_0 0 /* Unused section. */
+#define ONFI_SECTION_TYPE_1 1 /* for additional sections. */
+#define ONFI_SECTION_TYPE_2 2 /* for ECC information. */
+struct onfi_ext_section {
+ u8 type;
+ u8 length;
+} __packed;
+
+#define ONFI_EXT_SECTION_MAX 8
+
+/* Extended Parameter Page Definition (since ONFI 2.1) */
+struct onfi_ext_param_page {
+ __le16 crc;
+ u8 sig[4]; /* 'E' 'P' 'P' 'S' */
+ u8 reserved0[10];
+ struct onfi_ext_section sections[ONFI_EXT_SECTION_MAX];
+
+ /*
+ * The actual size of the Extended Parameter Page is in
+ * @ext_param_page_length of nand_onfi_params{}.
+ * The following are the variable length sections.
+ * So we do not add any fields below. Please see the ONFI spec.
+ */
+} __packed;
+
+struct nand_onfi_vendor_micron {
+ u8 two_plane_read;
+ u8 read_cache;
+ u8 read_unique_id;
+ u8 dq_imped;
+ u8 dq_imped_num_settings;
+ u8 dq_imped_feat_addr;
+ u8 rb_pulldown_strength;
+ u8 rb_pulldown_strength_feat_addr;
+ u8 rb_pulldown_strength_num_settings;
+ u8 otp_mode;
+ u8 otp_page_start;
+ u8 otp_data_prot_addr;
+ u8 otp_num_pages;
+ u8 otp_feat_addr;
+ u8 read_retry_options;
+ u8 reserved[72];
+ u8 param_revision;
+} __packed;
+
+struct jedec_ecc_info {
+ u8 ecc_bits;
+ u8 codeword_size;
+ __le16 bb_per_lun;
+ __le16 block_endurance;
+ u8 reserved[2];
+} __packed;
+
+/* JEDEC features */
+#define JEDEC_FEATURE_16_BIT_BUS (1 << 0)
+
+struct nand_jedec_params {
+ /* rev info and features block */
+ /* 'J' 'E' 'S' 'D' */
+ u8 sig[4];
+ __le16 revision;
+ __le16 features;
+ u8 opt_cmd[3];
+ __le16 sec_cmd;
+ u8 num_of_param_pages;
+ u8 reserved0[18];
+
+ /* manufacturer information block */
+ char manufacturer[12];
+ char model[20];
+ u8 jedec_id[6];
+ u8 reserved1[10];
+
+ /* memory organization block */
+ __le32 byte_per_page;
+ __le16 spare_bytes_per_page;
+ u8 reserved2[6];
+ __le32 pages_per_block;
+ __le32 blocks_per_lun;
+ u8 lun_count;
+ u8 addr_cycles;
+ u8 bits_per_cell;
+ u8 programs_per_page;
+ u8 multi_plane_addr;
+ u8 multi_plane_op_attr;
+ u8 reserved3[38];
+
+ /* electrical parameter block */
+ __le16 async_sdr_speed_grade;
+ __le16 toggle_ddr_speed_grade;
+ __le16 sync_ddr_speed_grade;
+ u8 async_sdr_features;
+ u8 toggle_ddr_features;
+ u8 sync_ddr_features;
+ __le16 t_prog;
+ __le16 t_bers;
+ __le16 t_r;
+ __le16 t_r_multi_plane;
+ __le16 t_ccs;
+ __le16 io_pin_capacitance_typ;
+ __le16 input_pin_capacitance_typ;
+ __le16 clk_pin_capacitance_typ;
+ u8 driver_strength_support;
+ __le16 t_ald;
+ u8 reserved4[36];
+
+ /* ECC and endurance block */
+ u8 guaranteed_good_blocks;
+ __le16 guaranteed_block_endurance;
+ struct jedec_ecc_info ecc_info[4];
+ u8 reserved5[29];
+
+ /* reserved */
+ u8 reserved6[148];
+
+ /* vendor */
+ __le16 vendor_rev_num;
+ u8 reserved7[88];
+
+ /* CRC for Parameter Page */
+ __le16 crc;
+} __packed;
+
/**
* struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
* @lock: protection lock
@@ -313,12 +472,11 @@ struct nand_onfi_params {
* when a hw controller is available.
*/
struct nand_hw_control {
-/* XXX U-BOOT XXX */
-#if 0
- spinlock_t lock;
+ spinlock_t lock;
+ struct nand_chip *active;
+#ifndef __UBOOT__
wait_queue_head_t wq;
#endif
- struct nand_chip *active;
};
/**
@@ -344,6 +502,7 @@ struct nand_hw_control {
* any single ECC step, 0 if bitflips uncorrectable, -EIO hw error
* @read_subpage: function to read parts of the page covered by ECC;
* returns same as read_page()
+ * @write_subpage: function to write parts of the page covered by ECC.
* @write_page: function to write a page according to the ECC generator
* requirements.
* @write_oob_raw: function to write chip OOB data without ECC
@@ -374,7 +533,10 @@ struct nand_ecc_ctrl {
int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
uint8_t *buf, int oob_required, int page);
int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t offs, uint32_t len, uint8_t *buf);
+ uint32_t offs, uint32_t len, uint8_t *buf, int page);
+ int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
+ uint32_t offset, uint32_t data_len,
+ const uint8_t *data_buf, int oob_required);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf, int oob_required);
int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -388,18 +550,24 @@ struct nand_ecc_ctrl {
/**
* struct nand_buffers - buffer structure for read/write
- * @ecccalc: buffer for calculated ECC
- * @ecccode: buffer for ECC read from flash
- * @databuf: buffer for data - dynamically sized
+ * @ecccalc: buffer pointer for calculated ECC, size is oobsize.
+ * @ecccode: buffer pointer for ECC read from flash, size is oobsize.
+ * @databuf: buffer pointer for data, size is (page size + oobsize).
*
* Do not change the order of buffers. databuf and oobrbuf must be in
* consecutive order.
*/
struct nand_buffers {
+#ifndef __UBOOT__
+ uint8_t *ecccalc;
+ uint8_t *ecccode;
+ uint8_t *databuf;
+#else
uint8_t ecccalc[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)];
uint8_t ecccode[ALIGN(NAND_MAX_OOBSIZE, ARCH_DMA_MINALIGN)];
uint8_t databuf[ALIGN(NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE,
ARCH_DMA_MINALIGN)];
+#endif
};
/**
@@ -410,13 +578,13 @@ struct nand_buffers {
* flash device.
* @read_byte: [REPLACEABLE] read one byte from the chip
* @read_word: [REPLACEABLE] read one word from the chip
+ * @write_byte: [REPLACEABLE] write a single byte to the chip on the
+ * low 8 I/O lines
* @write_buf: [REPLACEABLE] write data from the buffer to the chip
* @read_buf: [REPLACEABLE] read data from the chip into the buffer
- * @verify_buf: [REPLACEABLE] verify buffer contents against the chip
- * data.
* @select_chip: [REPLACEABLE] select chip nr
- * @block_bad: [REPLACEABLE] check, if the block is bad
- * @block_markbad: [REPLACEABLE] mark the block bad
+ * @block_bad: [REPLACEABLE] check if a block is bad, using OOB markers
+ * @block_markbad: [REPLACEABLE] mark a block bad
* @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling
* ALE/CLE/nCE. Also used to write command and address
* @init_size: [BOARDSPECIFIC] hardwarespecific function for setting
@@ -431,6 +599,8 @@ struct nand_buffers {
* commands to the chip.
* @waitfunc: [REPLACEABLE] hardwarespecific function for wait on
* ready.
+ * @setup_read_retry: [FLASHSPECIFIC] flash (vendor) specific function for
+ * setting the read-retry mode. Mostly needed for MLC NAND.
* @ecc: [BOARDSPECIFIC] ECC control structure
* @buffers: buffer structure for read/write
* @hwcontrol: platform-specific hardware control structure
@@ -458,7 +628,13 @@ struct nand_buffers {
* @badblockbits: [INTERN] minimum number of set bits in a good block's
* bad block marker position; i.e., BBM == 11110111b is
* not bad when badblockbits == 7
- * @cellinfo: [INTERN] MLC/multichip data from chip ident
+ * @bits_per_cell: [INTERN] number of bits per cell. i.e., 1 means SLC.
+ * @ecc_strength_ds: [INTERN] ECC correctability from the datasheet.
+ * Minimum amount of bit errors per @ecc_step_ds guaranteed
+ * to be correctable. If unknown, set to zero.
+ * @ecc_step_ds: [INTERN] ECC step required by the @ecc_strength_ds,
+ * also from the datasheet. It is the recommended ECC step
+ * size, if known; if unknown, set to zero.
* @numchips: [INTERN] number of physical chips
* @chipsize: [INTERN] the size of one chip for multichip arrays
* @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
@@ -469,11 +645,15 @@ struct nand_buffers {
* @subpagesize: [INTERN] holds the subpagesize
* @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded),
* non 0 if ONFI supported.
+ * @jedec_version: [INTERN] holds the chip JEDEC version (BCD encoded),
+ * non 0 if JEDEC supported.
* @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is
* supported, 0 otherwise.
- * @onfi_set_features [REPLACEABLE] set the features for ONFI nand
- * @onfi_get_features [REPLACEABLE] get the features for ONFI nand
- * @ecclayout: [REPLACEABLE] the default ECC placement scheme
+ * @jedec_params: [INTERN] holds the JEDEC parameter page when JEDEC is
+ * supported, 0 otherwise.
+ * @read_retries: [INTERN] the number of read retry modes supported
+ * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
+ * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
* @bbt: [INTERN] bad block table pointer
* @bbt_td: [REPLACEABLE] bad block table descriptor for flash
* lookup.
@@ -496,9 +676,14 @@ struct nand_chip {
uint8_t (*read_byte)(struct mtd_info *mtd);
u16 (*read_word)(struct mtd_info *mtd);
+ void (*write_byte)(struct mtd_info *mtd, uint8_t byte);
void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
- int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+#ifdef __UBOOT__
+#if defined(CONFIG_MTD_NAND_VERIFY_WRITE)
+ int (*verify_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+#endif
+#endif
void (*select_chip)(struct mtd_info *mtd, int chip);
int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
@@ -514,12 +699,13 @@ struct nand_chip {
int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
int status, int page);
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required, int page,
- int cached, int raw);
+ uint32_t offset, int data_len, const uint8_t *buf,
+ int oob_required, int page, int cached, int raw);
int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
int feature_addr, uint8_t *subfeature_para);
int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
int feature_addr, uint8_t *subfeature_para);
+ int (*setup_read_retry)(struct mtd_info *mtd, int retry_mode);
int chip_delay;
unsigned int options;
@@ -535,20 +721,28 @@ struct nand_chip {
int pagebuf;
unsigned int pagebuf_bitflips;
int subpagesize;
- uint8_t cellinfo;
+ uint8_t bits_per_cell;
+ uint16_t ecc_strength_ds;
+ uint16_t ecc_step_ds;
int badblockpos;
int badblockbits;
int onfi_version;
+ int jedec_version;
#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
- struct nand_onfi_params onfi_params;
+ struct nand_onfi_params onfi_params;
#endif
+ struct nand_jedec_params jedec_params;
+
+ int read_retries;
- int state;
+ flstate_t state;
uint8_t *oob_poi;
struct nand_hw_control *controller;
+#ifdef __UBOOT__
struct nand_ecclayout *ecclayout;
+#endif
struct nand_ecc_ctrl ecc;
struct nand_buffers *buffers;
@@ -577,26 +771,83 @@ struct nand_chip {
#define NAND_MFR_AMD 0x01
#define NAND_MFR_MACRONIX 0xc2
#define NAND_MFR_EON 0x92
+#define NAND_MFR_SANDISK 0x45
+#define NAND_MFR_INTEL 0x89
+
+/* The maximum expected count of bytes in the NAND ID sequence */
+#define NAND_MAX_ID_LEN 8
+
+/*
+ * A helper for defining older NAND chips where the second ID byte fully
+ * defined the chip, including the geometry (chip size, eraseblock size, page
+ * size). All these chips have 512 bytes NAND page size.
+ */
+#define LEGACY_ID_NAND(nm, devid, chipsz, erasesz, opts) \
+ { .name = (nm), {{ .dev_id = (devid) }}, .pagesize = 512, \
+ .chipsize = (chipsz), .erasesize = (erasesz), .options = (opts) }
+
+/*
+ * A helper for defining newer chips which report their page size and
+ * eraseblock size via the extended ID bytes.
+ *
+ * The real difference between LEGACY_ID_NAND and EXTENDED_ID_NAND is that with
+ * EXTENDED_ID_NAND, manufacturers overloaded the same device ID so that the
+ * device ID now only represented a particular total chip size (and voltage,
+ * buswidth), and the page size, eraseblock size, and OOB size could vary while
+ * using the same device ID.
+ */
+#define EXTENDED_ID_NAND(nm, devid, chipsz, opts) \
+ { .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \
+ .options = (opts) }
+
+#define NAND_ECC_INFO(_strength, _step) \
+ { .strength_ds = (_strength), .step_ds = (_step) }
+#define NAND_ECC_STRENGTH(type) ((type)->ecc.strength_ds)
+#define NAND_ECC_STEP(type) ((type)->ecc.step_ds)
/**
* struct nand_flash_dev - NAND Flash Device ID Structure
- * @name: Identify the device type
- * @id: device ID code
- * @pagesize: Pagesize in bytes. Either 256 or 512 or 0
- * If the pagesize is 0, then the real pagesize
- * and the eraseize are determined from the
- * extended id bytes in the chip
- * @erasesize: Size of an erase block in the flash device.
- * @chipsize: Total chipsize in Mega Bytes
- * @options: Bitfield to store chip relevant options
+ * @name: a human-readable name of the NAND chip
+ * @dev_id: the device ID (the second byte of the full chip ID array)
+ * @mfr_id: manufecturer ID part of the full chip ID array (refers the same
+ * memory address as @id[0])
+ * @dev_id: device ID part of the full chip ID array (refers the same memory
+ * address as @id[1])
+ * @id: full device ID array
+ * @pagesize: size of the NAND page in bytes; if 0, then the real page size (as
+ * well as the eraseblock size) is determined from the extended NAND
+ * chip ID array)
+ * @chipsize: total chip size in MiB
+ * @erasesize: eraseblock size in bytes (determined from the extended ID if 0)
+ * @options: stores various chip bit options
+ * @id_len: The valid length of the @id.
+ * @oobsize: OOB size
+ * @ecc.strength_ds: The ECC correctability from the datasheet, same as the
+ * @ecc_strength_ds in nand_chip{}.
+ * @ecc.step_ds: The ECC step required by the @ecc.strength_ds, same as the
+ * @ecc_step_ds in nand_chip{}, also from the datasheet.
+ * For example, the "4bit ECC for each 512Byte" can be set with
+ * NAND_ECC_INFO(4, 512).
*/
struct nand_flash_dev {
char *name;
- int id;
- unsigned long pagesize;
- unsigned long chipsize;
- unsigned long erasesize;
- unsigned long options;
+ union {
+ struct {
+ uint8_t mfr_id;
+ uint8_t dev_id;
+ };
+ uint8_t id[NAND_MAX_ID_LEN];
+ };
+ unsigned int pagesize;
+ unsigned int chipsize;
+ unsigned int erasesize;
+ unsigned int options;
+ uint16_t id_len;
+ uint16_t oobsize;
+ struct {
+ uint16_t strength_ds;
+ uint16_t step_ds;
+ } ecc;
};
/**
@@ -609,23 +860,25 @@ struct nand_manufacturers {
char *name;
};
-extern const struct nand_flash_dev nand_flash_ids[];
-extern const struct nand_manufacturers nand_manuf_ids[];
+extern struct nand_flash_dev nand_flash_ids[];
+extern struct nand_manufacturers nand_manuf_ids[];
extern int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd);
-extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
extern int nand_default_bbt(struct mtd_info *mtd);
+extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
int allowbbt);
extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, uint8_t *buf);
+#ifdef __UBOOT__
/*
* Constants for oob configuration
*/
#define NAND_SMALL_BADBLOCK_POS 5
#define NAND_LARGE_BADBLOCK_POS 0
+#endif
/**
* struct platform_nand_chip - chip level device structure
@@ -656,20 +909,29 @@ struct platform_device;
/**
* struct platform_nand_ctrl - controller level device structure
+ * @probe: platform specific function to probe/setup hardware
+ * @remove: platform specific function to remove/teardown hardware
* @hwcontrol: platform specific hardware control structure
* @dev_ready: platform specific function to read ready/busy pin
* @select_chip: platform specific chip select function
* @cmd_ctrl: platform specific function for controlling
* ALE/CLE/nCE. Also used to write command and address
+ * @write_buf: platform specific function for write buffer
+ * @read_buf: platform specific function for read buffer
+ * @read_byte: platform specific function to read one byte from chip
* @priv: private data to transport driver specific settings
*
* All fields are optional and depend on the hardware driver requirements
*/
struct platform_nand_ctrl {
+ int (*probe)(struct platform_device *pdev);
+ void (*remove)(struct platform_device *pdev);
void (*hwcontrol)(struct mtd_info *mtd, int cmd);
int (*dev_ready)(struct mtd_info *mtd);
void (*select_chip)(struct mtd_info *mtd, int chip);
void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
+ void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
+ void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
unsigned char (*read_byte)(struct mtd_info *mtd);
void *priv;
};
@@ -693,16 +955,14 @@ struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
return chip->priv;
}
-/* Standard NAND functions from nand_base.c */
-void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
-void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len);
-void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len);
-void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len);
-uint8_t nand_read_byte(struct mtd_info *mtd);
+#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
+/* return the supported features. */
+static inline int onfi_feature(struct nand_chip *chip)
+{
+ return chip->onfi_version ? le16_to_cpu(chip->onfi_params.features) : 0;
+}
/* return the supported asynchronous timing mode. */
-
-#ifdef CONFIG_SYS_NAND_ONFI_DETECTION
static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
{
if (!chip->onfi_version)
@@ -719,6 +979,16 @@ static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
}
#endif
+/*
+ * Check if it is a SLC nand.
+ * The !nand_is_slc() can be used to check the MLC/TLC nand chips.
+ * We do not distinguish the MLC and TLC now.
+ */
+static inline bool nand_is_slc(struct nand_chip *chip)
+{
+ return chip->bits_per_cell == 1;
+}
+
/**
* Check if the opcode's address should be sent only on the lower 8 bits
* @command: opcode to check
@@ -737,5 +1007,19 @@ static inline int nand_opcode_8bits(unsigned int command)
return 0;
}
+/* return the supported JEDEC features. */
+static inline int jedec_feature(struct nand_chip *chip)
+{
+ return chip->jedec_version ? le16_to_cpu(chip->jedec_params.features)
+ : 0;
+}
+#ifdef __UBOOT__
+/* Standard NAND functions from nand_base.c */
+void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len);
+void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len);
+void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len);
+void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len);
+uint8_t nand_read_byte(struct mtd_info *mtd);
+#endif
#endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index d1d9a96d58..ce0e8dbee4 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -1,11 +1,9 @@
/*
* MTD partitioning layer definitions
*
- * (C) 2000 Nicolas Pitre <nico@cam.org>
+ * (C) 2000 Nicolas Pitre <nico@fluxnic.net>
*
* This code is GPL
- *
- * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $
*/
#ifndef MTD_PARTITIONS_H
@@ -18,7 +16,7 @@
* Partition definition structure:
*
* An array of struct partition is passed along with a MTD object to
- * add_mtd_partitions() to create them.
+ * mtd_device_register() to create them.
*
* For each partition, these fields are available:
* name: string that will be used to label the partition's MTD device.
@@ -26,7 +24,9 @@
* will extend to the end of the master MTD device.
* offset: absolute starting position within the master MTD device; if
* defined as MTDPART_OFS_APPEND, the partition will start where the
- * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
+ * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block;
+ * if MTDPART_OFS_RETAIN, consume as much as possible, leaving size
+ * after the end of partition.
* mask_flags: contains flags that have to be masked (removed) from the
* master MTD flag set for the corresponding MTD partition.
* For example, to force a read-only partition, simply adding
@@ -37,23 +37,34 @@
*/
struct mtd_partition {
- char *name; /* identifier string */
+ const char *name; /* identifier string */
uint64_t size; /* partition size */
uint64_t offset; /* offset within the master MTD space */
- u_int32_t mask_flags; /* master MTD flags to mask out for this partition */
- struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only)*/
- struct mtd_info **mtdp; /* pointer to store the MTD object */
+ uint32_t mask_flags; /* master MTD flags to mask out for this partition */
+ struct nand_ecclayout *ecclayout; /* out of band layout for this partition (NAND only) */
};
+#define MTDPART_OFS_RETAIN (-3)
#define MTDPART_OFS_NXTBLK (-2)
#define MTDPART_OFS_APPEND (-1)
#define MTDPART_SIZ_FULL (0)
-int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
-int del_mtd_partitions(struct mtd_info *);
+struct mtd_info;
+struct device_node;
+
+#ifndef __UBOOT__
+/**
+ * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
+ * @origin: for RedBoot, start address of MTD device
+ * @of_node: for OF parsers, device node containing partitioning information
+ */
+struct mtd_part_parser_data {
+ unsigned long origin;
+ struct device_node *of_node;
+};
+
-#if 0
/*
* Functions dealing with the various ways of partitioning the space
*/
@@ -62,23 +73,18 @@ struct mtd_part_parser {
struct list_head list;
struct module *owner;
const char *name;
- int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
+ int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
+ struct mtd_part_parser_data *);
};
-extern int register_mtd_parser(struct mtd_part_parser *parser);
-extern int deregister_mtd_parser(struct mtd_part_parser *parser);
-extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
- struct mtd_partition **pparts, unsigned long origin);
-
-#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
-
-struct device;
-struct device_node;
-
-int __devinit of_mtd_parse_partitions(struct device *dev,
- struct mtd_info *mtd,
- struct device_node *node,
- struct mtd_partition **pparts);
+extern void register_mtd_parser(struct mtd_part_parser *parser);
+extern void deregister_mtd_parser(struct mtd_part_parser *parser);
#endif
+int mtd_is_partition(const struct mtd_info *mtd);
+int mtd_add_partition(struct mtd_info *master, const char *name,
+ long long offset, long long length);
+int mtd_del_partition(struct mtd_info *master, int partno);
+uint64_t mtd_get_device_size(const struct mtd_info *mtd);
+
#endif
diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index 4755770c54..d9e58aedf6 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -9,9 +9,15 @@
#ifndef __LINUX_UBI_H__
#define __LINUX_UBI_H__
-/* #include <asm/ioctl.h> */
#include <linux/types.h>
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/ioctl.h>
#include <mtd/ubi-user.h>
+#endif
+
+/* All voumes/LEBs */
+#define UBI_ALL -1
/*
* enum ubi_open_mode - UBI volume open mode constants.
@@ -33,13 +39,13 @@ enum {
* @size: how many physical eraseblocks are reserved for this volume
* @used_bytes: how many bytes of data this volume contains
* @used_ebs: how many physical eraseblocks of this volume actually contain any
- * data
+ * data
* @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
* @corrupted: non-zero if the volume is corrupted (static volumes only)
* @upd_marker: non-zero if the volume has update marker set
* @alignment: volume alignment
* @usable_leb_size: how many bytes are available in logical eraseblocks of
- * this volume
+ * this volume
* @name_len: volume name length
* @name: volume name
* @cdev: UBI volume character device major and minor numbers
@@ -75,7 +81,7 @@ enum {
* physical eraseblock size and on how much bytes UBI headers consume. But
* because of the volume alignment (@alignment), the usable size of logical
* eraseblocks if a volume may be less. The following equation is true:
- * @usable_leb_size = LEB size - (LEB size mod @alignment),
+ * @usable_leb_size = LEB size - (LEB size mod @alignment),
* where LEB size is the logical eraseblock size defined by the UBI device.
*
* The alignment is multiple to the minimal flash input/output unit size or %1
@@ -104,20 +110,79 @@ struct ubi_volume_info {
* struct ubi_device_info - UBI device description data structure.
* @ubi_num: ubi device number
* @leb_size: logical eraseblock size on this UBI device
+ * @leb_start: starting offset of logical eraseblocks within physical
+ * eraseblocks
* @min_io_size: minimal I/O unit size
+ * @max_write_size: maximum amount of bytes the underlying flash can write at a
+ * time (MTD write buffer size)
* @ro_mode: if this device is in read-only mode
* @cdev: UBI character device major and minor numbers
*
* Note, @leb_size is the logical eraseblock size offered by the UBI device.
* Volumes of this UBI device may have smaller logical eraseblock size if their
* alignment is not equivalent to %1.
+ *
+ * The @max_write_size field describes flash write maximum write unit. For
+ * example, NOR flash allows for changing individual bytes, so @min_io_size is
+ * %1. However, it does not mean than NOR flash has to write data byte-by-byte.
+ * Instead, CFI NOR flashes have a write-buffer of, e.g., 64 bytes, and when
+ * writing large chunks of data, they write 64-bytes at a time. Obviously, this
+ * improves write throughput.
+ *
+ * Also, the MTD device may have N interleaved (striped) flash chips
+ * underneath, in which case @min_io_size can be physical min. I/O size of
+ * single flash chip, while @max_write_size can be N * @min_io_size.
+ *
+ * The @max_write_size field is always greater or equivalent to @min_io_size.
+ * E.g., some NOR flashes may have (@min_io_size = 1, @max_write_size = 64). In
+ * contrast, NAND flashes usually have @min_io_size = @max_write_size = NAND
+ * page size.
*/
struct ubi_device_info {
int ubi_num;
int leb_size;
+ int leb_start;
int min_io_size;
+ int max_write_size;
int ro_mode;
+#ifndef __UBOOT__
dev_t cdev;
+#endif
+};
+
+/*
+ * Volume notification types.
+ * @UBI_VOLUME_ADDED: a volume has been added (an UBI device was attached or a
+ * volume was created)
+ * @UBI_VOLUME_REMOVED: a volume has been removed (an UBI device was detached
+ * or a volume was removed)
+ * @UBI_VOLUME_RESIZED: a volume has been re-sized
+ * @UBI_VOLUME_RENAMED: a volume has been re-named
+ * @UBI_VOLUME_UPDATED: data has been written to a volume
+ *
+ * These constants define which type of event has happened when a volume
+ * notification function is invoked.
+ */
+enum {
+ UBI_VOLUME_ADDED,
+ UBI_VOLUME_REMOVED,
+ UBI_VOLUME_RESIZED,
+ UBI_VOLUME_RENAMED,
+ UBI_VOLUME_UPDATED,
+};
+
+/*
+ * struct ubi_notification - UBI notification description structure.
+ * @di: UBI device description object
+ * @vi: UBI volume description object
+ *
+ * UBI notifiers are called with a pointer to an object of this type. The
+ * object describes the notification. Namely, it provides a description of the
+ * UBI device and UBI volume the notification informs about.
+ */
+struct ubi_notification {
+ struct ubi_device_info di;
+ struct ubi_volume_info vi;
};
/* UBI descriptor given to users when they open UBI volumes */
@@ -129,17 +194,37 @@ void ubi_get_volume_info(struct ubi_volume_desc *desc,
struct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode);
struct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name,
int mode);
+struct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode);
+
+#ifndef __UBOOT__
+typedef int (*notifier_fn_t)(void *nb,
+ unsigned long action, void *data);
+
+struct notifier_block {
+ notifier_fn_t notifier_call;
+ struct notifier_block *next;
+ void *next;
+ int priority;
+};
+
+int ubi_register_volume_notifier(struct notifier_block *nb,
+ int ignore_existing);
+int ubi_unregister_volume_notifier(struct notifier_block *nb);
+#endif
+
void ubi_close_volume(struct ubi_volume_desc *desc);
int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
int len, int check);
int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int offset, int len, int dtype);
+ int offset, int len);
int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
- int len, int dtype);
+ int len);
int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum);
int ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
+int ubi_leb_map(struct ubi_volume_desc *desc, int lnum);
int ubi_is_mapped(struct ubi_volume_desc *desc, int lnum);
+int ubi_sync(int ubi_num);
+int ubi_flush(int ubi_num, int vol_id, int lnum);
/*
* This function is the same as the 'ubi_leb_read()' function, but it does not
@@ -150,25 +235,4 @@ static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf,
{
return ubi_leb_read(desc, lnum, buf, offset, len, 0);
}
-
-/*
- * This function is the same as the 'ubi_leb_write()' functions, but it does
- * not have the data type argument.
- */
-static inline int ubi_write(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int offset, int len)
-{
- return ubi_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-}
-
-/*
- * This function is the same as the 'ubi_leb_change()' functions, but it does
- * not have the data type argument.
- */
-static inline int ubi_change(struct ubi_volume_desc *desc, int lnum,
- const void *buf, int len)
-{
- return ubi_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-}
-
#endif /* !__LINUX_UBI_H__ */
diff --git a/include/linux/rbtree.h b/include/linux/rbtree.h
index ad892d1cbb..b5994e3799 100644
--- a/include/linux/rbtree.h
+++ b/include/linux/rbtree.h
@@ -1,7 +1,7 @@
/*
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
-
+
* SPDX-License-Identifier: GPL-2.0+
linux/include/linux/rbtree.h
@@ -11,138 +11,89 @@
I know it's not the cleaner way, but in C (not in C++) to get
performances and genericity...
- Some example of insert and search follows here. The search is a plain
- normal search over an ordered tree. The insert instead must be implemented
- int two steps: as first thing the code must insert the element in
- order as a red leaf in the tree, then the support library function
- rb_insert_color() must be called. Such function will do the
- not trivial work to rebalance the rbtree if necessary.
-
------------------------------------------------------------------------
-static inline struct page * rb_search_page_cache(struct inode * inode,
- unsigned long offset)
-{
- struct rb_node * n = inode->i_rb_page_cache.rb_node;
- struct page * page;
-
- while (n)
- {
- page = rb_entry(n, struct page, rb_page_cache);
-
- if (offset < page->offset)
- n = n->rb_left;
- else if (offset > page->offset)
- n = n->rb_right;
- else
- return page;
- }
- return NULL;
-}
-
-static inline struct page * __rb_insert_page_cache(struct inode * inode,
- unsigned long offset,
- struct rb_node * node)
-{
- struct rb_node ** p = &inode->i_rb_page_cache.rb_node;
- struct rb_node * parent = NULL;
- struct page * page;
-
- while (*p)
- {
- parent = *p;
- page = rb_entry(parent, struct page, rb_page_cache);
-
- if (offset < page->offset)
- p = &(*p)->rb_left;
- else if (offset > page->offset)
- p = &(*p)->rb_right;
- else
- return page;
- }
-
- rb_link_node(node, parent, p);
-
- return NULL;
-}
-
-static inline struct page * rb_insert_page_cache(struct inode * inode,
- unsigned long offset,
- struct rb_node * node)
-{
- struct page * ret;
- if ((ret = __rb_insert_page_cache(inode, offset, node)))
- goto out;
- rb_insert_color(node, &inode->i_rb_page_cache);
- out:
- return ret;
-}
------------------------------------------------------------------------
+ See Documentation/rbtree.txt for documentation and samples.
*/
#ifndef _LINUX_RBTREE_H
#define _LINUX_RBTREE_H
+#define __UBOOT__
+#ifndef __UBOOT__
+#include <linux/kernel.h>
+#endif
#include <linux/stddef.h>
-struct rb_node
-{
- unsigned long rb_parent_color;
-#define RB_RED 0
-#define RB_BLACK 1
+struct rb_node {
+ unsigned long __rb_parent_color;
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
-struct rb_root
-{
+struct rb_root {
struct rb_node *rb_node;
};
-#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
-#define rb_color(r) ((r)->rb_parent_color & 1)
-#define rb_is_red(r) (!rb_color(r))
-#define rb_is_black(r) rb_color(r)
-#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
-#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
-
-static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
-{
- rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
-}
-static inline void rb_set_color(struct rb_node *rb, int color)
-{
- rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
-}
+#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3))
#define RB_ROOT (struct rb_root) { NULL, }
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
-#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
-#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
-#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
+#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
+
+/* 'empty' nodes are nodes that are known not to be inserted in an rbree */
+#define RB_EMPTY_NODE(node) \
+ ((node)->__rb_parent_color == (unsigned long)(node))
+#define RB_CLEAR_NODE(node) \
+ ((node)->__rb_parent_color = (unsigned long)(node))
+
extern void rb_insert_color(struct rb_node *, struct rb_root *);
extern void rb_erase(struct rb_node *, struct rb_root *);
+
/* Find logical next and previous nodes in a tree */
-extern struct rb_node *rb_next(struct rb_node *);
-extern struct rb_node *rb_prev(struct rb_node *);
-extern struct rb_node *rb_first(struct rb_root *);
-extern struct rb_node *rb_last(struct rb_root *);
+extern struct rb_node *rb_next(const struct rb_node *);
+extern struct rb_node *rb_prev(const struct rb_node *);
+extern struct rb_node *rb_first(const struct rb_root *);
+extern struct rb_node *rb_last(const struct rb_root *);
+
+/* Postorder iteration - always visit the parent after its children */
+extern struct rb_node *rb_first_postorder(const struct rb_root *);
+extern struct rb_node *rb_next_postorder(const struct rb_node *);
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
-extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
struct rb_root *root);
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
{
- node->rb_parent_color = (unsigned long )parent;
+ node->__rb_parent_color = (unsigned long)parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+#define rb_entry_safe(ptr, type, member) \
+ ({ typeof(ptr) ____ptr = (ptr); \
+ ____ptr ? rb_entry(____ptr, type, member) : NULL; \
+ })
+
+/**
+ * rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of
+ * given type safe against removal of rb_node entry
+ *
+ * @pos: the 'type *' to use as a loop cursor.
+ * @n: another 'type *' to use as temporary storage
+ * @root: 'rb_root *' of the rbtree.
+ * @field: the name of the rb_node field within 'type'.
+ */
+#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
+ for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
+ pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
+ typeof(*pos), field); 1; }); \
+ pos = n)
+
#endif /* _LINUX_RBTREE_H */
diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h
new file mode 100644
index 0000000000..a86797edb6
--- /dev/null
+++ b/include/linux/rbtree_augmented.h
@@ -0,0 +1,220 @@
+/*
+ Red Black Trees
+ (C) 1999 Andrea Arcangeli <andrea@suse.de>
+ (C) 2002 David Woodhouse <dwmw2@infradead.org>
+ (C) 2012 Michel Lespinasse <walken@google.com>
+
+ * SPDX-License-Identifier: GPL-2.0+
+
+ linux/include/linux/rbtree_augmented.h
+*/
+
+#ifndef _LINUX_RBTREE_AUGMENTED_H
+#define _LINUX_RBTREE_AUGMENTED_H
+
+#include <linux/compiler.h>
+#include <linux/rbtree.h>
+
+/*
+ * Please note - only struct rb_augment_callbacks and the prototypes for
+ * rb_insert_augmented() and rb_erase_augmented() are intended to be public.
+ * The rest are implementation details you are not expected to depend on.
+ *
+ * See Documentation/rbtree.txt for documentation and samples.
+ */
+
+struct rb_augment_callbacks {
+ void (*propagate)(struct rb_node *node, struct rb_node *stop);
+ void (*copy)(struct rb_node *old, struct rb_node *new);
+ void (*rotate)(struct rb_node *old, struct rb_node *new);
+};
+
+extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
+static inline void
+rb_insert_augmented(struct rb_node *node, struct rb_root *root,
+ const struct rb_augment_callbacks *augment)
+{
+ __rb_insert_augmented(node, root, augment->rotate);
+}
+
+#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \
+ rbtype, rbaugmented, rbcompute) \
+static inline void \
+rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \
+{ \
+ while (rb != stop) { \
+ rbstruct *node = rb_entry(rb, rbstruct, rbfield); \
+ rbtype augmented = rbcompute(node); \
+ if (node->rbaugmented == augmented) \
+ break; \
+ node->rbaugmented = augmented; \
+ rb = rb_parent(&node->rbfield); \
+ } \
+} \
+static inline void \
+rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \
+{ \
+ rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \
+ rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \
+ new->rbaugmented = old->rbaugmented; \
+} \
+static void \
+rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \
+{ \
+ rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \
+ rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \
+ new->rbaugmented = old->rbaugmented; \
+ old->rbaugmented = rbcompute(old); \
+} \
+rbstatic const struct rb_augment_callbacks rbname = { \
+ rbname ## _propagate, rbname ## _copy, rbname ## _rotate \
+};
+
+
+#define RB_RED 0
+#define RB_BLACK 1
+
+#define __rb_parent(pc) ((struct rb_node *)(pc & ~3))
+
+#define __rb_color(pc) ((pc) & 1)
+#define __rb_is_black(pc) __rb_color(pc)
+#define __rb_is_red(pc) (!__rb_color(pc))
+#define rb_color(rb) __rb_color((rb)->__rb_parent_color)
+#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color)
+#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color)
+
+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
+{
+ rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
+}
+
+static inline void rb_set_parent_color(struct rb_node *rb,
+ struct rb_node *p, int color)
+{
+ rb->__rb_parent_color = (unsigned long)p | color;
+}
+
+static inline void
+__rb_change_child(struct rb_node *old, struct rb_node *new,
+ struct rb_node *parent, struct rb_root *root)
+{
+ if (parent) {
+ if (parent->rb_left == old)
+ parent->rb_left = new;
+ else
+ parent->rb_right = new;
+ } else
+ root->rb_node = new;
+}
+
+extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
+ void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
+
+static __always_inline struct rb_node *
+__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+ const struct rb_augment_callbacks *augment)
+{
+ struct rb_node *child = node->rb_right, *tmp = node->rb_left;
+ struct rb_node *parent, *rebalance;
+ unsigned long pc;
+
+ if (!tmp) {
+ /*
+ * Case 1: node to erase has no more than 1 child (easy!)
+ *
+ * Note that if there is one child it must be red due to 5)
+ * and node must be black due to 4). We adjust colors locally
+ * so as to bypass __rb_erase_color() later on.
+ */
+ pc = node->__rb_parent_color;
+ parent = __rb_parent(pc);
+ __rb_change_child(node, child, parent, root);
+ if (child) {
+ child->__rb_parent_color = pc;
+ rebalance = NULL;
+ } else
+ rebalance = __rb_is_black(pc) ? parent : NULL;
+ tmp = parent;
+ } else if (!child) {
+ /* Still case 1, but this time the child is node->rb_left */
+ tmp->__rb_parent_color = pc = node->__rb_parent_color;
+ parent = __rb_parent(pc);
+ __rb_change_child(node, tmp, parent, root);
+ rebalance = NULL;
+ tmp = parent;
+ } else {
+ struct rb_node *successor = child, *child2;
+ tmp = child->rb_left;
+ if (!tmp) {
+ /*
+ * Case 2: node's successor is its right child
+ *
+ * (n) (s)
+ * / \ / \
+ * (x) (s) -> (x) (c)
+ * \
+ * (c)
+ */
+ parent = successor;
+ child2 = successor->rb_right;
+ augment->copy(node, successor);
+ } else {
+ /*
+ * Case 3: node's successor is leftmost under
+ * node's right child subtree
+ *
+ * (n) (s)
+ * / \ / \
+ * (x) (y) -> (x) (y)
+ * / /
+ * (p) (p)
+ * / /
+ * (s) (c)
+ * \
+ * (c)
+ */
+ do {
+ parent = successor;
+ successor = tmp;
+ tmp = tmp->rb_left;
+ } while (tmp);
+ parent->rb_left = child2 = successor->rb_right;
+ successor->rb_right = child;
+ rb_set_parent(child, successor);
+ augment->copy(node, successor);
+ augment->propagate(parent, successor);
+ }
+
+ successor->rb_left = tmp = node->rb_left;
+ rb_set_parent(tmp, successor);
+
+ pc = node->__rb_parent_color;
+ tmp = __rb_parent(pc);
+ __rb_change_child(node, successor, tmp, root);
+ if (child2) {
+ successor->__rb_parent_color = pc;
+ rb_set_parent_color(child2, parent, RB_BLACK);
+ rebalance = NULL;
+ } else {
+ unsigned long pc2 = successor->__rb_parent_color;
+ successor->__rb_parent_color = pc;
+ rebalance = __rb_is_black(pc2) ? parent : NULL;
+ }
+ tmp = successor;
+ }
+
+ augment->propagate(tmp, NULL);
+ return rebalance;
+}
+
+static __always_inline void
+rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+ const struct rb_augment_callbacks *augment)
+{
+ struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
+ if (rebalance)
+ __rb_erase_color(rebalance, root, augment->rotate);
+}
+
+#endif /* _LINUX_RBTREE_AUGMENTED_H */
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index a8a576316d..9bccd451af 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -19,6 +19,7 @@
#define __LINUX_USB_GADGET_H
#include <errno.h>
+#include <linux/compat.h>
#include <linux/list.h>
struct usb_ep;
@@ -410,11 +411,6 @@ struct usb_gadget_ops {
unsigned code, unsigned long param);
};
-struct device {
- void *driver_data; /* data private to the driver */
- void *device_data; /* data private to the device */
-};
-
/**
* struct usb_gadget - represents a usb slave device
* @ops: Function pointers used to access hardware-specific operations.