From fae8034962edf607151ec811ed78b1d932c1c908 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Fri, 6 Sep 2013 09:28:45 -0700 Subject: [PATCH] Update compat.h to improve support of older kernels. Signed-off-by: Guenter Roeck --- compat.h | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 132 insertions(+), 8 deletions(-) diff --git a/compat.h b/compat.h index 03cb1ff..b18f4e2 100644 --- a/compat.h +++ b/compat.h @@ -1,13 +1,137 @@ -/*--------------------------------------------------------------------------- - * - * compat.h - * Copyright (c) 2012 Guenter Roeck +#ifndef __COMPAT_H +#define __COMPAT_H + +#include + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16) +#error This driver is for kernel versions 2.6.16 and later +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 21) +#if !(defined RHEL_MAJOR && RHEL_MAJOR == 5 && RHEL_MINOR >= 6) +/* Simplified version for compatibility */ +struct i2c_board_info { + char type[I2C_NAME_SIZE]; + unsigned short flags; + unsigned short addr; +}; +#endif +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 25) +/* Some older kernels have a different, useless struct i2c_device_id */ +#define i2c_device_id i2c_device_id_compat +struct i2c_device_id { + char name[I2C_NAME_SIZE]; + kernel_ulong_t driver_data /* Data private to the driver */ + __attribute__((aligned(sizeof(kernel_ulong_t)))); +}; +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32) +static unsigned short empty_i2c[] = { I2C_CLIENT_END }; +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_i2c, + .probe = empty_i2c, + .ignore = empty_i2c, +}; +#endif + +/* Red Hat EL5 includes backports of these functions, so we can't redefine + * our own. */ +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 24) +#if !(defined RHEL_MAJOR && RHEL_MAJOR == 5 && RHEL_MINOR >= 5) +static inline int strict_strtoul(const char *cp, unsigned int base, + unsigned long *res) +{ + *res = simple_strtoul(cp, NULL, base); + return 0; +} + +static inline int strict_strtol(const char *cp, unsigned int base, long *res) +{ + *res = simple_strtol(cp, NULL, base); + return 0; +} +#endif +#endif + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 28) +/* + * Divide positive or negative dividend by positive divisor and round + * to closest integer. Result is undefined for negative divisors and + * for negative dividends if the divisor variable type is unsigned. + */ +#define DIV_ROUND_CLOSEST(x, divisor)( \ +{ \ + typeof(x) __x = x; \ + typeof(divisor) __d = divisor; \ + (((typeof(x))-1) > 0 || \ + ((typeof(divisor))-1) > 0 || (__x) > 0) ? \ + (((__x) + ((__d) / 2)) / (__d)) : \ + (((__x) - ((__d) / 2)) / (__d)); \ +} \ +) +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0) +static inline s32 +i2c_smbus_read_word_swapped(const struct i2c_client *client, u8 command) +{ + s32 value = i2c_smbus_read_word_data(client, command); + + return (value < 0) ? value : swab16(value); +} + +static inline s32 +i2c_smbus_write_word_swapped(const struct i2c_client *client, + u8 command, u16 value) +{ + return i2c_smbus_write_word_data(client, command, swab16(value)); +} +#endif + +#ifndef module_driver +/** + * module_driver() - Helper macro for drivers that don't do anything + * special in module init/exit. This eliminates a lot of boilerplate. + * Each module may only use this macro once, and calling it replaces + * module_init() and module_exit(). + * + * @__driver: driver name + * @__register: register function for this driver type + * @__unregister: unregister function for this driver type + * @...: Additional arguments to be passed to __register and __unregister. * - *--------------------------------------------------------------------------- + * Use this macro to construct bus specific macros for registering + * drivers, and do not use it on its own. */ +#define module_driver(__driver, __register, __unregister, ...) \ +static int __init __driver##_init(void) \ +{ \ + return __register(&(__driver) , ##__VA_ARGS__); \ +} \ +module_init(__driver##_init); \ +static void __exit __driver##_exit(void) \ +{ \ + __unregister(&(__driver) , ##__VA_ARGS__); \ +} \ +module_exit(__driver##_exit); +#endif -#ifndef COMPAT_H -#define COMPAT_H +#ifndef module_i2c_driver +/** + * module_i2c_driver() - Helper macro for registering a I2C driver + * @__i2c_driver: i2c_driver struct + * + * Helper macro for I2C drivers which do not do anything special in module + * init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_i2c_driver(__i2c_driver) \ + module_driver(__i2c_driver, i2c_add_driver, \ + i2c_del_driver) +#endif #ifndef clamp_val #define clamp_val SENSORS_LIMIT @@ -25,4 +149,4 @@ #define release_region(a, b) #endif -#endif /* COMPAT_H */ +#endif /* __COMPAT_H */ -- 2.39.5