diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/asm-generic/div64.h | 216 | ||||
-rw-r--r-- | include/asm-generic/io.h | 55 | ||||
-rw-r--r-- | include/linux/kernel.h | 2 | ||||
-rw-r--r-- | include/linux/math64.h | 1 | ||||
-rw-r--r-- | include/linux/mtd/mtd-abi.h | 2 | ||||
-rw-r--r-- | include/linux/mtd/mtd.h | 2 | ||||
-rw-r--r-- | include/printk.h | 28 | ||||
-rw-r--r-- | include/regulator.h | 28 |
8 files changed, 330 insertions, 4 deletions
diff --git a/include/asm-generic/div64.h b/include/asm-generic/div64.h index 2e0ba8389e..a3b98c86f0 100644 --- a/include/asm-generic/div64.h +++ b/include/asm-generic/div64.h @@ -1,9 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ #ifndef _ASM_GENERIC_DIV64_H #define _ASM_GENERIC_DIV64_H /* * Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com> * Based on former asm-ppc/div64.h and asm-m68knommu/div64.h * + * Optimization for constant divisors on 32-bit machines: + * Copyright (C) 2006-2015 Nicolas Pitre + * * The semantics of do_div() are: * * uint32_t do_div(uint64_t *n, uint32_t base) @@ -18,8 +22,200 @@ */ #include <linux/types.h> +#include <linux/compiler.h> + +#if BITS_PER_LONG == 64 + +/** + * do_div - returns 2 values: calculate remainder and update new dividend + * @n: uint64_t dividend (will be updated) + * @base: uint32_t divisor + * + * Summary: + * ``uint32_t remainder = n % base;`` + * ``n = n / base;`` + * + * Return: (uint32_t)remainder + * + * NOTE: macro parameter @n is evaluated multiple times, + * beware of side effects! + */ +# define do_div(n,base) ({ \ + uint32_t __base = (base); \ + uint32_t __rem; \ + __rem = ((uint64_t)(n)) % __base; \ + (n) = ((uint64_t)(n)) / __base; \ + __rem; \ + }) + +#elif BITS_PER_LONG == 32 + +#include <linux/log2.h> + +/* + * If the divisor happens to be constant, we determine the appropriate + * inverse at compile time to turn the division into a few inline + * multiplications which ought to be much faster. And yet only if compiling + * with a sufficiently recent gcc version to perform proper 64-bit constant + * propagation. + * + * (It is unfortunate that gcc doesn't perform all this internally.) + */ +#ifndef __div64_const32_is_OK +#define __div64_const32_is_OK (__GNUC__ >= 4) +#endif + +#define __div64_const32(n, ___b) \ +({ \ + /* \ + * Multiplication by reciprocal of b: n / b = n * (p / b) / p \ + * \ + * We rely on the fact that most of this code gets optimized \ + * away at compile time due to constant propagation and only \ + * a few multiplication instructions should remain. \ + * Hence this monstrous macro (static inline doesn't always \ + * do the trick here). \ + */ \ + uint64_t ___res, ___x, ___t, ___m, ___n = (n); \ + uint32_t ___p, ___bias; \ + \ + /* determine MSB of b */ \ + ___p = 1 << ilog2(___b); \ + \ + /* compute m = ((p << 64) + b - 1) / b */ \ + ___m = (~0ULL / ___b) * ___p; \ + ___m += (((~0ULL % ___b + 1) * ___p) + ___b - 1) / ___b; \ + \ + /* one less than the dividend with highest result */ \ + ___x = ~0ULL / ___b * ___b - 1; \ + \ + /* test our ___m with res = m * x / (p << 64) */ \ + ___res = ((___m & 0xffffffff) * (___x & 0xffffffff)) >> 32; \ + ___t = ___res += (___m & 0xffffffff) * (___x >> 32); \ + ___res += (___x & 0xffffffff) * (___m >> 32); \ + ___t = (___res < ___t) ? (1ULL << 32) : 0; \ + ___res = (___res >> 32) + ___t; \ + ___res += (___m >> 32) * (___x >> 32); \ + ___res /= ___p; \ + \ + /* Now sanitize and optimize what we've got. */ \ + if (~0ULL % (___b / (___b & -___b)) == 0) { \ + /* special case, can be simplified to ... */ \ + ___n /= (___b & -___b); \ + ___m = ~0ULL / (___b / (___b & -___b)); \ + ___p = 1; \ + ___bias = 1; \ + } else if (___res != ___x / ___b) { \ + /* \ + * We can't get away without a bias to compensate \ + * for bit truncation errors. To avoid it we'd need an \ + * additional bit to represent m which would overflow \ + * a 64-bit variable. \ + * \ + * Instead we do m = p / b and n / b = (n * m + m) / p. \ + */ \ + ___bias = 1; \ + /* Compute m = (p << 64) / b */ \ + ___m = (~0ULL / ___b) * ___p; \ + ___m += ((~0ULL % ___b + 1) * ___p) / ___b; \ + } else { \ + /* \ + * Reduce m / p, and try to clear bit 31 of m when \ + * possible, otherwise that'll need extra overflow \ + * handling later. \ + */ \ + uint32_t ___bits = -(___m & -___m); \ + ___bits |= ___m >> 32; \ + ___bits = (~___bits) << 1; \ + /* \ + * If ___bits == 0 then setting bit 31 is unavoidable. \ + * Simply apply the maximum possible reduction in that \ + * case. Otherwise the MSB of ___bits indicates the \ + * best reduction we should apply. \ + */ \ + if (!___bits) { \ + ___p /= (___m & -___m); \ + ___m /= (___m & -___m); \ + } else { \ + ___p >>= ilog2(___bits); \ + ___m >>= ilog2(___bits); \ + } \ + /* No bias needed. */ \ + ___bias = 0; \ + } \ + \ + /* \ + * Now we have a combination of 2 conditions: \ + * \ + * 1) whether or not we need to apply a bias, and \ + * \ + * 2) whether or not there might be an overflow in the cross \ + * product determined by (___m & ((1 << 63) | (1 << 31))). \ + * \ + * Select the best way to do (m_bias + m * n) / (1 << 64). \ + * From now on there will be actual runtime code generated. \ + */ \ + ___res = __arch_xprod_64(___m, ___n, ___bias); \ + \ + ___res /= ___p; \ +}) + +#ifndef __arch_xprod_64 +/* + * Default C implementation for __arch_xprod_64() + * + * Prototype: uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias) + * Semantic: retval = ((bias ? m : 0) + m * n) >> 64 + * + * The product is a 128-bit value, scaled down to 64 bits. + * Assuming constant propagation to optimize away unused conditional code. + * Architectures may provide their own optimized assembly implementation. + */ +static inline uint64_t __arch_xprod_64(const uint64_t m, uint64_t n, bool bias) +{ + uint32_t m_lo = m; + uint32_t m_hi = m >> 32; + uint32_t n_lo = n; + uint32_t n_hi = n >> 32; + uint64_t res; + uint32_t res_lo, res_hi, tmp; + + if (!bias) { + res = ((uint64_t)m_lo * n_lo) >> 32; + } else if (!(m & ((1ULL << 63) | (1ULL << 31)))) { + /* there can't be any overflow here */ + res = (m + (uint64_t)m_lo * n_lo) >> 32; + } else { + res = m + (uint64_t)m_lo * n_lo; + res_lo = res >> 32; + res_hi = (res_lo < m_hi); + res = res_lo | ((uint64_t)res_hi << 32); + } + + if (!(m & ((1ULL << 63) | (1ULL << 31)))) { + /* there can't be any overflow here */ + res += (uint64_t)m_lo * n_hi; + res += (uint64_t)m_hi * n_lo; + res >>= 32; + } else { + res += (uint64_t)m_lo * n_hi; + tmp = res >> 32; + res += (uint64_t)m_hi * n_lo; + res_lo = res >> 32; + res_hi = (res_lo < tmp); + res = res_lo | ((uint64_t)res_hi << 32); + } + + res += (uint64_t)m_hi * n_hi; + + return res; +} +#endif + +#ifndef __div64_32 extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); +#endif /* The unnecessary pointer compare is there * to check for type safety (n must be 64bit) @@ -28,7 +224,19 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); uint32_t __base = (base); \ uint32_t __rem; \ (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ - if (((n) >> 32) == 0) { \ + if (__builtin_constant_p(__base) && \ + is_power_of_2(__base)) { \ + __rem = (n) & (__base - 1); \ + (n) >>= ilog2(__base); \ + } else if (__div64_const32_is_OK && \ + __builtin_constant_p(__base) && \ + __base != 0) { \ + uint32_t __res_lo, __n_lo = (n); \ + (n) = __div64_const32(n, __base); \ + /* the remainder can be computed with 32-bit regs */ \ + __res_lo = (n); \ + __rem = __n_lo - __res_lo * __base; \ + } else if (likely(((n) >> 32) == 0)) { \ __rem = (uint32_t)(n) % __base; \ (n) = (uint32_t)(n) / __base; \ } else \ @@ -36,4 +244,10 @@ extern uint32_t __div64_32(uint64_t *dividend, uint32_t divisor); __rem; \ }) +#else /* BITS_PER_LONG == ?? */ + +# error do_div() does not yet support the C64 + +#endif /* BITS_PER_LONG */ + #endif /* _ASM_GENERIC_DIV64_H */ diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h index 76e6d0dc11..a4b0dc4b43 100644 --- a/include/asm-generic/io.h +++ b/include/asm-generic/io.h @@ -11,6 +11,7 @@ #ifndef __ASM_GENERIC_IO_H #define __ASM_GENERIC_IO_H +#include <linux/string.h> /* for memset() and memcpy() */ #include <linux/types.h> #include <asm/byteorder.h> @@ -424,4 +425,58 @@ static inline void iowrite64be(u64 value, volatile void __iomem *addr) #define IOMEM(addr) ((void __force __iomem *)(addr)) #endif +#define __io_virt(x) ((void __force *)(x)) + +#ifndef memset_io +#define memset_io memset_io +/** + * memset_io Set a range of I/O memory to a constant value + * @addr: The beginning of the I/O-memory range to set + * @val: The value to set the memory to + * @count: The number of bytes to set + * + * Set a range of I/O memory to a given value. + */ +static inline void memset_io(volatile void __iomem *addr, int value, + size_t size) +{ + memset(__io_virt(addr), value, size); +} +#endif + +#ifndef memcpy_fromio +#define memcpy_fromio memcpy_fromio +/** + * memcpy_fromio Copy a block of data from I/O memory + * @dst: The (RAM) destination for the copy + * @src: The (I/O memory) source for the data + * @count: The number of bytes to copy + * + * Copy a block of data from I/O memory. + */ +static inline void memcpy_fromio(void *buffer, + const volatile void __iomem *addr, + size_t size) +{ + memcpy(buffer, __io_virt(addr), size); +} +#endif + +#ifndef memcpy_toio +#define memcpy_toio memcpy_toio +/** + * memcpy_toio Copy a block of data into I/O memory + * @dst: The (I/O memory) destination for the copy + * @src: The (RAM) source for the data + * @count: The number of bytes to copy + * + * Copy a block of data to I/O memory. + */ +static inline void memcpy_toio(volatile void __iomem *addr, const void *buffer, + size_t size) +{ + memcpy(__io_virt(addr), buffer, size); +} +#endif + #endif /* __ASM_GENERIC_IO_H */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 787571a5a0..9ccdd60224 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -6,7 +6,7 @@ #include <linux/bug.h> #include <linux/barebox-wrapper.h> #include <linux/limits.h> -#include <asm-generic/div64.h> +#include <linux/math64.h> #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) #define ALIGN_DOWN(x, a) ALIGN((x) - ((a) - 1), (a)) diff --git a/include/linux/math64.h b/include/linux/math64.h index e8b737e70e..8537c0412d 100644 --- a/include/linux/math64.h +++ b/include/linux/math64.h @@ -3,6 +3,7 @@ #define _LINUX_MATH64_H #include <linux/types.h> +#include <linux/compiler.h> #include <asm-generic/div64.h> #if BITS_PER_LONG == 64 diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h index 6ad34c8912..b7a8955880 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/include/linux/mtd/mtd-abi.h @@ -7,7 +7,7 @@ #ifndef __MTD_ABI_H__ #define __MTD_ABI_H__ -#include <asm-generic/div64.h> +#include <linux/math64.h> struct erase_info_user { uint64_t start; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 0d977fea25..b17e590f5e 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -15,7 +15,7 @@ #include <linux/types.h> #include <linux/list.h> #include <linux/mtd/mtd-abi.h> -#include <asm-generic/div64.h> +#include <linux/math64.h> #define MTD_CHAR_MAJOR 90 #define MTD_BLOCK_MAJOR 31 diff --git a/include/printk.h b/include/printk.h index 9941ddb12c..f92e477298 100644 --- a/include/printk.h +++ b/include/printk.h @@ -160,4 +160,32 @@ extern void print_hex_dump(const char *level, const char *prefix_str, int prefix_type, int rowsize, int groupsize, const void *buf, size_t len, bool ascii); +#if LOGLEVEL <= MSG_DEBUG +#define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) \ + print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ + groupsize, buf, len, ascii) +#else +static inline void print_hex_dump_debug(const char *prefix_str, int prefix_type, + int rowsize, int groupsize, + const void *buf, size_t len, bool ascii) +{ +} +#endif + +/** + * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params + * @prefix_str: string to prefix each line with; + * caller supplies trailing spaces for alignment if desired + * @prefix_type: controls whether prefix of an offset, address, or none + * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE) + * @buf: data blob to dump + * @len: number of bytes in the @buf + * + * Calls print_hex_dump(), with log level of KERN_DEBUG, + * rowsize of 16, groupsize of 1, and ASCII output included. + */ +#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ + print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true) + #endif diff --git a/include/regulator.h b/include/regulator.h index 7c2a01b687..bbe8dd91d8 100644 --- a/include/regulator.h +++ b/include/regulator.h @@ -51,6 +51,9 @@ struct regulator_bulk_data { * @disable_val: Disabling value for control when using regmap enable/disable ops * @enable_is_inverted: A flag to indicate set enable_mask bits to disable * when using regulator_enable_regmap and friends APIs. + * @volt_table: Voltage mapping table (if table based mapping) + * @fixed_uV: Fixed voltage of rails. + * @off_on_delay: guard time (in uS), before re-enabling a regulator */ struct regulator_desc { @@ -73,6 +76,9 @@ struct regulator_desc { const struct regulator_linear_range *linear_ranges; int n_linear_ranges; + const unsigned int *volt_table; + int fixed_uV; + unsigned int off_on_delay; }; struct regulator_dev { @@ -92,6 +98,9 @@ struct regulator_ops { int (*list_voltage) (struct regulator_dev *, unsigned int); int (*set_voltage_sel) (struct regulator_dev *, unsigned int); int (*map_voltage)(struct regulator_dev *, int min_uV, int max_uV); + + int (*get_voltage) (struct regulator_dev *); + int (*get_voltage_sel) (struct regulator_dev *); }; /* @@ -166,12 +175,26 @@ int regulator_bulk_disable(int num_consumers, void regulator_bulk_free(int num_consumers, struct regulator_bulk_data *consumers); +/** + * regulator_get_voltage - get regulator output voltage + * @regulator: regulator source + * + * This returns the current regulator voltage in uV. + * + * NOTE: If the regulator is disabled it will return the voltage value. This + * function should not be used to determine regulator state. + */ +int regulator_get_voltage(struct regulator *regulator); + /* * Helper functions intended to be used by regulator drivers prior registering * their regulators. */ int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc, unsigned int selector); + +int regulator_list_voltage_table(struct regulator_dev *rdev, + unsigned int selector); #else static inline struct regulator *regulator_get(struct device_d *dev, const char *id) @@ -223,6 +246,11 @@ static inline void regulator_bulk_free(int num_consumers, { } +static inline int regulator_get_voltage(struct regulator *regulator) +{ + return -EINVAL; +} + #endif #endif /* __REGULATOR_H */ |