Greg Kroah-Hartman | f91121b | 2014-09-11 08:22:06 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Greybus kernel "version" glue logic. |
| 3 | * |
| 4 | * Copyright 2014 Google Inc. |
Alex Elder | a46e967 | 2014-12-12 12:08:42 -0600 | [diff] [blame] | 5 | * Copyright 2014 Linaro Ltd. |
Greg Kroah-Hartman | f91121b | 2014-09-11 08:22:06 -0700 | [diff] [blame] | 6 | * |
| 7 | * Released under the GPLv2 only. |
| 8 | * |
| 9 | * Backports of newer kernel apis to allow the code to build properly on older |
| 10 | * kernel versions. Remove this file when merging to upstream, it should not be |
| 11 | * needed at all |
| 12 | */ |
| 13 | |
| 14 | #ifndef __GREYBUS_KERNEL_VER_H |
| 15 | #define __GREYBUS_KERNEL_VER_H |
| 16 | |
Viresh Kumar | e2cb6ca | 2015-03-27 16:32:56 +0530 | [diff] [blame] | 17 | #include <linux/kernel.h> |
Alex Elder | 5c58640 | 2015-05-07 13:00:21 -0500 | [diff] [blame] | 18 | #include <linux/version.h> |
| 19 | |
| 20 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 1, 0) |
| 21 | /* Commit: 297d716 power_supply: Change ownership from driver to core */ |
| 22 | #define DRIVER_OWNS_PSY_STRUCT |
| 23 | #endif |
Viresh Kumar | e2cb6ca | 2015-03-27 16:32:56 +0530 | [diff] [blame] | 24 | |
Greg Kroah-Hartman | 4efe606 | 2014-11-17 16:55:54 -0800 | [diff] [blame] | 25 | #ifndef __ATTR_WO |
| 26 | #define __ATTR_WO(_name) { \ |
Greg Kroah-Hartman | 99a4bd5 | 2015-05-01 21:04:47 +0200 | [diff] [blame] | 27 | .attr = { .name = __stringify(_name), .mode = S_IWUSR }, \ |
| 28 | .store = _name##_store, \ |
Greg Kroah-Hartman | 4efe606 | 2014-11-17 16:55:54 -0800 | [diff] [blame] | 29 | } |
| 30 | #endif |
| 31 | |
Greg Kroah-Hartman | df67155 | 2014-12-21 14:10:26 -0800 | [diff] [blame] | 32 | #ifndef __ATTR_RW |
| 33 | #define __ATTR_RW(_name) __ATTR(_name, (S_IWUSR | S_IRUGO), \ |
Greg Kroah-Hartman | 99a4bd5 | 2015-05-01 21:04:47 +0200 | [diff] [blame] | 34 | _name##_show, _name##_store) |
Greg Kroah-Hartman | df67155 | 2014-12-21 14:10:26 -0800 | [diff] [blame] | 35 | #endif |
| 36 | |
Greg Kroah-Hartman | f91121b | 2014-09-11 08:22:06 -0700 | [diff] [blame] | 37 | #ifndef DEVICE_ATTR_RO |
| 38 | #define DEVICE_ATTR_RO(_name) \ |
| 39 | struct device_attribute dev_attr_##_name = __ATTR_RO(_name) |
| 40 | #endif |
| 41 | |
Greg Kroah-Hartman | ac4029f | 2014-11-17 16:03:34 -0800 | [diff] [blame] | 42 | #ifndef DEVICE_ATTR_WO |
| 43 | #define DEVICE_ATTR_WO(_name) \ |
| 44 | struct device_attribute dev_attr_##_name = __ATTR_WO(_name) |
| 45 | #endif |
| 46 | |
Greg Kroah-Hartman | df67155 | 2014-12-21 14:10:26 -0800 | [diff] [blame] | 47 | #ifndef DEVICE_ATTR_RW |
| 48 | #define DEVICE_ATTR_RW(_name) \ |
| 49 | struct device_attribute dev_attr_##_name = __ATTR_RW(_name) |
| 50 | #endif |
| 51 | |
Alex Elder | 1cfc667 | 2014-09-30 19:25:21 -0500 | [diff] [blame] | 52 | #ifndef U8_MAX |
| 53 | #define U8_MAX ((u8)~0U) |
| 54 | #endif /* ! U8_MAX */ |
Greg Kroah-Hartman | f91121b | 2014-09-11 08:22:06 -0700 | [diff] [blame] | 55 | |
Alex Elder | e88afa5 | 2014-10-01 21:54:15 -0500 | [diff] [blame] | 56 | #ifndef U16_MAX |
| 57 | #define U16_MAX ((u16)(~0U)) |
| 58 | #endif /* !U16_MAX */ |
| 59 | |
Alex Elder | 47a9685 | 2015-08-04 13:44:10 -0500 | [diff] [blame] | 60 | #ifndef U32_MAX |
| 61 | #define U32_MAX ((u32)(~0U)) |
| 62 | #endif /* !U32_MAX */ |
| 63 | |
| 64 | #ifndef U64_MAX |
| 65 | #define U64_MAX ((u64)(~0U)) |
| 66 | #endif /* !U64_MAX */ |
| 67 | |
Greg Kroah-Hartman | 213aefe | 2014-10-20 13:40:02 +0800 | [diff] [blame] | 68 | /* |
| 69 | * The GPIO api sucks rocks in places, like removal, so work around their |
| 70 | * explicit requirements of catching the return value for kernels older than |
| 71 | * 3.17, which they explicitly changed in the 3.17 kernel. Consistency is |
| 72 | * overrated. |
| 73 | */ |
Greg Kroah-Hartman | 213aefe | 2014-10-20 13:40:02 +0800 | [diff] [blame] | 74 | #include <linux/gpio.h> |
| 75 | |
Greg Kroah-Hartman | 3906a59 | 2015-05-01 21:05:03 +0200 | [diff] [blame] | 76 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) |
Greg Kroah-Hartman | 213aefe | 2014-10-20 13:40:02 +0800 | [diff] [blame] | 77 | static inline void gb_gpiochip_remove(struct gpio_chip *chip) |
| 78 | { |
| 79 | gpiochip_remove(chip); |
| 80 | } |
| 81 | #else |
| 82 | static inline void gb_gpiochip_remove(struct gpio_chip *chip) |
| 83 | { |
| 84 | int ret; |
Greg Kroah-Hartman | 63ca78b | 2015-05-01 21:05:29 +0200 | [diff] [blame] | 85 | |
Greg Kroah-Hartman | 213aefe | 2014-10-20 13:40:02 +0800 | [diff] [blame] | 86 | ret = gpiochip_remove(chip); |
| 87 | } |
| 88 | #endif |
| 89 | |
Greg Kroah-Hartman | f348964 | 2014-10-28 09:27:50 +0800 | [diff] [blame] | 90 | /* |
| 91 | * ATTRIBUTE_GROUPS showed up in 3.11-rc2, but we need to build on 3.10, so add |
| 92 | * it here. |
| 93 | */ |
Greg Kroah-Hartman | 3906a59 | 2015-05-01 21:05:03 +0200 | [diff] [blame] | 94 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) |
Greg Kroah-Hartman | 66c9898 | 2015-04-01 01:36:23 +0200 | [diff] [blame] | 95 | #include <linux/sysfs.h> |
| 96 | |
Greg Kroah-Hartman | f348964 | 2014-10-28 09:27:50 +0800 | [diff] [blame] | 97 | #define ATTRIBUTE_GROUPS(name) \ |
| 98 | static const struct attribute_group name##_group = { \ |
| 99 | .attrs = name##_attrs, \ |
| 100 | }; \ |
| 101 | static const struct attribute_group *name##_groups[] = { \ |
| 102 | &name##_group, \ |
| 103 | NULL, \ |
| 104 | } |
Greg Kroah-Hartman | 66c9898 | 2015-04-01 01:36:23 +0200 | [diff] [blame] | 105 | |
| 106 | static inline int sysfs_create_groups(struct kobject *kobj, |
| 107 | const struct attribute_group **groups) |
| 108 | { |
| 109 | int error = 0; |
| 110 | int i; |
| 111 | |
| 112 | if (!groups) |
| 113 | return 0; |
| 114 | |
| 115 | for (i = 0; groups[i]; i++) { |
| 116 | error = sysfs_create_group(kobj, groups[i]); |
| 117 | if (error) { |
| 118 | while (--i >= 0) |
| 119 | sysfs_remove_group(kobj, groups[i]); |
| 120 | break; |
| 121 | } |
| 122 | } |
| 123 | return error; |
| 124 | } |
| 125 | |
| 126 | static inline void sysfs_remove_groups(struct kobject *kobj, |
| 127 | const struct attribute_group **groups) |
| 128 | { |
| 129 | int i; |
| 130 | |
| 131 | if (!groups) |
| 132 | return; |
| 133 | for (i = 0; groups[i]; i++) |
| 134 | sysfs_remove_group(kobj, groups[i]); |
| 135 | } |
Greg Kroah-Hartman | f348964 | 2014-10-28 09:27:50 +0800 | [diff] [blame] | 136 | #endif |
| 137 | |
Rui Miguel Silva | 5656ab9 | 2015-06-24 23:20:26 +0100 | [diff] [blame] | 138 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) |
| 139 | #define MMC_HS400_SUPPORTED |
| 140 | #define MMC_DDR52_DEFINED |
| 141 | #endif |
| 142 | |
| 143 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) |
| 144 | #define MMC_POWER_UNDEFINED_SUPPORTED |
| 145 | #endif |
Rui Miguel Silva | 8a01b40 | 2015-06-24 23:20:27 +0100 | [diff] [blame] | 146 | |
| 147 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0) |
| 148 | #include <linux/scatterlist.h> |
| 149 | static inline bool sg_miter_get_next_page(struct sg_mapping_iter *miter) |
| 150 | { |
| 151 | if (!miter->__remaining) { |
| 152 | struct scatterlist *sg; |
| 153 | unsigned long pgoffset; |
| 154 | |
| 155 | if (!__sg_page_iter_next(&miter->piter)) |
| 156 | return false; |
| 157 | |
| 158 | sg = miter->piter.sg; |
| 159 | pgoffset = miter->piter.sg_pgoffset; |
| 160 | |
| 161 | miter->__offset = pgoffset ? 0 : sg->offset; |
| 162 | miter->__remaining = sg->offset + sg->length - |
| 163 | (pgoffset << PAGE_SHIFT) - miter->__offset; |
| 164 | miter->__remaining = min_t(unsigned long, miter->__remaining, |
| 165 | PAGE_SIZE - miter->__offset); |
| 166 | } |
| 167 | |
| 168 | return true; |
| 169 | } |
| 170 | |
| 171 | static inline bool sg_miter_skip(struct sg_mapping_iter *miter, off_t offset) |
| 172 | { |
| 173 | sg_miter_stop(miter); |
| 174 | |
| 175 | while (offset) { |
| 176 | off_t consumed; |
| 177 | |
| 178 | if (!sg_miter_get_next_page(miter)) |
| 179 | return false; |
| 180 | |
| 181 | consumed = min_t(off_t, offset, miter->__remaining); |
| 182 | miter->__offset += consumed; |
| 183 | miter->__remaining -= consumed; |
| 184 | offset -= consumed; |
| 185 | } |
| 186 | |
| 187 | return true; |
| 188 | } |
| 189 | |
| 190 | static inline size_t _sg_copy_buffer(struct scatterlist *sgl, |
| 191 | unsigned int nents, void *buf, |
| 192 | size_t buflen, off_t skip, |
| 193 | bool to_buffer) |
| 194 | { |
| 195 | unsigned int offset = 0; |
| 196 | struct sg_mapping_iter miter; |
| 197 | unsigned long flags; |
| 198 | unsigned int sg_flags = SG_MITER_ATOMIC; |
| 199 | |
| 200 | if (to_buffer) |
| 201 | sg_flags |= SG_MITER_FROM_SG; |
| 202 | else |
| 203 | sg_flags |= SG_MITER_TO_SG; |
| 204 | |
| 205 | sg_miter_start(&miter, sgl, nents, sg_flags); |
| 206 | |
| 207 | if (!sg_miter_skip(&miter, skip)) |
| 208 | return false; |
| 209 | |
| 210 | local_irq_save(flags); |
| 211 | |
| 212 | while (sg_miter_next(&miter) && offset < buflen) { |
| 213 | unsigned int len; |
| 214 | |
| 215 | len = min(miter.length, buflen - offset); |
| 216 | |
| 217 | if (to_buffer) |
| 218 | memcpy(buf + offset, miter.addr, len); |
| 219 | else |
| 220 | memcpy(miter.addr, buf + offset, len); |
| 221 | |
| 222 | offset += len; |
| 223 | } |
| 224 | |
| 225 | sg_miter_stop(&miter); |
| 226 | |
| 227 | local_irq_restore(flags); |
| 228 | return offset; |
| 229 | } |
| 230 | |
| 231 | static inline size_t sg_pcopy_to_buffer(struct scatterlist *sgl, |
| 232 | unsigned int nents, void *buf, |
| 233 | size_t buflen, off_t skip) |
| 234 | { |
| 235 | return _sg_copy_buffer(sgl, nents, buf, buflen, skip, true); |
| 236 | } |
| 237 | |
| 238 | static inline size_t sg_pcopy_from_buffer(struct scatterlist *sgl, |
| 239 | unsigned int nents, void *buf, |
| 240 | size_t buflen, off_t skip) |
| 241 | { |
| 242 | return _sg_copy_buffer(sgl, nents, buf, buflen, skip, false); |
| 243 | } |
| 244 | #endif |
| 245 | |
Johan Hovold | 93047af | 2015-07-16 11:44:01 +0200 | [diff] [blame] | 246 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) |
| 247 | #define list_last_entry(ptr, type, member) \ |
| 248 | list_entry((ptr)->prev, type, member) |
| 249 | #endif |
| 250 | |
Rui Miguel Silva | 2870b52 | 2015-08-14 13:58:19 +0100 | [diff] [blame] | 251 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0) |
| 252 | /* |
| 253 | * Before this version the led classdev did not support groups |
| 254 | */ |
| 255 | #define LED_HAVE_GROUPS |
| 256 | #endif |
| 257 | |
| 258 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) |
| 259 | /* |
| 260 | * At this time the internal API for the set brightness was changed to the async |
| 261 | * version, and one sync API was added to handle cases that need immediate |
| 262 | * effect. Also, the led class flash and lock for sysfs access was introduced. |
| 263 | */ |
| 264 | #define LED_HAVE_SET_SYNC |
| 265 | #define LED_HAVE_FLASH |
| 266 | #define LED_HAVE_LOCK |
| 267 | #include <linux/led-class-flash.h> |
| 268 | #endif |
| 269 | |
Rui Miguel Silva | b827e11 | 2016-01-12 14:35:48 +0000 | [diff] [blame] | 270 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0) |
| 271 | /* |
| 272 | * New change in LED api, the set_sync operation was renamed to set_blocking and |
| 273 | * the workqueue is now handle by core. So, only one set operation is need. |
| 274 | */ |
| 275 | #undef LED_HAVE_SET_SYNC |
| 276 | #define LED_HAVE_SET_BLOCKING |
| 277 | #endif |
| 278 | |
Rui Miguel Silva | 2870b52 | 2015-08-14 13:58:19 +0100 | [diff] [blame] | 279 | #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0) |
| 280 | /* |
| 281 | * From this version upper it was introduced the possibility to disable led |
| 282 | * sysfs entries to handle control of the led device to v4l2, which was |
| 283 | * implemented later. So, before that this should return false. |
| 284 | */ |
| 285 | #include <linux/leds.h> |
| 286 | static inline bool led_sysfs_is_disabled(struct led_classdev *led_cdev) |
| 287 | { |
| 288 | return false; |
| 289 | } |
| 290 | #endif |
| 291 | |
| 292 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) |
| 293 | /* |
| 294 | * New helper functions for registering/unregistering flash led devices as v4l2 |
| 295 | * subdevices were added. |
| 296 | */ |
| 297 | #define V4L2_HAVE_FLASH |
| 298 | #include <media/v4l2-flash-led-class.h> |
| 299 | #endif |
| 300 | |
Rui Miguel Silva | ffe2e24 | 2015-11-12 15:36:02 +0000 | [diff] [blame] | 301 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) |
| 302 | /* |
| 303 | * Power supply get by name need to drop reference after call |
| 304 | */ |
| 305 | #define PSY_HAVE_PUT |
| 306 | #endif |
| 307 | |
Rui Miguel Silva | 0273038 | 2016-02-02 14:23:16 +0000 | [diff] [blame] | 308 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0) |
| 309 | #define SPI_DEV_MODALIAS "spidev" |
| 310 | #define SPI_NOR_MODALIAS "spi-nor" |
| 311 | #else |
| 312 | #define SPI_DEV_MODALIAS "spidev" |
| 313 | #define SPI_NOR_MODALIAS "m25p80" |
| 314 | #endif |
| 315 | |
Greg Kroah-Hartman | f91121b | 2014-09-11 08:22:06 -0700 | [diff] [blame] | 316 | #endif /* __GREYBUS_KERNEL_VER_H */ |