summaryrefslogtreecommitdiffstats
path: root/drivers/staging/csr/oska/kernel-compat.h
blob: b6d27d39c33b50a851ea1c9efa0efdddf5c56f3b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/*
 * Kernel version compatibility.
 *
 * Copyright (C) 2007-2008 Cambridge Silicon Radio Ltd.
 *
 * Refer to LICENSE.txt included with this source code for details on
 * the license terms.
 *
 * Wherever possible compatible implementations of newer APIs are
 * provided for older kernel versions.
 */
#ifndef __LINUX_KERNEL_COMPAT_H
#define __LINUX_KERNEL_COMPAT_H

#include <linux/version.h>
#include <linux/device.h>
#include <linux/workqueue.h>

#include <asm/io.h>

/*
 * linux/semaphore.h replaces asm/semaphore.h in 2.6.27.
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)
#  include <asm/semaphore.h>
#else
#  include <linux/semaphore.h>
#endif

/*
 * Workqueue API changes in 2.6.20
 *
 * See http://lwn.net/Articles/211279/ for details.
 *
 * We deliberately don't provide the non-automatic release (NAR)
 * variants as a simple compatible implementation is not possible.
 * This shouldn't be a problem as all usage so far is to embed the
 * struct work_struct into another struct and the NAR variants aren't
 * useful in this case (see http://lwn.net/Articles/213149/).
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)

#include <linux/workqueue.h>

#undef INIT_WORK
#define INIT_WORK(_work, _func)                                         \
    do {                                                                \
        INIT_LIST_HEAD(&(_work)->entry);                                \
        (_work)->pending = 0;                                           \
        PREPARE_WORK((_work), (_func), (_work));                        \
        init_timer(&(_work)->timer);                                    \
    } while(0)

#undef DECLARE_WORK
#define DECLARE_WORK(n, f) \
    struct work_struct n = __WORK_INITIALIZER((n), (f), &(n))

struct delayed_work {
    struct work_struct work;
};

#define INIT_DELAYED_WORK(dw, fn) \
    INIT_WORK(&(dw)->work, (fn))

#define queue_delayed_work(wq, dw, delay) \
    queue_delayed_work((wq), &(dw)->work, (delay))

#define schedule_delayed_work(dw, delay) \
    schedule_delayed_work(&(dw)->work, (delay))

#define cancel_delayed_work(dw) \
    cancel_delayed_work(&(dw)->work)

#endif  /* Linux kernel < 2.6.20 */

/*
 * device_create()/class_device_create()
 *
 * device_create() gains a drvdata parameter in 2.6.27. Since all
 * users of device_create() in CSR code don't use drvdata just ignore
 * it.
 *
 * device_create() replaces class_device_create() in 2.6.21.
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)

#define device_create(class, parent, devt, drvdata, fmt, args...) \
    class_device_create((class), (parent), (devt), NULL, (fmt), ## args)
#define device_destroy(class, devt) \
    class_device_destroy(class, devt)

#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27)

#define device_create(class, parent, devt, drvdata, fmt, args...) \
    device_create((class), (parent), (devt), (fmt), ## args)

#endif /* Linux kernel < 2.6.26 */

/*
 * dev_name() and dev_set_name() added in 2.6.26.
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)

static inline char *dev_name(struct device *dev)
{
    return dev->bus_id;
}

int dev_set_name(struct device *dev, const char *fmt, ...);

#endif /* Linux kernel < 2.6.26 */

/*
 * class_find_device() in 2.6.25
 */

#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)

struct device *class_find_device(struct class *class, struct device *start,
                                 void *data, int (*match)(struct device *, void *));

#endif /* Linux kernel < 2.6.25 */

/*
 * list_first_entry in 2.6.22.
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)

#define list_first_entry(ptr, type, member) \
    list_entry((ptr)->next, type, member)

#endif /* Linux kernel < 2.6.22 */

/*
 * 2.6.19 adds a bool type.
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)

typedef _Bool bool;
enum {
        false   = 0,
        true    = 1
};

#endif /* Linux kernel < 2.6.19 */

/*
 * Provide readq() and writeq() if unavailable.
 */
#ifndef readq
static inline __u64 readq(const volatile void __iomem *addr)
{
    const volatile u32 __iomem *p = addr;
    u32 low, high;

    low = readl(p);
    high = readl(p + 1);

    return low + ((u64)high << 32);
}
#endif

#ifndef writeq
static inline void writeq(__u64 val, volatile void __iomem *addr)
{
    writel(val, addr);
    writel(val >> 32, addr+4);
}
#endif

/*
 * get_unaligned_le16() and friends added in 2.6.26.
 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
#include <asm/unaligned.h>

static inline __u16 get_unaligned_le16(const void *p)
{
    return le16_to_cpu(get_unaligned((__le16 *)p));
}

static inline void put_unaligned_le16(__u16 val, const void *p)
{
    put_unaligned(cpu_to_le16(val), (__le16 *)p);
}
#endif /* Linux kernel < 2.6.26 */

/*
 * Various device or vendor IDs may not exist.
 */
#ifndef PCI_VENDOR_ID_CSR
#  define PCI_VENDOR_ID_CSR 0x18e5
#endif

#ifndef PCI_DEVICE_ID_JMICRON_JMB38X_SD
#  define PCI_DEVICE_ID_JMICRON_JMB38X_SD 0x2381
#endif

#endif /* #ifndef __LINUX_KERNEL_COMPAT_H */