diff options
Diffstat (limited to 'include/linux')
173 files changed, 11924 insertions, 822 deletions
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h index 390220a3de..cc24b38e83 100644 --- a/include/linux/amba/bus.h +++ b/include/linux/amba/bus.h @@ -37,7 +37,7 @@ struct amba_id { struct clk; struct amba_device { - struct device_d dev; + struct device dev; struct resource res; void __iomem *base; struct clk *pclk; @@ -45,7 +45,7 @@ struct amba_device { }; struct amba_driver { - struct driver_d drv; + struct driver drv; int (*probe)(struct amba_device *, const struct amba_id *); int (*remove)(struct amba_device *); const struct amba_id *id_table; @@ -75,12 +75,12 @@ int amba_device_add(struct amba_device *); int amba_device_register(struct amba_device *, struct resource *); struct amba_device * -amba_aphb_device_add(struct device_d *parent, const char *name, int id, +amba_aphb_device_add(struct device *parent, const char *name, int id, resource_size_t base, size_t size, void *pdata, unsigned int periphid); static inline struct amba_device * -amba_apb_device_add(struct device_d *parent, const char *name, int id, +amba_apb_device_add(struct device *parent, const char *name, int id, resource_size_t base, size_t size, void *pdata, unsigned int periphid) { @@ -89,7 +89,7 @@ amba_apb_device_add(struct device_d *parent, const char *name, int id, } static inline struct amba_device * -amba_ahb_device_add(struct device_d *parent, const char *name, int id, +amba_ahb_device_add(struct device *parent, const char *name, int id, resource_size_t base, size_t size, void *pdata, unsigned int periphid) { diff --git a/include/linux/amba/mmci.h b/include/linux/amba/mmci.h index 0bf558124c..719daadbb7 100644 --- a/include/linux/amba/mmci.h +++ b/include/linux/amba/mmci.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * include/linux/amba/mmci.h */ diff --git a/include/linux/amba/pl061.h b/include/linux/amba/pl061.h index d498cd7a8c..e1b2fac152 100644 --- a/include/linux/amba/pl061.h +++ b/include/linux/amba/pl061.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __AMBA_PL061_H__ #define __AMBA_PL061_H__ diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 1b38b7b372..f6942c6420 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -1,28 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2015, Linaro Limited - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #ifndef __LINUX_ARM_SMCCC_H #define __LINUX_ARM_SMCCC_H +#include <linux/const.h> + /* * This file provides common defines for ARM SMC Calling Convention as * specified in - * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html + * https://developer.arm.com/docs/den0028/latest + * + * This code is up-to-date with version DEN 0028 C */ -/* This constant is shifted by 31, make sure it's of an unsigned type */ -#define ARM_SMCCC_STD_CALL 0UL -#define ARM_SMCCC_FAST_CALL 1UL +#define ARM_SMCCC_STD_CALL _AC(0,U) +#define ARM_SMCCC_FAST_CALL _AC(1,U) #define ARM_SMCCC_TYPE_SHIFT 31 #define ARM_SMCCC_SMC_32 0 @@ -53,18 +47,178 @@ #define ARM_SMCCC_OWNER_SIP 2 #define ARM_SMCCC_OWNER_OEM 3 #define ARM_SMCCC_OWNER_STANDARD 4 +#define ARM_SMCCC_OWNER_STANDARD_HYP 5 +#define ARM_SMCCC_OWNER_VENDOR_HYP 6 #define ARM_SMCCC_OWNER_TRUSTED_APP 48 #define ARM_SMCCC_OWNER_TRUSTED_APP_END 49 #define ARM_SMCCC_OWNER_TRUSTED_OS 50 #define ARM_SMCCC_OWNER_TRUSTED_OS_END 63 +#define ARM_SMCCC_FUNC_QUERY_CALL_UID 0xff01 + #define ARM_SMCCC_QUIRK_NONE 0 #define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */ +#define ARM_SMCCC_VERSION_1_0 0x10000 +#define ARM_SMCCC_VERSION_1_1 0x10001 +#define ARM_SMCCC_VERSION_1_2 0x10002 + +#define ARM_SMCCC_VERSION_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0) + +#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 1) + +#define ARM_SMCCC_ARCH_SOC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 2) + +#define ARM_SMCCC_ARCH_WORKAROUND_1 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x8000) + +#define ARM_SMCCC_ARCH_WORKAROUND_2 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x7fff) + +#define ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_FUNC_QUERY_CALL_UID) + +/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */ +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 0xb66fb428U +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 0xe911c52eU +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 0x564bcaa9U +#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3 0x743a004dU + +/* KVM "vendor specific" services */ +#define ARM_SMCCC_KVM_FUNC_FEATURES 0 +#define ARM_SMCCC_KVM_FUNC_PTP 1 +#define ARM_SMCCC_KVM_FUNC_FEATURES_2 127 +#define ARM_SMCCC_KVM_NUM_FUNCS 128 + +#define ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_KVM_FUNC_FEATURES) + +#define SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED 1 + +/* + * ptp_kvm is a feature used for time sync between vm and host. + * ptp_kvm module in guest kernel will get service from host using + * this hypercall ID. + */ +#define ARM_SMCCC_VENDOR_HYP_KVM_PTP_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_VENDOR_HYP, \ + ARM_SMCCC_KVM_FUNC_PTP) + +/* ptp_kvm counter type ID */ +#define KVM_PTP_VIRT_COUNTER 0 +#define KVM_PTP_PHYS_COUNTER 1 + +/* Paravirtualised time calls (defined by ARM DEN0057A) */ +#define ARM_SMCCC_HV_PV_TIME_FEATURES \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x20) + +#define ARM_SMCCC_HV_PV_TIME_ST \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD_HYP, \ + 0x21) + +/* TRNG entropy source calls (defined by ARM DEN0098) */ +#define ARM_SMCCC_TRNG_VERSION \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x50) + +#define ARM_SMCCC_TRNG_FEATURES \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x51) + +#define ARM_SMCCC_TRNG_GET_UUID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x52) + +#define ARM_SMCCC_TRNG_RND32 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x53) + +#define ARM_SMCCC_TRNG_RND64 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_64, \ + ARM_SMCCC_OWNER_STANDARD, \ + 0x53) + +/* + * Return codes defined in ARM DEN 0070A + * ARM DEN 0070A is now merged/consolidated into ARM DEN 0028 C + */ +#define SMCCC_RET_SUCCESS 0 +#define SMCCC_RET_NOT_SUPPORTED -1 +#define SMCCC_RET_NOT_REQUIRED -2 +#define SMCCC_RET_INVALID_PARAMETER -3 + #ifndef __ASSEMBLY__ #include <linux/linkage.h> #include <linux/types.h> + +enum arm_smccc_conduit { + SMCCC_CONDUIT_NONE, + SMCCC_CONDUIT_SMC, + SMCCC_CONDUIT_HVC, +}; + +/** + * arm_smccc_1_1_get_conduit() + * + * Returns the conduit to be used for SMCCCv1.1 or later. + * + * When SMCCCv1.1 is not present, returns SMCCC_CONDUIT_NONE. + */ +static inline enum arm_smccc_conduit arm_smccc_1_1_get_conduit(void) +{ + /* No HVC support yet */ + return SMCCC_CONDUIT_SMC; +} + +/** + * arm_smccc_get_version() + * + * Returns the version to be used for SMCCCv1.1 or later. + * + * When SMCCCv1.1 or above is not present, returns SMCCCv1.0, but this + * does not imply the presence of firmware or a valid conduit. Caller + * handling SMCCCv1.0 must determine the conduit by other means. + */ +u32 arm_smccc_get_version(void); + +void arm_smccc_version_init(u32 version, enum arm_smccc_conduit conduit); + /** * struct arm_smccc_res - Result from SMC/HVC call * @a0-a3 result values from registers 0 to 3 @@ -131,5 +285,186 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__) +/* SMCCC v1.1 implementation madness follows */ +#ifdef CONFIG_CPU_64 + +#define SMCCC_SMC_INST "smc #0" +#define SMCCC_HVC_INST "hvc #0" + +#elif defined(CONFIG_CPU_32) +#include <asm/opcodes-sec.h> +#include <asm/opcodes-virt.h> + +#define SMCCC_SMC_INST __SMC(0) +#define SMCCC_HVC_INST __HVC(0) + +#endif + +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x + +#define __count_args(...) \ + ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) + +#define __constraint_read_0 "r" (arg0) +#define __constraint_read_1 __constraint_read_0, "r" (arg1) +#define __constraint_read_2 __constraint_read_1, "r" (arg2) +#define __constraint_read_3 __constraint_read_2, "r" (arg3) +#define __constraint_read_4 __constraint_read_3, "r" (arg4) +#define __constraint_read_5 __constraint_read_4, "r" (arg5) +#define __constraint_read_6 __constraint_read_5, "r" (arg6) +#define __constraint_read_7 __constraint_read_6, "r" (arg7) + +#define __declare_arg_0(a0, res) \ + struct arm_smccc_res *___res = res; \ + register unsigned long arg0 asm("r0") = (u32)a0 + +#define __declare_arg_1(a0, a1, res) \ + typeof(a1) __a1 = a1; \ + struct arm_smccc_res *___res = res; \ + register unsigned long arg0 asm("r0") = (u32)a0; \ + register typeof(a1) arg1 asm("r1") = __a1 + +#define __declare_arg_2(a0, a1, a2, res) \ + typeof(a1) __a1 = a1; \ + typeof(a2) __a2 = a2; \ + struct arm_smccc_res *___res = res; \ + register unsigned long arg0 asm("r0") = (u32)a0; \ + register typeof(a1) arg1 asm("r1") = __a1; \ + register typeof(a2) arg2 asm("r2") = __a2 + +#define __declare_arg_3(a0, a1, a2, a3, res) \ + typeof(a1) __a1 = a1; \ + typeof(a2) __a2 = a2; \ + typeof(a3) __a3 = a3; \ + struct arm_smccc_res *___res = res; \ + register unsigned long arg0 asm("r0") = (u32)a0; \ + register typeof(a1) arg1 asm("r1") = __a1; \ + register typeof(a2) arg2 asm("r2") = __a2; \ + register typeof(a3) arg3 asm("r3") = __a3 + +#define __declare_arg_4(a0, a1, a2, a3, a4, res) \ + typeof(a4) __a4 = a4; \ + __declare_arg_3(a0, a1, a2, a3, res); \ + register typeof(a4) arg4 asm("r4") = __a4 + +#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \ + typeof(a5) __a5 = a5; \ + __declare_arg_4(a0, a1, a2, a3, a4, res); \ + register typeof(a5) arg5 asm("r5") = __a5 + +#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \ + typeof(a6) __a6 = a6; \ + __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \ + register typeof(a6) arg6 asm("r6") = __a6 + +#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \ + typeof(a7) __a7 = a7; \ + __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \ + register typeof(a7) arg7 asm("r7") = __a7 + +#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__) +#define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__) + +#define ___constraints(count) \ + : __constraint_read_ ## count \ + : "memory" +#define __constraints(count) ___constraints(count) + +/* + * We have an output list that is not necessarily used, and GCC feels + * entitled to optimise the whole sequence away. "volatile" is what + * makes it stick. + */ +#define __arm_smccc_1_1(inst, ...) \ + do { \ + register unsigned long r0 asm("r0"); \ + register unsigned long r1 asm("r1"); \ + register unsigned long r2 asm("r2"); \ + register unsigned long r3 asm("r3"); \ + __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ + asm volatile(inst "\n" : \ + "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \ + __constraints(__count_args(__VA_ARGS__))); \ + if (___res) \ + *___res = (typeof(*___res)){r0, r1, r2, r3}; \ + } while (0) + +/* + * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call + * + * This is a variadic macro taking one to eight source arguments, and + * an optional return structure. + * + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This macro is used to make SMC calls following SMC Calling Convention v1.1. + * The content of the supplied param are copied to registers 0 to 7 prior + * to the SMC instruction. The return values are updated with the content + * from register 0 to 3 on return from the SMC instruction if not NULL. + */ +#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__) + +/* + * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call + * + * This is a variadic macro taking one to eight source arguments, and + * an optional return structure. + * + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This macro is used to make HVC calls following SMC Calling Convention v1.1. + * The content of the supplied param are copied to registers 0 to 7 prior + * to the HVC instruction. The return values are updated with the content + * from register 0 to 3 on return from the HVC instruction if not NULL. + */ +#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) + +/* + * Like arm_smccc_1_1* but always returns SMCCC_RET_NOT_SUPPORTED. + * Used when the SMCCC conduit is not defined. The empty asm statement + * avoids compiler warnings about unused variables. + */ +#define __fail_smccc_1_1(...) \ + do { \ + __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ + asm ("" : __constraints(__count_args(__VA_ARGS__))); \ + if (___res) \ + ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ + } while (0) + +/* + * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call + * + * This is a variadic macro taking one to eight source arguments, and + * an optional return structure. + * + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This macro will make either an HVC call or an SMC call depending on the + * current SMCCC conduit. If no valid conduit is available then -1 + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied). + * + * The return value also provides the conduit that was used. + */ +#define arm_smccc_1_1_invoke(...) ({ \ + int method = arm_smccc_1_1_get_conduit(); \ + switch (method) { \ + case SMCCC_CONDUIT_HVC: \ + arm_smccc_1_1_hvc(__VA_ARGS__); \ + break; \ + case SMCCC_CONDUIT_SMC: \ + arm_smccc_1_1_smc(__VA_ARGS__); \ + break; \ + default: \ + __fail_smccc_1_1(__VA_ARGS__); \ + method = SMCCC_CONDUIT_NONE; \ + break; \ + } \ + method; \ + }) + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/ diff --git a/include/linux/atomic.h b/include/linux/atomic.h new file mode 100644 index 0000000000..c7bdf5857c --- /dev/null +++ b/include/linux/atomic.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LINUX_ATOMIC_H_ +#define LINUX_ATOMIC_H_ + +#include <asm-generic/atomic.h> +#include <linux/compiler.h> +#include <asm-generic/cmpxchg.h> + +#define raw_cmpxchg_relaxed cmpxchg + +/** + * raw_atomic_cmpxchg_relaxed() - atomic compare and exchange with relaxed ordering + * @v: pointer to atomic_t + * @old: int value to compare with + * @new: int value to assign + * + * If (@v == @old), atomically updates @v to @new with relaxed ordering. + * + * Safe to use in noinstr code; prefer atomic_cmpxchg_relaxed() elsewhere. + * + * Return: The original value of @v. + */ +static __always_inline int +raw_atomic_cmpxchg_relaxed(atomic_t *v, int old, int new) +{ + return raw_cmpxchg_relaxed(&v->counter, old, new); +} + +/** + * atomic_try_cmpxchg_relaxed() - atomic compare and exchange with relaxed ordering + * @v: pointer to atomic_t + * @old: pointer to int value to compare with + * @new: int value to assign + * + * If (@v == @old), atomically updates @v to @new with relaxed ordering. + * Otherwise, updates @old to the current value of @v. + * + * Return: @true if the exchange occured, @false otherwise. + */ +static __always_inline bool +atomic_try_cmpxchg_relaxed(atomic_t *v, int *old, int new) +{ + int r, o = *old; + r = raw_atomic_cmpxchg_relaxed(v, o, new); + if (unlikely(r != o)) + *old = r; + return likely(r == o); +} + +/** + * atomic_fetch_add() - atomic add + * @i: int value to add + * @v: pointer to atomic_t + * + * Atomically updates @v to (@v + @i). + * + * Return: The original value of @v. + */ +static __always_inline int +atomic_fetch_add(int i, atomic_t *v) +{ + int old = v->counter; + v->counter += i; + return old; +} +#define atomic_fetch_add_relaxed atomic_fetch_add +#define atomic_fetch_sub(i, v) atomic_fetch_add(-i, v) +#define atomic_fetch_sub_release atomic_fetch_sub + +#endif diff --git a/include/linux/barebox-wrapper.h b/include/linux/barebox-wrapper.h index 83fa9223de..5d311e1d70 100644 --- a/include/linux/barebox-wrapper.h +++ b/include/linux/barebox-wrapper.h @@ -19,7 +19,11 @@ static inline void vfree(const void *addr) #define MODULE_AUTHOR(x) #define MODULE_DESCRIPTION(x) #define MODULE_LICENSE(x) +#define MODULE_VERSION(x) #define MODULE_ALIAS(x) +#define MODULE_DEVICE_TABLE(bus, table) +#define MODULE_ALIAS_DSA_TAG_DRIVER(drv) +#define MODULE_ALIAS_CRYPTO(alias) #define __user #define __init diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h index 34e2f470fb..8917f99ccb 100644 --- a/include/linux/basic_mmio_gpio.h +++ b/include/linux/basic_mmio_gpio.h @@ -60,7 +60,7 @@ static inline struct bgpio_chip *to_bgpio_chip(struct gpio_chip *gc) return container_of(gc, struct bgpio_chip, gc); } -int bgpio_init(struct bgpio_chip *bgc, struct device_d *dev, +int bgpio_init(struct bgpio_chip *bgc, struct device *dev, unsigned int sz, void __iomem *dat, void __iomem *set, void __iomem *clr, void __iomem *dirout, void __iomem *dirin, unsigned long flags); diff --git a/include/linux/bcd.h b/include/linux/bcd.h index 18fff11fb3..718f305bf7 100644 --- a/include/linux/bcd.h +++ b/include/linux/bcd.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _BCD_H #define _BCD_H diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h index cf2588d811..44e8cb3a7d 100644 --- a/include/linux/bitfield.h +++ b/include/linux/bitfield.h @@ -53,7 +53,7 @@ ({ \ BUILD_BUG_ON_MSG(!__builtin_constant_p(_mask), \ _pfx "mask is not constant"); \ - BUILD_BUG_ON_MSG(!(_mask), _pfx "mask is zero"); \ + BUILD_BUG_ON_MSG(_mask == 0, _pfx "mask is zero"); \ BUILD_BUG_ON_MSG(__builtin_constant_p(_val) ? \ ~((_mask) >> __bf_shf(_mask)) & (_val) : 0, \ _pfx "value too large for the field"); \ diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 4b98521a83..9ec1ee2d14 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_BITMAP_H #define __LINUX_BITMAP_H @@ -54,6 +56,10 @@ * bitmap_find_free_region(bitmap, bits, order) Find and allocate bit region * bitmap_release_region(bitmap, pos, order) Free specified bit region * bitmap_allocate_region(bitmap, pos, order) Allocate specified bit region + * bitmap_from_arr32(dst, buf, nbits) Copy nbits from u32[] buf to dst + * bitmap_from_arr64(dst, buf, nbits) Copy nbits from u64[] buf to dst + * bitmap_to_arr32(buf, src, nbits) Copy nbits from buf to u32[] dst + * bitmap_to_arr64(buf, src, nbits) Copy nbits from buf to u64[] dst */ /* @@ -79,6 +85,13 @@ */ /* + * Allocation and deallocation of bitmap. + * Provided in lib/bitmap.c to avoid circular dependency. + */ +unsigned long *bitmap_zalloc(unsigned int nbits); +unsigned long *bitmap_xzalloc(unsigned int nbits); + +/* * lib/bitmap.c provides these functions: */ @@ -169,6 +182,103 @@ static inline void bitmap_copy(unsigned long *dst, const unsigned long *src, } } +/* + * Copy bitmap and clear tail bits in last word. + */ +static inline void bitmap_copy_clear_tail(unsigned long *dst, + const unsigned long *src, unsigned int nbits) +{ + bitmap_copy(dst, src, nbits); + if (nbits % BITS_PER_LONG) + dst[nbits / BITS_PER_LONG] &= BITMAP_LAST_WORD_MASK(nbits); +} + +/* + * On 32-bit systems bitmaps are represented as u32 arrays internally. On LE64 + * machines the order of hi and lo parts of numbers match the bitmap structure. + * In both cases conversion is not needed when copying data from/to arrays of + * u32. But in LE64 case, typecast in bitmap_copy_clear_tail() may lead + * to out-of-bound access. To avoid that, both LE and BE variants of 64-bit + * architectures are not using bitmap_copy_clear_tail(). + */ +#if BITS_PER_LONG == 64 +void bitmap_from_arr32(unsigned long *bitmap, const u32 *buf, + unsigned int nbits); +void bitmap_to_arr32(u32 *buf, const unsigned long *bitmap, + unsigned int nbits); +#else +#define bitmap_from_arr32(bitmap, buf, nbits) \ + bitmap_copy_clear_tail((unsigned long *) (bitmap), \ + (const unsigned long *) (buf), (nbits)) +#define bitmap_to_arr32(buf, bitmap, nbits) \ + bitmap_copy_clear_tail((unsigned long *) (buf), \ + (const unsigned long *) (bitmap), (nbits)) +#endif + +/* + * On 64-bit systems bitmaps are represented as u64 arrays internally. On LE32 + * machines the order of hi and lo parts of numbers match the bitmap structure. + * In both cases conversion is not needed when copying data from/to arrays of + * u64. + */ +#if (BITS_PER_LONG == 32) && defined(__BIG_ENDIAN) +void bitmap_from_arr64(unsigned long *bitmap, const u64 *buf, unsigned int nbits); +void bitmap_to_arr64(u64 *buf, const unsigned long *bitmap, unsigned int nbits); +#else +#define bitmap_from_arr64(bitmap, buf, nbits) \ + bitmap_copy_clear_tail((unsigned long *)(bitmap), (const unsigned long *)(buf), (nbits)) +#define bitmap_to_arr64(buf, bitmap, nbits) \ + bitmap_copy_clear_tail((unsigned long *)(buf), (const unsigned long *)(bitmap), (nbits)) +#endif + +/** + * BITMAP_FROM_U64() - Represent u64 value in the format suitable for bitmap. + * @n: u64 value + * + * Linux bitmaps are internally arrays of unsigned longs, i.e. 32-bit + * integers in 32-bit environment, and 64-bit integers in 64-bit one. + * + * There are four combinations of endianness and length of the word in linux + * ABIs: LE64, BE64, LE32 and BE32. + * + * On 64-bit kernels 64-bit LE and BE numbers are naturally ordered in + * bitmaps and therefore don't require any special handling. + * + * On 32-bit kernels 32-bit LE ABI orders lo word of 64-bit number in memory + * prior to hi, and 32-bit BE orders hi word prior to lo. The bitmap on the + * other hand is represented as an array of 32-bit words and the position of + * bit N may therefore be calculated as: word #(N/32) and bit #(N%32) in that + * word. For example, bit #42 is located at 10th position of 2nd word. + * It matches 32-bit LE ABI, and we can simply let the compiler store 64-bit + * values in memory as it usually does. But for BE we need to swap hi and lo + * words manually. + * + * With all that, the macro BITMAP_FROM_U64() does explicit reordering of hi and + * lo parts of u64. For LE32 it does nothing, and for BE environment it swaps + * hi and lo words, as is expected by bitmap. + */ +#if BITS_PER_LONG == 64 +#define BITMAP_FROM_U64(n) (n) +#else +#define BITMAP_FROM_U64(n) ((unsigned long) ((u64)(n) & ULONG_MAX)), \ + ((unsigned long) ((u64)(n) >> 32)) +#endif + +/** + * bitmap_from_u64 - Check and swap words within u64. + * @mask: source bitmap + * @dst: destination bitmap + * + * In 32-bit Big Endian kernel, when using ``(u32 *)(&val)[*]`` + * to read u64 mask, we will get the wrong word. + * That is ``(u32 *)(&val)[0]`` gets the upper 32 bits, + * but we expect the lower 32-bits of u64. + */ +static inline void bitmap_from_u64(unsigned long *dst, u64 mask) +{ + bitmap_from_arr64(dst, &mask, 64); +} + static inline int bitmap_and(unsigned long *dst, const unsigned long *src1, const unsigned long *src2, int nbits) { diff --git a/include/linux/bitops.h b/include/linux/bitops.h index dd13bf9311..7646e15634 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -1,29 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_BITOPS_H #define _LINUX_BITOPS_H -#include <asm/types.h> + +#include <linux/types.h> +#include <linux/const.h> +#include <linux/bits.h> #ifdef __KERNEL__ -#define BIT(nr) (1UL << (nr)) -#define BIT_ULL(nr) (1ULL << (nr)) -#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) -#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) -#define BITS_PER_BYTE 8 -#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) +#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE) +#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(long)) +#define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(u64)) +#define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(u32)) +#define BITS_TO_BYTES(nr) DIV_ROUND_UP(nr, BITS_PER_TYPE(char)) +#define BYTES_TO_BITS(nb) (((BITS_PER_LONG * (nb)) / sizeof(long))) #endif -/* - * Create a contiguous bitmask starting at bit position @l and ending at - * position @h. For example - * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. - */ -#define GENMASK(h, l) \ - (((~0UL) << (l)) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) - -#define GENMASK_ULL(h, l) \ - (((~0ULL) << (l)) & (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) - +#ifndef __ASSEMBLY__ /* * Include this here because some architectures need generic_ffs/fls in * scope @@ -192,6 +185,20 @@ static inline unsigned long __ffs64(u64 word) return __ffs((unsigned long)word); } +/** + * assign_bit - Assign value to a bit in memory + * @nr: the bit to set + * @addr: the address to start counting from + * @value: the value to assign + */ +static inline void assign_bit(long nr, volatile unsigned long *addr, bool value) +{ + if (value) + set_bit(nr, addr); + else + clear_bit(nr, addr); +} + #ifdef __KERNEL__ #ifndef set_mask_bits @@ -221,5 +228,6 @@ extern unsigned long find_last_bit(const unsigned long *addr, unsigned long size); #endif +#endif /* !(__ASSEMBLY__) */ #endif /* __KERNEL__ */ #endif diff --git a/include/linux/bitrev.h b/include/linux/bitrev.h index 7ffe03f469..ba2965977d 100644 --- a/include/linux/bitrev.h +++ b/include/linux/bitrev.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_BITREV_H #define _LINUX_BITREV_H diff --git a/include/linux/bits.h b/include/linux/bits.h new file mode 100644 index 0000000000..ea5dfa1201 --- /dev/null +++ b/include/linux/bits.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_BITS_H +#define __LINUX_BITS_H + +#include <linux/types.h> +#include <linux/const.h> +#include <asm/bitsperlong.h> + +#define BIT(nr) (UL(1) << (nr)) +#define BIT_ULL(nr) (ULL(1) << (nr)) +#define BIT_MASK(nr) (UL(1) << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BIT_ULL_MASK(nr) (ULL(1) << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) +#define BITS_PER_BYTE 8 + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#define GENMASK(h, l) \ + (((~UL(0)) - (UL(1) << (l)) + 1) & \ + (~UL(0) >> (BITS_PER_LONG - 1 - (h)))) + +#define GENMASK_ULL(h, l) \ + (((~ULL(0)) - (ULL(1) << (l)) + 1) & \ + (~ULL(0) >> (BITS_PER_LONG_LONG - 1 - (h)))) + +#endif /* __LINUX_BITS_H */ diff --git a/include/linux/bsearch.h b/include/linux/bsearch.h new file mode 100644 index 0000000000..26f6bd1f70 --- /dev/null +++ b/include/linux/bsearch.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_BSEARCH_H +#define _LINUX_BSEARCH_H + +#include <linux/compiler.h> +#include <linux/types.h> + +static __always_inline +void *__inline_bsearch(const void *key, const void *base, size_t num, size_t size, cmp_func_t cmp) +{ + const char *pivot; + int result; + + while (num > 0) { + pivot = base + (num >> 1) * size; + result = cmp(key, pivot); + + if (result == 0) + return (void *)pivot; + + if (result > 0) { + base = pivot + size; + num--; + } + num >>= 1; + } + + return NULL; +} + +extern void *bsearch(const void *key, const void *base, size_t num, size_t size, cmp_func_t cmp); + +#endif /* _LINUX_BSEARCH_H */ diff --git a/include/linux/bug.h b/include/linux/bug.h index 8367a11ec2..8ea5f8d1b2 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -1,7 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_BUG_H #define _LINUX_BUG_H #include <asm-generic/bug.h> #include <linux/build_bug.h> +/* + * Since detected data corruption should stop operation on the affected + * structures. Return value must be checked and sanely acted on by caller. + */ +static inline __must_check bool check_data_corruption(bool v) { return v; } +#define CHECK_DATA_CORRUPTION(condition, fmt, ...) \ + check_data_corruption(({ \ + bool corruption = unlikely(condition); \ + if (corruption) { \ + if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \ + panic(fmt, ##__VA_ARGS__); \ + } else \ + WARN(1, fmt, ##__VA_ARGS__); \ + } \ + corruption; \ + })) + #endif /* _LINUX_BUG_H */ diff --git a/include/linux/byteorder/big_endian.h b/include/linux/byteorder/big_endian.h index 539f710a39..ba07edf0ae 100644 --- a/include/linux/byteorder/big_endian.h +++ b/include/linux/byteorder/big_endian.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_BYTEORDER_BIG_ENDIAN_H #define _LINUX_BYTEORDER_BIG_ENDIAN_H diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h index e59ba455e3..d5252959d8 100644 --- a/include/linux/byteorder/generic.h +++ b/include/linux/byteorder/generic.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_BYTEORDER_GENERIC_H #define _LINUX_BYTEORDER_GENERIC_H diff --git a/include/linux/byteorder/little_endian.h b/include/linux/byteorder/little_endian.h index dfe9531fba..e23111d4cd 100644 --- a/include/linux/byteorder/little_endian.h +++ b/include/linux/byteorder/little_endian.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_BYTEORDER_LITTLE_ENDIAN_H #define _LINUX_BYTEORDER_LITTLE_ENDIAN_H diff --git a/include/linux/circ_buf.h b/include/linux/circ_buf.h index 90f2471dc6..36b3be9c14 100644 --- a/include/linux/circ_buf.h +++ b/include/linux/circ_buf.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * See Documentation/circular-buffers.txt for more information. */ diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h new file mode 100644 index 0000000000..eab8305821 --- /dev/null +++ b/include/linux/clk-provider.h @@ -0,0 +1,185 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2010-2011 Jeremy Kerr <jeremy.kerr@canonical.com> + * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org> + */ +#ifndef __LINUX_CLK_PROVIDER_H +#define __LINUX_CLK_PROVIDER_H + +#include <linux/clk.h> + +long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, + u8 width, unsigned long flags); + +long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent, + unsigned long rate, unsigned long *prate, + const struct clk_div_table *table, u8 width, + unsigned long flags, unsigned int val); + +static inline long divider_ro_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate, + const struct clk_div_table *table, + u8 width, unsigned long flags, + unsigned int val) +{ + return divider_ro_round_rate_parent(hw, clk_hw_get_parent(hw), + rate, prate, table, width, flags, + val); +} + +/** + * struct clk_rate_request - Structure encoding the clk constraints that + * a clock user might require. + * + * Should be initialized by calling clk_hw_init_rate_request(). + * + * @core: Pointer to the struct clk_core affected by this request + * @rate: Requested clock rate. This field will be adjusted by + * clock drivers according to hardware capabilities. + * @min_rate: Minimum rate imposed by clk users. + * @max_rate: Maximum rate imposed by clk users. + * @best_parent_rate: The best parent rate a parent can provide to fulfill the + * requested constraints. + * @best_parent_hw: The most appropriate parent clock that fulfills the + * requested constraints. + * + */ +struct clk_rate_request { + struct clk_core *core; + unsigned long rate; + unsigned long min_rate; + unsigned long max_rate; + unsigned long best_parent_rate; + struct clk_hw *best_parent_hw; +}; + +#define CLK_HW_INIT(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = (const char *[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_HW(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_hws = (const struct clk_hw*[]) { _parent }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +/* + * This macro is intended for drivers to be able to share the otherwise + * individual struct clk_hw[] compound literals created by the compiler + * when using CLK_HW_INIT_HW. It does NOT support multiple parents. + */ +#define CLK_HW_INIT_HWS(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_hws = _parent, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_FW_NAME(_name, _parent, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_data = (const struct clk_parent_data[]) { \ + { .fw_name = _parent }, \ + }, \ + .num_parents = 1, \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS_HW(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_hws = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_PARENTS_DATA(_name, _parents, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_data = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .ops = _ops, \ + }) + +#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags) \ + (&(struct clk_init_data) { \ + .flags = _flags, \ + .name = _name, \ + .parent_names = NULL, \ + .num_parents = 0, \ + .ops = _ops, \ + }) + +#define CLK_FIXED_FACTOR(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#define CLK_FIXED_FACTOR_HW(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT_HW(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +/* + * This macro allows the driver to reuse the _parent array for multiple + * fixed factor clk declarations. + */ +#define CLK_FIXED_FACTOR_HWS(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT_HWS(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#define CLK_FIXED_FACTOR_FW_NAME(_struct, _name, _parent, \ + _div, _mult, _flags) \ + struct clk_fixed_factor _struct = { \ + .div = _div, \ + .mult = _mult, \ + .hw.init = CLK_HW_INIT_FW_NAME(_name, \ + _parent, \ + &clk_fixed_factor_ops, \ + _flags), \ + } + +#endif diff --git a/include/linux/clk.h b/include/linux/clk.h index 6565429a9b..7ba0679d03 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -13,8 +13,11 @@ #include <linux/err.h> #include <linux/spinlock.h> #include <linux/stringify.h> +#include <linux/container_of.h> +#include <deep-probe.h> +#include <xfuncs.h> -struct device_d; +struct device; /* * The base API. @@ -59,64 +62,7 @@ struct clk_bulk_data { * * clk_get should not be called from within interrupt context. */ -struct clk *clk_get(struct device_d *dev, const char *id); - -/** - * clk_bulk_get - lookup and obtain a number of references to clock producer. - * @dev: device for clock "consumer" - * @num_clks: the number of clk_bulk_data - * @clks: the clk_bulk_data table of consumer - * - * This helper function allows drivers to get several clk consumers in one - * operation. If any of the clk cannot be acquired then any clks - * that were obtained will be freed before returning to the caller. - * - * Returns 0 if all clocks specified in clk_bulk_data table are obtained - * successfully, or valid IS_ERR() condition containing errno. - * The implementation uses @dev and @clk_bulk_data.id to determine the - * clock consumer, and thereby the clock producer. - * The clock returned is stored in each @clk_bulk_data.clk field. - * - * Drivers must assume that the clock source is not enabled. - * - * clk_bulk_get should not be called from within interrupt context. - */ -int __must_check clk_bulk_get(struct device_d *dev, int num_clks, - struct clk_bulk_data *clks); - -/** - * clk_bulk_get_optional - lookup and obtain a number of references to clock producer - * @dev: device for clock "consumer" - * @num_clks: the number of clk_bulk_data - * @clks: the clk_bulk_data table of consumer - * - * Behaves the same as clk_bulk_get() except where there is no clock producer. - * In this case, instead of returning -ENOENT, the function returns 0 and - * NULL for a clk for which a clock producer could not be determined. - */ -int __must_check clk_bulk_get_optional(struct device_d *dev, int num_clks, - struct clk_bulk_data *clks); - -/** - * clk_bulk_get_all - lookup and obtain all available references to clock - * producer. - * @dev: device for clock "consumer" - * @clks: pointer to the clk_bulk_data table of consumer - * - * This helper function allows drivers to get all clk consumers in one - * operation. If any of the clk cannot be acquired then any clks - * that were obtained will be freed before returning to the caller. - * - * Returns a positive value for the number of clocks obtained while the - * clock references are stored in the clk_bulk_data table in @clks field. - * Returns 0 if there're none and a negative value if something failed. - * - * Drivers must assume that the clock source is not enabled. - * - * clk_bulk_get should not be called from within interrupt context. - */ -int __must_check clk_bulk_get_all(struct device_d *dev, - struct clk_bulk_data **clks); +struct clk *clk_get(struct device *dev, const char *id); /** * clk_enable - inform the system when the clock source should be running. @@ -129,18 +75,6 @@ int __must_check clk_bulk_get_all(struct device_d *dev, int clk_enable(struct clk *clk); /** - * clk_bulk_enable - inform the system when the set of clks should be running. - * @num_clks: the number of clk_bulk_data - * @clks: the clk_bulk_data table of consumer - * - * May be called from atomic contexts. - * - * Returns success (0) or negative errno. - */ -int __must_check clk_bulk_enable(int num_clks, - const struct clk_bulk_data *clks); - -/** * clk_disable - inform the system when the clock source is no longer required. * @clk: clock source * @@ -155,24 +89,6 @@ int __must_check clk_bulk_enable(int num_clks, void clk_disable(struct clk *clk); /** - * clk_bulk_disable - inform the system when the set of clks is no - * longer required. - * @num_clks: the number of clk_bulk_data - * @clks: the clk_bulk_data table of consumer - * - * Inform the system that a set of clks is no longer required by - * a driver and may be shut down. - * - * May be called from atomic contexts. - * - * Implementation detail: if the set of clks is shared between - * multiple drivers, clk_bulk_enable() calls must be balanced by the - * same number of clk_bulk_disable() calls for the clock source to be - * disabled. - */ -void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks); - -/** * clk_get_rate - obtain the current clock rate (in Hz) for a clock source. * This is only valid once the clock source has been enabled. * @clk: clock source @@ -180,32 +96,6 @@ void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks); unsigned long clk_get_rate(struct clk *clk); unsigned long clk_hw_get_rate(struct clk_hw *hw); -/** - * clk_bulk_put - "free" the clock source - * @num_clks: the number of clk_bulk_data - * @clks: the clk_bulk_data table of consumer - * - * Note: drivers must ensure that all clk_bulk_enable calls made on this - * clock source are balanced by clk_bulk_disable calls prior to calling - * this function. - * - * clk_bulk_put should not be called from within interrupt context. - */ -void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); - -/** - * clk_bulk_put_all - "free" all the clock source - * @num_clks: the number of clk_bulk_data - * @clks: the clk_bulk_data table of consumer - * - * Note: drivers must ensure that all clk_bulk_enable calls made on this - * clock source are balanced by clk_bulk_disable calls prior to calling - * this function. - * - * clk_bulk_put_all should not be called from within interrupt context. - */ -void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks); - /* * The remaining APIs are optional for machine class support. */ @@ -239,6 +129,7 @@ int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate); */ int clk_set_parent(struct clk *clk, struct clk *parent); int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp); +struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, unsigned int idx); /** * clk_get_parent - get the parent clock source for this clock @@ -249,6 +140,7 @@ int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *hwp); */ struct clk *clk_get_parent(struct clk *clk); struct clk_hw *clk_hw_get_parent(struct clk_hw *hw); +int clk_hw_get_parent_index(struct clk_hw *hw); int clk_set_phase(struct clk *clk, int degrees); int clk_get_phase(struct clk *clk); @@ -281,55 +173,34 @@ struct clk *clk_get_sys(const char *dev_id, const char *con_id); * Assumes clkdev, see clkdev.h for more info. */ int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, - struct device_d *dev); + struct device *dev); #else -static inline struct clk *clk_get(struct device_d *dev, const char *id) +static inline struct clk *clk_get(struct device *dev, const char *id) { return NULL; } -static inline int __must_check clk_bulk_get(struct device_d *dev, int num_clks, - struct clk_bulk_data *clks) -{ - return 0; -} - -static inline int __must_check clk_bulk_get_optional(struct device_d *dev, - int num_clks, - struct clk_bulk_data *clks) +static inline struct clk *clk_get_parent(struct clk *clk) { - return 0; + return NULL; } -static inline int __must_check clk_bulk_get_all(struct device_d *dev, - struct clk_bulk_data **clks) +static inline int clk_hw_get_parent_index(struct clk_hw *hw) { - return 0; + return -EINVAL; } -static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} - -static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {} - static inline int clk_enable(struct clk *clk) { return 0; } -static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks) -{ - return 0; -} - static inline void clk_disable(struct clk *clk) { } -static inline void clk_bulk_disable(int num_clks, - struct clk_bulk_data *clks) {} - static inline unsigned long clk_get_rate(struct clk *clk) { return 0; @@ -346,6 +217,9 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate) } #endif +#define clk_prepare_enable(clk) clk_enable(clk) +#define clk_disable_unprepare(clk) clk_disable(clk) + static inline void clk_put(struct clk *clk) { } @@ -366,6 +240,76 @@ static inline void clk_put(struct clk *clk) #define CLK_GATE_SET_TO_DISABLE (1 << 0) #define CLK_GATE_HIWORD_MASK (1 << 1) +/* Ignored sanity checking flags */ +#define CLK_SET_RATE_GATE 0 /* must be gated across rate change */ +#define CLK_SET_PARENT_GATE 0 /* must be gated across re-parent */ + + +/** + * struct clk_ops - Callback operations for hardware clocks; these are to + * be provided by the clock implementation, and will be called by drivers + * through the clk_* api. + * + * @init: Perform platform-specific initialization magic. + * This is not used by any of the basic clock types. + * This callback exist for HW which needs to perform some + * initialisation magic for CCF to get an accurate view of the + * clock. It may also be used dynamic resource allocation is + * required. It shall not used to deal with clock parameters, + * such as rate or parents. + * Returns 0 on success, -EERROR otherwise. + * + * @enable: Prepare and enable the clock atomically. This must not return + * until the clock is generating a valid clock signal, usable by + * consumer devices. + * + * @disable: Unprepare and disable the clock atomically. + * + * @is_enabled: Queries the hardware to determine if the clock is enabled. + * Optional, if this op is not set then the enable count will be + * used. + * + * @recalc_rate Recalculate the rate of this clock, by querying hardware. The + * parent rate is an input parameter. If the driver cannot figure + * out a rate for this clock, it must return 0. Returns the + * calculated rate. Optional, but recommended - if this op is not + * set then clock rate will be initialized to 0. + * + * @round_rate: Given a target rate as input, returns the closest rate actually + * supported by the clock. The parent rate is an input/output + * parameter. + * + * @set_parent: Change the input source of this clock; for clocks with multiple + * possible parents specify a new parent by passing in the index + * as a u8 corresponding to the parent in either the .parent_names + * or .parents arrays. This function in affect translates an + * array index into the value programmed into the hardware. + * Returns 0 on success, -EERROR otherwise. + * + * @get_parent: Queries the hardware to determine the parent of a clock. The + * return value is a u8 which specifies the index corresponding to + * the parent clock. This index can be applied to either the + * .parent_names or .parents arrays. In short, this function + * translates the parent value read from hardware into an array + * index. + * + * @set_rate: Change the rate of this clock. The requested rate is specified + * by the second argument, which should typically be the return + * of .round_rate call. The third argument gives the parent rate + * which is likely helpful for most .set_rate implementation. + * Returns 0 on success, -EERROR otherwise. + * + * @set_phase: Shift the phase this clock signal in degrees specified + * by the second argument. Valid values for degrees are + * 0-359. Return 0 on success, otherwise -EERROR. + * + * @get_phase: Queries the hardware to get the current phase of a clock. + * Returned values are 0-359 degrees on success, negative + * error codes on failure. + * + * Unlike Linux, there is no differentiation between clk_prepare/clk_enable + * and clk_unprepare/clk_disable in barebox as all work is atomic. + */ struct clk_ops { int (*init)(struct clk_hw *hw); int (*enable)(struct clk_hw *hw); @@ -390,6 +334,8 @@ struct clk_ops { * @name: clock name * @ops: operations this clock supports * @parent_names: array of string names for all possible parents + * @parent_hws: array of pointers to all possible parents (when all parents + * are internal to the clk controller) * @num_parents: number of possible parents * @flags: framework-level hints and quirks */ @@ -397,6 +343,7 @@ struct clk_init_data { const char *name; const struct clk_ops *ops; const char * const *parent_names; + const struct clk_hw **parent_hws; unsigned int num_parents; unsigned long flags; }; @@ -430,15 +377,16 @@ struct clk_hw { const struct clk_init_data *init; }; -static inline struct clk *clk_hw_to_clk(struct clk_hw *hw) +static inline struct clk *clk_hw_to_clk(const struct clk_hw *hw) { - return &hw->clk; + return IS_ERR(hw) ? ERR_CAST(hw) : (struct clk *)&hw->clk; } -static inline struct clk_hw *clk_to_clk_hw(struct clk *clk) +static inline struct clk_hw *clk_to_clk_hw(const struct clk *clk) { - return container_of(clk, struct clk_hw, clk); + return container_of_safe(clk, struct clk_hw, clk); } +#define __clk_get_hw(clk) clk_to_clk_hw(clk) struct clk_div_table { unsigned int val; @@ -449,6 +397,12 @@ struct clk *clk_register_fixed_rate(const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate); +struct clk_hw *clk_hw_register_fixed_rate(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + unsigned long rate); + static inline struct clk *clk_fixed(const char *name, int rate) { return clk_register_fixed_rate(name, NULL, 0, rate); @@ -473,6 +427,7 @@ struct clk_divider { #define clk_div_mask(width) ((1 << (width)) - 1) #define CLK_DIVIDER_POWER_OF_TWO (1 << 1) +#define CLK_DIVIDER_ALLOW_ZERO (1 << 2) #define CLK_DIVIDER_HIWORD_MASK (1 << 3) #define CLK_DIVIDER_READ_ONLY (1 << 5) @@ -482,6 +437,16 @@ struct clk_divider { extern const struct clk_ops clk_divider_ops; extern const struct clk_ops clk_divider_ro_ops; +static inline void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent) +{ + /* clk_get_parent always reads from HW, so nothing to update here */ +} + +static inline int __clk_get_enable_count(struct clk *clk) +{ + return !clk ? 0 : clk->enable_count; +} + unsigned long divider_recalc_rate(struct clk *clk, unsigned long parent_rate, unsigned int val, const struct clk_div_table *table, @@ -502,10 +467,10 @@ void clk_divider_free(struct clk *clk_divider); struct clk *clk_divider(const char *name, const char *parent, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, unsigned div_flags); -struct clk *clk_register_divider(struct device_d *dev, const char *name, - const char *parent_name, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, spinlock_t *lock); +struct clk *clk_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, spinlock_t *lock); struct clk *clk_divider_one_based(const char *name, const char *parent, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, unsigned div_flags); @@ -513,11 +478,29 @@ struct clk *clk_divider_table(const char *name, const char *parent, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, const struct clk_div_table *table, unsigned div_flags); -struct clk *clk_register_divider_table(struct device_d *dev, const char *name, - const char *parent_name, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, const struct clk_div_table *table, - spinlock_t *lock); +struct clk *clk_register_divider_table(struct device *dev, const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, + const struct clk_div_table *table, + spinlock_t *lock); + +struct clk_hw *clk_hw_register_divider_table(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 shift, + u8 width, + u8 clk_divider_flags, + const struct clk_div_table *table, + spinlock_t *lock); + +struct clk_hw *clk_hw_register_divider(struct device *dev, const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags, spinlock_t *lock); struct clk_fixed_factor { struct clk_hw hw; @@ -536,9 +519,17 @@ extern struct clk_ops clk_fixed_factor_ops; struct clk *clk_fixed_factor(const char *name, const char *parent, unsigned int mult, unsigned int div, unsigned flags); -struct clk *clk_register_fixed_factor(struct device_d *dev, const char *name, - const char *parent_name, unsigned long flags, - unsigned int mult, unsigned int div); +struct clk *clk_register_fixed_factor(struct device *dev, const char *name, + const char *parent_name, + unsigned long flags, + unsigned int mult, unsigned int div); + +struct clk_hw *clk_hw_register_fixed_factor(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + unsigned int mult, + unsigned int div); /** * struct clk_fractional_divider - adjustable fractional divider clock @@ -600,6 +591,7 @@ struct clk_mux { int shift; int width; unsigned flags; + u32 *table; spinlock_t *lock; }; @@ -616,11 +608,42 @@ void clk_mux_free(struct clk *clk_mux); struct clk *clk_mux(const char *name, unsigned clk_flags, void __iomem *reg, u8 shift, u8 width, const char * const *parents, u8 num_parents, unsigned mux_flags); -struct clk *clk_register_mux(struct device_d *dev, const char *name, - const char * const *parent_names, u8 num_parents, - unsigned long flags, - void __iomem *reg, u8 shift, u8 width, - u8 clk_mux_flags, spinlock_t *lock); +struct clk *clk_register_mux(struct device *dev, const char *name, + const char * const *parent_names, u8 num_parents, + unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_mux_flags, spinlock_t *lock); + +struct clk_hw *__clk_hw_register_mux(struct device *dev, + const char *name, u8 num_parents, + const char * const *parent_names, + unsigned long flags, void __iomem *reg, + u8 shift, u32 mask, + u8 clk_mux_flags, u32 *table, + spinlock_t *lock); + +#define clk_hw_register_mux(dev, name, parent_names, \ + num_parents, flags, reg, shift, mask, \ + clk_mux_flags, lock) \ + __clk_hw_register_mux((dev), (name), (num_parents), \ + (parent_names), \ + (flags), (reg), (shift), (mask), \ + (clk_mux_flags), NULL, (lock)) + +#define clk_hw_register_mux_table(dev, name, parent_names, num_parents, \ + flags, reg, shift, mask, clk_mux_flags, \ + table, lock) \ + __clk_hw_register_mux((dev), (name), (num_parents), \ + (parent_names), (flags), (reg), \ + (shift), (mask), (clk_mux_flags), (table), \ + (lock)) + +int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags, + unsigned int val); +unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index); + +long clk_mux_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate); struct clk_gate { struct clk_hw hw; @@ -647,10 +670,24 @@ struct clk *clk_gate_inverted(const char *name, const char *parent, void __iomem u8 shift, unsigned flags); struct clk *clk_gate_shared(const char *name, const char *parent, const char *shared, unsigned flags); -struct clk *clk_register_gate(struct device_d *dev, const char *name, - const char *parent_name, unsigned long flags, - void __iomem *reg, u8 bit_idx, - u8 clk_gate_flags, spinlock_t *lock); +struct clk *clk_register_gate(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 bit_idx, + u8 clk_gate_flags, spinlock_t *lock); + +static inline struct clk_hw *clk_hw_register_gate(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *reg, + u8 bit_idx, + u8 clk_gate_flags, + spinlock_t *lock) +{ + return clk_to_clk_hw(clk_register_gate(dev, xstrdup(name), xstrdup(parent_name), + flags, reg, bit_idx, + clk_gate_flags, lock)); +} int clk_is_enabled(struct clk *clk); int clk_hw_is_enabled(struct clk_hw *hw); @@ -662,7 +699,12 @@ int clk_parent_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate); int bclk_register(struct clk *clk); -struct clk *clk_register(struct device_d *dev, struct clk_hw *hw); +struct clk *clk_register(struct device *dev, struct clk_hw *hw); + +static inline int clk_hw_register(struct device *dev, struct clk_hw *hw) +{ + return PTR_ERR_OR_ZERO(clk_register(dev, hw)); +} struct clk *clk_lookup(const char *name); @@ -676,11 +718,33 @@ struct clk *clk_register_composite(const char *name, struct clk *gate_clk, unsigned long flags); +struct clk_hw *clk_hw_register_composite(struct device *dev, + const char *name, + const char * const *parent_names, + int num_parents, + struct clk_hw *mux_hw, + const struct clk_ops *mux_ops, + struct clk_hw *rate_hw, + const struct clk_ops *rate_ops, + struct clk_hw *gate_hw, + const struct clk_ops *gate_ops, + unsigned long flags); + static inline const char *clk_hw_get_name(struct clk_hw *hw) { return hw->clk.name; } +static inline unsigned int clk_hw_get_num_parents(const struct clk_hw *hw) +{ + return hw->clk.num_parents; +} + +static inline unsigned long clk_hw_get_flags(const struct clk_hw *hw) +{ + return hw->clk.flags; +} + int clk_name_set_parent(const char *clkname, const char *clkparentname); int clk_name_set_rate(const char *clkname, unsigned long rate); @@ -695,11 +759,16 @@ struct clk_onecell_data { unsigned int clk_num; }; +struct clk_hw_onecell_data { + unsigned int num; + struct clk_hw *hws[]; +}; + #if defined(CONFIG_COMMON_CLK_OF_PROVIDER) #define CLK_OF_DECLARE(name, compat, fn) \ const struct of_device_id __clk_of_table_##name \ -__attribute__ ((unused,section (".__clk_of_table"))) \ + __ll_elem(.__clk_of_table) \ = { .compatible = compat, .data = fn } void of_clk_del_provider(struct device_node *np); @@ -708,6 +777,8 @@ typedef int (*of_clk_init_cb_t)(struct device_node *); struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data); struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data); +struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data); +struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data); struct clk *of_clk_get(struct device_node *np, int index); struct clk *of_clk_get_by_name(struct device_node *np, const char *name); @@ -715,16 +786,16 @@ struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec); unsigned int of_clk_get_parent_count(struct device_node *np); int of_clk_parent_fill(struct device_node *np, const char **parents, unsigned int size); -int of_clk_init(struct device_node *root, const struct of_device_id *matches); +int of_clk_init(void); int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args *args, void *data), void *data); -static inline unsigned int clk_get_num_parents(const struct clk *hw) -{ - return hw->num_parents; -} +int of_clk_add_hw_provider(struct device_node *np, + struct clk_hw *(*clk_hw_src_get)(struct of_phandle_args *clkspec, + void *data), + void *data); #else @@ -743,11 +814,21 @@ static inline struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec { return ERR_PTR(-ENOENT); } +static inline struct clk_hw *of_clk_hw_onecell_get(struct of_phandle_args *clkspec, + void *data) +{ + return ERR_PTR(-ENOENT); +} static inline struct clk * of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data) { return ERR_PTR(-ENOENT); } +static inline struct clk_hw * +of_clk_hw_simple_get(struct of_phandle_args *clkspec, void *data) +{ + return ERR_PTR(-ENOENT); +} static inline struct clk *of_clk_get(struct device_node *np, int index) { return ERR_PTR(-ENOENT); @@ -761,8 +842,8 @@ static inline unsigned int of_clk_get_parent_count(struct device_node *np) { return 0; } -static inline int of_clk_init(struct device_node *root, - const struct of_device_id *matches) + +static inline int of_clk_init(void) { return 0; } @@ -773,6 +854,14 @@ static inline int of_clk_add_provider(struct device_node *np, { return 0; } + +static inline int of_clk_add_hw_provider(struct device_node *np, + struct clk_hw *(*clk_hw_src_get)(struct of_phandle_args *clkspec, + void *data), + void *data) +{ + return 0; +} #endif #define CLK_OF_DECLARE_DRIVER(name, compat, fn) CLK_OF_DECLARE(name, compat, fn) @@ -787,4 +876,278 @@ static inline void clk_unregister(struct clk *clk) { } +static inline void clk_hw_unregister(struct clk_hw *hw) +{ +} + +#ifdef CONFIG_COMMON_CLK + +/** + * clk_bulk_get - lookup and obtain a number of references to clock producer. + * @dev: device for clock "consumer" + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * This helper function allows drivers to get several clk consumers in one + * operation. If any of the clk cannot be acquired then any clks + * that were obtained will be freed before returning to the caller. + * + * Returns 0 if all clocks specified in clk_bulk_data table are obtained + * successfully, or valid IS_ERR() condition containing errno. + * The implementation uses @dev and @clk_bulk_data.id to determine the + * clock consumer, and thereby the clock producer. + * The clock returned is stored in each @clk_bulk_data.clk field. + * + * Drivers must assume that the clock source is not enabled. + * + * clk_bulk_get should not be called from within interrupt context. + */ +int __must_check clk_bulk_get(struct device *dev, int num_clks, + struct clk_bulk_data *clks); + +/** + * clk_bulk_get_optional - lookup and obtain a number of references to clock producer + * @dev: device for clock "consumer" + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * Behaves the same as clk_bulk_get() except where there is no clock producer. + * In this case, instead of returning -ENOENT, the function returns 0 and + * NULL for a clk for which a clock producer could not be determined. + */ +int __must_check clk_bulk_get_optional(struct device *dev, int num_clks, + struct clk_bulk_data *clks); + +/** + * clk_bulk_get_all - lookup and obtain all available references to clock + * producer. + * @dev: device for clock "consumer" + * @clks: pointer to the clk_bulk_data table of consumer + * + * This helper function allows drivers to get all clk consumers in one + * operation. If any of the clk cannot be acquired then any clks + * that were obtained will be freed before returning to the caller. + * + * Returns a positive value for the number of clocks obtained while the + * clock references are stored in the clk_bulk_data table in @clks field. + * Returns 0 if there're none and a negative value if something failed. + * + * Drivers must assume that the clock source is not enabled. + * + * clk_bulk_get should not be called from within interrupt context. + */ +int __must_check clk_bulk_get_all(struct device *dev, + struct clk_bulk_data **clks); + +/** + * clk_bulk_put - "free" the clock source + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * Note: drivers must ensure that all clk_bulk_enable calls made on this + * clock source are balanced by clk_bulk_disable calls prior to calling + * this function. + * + * clk_bulk_put should not be called from within interrupt context. + */ +void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); + +/** + * clk_bulk_put_all - "free" all the clock source + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * Note: drivers must ensure that all clk_bulk_enable calls made on this + * clock source are balanced by clk_bulk_disable calls prior to calling + * this function. + * + * clk_bulk_put_all should not be called from within interrupt context. + */ +void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks); + +/** + * clk_bulk_enable - inform the system when the set of clks should be running. + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * May be called from atomic contexts. + * + * Returns success (0) or negative errno. + */ +int __must_check clk_bulk_enable(int num_clks, + const struct clk_bulk_data *clks); + +/** + * clk_bulk_disable - inform the system when the set of clks is no + * longer required. + * @num_clks: the number of clk_bulk_data + * @clks: the clk_bulk_data table of consumer + * + * Inform the system that a set of clks is no longer required by + * a driver and may be shut down. + * + * May be called from atomic contexts. + * + * Implementation detail: if the set of clks is shared between + * multiple drivers, clk_bulk_enable() calls must be balanced by the + * same number of clk_bulk_disable() calls for the clock source to be + * disabled. + */ +void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks); + +#else +static inline int __must_check clk_bulk_get(struct device *dev, int num_clks, + struct clk_bulk_data *clks) +{ + return 0; +} + +static inline int __must_check clk_bulk_get_optional(struct device *dev, + int num_clks, + struct clk_bulk_data *clks) +{ + return 0; +} + +static inline int __must_check clk_bulk_get_all(struct device *dev, + struct clk_bulk_data **clks) +{ + return 0; +} + +static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} + +static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {} + +static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks) +{ + return 0; +} + +static inline void clk_bulk_disable(int num_clks, + struct clk_bulk_data *clks) {} + +#endif + +/** + * clk_hw_register_fixed_rate_with_accuracy - register fixed-rate clock with + * the clock framework + * @dev: device that is registering this clock + * @name: name of this clock + * @parent_name: name of clock's parent + * @flags: framework-specific flags + * @fixed_rate: non-adjustable clock rate + * @fixed_accuracy: non-adjustable clock accuracy (ignored) + */ +#define clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, \ + flags, fixed_rate, \ + fixed_accuracy) \ + clk_hw_register_fixed_rate((dev), (name), (parent_name), (flags), (fixed_rate)) + +#define clk_bulk_prepare_enable clk_bulk_enable +#define clk_bulk_disable_unprepare clk_bulk_disable + +/** + * clk_get_optional - lookup and obtain a reference to an optional clock + * producer. + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Behaves the same as clk_get() except where there is no clock producer. In + * this case, instead of returning -ENOENT, the function returns NULL. + */ +static inline struct clk *clk_get_optional(struct device *dev, const char *id) +{ + struct clk *clk = clk_get(dev, id); + + if (clk == ERR_PTR(-ENOENT)) + return NULL; + + return clk; +} + +/** + * clk_get_enabled - clk_get() + clk_prepare_enable() + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. (IOW, @id may be identical strings, but + * clk_get may return different clock producers depending on @dev.) + * + * The returned clk (if valid) is enabled. + */ +static inline struct clk *clk_get_enabled(struct device *dev, const char *id) +{ + struct clk *clk; + int ret; + + clk = clk_get(dev, id); + if (IS_ERR(clk)) + return clk; + + ret = clk_enable(clk); + if (ret) { + clk_put(clk); + return ERR_PTR(ret); + } + + return clk; +} + +/** + * clk_get_optional_enabled - clk_get_optional() + + * clk_prepare_enable() + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Return: a struct clk corresponding to the clock producer, or + * valid IS_ERR() condition containing errno. The implementation + * uses @dev and @id to determine the clock consumer, and thereby + * the clock producer. If no such clk is found, it returns NULL + * which serves as a dummy clk. That's the only difference compared + * to clk_get_enabled(). + * + * The returned clk (if valid) is enabled. + */ +static inline struct clk *clk_get_optional_enabled(struct device *dev, const char *id) +{ + struct clk *clk; + int ret; + + clk = clk_get_optional(dev, id); + if (IS_ERR_OR_NULL(clk)) + return clk; + + ret = clk_enable(clk); + if (ret) { + clk_put(clk); + return ERR_PTR(ret); + } + + return clk; +} + +/** + * clk_get_if_available - get clock, ignoring known unavailable clock controller + * @dev: device for clock "consumer" + * @id: clock consumer ID + * + * Return: a struct clk corresponding to the clock producer, a + * valid IS_ERR() condition containing errno or NULL if it could + * be determined that the clock producer will never be probed in + * absence of modules. + */ +static inline struct clk *clk_get_if_available(struct device *dev, const char *id) +{ + struct clk *clk = clk_get(dev, id); + + if (clk == ERR_PTR(-EPROBE_DEFER) && deep_probe_is_supported()) + return NULL; + + return clk; +} + #endif diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h index 390437887b..7af499bdbe 100644 --- a/include/linux/clk/at91_pmc.h +++ b/include/linux/clk/at91_pmc.h @@ -12,6 +12,11 @@ #ifndef AT91_PMC_H #define AT91_PMC_H +#include <linux/bits.h> + +#define AT91_PMC_V1 (1) /* PMC version 1 */ +#define AT91_PMC_V2 (2) /* PMC version 2 [SAM9X60] */ + #define AT91_PMC_SCER 0x00 /* System Clock Enable Register */ #define AT91_PMC_SCDR 0x04 /* System Clock Disable Register */ @@ -30,16 +35,35 @@ #define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */ #define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */ +#define AT91_PMC_PLL_CTRL0 0x0C /* PLL Control Register 0 [for SAM9X60] */ +#define AT91_PMC_PLL_CTRL0_ENPLL (1 << 28) /* Enable PLL */ +#define AT91_PMC_PLL_CTRL0_ENPLLCK (1 << 29) /* Enable PLL clock for PMC */ +#define AT91_PMC_PLL_CTRL0_ENLOCK (1 << 31) /* Enable PLL lock */ + +#define AT91_PMC_PLL_CTRL1 0x10 /* PLL Control Register 1 [for SAM9X60] */ + #define AT91_PMC_PCER 0x10 /* Peripheral Clock Enable Register */ #define AT91_PMC_PCDR 0x14 /* Peripheral Clock Disable Register */ #define AT91_PMC_PCSR 0x18 /* Peripheral Clock Status Register */ +#define AT91_PMC_PLL_ACR 0x18 /* PLL Analog Control Register [for SAM9X60] */ +#define AT91_PMC_PLL_ACR_DEFAULT_UPLL UL(0x12020010) /* Default PLL ACR value for UPLL */ +#define AT91_PMC_PLL_ACR_DEFAULT_PLLA UL(0x00020010) /* Default PLL ACR value for PLLA */ +#define AT91_PMC_PLL_ACR_UTMIVR (1 << 12) /* UPLL Voltage regulator Control */ +#define AT91_PMC_PLL_ACR_UTMIBG (1 << 13) /* UPLL Bandgap Control */ + #define AT91_CKGR_UCKR 0x1C /* UTMI Clock Register [some SAM9] */ #define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */ #define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */ #define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */ #define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */ +#define AT91_PMC_PLL_UPDT 0x1C /* PMC PLL update register [for SAM9X60] */ +#define AT91_PMC_PLL_UPDT_UPDATE (1 << 8) /* Update PLL settings */ +#define AT91_PMC_PLL_UPDT_ID (1 << 0) /* PLL ID */ +#define AT91_PMC_PLL_UPDT_ID_MSK (0xf) /* PLL ID mask */ +#define AT91_PMC_PLL_UPDT_STUPTIM (0xff << 16) /* Startup time */ + #define AT91_CKGR_MOR 0x20 /* Main Oscillator Register [not on SAM9RL] */ #define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */ #define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass */ @@ -56,6 +80,10 @@ #define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */ #define AT91_CKGR_PLLAR 0x28 /* PLL A Register */ + +#define AT91_PMC_RATIO 0x2c /* Processor clock ratio register [SAMA7G5 only] */ +#define AT91_PMC_RATIO_RATIO (0xf) /* CPU clock ratio. */ + #define AT91_CKGR_PLLBR 0x2c /* PLL B Register */ #define AT91_PMC_DIV (0xff << 0) /* Divider */ #define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */ @@ -115,6 +143,34 @@ #define AT91_PMC_PLLADIV2_ON (1 << 12) #define AT91_PMC_H32MXDIV BIT(24) +#define AT91_PMC_MCR_V2 0x30 /* Master Clock Register [SAMA7G5 only] */ +#define AT91_PMC_MCR_V2_ID_MSK (0xF) +#define AT91_PMC_MCR_V2_ID(_id) ((_id) & AT91_PMC_MCR_V2_ID_MSK) +#define AT91_PMC_MCR_V2_CMD (1 << 7) +#define AT91_PMC_MCR_V2_DIV (7 << 8) +#define AT91_PMC_MCR_V2_DIV1 (0 << 8) +#define AT91_PMC_MCR_V2_DIV2 (1 << 8) +#define AT91_PMC_MCR_V2_DIV4 (2 << 8) +#define AT91_PMC_MCR_V2_DIV8 (3 << 8) +#define AT91_PMC_MCR_V2_DIV16 (4 << 8) +#define AT91_PMC_MCR_V2_DIV32 (5 << 8) +#define AT91_PMC_MCR_V2_DIV64 (6 << 8) +#define AT91_PMC_MCR_V2_DIV3 (7 << 8) +#define AT91_PMC_MCR_V2_CSS (0x1F << 16) +#define AT91_PMC_MCR_V2_CSS_MD_SLCK (0 << 16) +#define AT91_PMC_MCR_V2_CSS_TD_SLCK (1 << 16) +#define AT91_PMC_MCR_V2_CSS_MAINCK (2 << 16) +#define AT91_PMC_MCR_V2_CSS_MCK0 (3 << 16) +#define AT91_PMC_MCR_V2_CSS_SYSPLL (5 << 16) +#define AT91_PMC_MCR_V2_CSS_DDRPLL (6 << 16) +#define AT91_PMC_MCR_V2_CSS_IMGPLL (7 << 16) +#define AT91_PMC_MCR_V2_CSS_BAUDPLL (8 << 16) +#define AT91_PMC_MCR_V2_CSS_AUDIOPLL (9 << 16) +#define AT91_PMC_MCR_V2_CSS_ETHPLL (10 << 16) +#define AT91_PMC_MCR_V2_EN (1 << 28) + +#define AT91_PMC_XTALF 0x34 /* Main XTAL Frequency Register [SAMA7G5 only] */ + #define AT91_PMC_USB 0x38 /* USB Clock Register [some SAM9 only] */ #define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */ #define AT91_PMC_USBS_PLLA (0 << 0) @@ -153,6 +209,7 @@ #define AT91_PMC_MOSCRCS (1 << 17) /* Main On-Chip RC [some SAM9] */ #define AT91_PMC_CFDEV (1 << 18) /* Clock Failure Detector Event [some SAM9] */ #define AT91_PMC_GCKRDY (1 << 24) /* Generated Clocks */ +#define AT91_PMC_MCKXRDY (1 << 26) /* Master Clock x [x=1..4] Ready Status */ #define AT91_PMC_IMR 0x6c /* Interrupt Mask Register */ #define AT91_PMC_FSMR 0x70 /* Fast Startup Mode Register */ @@ -180,6 +237,8 @@ #define AT91_PMC_WPVS (0x1 << 0) /* Write Protect Violation Status */ #define AT91_PMC_WPVSRC (0xffff << 8) /* Write Protect Violation Source */ +#define AT91_PMC_PLL_ISR0 0xEC /* PLL Interrupt Status Register 0 [SAM9X60 only] */ + #define AT91_PMC_PCER1 0x100 /* Peripheral Clock Enable Register 1 [SAMA5 only]*/ #define AT91_PMC_PCDR1 0x104 /* Peripheral Clock Enable Register 1 */ #define AT91_PMC_PCSR1 0x108 /* Peripheral Clock Enable Register 1 */ diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index eeadcfefa7..65edbd760b 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h @@ -13,7 +13,7 @@ #define __CLKDEV_H struct clk; -struct device_d; +struct device; struct clk_lookup { struct list_head node; @@ -30,7 +30,7 @@ void clkdev_add(struct clk_lookup *cl); void clkdev_drop(struct clk_lookup *cl); void clkdev_add_table(struct clk_lookup *, size_t); -int clk_add_alias(const char *, const char *, char *, struct device_d *); +int clk_add_alias(const char *, const char *, char *, struct device *); int clk_register_clkdev(struct clk *, const char *, const char *, ...); int clkdev_add_physbase(struct clk *clk, unsigned long base, const char *id); diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 4d36b27214..2534386d04 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -234,3 +234,11 @@ #else #define __diag_GCC_8(s) #endif + +/* + * Prior to 9.1, -Wno-alloc-size-larger-than (and therefore the "alloc_size" + * attribute) do not work, and must be disabled. + */ +#if GCC_VERSION < 90100 +#undef __alloc_size__ +#endif diff --git a/include/linux/compiler.h b/include/linux/compiler.h index f61a458414..6654c164f5 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -276,16 +276,6 @@ unsigned long read_word_at_a_time(const void *addr) #endif /* __KERNEL__ */ -/* - * Force the compiler to emit 'sym' as a symbol, so that we can reference - * it from inline assembler. Necessary in case 'sym' could be inlined - * otherwise, or eliminated entirely due to lack of references that are - * visible to the compiler. - */ -#define __ADDRESSABLE(sym) \ - static void * __attribute__((section(".discard.addressable"), used)) \ - __PASTE(__addressable_##sym, __LINE__) = (void *)&sym; - /** * offset_to_ptr - convert a relative memory offset to an absolute pointer * @off: the address of the 32-bit offset value diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index db192becfe..d925b3da29 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_COMPILER_TYPES_H #define __LINUX_COMPILER_TYPES_H @@ -54,6 +56,16 @@ extern void __chk_io_ptr(const volatile void __iomem *); #ifdef __KERNEL__ +/* + * Note: do not use this directly. Instead, use __alloc_size() since it is conditionally + * available and includes other attributes. For GCC < 9.1, __alloc_size__ gets undefined + * in compiler-gcc.h, due to misbehaviors. + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-alloc_005fsize-function-attribute + * clang: https://clang.llvm.org/docs/AttributeReference.html#alloc-size + */ +#define __alloc_size__(x, ...) __attribute__((__alloc_size__(x, ## __VA_ARGS__))) + /* Compiler specific macros. */ #ifdef __clang__ #include <linux/compiler-clang.h> @@ -110,6 +122,41 @@ struct ftrace_likely_data { #define __deprecated #define __deprecated_for_modules +#ifndef __has_attribute +#define __has_attribute(...) 0 +#endif + +/* + * Add the pseudo keyword 'fallthrough' so case statement blocks + * must end with any of these keywords: + * break; + * fallthrough; + * continue; + * goto <label>; + * return [expression]; + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html#Statement-Attributes + */ +#if __has_attribute(__fallthrough__) +# define fallthrough __attribute__((__fallthrough__)) +#else +# define fallthrough do {} while (0) /* fallthrough */ +#endif + +/* + * Optional: only supported since GCC >= 11.1, clang >= 7.0. + * + * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-no_005fstack_005fprotector-function-attribute + * clang: https://clang.llvm.org/docs/AttributeReference.html#no-stack-protector-safebuffers + */ +#if __has_attribute(__no_stack_protector__) +# define __no_stack_protector __attribute__((__no_stack_protector__)) +#elif ! defined CONFIG_STACKPROTECTOR +# define __no_stack_protector __attribute__((__optimize__("-fno-stack-protector"))) +#else +# define __no_stack_protector +#endif + #endif /* __KERNEL__ */ #endif /* __ASSEMBLY__ */ @@ -151,6 +198,20 @@ struct ftrace_likely_data { #define __assume_aligned(a, ...) #endif +/* + * Any place that could be marked with the "alloc_size" attribute is also + * a place to be marked with the "malloc" attribute, except those that may + * be performing a _reallocation_, as that may alias the existing pointer. + * For these, use __realloc_size(). + */ +#ifdef __alloc_size__ +# define __alloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__) __malloc +# define __realloc_size(x, ...) __alloc_size__(x, ## __VA_ARGS__) +#else +# define __alloc_size(x, ...) __malloc +# define __realloc_size(x, ...) +#endif + /* Are two types/vars the same type (ignoring qualifiers)? */ #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) @@ -199,8 +260,8 @@ struct ftrace_likely_data { #define __pure __attribute__((pure)) #define __aligned(x) __attribute__((aligned(x))) #define __aligned_largest __attribute__((aligned)) -#define __printf(a, b) __attribute__((format(printf, a, b))) -#define __scanf(a, b) __attribute__((format(scanf, a, b))) +#define __printf(a, b) __attribute__((format(__printf__, a, b))) +#define __scanf(a, b) __attribute__((format(__scanf__, a, b))) #define __maybe_unused __attribute__((unused)) #define __always_unused __attribute__((unused)) #define __mode(x) __attribute__((mode(x))) @@ -213,6 +274,12 @@ struct ftrace_likely_data { #define __cold __attribute__((cold)) #define __section(S) __attribute__((__section__(#S))) +#ifdef __clang__ +#define __ll_elem(S) __section(S) __used __no_sanitize_address +#else +#define __ll_elem(S) __section(S) __used +#endif + #ifdef CONFIG_ENABLE_MUST_CHECK #define __must_check __attribute__((warn_unused_result)) @@ -282,4 +349,11 @@ struct ftrace_likely_data { */ #define noinline_for_stack noinline +/* code that can't be instrumented at all */ +#define noinstr \ + noinline notrace __no_sanitize_address __no_stack_protector + +#define __prereloc \ + notrace __no_sanitize_address __no_stack_protector + #endif /* __LINUX_COMPILER_TYPES_H */ diff --git a/include/linux/const.h b/include/linux/const.h index c872bfd25e..77e4f6fd8a 100644 --- a/include/linux/const.h +++ b/include/linux/const.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* const.h: Macros for dealing with constants. */ #ifndef _LINUX_CONST_H @@ -21,7 +23,22 @@ #define _AT(T,X) ((T)(X)) #endif -#define _BITUL(x) (_AC(1,UL) << (x)) -#define _BITULL(x) (_AC(1,ULL) << (x)) +#define _UL(x) (_AC(x, UL)) +#define _ULL(x) (_AC(x, ULL)) + +#define _BITUL(x) (_UL(1) << (x)) +#define _BITULL(x) (_ULL(1) << (x)) + +#define UL(x) (_UL(x)) +#define ULL(x) (_ULL(x)) + + +/* + * This returns a constant expression while determining if an argument is + * a constant expression, most importantly without evaluating the argument. + * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de> + */ +#define __is_constexpr(x) \ + (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) #endif /* !(_LINUX_CONST_H) */ diff --git a/include/linux/container_of.h b/include/linux/container_of.h new file mode 100644 index 0000000000..2f4944b791 --- /dev/null +++ b/include/linux/container_of.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_CONTAINER_OF_H +#define _LINUX_CONTAINER_OF_H + +#include <linux/build_bug.h> +#include <linux/err.h> + +#define typeof_member(T, m) typeof(((T*)0)->m) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + void *__mptr = (void *)(ptr); \ + static_assert(__same_type(*(ptr), ((type *)0)->member) || \ + __same_type(*(ptr), void), \ + "pointer type mismatch in container_of()"); \ + ((type *)(__mptr - offsetof(type, member))); }) + +/** + * container_of_safe - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + * If IS_ERR_OR_NULL(ptr), ptr is returned unchanged. + */ +#define container_of_safe(ptr, type, member) ({ \ + void *__mptr = (void *)(ptr); \ + static_assert(__same_type(*(ptr), ((type *)0)->member) || \ + __same_type(*(ptr), void), \ + "pointer type mismatch in container_of_safe()"); \ + IS_ERR_OR_NULL(__mptr) ? ERR_CAST(__mptr) : \ + ((type *)(__mptr - offsetof(type, member))); }) + +#endif /* _LINUX_CONTAINER_OF_H */ diff --git a/include/linux/crc8.h b/include/linux/crc8.h index 13c8dabb04..8fcd6d1324 100644 --- a/include/linux/crc8.h +++ b/include/linux/crc8.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * Copyright (c) 2011 Broadcom Corporation * diff --git a/include/linux/ctype.h b/include/linux/ctype.h index 633c3862d8..ab9bf910d8 100644 --- a/include/linux/ctype.h +++ b/include/linux/ctype.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_CTYPE_H #define _LINUX_CTYPE_H diff --git a/include/linux/dcache.h b/include/linux/dcache.h index a961942201..ed7e5c2cbc 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_DCACHE_H #define __LINUX_DCACHE_H diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h index 81676ae906..1891a51368 100644 --- a/include/linux/decompress/mm.h +++ b/include/linux/decompress/mm.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * linux/compr_mm.h * @@ -64,8 +66,17 @@ static __maybe_unused void simple_free(void *where) #define MALLOC simple_malloc #define FREE simple_free -#define INIT +#else + +#define large_malloc(a) malloc(a) +#define large_free(a) free(a) #endif /* STATIC */ +#ifndef STATIC +#define STATIC +#endif + +#define INIT + #endif /* DECOMPR_MM_H */ diff --git a/include/linux/decompress/unlz4.h b/include/linux/decompress/unlz4.h index 7aaafc2b1c..fb6d499d1b 100644 --- a/include/linux/decompress/unlz4.h +++ b/include/linux/decompress/unlz4.h @@ -1,10 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef DECOMPRESS_UNLZ4_H #define DECOMPRESS_UNLZ4_H -int decompress_unlz4(unsigned char *inbuf, int len, - int(*fill)(void*, unsigned int), - int(*flush)(void*, unsigned int), +int decompress_unlz4(unsigned char *inbuf, long len, + long(*fill)(void*, unsigned long), + long(*flush)(void*, unsigned long), unsigned char *output, - int *pos, + long *pos, void(*error)(char *x)); #endif diff --git a/include/linux/decompress/unzstd.h b/include/linux/decompress/unzstd.h new file mode 100644 index 0000000000..56d539ae88 --- /dev/null +++ b/include/linux/decompress/unzstd.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LINUX_DECOMPRESS_UNZSTD_H +#define LINUX_DECOMPRESS_UNZSTD_H + +int unzstd(unsigned char *inbuf, long len, + long (*fill)(void*, unsigned long), + long (*flush)(void*, unsigned long), + unsigned char *output, + long *pos, + void (*error_fn)(char *x)); +#endif diff --git a/include/linux/device.h b/include/linux/device.h new file mode 100644 index 0000000000..d892a9cb0e --- /dev/null +++ b/include/linux/device.h @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LINUX_DRIVER_H_ +#define LINUX_DRIVER_H_ + +#include <driver.h> +#include <linux/slab.h> +#include <linux/bug.h> +#include <mmu.h> + +#define device_driver driver + +#define __devm_wrapper(fn, dev, ...) ({ BUG_ON(!dev); fn(__VA_ARGS__); }) + +#define devm_kmalloc(...) __devm_wrapper(kmalloc, __VA_ARGS__) +#define devm_krealloc(...) __devm_wrapper(krealloc, __VA_ARGS__) +#define devm_kvasprintf(...) __devm_wrapper(kvasprintf, __VA_ARGS__) +#define devm_kasprintf(...) __devm_wrapper(kasprintf, __VA_ARGS__) +#define devm_kzalloc(...) __devm_wrapper(kzalloc, __VA_ARGS__) +#define devm_kmalloc_array(...) __devm_wrapper(kmalloc_array, __VA_ARGS__) +#define devm_kcalloc(...) __devm_wrapper(kcalloc, __VA_ARGS__) +#define devm_krealloc_array(...) __devm_wrapper(krealloc_array, __VA_ARGS__) +#define devm_kfree(...) __devm_wrapper(kfree, __VA_ARGS__) +#define devm_kstrdup(...) __devm_wrapper(kstrdup, __VA_ARGS__) +#define devm_kstrdup_const(...) __devm_wrapper(kstrdup_const, __VA_ARGS__) +#define devm_kmemdup(...) __devm_wrapper(kmemdup, __VA_ARGS__) +#define devm_bitmap_zalloc(dev, nbits, gfp) \ + __devm_wrapper(bitmap_zalloc, dev, nbits) + +#define device_register register_device +#define device_unregister unregister_device + +#define driver_register register_driver +#define driver_unregister unregister_driver + + +static inline void __iomem *dev_platform_ioremap_resource(struct device *dev, + int resource) +{ + /* + * barebox maps everything outside the RAM banks suitably for MMIO, + * so we don't need to do anything besides requesting the regions + * and can leave the memory attributes unchanged. + */ + return dev_request_mem_region_err_null(dev, resource); +} + +static inline void __iomem *devm_ioremap(struct device *dev, + resource_size_t start, + resource_size_t size) +{ + if (start) + remap_range((void *)start, size, MAP_UNCACHED); + + return IOMEM(start); +} + +static inline int bus_for_each_dev(const struct bus_type *bus, struct device *start, void *data, + int (*fn)(struct device *dev, void *data)) +{ + struct device *dev; + int ret; + + bus_for_each_device(bus, dev) { + if (start) { + if (dev == start) + start = NULL; + continue; + } + + ret = fn(dev, data); + if (ret) + return ret; + } + + return 0; +} + +#endif diff --git a/include/linux/err.h b/include/linux/err.h index ed563f2c4a..d743b4d092 100644 --- a/include/linux/err.h +++ b/include/linux/err.h @@ -1,9 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_ERR_H #define _LINUX_ERR_H #include <linux/compiler.h> -#include <asm-generic/errno.h> +#include <linux/errno.h> /* * Kernel pointers have redundant information, so we can use a @@ -17,7 +19,7 @@ #ifndef __ASSEMBLY__ -#define IS_ERR_VALUE(x) unlikely((x) >= (unsigned long)-MAX_ERRNO) +#define IS_ERR_VALUE(x) unlikely((unsigned long)(void *)(x) >= (unsigned long)-MAX_ERRNO) static inline void *ERR_PTR(long error) { diff --git a/include/linux/errno.h b/include/linux/errno.h new file mode 100644 index 0000000000..b3bf44d249 --- /dev/null +++ b/include/linux/errno.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_ERRNO_H +#define _LINUX_ERRNO_H + +#include <asm-generic/errno.h> + + +/* + * These should never be seen by user programs. To return one of ERESTART* + * codes, signal_pending() MUST be set. Note that ptrace can observe these + * at syscall exit tracing, but they will never be left for the debugged user + * process to see. + */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ +#define ERESTART_RESTARTBLOCK 516 /* restart by calling sys_restart_syscall */ +#define EPROBE_DEFER 517 /* Driver requests probe retry */ +#define EOPENSTALE 518 /* open found a stale dentry */ +#define ENOPARAM 519 /* Parameter not supported */ + +/* Defined for the NFSv3 protocol */ +#define EBADHANDLE 521 /* Illegal NFS file handle */ +#define ENOTSYNC 522 /* Update synchronization mismatch */ +#define EBADCOOKIE 523 /* Cookie is stale */ +#define ENOTSUPP 524 /* Operation is not supported */ +#define ETOOSMALL 525 /* Buffer or request is too small */ +#define ESERVERFAULT 526 /* An untranslatable error occurred */ +#define EBADTYPE 527 /* Type not supported by server */ +#define EJUKEBOX 528 /* Request initiated, but will not complete before timeout */ +#define EIOCBQUEUED 529 /* iocb queued, will get completion event */ +#define ERECALLCONFLICT 530 /* conflict with recalled state */ +#define ENOGRACE 531 /* NFS file lock reclaim refused */ + +#endif diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 324e40cdeb..f47e17ea31 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * ethtool.h: Defines for Linux ethtool. * diff --git a/include/linux/export.h b/include/linux/export.h index 88d318bd8a..a136d727d1 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -2,9 +2,11 @@ #ifndef _LINUX_EXPORT_H #define _LINUX_EXPORT_H +#ifndef __ASSEMBLY__ + #define THIS_MODULE 0 -#ifdef CONFIG_MODULES +#if defined(CONFIG_MODULES) && !defined(__DISABLE_EXPORTS) struct kernel_symbol { @@ -13,21 +15,20 @@ struct kernel_symbol }; /* For every exported symbol, place a struct in the __ksymtab section */ -#define __EXPORT_SYMBOL(sym, sec) \ +#define __EXPORT_SYMBOL(sym) \ extern typeof(sym) sym; \ static const char __ustrtab_##sym[] \ - __attribute__((section("__usymtab_strings"))) \ + __ll_elem(__usymtab_strings) \ = MODULE_SYMBOL_PREFIX #sym; \ static const struct kernel_symbol __usymtab_##sym \ - __used \ - __attribute__((section("__usymtab" sec), unused)) \ + __ll_elem(__usymtab) \ = { (unsigned long)&sym, __ustrtab_##sym } #define EXPORT_SYMBOL(sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym) #define EXPORT_SYMBOL_GPL(sym) \ - __EXPORT_SYMBOL(sym, "") + __EXPORT_SYMBOL(sym) #else @@ -36,4 +37,6 @@ struct kernel_symbol #endif /* CONFIG_MODULES */ +#endif /* __ASSEMBLY__ */ + #endif /* _LINUX_EXPORT_H */ diff --git a/include/linux/font.h b/include/linux/font.h index feeab97191..5c4bcd151d 100644 --- a/include/linux/font.h +++ b/include/linux/font.h @@ -32,10 +32,10 @@ struct font_desc { extern int find_font_index(const struct font_desc *font, int ch); extern const struct font_desc *find_font_enum(int n); -extern struct param_d *add_param_font(struct device_d *dev, - int (*set)(struct param_d *p, void *priv), - int (*get)(struct param_d *p, void *priv), - int *value, void *priv); +extern struct param_d *add_param_font(struct device *dev, + int (*set)(struct param_d *p, void *priv), + int (*get)(struct param_d *p, void *priv), + int *value, void *priv); int font_register(struct font_desc *font); diff --git a/include/linux/fs.h b/include/linux/fs.h index a72bc066c3..fc1357137a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_FS_H #define _LINUX_FS_H diff --git a/include/linux/gcd.h b/include/linux/gcd.h index 0ac262162d..affb402f22 100644 --- a/include/linux/gcd.h +++ b/include/linux/gcd.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _GCD_H #define _GCD_H diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h new file mode 100644 index 0000000000..566e62d196 --- /dev/null +++ b/include/linux/genalloc.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Basic general purpose allocator for managing special purpose + * memory, for example, memory that is not managed by the regular + * kmalloc/kfree interface. Uses for this includes on-device special + * memory, uncached memory etc. + */ + + +#ifndef __GENALLOC_H__ +#define __GENALLOC_H__ + +#include <linux/types.h> + +struct device_node; + +struct gen_pool; + +extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); + +extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, + dma_addr_t *dma); + +extern void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma); + +#ifdef CONFIG_OFDEVICE +extern struct gen_pool *of_gen_pool_get(struct device_node *np, + const char *propname, int index); +#else +static inline struct gen_pool *of_gen_pool_get(struct device_node *np, + const char *propname, int index) +{ + return NULL; +} +#endif +#endif /* __GENALLOC_H__ */ diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h new file mode 100644 index 0000000000..531ed14725 --- /dev/null +++ b/include/linux/gpio/consumer.h @@ -0,0 +1,224 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_GPIO_CONSUMER_H +#define __LINUX_GPIO_CONSUMER_H + +#include <gpio.h> +#include <of_gpio.h> +#include <driver.h> +#include <linux/bug.h> +#include <linux/iopoll.h> + +/** + * Optional flags that can be passed to one of gpiod_* to configure direction + * and output value. These values cannot be OR'd. + */ +enum gpiod_flags { + GPIOD_ASIS = 0, + GPIOD_IN = GPIOF_IN, + /* + * To change this later to a different logic level (i.e. taking + * active low into account), use gpiod_set_value() + */ + GPIOD_OUT_LOW = GPIOF_OUT_INIT_INACTIVE, + GPIOD_OUT_HIGH = GPIOF_OUT_INIT_ACTIVE, +}; + +#define gpiod_not_found(desc) (IS_ERR(desc) && PTR_ERR(desc) == -ENOENT) + +struct gpio_desc; +struct gpio_array; + +/** + * struct gpio_descs - Struct containing an array of descriptors that can be + * obtained using gpiod_get_array() + * + * @info: Pointer to the opaque gpio_array structure + * @ndescs: Number of held descriptors + * @desc: Array of pointers to GPIO descriptors + */ +struct gpio_descs { + unsigned int ndescs; + /* info is used for fastpath, which we don't have in barebox. + * We define the member anyway, as not to change API + */ + struct gpio_array *info; + DECLARE_FLEX_ARRAY(struct gpio_desc *, desc); +}; + +#if defined(CONFIG_OFDEVICE) && defined(CONFIG_GPIOLIB) + +/* returned gpio descriptor can be passed to any normal gpio_* function */ +struct gpio_desc *dev_gpiod_get_index(struct device *dev, + struct device_node *np, + const char *_con_id, int index, + enum gpiod_flags flags, + const char *label); + +#else +static inline struct gpio_desc *dev_gpiod_get_index(struct device *dev, + struct device_node *np, + const char *_con_id, int index, + enum gpiod_flags flags, + const char *label) +{ + return ERR_PTR(-ENODEV); +} +#endif + +#ifdef CONFIG_GPIOLIB + +int gpiod_direction_input(struct gpio_desc *desc); + +int gpiod_direction_output_raw(struct gpio_desc *desc, int value); +int gpiod_direction_output(struct gpio_desc *desc, int value); + +void gpiod_set_raw_value(struct gpio_desc *desc, int value); +void gpiod_set_value(struct gpio_desc *desc, int value); + +int gpiod_get_raw_value(const struct gpio_desc *desc); +int gpiod_get_value(const struct gpio_desc *desc); + +void gpiod_put(struct gpio_desc *desc); + +int gpiod_count(struct device *dev, const char *con_id); + +struct gpio_descs *__must_check gpiod_get_array(struct device *dev, + const char *con_id, + enum gpiod_flags flags); + +void gpiod_put_array(struct gpio_descs *descs); + +int gpiod_set_array_value(unsigned int array_size, + struct gpio_desc **desc_array, + struct gpio_array *array_info, + unsigned long *value_bitmap); + +#else + +static inline int gpiod_direction_input(struct gpio_desc *desc) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); + return 0; +} + +static inline int gpiod_direction_output_raw(struct gpio_desc *desc, int value) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); + return 0; +} + +static inline int gpiod_direction_output(struct gpio_desc *desc, int value) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); + return 0; +} + +static inline void gpiod_set_raw_value(struct gpio_desc *desc, int value) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); +} + +static inline void gpiod_set_value(struct gpio_desc *desc, int value) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); +} + +static inline int gpiod_get_raw_value(const struct gpio_desc *desc) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); + return 0; +} + +static inline int gpiod_get_value(const struct gpio_desc *desc) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); + return 0; +} + +static inline void gpiod_put(struct gpio_desc *desc) +{ + /* GPIO can never have been requested */ + WARN_ON(desc); +} + +static inline int gpiod_count(struct device *dev, const char *con_id) +{ + return 0; +} + +static inline struct gpio_descs *__must_check +gpiod_get_array(struct device *dev, const char *con_id, enum gpiod_flags flags) +{ + return ERR_PTR(-ENOSYS); +} + +static inline void gpiod_put_array(struct gpio_descs *descs) +{ + /* GPIO can never have been requested */ + WARN_ON(descs); +} + +static inline int gpiod_set_array_value(unsigned int array_size, + struct gpio_desc **desc_array, + struct gpio_array *array_info, + unsigned long *value_bitmap) +{ + /* GPIO can never have been requested */ + WARN_ON(desc_array); + return 0; +} + +#endif + +static inline struct gpio_desc *dev_gpiod_get(struct device *dev, + struct device_node *np, + const char *con_id, + enum gpiod_flags flags, + const char *label) +{ + return dev_gpiod_get_index(dev, np, con_id, 0, flags, label); +} + +static inline struct gpio_desc *gpiod_get(struct device *dev, + const char *_con_id, + enum gpiod_flags flags) +{ + return dev_gpiod_get(dev, dev->of_node, _con_id, flags, NULL); +} + +static inline struct gpio_desc *__must_check +gpiod_get_optional(struct device *dev, const char *con_id, + enum gpiod_flags flags) +{ + struct gpio_desc *desc; + + desc = gpiod_get(dev, con_id, flags); + if (gpiod_not_found(desc)) + return NULL; + + return desc; +} + +/** + * gpiod_poll_timeout_us - poll till gpio descriptor reaches requested active state + * @gpiod: gpio descriptor to poll + * @active: wait till gpio is active if true, wait till it's inactive if false + * @timeout_us: timeout in microseconds + * + * during the wait barebox pollers are called, if any. + */ +#define gpiod_poll_timeout_us(gpiod, active, timeout_us) \ + ({ \ + int __state; \ + readx_poll_timeout(gpiod_get_value, gpiod, __state, \ + __state == (active), timeout_us); \ + }) + +#endif diff --git a/include/linux/hash.h b/include/linux/hash.h index ad6fa21d97..5e62f1bd8c 100644 --- a/include/linux/hash.h +++ b/include/linux/hash.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_HASH_H #define _LINUX_HASH_H /* Fast hashing routine for ints, longs and pointers. diff --git a/include/linux/hidden.h b/include/linux/hidden.h new file mode 100644 index 0000000000..49a17b6b59 --- /dev/null +++ b/include/linux/hidden.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * When building position independent code with GCC using the -fPIC option, + * (or even the -fPIE one on older versions), it will assume that we are + * building a dynamic object (either a shared library or an executable) that + * may have symbol references that can only be resolved at load time. For a + * variety of reasons (ELF symbol preemption, the CoW footprint of the section + * that is modified by the loader), this results in all references to symbols + * with external linkage to go via entries in the Global Offset Table (GOT), + * which carries absolute addresses which need to be fixed up when the + * executable image is loaded at an offset which is different from its link + * time offset. + * + * Fortunately, there is a way to inform the compiler that such symbol + * references will be satisfied at link time rather than at load time, by + * giving them 'hidden' visibility. + */ + +#pragma GCC visibility push(hidden) diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h index 116afd9721..ff6d3bb582 100644 --- a/include/linux/hw_random.h +++ b/include/linux/hw_random.h @@ -14,6 +14,7 @@ #define LINUX_HWRANDOM_H_ #include <linux/list.h> +#include <driver.h> /** * struct hwrng - Hardware Random Number Generator driver @@ -30,20 +31,30 @@ struct hwrng { struct list_head list; struct cdev cdev; - struct device_d *dev; + struct device *dev; void *buf; + unsigned long priv; }; /* Register a new Hardware Random Number Generator driver. */ -int hwrng_register(struct device_d *dev, struct hwrng *rng); -int hwrng_get_data(struct hwrng *rng, void *buffer, size_t size, int wait); +int hwrng_register(struct device *dev, struct hwrng *rng); #ifdef CONFIG_HWRNG struct hwrng *hwrng_get_first(void); +int hwrng_get_data(struct hwrng *rng, void *buffer, size_t size, int wait); #else static inline struct hwrng *hwrng_get_first(void) { return ERR_PTR(-ENODEV); }; +static inline int hwrng_get_data(struct hwrng *rng, void *buffer, size_t size, int wait) +{ + return -ENODEV; +} #endif void hwrng_unregister(struct hwrng *rng); +static inline long hwrng_yield(struct hwrng *rng) +{ + return 0; +} + #endif /* LINUX_HWRANDOM_H_ */ diff --git a/include/linux/idr.h b/include/linux/idr.h new file mode 100644 index 0000000000..9939085d0e --- /dev/null +++ b/include/linux/idr.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * include/linux/idr.h + * + * 2002-10-18 written by Jim Houston jim.houston@ccur.com + * Copyright (C) 2002 by Concurrent Computer Corporation + * + * Small id to pointer translation service avoiding fixed sized + * tables. + */ + +#ifndef __IDR_H__ +#define __IDR_H__ + +#include <errno.h> +#include <linux/list.h> + +struct idr { + int id; + void *ptr; + struct list_head list; +}; + +#define DEFINE_IDR(name) \ + struct idr name = { .list = LIST_HEAD_INIT((name).list) } + +/** + * idr_for_each_entry() - Iterate over an IDR's elements of a given type. + * @_idr: IDR handle. + * @_entry: The type * to use as cursor + * @_id: Entry ID. + * + * @_entry and @_id do not need to be initialized before the loop, and + * after normal termination @_entry is left with the value NULL. This + * is convenient for a "not found" value. + */ +#define idr_for_each_entry(_idr, _entry, _id) \ + for (struct idr *iter = \ + list_first_entry_or_null(&(_idr)->list, struct idr, list); \ + (iter && iter != (_idr)) || (_entry = NULL); \ + iter = list_next_entry(iter, list)) \ + if ((_entry = iter->ptr, _id = iter->id, true)) + +struct idr *__idr_find(struct idr *head, int lookup_id); + +int idr_for_each(const struct idr *idr, + int (*fn)(int id, void *p, void *data), void *data); + +static inline int idr_is_empty(const struct idr *idr) +{ + return list_empty(&idr->list); +} + +static inline void *idr_find(struct idr *head, int id) +{ + struct idr *idr = __idr_find(head, id); + + return idr ? idr->ptr : NULL; +} + +int idr_alloc_one(struct idr *head, void *ptr, int start); + +static inline void idr_init(struct idr *idr) +{ + INIT_LIST_HEAD(&idr->list); +} + +void idr_destroy(struct idr *idr); + +void idr_remove(struct idr *idr, int id); + +#endif /* __IDR_H__ */ diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h new file mode 100644 index 0000000000..05f8e3a957 --- /dev/null +++ b/include/linux/if_bridge.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _LINUX_IF_BRIDGE_H +#define _LINUX_IF_BRIDGE_H + +#define BR_STATE_DISABLED 0 +#define BR_STATE_FORWARDING 3 + +#endif diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h new file mode 100644 index 0000000000..9e54685064 --- /dev/null +++ b/include/linux/if_vlan.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * VLAN An implementation of 802.1Q VLAN tagging. + * + * Authors: Ben Greear <greearb@candelatech.com> + */ +#ifndef _LINUX_IF_VLAN_H_ +#define _LINUX_IF_VLAN_H_ + +#define VLAN_HLEN 4 /* The additional bytes required by VLAN + * (in addition to the Ethernet header) + */ +#define VLAN_ETH_HLEN 18 /* Total octets in header. */ +#define VLAN_ETH_ZLEN 64 /* Min. octets in frame sans FCS */ + +/* + * According to 802.3ac, the packet can be 4 bytes longer. --Klika Jan + */ +#define VLAN_ETH_DATA_LEN 1500 /* Max. octets in payload */ +#define VLAN_ETH_FRAME_LEN 1518 /* Max. octets in frame sans FCS */ + +#define VLAN_MAX_DEPTH 8 /* Max. number of nested VLAN tags parsed */ + +/* + * struct vlan_hdr - vlan header + * @h_vlan_TCI: priority and VLAN ID + * @h_vlan_encapsulated_proto: packet type ID or len + */ +struct vlan_hdr { + __be16 h_vlan_TCI; + __be16 h_vlan_encapsulated_proto; +}; + +/** + * struct vlan_ethhdr - vlan ethernet header (ethhdr + vlan_hdr) + * @h_dest: destination ethernet address + * @h_source: source ethernet address + * @h_vlan_proto: ethernet protocol + * @h_vlan_TCI: priority and VLAN ID + * @h_vlan_encapsulated_proto: packet type ID or len + */ +struct vlan_ethhdr { + unsigned char h_dest[ETH_ALEN]; + unsigned char h_source[ETH_ALEN]; + __be16 h_vlan_proto; + __be16 h_vlan_TCI; + __be16 h_vlan_encapsulated_proto; +}; + +#define VLAN_PRIO_MASK 0xe000 /* Priority Code Point */ +#define VLAN_PRIO_SHIFT 13 +#define VLAN_CFI_MASK 0x1000 /* Canonical Format Indicator / Drop Eligible Indicator */ +#define VLAN_VID_MASK 0x0fff /* VLAN Identifier */ +#define VLAN_N_VID 4096 + +#endif /* !(_LINUX_IF_VLAN_H_) */ diff --git a/include/linux/instruction_pointer.h b/include/linux/instruction_pointer.h new file mode 100644 index 0000000000..6564127a31 --- /dev/null +++ b/include/linux/instruction_pointer.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_INSTRUCTION_POINTER_H +#define _LINUX_INSTRUCTION_POINTER_H + +#define _RET_IP_ (unsigned long)__builtin_return_address(0) + +#ifndef _THIS_IP_ +#define _THIS_IP_ ({ __label__ __here; __here: (unsigned long)&&__here; }) +#endif + +#endif /* _LINUX_INSTRUCTION_POINTER_H */ diff --git a/include/linux/io.h b/include/linux/io.h new file mode 100644 index 0000000000..9119e4e629 --- /dev/null +++ b/include/linux/io.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _LINUX_IO_H +#define _LINUX_IO_H + +#define __LINUX_IO_STRICT_PROTOTYPES__ +#include <asm/io.h> + +#endif diff --git a/include/linux/iopoll.h b/include/linux/iopoll.h index 8bf912e173..96b17dee48 100644 --- a/include/linux/iopoll.h +++ b/include/linux/iopoll.h @@ -32,13 +32,13 @@ #define read_poll_timeout(op, val, cond, timeout_us, args...) \ ({ \ uint64_t start; \ - if (!IN_PBL && timeout_us) \ + if (!IN_PBL && (timeout_us) != 0) \ start = get_time_ns(); \ for (;;) { \ (val) = op(args); \ if (cond) \ break; \ - if (!IN_PBL && timeout_us && \ + if (!IN_PBL && (timeout_us) != 0 && \ is_timeout(start, ((timeout_us) * USECOND))) { \ (val) = op(args); \ break; \ diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 295ab4a49d..c6328e9a7f 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * ioport.h Definitions of routines for detecting, reserving and * allocating system resources. @@ -153,8 +155,8 @@ struct resource *request_ioport_region(const char *name, resource_size_t start, resource_size_t end); struct resource *__request_region(struct resource *parent, - const char *name, resource_size_t end, - resource_size_t size); + resource_size_t start, resource_size_t end, + const char *name, unsigned flags); int __merge_regions(const char *name, struct resource *resa, struct resource *resb); diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index ed2ebcfc42..e34465263c 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * JFFS2 -- Journalling Flash File System, Version 2. * diff --git a/include/linux/kasan.h b/include/linux/kasan.h index 7c184cd0e2..5fa0bebb79 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -42,11 +42,11 @@ #define KASAN_ALLOCA_LEFT 0xCA #define KASAN_ALLOCA_RIGHT 0xCB -#ifdef CONFIG_KASAN - extern unsigned long kasan_shadow_start; extern unsigned long kasan_shadow_base; +#if defined(CONFIG_KASAN) && !defined(__PBL__) + static inline void *kasan_mem_to_shadow(const void *addr) { unsigned long a = (unsigned long)addr; diff --git a/include/linux/kbuild.h b/include/linux/kbuild.h index 359d4a8682..de0f9bdb95 100644 --- a/include/linux/kbuild.h +++ b/include/linux/kbuild.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_KBUILD_H #define __LINUX_KBUILD_H diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4483d33e65..4e50f60751 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -7,11 +7,24 @@ #include <linux/barebox-wrapper.h> #include <linux/limits.h> #include <linux/math64.h> +#include <linux/container_of.h> +#include <linux/instruction_pointer.h> +#include <linux/minmax.h> + +/** + * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value + * @x: value to repeat + * + * NOTE: @x is not checked for > 0xff; larger values produce odd results. + */ +#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) #define ALIGN_DOWN(x, a) ALIGN((x) - ((a) - 1), (a)) #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) +#define PTR_ALIGN_DOWN(p, a) ((typeof(p))ALIGN_DOWN((unsigned long)(p), (a))) +#define PTR_IS_ALIGNED(x, a) IS_ALIGNED((unsigned long)(x), (a)) #define IS_ALIGNED(x, a) (((x) & ((typeof(x))(a) - 1)) == 0) #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) @@ -82,128 +95,11 @@ (__x < 0) ? -__x : __x; \ }) -void __noreturn panic(const char *fmt, ...); - extern unsigned long simple_strtoul(const char *,char **,unsigned int); extern long simple_strtol(const char *,char **,unsigned int); extern unsigned long long simple_strtoull(const char *,char **,unsigned int); extern long long simple_strtoll(const char *,char **,unsigned int); -/* - * min()/max()/clamp() macros that also do - * strict type-checking.. See the - * "unnecessary" pointer comparison. - */ -#define min(x, y) ({ \ - typeof(x) _min1 = (x); \ - typeof(y) _min2 = (y); \ - (void) (&_min1 == &_min2); \ - _min1 < _min2 ? _min1 : _min2; }) - -#define max(x, y) ({ \ - typeof(x) _max1 = (x); \ - typeof(y) _max2 = (y); \ - (void) (&_max1 == &_max2); \ - _max1 > _max2 ? _max1 : _max2; }) - -#define min3(x, y, z) ({ \ - typeof(x) _min1 = (x); \ - typeof(y) _min2 = (y); \ - typeof(z) _min3 = (z); \ - (void) (&_min1 == &_min2); \ - (void) (&_min1 == &_min3); \ - _min1 < _min2 ? (_min1 < _min3 ? _min1 : _min3) : \ - (_min2 < _min3 ? _min2 : _min3); }) - -#define max3(x, y, z) ({ \ - typeof(x) _max1 = (x); \ - typeof(y) _max2 = (y); \ - typeof(z) _max3 = (z); \ - (void) (&_max1 == &_max2); \ - (void) (&_max1 == &_max3); \ - _max1 > _max2 ? (_max1 > _max3 ? _max1 : _max3) : \ - (_max2 > _max3 ? _max2 : _max3); }) - -/** - * min_not_zero - return the minimum that is _not_ zero, unless both are zero - * @x: value1 - * @y: value2 - */ -#define min_not_zero(x, y) ({ \ - typeof(x) __x = (x); \ - typeof(y) __y = (y); \ - __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) - -/** - * clamp - return a value clamped to a given range with strict typechecking - * @val: current value - * @min: minimum allowable value - * @max: maximum allowable value - * - * This macro does strict typechecking of min/max to make sure they are of the - * same type as val. See the unnecessary pointer comparisons. - */ -#define clamp(val, min, max) ({ \ - typeof(val) __val = (val); \ - typeof(min) __min = (min); \ - typeof(max) __max = (max); \ - (void) (&__val == &__min); \ - (void) (&__val == &__max); \ - __val = __val < __min ? __min: __val; \ - __val > __max ? __max: __val; }) - -/* - * ..and if you can't take the strict - * types, you can specify one yourself. - * - * Or not use min/max/clamp at all, of course. - */ -#define min_t(type, x, y) ({ \ - type __min1 = (x); \ - type __min2 = (y); \ - __min1 < __min2 ? __min1: __min2; }) - -#define max_t(type, x, y) ({ \ - type __max1 = (x); \ - type __max2 = (y); \ - __max1 > __max2 ? __max1: __max2; }) - -/** - * clamp_t - return a value clamped to a given range using a given type - * @type: the type of variable to use - * @val: current value - * @min: minimum allowable value - * @max: maximum allowable value - * - * This macro does no typechecking and uses temporary variables of type - * 'type' to make all the comparisons. - */ -#define clamp_t(type, val, min, max) ({ \ - type __val = (val); \ - type __min = (min); \ - type __max = (max); \ - __val = __val < __min ? __min: __val; \ - __val > __max ? __max: __val; }) - -/** - * clamp_val - return a value clamped to a given range using val's type - * @val: current value - * @min: minimum allowable value - * @max: maximum allowable value - * - * This macro does no typechecking and uses temporary variables of whatever - * type the input argument 'val' is. This is useful when val is an unsigned - * type and min and max are literals that will otherwise be assigned a signed - * integer type. - */ -#define clamp_val(val, min, max) ({ \ - typeof(val) __val = (val); \ - typeof(val) __min = (min); \ - typeof(val) __max = (max); \ - __val = __val < __min ? __min: __val; \ - __val > __max ? __max: __val; }) - - /* The `const' in roundup() prevents gcc-3.3 from calling __divdi3 */ #define roundup(x, y) ( \ { \ @@ -230,8 +126,6 @@ extern long long simple_strtoll(const char *,char **,unsigned int); } \ ) -#define _RET_IP_ (unsigned long)__builtin_return_address(0) - extern const char hex_asc[]; #define hex_asc_lo(x) hex_asc[((x) & 0x0f)] #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] @@ -258,24 +152,6 @@ extern int hex_to_bin(char ch); extern int __must_check hex2bin(u8 *dst, const char *src, size_t count); extern char *bin2hex(char *dst, const void *src, size_t count); -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) - -/* - * swap - swap value of @a and @b - */ -#define swap(a, b) \ - do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) - - /* Internal, do not use. */ int __must_check _kstrtoul(const char *s, unsigned int base, unsigned long *res); int __must_check _kstrtol(const char *s, unsigned int base, long *res); diff --git a/include/linux/kref.h b/include/linux/kref.h new file mode 100644 index 0000000000..6add3d91da --- /dev/null +++ b/include/linux/kref.h @@ -0,0 +1,90 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * kref.h - library routines for handling generic reference counted objects + * + * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com> + * Copyright (C) 2004 IBM Corp. + * + * based on kobject.h which was: + * Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org> + * Copyright (C) 2002-2003 Open Source Development Labs + */ + +#ifndef _KREF_H_ +#define _KREF_H_ + +#include <linux/refcount.h> + +struct kref { + refcount_t refcount; +}; + +#define KREF_INIT(n) { .refcount = REFCOUNT_INIT(n), } + +/** + * kref_init - initialize object. + * @kref: object in question. + */ +static inline void kref_init(struct kref *kref) +{ + refcount_set(&kref->refcount, 1); +} + +static inline unsigned int kref_read(const struct kref *kref) +{ + return refcount_read(&kref->refcount); +} + +/** + * kref_get - increment refcount for object. + * @kref: object. + */ +static inline void kref_get(struct kref *kref) +{ + refcount_inc(&kref->refcount); +} + +/** + * kref_put - decrement refcount for object. + * @kref: object. + * @release: pointer to the function that will clean up the object when the + * last reference to the object is released. + * This pointer is required, and it is not acceptable to pass kfree + * in as this function. + * + * Decrement the refcount, and if 0, call release(). + * Return 1 if the object was removed, otherwise return 0. Beware, if this + * function returns 0, you still can not count on the kref from remaining in + * memory. Only use the return value if you want to see if the kref is now + * gone, not present. + */ +static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)) +{ + if (refcount_dec_and_test(&kref->refcount)) { + release(kref); + return 1; + } + return 0; +} + +/** + * kref_get_unless_zero - Increment refcount for object unless it is zero. + * @kref: object. + * + * Return non-zero if the increment succeeded. Otherwise return 0. + * + * This function is intended to simplify locking around refcounting for + * objects that can be looked up from a lookup structure, and which are + * removed from that lookup structure in the object destructor. + * Operations on such objects require at least a read lock around + * lookup + kref_get, and a write lock around kref_put + remove from lookup + * structure. Furthermore, RCU implementations become extremely tricky. + * With a lookup followed by a kref_get_unless_zero *with return value check* + * locking in the kref_put path can be deferred to the actual removal from + * the lookup structure and RCU lookups become trivial. + */ +static inline int __must_check kref_get_unless_zero(struct kref *kref) +{ + return refcount_inc_not_zero(&kref->refcount); +} +#endif /* _KREF_H_ */ diff --git a/include/linux/ktime.h b/include/linux/ktime.h new file mode 100644 index 0000000000..ea368b8802 --- /dev/null +++ b/include/linux/ktime.h @@ -0,0 +1,212 @@ +/* + * include/linux/ktime.h + * + * ktime_t - nanosecond-resolution time format. + * + * Copyright(C) 2005, Thomas Gleixner <tglx@linutronix.de> + * Copyright(C) 2005, Red Hat, Inc., Ingo Molnar + * + * data type definitions, declarations, prototypes and macros. + * + * Started by: Thomas Gleixner and Ingo Molnar + * + * Credits: + * + * Roman Zippel provided the ideas and primary code snippets of + * the ktime_t union and further simplifications of the original + * code. + * + * For licencing details see kernel-base/COPYING + */ +#ifndef _LINUX_KTIME_H +#define _LINUX_KTIME_H + +#include <linux/time.h> +#include <clock.h> +#include <linux/bug.h> + +#define KTIME_MAX ((s64)~((u64)1 << 63)) +#define KTIME_MIN (-KTIME_MAX - 1) +#define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) +#define KTIME_SEC_MIN (KTIME_MIN / NSEC_PER_SEC) + +/* Nanosecond scalar representation for kernel time values */ +typedef s64 ktime_t; + +/** + * ktime_set - Set a ktime_t variable from a seconds/nanoseconds value + * @secs: seconds to set + * @nsecs: nanoseconds to set + * + * Return: The ktime_t representation of the value. + */ +static inline ktime_t ktime_set(const s64 secs, const unsigned long nsecs) +{ + if (unlikely(secs >= KTIME_SEC_MAX)) + return KTIME_MAX; + + return secs * NSEC_PER_SEC + (s64)nsecs; +} + +/* Subtract two ktime_t variables. rem = lhs -rhs: */ +#define ktime_sub(lhs, rhs) ((lhs) - (rhs)) + +/* Add two ktime_t variables. res = lhs + rhs: */ +#define ktime_add(lhs, rhs) ((lhs) + (rhs)) + +/* + * Same as ktime_add(), but avoids undefined behaviour on overflow; however, + * this means that you must check the result for overflow yourself. + */ +#define ktime_add_unsafe(lhs, rhs) ((u64) (lhs) + (rhs)) + +/* + * Add a ktime_t variable and a scalar nanosecond value. + * res = kt + nsval: + */ +#define ktime_add_ns(kt, nsval) ((kt) + (nsval)) + +/* + * Subtract a scalar nanosecod from a ktime_t variable + * res = kt - nsval: + */ +#define ktime_sub_ns(kt, nsval) ((kt) - (nsval)) + +/* Convert ktime_t to nanoseconds */ +static inline s64 ktime_to_ns(const ktime_t kt) +{ + return kt; +} + +/** + * ktime_compare - Compares two ktime_t variables for less, greater or equal + * @cmp1: comparable1 + * @cmp2: comparable2 + * + * Return: ... + * cmp1 < cmp2: return <0 + * cmp1 == cmp2: return 0 + * cmp1 > cmp2: return >0 + */ +static inline int ktime_compare(const ktime_t cmp1, const ktime_t cmp2) +{ + if (cmp1 < cmp2) + return -1; + if (cmp1 > cmp2) + return 1; + return 0; +} + +/** + * ktime_after - Compare if a ktime_t value is bigger than another one. + * @cmp1: comparable1 + * @cmp2: comparable2 + * + * Return: true if cmp1 happened after cmp2. + */ +static inline bool ktime_after(const ktime_t cmp1, const ktime_t cmp2) +{ + return ktime_compare(cmp1, cmp2) > 0; +} + +/** + * ktime_before - Compare if a ktime_t value is smaller than another one. + * @cmp1: comparable1 + * @cmp2: comparable2 + * + * Return: true if cmp1 happened before cmp2. + */ +static inline bool ktime_before(const ktime_t cmp1, const ktime_t cmp2) +{ + return ktime_compare(cmp1, cmp2) < 0; +} + +#if BITS_PER_LONG < 64 +extern s64 __ktime_divns(const ktime_t kt, s64 div); +static inline s64 ktime_divns(const ktime_t kt, s64 div) +{ + /* + * Negative divisors could cause an inf loop, + * so bug out here. + */ + BUG_ON(div < 0); + if (__builtin_constant_p(div) && !(div >> 32)) { + s64 ns = kt; + u64 tmp = ns < 0 ? -ns : ns; + + do_div(tmp, div); + return ns < 0 ? -tmp : tmp; + } else { + return __ktime_divns(kt, div); + } +} +#else /* BITS_PER_LONG < 64 */ +static inline s64 ktime_divns(const ktime_t kt, s64 div) +{ + /* + * 32-bit implementation cannot handle negative divisors, + * so catch them on 64bit as well. + */ + WARN_ON(div < 0); + return kt / div; +} +#endif + +static inline s64 ktime_to_us(const ktime_t kt) +{ + return ktime_divns(kt, NSEC_PER_USEC); +} + +static inline s64 ktime_to_ms(const ktime_t kt) +{ + return ktime_divns(kt, NSEC_PER_MSEC); +} + +static inline s64 ktime_us_delta(const ktime_t later, const ktime_t earlier) +{ + return ktime_to_us(ktime_sub(later, earlier)); +} + +static inline s64 ktime_ms_delta(const ktime_t later, const ktime_t earlier) +{ + return ktime_to_ms(ktime_sub(later, earlier)); +} + +static inline ktime_t ktime_add_us(const ktime_t kt, const u64 usec) +{ + return ktime_add_ns(kt, usec * NSEC_PER_USEC); +} + +static inline ktime_t ktime_add_ms(const ktime_t kt, const u64 msec) +{ + return ktime_add_ns(kt, msec * NSEC_PER_MSEC); +} + +static inline ktime_t ktime_sub_us(const ktime_t kt, const u64 usec) +{ + return ktime_sub_ns(kt, usec * NSEC_PER_USEC); +} + +static inline ktime_t ktime_sub_ms(const ktime_t kt, const u64 msec) +{ + return ktime_sub_ns(kt, msec * NSEC_PER_MSEC); +} + +extern ktime_t ktime_add_safe(const ktime_t lhs, const ktime_t rhs); + +static inline ktime_t ns_to_ktime(u64 ns) +{ + return ns; +} + +static inline ktime_t ms_to_ktime(u64 ms) +{ + return ms * NSEC_PER_MSEC; +} + +static inline ktime_t ktime_get(void) +{ + return get_time_ns(); +} + +#endif diff --git a/include/linux/limits.h b/include/linux/limits.h index bda9c94bb5..8baf849494 100644 --- a/include/linux/limits.h +++ b/include/linux/limits.h @@ -18,6 +18,9 @@ #define ULLONG_MAX (~0ULL) #define SIZE_MAX (~(size_t)0) #define PHYS_ADDR_MAX (~(phys_addr_t)0) +#define SSIZE_MAX ((ssize_t)(SIZE_MAX >> 1)) +#define INTPTR_MAX LONG_MAX +#define UINTPTR_MAX ULONG_MAX #define U8_MAX ((u8)~0U) #define S8_MAX ((s8)(U8_MAX >> 1)) @@ -32,4 +35,6 @@ #define S64_MAX ((s64)(U64_MAX >> 1)) #define S64_MIN ((s64)(-S64_MAX - 1)) +#define PATH_MAX 1024 + #endif /* _LINUX_LIMITS_H */ diff --git a/include/linux/linkage.h b/include/linux/linkage.h index 9fd1f85902..c262c7b369 100644 --- a/include/linux/linkage.h +++ b/include/linux/linkage.h @@ -1,9 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_LINKAGE_H #define _LINUX_LINKAGE_H -#include <linux/compiler.h> +#include <linux/compiler_types.h> +#include <linux/stringify.h> +#include <linux/export.h> #include <asm/linkage.h> +/* Some toolchains use other characters (e.g. '`') to mark new line in macro */ +#ifndef ASM_NL +#define ASM_NL ; +#endif + #ifdef __cplusplus #define CPP_ASMLINKAGE extern "C" #else @@ -14,12 +23,31 @@ #define asmlinkage CPP_ASMLINKAGE #endif -#ifndef asmregparm -# define asmregparm +#ifndef cond_syscall +#define cond_syscall(x) asm( \ + ".weak " __stringify(x) "\n\t" \ + ".set " __stringify(x) "," \ + __stringify(sys_ni_syscall)) #endif -#define __page_aligned_data __section(.data.page_aligned) __aligned(PAGE_SIZE) -#define __page_aligned_bss __section(.bss.page_aligned) __aligned(PAGE_SIZE) +#ifndef SYSCALL_ALIAS +#define SYSCALL_ALIAS(alias, name) asm( \ + ".globl " __stringify(alias) "\n\t" \ + ".set " __stringify(alias) "," \ + __stringify(name)) +#endif + +#define __page_aligned_data __section(".data..page_aligned") __aligned(PAGE_SIZE) +#define __page_aligned_bss __section(".bss..page_aligned") __aligned(PAGE_SIZE) + +/* + * For assembly routines. + * + * Note when using these that you must specify the appropriate + * alignment directives yourself + */ +#define __PAGE_ALIGNED_DATA .section ".data..page_aligned", "aw" +#define __PAGE_ALIGNED_BSS .section ".bss..page_aligned", "aw" /* * This is used by architectures to keep arguments on the stack @@ -42,39 +70,69 @@ #endif #ifndef __ALIGN -#define __ALIGN .align 4,0x90 -#define __ALIGN_STR ".align 4,0x90" +#define __ALIGN .balign 4 +#define __ALIGN_STR __stringify(__ALIGN) #endif #ifdef __ASSEMBLY__ +/* SYM_T_FUNC -- type used by assembler to mark functions */ +#ifndef SYM_T_FUNC +#define SYM_T_FUNC STT_FUNC +#endif + +/* SYM_T_OBJECT -- type used by assembler to mark data */ +#ifndef SYM_T_OBJECT +#define SYM_T_OBJECT STT_OBJECT +#endif + +/* SYM_T_NONE -- type used by assembler to mark entries of unknown type */ +#ifndef SYM_T_NONE +#define SYM_T_NONE STT_NOTYPE +#endif + +/* SYM_A_* -- align the symbol? */ +#define SYM_A_ALIGN ALIGN +#define SYM_A_NONE /* nothing */ + +/* SYM_L_* -- linkage of symbols */ +#define SYM_L_GLOBAL(name) .globl name +#define SYM_L_WEAK(name) .weak name +#define SYM_L_LOCAL(name) /* nothing */ + +#ifndef LINKER_SCRIPT #define ALIGN __ALIGN #define ALIGN_STR __ALIGN_STR +/* === DEPRECATED annotations === */ + +#ifndef CONFIG_ARCH_USE_SYM_ANNOTATIONS +#ifndef GLOBAL +/* deprecated, use SYM_DATA*, SYM_ENTRY, or similar */ +#define GLOBAL(name) \ + .globl name ASM_NL \ + name: +#endif + #ifndef ENTRY +/* deprecated, use SYM_FUNC_START */ #define ENTRY(name) \ - .globl name; \ - ALIGN; \ - name: + SYM_FUNC_START(name) #endif +#endif /* CONFIG_ARCH_USE_SYM_ANNOTATIONS */ +#endif /* LINKER_SCRIPT */ +#ifndef CONFIG_ARCH_USE_SYM_ANNOTATIONS #ifndef WEAK +/* deprecated, use SYM_FUNC_START_WEAK* */ #define WEAK(name) \ - .weak name; \ - name: + SYM_FUNC_START_WEAK(name) #endif -#define KPROBE_ENTRY(name) \ - .pushsection .kprobes.text, "ax"; \ - ENTRY(name) - -#define KPROBE_END(name) \ - END(name); \ - .popsection - #ifndef END +/* deprecated, use SYM_FUNC_END, SYM_DATA_END, or SYM_END */ #define END(name) \ - .size name, .-name + .size name, .-name #endif /* If symbol 'name' is treated as a subroutine (gets called, and returns) @@ -82,15 +140,222 @@ * static analysis tools such as stack depth analyzer. */ #ifndef ENDPROC +/* deprecated, use SYM_FUNC_END */ #define ENDPROC(name) \ - .type name, @function; \ - END(name) + SYM_FUNC_END(name) #endif +#endif /* CONFIG_ARCH_USE_SYM_ANNOTATIONS */ +/* === generic annotations === */ + +/* SYM_ENTRY -- use only if you have to for non-paired symbols */ +#ifndef SYM_ENTRY +#define SYM_ENTRY(name, linkage, align...) \ + linkage(name) ASM_NL \ + align ASM_NL \ + name: +#endif + +/* SYM_START -- use only if you have to */ +#ifndef SYM_START +#define SYM_START(name, linkage, align...) \ + SYM_ENTRY(name, linkage, align) +#endif + +/* SYM_END -- use only if you have to */ +#ifndef SYM_END +#define SYM_END(name, sym_type) \ + .type name sym_type ASM_NL \ + .set .L__sym_size_##name, .-name ASM_NL \ + .size name, .L__sym_size_##name +#endif + +/* SYM_ALIAS -- use only if you have to */ +#ifndef SYM_ALIAS +#define SYM_ALIAS(alias, name, linkage) \ + linkage(alias) ASM_NL \ + .set alias, name ASM_NL +#endif + +/* === code annotations === */ + +/* + * FUNC -- C-like functions (proper stack frame etc.) + * CODE -- non-C code (e.g. irq handlers with different, special stack etc.) + * + * Objtool validates stack for FUNC, but not for CODE. + * Objtool generates debug info for both FUNC & CODE, but needs special + * annotations for each CODE's start (to describe the actual stack frame). + * + * Objtool requires that all code must be contained in an ELF symbol. Symbol + * names that have a .L prefix do not emit symbol table entries. .L + * prefixed symbols can be used within a code region, but should be avoided for + * denoting a range of code via ``SYM_*_START/END`` annotations. + * + * ALIAS -- does not generate debug info -- the aliased function will + */ + +/* SYM_INNER_LABEL_ALIGN -- only for labels in the middle of code */ +#ifndef SYM_INNER_LABEL_ALIGN +#define SYM_INNER_LABEL_ALIGN(name, linkage) \ + .type name SYM_T_NONE ASM_NL \ + SYM_ENTRY(name, linkage, SYM_A_ALIGN) +#endif + +/* SYM_INNER_LABEL -- only for labels in the middle of code */ +#ifndef SYM_INNER_LABEL +#define SYM_INNER_LABEL(name, linkage) \ + .type name SYM_T_NONE ASM_NL \ + SYM_ENTRY(name, linkage, SYM_A_NONE) +#endif + +/* SYM_FUNC_START -- use for global functions */ +#ifndef SYM_FUNC_START +#define SYM_FUNC_START(name) \ + SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) #endif -#define NORET_TYPE /**/ -#define ATTRIB_NORET __attribute__((noreturn)) -#define NORET_AND noreturn, +/* SYM_FUNC_START_NOALIGN -- use for global functions, w/o alignment */ +#ifndef SYM_FUNC_START_NOALIGN +#define SYM_FUNC_START_NOALIGN(name) \ + SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) +#endif + +/* SYM_FUNC_START_LOCAL -- use for local functions */ +#ifndef SYM_FUNC_START_LOCAL +#define SYM_FUNC_START_LOCAL(name) \ + SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) +#endif +/* SYM_FUNC_START_LOCAL_NOALIGN -- use for local functions, w/o alignment */ +#ifndef SYM_FUNC_START_LOCAL_NOALIGN +#define SYM_FUNC_START_LOCAL_NOALIGN(name) \ + SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) #endif + +/* SYM_FUNC_START_WEAK -- use for weak functions */ +#ifndef SYM_FUNC_START_WEAK +#define SYM_FUNC_START_WEAK(name) \ + SYM_START(name, SYM_L_WEAK, SYM_A_ALIGN) +#endif + +/* SYM_FUNC_START_WEAK_NOALIGN -- use for weak functions, w/o alignment */ +#ifndef SYM_FUNC_START_WEAK_NOALIGN +#define SYM_FUNC_START_WEAK_NOALIGN(name) \ + SYM_START(name, SYM_L_WEAK, SYM_A_NONE) +#endif + +/* + * SYM_FUNC_END -- the end of SYM_FUNC_START_LOCAL, SYM_FUNC_START, + * SYM_FUNC_START_WEAK, ... + */ +#ifndef SYM_FUNC_END +#define SYM_FUNC_END(name) \ + SYM_END(name, SYM_T_FUNC) +#endif + +/* + * SYM_FUNC_ALIAS -- define a global alias for an existing function + */ +#ifndef SYM_FUNC_ALIAS +#define SYM_FUNC_ALIAS(alias, name) \ + SYM_ALIAS(alias, name, SYM_L_GLOBAL) +#endif + +/* + * SYM_FUNC_ALIAS_LOCAL -- define a local alias for an existing function + */ +#ifndef SYM_FUNC_ALIAS_LOCAL +#define SYM_FUNC_ALIAS_LOCAL(alias, name) \ + SYM_ALIAS(alias, name, SYM_L_LOCAL) +#endif + +/* + * SYM_FUNC_ALIAS_WEAK -- define a weak global alias for an existing function + */ +#ifndef SYM_FUNC_ALIAS_WEAK +#define SYM_FUNC_ALIAS_WEAK(alias, name) \ + SYM_ALIAS(alias, name, SYM_L_WEAK) +#endif + +/* SYM_CODE_START -- use for non-C (special) functions */ +#ifndef SYM_CODE_START +#define SYM_CODE_START(name) \ + SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN) +#endif + +/* SYM_CODE_START_NOALIGN -- use for non-C (special) functions, w/o alignment */ +#ifndef SYM_CODE_START_NOALIGN +#define SYM_CODE_START_NOALIGN(name) \ + SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) +#endif + +/* SYM_CODE_START_LOCAL -- use for local non-C (special) functions */ +#ifndef SYM_CODE_START_LOCAL +#define SYM_CODE_START_LOCAL(name) \ + SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN) +#endif + +/* + * SYM_CODE_START_LOCAL_NOALIGN -- use for local non-C (special) functions, + * w/o alignment + */ +#ifndef SYM_CODE_START_LOCAL_NOALIGN +#define SYM_CODE_START_LOCAL_NOALIGN(name) \ + SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) +#endif + +/* SYM_CODE_END -- the end of SYM_CODE_START_LOCAL, SYM_CODE_START, ... */ +#ifndef SYM_CODE_END +#define SYM_CODE_END(name) \ + SYM_END(name, SYM_T_NONE) +#endif + +/* === data annotations === */ + +/* SYM_DATA_START -- global data symbol */ +#ifndef SYM_DATA_START +#define SYM_DATA_START(name) \ + SYM_START(name, SYM_L_GLOBAL, SYM_A_NONE) +#endif + +/* SYM_DATA_START -- local data symbol */ +#ifndef SYM_DATA_START_LOCAL +#define SYM_DATA_START_LOCAL(name) \ + SYM_START(name, SYM_L_LOCAL, SYM_A_NONE) +#endif + +/* SYM_DATA_END -- the end of SYM_DATA_START symbol */ +#ifndef SYM_DATA_END +#define SYM_DATA_END(name) \ + SYM_END(name, SYM_T_OBJECT) +#endif + +/* SYM_DATA_END_LABEL -- the labeled end of SYM_DATA_START symbol */ +#ifndef SYM_DATA_END_LABEL +#define SYM_DATA_END_LABEL(name, linkage, label) \ + linkage(label) ASM_NL \ + .type label SYM_T_OBJECT ASM_NL \ + label: \ + SYM_END(name, SYM_T_OBJECT) +#endif + +/* SYM_DATA -- start+end wrapper around simple global data */ +#ifndef SYM_DATA +#define SYM_DATA(name, data...) \ + SYM_DATA_START(name) ASM_NL \ + data ASM_NL \ + SYM_DATA_END(name) +#endif + +/* SYM_DATA_LOCAL -- start+end wrapper around simple local data */ +#ifndef SYM_DATA_LOCAL +#define SYM_DATA_LOCAL(name, data...) \ + SYM_DATA_START_LOCAL(name) ASM_NL \ + data ASM_NL \ + SYM_DATA_END(name) +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* _LINUX_LINKAGE_H */ diff --git a/include/linux/list.h b/include/linux/list.h index 1341806b59..60b0111f46 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -37,18 +37,18 @@ static inline void INIT_LIST_HEAD(struct list_head *list) } #ifdef CONFIG_DEBUG_LIST -extern bool __list_add_valid(struct list_head *new, - struct list_head *prev, - struct list_head *next); -extern bool __list_del_entry_valid(struct list_head *entry); +extern bool __list_add_valid_or_report(struct list_head *new, + struct list_head *prev, + struct list_head *next); +extern bool __list_del_entry_valid_or_report(struct list_head *entry); #else -static inline bool __list_add_valid(struct list_head *new, - struct list_head *prev, - struct list_head *next) +static inline bool __list_add_valid_or_report(struct list_head *new, + struct list_head *prev, + struct list_head *next) { return true; } -static inline bool __list_del_entry_valid(struct list_head *entry) +static inline bool __list_del_entry_valid_or_report(struct list_head *entry) { return true; } @@ -64,7 +64,7 @@ static inline void __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { - if (!__list_add_valid(new, prev, next)) + if (!__list_add_valid_or_report(new, prev, next)) return; next->prev = new; @@ -129,7 +129,7 @@ static inline void __list_del_clearprev(struct list_head *entry) static inline void __list_del_entry(struct list_head *entry) { - if (!__list_del_entry_valid(entry)) + if (!__list_del_entry_valid_or_report(entry)) return; __list_del(entry->prev, entry->next); diff --git a/include/linux/list_sort.h b/include/linux/list_sort.h index 1a2df2efb7..9260df2fb1 100644 --- a/include/linux/list_sort.h +++ b/include/linux/list_sort.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_LIST_SORT_H #define _LINUX_LIST_SORT_H diff --git a/include/linux/magic.h b/include/linux/magic.h index 0de181ad73..2af9665075 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_MAGIC_H__ #define __LINUX_MAGIC_H__ diff --git a/include/linux/mdio-bitbang.h b/include/linux/mdio-bitbang.h index 76f52bbbb2..49fe435429 100644 --- a/include/linux/mdio-bitbang.h +++ b/include/linux/mdio-bitbang.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_MDIO_BITBANG_H #define __LINUX_MDIO_BITBANG_H @@ -34,6 +36,9 @@ struct mdiobb_ctrl { const struct mdiobb_ops *ops; /* reset callback */ int (*reset)(struct mii_bus *bus); + unsigned int override_op_c22; + u8 op_c22_read; + u8 op_c22_write; }; /* The returned bus is not yet registered with the phy layer. */ diff --git a/include/linux/mdio-mux.h b/include/linux/mdio-mux.h index 1730939bfc..c35220a62d 100644 --- a/include/linux/mdio-mux.h +++ b/include/linux/mdio-mux.h @@ -19,7 +19,7 @@ * @data Private data used by switch_fn() * @mux_bus An optional parent bus (Other case are to use parent_bus property) */ -int mdio_mux_init(struct device_d *dev, +int mdio_mux_init(struct device *dev, struct device_node *mux_node, int (*switch_fn) (int cur, int desired, void *data), void *data, diff --git a/include/linux/mdio.h b/include/linux/mdio.h index 4bcb41c71b..c441a074ec 100644 --- a/include/linux/mdio.h +++ b/include/linux/mdio.h @@ -13,6 +13,7 @@ #include <linux/types.h> #include <linux/mii.h> +#include <init.h> /* MDIO Manageable Devices (MMDs). */ #define MDIO_MMD_PMAPMD 1 /* Physical Medium Attachment/ @@ -324,4 +325,20 @@ static inline __u16 mdio_phy_id_c45(int prtad, int devad) return MDIO_PHY_ID_C45 | (prtad << 5) | devad; } +#define MDIO_DEVAD_NONE (-1) + +struct phy_driver; + +int mdio_driver_register(struct phy_driver *drv); + +#define mdio_register_driver_macro(level, drv) \ + static int __init drv##_register(void) \ + { \ + return mdio_driver_register(&drv); \ + } \ + level##_initcall(drv##_register) + +#define device_mdio_driver(drv) \ + mdio_register_driver_macro(device, drv) + #endif /* _UAPI__LINUX_MDIO_H__ */ diff --git a/include/linux/mfd/axp20x.h b/include/linux/mfd/axp20x.h new file mode 100644 index 0000000000..93d303c459 --- /dev/null +++ b/include/linux/mfd/axp20x.h @@ -0,0 +1,485 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Functions and registers to access AXP20X power management chip. + * + * Copyright (C) 2013, Carlo Caione <carlo@caione.org> + */ + +#ifndef __LINUX_MFD_AXP20X_H +#define __LINUX_MFD_AXP20X_H + +#include <poweroff.h> + +enum axp20x_variants { + AXP152_ID = 0, + AXP202_ID, + AXP209_ID, + AXP221_ID, + AXP223_ID, + AXP288_ID, + AXP313A_ID, + AXP803_ID, + AXP806_ID, + AXP809_ID, + AXP813_ID, + NR_AXP20X_VARIANTS, +}; + +#define AXP20X_DATACACHE(m) (0x04 + (m)) + +/* Power supply */ +#define AXP152_PWR_OP_MODE 0x01 +#define AXP152_LDO3456_DC1234_CTRL 0x12 +#define AXP152_ALDO_OP_MODE 0x13 +#define AXP152_LDO0_CTRL 0x15 +#define AXP152_DCDC2_V_OUT 0x23 +#define AXP152_DCDC2_V_RAMP 0x25 +#define AXP152_DCDC1_V_OUT 0x26 +#define AXP152_DCDC3_V_OUT 0x27 +#define AXP152_ALDO12_V_OUT 0x28 +#define AXP152_DLDO1_V_OUT 0x29 +#define AXP152_DLDO2_V_OUT 0x2a +#define AXP152_DCDC4_V_OUT 0x2b +#define AXP152_V_OFF 0x31 +#define AXP152_OFF_CTRL 0x32 +#define AXP152_PEK_KEY 0x36 +#define AXP152_DCDC_FREQ 0x37 +#define AXP152_DCDC_MODE 0x80 + +#define AXP20X_PWR_INPUT_STATUS 0x00 +#define AXP20X_PWR_OP_MODE 0x01 +#define AXP20X_USB_OTG_STATUS 0x02 +#define AXP20X_PWR_OUT_CTRL 0x12 +#define AXP20X_DCDC2_V_OUT 0x23 +#define AXP20X_DCDC2_LDO3_V_RAMP 0x25 +#define AXP20X_DCDC3_V_OUT 0x27 +#define AXP20X_LDO24_V_OUT 0x28 +#define AXP20X_LDO3_V_OUT 0x29 +#define AXP20X_VBUS_IPSOUT_MGMT 0x30 +#define AXP20X_V_OFF 0x31 +#define AXP20X_OFF_CTRL 0x32 +#define AXP20X_CHRG_CTRL1 0x33 +#define AXP20X_CHRG_CTRL2 0x34 +#define AXP20X_CHRG_BAK_CTRL 0x35 +#define AXP20X_PEK_KEY 0x36 +#define AXP20X_DCDC_FREQ 0x37 +#define AXP20X_V_LTF_CHRG 0x38 +#define AXP20X_V_HTF_CHRG 0x39 +#define AXP20X_APS_WARN_L1 0x3a +#define AXP20X_APS_WARN_L2 0x3b +#define AXP20X_V_LTF_DISCHRG 0x3c +#define AXP20X_V_HTF_DISCHRG 0x3d + +#define AXP22X_PWR_OUT_CTRL1 0x10 +#define AXP22X_PWR_OUT_CTRL2 0x12 +#define AXP22X_PWR_OUT_CTRL3 0x13 +#define AXP22X_DLDO1_V_OUT 0x15 +#define AXP22X_DLDO2_V_OUT 0x16 +#define AXP22X_DLDO3_V_OUT 0x17 +#define AXP22X_DLDO4_V_OUT 0x18 +#define AXP22X_ELDO1_V_OUT 0x19 +#define AXP22X_ELDO2_V_OUT 0x1a +#define AXP22X_ELDO3_V_OUT 0x1b +#define AXP22X_DC5LDO_V_OUT 0x1c +#define AXP22X_DCDC1_V_OUT 0x21 +#define AXP22X_DCDC2_V_OUT 0x22 +#define AXP22X_DCDC3_V_OUT 0x23 +#define AXP22X_DCDC4_V_OUT 0x24 +#define AXP22X_DCDC5_V_OUT 0x25 +#define AXP22X_DCDC23_V_RAMP_CTRL 0x27 +#define AXP22X_ALDO1_V_OUT 0x28 +#define AXP22X_ALDO2_V_OUT 0x29 +#define AXP22X_ALDO3_V_OUT 0x2a +#define AXP22X_CHRG_CTRL3 0x35 + +#define AXP806_STARTUP_SRC 0x00 +#define AXP806_CHIP_ID 0x03 +#define AXP806_PWR_OUT_CTRL1 0x10 +#define AXP806_PWR_OUT_CTRL2 0x11 +#define AXP806_DCDCA_V_CTRL 0x12 +#define AXP806_DCDCB_V_CTRL 0x13 +#define AXP806_DCDCC_V_CTRL 0x14 +#define AXP806_DCDCD_V_CTRL 0x15 +#define AXP806_DCDCE_V_CTRL 0x16 +#define AXP806_ALDO1_V_CTRL 0x17 +#define AXP806_ALDO2_V_CTRL 0x18 +#define AXP806_ALDO3_V_CTRL 0x19 +#define AXP806_DCDC_MODE_CTRL1 0x1a +#define AXP806_DCDC_MODE_CTRL2 0x1b +#define AXP806_DCDC_FREQ_CTRL 0x1c +#define AXP806_BLDO1_V_CTRL 0x20 +#define AXP806_BLDO2_V_CTRL 0x21 +#define AXP806_BLDO3_V_CTRL 0x22 +#define AXP806_BLDO4_V_CTRL 0x23 +#define AXP806_CLDO1_V_CTRL 0x24 +#define AXP806_CLDO2_V_CTRL 0x25 +#define AXP806_CLDO3_V_CTRL 0x26 +#define AXP806_VREF_TEMP_WARN_L 0xf3 +#define AXP806_BUS_ADDR_EXT 0xfe +#define AXP806_REG_ADDR_EXT 0xff + +#define AXP803_POLYPHASE_CTRL 0x14 +#define AXP803_FLDO1_V_OUT 0x1c +#define AXP803_FLDO2_V_OUT 0x1d +#define AXP803_DCDC1_V_OUT 0x20 +#define AXP803_DCDC2_V_OUT 0x21 +#define AXP803_DCDC3_V_OUT 0x22 +#define AXP803_DCDC4_V_OUT 0x23 +#define AXP803_DCDC5_V_OUT 0x24 +#define AXP803_DCDC6_V_OUT 0x25 +#define AXP803_DCDC_FREQ_CTRL 0x3b + +/* Other DCDC regulator control registers are the same as AXP803 */ +#define AXP813_DCDC7_V_OUT 0x26 + +/* Interrupt */ +#define AXP152_IRQ1_EN 0x40 +#define AXP152_IRQ2_EN 0x41 +#define AXP152_IRQ3_EN 0x42 +#define AXP152_IRQ1_STATE 0x48 +#define AXP152_IRQ2_STATE 0x49 +#define AXP152_IRQ3_STATE 0x4a + +#define AXP20X_IRQ1_EN 0x40 +#define AXP20X_IRQ2_EN 0x41 +#define AXP20X_IRQ3_EN 0x42 +#define AXP20X_IRQ4_EN 0x43 +#define AXP20X_IRQ5_EN 0x44 +#define AXP20X_IRQ6_EN 0x45 +#define AXP20X_IRQ1_STATE 0x48 +#define AXP20X_IRQ2_STATE 0x49 +#define AXP20X_IRQ3_STATE 0x4a +#define AXP20X_IRQ4_STATE 0x4b +#define AXP20X_IRQ5_STATE 0x4c +#define AXP20X_IRQ6_STATE 0x4d + +/* ADC */ +#define AXP20X_ACIN_V_ADC_H 0x56 +#define AXP20X_ACIN_V_ADC_L 0x57 +#define AXP20X_ACIN_I_ADC_H 0x58 +#define AXP20X_ACIN_I_ADC_L 0x59 +#define AXP20X_VBUS_V_ADC_H 0x5a +#define AXP20X_VBUS_V_ADC_L 0x5b +#define AXP20X_VBUS_I_ADC_H 0x5c +#define AXP20X_VBUS_I_ADC_L 0x5d +#define AXP20X_TEMP_ADC_H 0x5e +#define AXP20X_TEMP_ADC_L 0x5f +#define AXP20X_TS_IN_H 0x62 +#define AXP20X_TS_IN_L 0x63 +#define AXP20X_GPIO0_V_ADC_H 0x64 +#define AXP20X_GPIO0_V_ADC_L 0x65 +#define AXP20X_GPIO1_V_ADC_H 0x66 +#define AXP20X_GPIO1_V_ADC_L 0x67 +#define AXP20X_PWR_BATT_H 0x70 +#define AXP20X_PWR_BATT_M 0x71 +#define AXP20X_PWR_BATT_L 0x72 +#define AXP20X_BATT_V_H 0x78 +#define AXP20X_BATT_V_L 0x79 +#define AXP20X_BATT_CHRG_I_H 0x7a +#define AXP20X_BATT_CHRG_I_L 0x7b +#define AXP20X_BATT_DISCHRG_I_H 0x7c +#define AXP20X_BATT_DISCHRG_I_L 0x7d +#define AXP20X_IPSOUT_V_HIGH_H 0x7e +#define AXP20X_IPSOUT_V_HIGH_L 0x7f + +/* Power supply */ +#define AXP20X_DCDC_MODE 0x80 +#define AXP20X_ADC_EN1 0x82 +#define AXP20X_ADC_EN2 0x83 +#define AXP20X_ADC_RATE 0x84 +#define AXP20X_GPIO10_IN_RANGE 0x85 +#define AXP20X_GPIO1_ADC_IRQ_RIS 0x86 +#define AXP20X_GPIO1_ADC_IRQ_FAL 0x87 +#define AXP20X_TIMER_CTRL 0x8a +#define AXP20X_VBUS_MON 0x8b +#define AXP20X_OVER_TMP 0x8f + +#define AXP22X_PWREN_CTRL1 0x8c +#define AXP22X_PWREN_CTRL2 0x8d + +/* GPIO */ +#define AXP152_GPIO0_CTRL 0x90 +#define AXP152_GPIO1_CTRL 0x91 +#define AXP152_GPIO2_CTRL 0x92 +#define AXP152_GPIO3_CTRL 0x93 +#define AXP152_LDOGPIO2_V_OUT 0x96 +#define AXP152_GPIO_INPUT 0x97 +#define AXP152_PWM0_FREQ_X 0x98 +#define AXP152_PWM0_FREQ_Y 0x99 +#define AXP152_PWM0_DUTY_CYCLE 0x9a +#define AXP152_PWM1_FREQ_X 0x9b +#define AXP152_PWM1_FREQ_Y 0x9c +#define AXP152_PWM1_DUTY_CYCLE 0x9d + +#define AXP20X_GPIO0_CTRL 0x90 +#define AXP20X_LDO5_V_OUT 0x91 +#define AXP20X_GPIO1_CTRL 0x92 +#define AXP20X_GPIO2_CTRL 0x93 +#define AXP20X_GPIO20_SS 0x94 +#define AXP20X_GPIO3_CTRL 0x95 + +#define AXP22X_LDO_IO0_V_OUT 0x91 +#define AXP22X_LDO_IO1_V_OUT 0x93 +#define AXP22X_GPIO_STATE 0x94 +#define AXP22X_GPIO_PULL_DOWN 0x95 + +/* Battery */ +#define AXP20X_CHRG_CC_31_24 0xb0 +#define AXP20X_CHRG_CC_23_16 0xb1 +#define AXP20X_CHRG_CC_15_8 0xb2 +#define AXP20X_CHRG_CC_7_0 0xb3 +#define AXP20X_DISCHRG_CC_31_24 0xb4 +#define AXP20X_DISCHRG_CC_23_16 0xb5 +#define AXP20X_DISCHRG_CC_15_8 0xb6 +#define AXP20X_DISCHRG_CC_7_0 0xb7 +#define AXP20X_CC_CTRL 0xb8 +#define AXP20X_FG_RES 0xb9 + +/* OCV */ +#define AXP20X_RDC_H 0xba +#define AXP20X_RDC_L 0xbb +#define AXP20X_OCV(m) (0xc0 + (m)) +#define AXP20X_OCV_MAX 0xf + +/* AXP22X specific registers */ +#define AXP22X_PMIC_TEMP_H 0x56 +#define AXP22X_PMIC_TEMP_L 0x57 +#define AXP22X_TS_ADC_H 0x58 +#define AXP22X_TS_ADC_L 0x59 +#define AXP22X_BATLOW_THRES1 0xe6 + +/* AXP288/AXP803 specific registers */ +#define AXP288_POWER_REASON 0x02 +#define AXP288_BC_GLOBAL 0x2c +#define AXP288_BC_VBUS_CNTL 0x2d +#define AXP288_BC_USB_STAT 0x2e +#define AXP288_BC_DET_STAT 0x2f +#define AXP288_PMIC_ADC_H 0x56 +#define AXP288_PMIC_ADC_L 0x57 +#define AXP288_TS_ADC_H 0x58 +#define AXP288_TS_ADC_L 0x59 +#define AXP288_GP_ADC_H 0x5a +#define AXP288_GP_ADC_L 0x5b +#define AXP288_ADC_TS_PIN_CTRL 0x84 +#define AXP288_RT_BATT_V_H 0xa0 +#define AXP288_RT_BATT_V_L 0xa1 + +#define AXP813_ACIN_PATH_CTRL 0x3a +#define AXP813_ADC_RATE 0x85 + +/* Fuel Gauge */ +#define AXP288_FG_RDC1_REG 0xba +#define AXP288_FG_RDC0_REG 0xbb +#define AXP288_FG_OCVH_REG 0xbc +#define AXP288_FG_OCVL_REG 0xbd +#define AXP288_FG_OCV_CURVE_REG 0xc0 +#define AXP288_FG_DES_CAP1_REG 0xe0 +#define AXP288_FG_DES_CAP0_REG 0xe1 +#define AXP288_FG_CC_MTR1_REG 0xe2 +#define AXP288_FG_CC_MTR0_REG 0xe3 +#define AXP288_FG_OCV_CAP_REG 0xe4 +#define AXP288_FG_CC_CAP_REG 0xe5 +#define AXP288_FG_LOW_CAP_REG 0xe6 +#define AXP288_FG_TUNE0 0xe8 +#define AXP288_FG_TUNE1 0xe9 +#define AXP288_FG_TUNE2 0xea +#define AXP288_FG_TUNE3 0xeb +#define AXP288_FG_TUNE4 0xec +#define AXP288_FG_TUNE5 0xed + +#define AXP313A_ON_INDICATE 0x00 +#define AXP313A_OFF_INDICATE 0x01 +#define AXP313A_IC_TYPE 0x03 +#define AXP313A_OUTPUT_CONTROL 0x10 +#define AXP313A_DCDC_DVM_PWM 0x12 +#define AXP313A_DCDC1_CONTROL 0x13 +#define AXP313A_DCDC2_CONTROL 0x14 +#define AXP313A_DCDC3_CONTROL 0x15 +#define AXP313A_ALDO1_CONTROL 0x16 +#define AXP313A_DLDO1_CONTROL 0x17 +#define AXP313A_POWER_STATUS 0x1A +#define AXP313A_PWROK_SET 0x1B +#define AXP313A_WAKEUP_CONRTOL 0x1C +#define AXP313A_OUTOUT_MONITOR 0x1D +#define AXP313A_POK_CONTROL 0x1E +#define AXP313A_IRQ_ENABLE1 0x20 +#define AXP313A_IRQ_STATUS1 0x21 + +/* Regulators IDs */ +enum { + AXP20X_LDO1 = 0, + AXP20X_LDO2, + AXP20X_LDO3, + AXP20X_LDO4, + AXP20X_LDO5, + AXP20X_DCDC2, + AXP20X_DCDC3, + AXP20X_REG_ID_MAX, +}; + +enum { + AXP22X_DCDC1 = 0, + AXP22X_DCDC2, + AXP22X_DCDC3, + AXP22X_DCDC4, + AXP22X_DCDC5, + AXP22X_DC1SW, + AXP22X_DC5LDO, + AXP22X_ALDO1, + AXP22X_ALDO2, + AXP22X_ALDO3, + AXP22X_ELDO1, + AXP22X_ELDO2, + AXP22X_ELDO3, + AXP22X_DLDO1, + AXP22X_DLDO2, + AXP22X_DLDO3, + AXP22X_DLDO4, + AXP22X_RTC_LDO, + AXP22X_LDO_IO0, + AXP22X_LDO_IO1, + AXP22X_REG_ID_MAX, +}; + +enum { + AXP313A_DCDC1 = 0, + AXP313A_DCDC2, + AXP313A_DCDC3, + AXP313A_LDO1, /* RTCLDO */ + AXP313A_LDO2, /* RTCLDO1 */ + AXP313A_REG_ID_MAX, +}; + +enum { + AXP806_DCDCA = 0, + AXP806_DCDCB, + AXP806_DCDCC, + AXP806_DCDCD, + AXP806_DCDCE, + AXP806_ALDO1, + AXP806_ALDO2, + AXP806_ALDO3, + AXP806_BLDO1, + AXP806_BLDO2, + AXP806_BLDO3, + AXP806_BLDO4, + AXP806_CLDO1, + AXP806_CLDO2, + AXP806_CLDO3, + AXP806_SW, + AXP806_REG_ID_MAX, +}; + +enum { + AXP809_DCDC1 = 0, + AXP809_DCDC2, + AXP809_DCDC3, + AXP809_DCDC4, + AXP809_DCDC5, + AXP809_DC1SW, + AXP809_DC5LDO, + AXP809_ALDO1, + AXP809_ALDO2, + AXP809_ALDO3, + AXP809_ELDO1, + AXP809_ELDO2, + AXP809_ELDO3, + AXP809_DLDO1, + AXP809_DLDO2, + AXP809_RTC_LDO, + AXP809_LDO_IO0, + AXP809_LDO_IO1, + AXP809_SW, + AXP809_REG_ID_MAX, +}; + +enum { + AXP803_DCDC1 = 0, + AXP803_DCDC2, + AXP803_DCDC3, + AXP803_DCDC4, + AXP803_DCDC5, + AXP803_DCDC6, + AXP803_DC1SW, + AXP803_ALDO1, + AXP803_ALDO2, + AXP803_ALDO3, + AXP803_DLDO1, + AXP803_DLDO2, + AXP803_DLDO3, + AXP803_DLDO4, + AXP803_ELDO1, + AXP803_ELDO2, + AXP803_ELDO3, + AXP803_FLDO1, + AXP803_FLDO2, + AXP803_RTC_LDO, + AXP803_LDO_IO0, + AXP803_LDO_IO1, + AXP803_REG_ID_MAX, +}; + +enum { + AXP813_DCDC1 = 0, + AXP813_DCDC2, + AXP813_DCDC3, + AXP813_DCDC4, + AXP813_DCDC5, + AXP813_DCDC6, + AXP813_DCDC7, + AXP813_ALDO1, + AXP813_ALDO2, + AXP813_ALDO3, + AXP813_DLDO1, + AXP813_DLDO2, + AXP813_DLDO3, + AXP813_DLDO4, + AXP813_ELDO1, + AXP813_ELDO2, + AXP813_ELDO3, + AXP813_FLDO1, + AXP813_FLDO2, + AXP813_FLDO3, + AXP813_RTC_LDO, + AXP813_LDO_IO0, + AXP813_LDO_IO1, + AXP813_SW, + AXP813_REG_ID_MAX, +}; + +struct regmap; +struct regmap_config; + +struct axp20x_dev { + struct device *dev; + struct regmap *regmap; + long variant; + int nr_cells; + const struct mfd_cell *cells; + const struct regmap_config *regmap_cfg; + struct poweroff_handler poweroff; +}; + +/** + * axp20x_match_device(): Setup axp20x variant related fields + * + * @axp20x: axp20x device to setup (.dev field must be set) + * @dev: device associated with this axp20x device + * + * This lets the axp20x core configure the mfd cells and register maps + * for later use. + */ +int axp20x_match_device(struct axp20x_dev *axp20x); + +/** + * axp20x_device_probe(): Probe a configured axp20x device + * + * @axp20x: axp20x device to probe (must be configured) + * + * This function lets the axp20x core register the axp20x mfd devices + * The axp20x device passed in must be fully configured + * with axp20x_match_device, and regmap created. + */ +int axp20x_device_probe(struct axp20x_dev *axp20x); + +#endif /* __LINUX_MFD_AXP20X_H */ diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h new file mode 100644 index 0000000000..18ff16a642 --- /dev/null +++ b/include/linux/mfd/core.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2006 Ian Molton + * Copyright (c) 2007 Dmitry Baryshkov + */ + +#ifndef MFD_CORE_H +#define MFD_CORE_H + +struct device; + +/* + * This struct describes the MFD part ("cell"). + * After registration the copy of this structure will become the platform data + * of the resulting device + */ +struct mfd_cell { + const char *name; +}; + +int mfd_add_devices(struct device *parent, const struct mfd_cell *cells, + int n_devs); + +#endif diff --git a/include/linux/mfd/rk808.h b/include/linux/mfd/rk808.h new file mode 100644 index 0000000000..d8e465f885 --- /dev/null +++ b/include/linux/mfd/rk808.h @@ -0,0 +1,721 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Register definitions for Rockchip's RK808/RK818 PMIC + * + * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd + * + * Author: Chris Zhong <zyw@rock-chips.com> + * Author: Zhang Qing <zhangqing@rock-chips.com> + * + * Copyright (C) 2016 PHYTEC Messtechnik GmbH + * + * Author: Wadim Egorov <w.egorov@phytec.de> + */ + +#ifndef __LINUX_REGULATOR_RK808_H +#define __LINUX_REGULATOR_RK808_H + +#include <linux/bitops.h> +#include <poweroff.h> + +/* + * rk808 Global Register Map. + */ + +#define RK808_DCDC1 0 /* (0+RK808_START) */ +#define RK808_LDO1 4 /* (4+RK808_START) */ +#define RK808_NUM_REGULATORS 14 + +enum rk808_reg { + RK808_ID_DCDC1, + RK808_ID_DCDC2, + RK808_ID_DCDC3, + RK808_ID_DCDC4, + RK808_ID_LDO1, + RK808_ID_LDO2, + RK808_ID_LDO3, + RK808_ID_LDO4, + RK808_ID_LDO5, + RK808_ID_LDO6, + RK808_ID_LDO7, + RK808_ID_LDO8, + RK808_ID_SWITCH1, + RK808_ID_SWITCH2, +}; + +#define RK808_SECONDS_REG 0x00 +#define RK808_MINUTES_REG 0x01 +#define RK808_HOURS_REG 0x02 +#define RK808_DAYS_REG 0x03 +#define RK808_MONTHS_REG 0x04 +#define RK808_YEARS_REG 0x05 +#define RK808_WEEKS_REG 0x06 +#define RK808_ALARM_SECONDS_REG 0x08 +#define RK808_ALARM_MINUTES_REG 0x09 +#define RK808_ALARM_HOURS_REG 0x0a +#define RK808_ALARM_DAYS_REG 0x0b +#define RK808_ALARM_MONTHS_REG 0x0c +#define RK808_ALARM_YEARS_REG 0x0d +#define RK808_RTC_CTRL_REG 0x10 +#define RK808_RTC_STATUS_REG 0x11 +#define RK808_RTC_INT_REG 0x12 +#define RK808_RTC_COMP_LSB_REG 0x13 +#define RK808_RTC_COMP_MSB_REG 0x14 +#define RK808_ID_MSB 0x17 +#define RK808_ID_LSB 0x18 +#define RK808_CLK32OUT_REG 0x20 +#define RK808_VB_MON_REG 0x21 +#define RK808_THERMAL_REG 0x22 +#define RK808_DCDC_EN_REG 0x23 +#define RK808_LDO_EN_REG 0x24 +#define RK808_SLEEP_SET_OFF_REG1 0x25 +#define RK808_SLEEP_SET_OFF_REG2 0x26 +#define RK808_DCDC_UV_STS_REG 0x27 +#define RK808_DCDC_UV_ACT_REG 0x28 +#define RK808_LDO_UV_STS_REG 0x29 +#define RK808_LDO_UV_ACT_REG 0x2a +#define RK808_DCDC_PG_REG 0x2b +#define RK808_LDO_PG_REG 0x2c +#define RK808_VOUT_MON_TDB_REG 0x2d +#define RK808_BUCK1_CONFIG_REG 0x2e +#define RK808_BUCK1_ON_VSEL_REG 0x2f +#define RK808_BUCK1_SLP_VSEL_REG 0x30 +#define RK808_BUCK1_DVS_VSEL_REG 0x31 +#define RK808_BUCK2_CONFIG_REG 0x32 +#define RK808_BUCK2_ON_VSEL_REG 0x33 +#define RK808_BUCK2_SLP_VSEL_REG 0x34 +#define RK808_BUCK2_DVS_VSEL_REG 0x35 +#define RK808_BUCK3_CONFIG_REG 0x36 +#define RK808_BUCK4_CONFIG_REG 0x37 +#define RK808_BUCK4_ON_VSEL_REG 0x38 +#define RK808_BUCK4_SLP_VSEL_REG 0x39 +#define RK808_BOOST_CONFIG_REG 0x3a +#define RK808_LDO1_ON_VSEL_REG 0x3b +#define RK808_LDO1_SLP_VSEL_REG 0x3c +#define RK808_LDO2_ON_VSEL_REG 0x3d +#define RK808_LDO2_SLP_VSEL_REG 0x3e +#define RK808_LDO3_ON_VSEL_REG 0x3f +#define RK808_LDO3_SLP_VSEL_REG 0x40 +#define RK808_LDO4_ON_VSEL_REG 0x41 +#define RK808_LDO4_SLP_VSEL_REG 0x42 +#define RK808_LDO5_ON_VSEL_REG 0x43 +#define RK808_LDO5_SLP_VSEL_REG 0x44 +#define RK808_LDO6_ON_VSEL_REG 0x45 +#define RK808_LDO6_SLP_VSEL_REG 0x46 +#define RK808_LDO7_ON_VSEL_REG 0x47 +#define RK808_LDO7_SLP_VSEL_REG 0x48 +#define RK808_LDO8_ON_VSEL_REG 0x49 +#define RK808_LDO8_SLP_VSEL_REG 0x4a +#define RK808_DEVCTRL_REG 0x4b +#define RK808_INT_STS_REG1 0x4c +#define RK808_INT_STS_MSK_REG1 0x4d +#define RK808_INT_STS_REG2 0x4e +#define RK808_INT_STS_MSK_REG2 0x4f +#define RK808_IO_POL_REG 0x50 + +/* RK818 */ +#define RK818_DCDC1 0 +#define RK818_LDO1 4 +#define RK818_NUM_REGULATORS 17 + +enum rk818_reg { + RK818_ID_DCDC1, + RK818_ID_DCDC2, + RK818_ID_DCDC3, + RK818_ID_DCDC4, + RK818_ID_BOOST, + RK818_ID_LDO1, + RK818_ID_LDO2, + RK818_ID_LDO3, + RK818_ID_LDO4, + RK818_ID_LDO5, + RK818_ID_LDO6, + RK818_ID_LDO7, + RK818_ID_LDO8, + RK818_ID_LDO9, + RK818_ID_SWITCH, + RK818_ID_HDMI_SWITCH, + RK818_ID_OTG_SWITCH, +}; + +#define RK818_DCDC_EN_REG 0x23 +#define RK818_LDO_EN_REG 0x24 +#define RK818_SLEEP_SET_OFF_REG1 0x25 +#define RK818_SLEEP_SET_OFF_REG2 0x26 +#define RK818_DCDC_UV_STS_REG 0x27 +#define RK818_DCDC_UV_ACT_REG 0x28 +#define RK818_LDO_UV_STS_REG 0x29 +#define RK818_LDO_UV_ACT_REG 0x2a +#define RK818_DCDC_PG_REG 0x2b +#define RK818_LDO_PG_REG 0x2c +#define RK818_VOUT_MON_TDB_REG 0x2d +#define RK818_BUCK1_CONFIG_REG 0x2e +#define RK818_BUCK1_ON_VSEL_REG 0x2f +#define RK818_BUCK1_SLP_VSEL_REG 0x30 +#define RK818_BUCK2_CONFIG_REG 0x32 +#define RK818_BUCK2_ON_VSEL_REG 0x33 +#define RK818_BUCK2_SLP_VSEL_REG 0x34 +#define RK818_BUCK3_CONFIG_REG 0x36 +#define RK818_BUCK4_CONFIG_REG 0x37 +#define RK818_BUCK4_ON_VSEL_REG 0x38 +#define RK818_BUCK4_SLP_VSEL_REG 0x39 +#define RK818_BOOST_CONFIG_REG 0x3a +#define RK818_LDO1_ON_VSEL_REG 0x3b +#define RK818_LDO1_SLP_VSEL_REG 0x3c +#define RK818_LDO2_ON_VSEL_REG 0x3d +#define RK818_LDO2_SLP_VSEL_REG 0x3e +#define RK818_LDO3_ON_VSEL_REG 0x3f +#define RK818_LDO3_SLP_VSEL_REG 0x40 +#define RK818_LDO4_ON_VSEL_REG 0x41 +#define RK818_LDO4_SLP_VSEL_REG 0x42 +#define RK818_LDO5_ON_VSEL_REG 0x43 +#define RK818_LDO5_SLP_VSEL_REG 0x44 +#define RK818_LDO6_ON_VSEL_REG 0x45 +#define RK818_LDO6_SLP_VSEL_REG 0x46 +#define RK818_LDO7_ON_VSEL_REG 0x47 +#define RK818_LDO7_SLP_VSEL_REG 0x48 +#define RK818_LDO8_ON_VSEL_REG 0x49 +#define RK818_LDO8_SLP_VSEL_REG 0x4a +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54 +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55 +#define RK818_DEVCTRL_REG 0x4b +#define RK818_INT_STS_REG1 0X4c +#define RK818_INT_STS_MSK_REG1 0x4d +#define RK818_INT_STS_REG2 0x4e +#define RK818_INT_STS_MSK_REG2 0x4f +#define RK818_IO_POL_REG 0x50 +#define RK818_H5V_EN_REG 0x52 +#define RK818_SLEEP_SET_OFF_REG3 0x53 +#define RK818_BOOST_LDO9_ON_VSEL_REG 0x54 +#define RK818_BOOST_LDO9_SLP_VSEL_REG 0x55 +#define RK818_BOOST_CTRL_REG 0x56 +#define RK818_DCDC_ILMAX 0x90 +#define RK818_USB_CTRL_REG 0xa1 + +#define RK818_H5V_EN BIT(0) +#define RK818_REF_RDY_CTRL BIT(1) +#define RK818_USB_ILIM_SEL_MASK 0xf +#define RK818_USB_ILMIN_2000MA 0x7 +#define RK818_USB_CHG_SD_VSEL_MASK 0x70 + +/* RK805 */ +enum rk805_reg { + RK805_ID_DCDC1, + RK805_ID_DCDC2, + RK805_ID_DCDC3, + RK805_ID_DCDC4, + RK805_ID_LDO1, + RK805_ID_LDO2, + RK805_ID_LDO3, +}; + +/* CONFIG REGISTER */ +#define RK805_VB_MON_REG 0x21 +#define RK805_THERMAL_REG 0x22 + +/* POWER CHANNELS ENABLE REGISTER */ +#define RK805_DCDC_EN_REG 0x23 +#define RK805_SLP_DCDC_EN_REG 0x25 +#define RK805_SLP_LDO_EN_REG 0x26 +#define RK805_LDO_EN_REG 0x27 + +/* BUCK AND LDO CONFIG REGISTER */ +#define RK805_BUCK_LDO_SLP_LP_EN_REG 0x2A +#define RK805_BUCK1_CONFIG_REG 0x2E +#define RK805_BUCK1_ON_VSEL_REG 0x2F +#define RK805_BUCK1_SLP_VSEL_REG 0x30 +#define RK805_BUCK2_CONFIG_REG 0x32 +#define RK805_BUCK2_ON_VSEL_REG 0x33 +#define RK805_BUCK2_SLP_VSEL_REG 0x34 +#define RK805_BUCK3_CONFIG_REG 0x36 +#define RK805_BUCK4_CONFIG_REG 0x37 +#define RK805_BUCK4_ON_VSEL_REG 0x38 +#define RK805_BUCK4_SLP_VSEL_REG 0x39 +#define RK805_LDO1_ON_VSEL_REG 0x3B +#define RK805_LDO1_SLP_VSEL_REG 0x3C +#define RK805_LDO2_ON_VSEL_REG 0x3D +#define RK805_LDO2_SLP_VSEL_REG 0x3E +#define RK805_LDO3_ON_VSEL_REG 0x3F +#define RK805_LDO3_SLP_VSEL_REG 0x40 + +/* INTERRUPT REGISTER */ +#define RK805_PWRON_LP_INT_TIME_REG 0x47 +#define RK805_PWRON_DB_REG 0x48 +#define RK805_DEV_CTRL_REG 0x4B +#define RK805_INT_STS_REG 0x4C +#define RK805_INT_STS_MSK_REG 0x4D +#define RK805_GPIO_IO_POL_REG 0x50 +#define RK805_OUT_REG 0x52 +#define RK805_ON_SOURCE_REG 0xAE +#define RK805_OFF_SOURCE_REG 0xAF + +#define RK805_NUM_REGULATORS 7 + +#define RK805_PWRON_FALL_RISE_INT_EN 0x0 +#define RK805_PWRON_FALL_RISE_INT_MSK 0x81 + +/* RK805 IRQ Definitions */ +#define RK805_IRQ_PWRON_RISE 0 +#define RK805_IRQ_VB_LOW 1 +#define RK805_IRQ_PWRON 2 +#define RK805_IRQ_PWRON_LP 3 +#define RK805_IRQ_HOTDIE 4 +#define RK805_IRQ_RTC_ALARM 5 +#define RK805_IRQ_RTC_PERIOD 6 +#define RK805_IRQ_PWRON_FALL 7 + +#define RK805_IRQ_PWRON_RISE_MSK BIT(0) +#define RK805_IRQ_VB_LOW_MSK BIT(1) +#define RK805_IRQ_PWRON_MSK BIT(2) +#define RK805_IRQ_PWRON_LP_MSK BIT(3) +#define RK805_IRQ_HOTDIE_MSK BIT(4) +#define RK805_IRQ_RTC_ALARM_MSK BIT(5) +#define RK805_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK805_IRQ_PWRON_FALL_MSK BIT(7) + +#define RK805_PWR_RISE_INT_STATUS BIT(0) +#define RK805_VB_LOW_INT_STATUS BIT(1) +#define RK805_PWRON_INT_STATUS BIT(2) +#define RK805_PWRON_LP_INT_STATUS BIT(3) +#define RK805_HOTDIE_INT_STATUS BIT(4) +#define RK805_ALARM_INT_STATUS BIT(5) +#define RK805_PERIOD_INT_STATUS BIT(6) +#define RK805_PWR_FALL_INT_STATUS BIT(7) + +#define RK805_BUCK1_2_ILMAX_MASK (3 << 6) +#define RK805_BUCK3_4_ILMAX_MASK (3 << 3) +#define RK805_RTC_PERIOD_INT_MASK (1 << 6) +#define RK805_RTC_ALARM_INT_MASK (1 << 5) +#define RK805_INT_ALARM_EN (1 << 3) +#define RK805_INT_TIMER_EN (1 << 2) + +/* RK808 IRQ Definitions */ +#define RK808_IRQ_VOUT_LO 0 +#define RK808_IRQ_VB_LO 1 +#define RK808_IRQ_PWRON 2 +#define RK808_IRQ_PWRON_LP 3 +#define RK808_IRQ_HOTDIE 4 +#define RK808_IRQ_RTC_ALARM 5 +#define RK808_IRQ_RTC_PERIOD 6 +#define RK808_IRQ_PLUG_IN_INT 7 +#define RK808_IRQ_PLUG_OUT_INT 8 +#define RK808_NUM_IRQ 9 + +#define RK808_IRQ_VOUT_LO_MSK BIT(0) +#define RK808_IRQ_VB_LO_MSK BIT(1) +#define RK808_IRQ_PWRON_MSK BIT(2) +#define RK808_IRQ_PWRON_LP_MSK BIT(3) +#define RK808_IRQ_HOTDIE_MSK BIT(4) +#define RK808_IRQ_RTC_ALARM_MSK BIT(5) +#define RK808_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK808_IRQ_PLUG_IN_INT_MSK BIT(0) +#define RK808_IRQ_PLUG_OUT_INT_MSK BIT(1) + +/* RK818 IRQ Definitions */ +#define RK818_IRQ_VOUT_LO 0 +#define RK818_IRQ_VB_LO 1 +#define RK818_IRQ_PWRON 2 +#define RK818_IRQ_PWRON_LP 3 +#define RK818_IRQ_HOTDIE 4 +#define RK818_IRQ_RTC_ALARM 5 +#define RK818_IRQ_RTC_PERIOD 6 +#define RK818_IRQ_USB_OV 7 +#define RK818_IRQ_PLUG_IN 8 +#define RK818_IRQ_PLUG_OUT 9 +#define RK818_IRQ_CHG_OK 10 +#define RK818_IRQ_CHG_TE 11 +#define RK818_IRQ_CHG_TS1 12 +#define RK818_IRQ_TS2 13 +#define RK818_IRQ_CHG_CVTLIM 14 +#define RK818_IRQ_DISCHG_ILIM 15 + +#define RK818_IRQ_VOUT_LO_MSK BIT(0) +#define RK818_IRQ_VB_LO_MSK BIT(1) +#define RK818_IRQ_PWRON_MSK BIT(2) +#define RK818_IRQ_PWRON_LP_MSK BIT(3) +#define RK818_IRQ_HOTDIE_MSK BIT(4) +#define RK818_IRQ_RTC_ALARM_MSK BIT(5) +#define RK818_IRQ_RTC_PERIOD_MSK BIT(6) +#define RK818_IRQ_USB_OV_MSK BIT(7) +#define RK818_IRQ_PLUG_IN_MSK BIT(0) +#define RK818_IRQ_PLUG_OUT_MSK BIT(1) +#define RK818_IRQ_CHG_OK_MSK BIT(2) +#define RK818_IRQ_CHG_TE_MSK BIT(3) +#define RK818_IRQ_CHG_TS1_MSK BIT(4) +#define RK818_IRQ_TS2_MSK BIT(5) +#define RK818_IRQ_CHG_CVTLIM_MSK BIT(6) +#define RK818_IRQ_DISCHG_ILIM_MSK BIT(7) + +#define RK818_NUM_IRQ 16 + +#define RK808_VBAT_LOW_2V8 0x00 +#define RK808_VBAT_LOW_2V9 0x01 +#define RK808_VBAT_LOW_3V0 0x02 +#define RK808_VBAT_LOW_3V1 0x03 +#define RK808_VBAT_LOW_3V2 0x04 +#define RK808_VBAT_LOW_3V3 0x05 +#define RK808_VBAT_LOW_3V4 0x06 +#define RK808_VBAT_LOW_3V5 0x07 +#define VBAT_LOW_VOL_MASK (0x07 << 0) +#define EN_VABT_LOW_SHUT_DOWN (0x00 << 4) +#define EN_VBAT_LOW_IRQ (0x1 << 4) +#define VBAT_LOW_ACT_MASK (0x1 << 4) + +#define BUCK_ILMIN_MASK (7 << 0) +#define BOOST_ILMIN_MASK (7 << 0) +#define BUCK1_RATE_MASK (3 << 3) +#define BUCK2_RATE_MASK (3 << 3) +#define MASK_ALL 0xff + +#define BUCK_UV_ACT_MASK 0x0f +#define BUCK_UV_ACT_DISABLE 0 + +#define SWITCH2_EN BIT(6) +#define SWITCH1_EN BIT(5) +#define DEV_OFF_RST BIT(3) +#define DEV_OFF BIT(0) +#define RTC_STOP BIT(0) + +#define VB_LO_ACT BIT(4) +#define VB_LO_SEL_3500MV (7 << 0) + +#define VOUT_LO_INT BIT(0) +#define CLK32KOUT2_EN BIT(0) + +#define TEMP115C 0x0c +#define TEMP_HOTDIE_MSK 0x0c +#define SLP_SD_MSK (0x3 << 2) +#define SHUTDOWN_FUN (0x2 << 2) +#define SLEEP_FUN (0x1 << 2) +#define RK8XX_ID_MSK 0xfff0 +#define PWM_MODE_MSK BIT(7) +#define FPWM_MODE BIT(7) +#define AUTO_PWM_MODE 0 + +enum rk817_reg_id { + RK817_ID_DCDC1 = 0, + RK817_ID_DCDC2, + RK817_ID_DCDC3, + RK817_ID_DCDC4, + RK817_ID_LDO1, + RK817_ID_LDO2, + RK817_ID_LDO3, + RK817_ID_LDO4, + RK817_ID_LDO5, + RK817_ID_LDO6, + RK817_ID_LDO7, + RK817_ID_LDO8, + RK817_ID_LDO9, + RK817_ID_BOOST, + RK817_ID_BOOST_OTG_SW, + RK817_NUM_REGULATORS +}; + +enum rk809_reg_id { + RK809_ID_DCDC1 = 0, + RK809_ID_DCDC2, + RK809_ID_DCDC3, + RK809_ID_DCDC4, + RK809_ID_LDO1, + RK809_ID_LDO2, + RK809_ID_LDO3, + RK809_ID_LDO4, + RK809_ID_LDO5, + RK809_ID_LDO6, + RK809_ID_LDO7, + RK809_ID_LDO8, + RK809_ID_LDO9, + RK809_ID_DCDC5, + RK809_ID_SW1, + RK809_ID_SW2, + RK809_NUM_REGULATORS +}; + +#define RK817_SECONDS_REG 0x00 +#define RK817_MINUTES_REG 0x01 +#define RK817_HOURS_REG 0x02 +#define RK817_DAYS_REG 0x03 +#define RK817_MONTHS_REG 0x04 +#define RK817_YEARS_REG 0x05 +#define RK817_WEEKS_REG 0x06 +#define RK817_ALARM_SECONDS_REG 0x07 +#define RK817_ALARM_MINUTES_REG 0x08 +#define RK817_ALARM_HOURS_REG 0x09 +#define RK817_ALARM_DAYS_REG 0x0a +#define RK817_ALARM_MONTHS_REG 0x0b +#define RK817_ALARM_YEARS_REG 0x0c +#define RK817_RTC_CTRL_REG 0xd +#define RK817_RTC_STATUS_REG 0xe +#define RK817_RTC_INT_REG 0xf +#define RK817_RTC_COMP_LSB_REG 0x10 +#define RK817_RTC_COMP_MSB_REG 0x11 + +/* RK817 Codec Registers */ +#define RK817_CODEC_DTOP_VUCTL 0x12 +#define RK817_CODEC_DTOP_VUCTIME 0x13 +#define RK817_CODEC_DTOP_LPT_SRST 0x14 +#define RK817_CODEC_DTOP_DIGEN_CLKE 0x15 +#define RK817_CODEC_AREF_RTCFG0 0x16 +#define RK817_CODEC_AREF_RTCFG1 0x17 +#define RK817_CODEC_AADC_CFG0 0x18 +#define RK817_CODEC_AADC_CFG1 0x19 +#define RK817_CODEC_DADC_VOLL 0x1a +#define RK817_CODEC_DADC_VOLR 0x1b +#define RK817_CODEC_DADC_SR_ACL0 0x1e +#define RK817_CODEC_DADC_ALC1 0x1f +#define RK817_CODEC_DADC_ALC2 0x20 +#define RK817_CODEC_DADC_NG 0x21 +#define RK817_CODEC_DADC_HPF 0x22 +#define RK817_CODEC_DADC_RVOLL 0x23 +#define RK817_CODEC_DADC_RVOLR 0x24 +#define RK817_CODEC_AMIC_CFG0 0x27 +#define RK817_CODEC_AMIC_CFG1 0x28 +#define RK817_CODEC_DMIC_PGA_GAIN 0x29 +#define RK817_CODEC_DMIC_LMT1 0x2a +#define RK817_CODEC_DMIC_LMT2 0x2b +#define RK817_CODEC_DMIC_NG1 0x2c +#define RK817_CODEC_DMIC_NG2 0x2d +#define RK817_CODEC_ADAC_CFG0 0x2e +#define RK817_CODEC_ADAC_CFG1 0x2f +#define RK817_CODEC_DDAC_POPD_DACST 0x30 +#define RK817_CODEC_DDAC_VOLL 0x31 +#define RK817_CODEC_DDAC_VOLR 0x32 +#define RK817_CODEC_DDAC_SR_LMT0 0x35 +#define RK817_CODEC_DDAC_LMT1 0x36 +#define RK817_CODEC_DDAC_LMT2 0x37 +#define RK817_CODEC_DDAC_MUTE_MIXCTL 0x38 +#define RK817_CODEC_DDAC_RVOLL 0x39 +#define RK817_CODEC_DDAC_RVOLR 0x3a +#define RK817_CODEC_AHP_ANTI0 0x3b +#define RK817_CODEC_AHP_ANTI1 0x3c +#define RK817_CODEC_AHP_CFG0 0x3d +#define RK817_CODEC_AHP_CFG1 0x3e +#define RK817_CODEC_AHP_CP 0x3f +#define RK817_CODEC_ACLASSD_CFG1 0x40 +#define RK817_CODEC_ACLASSD_CFG2 0x41 +#define RK817_CODEC_APLL_CFG0 0x42 +#define RK817_CODEC_APLL_CFG1 0x43 +#define RK817_CODEC_APLL_CFG2 0x44 +#define RK817_CODEC_APLL_CFG3 0x45 +#define RK817_CODEC_APLL_CFG4 0x46 +#define RK817_CODEC_APLL_CFG5 0x47 +#define RK817_CODEC_DI2S_CKM 0x48 +#define RK817_CODEC_DI2S_RSD 0x49 +#define RK817_CODEC_DI2S_RXCR1 0x4a +#define RK817_CODEC_DI2S_RXCR2 0x4b +#define RK817_CODEC_DI2S_RXCMD_TSD 0x4c +#define RK817_CODEC_DI2S_TXCR1 0x4d +#define RK817_CODEC_DI2S_TXCR2 0x4e +#define RK817_CODEC_DI2S_TXCR3_TXCMD 0x4f + +/* RK817_CODEC_DI2S_CKM */ +#define RK817_I2S_MODE_MASK (0x1 << 0) +#define RK817_I2S_MODE_MST (0x1 << 0) +#define RK817_I2S_MODE_SLV (0x0 << 0) + +/* RK817_CODEC_DDAC_MUTE_MIXCTL */ +#define DACMT_MASK (0x1 << 0) +#define DACMT_ENABLE (0x1 << 0) +#define DACMT_DISABLE (0x0 << 0) + +/* RK817_CODEC_DI2S_RXCR2 */ +#define VDW_RX_24BITS (0x17) +#define VDW_RX_16BITS (0x0f) + +/* RK817_CODEC_DI2S_TXCR2 */ +#define VDW_TX_24BITS (0x17) +#define VDW_TX_16BITS (0x0f) + +/* RK817_CODEC_AMIC_CFG0 */ +#define MIC_DIFF_MASK (0x1 << 7) +#define MIC_DIFF_DIS (0x0 << 7) +#define MIC_DIFF_EN (0x1 << 7) + +#define RK817_POWER_EN_REG(i) (0xb1 + (i)) +#define RK817_POWER_SLP_EN_REG(i) (0xb5 + (i)) + +#define RK817_POWER_CONFIG (0xb9) + +#define RK817_BUCK_CONFIG_REG(i) (0xba + (i) * 3) + +#define RK817_BUCK1_ON_VSEL_REG 0xBB +#define RK817_BUCK1_SLP_VSEL_REG 0xBC + +#define RK817_BUCK2_CONFIG_REG 0xBD +#define RK817_BUCK2_ON_VSEL_REG 0xBE +#define RK817_BUCK2_SLP_VSEL_REG 0xBF + +#define RK817_BUCK3_CONFIG_REG 0xC0 +#define RK817_BUCK3_ON_VSEL_REG 0xC1 +#define RK817_BUCK3_SLP_VSEL_REG 0xC2 + +#define RK817_BUCK4_CONFIG_REG 0xC3 +#define RK817_BUCK4_ON_VSEL_REG 0xC4 +#define RK817_BUCK4_SLP_VSEL_REG 0xC5 + +#define RK817_LDO_ON_VSEL_REG(idx) (0xcc + (idx) * 2) +#define RK817_BOOST_OTG_CFG (0xde) + +#define RK817_ID_MSB 0xed +#define RK817_ID_LSB 0xee + +#define RK817_SYS_STS 0xf0 +#define RK817_SYS_CFG(i) (0xf1 + (i)) + +#define RK817_ON_SOURCE_REG 0xf5 +#define RK817_OFF_SOURCE_REG 0xf6 + +/* INTERRUPT REGISTER */ +#define RK817_INT_STS_REG0 0xf8 +#define RK817_INT_STS_MSK_REG0 0xf9 +#define RK817_INT_STS_REG1 0xfa +#define RK817_INT_STS_MSK_REG1 0xfb +#define RK817_INT_STS_REG2 0xfc +#define RK817_INT_STS_MSK_REG2 0xfd +#define RK817_GPIO_INT_CFG 0xfe + +/* IRQ Definitions */ +#define RK817_IRQ_PWRON_FALL 0 +#define RK817_IRQ_PWRON_RISE 1 +#define RK817_IRQ_PWRON 2 +#define RK817_IRQ_PWMON_LP 3 +#define RK817_IRQ_HOTDIE 4 +#define RK817_IRQ_RTC_ALARM 5 +#define RK817_IRQ_RTC_PERIOD 6 +#define RK817_IRQ_VB_LO 7 +#define RK817_IRQ_PLUG_IN 8 +#define RK817_IRQ_PLUG_OUT 9 +#define RK817_IRQ_CHRG_TERM 10 +#define RK817_IRQ_CHRG_TIME 11 +#define RK817_IRQ_CHRG_TS 12 +#define RK817_IRQ_USB_OV 13 +#define RK817_IRQ_CHRG_IN_CLMP 14 +#define RK817_IRQ_BAT_DIS_ILIM 15 +#define RK817_IRQ_GATE_GPIO 16 +#define RK817_IRQ_TS_GPIO 17 +#define RK817_IRQ_CODEC_PD 18 +#define RK817_IRQ_CODEC_PO 19 +#define RK817_IRQ_CLASSD_MUTE_DONE 20 +#define RK817_IRQ_CLASSD_OCP 21 +#define RK817_IRQ_BAT_OVP 22 +#define RK817_IRQ_CHRG_BAT_HI 23 +#define RK817_IRQ_END (RK817_IRQ_CHRG_BAT_HI + 1) + +/* + * rtc_ctrl 0xd + * same as 808, except bit4 + */ +#define RK817_RTC_CTRL_RSV4 BIT(4) + +/* power config 0xb9 */ +#define RK817_BUCK3_FB_RES_MSK BIT(6) +#define RK817_BUCK3_FB_RES_INTER BIT(6) +#define RK817_BUCK3_FB_RES_EXT 0 + +/* buck config 0xba */ +#define RK817_RAMP_RATE_OFFSET 6 +#define RK817_RAMP_RATE_MASK (0x3 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_3MV_PER_US (0x0 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_6_3MV_PER_US (0x1 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_12_5MV_PER_US (0x2 << RK817_RAMP_RATE_OFFSET) +#define RK817_RAMP_RATE_25MV_PER_US (0x3 << RK817_RAMP_RATE_OFFSET) + +/* sys_cfg1 0xf2 */ +#define RK817_HOTDIE_TEMP_MSK (0x3 << 4) +#define RK817_HOTDIE_85 (0x0 << 4) +#define RK817_HOTDIE_95 (0x1 << 4) +#define RK817_HOTDIE_105 (0x2 << 4) +#define RK817_HOTDIE_115 (0x3 << 4) + +#define RK817_TSD_TEMP_MSK BIT(6) +#define RK817_TSD_140 0 +#define RK817_TSD_160 BIT(6) + +#define RK817_CLK32KOUT2_EN BIT(7) + +/* sys_cfg3 0xf4 */ +#define RK817_SLPPIN_FUNC_MSK (0x3 << 3) +#define SLPPIN_NULL_FUN (0x0 << 3) +#define SLPPIN_SLP_FUN (0x1 << 3) +#define SLPPIN_DN_FUN (0x2 << 3) +#define SLPPIN_RST_FUN (0x3 << 3) + +#define RK817_RST_FUNC_MSK (0x3 << 6) +#define RK817_RST_FUNC_SFT (6) +#define RK817_RST_FUNC_CNT (3) +#define RK817_RST_FUNC_DEV (0) /* reset the dev */ +#define RK817_RST_FUNC_REG (0x1 << 6) /* reset the reg only */ + +#define RK817_SLPPOL_MSK BIT(5) +#define RK817_SLPPOL_H BIT(5) +#define RK817_SLPPOL_L (0) + +/* gpio&int 0xfe */ +#define RK817_INT_POL_MSK BIT(1) +#define RK817_INT_POL_H BIT(1) +#define RK817_INT_POL_L 0 +#define RK809_BUCK5_CONFIG(i) (RK817_BOOST_OTG_CFG + (i) * 1) + +enum { + BUCK_ILMIN_50MA, + BUCK_ILMIN_100MA, + BUCK_ILMIN_150MA, + BUCK_ILMIN_200MA, + BUCK_ILMIN_250MA, + BUCK_ILMIN_300MA, + BUCK_ILMIN_350MA, + BUCK_ILMIN_400MA, +}; + +enum { + BOOST_ILMIN_75MA, + BOOST_ILMIN_100MA, + BOOST_ILMIN_125MA, + BOOST_ILMIN_150MA, + BOOST_ILMIN_175MA, + BOOST_ILMIN_200MA, + BOOST_ILMIN_225MA, + BOOST_ILMIN_250MA, +}; + +enum { + RK805_BUCK1_2_ILMAX_2500MA, + RK805_BUCK1_2_ILMAX_3000MA, + RK805_BUCK1_2_ILMAX_3500MA, + RK805_BUCK1_2_ILMAX_4000MA, +}; + +enum { + RK805_BUCK3_ILMAX_1500MA, + RK805_BUCK3_ILMAX_2000MA, + RK805_BUCK3_ILMAX_2500MA, + RK805_BUCK3_ILMAX_3000MA, +}; + +enum { + RK805_BUCK4_ILMAX_2000MA, + RK805_BUCK4_ILMAX_2500MA, + RK805_BUCK4_ILMAX_3000MA, + RK805_BUCK4_ILMAX_3500MA, +}; + +enum { + RK805_ID = 0x8050, + RK808_ID = 0x0000, + RK809_ID = 0x8090, + RK817_ID = 0x8170, + RK818_ID = 0x8180, +}; + +struct i2c_client; +struct regmap; +struct regmap_config; + +struct rk808 { + struct i2c_client *i2c; + struct regmap *regmap; + long variant; + const struct regmap_config *regmap_cfg; + struct poweroff_handler poweroff; +}; +#endif /* __LINUX_REGULATOR_RK808_H */ diff --git a/include/linux/mfd/stm32-timers.h b/include/linux/mfd/stm32-timers.h index 28fad44598..35aa0681ba 100644 --- a/include/linux/mfd/stm32-timers.h +++ b/include/linux/mfd/stm32-timers.h @@ -8,7 +8,6 @@ #define _LINUX_STM32_GPTIMER_H_ #include <clock.h> -#include <regmap.h> #define TIM_CR1 0x00 /* Control Register 1 */ #define TIM_CR2 0x04 /* Control Register 2 */ @@ -88,6 +87,8 @@ #define TIM_BDTR_BKF_SHIFT 16 #define TIM_BDTR_BK2F_SHIFT 20 +struct regmap; + struct stm32_timers { struct clk *clk; struct regmap *regmap; diff --git a/include/linux/mfd/syscon/atmel-matrix.h b/include/linux/mfd/syscon/atmel-matrix.h new file mode 100644 index 0000000000..20c2566521 --- /dev/null +++ b/include/linux/mfd/syscon/atmel-matrix.h @@ -0,0 +1,112 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2014 Atmel Corporation. + * + * Memory Controllers (MATRIX, EBI) - System peripherals registers. + */ + +#ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H +#define _LINUX_MFD_SYSCON_ATMEL_MATRIX_H + +#define AT91SAM9260_MATRIX_MCFG 0x00 +#define AT91SAM9260_MATRIX_SCFG 0x40 +#define AT91SAM9260_MATRIX_PRS 0x80 +#define AT91SAM9260_MATRIX_MRCR 0x100 +#define AT91SAM9260_MATRIX_EBICSA 0x11c + +#define AT91SAM9261_MATRIX_MRCR 0x0 +#define AT91SAM9261_MATRIX_SCFG 0x4 +#define AT91SAM9261_MATRIX_TCR 0x24 +#define AT91SAM9261_MATRIX_EBICSA 0x30 +#define AT91SAM9261_MATRIX_USBPUCR 0x34 + +#define AT91SAM9263_MATRIX_MCFG 0x00 +#define AT91SAM9263_MATRIX_SCFG 0x40 +#define AT91SAM9263_MATRIX_PRS 0x80 +#define AT91SAM9263_MATRIX_MRCR 0x100 +#define AT91SAM9263_MATRIX_TCR 0x114 +#define AT91SAM9263_MATRIX_EBI0CSA 0x120 +#define AT91SAM9263_MATRIX_EBI1CSA 0x124 + +#define AT91SAM9RL_MATRIX_MCFG 0x00 +#define AT91SAM9RL_MATRIX_SCFG 0x40 +#define AT91SAM9RL_MATRIX_PRS 0x80 +#define AT91SAM9RL_MATRIX_MRCR 0x100 +#define AT91SAM9RL_MATRIX_TCR 0x114 +#define AT91SAM9RL_MATRIX_EBICSA 0x120 + +#define AT91SAM9G45_MATRIX_MCFG 0x00 +#define AT91SAM9G45_MATRIX_SCFG 0x40 +#define AT91SAM9G45_MATRIX_PRS 0x80 +#define AT91SAM9G45_MATRIX_MRCR 0x100 +#define AT91SAM9G45_MATRIX_TCR 0x110 +#define AT91SAM9G45_MATRIX_DDRMPR 0x118 +#define AT91SAM9G45_MATRIX_EBICSA 0x128 + +#define AT91SAM9N12_MATRIX_MCFG 0x00 +#define AT91SAM9N12_MATRIX_SCFG 0x40 +#define AT91SAM9N12_MATRIX_PRS 0x80 +#define AT91SAM9N12_MATRIX_MRCR 0x100 +#define AT91SAM9N12_MATRIX_EBICSA 0x118 + +#define AT91SAM9X5_MATRIX_MCFG 0x00 +#define AT91SAM9X5_MATRIX_SCFG 0x40 +#define AT91SAM9X5_MATRIX_PRS 0x80 +#define AT91SAM9X5_MATRIX_MRCR 0x100 +#define AT91SAM9X5_MATRIX_EBICSA 0x120 + +#define SAMA5D3_MATRIX_MCFG 0x00 +#define SAMA5D3_MATRIX_SCFG 0x40 +#define SAMA5D3_MATRIX_PRS 0x80 +#define SAMA5D3_MATRIX_MRCR 0x100 + +#define AT91_MATRIX_MCFG(o, x) ((o) + ((x) * 0x4)) +#define AT91_MATRIX_ULBT GENMASK(2, 0) +#define AT91_MATRIX_ULBT_INFINITE (0 << 0) +#define AT91_MATRIX_ULBT_SINGLE (1 << 0) +#define AT91_MATRIX_ULBT_FOUR (2 << 0) +#define AT91_MATRIX_ULBT_EIGHT (3 << 0) +#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0) + +#define AT91_MATRIX_SCFG(o, x) ((o) + ((x) * 0x4)) +#define AT91_MATRIX_SLOT_CYCLE GENMASK(7, 0) +#define AT91_MATRIX_DEFMSTR_TYPE GENMASK(17, 16) +#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16) +#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16) +#define AT91_MATRIX_FIXED_DEFMSTR GENMASK(20, 18) +#define AT91_MATRIX_ARBT GENMASK(25, 24) +#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24) +#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24) + +#define AT91_MATRIX_ITCM_SIZE GENMASK(3, 0) +#define AT91_MATRIX_ITCM_0 (0 << 0) +#define AT91_MATRIX_ITCM_16 (5 << 0) +#define AT91_MATRIX_ITCM_32 (6 << 0) +#define AT91_MATRIX_ITCM_64 (7 << 0) +#define AT91_MATRIX_DTCM_SIZE GENMASK(7, 4) +#define AT91_MATRIX_DTCM_0 (0 << 4) +#define AT91_MATRIX_DTCM_16 (5 << 4) +#define AT91_MATRIX_DTCM_32 (6 << 4) +#define AT91_MATRIX_DTCM_64 (7 << 4) + +#define AT91_MATRIX_PRAS(o, x) ((o) + ((x) * 0x8)) +#define AT91_MATRIX_PRBS(o, x) ((o) + ((x) * 0x8) + 0x4) +#define AT91_MATRIX_MPR(x) GENMASK(((x) * 0x4) + 1, ((x) * 0x4)) + +#define AT91_MATRIX_RCB(x) BIT(x) + +#define AT91_MATRIX_CSA(cs, val) (val << (cs)) +#define AT91_MATRIX_DBPUC BIT(8) +#define AT91_MATRIX_DBPDC BIT(9) +#define AT91_MATRIX_VDDIOMSEL BIT(16) +#define AT91_MATRIX_VDDIOMSEL_1_8V (0 << 16) +#define AT91_MATRIX_VDDIOMSEL_3_3V (1 << 16) +#define AT91_MATRIX_EBI_IOSR BIT(17) +#define AT91_MATRIX_DDR_IOSR BIT(18) +#define AT91_MATRIX_NFD0_SELECT BIT(24) +#define AT91_MATRIX_DDR_MP_EN BIT(25) + +#define AT91_MATRIX_USBPUCR_PUON BIT(30) + +#endif /* _LINUX_MFD_SYSCON_ATMEL_MATRIX_H */ diff --git a/include/linux/mfd/syscon/atmel-smc.h b/include/linux/mfd/syscon/atmel-smc.h new file mode 100644 index 0000000000..16d09ea497 --- /dev/null +++ b/include/linux/mfd/syscon/atmel-smc.h @@ -0,0 +1,120 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Atmel SMC (Static Memory Controller) register offsets and bit definitions. + * + * Copyright (C) 2014 Atmel + * Copyright (C) 2014 Free Electrons + * + * Author: Boris Brezillon <boris.brezillon@free-electrons.com> + */ + +#ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_ +#define _LINUX_MFD_SYSCON_ATMEL_SMC_H_ + +#include <linux/kernel.h> +#include <of.h> + +#define ATMEL_SMC_SETUP(cs) (((cs) * 0x10)) +#define ATMEL_HSMC_SETUP(layout, cs) \ + ((layout)->timing_regs_offset + ((cs) * 0x14)) +#define ATMEL_SMC_PULSE(cs) (((cs) * 0x10) + 0x4) +#define ATMEL_HSMC_PULSE(layout, cs) \ + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0x4) +#define ATMEL_SMC_CYCLE(cs) (((cs) * 0x10) + 0x8) +#define ATMEL_HSMC_CYCLE(layout, cs) \ + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0x8) +#define ATMEL_SMC_NWE_SHIFT 0 +#define ATMEL_SMC_NCS_WR_SHIFT 8 +#define ATMEL_SMC_NRD_SHIFT 16 +#define ATMEL_SMC_NCS_RD_SHIFT 24 + +#define ATMEL_SMC_MODE(cs) (((cs) * 0x10) + 0xc) +#define ATMEL_HSMC_MODE(layout, cs) \ + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0x10) +#define ATMEL_SMC_MODE_READMODE_MASK BIT(0) +#define ATMEL_SMC_MODE_READMODE_NCS (0 << 0) +#define ATMEL_SMC_MODE_READMODE_NRD (1 << 0) +#define ATMEL_SMC_MODE_WRITEMODE_MASK BIT(1) +#define ATMEL_SMC_MODE_WRITEMODE_NCS (0 << 1) +#define ATMEL_SMC_MODE_WRITEMODE_NWE (1 << 1) +#define ATMEL_SMC_MODE_EXNWMODE_MASK GENMASK(5, 4) +#define ATMEL_SMC_MODE_EXNWMODE_DISABLE (0 << 4) +#define ATMEL_SMC_MODE_EXNWMODE_FROZEN (2 << 4) +#define ATMEL_SMC_MODE_EXNWMODE_READY (3 << 4) +#define ATMEL_SMC_MODE_BAT_MASK BIT(8) +#define ATMEL_SMC_MODE_BAT_SELECT (0 << 8) +#define ATMEL_SMC_MODE_BAT_WRITE (1 << 8) +#define ATMEL_SMC_MODE_DBW_MASK GENMASK(13, 12) +#define ATMEL_SMC_MODE_DBW_8 (0 << 12) +#define ATMEL_SMC_MODE_DBW_16 (1 << 12) +#define ATMEL_SMC_MODE_DBW_32 (2 << 12) +#define ATMEL_SMC_MODE_TDF_MASK GENMASK(19, 16) +#define ATMEL_SMC_MODE_TDF(x) (((x) - 1) << 16) +#define ATMEL_SMC_MODE_TDF_MAX 16 +#define ATMEL_SMC_MODE_TDF_MIN 1 +#define ATMEL_SMC_MODE_TDFMODE_OPTIMIZED BIT(20) +#define ATMEL_SMC_MODE_PMEN BIT(24) +#define ATMEL_SMC_MODE_PS_MASK GENMASK(29, 28) +#define ATMEL_SMC_MODE_PS_4 (0 << 28) +#define ATMEL_SMC_MODE_PS_8 (1 << 28) +#define ATMEL_SMC_MODE_PS_16 (2 << 28) +#define ATMEL_SMC_MODE_PS_32 (3 << 28) + +#define ATMEL_HSMC_TIMINGS(layout, cs) \ + ((layout)->timing_regs_offset + ((cs) * 0x14) + 0xc) +#define ATMEL_HSMC_TIMINGS_OCMS BIT(12) +#define ATMEL_HSMC_TIMINGS_RBNSEL(x) ((x) << 28) +#define ATMEL_HSMC_TIMINGS_NFSEL BIT(31) +#define ATMEL_HSMC_TIMINGS_TCLR_SHIFT 0 +#define ATMEL_HSMC_TIMINGS_TADL_SHIFT 4 +#define ATMEL_HSMC_TIMINGS_TAR_SHIFT 8 +#define ATMEL_HSMC_TIMINGS_TRR_SHIFT 16 +#define ATMEL_HSMC_TIMINGS_TWB_SHIFT 24 + +struct atmel_hsmc_reg_layout { + unsigned int timing_regs_offset; +}; + +/** + * struct atmel_smc_cs_conf - SMC CS config as described in the datasheet. + * @setup: NCS/NWE/NRD setup timings (not applicable to at91rm9200) + * @pulse: NCS/NWE/NRD pulse timings (not applicable to at91rm9200) + * @cycle: NWE/NRD cycle timings (not applicable to at91rm9200) + * @timings: advanced NAND related timings (only applicable to HSMC) + * @mode: all kind of config parameters (see the fields definition above). + * The mode fields are different on at91rm9200 + */ +struct atmel_smc_cs_conf { + u32 setup; + u32 pulse; + u32 cycle; + u32 timings; + u32 mode; +}; + +struct regmap; + +void atmel_smc_cs_conf_init(struct atmel_smc_cs_conf *conf); +int atmel_smc_cs_conf_set_timing(struct atmel_smc_cs_conf *conf, + unsigned int shift, + unsigned int ncycles); +int atmel_smc_cs_conf_set_setup(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles); +int atmel_smc_cs_conf_set_pulse(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles); +int atmel_smc_cs_conf_set_cycle(struct atmel_smc_cs_conf *conf, + unsigned int shift, unsigned int ncycles); +void atmel_smc_cs_conf_apply(struct regmap *regmap, int cs, + const struct atmel_smc_cs_conf *conf); +void atmel_hsmc_cs_conf_apply(struct regmap *regmap, + const struct atmel_hsmc_reg_layout *reglayout, + int cs, const struct atmel_smc_cs_conf *conf); +void atmel_smc_cs_conf_get(struct regmap *regmap, int cs, + struct atmel_smc_cs_conf *conf); +void atmel_hsmc_cs_conf_get(struct regmap *regmap, + const struct atmel_hsmc_reg_layout *reglayout, + int cs, struct atmel_smc_cs_conf *conf); +const struct atmel_hsmc_reg_layout * +atmel_hsmc_get_reg_layout(struct device_node *np); + +#endif /* _LINUX_MFD_SYSCON_ATMEL_SMC_H_ */ diff --git a/include/linux/micrel_phy.h b/include/linux/micrel_phy.h index 8752dbbc61..591bf5b5e8 100644 --- a/include/linux/micrel_phy.h +++ b/include/linux/micrel_phy.h @@ -1,26 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /* * include/linux/micrel_phy.h * * Micrel PHY IDs - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * */ #ifndef _MICREL_PHY_H #define _MICREL_PHY_H +#define MICREL_OUI 0x0885 + #define MICREL_PHY_ID_MASK 0x00fffff0 #define PHY_ID_KSZ8873MLL 0x000e7237 #define PHY_ID_KSZ9021 0x00221610 +#define PHY_ID_KSZ9021RLRN 0x00221611 #define PHY_ID_KS8737 0x00221720 #define PHY_ID_KSZ8021 0x00221555 #define PHY_ID_KSZ8031 0x00221556 #define PHY_ID_KSZ8041 0x00221510 +/* undocumented */ +#define PHY_ID_KSZ8041RNLI 0x00221537 #define PHY_ID_KSZ8051 0x00221550 /* same id: ks8001 Rev. A/B, and ks8721 Rev 3. */ #define PHY_ID_KSZ8001 0x0022161A @@ -28,11 +28,46 @@ #define PHY_ID_KSZ8081 0x00221560 #define PHY_ID_KSZ8061 0x00221570 #define PHY_ID_KSZ9031 0x00221620 +#define PHY_ID_KSZ9131 0x00221640 +#define PHY_ID_LAN8814 0x00221660 +#define PHY_ID_LAN8804 0x00221670 +#define PHY_ID_LAN8841 0x00221650 #define PHY_ID_KSZ886X 0x00221430 #define PHY_ID_KSZ8863 0x00221435 +#define PHY_ID_KSZ87XX 0x00221550 + +#define PHY_ID_KSZ9477 0x00221631 + /* struct phy_device dev_flags definitions */ -#define MICREL_PHY_50MHZ_CLK 0x00000001 +#define MICREL_PHY_50MHZ_CLK BIT(0) +#define MICREL_PHY_FXEN BIT(1) +#define MICREL_KSZ8_P1_ERRATA BIT(2) +#define MICREL_NO_EEE BIT(3) + +#define MICREL_KSZ9021_EXTREG_CTRL 0xB +#define MICREL_KSZ9021_EXTREG_DATA_WRITE 0xC +#define MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW 0x104 +#define MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW 0x105 + +/* Device specific MII_BMCR (Reg 0) bits */ +/* 1 = HP Auto MDI/MDI-X mode, 0 = Microchip Auto MDI/MDI-X mode */ +#define KSZ886X_BMCR_HP_MDIX BIT(5) +/* 1 = Force MDI (transmit on RXP/RXM pins), 0 = Normal operation + * (transmit on TXP/TXM pins) + */ +#define KSZ886X_BMCR_FORCE_MDI BIT(4) +/* 1 = Disable auto MDI-X */ +#define KSZ886X_BMCR_DISABLE_AUTO_MDIX BIT(3) +#define KSZ886X_BMCR_DISABLE_FAR_END_FAULT BIT(2) +#define KSZ886X_BMCR_DISABLE_TRANSMIT BIT(1) +#define KSZ886X_BMCR_DISABLE_LED BIT(0) + +/* PHY Special Control/Status Register (Reg 31) */ +#define KSZ886X_CTRL_MDIX_STAT BIT(4) +#define KSZ886X_CTRL_FORCE_LINK BIT(3) +#define KSZ886X_CTRL_PWRSAVE BIT(2) +#define KSZ886X_CTRL_REMOTE_LOOPBACK BIT(1) #endif /* _MICREL_PHY_H */ diff --git a/include/linux/mii.h b/include/linux/mii.h index 5bac6c229a..257dfd1790 100644 --- a/include/linux/mii.h +++ b/include/linux/mii.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * linux/mii.h: definitions for MII-compatible transceivers * Originally drivers/net/sunhme.h. diff --git a/include/linux/minmax.h b/include/linux/minmax.h new file mode 100644 index 0000000000..9b6ddad7b3 --- /dev/null +++ b/include/linux/minmax.h @@ -0,0 +1,189 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_MINMAX_H +#define _LINUX_MINMAX_H + +#include <linux/const.h> + +/* + * min()/max()/clamp() macros must accomplish three things: + * + * - avoid multiple evaluations of the arguments (so side-effects like + * "x++" happen only once) when non-constant. + * - perform strict type-checking (to generate warnings instead of + * nasty runtime surprises). See the "unnecessary" pointer comparison + * in __typecheck(). + * - retain result as a constant expressions when called with only + * constant expressions (to avoid tripping VLA warnings in stack + * allocation usage). + */ +#define __typecheck(x, y) \ + (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) + +#define __no_side_effects(x, y) \ + (__is_constexpr(x) && __is_constexpr(y)) + +#define __safe_cmp(x, y) \ + (__typecheck(x, y) && __no_side_effects(x, y)) + +#define __cmp(x, y, op) ((x) op (y) ? (x) : (y)) + +#define __cmp_once(x, y, unique_x, unique_y, op) ({ \ + typeof(x) unique_x = (x); \ + typeof(y) unique_y = (y); \ + __cmp(unique_x, unique_y, op); }) + +#define __careful_cmp(x, y, op) \ + __builtin_choose_expr(__safe_cmp(x, y), \ + __cmp(x, y, op), \ + __cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op)) + +#define __clamp(val, lo, hi) \ + ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val))) + +#define __clamp_once(val, lo, hi, unique_val, unique_lo, unique_hi) ({ \ + typeof(val) unique_val = (val); \ + typeof(lo) unique_lo = (lo); \ + typeof(hi) unique_hi = (hi); \ + __clamp(unique_val, unique_lo, unique_hi); }) + +#define __clamp_input_check(lo, hi) \ + (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \ + __is_constexpr((lo) > (hi)), (lo) > (hi), false))) + +#define __careful_clamp(val, lo, hi) ({ \ + __clamp_input_check(lo, hi) + \ + __builtin_choose_expr(__typecheck(val, lo) && __typecheck(val, hi) && \ + __typecheck(hi, lo) && __is_constexpr(val) && \ + __is_constexpr(lo) && __is_constexpr(hi), \ + __clamp(val, lo, hi), \ + __clamp_once(val, lo, hi, __UNIQUE_ID(__val), \ + __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); }) + +/** + * min - return minimum of two values of the same or compatible types + * @x: first value + * @y: second value + */ +#define min(x, y) __careful_cmp(x, y, <) + +/** + * max - return maximum of two values of the same or compatible types + * @x: first value + * @y: second value + */ +#define max(x, y) __careful_cmp(x, y, >) + +/** + * min3 - return minimum of three values + * @x: first value + * @y: second value + * @z: third value + */ +#define min3(x, y, z) min((typeof(x))min(x, y), z) + +/** + * max3 - return maximum of three values + * @x: first value + * @y: second value + * @z: third value + */ +#define max3(x, y, z) max((typeof(x))max(x, y), z) + +/** + * min_not_zero - return the minimum that is _not_ zero, unless both are zero + * @x: value1 + * @y: value2 + */ +#define min_not_zero(x, y) ({ \ + typeof(x) __x = (x); \ + typeof(y) __y = (y); \ + __x == 0 ? __y : ((__y == 0) ? __x : min(__x, __y)); }) + +/** + * clamp - return a value clamped to a given range with strict typechecking + * @val: current value + * @lo: lowest allowable value + * @hi: highest allowable value + * + * This macro does strict typechecking of @lo/@hi to make sure they are of the + * same type as @val. See the unnecessary pointer comparisons. + */ +#define clamp(val, lo, hi) __careful_clamp(val, lo, hi) + +/* + * ..and if you can't take the strict + * types, you can specify one yourself. + * + * Or not use min/max/clamp at all, of course. + */ + +/** + * min_t - return minimum of two values, using the specified type + * @type: data type to use + * @x: first value + * @y: second value + */ +#define min_t(type, x, y) __careful_cmp((type)(x), (type)(y), <) + +/** + * max_t - return maximum of two values, using the specified type + * @type: data type to use + * @x: first value + * @y: second value + */ +#define max_t(type, x, y) __careful_cmp((type)(x), (type)(y), >) + +/** + * clamp_t - return a value clamped to a given range using a given type + * @type: the type of variable to use + * @val: current value + * @lo: minimum allowable value + * @hi: maximum allowable value + * + * This macro does no typechecking and uses temporary variables of type + * @type to make all the comparisons. + */ +#define clamp_t(type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi)) + +/** + * clamp_val - return a value clamped to a given range using val's type + * @val: current value + * @lo: minimum allowable value + * @hi: maximum allowable value + * + * This macro does no typechecking and uses temporary variables of whatever + * type the input argument @val is. This is useful when @val is an unsigned + * type and @lo and @hi are literals that will otherwise be assigned a signed + * integer type. + */ +#define clamp_val(val, lo, hi) clamp_t(typeof(val), val, lo, hi) + +/** + * swap - swap values of @a and @b + * @a: first value + * @b: second value + */ +#define swap(a, b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) + + +#define __compare3(x, y) ((x) < (y) ? -1 : (x) > (y) ? 1 : 0) + +#define __compare3_once(x, y, unique_x, unique_y) ({ \ + typeof(x) unique_x = (x); \ + typeof(y) unique_y = (y); \ + __compare3(unique_x, unique_y); }) + +/** + * compare3 - 3-way comparison of @x and @y + * @x: first value + * @y: second value + * + * returns -1 if x < y, 0 if x == y and 1 if x > y + */ +#define compare3(x, y) \ + __builtin_choose_expr(__safe_cmp(x, y), \ + __compare3(x, y), \ + __compare3_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y))) + +#endif /* _LINUX_MINMAX_H */ diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index 2c04454260..4d3feb17e5 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * Device tables which are exported to userspace via * scripts/mod/file2alias.c. You must keep that file in sync with this @@ -8,6 +10,7 @@ #define LINUX_MOD_DEVICETABLE_H #include <linux/types.h> +#include <linux/uuid.h> #define PCI_ANY_ID (~0) @@ -25,4 +28,13 @@ struct spi_device_id { unsigned long driver_data; }; +/** + * struct tee_client_device_id - tee based device identifier + * @uuid: For TEE based client devices we use the device uuid as + * the identifier. + */ +struct tee_client_device_id { + uuid_t uuid; +}; + #endif /* LINUX_MOD_DEVICETABLE_H */ diff --git a/include/linux/mount.h b/include/linux/mount.h index 9557365fb5..4abeda6b79 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * * Definitions for mount interface. This describes the in the kernel build diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h index b7a8955880..b74f4b8348 100644 --- a/include/linux/mtd/mtd-abi.h +++ b/include/linux/mtd/mtd-abi.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $ * diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index f9c4645180..54cb2ec64c 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -225,7 +225,7 @@ struct mtd_info { int (*_get_device) (struct mtd_info *mtd); void (*_put_device) (struct mtd_info *mtd); - struct device_d dev; + struct device dev; struct cdev cdev; struct cdev *cdev_bb; @@ -288,15 +288,17 @@ int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops); static inline void mtd_set_of_node(struct mtd_info *mtd, struct device_node *np) { - mtd->dev.device_node = np; + mtd->dev.of_node = np; } static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd) { - if (mtd->dev.device_node) - return mtd->dev.device_node; + if (!IS_ENABLED(CONFIG_OFDEVICE)) + return NULL; + if (mtd->dev.of_node) + return mtd->dev.of_node; if (mtd->dev.parent) - return mtd->dev.parent->device_node; + return mtd->dev.parent->of_node; return NULL; } diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 876849e7e8..6ce5c1d041 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -166,10 +166,18 @@ struct nand_ops { }; /** + * struct nand_ecc - Information relative to the ECC + * @requirements: ECC requirements from the NAND chip perspective + */ +struct nand_ecc { + struct nand_ecc_props requirements; +}; + +/** * struct nand_device - NAND device * @mtd: MTD instance attached to the NAND device * @memorg: memory layout - * @eccreq: ECC requirements + * @ecc: ECC information * @rowconv: position to row address converter * @bbt: bad block table info * @ops: NAND operations attached to the NAND device @@ -177,8 +185,8 @@ struct nand_ops { * Generic NAND object. Specialized NAND layers (raw NAND, SPI NAND, OneNAND) * should declare their own NAND object embedding a nand_device struct (that's * how inheritance is done). - * struct_nand_device->memorg and struct_nand_device->eccreq should be filled - * at device detection time to reflect the NAND device + * struct_nand_device->memorg and struct_nand_device->ecc.requirement should + * be filled at device detection time to reflect the NAND device * capabilities/requirements. Once this is done nanddev_init() can be called. * It will take care of converting NAND information into MTD ones, which means * the specialized NAND layers should never manually tweak @@ -187,7 +195,7 @@ struct nand_ops { struct nand_device { struct mtd_info mtd; struct nand_memory_organization memorg; - struct nand_ecc_props eccreq; + struct nand_ecc ecc; struct nand_row_converter rowconv; struct nand_bbt bbt; const struct nand_ops *ops; @@ -396,6 +404,17 @@ int nanddev_init(struct nand_device *nand, const struct nand_ops *ops, void nanddev_cleanup(struct nand_device *nand); /** + * nanddev_get_ecc_requirements() - Extract the ECC requirements from a NAND + * device + * @nand: NAND device + */ +static inline const struct nand_ecc_props * +nanddev_get_ecc_requirements(struct nand_device *nand) +{ + return &nand->ecc.requirements; +} + +/** * nanddev_offs_to_pos() - Convert an absolute NAND offset into a NAND position * @nand: NAND device * @offs: absolute NAND offset (usually passed by the MTD layer) diff --git a/include/linux/mtd/nand_mxs.h b/include/linux/mtd/nand_mxs.h index 7eda0b8e63..4c1e90d6f0 100644 --- a/include/linux/mtd/nand_mxs.h +++ b/include/linux/mtd/nand_mxs.h @@ -28,5 +28,9 @@ */ int mxs_nand_get_geo(int *ecc_strength, int *bb_mark_bit_offset); +int mxs_nand_read_fcb_bch62(unsigned int block, void *buf, size_t size); +int mxs_nand_write_fcb_bch62(unsigned int block, void *buf, size_t size); + +struct mtd_info; #endif /* __NAND_MXS_H */ diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h index 438130625d..36b80dea77 100644 --- a/include/linux/mtd/nftl.h +++ b/include/linux/mtd/nftl.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* Defines for NAND Flash Translation Layer */ /* (c) 1999 Machine Vision Holdings, Inc. */ diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h index 1147f235a6..54a788cc18 100644 --- a/include/linux/mtd/rawnand.h +++ b/include/linux/mtd/rawnand.h @@ -95,11 +95,27 @@ enum nand_ecc_mode { NAND_ECC_SOFT_BCH }; +/** + * enum nand_ecc_engine_type - NAND ECC engine type + * @NAND_ECC_ENGINE_TYPE_INVALID: Invalid value + * @NAND_ECC_ENGINE_TYPE_NONE: No ECC correction + * @NAND_ECC_ENGINE_TYPE_SOFT: Software ECC correction + * @NAND_ECC_ENGINE_TYPE_ON_HOST: On host hardware ECC correction + * @NAND_ECC_ENGINE_TYPE_ON_DIE: On chip hardware ECC correction + */ +enum nand_ecc_engine_type { + NAND_ECC_ENGINE_TYPE_INVALID, + NAND_ECC_ENGINE_TYPE_NONE, + NAND_ECC_ENGINE_TYPE_SOFT, + NAND_ECC_ENGINE_TYPE_ON_HOST, + NAND_ECC_ENGINE_TYPE_ON_DIE, +}; + enum nand_ecc_algo { - NAND_ECC_UNKNOWN, - NAND_ECC_HAMMING, - NAND_ECC_BCH, - NAND_ECC_RS, + NAND_ECC_ALGO_UNKNOWN, + NAND_ECC_ALGO_HAMMING, + NAND_ECC_ALGO_BCH, + NAND_ECC_ALGO_RS, }; /* @@ -313,6 +329,7 @@ static const struct nand_ecc_caps __name = { \ /** * struct nand_ecc_ctrl - Control structure for ECC + * @engine_type: ECC engine type * @mode: ECC mode * @algo: ECC algorithm * @steps: number of ECC steps per page @@ -365,6 +382,7 @@ static const struct nand_ecc_caps __name = { \ * @write_oob: function to write chip OOB data */ struct nand_ecc_ctrl { + enum nand_ecc_engine_type engine_type; enum nand_ecc_mode mode; enum nand_ecc_algo algo; int steps; @@ -520,13 +538,22 @@ struct nand_interface_config { }; /** + * nand_interface_is_sdr - get the interface type + * @conf: The data interface + */ +static bool nand_interface_is_sdr(const struct nand_interface_config *conf) +{ + return conf->type == NAND_SDR_IFACE; +} + +/** * nand_get_sdr_timings - get SDR timing from data interface * @conf: The data interface */ static inline const struct nand_sdr_timings * nand_get_sdr_timings(const struct nand_interface_config *conf) { - if (conf->type != NAND_SDR_IFACE) + if (!nand_interface_is_sdr(conf)) return ERR_PTR(-EINVAL); return &conf->timings.sdr; @@ -1168,8 +1195,8 @@ struct nand_chip { unsigned int bbt_type; }; -extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops; -extern const struct mtd_ooblayout_ops nand_ooblayout_lp_ops; +const struct mtd_ooblayout_ops *nand_get_small_page_ooblayout(void); +const struct mtd_ooblayout_ops *nand_get_large_page_ooblayout(void); static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd) { @@ -1409,11 +1436,15 @@ void nand_wait_ready(struct nand_chip *chip); */ void nand_cleanup(struct nand_chip *chip); +struct gpio_desc; + /* * External helper for controller drivers that have to implement the WAITRDY * instruction and have no physical pin to check it. */ int nand_soft_waitrdy(struct nand_chip *chip, unsigned long timeout_ms); +int nand_gpio_waitrdy(struct nand_chip *chip, struct gpio_desc *gpio, + unsigned long timeout_ms); /* Select/deselect a NAND target. */ void nand_select_target(struct nand_chip *chip, unsigned int cs); diff --git a/include/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h index 1c6f442866..720b4888d4 100644 --- a/include/linux/mtd/spi-nor.h +++ b/include/linux/mtd/spi-nor.h @@ -142,6 +142,8 @@ SNOR_PROTO_ADDR(_addr_nbits) | \ SNOR_PROTO_DATA(_data_nbits)) +#define SPI_NOR_MAX_ADDR_WIDTH 4 + enum spi_nor_protocol { SNOR_PROTO_1_1_1 = SNOR_PROTO_STR(1, 1, 1), SNOR_PROTO_1_1_2 = SNOR_PROTO_STR(1, 1, 2), @@ -222,7 +224,7 @@ enum spi_nor_option_flags { struct spi_nor { struct mtd_info *mtd; struct mutex lock; - struct device_d *dev; + struct device *dev; const struct flash_info *info; u32 page_size; u8 addr_width; diff --git a/include/linux/mutex.h b/include/linux/mutex.h index de698dbc4f..f511c45814 100644 --- a/include/linux/mutex.h +++ b/include/linux/mutex.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * Mutexes: blocking mutual exclusion locks * @@ -18,4 +20,6 @@ #define mutex_is_locked(...) 0 struct mutex { int i; }; +#define DEFINE_MUTEX(obj) struct mutex __always_unused obj + #endif /* __LINUX_MUTEX_H */ diff --git a/include/linux/namei.h b/include/linux/namei.h index 9f6e568591..29c3460ace 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -19,30 +19,17 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; * - follow links at the end * - require a directory * - ending slashes ok even for nonexistent files - * - internal "there are more path components" flag - * - dentry cache is untrusted; force a real lookup - * - suppress terminal automount */ #define LOOKUP_FOLLOW 0x0001 #define LOOKUP_DIRECTORY 0x0002 #define LOOKUP_AUTOMOUNT 0x0004 #define LOOKUP_PARENT 0x0010 -#define LOOKUP_REVAL 0x0020 -#define LOOKUP_RCU 0x0040 -#define LOOKUP_NO_REVAL 0x0080 /* * Intent data */ -#define LOOKUP_OPEN 0x0100 -#define LOOKUP_CREATE 0x0200 -#define LOOKUP_EXCL 0x0400 -#define LOOKUP_RENAME_TARGET 0x0800 #define LOOKUP_JUMPED 0x1000 -#define LOOKUP_ROOT 0x2000 -#define LOOKUP_EMPTY 0x4000 -#define LOOKUP_DOWN 0x8000 #endif /* _LINUX_NAMEI_H */ diff --git a/include/linux/notifier.h b/include/linux/notifier.h new file mode 100644 index 0000000000..25f4921a3e --- /dev/null +++ b/include/linux/notifier.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LINUX_NOTIFIER_H +#define __LINUX_NOTIFIER_H + +#include <notifier.h> + +#define BLOCKING_NOTIFIER_HEAD NOTIFIER_HEAD + +#define blocking_notifier_call_chain notifier_call_chain + +#define blocking_notifier_head notifier_head + +#define blocking_notifier_chain_register notifier_chain_register +#define blocking_notifier_chain_unregister notifier_chain_unregister + +#endif diff --git a/include/linux/nvmem-consumer.h b/include/linux/nvmem-consumer.h index b979f23372..397c4c29da 100644 --- a/include/linux/nvmem-consumer.h +++ b/include/linux/nvmem-consumer.h @@ -12,7 +12,7 @@ #ifndef _LINUX_NVMEM_CONSUMER_H #define _LINUX_NVMEM_CONSUMER_H -struct device_d; +struct device; struct device_node; /* consumer cookie */ struct nvmem_cell; @@ -29,16 +29,18 @@ struct nvmem_cell_info { #if IS_ENABLED(CONFIG_NVMEM) /* Cell based interface */ -struct nvmem_cell *nvmem_cell_get(struct device_d *dev, const char *name); +struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name); void nvmem_cell_put(struct nvmem_cell *cell); void *nvmem_cell_read(struct nvmem_cell *cell, size_t *len); void *nvmem_cell_get_and_read(struct device_node *np, const char *cell_name, size_t bytes); +int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id, + u32 *val); int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len); /* direct nvmem device read/write interface */ -struct nvmem_device *nvmem_device_get(struct device_d *dev, const char *name); +struct nvmem_device *nvmem_device_get(struct device *dev, const char *name); void nvmem_device_put(struct nvmem_device *nvmem); int nvmem_device_read(struct nvmem_device *nvmem, unsigned int offset, size_t bytes, void *buf); @@ -53,7 +55,7 @@ void nvmem_devices_print(void); #else -static inline struct nvmem_cell *nvmem_cell_get(struct device_d *dev, +static inline struct nvmem_cell *nvmem_cell_get(struct device *dev, const char *name) { return ERR_PTR(-EOPNOTSUPP); @@ -75,13 +77,20 @@ static inline void *nvmem_cell_get_and_read(struct device_node *np, return ERR_PTR(-EOPNOTSUPP); } +static inline int nvmem_cell_read_variable_le_u32(struct device *dev, + const char *cell_id, + u32 *val) +{ + return -EOPNOTSUPP; +} + static inline int nvmem_cell_write(struct nvmem_cell *cell, void *buf, size_t len) { return -EOPNOTSUPP; } -static inline struct nvmem_device *nvmem_device_get(struct device_d *dev, +static inline struct nvmem_device *nvmem_device_get(struct device *dev, const char *name) { return ERR_PTR(-EOPNOTSUPP); diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h index a293f60c1e..41c636b3a4 100644 --- a/include/linux/nvmem-provider.h +++ b/include/linux/nvmem-provider.h @@ -17,21 +17,25 @@ struct nvmem_device; -struct nvmem_bus { - int (*write)(void *ctx, unsigned int reg, const void *val, size_t val_size); - int (*read)(void *ctx, unsigned int reg, void *val, size_t val_size); -}; +/* used for vendor specific post processing of cell data */ +typedef int (*nvmem_cell_post_process_t)(void *priv, const char *id, + unsigned int offset, void *buf, + size_t bytes); struct nvmem_config { - struct device_d *dev; + struct device *dev; const char *name; bool read_only; struct cdev *cdev; int stride; int word_size; int size; - const struct nvmem_bus *bus; + int (*reg_write)(void *ctx, unsigned int reg, + const void *val, size_t val_size); + int (*reg_read)(void *ctx, unsigned int reg, + void *val, size_t val_size); void *priv; + nvmem_cell_post_process_t cell_post_process; }; struct regmap; @@ -41,7 +45,10 @@ struct cdev; struct nvmem_device *nvmem_register(const struct nvmem_config *cfg); struct nvmem_device *nvmem_regmap_register(struct regmap *regmap, const char *name); +struct nvmem_device *nvmem_regmap_register_with_pp(struct regmap *regmap, + const char *name, nvmem_cell_post_process_t cell_post_process); struct nvmem_device *nvmem_partition_register(struct cdev *cdev); +struct device *nvmem_device_get_device(struct nvmem_device *nvmem); #else @@ -55,10 +62,21 @@ static inline struct nvmem_device *nvmem_regmap_register(struct regmap *regmap, return ERR_PTR(-ENOSYS); } +static inline struct nvmem_device * +nvmem_regmap_register_with_pp(struct regmap *regmap, const char *name, + nvmem_cell_post_process_t cell_post_process) +{ + return ERR_PTR(-ENOSYS); +} + static inline struct nvmem_device *nvmem_partition_register(struct cdev *cdev) { return ERR_PTR(-ENOSYS); } +static inline struct device *nvmem_device_get_device(struct nvmem_device *nvmem) +{ + return ERR_PTR(-ENOSYS); +} #endif /* CONFIG_NVMEM */ #endif /* ifndef _LINUX_NVMEM_PROVIDER_H */ diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 6590450464..f9b60313ea 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -3,14 +3,13 @@ #define __LINUX_OVERFLOW_H #include <linux/compiler.h> +#include <linux/limits.h> +#include <linux/const.h> /* - * In the fallback code below, we need to compute the minimum and - * maximum values representable in a given type. These macros may also - * be useful elsewhere, so we provide them outside the - * COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW block. - * - * It would seem more obvious to do something like + * We need to compute the minimum and maximum values representable in a given + * type. These macros may also be useful elsewhere. It would seem more obvious + * to do something like: * * #define type_min(T) (T)(is_signed_type(T) ? (T)1 << (8*sizeof(T)-1) : 0) * #define type_max(T) (T)(is_signed_type(T) ? ((T)1 << (8*sizeof(T)-1)) - 1 : ~(T)0) @@ -31,7 +30,6 @@ * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html - * credit to Christian Biere. */ -#define is_signed_type(type) (((type)(-1)) < (type)1) #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type))) #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T))) #define type_min(T) ((T)((T)-type_max(T)-(T)1)) @@ -43,191 +41,82 @@ #define is_non_negative(a) ((a) > 0 || (a) == 0) #define is_negative(a) (!(is_non_negative(a))) -#ifdef COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW -/* - * For simplicity and code hygiene, the fallback code below insists on - * a, b and *d having the same type (similar to the min() and max() - * macros), whereas gcc's type-generic overflow checkers accept - * different types. Hence we don't just make check_add_overflow an - * alias for __builtin_add_overflow, but add type checks similar to - * below. - */ -#define check_add_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - __builtin_add_overflow(__a, __b, __d); \ -}) - -#define check_sub_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - __builtin_sub_overflow(__a, __b, __d); \ -}) - -#define check_mul_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - __builtin_mul_overflow(__a, __b, __d); \ -}) - -#else - - -/* Checking for unsigned overflow is relatively easy without causing UB. */ -#define __unsigned_add_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - *__d = __a + __b; \ - *__d < __a; \ -}) -#define __unsigned_sub_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - *__d = __a - __b; \ - __a < __b; \ -}) -/* - * If one of a or b is a compile-time constant, this avoids a division. - */ -#define __unsigned_mul_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - *__d = __a * __b; \ - __builtin_constant_p(__b) ? \ - __b > 0 && __a > type_max(typeof(__a)) / __b : \ - __a > 0 && __b > type_max(typeof(__b)) / __a; \ -}) - /* - * For signed types, detecting overflow is much harder, especially if - * we want to avoid UB. But the interface of these macros is such that - * we must provide a result in *d, and in fact we must produce the - * result promised by gcc's builtins, which is simply the possibly - * wrapped-around value. Fortunately, we can just formally do the - * operations in the widest relevant unsigned type (u64) and then - * truncate the result - gcc is smart enough to generate the same code - * with and without the (u64) casts. + * Allows for effectively applying __must_check to a macro so we can have + * both the type-agnostic benefits of the macros while also being able to + * enforce that the return value is, in fact, checked. */ +static inline bool __must_check __must_check_overflow(bool overflow) +{ + return unlikely(overflow); +} -/* - * Adding two signed integers can overflow only if they have the same - * sign, and overflow has happened iff the result has the opposite - * sign. +/** + * check_add_overflow() - Calculate addition with overflow checking + * @a: first addend + * @b: second addend + * @d: pointer to store sum + * + * Returns 0 on success. + * + * *@d holds the results of the attempted addition, but is not considered + * "safe for use" on a non-zero return value, which indicates that the + * sum has overflowed or been truncated. */ -#define __signed_add_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - *__d = (u64)__a + (u64)__b; \ - (((~(__a ^ __b)) & (*__d ^ __a)) \ - & type_min(typeof(__a))) != 0; \ -}) +#define check_add_overflow(a, b, d) \ + __must_check_overflow(__builtin_add_overflow(a, b, d)) -/* - * Subtraction is similar, except that overflow can now happen only - * when the signs are opposite. In this case, overflow has happened if - * the result has the opposite sign of a. +/** + * check_sub_overflow() - Calculate subtraction with overflow checking + * @a: minuend; value to subtract from + * @b: subtrahend; value to subtract from @a + * @d: pointer to store difference + * + * Returns 0 on success. + * + * *@d holds the results of the attempted subtraction, but is not considered + * "safe for use" on a non-zero return value, which indicates that the + * difference has underflowed or been truncated. */ -#define __signed_sub_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - *__d = (u64)__a - (u64)__b; \ - ((((__a ^ __b)) & (*__d ^ __a)) \ - & type_min(typeof(__a))) != 0; \ -}) +#define check_sub_overflow(a, b, d) \ + __must_check_overflow(__builtin_sub_overflow(a, b, d)) -/* - * Signed multiplication is rather hard. gcc always follows C99, so - * division is truncated towards 0. This means that we can write the - * overflow check like this: - * - * (a > 0 && (b > MAX/a || b < MIN/a)) || - * (a < -1 && (b > MIN/a || b < MAX/a) || - * (a == -1 && b == MIN) - * - * The redundant casts of -1 are to silence an annoying -Wtype-limits - * (included in -Wextra) warning: When the type is u8 or u16, the - * __b_c_e in check_mul_overflow obviously selects - * __unsigned_mul_overflow, but unfortunately gcc still parses this - * code and warns about the limited range of __b. +/** + * check_mul_overflow() - Calculate multiplication with overflow checking + * @a: first factor + * @b: second factor + * @d: pointer to store product + * + * Returns 0 on success. + * + * *@d holds the results of the attempted multiplication, but is not + * considered "safe for use" on a non-zero return value, which indicates + * that the product has overflowed or been truncated. */ +#define check_mul_overflow(a, b, d) \ + __must_check_overflow(__builtin_mul_overflow(a, b, d)) -#define __signed_mul_overflow(a, b, d) ({ \ - typeof(a) __a = (a); \ - typeof(b) __b = (b); \ - typeof(d) __d = (d); \ - typeof(a) __tmax = type_max(typeof(a)); \ - typeof(a) __tmin = type_min(typeof(a)); \ - (void) (&__a == &__b); \ - (void) (&__a == __d); \ - *__d = (u64)__a * (u64)__b; \ - (__b > 0 && (__a > __tmax/__b || __a < __tmin/__b)) || \ - (__b < (typeof(__b))-1 && (__a > __tmin/__b || __a < __tmax/__b)) || \ - (__b == (typeof(__b))-1 && __a == __tmin); \ -}) - - -#define check_add_overflow(a, b, d) \ - __builtin_choose_expr(is_signed_type(typeof(a)), \ - __signed_add_overflow(a, b, d), \ - __unsigned_add_overflow(a, b, d)) - -#define check_sub_overflow(a, b, d) \ - __builtin_choose_expr(is_signed_type(typeof(a)), \ - __signed_sub_overflow(a, b, d), \ - __unsigned_sub_overflow(a, b, d)) - -#define check_mul_overflow(a, b, d) \ - __builtin_choose_expr(is_signed_type(typeof(a)), \ - __signed_mul_overflow(a, b, d), \ - __unsigned_mul_overflow(a, b, d)) - - -#endif /* COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW */ - -/** check_shl_overflow() - Calculate a left-shifted value and check overflow - * +/** + * check_shl_overflow() - Calculate a left-shifted value and check overflow * @a: Value to be shifted * @s: How many bits left to shift * @d: Pointer to where to store the result * * Computes *@d = (@a << @s) * - * Returns true if '*d' cannot hold the result or when 'a << s' doesn't + * Returns true if '*@d' cannot hold the result or when '@a << @s' doesn't * make sense. Example conditions: - * - 'a << s' causes bits to be lost when stored in *d. - * - 's' is garbage (e.g. negative) or so large that the result of - * 'a << s' is guaranteed to be 0. - * - 'a' is negative. - * - 'a << s' sets the sign bit, if any, in '*d'. - * - * '*d' will hold the results of the attempted shift, but is not - * considered "safe for use" if false is returned. + * + * - '@a << @s' causes bits to be lost when stored in *@d. + * - '@s' is garbage (e.g. negative) or so large that the result of + * '@a << @s' is guaranteed to be 0. + * - '@a' is negative. + * - '@a << @s' sets the sign bit, if any, in '*@d'. + * + * '*@d' will hold the results of the attempted shift, but is not + * considered "safe for use" if true is returned. */ -#define check_shl_overflow(a, s, d) ({ \ +#define check_shl_overflow(a, s, d) __must_check_overflow(({ \ typeof(a) _a = a; \ typeof(s) _s = s; \ typeof(d) _d = d; \ @@ -237,83 +126,187 @@ *_d = (_a_full << _to_shift); \ (_to_shift != _s || is_negative(*_d) || is_negative(_a) || \ (*_d >> _to_shift) != _a); \ +})) + +#define __overflows_type_constexpr(x, T) ( \ + is_unsigned_type(typeof(x)) ? \ + (x) > type_max(typeof(T)) : \ + is_unsigned_type(typeof(T)) ? \ + (x) < 0 || (x) > type_max(typeof(T)) : \ + (x) < type_min(typeof(T)) || (x) > type_max(typeof(T))) + +#define __overflows_type(x, T) ({ \ + typeof(T) v = 0; \ + check_add_overflow((x), v, &v); \ }) /** - * array_size() - Calculate size of 2-dimensional array. + * overflows_type - helper for checking the overflows between value, variables, + * or data type * - * @a: dimension one - * @b: dimension two + * @n: source constant value or variable to be checked + * @T: destination variable or data type proposed to store @x * - * Calculates size of 2-dimensional array: @a * @b. + * Compares the @x expression for whether or not it can safely fit in + * the storage of the type in @T. @x and @T can have different types. + * If @x is a constant expression, this will also resolve to a constant + * expression. * - * Returns: number of bytes needed to represent the array or SIZE_MAX on - * overflow. + * Returns: true if overflow can occur, false otherwise. + */ +#define overflows_type(n, T) \ + __builtin_choose_expr(__is_constexpr(n), \ + __overflows_type_constexpr(n, T), \ + __overflows_type(n, T)) + +/** + * castable_to_type - like __same_type(), but also allows for casted literals + * + * @n: variable or constant value + * @T: variable or data type + * + * Unlike the __same_type() macro, this allows a constant value as the + * first argument. If this value would not overflow into an assignment + * of the second argument's type, it returns true. Otherwise, this falls + * back to __same_type(). */ -static inline __must_check size_t array_size(size_t a, size_t b) +#define castable_to_type(n, T) \ + __builtin_choose_expr(__is_constexpr(n), \ + !__overflows_type_constexpr(n, T), \ + __same_type(n, T)) + +/** + * size_mul() - Calculate size_t multiplication with saturation at SIZE_MAX + * @factor1: first factor + * @factor2: second factor + * + * Returns: calculate @factor1 * @factor2, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. The + * lvalue must be size_t to avoid implicit type conversion. + */ +static inline size_t __must_check size_mul(size_t factor1, size_t factor2) { size_t bytes; - if (check_mul_overflow(a, b, &bytes)) + if (check_mul_overflow(factor1, factor2, &bytes)) return SIZE_MAX; return bytes; } /** - * array3_size() - Calculate size of 3-dimensional array. - * - * @a: dimension one - * @b: dimension two - * @c: dimension three - * - * Calculates size of 3-dimensional array: @a * @b * @c. + * size_add() - Calculate size_t addition with saturation at SIZE_MAX + * @addend1: first addend + * @addend2: second addend * - * Returns: number of bytes needed to represent the array or SIZE_MAX on - * overflow. + * Returns: calculate @addend1 + @addend2, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. The + * lvalue must be size_t to avoid implicit type conversion. */ -static inline __must_check size_t array3_size(size_t a, size_t b, size_t c) +static inline size_t __must_check size_add(size_t addend1, size_t addend2) { size_t bytes; - if (check_mul_overflow(a, b, &bytes)) - return SIZE_MAX; - if (check_mul_overflow(bytes, c, &bytes)) + if (check_add_overflow(addend1, addend2, &bytes)) return SIZE_MAX; return bytes; } -/* - * Compute a*b+c, returning SIZE_MAX on overflow. Internal helper for - * struct_size() below. +/** + * size_sub() - Calculate size_t subtraction with saturation at SIZE_MAX + * @minuend: value to subtract from + * @subtrahend: value to subtract from @minuend + * + * Returns: calculate @minuend - @subtrahend, both promoted to size_t, + * with any overflow causing the return value to be SIZE_MAX. For + * composition with the size_add() and size_mul() helpers, neither + * argument may be SIZE_MAX (or the result with be forced to SIZE_MAX). + * The lvalue must be size_t to avoid implicit type conversion. */ -static inline __must_check size_t __ab_c_size(size_t a, size_t b, size_t c) +static inline size_t __must_check size_sub(size_t minuend, size_t subtrahend) { size_t bytes; - if (check_mul_overflow(a, b, &bytes)) - return SIZE_MAX; - if (check_add_overflow(bytes, c, &bytes)) + if (minuend == SIZE_MAX || subtrahend == SIZE_MAX || + check_sub_overflow(minuend, subtrahend, &bytes)) return SIZE_MAX; return bytes; } /** - * struct_size() - Calculate size of structure with trailing array. + * array_size() - Calculate size of 2-dimensional array. + * @a: dimension one + * @b: dimension two + * + * Calculates size of 2-dimensional array: @a * @b. + * + * Returns: number of bytes needed to represent the array or SIZE_MAX on + * overflow. + */ +#define array_size(a, b) size_mul(a, b) + +/** + * array3_size() - Calculate size of 3-dimensional array. + * @a: dimension one + * @b: dimension two + * @c: dimension three + * + * Calculates size of 3-dimensional array: @a * @b * @c. + * + * Returns: number of bytes needed to represent the array or SIZE_MAX on + * overflow. + */ +#define array3_size(a, b, c) size_mul(size_mul(a, b), c) + +/** + * flex_array_size() - Calculate size of a flexible array member + * within an enclosing structure. * @p: Pointer to the structure. + * @member: Name of the flexible array member. + * @count: Number of elements in the array. + * + * Calculates size of a flexible array of @count number of @member + * elements, at the end of structure @p. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define flex_array_size(p, member, count) \ + __builtin_choose_expr(__is_constexpr(count), \ + (count) * sizeof(*(p)->member) + __must_be_array((p)->member), \ + size_mul(count, sizeof(*(p)->member) + __must_be_array((p)->member))) + +/** + * struct_size() - Calculate size of structure with trailing flexible array. + * @p: Pointer to the structure. + * @member: Name of the array member. + * @count: Number of elements in the array. + * + * Calculates size of memory needed for structure of @p followed by an + * array of @count number of @member elements. + * + * Return: number of bytes needed or SIZE_MAX on overflow. + */ +#define struct_size(p, member, count) \ + __builtin_choose_expr(__is_constexpr(count), \ + sizeof(*(p)) + flex_array_size(p, member, count), \ + size_add(sizeof(*(p)), flex_array_size(p, member, count))) + +/** + * struct_size_t() - Calculate size of structure with trailing flexible array + * @type: structure type name. * @member: Name of the array member. - * @n: Number of elements in the array. + * @count: Number of elements in the array. * - * Calculates size of memory needed for structure @p followed by an - * array of @n @member elements. + * Calculates size of memory needed for structure @type followed by an + * array of @count number of @member elements. Prefer using struct_size() + * when possible instead, to keep calculations associated with a specific + * instance variable of type @type. * * Return: number of bytes needed or SIZE_MAX on overflow. */ -#define struct_size(p, member, n) \ - __ab_c_size(n, \ - sizeof(*(p)->member) + __must_be_array((p)->member),\ - sizeof(*(p))) +#define struct_size_t(type, member, count) \ + struct_size((type *)NULL, member, count) #endif /* __LINUX_OVERFLOW_H */ diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index 345bd402b7..0db192e4d3 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -1,11 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_PAGEMAP_H #define _LINUX_PAGEMAP_H +#include <linux/kernel.h> + /* * Copyright 1995 Linus Torvalds */ -#include <common.h> + +#define PAGE_SIZE 4096 +#define PAGE_SHIFT 12 +#define PAGE_MASK (PAGE_SIZE - 1) +#define PAGE_ALIGN(s) ALIGN(s, PAGE_SIZE) +#define PAGE_ALIGN_DOWN(x) ALIGN_DOWN(x, PAGE_SIZE) #define PAGE_CACHE_SHIFT PAGE_SHIFT #define PAGE_CACHE_SIZE PAGE_SIZE diff --git a/include/linux/path.h b/include/linux/path.h index cbebdc5c9a..3891c784d2 100644 --- a/include/linux/path.h +++ b/include/linux/path.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_PATH_H #define _LINUX_PATH_H diff --git a/include/linux/pci.h b/include/linux/pci.h index 486d4251d4..aa29ff5d17 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * pci.h * @@ -100,7 +102,7 @@ struct pci_dev { struct pci_slot *slot; /* Physical slot this device is in */ const struct pci_device_id *id; /* the id this device matches */ - struct device_d dev; + struct device dev; unsigned int devfn; /* encoded device & function index */ unsigned short vendor; @@ -139,7 +141,7 @@ enum { }; struct pci_bus { struct pci_controller *host; /* associated host controller */ - struct device_d *parent; + struct device *parent; struct pci_bus *parent_bus; /* parent bus */ struct list_head node; /* node in list of buses */ struct list_head children; /* list of child buses */ @@ -171,7 +173,7 @@ extern struct pci_ops *pci_ops; */ struct pci_controller { struct pci_controller *next; - struct device_d *parent; + struct device *parent; struct pci_bus *bus; const struct pci_ops *pci_ops; @@ -194,15 +196,11 @@ struct pci_driver { const struct pci_device_id *id_table; /* must be non-NULL for probe to be called */ int (*probe) (struct pci_dev *dev, const struct pci_device_id *id); /* New device inserted */ void (*remove) (struct pci_dev *dev); /* Device removed (NULL if not a hot-plug capable driver) */ - struct driver_d driver; + struct driver driver; }; #define to_pci_driver(drv) container_of(drv, struct pci_driver, driver) -/* these helpers provide future and backwards compatibility - * for accessing popular PCI BAR info */ -#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) - /** * DEFINE_PCI_DEVICE_TABLE - macro used to describe a pci device table * @_table: device table name @@ -324,12 +322,15 @@ static inline int pci_write_config_dword(const struct pci_dev *dev, int where, void pci_set_master(struct pci_dev *dev); void pci_clear_master(struct pci_dev *dev); int pci_enable_device(struct pci_dev *dev); +int pci_select_bars(struct pci_dev *dev, unsigned long flags); u8 pci_find_next_capability(struct pci_dev *dev, u8 pos, int cap); u8 pci_find_capability(struct pci_dev *dev, int cap); extern void __iomem *pci_iomap(struct pci_dev *dev, int bar); +int pci_flr(struct pci_dev *pdev); + /* * The world is not perfect and supplies us with broken PCI devices. * For at least a part of these bugs we need a work-around, so both @@ -354,8 +355,8 @@ enum pci_fixup_pass { /* Anonymous variables would be nice... */ #define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, class, \ class_shift, hook) \ - static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) __used \ - __attribute__((__section__(#section), aligned((sizeof(void *))))) \ + static const struct pci_fixup __PASTE(__pci_fixup_##name,__LINE__) \ + __ll_elem(section) __aligned(sizeof(void *)) \ = { vendor, device, class, class_shift, hook }; #define DECLARE_PCI_FIXUP_CLASS_EARLY(vendor, device, class, \ diff --git a/include/linux/pci_regs.h b/include/linux/pci_regs.h index efe3443572..8d71914f75 100644 --- a/include/linux/pci_regs.h +++ b/include/linux/pci_regs.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * pci_regs.h * @@ -67,6 +69,7 @@ #define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ #define PCI_LATENCY_TIMER 0x0d /* 8 bits */ #define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_HEADER_TYPE_MASK 0x7f #define PCI_HEADER_TYPE_NORMAL 0 #define PCI_HEADER_TYPE_BRIDGE 1 #define PCI_HEADER_TYPE_CARDBUS 2 @@ -216,7 +219,8 @@ #define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ #define PCI_CAP_ID_SATA 0x12 /* SATA Data/Index Conf. */ #define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */ -#define PCI_CAP_ID_MAX PCI_CAP_ID_AF +#define PCI_CAP_ID_EA 0x14 /* PCI Enhanced Allocation */ +#define PCI_CAP_ID_MAX PCI_CAP_ID_EA #define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ #define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ #define PCI_CAP_SIZEOF 4 @@ -352,6 +356,52 @@ #define PCI_AF_STATUS_TP 0x01 #define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */ +/* PCI Enhanced Allocation registers */ + +#define PCI_EA_NUM_ENT 2 /* Number of Capability Entries */ +#define PCI_EA_NUM_ENT_MASK 0x3f /* Num Entries Mask */ +#define PCI_EA_FIRST_ENT 4 /* First EA Entry in List */ +#define PCI_EA_FIRST_ENT_BRIDGE 8 /* First EA Entry for Bridges */ +#define PCI_EA_ES 0x00000007 /* Entry Size */ +#define PCI_EA_BEI 0x000000f0 /* BAR Equivalent Indicator */ + +/* EA fixed Secondary and Subordinate bus numbers for Bridge */ +#define PCI_EA_SEC_BUS_MASK 0xff +#define PCI_EA_SUB_BUS_MASK 0xff00 +#define PCI_EA_SUB_BUS_SHIFT 8 + +/* 0-5 map to BARs 0-5 respectively */ +#define PCI_EA_BEI_BAR0 0 +#define PCI_EA_BEI_BAR5 5 +#define PCI_EA_BEI_BRIDGE 6 /* Resource behind bridge */ +#define PCI_EA_BEI_ENI 7 /* Equivalent Not Indicated */ +#define PCI_EA_BEI_ROM 8 /* Expansion ROM */ +/* 9-14 map to VF BARs 0-5 respectively */ +#define PCI_EA_BEI_VF_BAR0 9 +#define PCI_EA_BEI_VF_BAR5 14 +#define PCI_EA_BEI_RESERVED 15 /* Reserved - Treat like ENI */ +#define PCI_EA_PP 0x0000ff00 /* Primary Properties */ +#define PCI_EA_SP 0x00ff0000 /* Secondary Properties */ +#define PCI_EA_P_MEM 0x00 /* Non-Prefetch Memory */ +#define PCI_EA_P_MEM_PREFETCH 0x01 /* Prefetchable Memory */ +#define PCI_EA_P_IO 0x02 /* I/O Space */ +#define PCI_EA_P_VF_MEM_PREFETCH 0x03 /* VF Prefetchable Memory */ +#define PCI_EA_P_VF_MEM 0x04 /* VF Non-Prefetch Memory */ +#define PCI_EA_P_BRIDGE_MEM 0x05 /* Bridge Non-Prefetch Memory */ +#define PCI_EA_P_BRIDGE_MEM_PREFETCH 0x06 /* Bridge Prefetchable Memory */ +#define PCI_EA_P_BRIDGE_IO 0x07 /* Bridge I/O Space */ +/* 0x08-0xfc reserved */ +#define PCI_EA_P_MEM_RESERVED 0xfd /* Reserved Memory */ +#define PCI_EA_P_IO_RESERVED 0xfe /* Reserved I/O Space */ +#define PCI_EA_P_UNAVAILABLE 0xff /* Entry Unavailable */ +#define PCI_EA_WRITABLE 0x40000000 /* Writable: 1 = RW, 0 = HwInit */ +#define PCI_EA_ENABLE 0x80000000 /* Enable for this entry */ +#define PCI_EA_BASE 4 /* Base Address Offset */ +#define PCI_EA_MAX_OFFSET 8 /* MaxOffset (resource length) */ +/* bit 0 is reserved */ +#define PCI_EA_IS_64 0x00000002 /* 64-bit field flag */ +#define PCI_EA_FIELD_MASK 0xfffffffc /* For Base & Max Offset */ + /* PCI-X registers (Type 0 (non-bridge) devices) */ #define PCI_X_CMD 2 /* Modes & Features */ diff --git a/include/linux/pe.h b/include/linux/pe.h new file mode 100644 index 0000000000..fdf9c95709 --- /dev/null +++ b/include/linux/pe.h @@ -0,0 +1,482 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2011 Red Hat, Inc. + * All rights reserved. + * + * Author(s): Peter Jones <pjones@redhat.com> + */ +#ifndef __LINUX_PE_H +#define __LINUX_PE_H + +#include <linux/types.h> + +/* + * Starting from version v3.0, the major version field should be interpreted as + * a bit mask of features supported by the kernel's EFI stub: + * - 0x1: initrd loading from the LINUX_EFI_INITRD_MEDIA_GUID device path, + * - 0x2: initrd loading using the initrd= command line option, where the file + * may be specified using device path notation, and is not required to + * reside on the same volume as the loaded kernel image. + * + * The recommended way of loading and starting v1.0 or later kernels is to use + * the LoadImage() and StartImage() EFI boot services, and expose the initrd + * via the LINUX_EFI_INITRD_MEDIA_GUID device path. + * + * Versions older than v1.0 may support initrd loading via the image load + * options (using initrd=, limited to the volume from which the kernel itself + * was loaded), or only via arch specific means (bootparams, DT, etc). + * + * The minor version field must remain 0x0. + * (https://lore.kernel.org/all/efd6f2d4-547c-1378-1faa-53c044dbd297@gmail.com/) + */ +#define LINUX_EFISTUB_MAJOR_VERSION 0x3 +#define LINUX_EFISTUB_MINOR_VERSION 0x0 + +/* + * LINUX_PE_MAGIC appears at offset 0x38 into the MS-DOS header of EFI bootable + * Linux kernel images that target the architecture as specified by the PE/COFF + * header machine type field. + */ +#define LINUX_PE_MAGIC 0x818223cd + +#define MZ_MAGIC 0x5a4d /* "MZ" */ + +#define PE_MAGIC 0x00004550 /* "PE\0\0" */ +#define PE_OPT_MAGIC_PE32 0x010b +#define PE_OPT_MAGIC_PE32_ROM 0x0107 +#define PE_OPT_MAGIC_PE32PLUS 0x020b + +/* machine type */ +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0000 +#define IMAGE_FILE_MACHINE_AM33 0x01d3 +#define IMAGE_FILE_MACHINE_AMD64 0x8664 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 +#define IMAGE_FILE_MACHINE_ARMV7 0x01c4 +#define IMAGE_FILE_MACHINE_ARM64 0xaa64 +#define IMAGE_FILE_MACHINE_EBC 0x0ebc +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_M32R 0x9041 +#define IMAGE_FILE_MACHINE_MIPS16 0x0266 +#define IMAGE_FILE_MACHINE_MIPSFPU 0x0366 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x0466 +#define IMAGE_FILE_MACHINE_POWERPC 0x01f0 +#define IMAGE_FILE_MACHINE_POWERPCFP 0x01f1 +#define IMAGE_FILE_MACHINE_R4000 0x0166 +#define IMAGE_FILE_MACHINE_RISCV32 0x5032 +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 +#define IMAGE_FILE_MACHINE_RISCV128 0x5128 +#define IMAGE_FILE_MACHINE_SH3 0x01a2 +#define IMAGE_FILE_MACHINE_SH3DSP 0x01a3 +#define IMAGE_FILE_MACHINE_SH3E 0x01a4 +#define IMAGE_FILE_MACHINE_SH4 0x01a6 +#define IMAGE_FILE_MACHINE_SH5 0x01a8 +#define IMAGE_FILE_MACHINE_THUMB 0x01c2 +#define IMAGE_FILE_MACHINE_WCEMIPSV2 0x0169 +#define IMAGE_FILE_MACHINE_LOONGARCH32 0x6232 +#define IMAGE_FILE_MACHINE_LOONGARCH64 0x6264 + +/* flags */ +#define IMAGE_FILE_RELOCS_STRIPPED 0x0001 +#define IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 +#define IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 +#define IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 +#define IMAGE_FILE_AGGRESSIVE_WS_TRIM 0x0010 +#define IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 +#define IMAGE_FILE_16BIT_MACHINE 0x0040 +#define IMAGE_FILE_BYTES_REVERSED_LO 0x0080 +#define IMAGE_FILE_32BIT_MACHINE 0x0100 +#define IMAGE_FILE_DEBUG_STRIPPED 0x0200 +#define IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP 0x0400 +#define IMAGE_FILE_NET_RUN_FROM_SWAP 0x0800 +#define IMAGE_FILE_SYSTEM 0x1000 +#define IMAGE_FILE_DLL 0x2000 +#define IMAGE_FILE_UP_SYSTEM_ONLY 0x4000 +#define IMAGE_FILE_BYTES_REVERSED_HI 0x8000 + +#define IMAGE_FILE_OPT_ROM_MAGIC 0x107 +#define IMAGE_FILE_OPT_PE32_MAGIC 0x10b +#define IMAGE_FILE_OPT_PE32_PLUS_MAGIC 0x20b + +#define IMAGE_SUBSYSTEM_UNKNOWN 0 +#define IMAGE_SUBSYSTEM_NATIVE 1 +#define IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define IMAGE_SUBSYSTEM_WINDOWS_CUI 3 +#define IMAGE_SUBSYSTEM_POSIX_CUI 7 +#define IMAGE_SUBSYSTEM_WINDOWS_CE_GUI 9 +#define IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define IMAGE_SUBSYSTEM_EFI_ROM_IMAGE 13 +#define IMAGE_SUBSYSTEM_XBOX 14 + +#define IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE 0x0040 +#define IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY 0x0080 +#define IMAGE_DLL_CHARACTERISTICS_NX_COMPAT 0x0100 +#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200 +#define IMAGE_DLLCHARACTERISTICS_NO_SEH 0x0400 +#define IMAGE_DLLCHARACTERISTICS_NO_BIND 0x0800 +#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER 0x2000 +#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE 0x8000 + +#define IMAGE_DLLCHARACTERISTICS_EX_CET_COMPAT 0x0001 +#define IMAGE_DLLCHARACTERISTICS_EX_FORWARD_CFI_COMPAT 0x0040 + +/* they actually defined 0x00000000 as well, but I think we'll skip that one. */ +#define IMAGE_SCN_RESERVED_0 0x00000001 +#define IMAGE_SCN_RESERVED_1 0x00000002 +#define IMAGE_SCN_RESERVED_2 0x00000004 +#define IMAGE_SCN_TYPE_NO_PAD 0x00000008 /* don't pad - obsolete */ +#define IMAGE_SCN_RESERVED_3 0x00000010 +#define IMAGE_SCN_CNT_CODE 0x00000020 /* .text */ +#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 /* .data */ +#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 /* .bss */ +#define IMAGE_SCN_LNK_OTHER 0x00000100 /* reserved */ +#define IMAGE_SCN_LNK_INFO 0x00000200 /* .drectve comments */ +#define IMAGE_SCN_RESERVED_4 0x00000400 +#define IMAGE_SCN_LNK_REMOVE 0x00000800 /* .o only - scn to be rm'd*/ +#define IMAGE_SCN_LNK_COMDAT 0x00001000 /* .o only - COMDAT data */ +#define IMAGE_SCN_RESERVED_5 0x00002000 /* spec omits this */ +#define IMAGE_SCN_RESERVED_6 0x00004000 /* spec omits this */ +#define IMAGE_SCN_GPREL 0x00008000 /* global pointer referenced data */ +/* spec lists 0x20000 twice, I suspect they meant 0x10000 for one of them */ +#define IMAGE_SCN_MEM_PURGEABLE 0x00010000 /* reserved for "future" use */ +#define IMAGE_SCN_16BIT 0x00020000 /* reserved for "future" use */ +#define IMAGE_SCN_LOCKED 0x00040000 /* reserved for "future" use */ +#define IMAGE_SCN_PRELOAD 0x00080000 /* reserved for "future" use */ +/* and here they just stuck a 1-byte integer in the middle of a bitfield */ +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 /* it does what it says on the box */ +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00a00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00b00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00c00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00d00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00e00000 +#define IMAGE_SCN_LNK_NRELOC_OVFL 0x01000000 /* extended relocations */ +#define IMAGE_SCN_MEM_DISCARDABLE 0x02000000 /* scn can be discarded */ +#define IMAGE_SCN_MEM_NOT_CACHED 0x04000000 /* cannot be cached */ +#define IMAGE_SCN_MEM_NOT_PAGED 0x08000000 /* not pageable */ +#define IMAGE_SCN_MEM_SHARED 0x10000000 /* can be shared */ +#define IMAGE_SCN_MEM_EXECUTE 0x20000000 /* can be executed as code */ +#define IMAGE_SCN_MEM_READ 0x40000000 /* readable */ +#define IMAGE_SCN_MEM_WRITE 0x80000000 /* writeable */ + +#define IMAGE_DEBUG_TYPE_CODEVIEW 2 +#define IMAGE_DEBUG_TYPE_EX_DLLCHARACTERISTICS 20 + +#ifndef __ASSEMBLY__ + +struct mz_hdr { + uint16_t magic; /* MZ_MAGIC */ + uint16_t lbsize; /* size of last used block */ + uint16_t blocks; /* pages in file, 0x3 */ + uint16_t relocs; /* relocations */ + uint16_t hdrsize; /* header size in "paragraphs" */ + uint16_t min_extra_pps; /* .bss */ + uint16_t max_extra_pps; /* runtime limit for the arena size */ + uint16_t ss; /* relative stack segment */ + uint16_t sp; /* initial %sp register */ + uint16_t checksum; /* word checksum */ + uint16_t ip; /* initial %ip register */ + uint16_t cs; /* initial %cs relative to load segment */ + uint16_t reloc_table_offset; /* offset of the first relocation */ + uint16_t overlay_num; /* overlay number. set to 0. */ + uint16_t reserved0[4]; /* reserved */ + uint16_t oem_id; /* oem identifier */ + uint16_t oem_info; /* oem specific */ + uint16_t reserved1[10]; /* reserved */ + uint32_t peaddr; /* address of pe header */ + char message[]; /* message to print */ +}; + +struct mz_reloc { + uint16_t offset; + uint16_t segment; +}; + +struct pe_hdr { + uint32_t magic; /* PE magic */ + uint16_t machine; /* machine type */ + uint16_t sections; /* number of sections */ + uint32_t timestamp; /* time_t */ + uint32_t symbol_table; /* symbol table offset */ + uint32_t symbols; /* number of symbols */ + uint16_t opt_hdr_size; /* size of optional header */ + uint16_t flags; /* flags */ +}; + +/* the fact that pe32 isn't padded where pe32+ is 64-bit means union won't + * work right. vomit. */ +struct pe32_opt_hdr { + /* "standard" header */ + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; /* size of text section(s) */ + uint32_t data_size; /* size of data section(s) */ + uint32_t bss_size; /* size of bss section(s) */ + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + uint32_t data_base; /* relative data addr in ram */ + /* "windows" header */ + uint32_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; /* major OS version */ + uint16_t os_minor; /* minor OS version */ + uint16_t image_major; /* major image version */ + uint16_t image_minor; /* minor image version */ + uint16_t subsys_major; /* major subsystem version */ + uint16_t subsys_minor; /* minor subsystem version */ + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; /* image size */ + uint32_t header_size; /* header size rounded up to + file_align */ + uint32_t csum; /* checksum */ + uint16_t subsys; /* subsystem */ + uint16_t dll_flags; /* more flags! */ + uint32_t stack_size_req;/* amt of stack requested */ + uint32_t stack_size; /* amt of stack required */ + uint32_t heap_size_req; /* amt of heap requested */ + uint32_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct pe32plus_opt_hdr { + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; /* size of text section(s) */ + uint32_t data_size; /* size of data section(s) */ + uint32_t bss_size; /* size of bss section(s) */ + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + /* "windows" header */ + uint64_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; /* major OS version */ + uint16_t os_minor; /* minor OS version */ + uint16_t image_major; /* major image version */ + uint16_t image_minor; /* minor image version */ + uint16_t subsys_major; /* major subsystem version */ + uint16_t subsys_minor; /* minor subsystem version */ + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; /* image size */ + uint32_t header_size; /* header size rounded up to + file_align */ + uint32_t csum; /* checksum */ + uint16_t subsys; /* subsystem */ + uint16_t dll_flags; /* more flags! */ + uint64_t stack_size_req;/* amt of stack requested */ + uint64_t stack_size; /* amt of stack required */ + uint64_t heap_size_req; /* amt of heap requested */ + uint64_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct data_dirent { + uint32_t virtual_address; /* relative to load address */ + uint32_t size; +}; + +struct data_directory { + struct data_dirent exports; /* .edata */ + struct data_dirent imports; /* .idata */ + struct data_dirent resources; /* .rsrc */ + struct data_dirent exceptions; /* .pdata */ + struct data_dirent certs; /* certs */ + struct data_dirent base_relocations; /* .reloc */ + struct data_dirent debug; /* .debug */ + struct data_dirent arch; /* reservered */ + struct data_dirent global_ptr; /* global pointer reg. Size=0 */ + struct data_dirent tls; /* .tls */ + struct data_dirent load_config; /* load configuration structure */ + struct data_dirent bound_imports; /* no idea */ + struct data_dirent import_addrs; /* import address table */ + struct data_dirent delay_imports; /* delay-load import table */ + struct data_dirent clr_runtime_hdr; /* .cor (object only) */ + struct data_dirent reserved; +}; + +struct section_header { + char name[8]; /* name or "/12\0" string tbl offset */ + uint32_t virtual_size; /* size of loaded section in ram */ + uint32_t virtual_address; /* relative virtual address */ + uint32_t raw_data_size; /* size of the section */ + uint32_t data_addr; /* file pointer to first page of sec */ + uint32_t relocs; /* file pointer to relocation entries */ + uint32_t line_numbers; /* line numbers! */ + uint16_t num_relocs; /* number of relocations */ + uint16_t num_lin_numbers; /* srsly. */ + uint32_t flags; +}; + +enum x64_coff_reloc_type { + IMAGE_REL_AMD64_ABSOLUTE = 0, + IMAGE_REL_AMD64_ADDR64, + IMAGE_REL_AMD64_ADDR32, + IMAGE_REL_AMD64_ADDR32N, + IMAGE_REL_AMD64_REL32, + IMAGE_REL_AMD64_REL32_1, + IMAGE_REL_AMD64_REL32_2, + IMAGE_REL_AMD64_REL32_3, + IMAGE_REL_AMD64_REL32_4, + IMAGE_REL_AMD64_REL32_5, + IMAGE_REL_AMD64_SECTION, + IMAGE_REL_AMD64_SECREL, + IMAGE_REL_AMD64_SECREL7, + IMAGE_REL_AMD64_TOKEN, + IMAGE_REL_AMD64_SREL32, + IMAGE_REL_AMD64_PAIR, + IMAGE_REL_AMD64_SSPAN32, +}; + +enum arm_coff_reloc_type { + IMAGE_REL_ARM_ABSOLUTE, + IMAGE_REL_ARM_ADDR32, + IMAGE_REL_ARM_ADDR32N, + IMAGE_REL_ARM_BRANCH2, + IMAGE_REL_ARM_BRANCH1, + IMAGE_REL_ARM_SECTION, + IMAGE_REL_ARM_SECREL, +}; + +enum sh_coff_reloc_type { + IMAGE_REL_SH3_ABSOLUTE, + IMAGE_REL_SH3_DIRECT16, + IMAGE_REL_SH3_DIRECT32, + IMAGE_REL_SH3_DIRECT8, + IMAGE_REL_SH3_DIRECT8_WORD, + IMAGE_REL_SH3_DIRECT8_LONG, + IMAGE_REL_SH3_DIRECT4, + IMAGE_REL_SH3_DIRECT4_WORD, + IMAGE_REL_SH3_DIRECT4_LONG, + IMAGE_REL_SH3_PCREL8_WORD, + IMAGE_REL_SH3_PCREL8_LONG, + IMAGE_REL_SH3_PCREL12_WORD, + IMAGE_REL_SH3_STARTOF_SECTION, + IMAGE_REL_SH3_SIZEOF_SECTION, + IMAGE_REL_SH3_SECTION, + IMAGE_REL_SH3_SECREL, + IMAGE_REL_SH3_DIRECT32_NB, + IMAGE_REL_SH3_GPREL4_LONG, + IMAGE_REL_SH3_TOKEN, + IMAGE_REL_SHM_PCRELPT, + IMAGE_REL_SHM_REFLO, + IMAGE_REL_SHM_REFHALF, + IMAGE_REL_SHM_RELLO, + IMAGE_REL_SHM_RELHALF, + IMAGE_REL_SHM_PAIR, + IMAGE_REL_SHM_NOMODE, +}; + +enum ppc_coff_reloc_type { + IMAGE_REL_PPC_ABSOLUTE, + IMAGE_REL_PPC_ADDR64, + IMAGE_REL_PPC_ADDR32, + IMAGE_REL_PPC_ADDR24, + IMAGE_REL_PPC_ADDR16, + IMAGE_REL_PPC_ADDR14, + IMAGE_REL_PPC_REL24, + IMAGE_REL_PPC_REL14, + IMAGE_REL_PPC_ADDR32N, + IMAGE_REL_PPC_SECREL, + IMAGE_REL_PPC_SECTION, + IMAGE_REL_PPC_SECREL16, + IMAGE_REL_PPC_REFHI, + IMAGE_REL_PPC_REFLO, + IMAGE_REL_PPC_PAIR, + IMAGE_REL_PPC_SECRELLO, + IMAGE_REL_PPC_GPREL, + IMAGE_REL_PPC_TOKEN, +}; + +enum x86_coff_reloc_type { + IMAGE_REL_I386_ABSOLUTE, + IMAGE_REL_I386_DIR16, + IMAGE_REL_I386_REL16, + IMAGE_REL_I386_DIR32, + IMAGE_REL_I386_DIR32NB, + IMAGE_REL_I386_SEG12, + IMAGE_REL_I386_SECTION, + IMAGE_REL_I386_SECREL, + IMAGE_REL_I386_TOKEN, + IMAGE_REL_I386_SECREL7, + IMAGE_REL_I386_REL32, +}; + +enum ia64_coff_reloc_type { + IMAGE_REL_IA64_ABSOLUTE, + IMAGE_REL_IA64_IMM14, + IMAGE_REL_IA64_IMM22, + IMAGE_REL_IA64_IMM64, + IMAGE_REL_IA64_DIR32, + IMAGE_REL_IA64_DIR64, + IMAGE_REL_IA64_PCREL21B, + IMAGE_REL_IA64_PCREL21M, + IMAGE_REL_IA64_PCREL21F, + IMAGE_REL_IA64_GPREL22, + IMAGE_REL_IA64_LTOFF22, + IMAGE_REL_IA64_SECTION, + IMAGE_REL_IA64_SECREL22, + IMAGE_REL_IA64_SECREL64I, + IMAGE_REL_IA64_SECREL32, + IMAGE_REL_IA64_DIR32NB, + IMAGE_REL_IA64_SREL14, + IMAGE_REL_IA64_SREL22, + IMAGE_REL_IA64_SREL32, + IMAGE_REL_IA64_UREL32, + IMAGE_REL_IA64_PCREL60X, + IMAGE_REL_IA64_PCREL60B, + IMAGE_REL_IA64_PCREL60F, + IMAGE_REL_IA64_PCREL60I, + IMAGE_REL_IA64_PCREL60M, + IMAGE_REL_IA64_IMMGPREL6, + IMAGE_REL_IA64_TOKEN, + IMAGE_REL_IA64_GPREL32, + IMAGE_REL_IA64_ADDEND, +}; + +struct coff_reloc { + uint32_t virtual_address; + uint32_t symbol_table_index; + union { + enum x64_coff_reloc_type x64_type; + enum arm_coff_reloc_type arm_type; + enum sh_coff_reloc_type sh_type; + enum ppc_coff_reloc_type ppc_type; + enum x86_coff_reloc_type x86_type; + enum ia64_coff_reloc_type ia64_type; + uint16_t data; + }; +}; + +/* + * Definitions for the contents of the certs data block + */ +#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 +#define WIN_CERT_TYPE_EFI_OKCS115 0x0EF0 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +#define WIN_CERT_REVISION_1_0 0x0100 +#define WIN_CERT_REVISION_2_0 0x0200 + +struct win_certificate { + uint32_t length; + uint16_t revision; + uint16_t cert_type; +}; + +#endif /* !__ASSEMBLY__ */ + +#endif /* __LINUX_PE_H */ diff --git a/include/linux/phy.h b/include/linux/phy.h index d9fb514277..7da4f94e0e 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -36,7 +36,46 @@ #define PHY_GBIT_FEATURES (PHY_BASIC_FEATURES | \ PHY_1000BT_FEATURES) -/* Interface Mode definitions */ +/** + * enum phy_interface_t - Interface Mode definitions + * + * @PHY_INTERFACE_MODE_NA: Not Applicable - don't touch + * @PHY_INTERFACE_MODE_INTERNAL: No interface, MAC and PHY combined + * @PHY_INTERFACE_MODE_MII: Media-independent interface + * @PHY_INTERFACE_MODE_GMII: Gigabit media-independent interface + * @PHY_INTERFACE_MODE_SGMII: Serial gigabit media-independent interface + * @PHY_INTERFACE_MODE_TBI: Ten Bit Interface + * @PHY_INTERFACE_MODE_REVMII: Reverse Media Independent Interface + * @PHY_INTERFACE_MODE_RMII: Reduced Media Independent Interface + * @PHY_INTERFACE_MODE_REVRMII: Reduced Media Independent Interface in PHY role + * @PHY_INTERFACE_MODE_RGMII: Reduced gigabit media-independent interface + * @PHY_INTERFACE_MODE_RGMII_ID: RGMII with Internal RX+TX delay + * @PHY_INTERFACE_MODE_RGMII_RXID: RGMII with Internal RX delay + * @PHY_INTERFACE_MODE_RGMII_TXID: RGMII with Internal RX delay + * @PHY_INTERFACE_MODE_RTBI: Reduced TBI + * @PHY_INTERFACE_MODE_SMII: Serial MII + * @PHY_INTERFACE_MODE_XGMII: 10 gigabit media-independent interface + * @PHY_INTERFACE_MODE_XLGMII:40 gigabit media-independent interface + * @PHY_INTERFACE_MODE_MOCA: Multimedia over Coax + * @PHY_INTERFACE_MODE_PSGMII: Penta SGMII + * @PHY_INTERFACE_MODE_QSGMII: Quad SGMII + * @PHY_INTERFACE_MODE_TRGMII: Turbo RGMII + * @PHY_INTERFACE_MODE_100BASEX: 100 BaseX + * @PHY_INTERFACE_MODE_1000BASEX: 1000 BaseX + * @PHY_INTERFACE_MODE_2500BASEX: 2500 BaseX + * @PHY_INTERFACE_MODE_5GBASER: 5G BaseR + * @PHY_INTERFACE_MODE_RXAUI: Reduced XAUI + * @PHY_INTERFACE_MODE_XAUI: 10 Gigabit Attachment Unit Interface + * @PHY_INTERFACE_MODE_10GBASER: 10G BaseR + * @PHY_INTERFACE_MODE_25GBASER: 25G BaseR + * @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII + * @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN + * @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII + * @PHY_INTERFACE_MODE_1000BASEKX: 1000Base-KX - with Clause 73 AN + * @PHY_INTERFACE_MODE_MAX: Book keeping + * + * Describes the interface between the MAC and PHY. + */ typedef enum { PHY_INTERFACE_MODE_NA, PHY_INTERFACE_MODE_INTERNAL, @@ -46,6 +85,7 @@ typedef enum { PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_REVMII, PHY_INTERFACE_MODE_RMII, + PHY_INTERFACE_MODE_REVRMII, PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_RGMII_ID, PHY_INTERFACE_MODE_RGMII_RXID, @@ -53,17 +93,25 @@ typedef enum { PHY_INTERFACE_MODE_RTBI, PHY_INTERFACE_MODE_SMII, PHY_INTERFACE_MODE_XGMII, + PHY_INTERFACE_MODE_XLGMII, PHY_INTERFACE_MODE_MOCA, + PHY_INTERFACE_MODE_PSGMII, PHY_INTERFACE_MODE_QSGMII, PHY_INTERFACE_MODE_TRGMII, + PHY_INTERFACE_MODE_100BASEX, PHY_INTERFACE_MODE_1000BASEX, PHY_INTERFACE_MODE_2500BASEX, + PHY_INTERFACE_MODE_5GBASER, PHY_INTERFACE_MODE_RXAUI, PHY_INTERFACE_MODE_XAUI, - /* 10GBASE-KR, XFI, SFI - single lane 10G Serdes */ + /* 10GBASE-R, XFI, SFI - single lane 10G Serdes */ + PHY_INTERFACE_MODE_10GBASER, + PHY_INTERFACE_MODE_25GBASER, + PHY_INTERFACE_MODE_USXGMII, + /* 10GBASE-KR - with Clause 73 AN */ PHY_INTERFACE_MODE_10GKR, - PHY_INTERFACE_MODE_SGMII_2500, - PHY_INTERFACE_MODE_NONE, + PHY_INTERFACE_MODE_QUSGMII, + PHY_INTERFACE_MODE_1000BASEKX, PHY_INTERFACE_MODE_MAX, } phy_interface_t; @@ -99,9 +147,9 @@ struct mii_bus { int (*write)(struct mii_bus *bus, int phy_id, int regnum, u16 val); int (*reset)(struct mii_bus *bus); - struct device_d *parent; + struct device *parent; - struct device_d dev; + struct device dev; /* list of all PHYs on bus */ struct phy_device *phy_map[PHY_MAX_ADDR]; @@ -128,7 +176,7 @@ struct phy_device *mdiobus_scan(struct mii_bus *bus, int addr); extern struct list_head mii_bus_list; -int mdiobus_detect(struct device_d *dev); +int mdiobus_detect(struct device *dev); #define for_each_mii_bus(mii) \ list_for_each_entry(mii, &mii_bus_list, list) @@ -142,12 +190,13 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); /* phy_device: An instance of a PHY * - * bus: Pointer to the bus this PHY is on - * dev: driver model device structure for this PHY - * phy_id: UID for this device found during discovery - * dev_flags: Device-specific flags used by the PHY driver. - * addr: Bus address of PHY - * attached_dev: The attached enet driver's device instance ptr + * @bus: Pointer to the bus this PHY is on + * @dev: driver model device structure for this PHY + * @phy_id: UID for this device found during discovery + * @c45_ids: 802.3-c45 Device Identifiers if is_c45. + * @dev_flags: Device-specific flags used by the PHY driver. + * @addr: Bus address of PHY + * @attached_dev: The attached enet driver's device instance ptr * * speed, duplex, pause, supported, advertising, and * autoneg are used like in mii_if_info @@ -155,10 +204,12 @@ int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val); struct phy_device { struct mii_bus *bus; - struct device_d dev; + struct device dev; u32 phy_id; + unsigned is_c45:1; + u32 dev_flags; phy_interface_t interface; @@ -201,11 +252,11 @@ struct phy_device { /* struct phy_driver: Driver structure for a particular PHY type * - * phy_id: The result of reading the UID registers of this PHY + * @phy_id: The result of reading the UID registers of this PHY * type, and ANDing them with the phy_id_mask. This driver * only works for PHYs with IDs which match this field - * phy_id_mask: Defines the important bits of the phy_id - * features: A list of features (speed, duplex, etc) supported + * @phy_id_mask: Defines the important bits of the phy_id + * @features: A list of features (speed, duplex, etc) supported * by this PHY * @driver_data: Static driver data * @@ -222,6 +273,7 @@ struct phy_driver { unsigned int phy_id_mask; u32 features; const void *driver_data; + bool is_phy; /* * Called to initialize the PHY, @@ -255,7 +307,7 @@ struct phy_driver { int (*read_page)(struct phy_device *phydev); int (*write_page)(struct phy_device *phydev, int page); - struct driver_d drv; + struct driver drv; }; #define to_phy_driver(d) ((d) ? container_of(d, struct phy_driver, drv) : NULL) @@ -280,6 +332,8 @@ int phy_drivers_register(struct phy_driver *new_driver, int n); struct phy_device *get_phy_device(struct mii_bus *bus, int addr); int phy_init(void); int phy_init_hw(struct phy_device *phydev); +struct phy_device *of_phy_register_fixed_link(struct device_node *np, + struct eth_device *edev); #define phy_register_drivers_macro(level, drvs) \ static int __init drvs##_register(void) \ @@ -405,12 +459,64 @@ int phy_scan_fixups(struct phy_device *phydev); int phy_read_mmd_indirect(struct phy_device *phydev, int prtad, int devad); void phy_write_mmd_indirect(struct phy_device *phydev, int prtad, int devad, u16 data); +int phy_modify_mmd_indirect(struct phy_device *phydev, int prtad, int devad, + u16 mask, u16 set); + +int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum); +int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val); +int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); +int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum, + u16 mask, u16 set); + +/** + * phy_set_bits_mmd - Convenience function for setting bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to set + */ +static inline int phy_set_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + return phy_modify_mmd(phydev, devad, regnum, 0, val); +} + +/** + * phy_clear_bits_mmd - Convenience function for clearing bits in a register + * on MMD + * @phydev: the phy_device struct + * @devad: the MMD containing register to modify + * @regnum: register number to modify + * @val: bits to clear + */ +static inline int phy_clear_bits_mmd(struct phy_device *phydev, int devad, + u32 regnum, u16 val) +{ + return phy_modify_mmd(phydev, devad, regnum, val, 0); +} static inline bool phy_acquired(struct phy_device *phydev) { return phydev && phydev->bus && slice_acquired(&phydev->bus->slice); } +#define phydev_err(_phydev, format, args...) \ + dev_err(&_phydev->dev, format, ##args) + +#define phydev_err_probe(_phydev, err, format, args...) \ + dev_err_probe(&_phydev->dev, err, format, ##args) + +#define phydev_info(_phydev, format, args...) \ + dev_info(&_phydev->dev, format, ##args) + +#define phydev_warn(_phydev, format, args...) \ + dev_warn(&_phydev->dev, format, ##args) + +#define phydev_dbg(_phydev, format, args...) \ + dev_dbg(&_phydev->dev, format, ##args) + #ifdef CONFIG_PHYLIB int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, int (*run)(struct phy_device *)); diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 679ce6e420..9f01bc3e9f 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -20,12 +20,36 @@ struct phy; +enum phy_mode { + PHY_MODE_INVALID, + PHY_MODE_USB_HOST, + PHY_MODE_USB_HOST_LS, + PHY_MODE_USB_HOST_FS, + PHY_MODE_USB_HOST_HS, + PHY_MODE_USB_HOST_SS, + PHY_MODE_USB_DEVICE, + PHY_MODE_USB_DEVICE_LS, + PHY_MODE_USB_DEVICE_FS, + PHY_MODE_USB_DEVICE_HS, + PHY_MODE_USB_DEVICE_SS, + PHY_MODE_USB_OTG, + PHY_MODE_UFS_HS_A, + PHY_MODE_UFS_HS_B, + PHY_MODE_PCIE, + PHY_MODE_ETHERNET, + PHY_MODE_MIPI_DPHY, + PHY_MODE_SATA, + PHY_MODE_LVDS, + PHY_MODE_DP +}; + /** * struct phy_ops - set of function pointers for performing phy operations * @init: operation to be performed for initializing phy * @exit: operation to be performed while exiting * @power_on: powering on the phy * @power_off: powering off the phy + * @set_mode: set the mode of the phy * @owner: the module owner containing the ops */ struct phy_ops { @@ -33,15 +57,18 @@ struct phy_ops { int (*exit)(struct phy *phy); int (*power_on)(struct phy *phy); int (*power_off)(struct phy *phy); + int (*set_mode)(struct phy *phy, enum phy_mode mode, int submode); struct usb_phy *(*to_usbphy)(struct phy *phy); }; /** * struct phy_attrs - represents phy attributes * @bus_width: Data path width implemented by PHY + * @mode: PHY mode */ struct phy_attrs { u32 bus_width; + enum phy_mode mode; }; /** @@ -55,7 +82,7 @@ struct phy_attrs { * @phy_attrs: used to specify PHY specific attributes */ struct phy { - struct device_d dev; + struct device dev; int id; const struct phy_ops *ops; int init_count; @@ -72,10 +99,10 @@ struct phy { * @list: to maintain a linked list of PHY providers */ struct phy_provider { - struct device_d *dev; + struct device *dev; struct list_head list; - struct phy * (*of_xlate)(struct device_d *dev, - struct of_phandle_args *args); + struct phy * (*of_xlate)(struct device *dev, + struct of_phandle_args *args); }; /** @@ -125,6 +152,9 @@ int phy_init(struct phy *phy); int phy_exit(struct phy *phy); int phy_power_on(struct phy *phy); int phy_power_off(struct phy *phy); +int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, int submode); +#define phy_set_mode(phy, mode) \ + phy_set_mode_ext(phy, mode, 0) static inline int phy_get_bus_width(struct phy *phy) { return phy->attrs.bus_width; @@ -133,21 +163,21 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width) { phy->attrs.bus_width = bus_width; } -struct phy *phy_get(struct device_d *dev, const char *string); -struct phy *phy_optional_get(struct device_d *dev, const char *string); -struct phy *of_phy_get_by_phandle(struct device_d *dev, const char *phandle, +struct phy *phy_get(struct device *dev, const char *string); +struct phy *phy_optional_get(struct device *dev, const char *string); +struct phy *of_phy_get_by_phandle(struct device *dev, const char *phandle, u8 index); void phy_put(struct phy *phy); struct phy *of_phy_get(struct device_node *np, const char *con_id); -struct phy *phy_create(struct device_d *dev, struct device_node *node, +struct phy *phy_create(struct device *dev, struct device_node *node, const struct phy_ops *ops); void phy_destroy(struct phy *phy); -struct phy_provider *__of_phy_provider_register(struct device_d *dev, - struct phy * (*of_xlate)(struct device_d *dev, - struct of_phandle_args *args)); +struct phy_provider *__of_phy_provider_register(struct device *dev, + struct phy * (*of_xlate)(struct device *dev, + struct of_phandle_args *args)); void of_phy_provider_unregister(struct phy_provider *phy_provider); struct usb_phy *phy_to_usbphy(struct phy *phy); -struct phy *phy_get_by_index(struct device_d *dev, int index); +struct phy *phy_get_by_index(struct device *dev, int index); #else static inline int phy_init(struct phy *phy) { @@ -177,6 +207,17 @@ static inline int phy_power_off(struct phy *phy) return -ENOSYS; } +static inline int phy_set_mode_ext(struct phy *phy, enum phy_mode mode, + int submode) +{ + if (!phy) + return 0; + return -ENOSYS; +} + +#define phy_set_mode(phy, mode) \ + phy_set_mode_ext(phy, mode, 0) + static inline int phy_get_bus_width(struct phy *phy) { return -ENOSYS; @@ -187,18 +228,18 @@ static inline void phy_set_bus_width(struct phy *phy, int bus_width) return; } -static inline struct phy *phy_get(struct device_d *dev, const char *string) +static inline struct phy *phy_get(struct device *dev, const char *string) { return ERR_PTR(-ENOSYS); } -static inline struct phy *phy_optional_get(struct device_d *dev, +static inline struct phy *phy_optional_get(struct device *dev, const char *string) { - return ERR_PTR(-ENOSYS); + return NULL; } -static inline struct phy *of_phy_get_by_phandle(struct device_d *dev, +static inline struct phy *of_phy_get_by_phandle(struct device *dev, const char *phandle, u8 index) { return ERR_PTR(-ENOSYS); @@ -213,7 +254,7 @@ static inline struct phy *of_phy_get(struct device_node *np, const char *con_id) return ERR_PTR(-ENOSYS); } -static inline struct phy *phy_create(struct device_d *dev, +static inline struct phy *phy_create(struct device *dev, struct device_node *node, const struct phy_ops *ops) { @@ -224,9 +265,8 @@ static inline void phy_destroy(struct phy *phy) { } -static inline struct phy_provider *__of_phy_provider_register( - struct device_d *dev, struct phy * (*of_xlate)( - struct device_d *dev, struct of_phandle_args *args)) +static inline struct phy_provider *__of_phy_provider_register(struct device *dev, + struct phy * (*of_xlate)(struct device *dev, struct of_phandle_args *args)) { return ERR_PTR(-ENOSYS); } @@ -240,7 +280,7 @@ static inline struct usb_phy *phy_to_usbphy(struct phy *phy) return NULL; } -static inline struct phy *phy_get_by_index(struct device_d *dev, int index) +static inline struct phy *phy_get_by_index(struct device *dev, int index) { return ERR_PTR(-ENODEV); } diff --git a/include/linux/posix_types.h b/include/linux/posix_types.h index bd37e1faf4..4a0b852b27 100644 --- a/include/linux/posix_types.h +++ b/include/linux/posix_types.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_POSIX_TYPES_H #define _LINUX_POSIX_TYPES_H diff --git a/include/linux/printk.h b/include/linux/printk.h index 39523b0572..07403ea60c 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -3,6 +3,7 @@ #define __LINUX_PRINTK_H #include <linux/list.h> +#include <linux/err.h> #include <printk.h> #include <stdarg.h> @@ -25,13 +26,14 @@ #endif /* debugging and troubleshooting/diagnostic helpers. */ -struct device_d; +struct device; #ifndef CONFIG_CONSOLE_NONE -int dev_printf(int level, const struct device_d *dev, const char *format, ...) +int dev_printf(int level, const struct device *dev, const char *format, ...) __attribute__ ((format(__printf__, 3, 4))); #else -static inline int dev_printf(int level, const struct device_d *dev, const char *format, ...) +static inline int dev_printf(int level, const struct device *dev, + const char *format, ...) { return 0; } @@ -55,7 +57,15 @@ static inline int pr_print(int level, const char *format, ...) (level) <= LOGLEVEL ? dev_printf((level), (dev), (format), ##args) : 0; \ }) - +#define __dev_printf_once(level, dev, format, args...) do { \ + static bool __print_once; \ + \ + if (!__print_once && (level) <= LOGLEVEL) { \ + __print_once = true; \ + dev_printf((level), (dev), (format), ##args); \ + } \ +} while (0) + #define dev_emerg(dev, format, arg...) \ __dev_printf(0, (dev) , format , ## arg) #define dev_alert(dev, format, arg...) \ @@ -75,23 +85,54 @@ static inline int pr_print(int level, const char *format, ...) #define dev_vdbg(dev, format, arg...) \ __dev_printf(8, (dev) , format , ## arg) +#define dev_emerg_once(dev, format, arg...) \ + __dev_printf_once(0, (dev) , format , ## arg) +#define dev_alert_once(dev, format, arg...) \ + __dev_printf_once(1, (dev) , format , ## arg) +#define dev_crit_once(dev, format, arg...) \ + __dev_printf_once(2, (dev) , format , ## arg) +#define dev_err_once(dev, format, arg...) \ + __dev_prin_oncetf(3, (dev) , format , ## arg) +#define dev_warn_once(dev, format, arg...) \ + __dev_printf_once(4, (dev) , format , ## arg) +#define dev_notice_once(dev, format, arg...) \ + __dev_printf(_once5, (dev) , format , ## arg) +#define dev_info_once(dev, format, arg...) \ + __dev_printf_once(6, (dev) , format , ## arg) +#define dev_dbg_once(dev, format, arg...) \ + __dev_prin_oncetf(7, (dev) , format , ## arg) +#define dev_vdbg_once(dev, format, arg...) \ + __dev_printf_once(8, (dev) , format , ## arg) + #if LOGLEVEL >= MSG_ERR -int dev_err_probe(const struct device_d *dev, int err, const char *fmt, ...) +int dev_err_probe(struct device *dev, int err, const char *fmt, ...) __attribute__ ((format(__printf__, 3, 4))); #elif !defined(dev_err_probe) -static int dev_err_probe(const struct device_d *dev, int err, const char *fmt, ...) +static int dev_err_probe(struct device *dev, int err, const char *fmt, ...) __attribute__ ((format(__printf__, 3, 4))); -static inline int dev_err_probe(const struct device_d *dev, int err, const char *fmt, ...) +static inline int dev_err_probe(struct device *dev, int err, const char *fmt, + ...) { return err; } #endif +#define dev_errp_probe(dev, errptr, args...) dev_err_probe((dev), PTR_ERR(errptr), args) + #define __pr_printk(level, format, args...) \ ({ \ (level) <= LOGLEVEL ? pr_print((level), (format), ##args) : 0; \ }) +#define __pr_printk_once(level, format, args...) do { \ + static bool __print_once; \ + \ + if (!__print_once && (level) <= LOGLEVEL) { \ + __print_once = true; \ + pr_print((level), (format), ##args); \ + } \ +} while (0) + #ifndef pr_fmt #define pr_fmt(fmt) fmt #endif @@ -108,7 +149,18 @@ static inline int dev_err_probe(const struct device_d *dev, int err, const char #define pr_vdebug(fmt, arg...) __pr_printk(8, pr_fmt(fmt), ##arg) #define pr_cont(fmt, arg...) __pr_printk(-1, fmt, ##arg) +#define pr_emerg_once(fmt, arg...) __pr_printk_once(0, pr_fmt(fmt), ##arg) +#define pr_alert_once(fmt, arg...) __pr_printk_once(1, pr_fmt(fmt), ##arg) +#define pr_crit_once(fmt, arg...) __pr_printk_once(2, pr_fmt(fmt), ##arg) +#define pr_err_once(fmt, arg...) __pr_printk_once(3, pr_fmt(fmt), ##arg) +#define pr_warning_once(fmt, arg...) __pr_printk_once(4, pr_fmt(fmt), ##arg) +#define pr_notice_once(fmt, arg...) __pr_printk_once(5, pr_fmt(fmt), ##arg) +#define pr_info_once(fmt, arg...) __pr_printk_once(6, pr_fmt(fmt), ##arg) +#define pr_debug_once(fmt, arg...) __pr_printk_once(7, pr_fmt(fmt), ##arg) +#define pr_vdebug_once(fmt, arg...) __pr_printk_once(8, pr_fmt(fmt), ##arg) + #define pr_warn pr_warning +#define pr_warn_once pr_warning_once int memory_display(const void *addr, loff_t offs, unsigned nbytes, int size, int swab); @@ -123,10 +175,9 @@ int __pr_memory_display(int level, const void *addr, loff_t offs, unsigned nbyte struct log_entry { struct list_head list; - char *msg; - void *dummy; uint64_t timestamp; int level; + char msg[]; }; extern struct list_head barebox_logbuf; @@ -137,18 +188,8 @@ extern void log_clean(unsigned int limit); #define BAREBOX_LOG_DIFF_TIME BIT(1) #define BAREBOX_LOG_PRINT_TIME BIT(0) -#define BAREBOX_LOG_PRINT_VDEBUG BIT(8) -#define BAREBOX_LOG_PRINT_DEBUG BIT(7) -#define BAREBOX_LOG_PRINT_INFO BIT(6) -#define BAREBOX_LOG_PRINT_NOTICE BIT(5) -#define BAREBOX_LOG_PRINT_WARNING BIT(4) -#define BAREBOX_LOG_PRINT_ERR BIT(3) -#define BAREBOX_LOG_PRINT_CRIT BIT(2) -#define BAREBOX_LOG_PRINT_ALERT BIT(1) -#define BAREBOX_LOG_PRINT_EMERG BIT(0) - int log_writefile(const char *filepath); -void log_print(unsigned flags, unsigned levels); +int log_print(unsigned flags, unsigned levels); struct va_format { const char *fmt; @@ -183,4 +224,17 @@ static inline void print_hex_dump_debug(const char *prefix_str, int prefix_type, #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true) +#define dev_WARN_ONCE(dev, condition, format...) ({ \ + static int __warned; \ + int __ret_warn_once = !!(condition); \ + \ + if (unlikely(__ret_warn_once)) { \ + if (!__warned) { \ + __warned = 1; \ + dev_warn(dev, format); \ + } \ + } \ + unlikely(__ret_warn_once); \ +}) + #endif diff --git a/include/linux/processor.h b/include/linux/processor.h new file mode 100644 index 0000000000..94a458c3d1 --- /dev/null +++ b/include/linux/processor.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Misc low level processor primitives */ +#ifndef _LINUX_PROCESSOR_H +#define _LINUX_PROCESSOR_H + +#include <linux/barebox-wrapper.h> + +/* + * spin_until_cond can be used to wait for a condition to become true. It + * may be expected that the first iteration will true in the common case + * (no spinning), so that callers should not require a first "likely" test + * for the uncontended case before using this primitive. + * + * Usage and implementation guidelines are the same as for the spin_begin + * primitives, above. + */ +#ifndef spin_until_cond +#define spin_until_cond(cond) \ +do { \ + if (unlikely(!(cond))) { \ + do { \ + cpu_relax(); \ + } while (!(cond)); \ + } \ +} while (0) + +#endif + +#endif /* _LINUX_PROCESSOR_H */ diff --git a/include/linux/pstore.h b/include/linux/pstore.h index f598f31a54..90e3bd2d42 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -23,7 +23,7 @@ #include <linux/time.h> #include <linux/types.h> -#include <asm-generic/errno.h> +#include <linux/errno.h> struct module; diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h index 9d9ce19c0e..66e7768fdf 100644 --- a/include/linux/reboot-mode.h +++ b/include/linux/reboot-mode.h @@ -4,11 +4,11 @@ #include <linux/types.h> -struct device_d; +struct device; #ifdef CONFIG_REBOOT_MODE struct reboot_mode_driver { - struct device_d *dev; + struct device *dev; int (*write)(struct reboot_mode_driver *reboot, const u32 *magic); int priority; bool no_fixup; diff --git a/include/linux/refcount.h b/include/linux/refcount.h new file mode 100644 index 0000000000..81eed1bbad --- /dev/null +++ b/include/linux/refcount.h @@ -0,0 +1,271 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _LINUX_REFCOUNT_H +#define _LINUX_REFCOUNT_H + +#include <linux/atomic.h> +#include <linux/bug.h> +#include <linux/compiler.h> +#include <linux/limits.h> + +/** + * typedef refcount_t - variant of atomic_t specialized for reference counts + * @refs: atomic_t counter field + * + * The counter saturates at REFCOUNT_SATURATED and will not move once + * there. This avoids wrapping the counter and causing 'spurious' + * use-after-free bugs. + */ +typedef struct refcount_struct { + atomic_t refs; +} refcount_t; + +#define REFCOUNT_INIT(n) { .refs = ATOMIC_INIT(n), } +#define REFCOUNT_MAX INT_MAX +#define REFCOUNT_SATURATED (INT_MIN / 2) + +enum refcount_saturation_type { + REFCOUNT_ADD_NOT_ZERO_OVF, + REFCOUNT_ADD_OVF, + REFCOUNT_ADD_UAF, + REFCOUNT_SUB_UAF, + REFCOUNT_DEC_LEAK, +}; + +void refcount_warn_saturate(refcount_t *r, enum refcount_saturation_type t); + +/** + * refcount_set - set a refcount's value + * @r: the refcount + * @n: value to which the refcount will be set + */ +static inline void refcount_set(refcount_t *r, int n) +{ + atomic_set(&r->refs, n); +} + +/** + * refcount_read - get a refcount's value + * @r: the refcount + * + * Return: the refcount's value + */ +static inline unsigned int refcount_read(const refcount_t *r) +{ + return atomic_read(&r->refs); +} + +static inline __must_check bool __refcount_add_not_zero(int i, refcount_t *r, int *oldp) +{ + int old = refcount_read(r); + + do { + if (!old) + break; + } while (!atomic_try_cmpxchg_relaxed(&r->refs, &old, old + i)); + + if (oldp) + *oldp = old; + + if (unlikely(old < 0 || old + i < 0)) + refcount_warn_saturate(r, REFCOUNT_ADD_NOT_ZERO_OVF); + + return old; +} + +/** + * refcount_add_not_zero - add a value to a refcount unless it is 0 + * @i: the value to add to the refcount + * @r: the refcount + * + * Will saturate at REFCOUNT_SATURATED and WARN. + * + * Provides no memory ordering, it is assumed the caller has guaranteed the + * object memory to be stable (RCU, etc.). It does provide a control dependency + * and thereby orders future stores. See the comment on top. + * + * Use of this function is not recommended for the normal reference counting + * use case in which references are taken and released one at a time. In these + * cases, refcount_inc(), or one of its variants, should instead be used to + * increment a reference count. + * + * Return: false if the passed refcount is 0, true otherwise + */ +static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r) +{ + return __refcount_add_not_zero(i, r, NULL); +} + +static inline void __refcount_add(int i, refcount_t *r, int *oldp) +{ + int old = atomic_fetch_add_relaxed(i, &r->refs); + + if (oldp) + *oldp = old; + + if (unlikely(!old)) + refcount_warn_saturate(r, REFCOUNT_ADD_UAF); + else if (unlikely(old < 0 || old + i < 0)) + refcount_warn_saturate(r, REFCOUNT_ADD_OVF); +} + +/** + * refcount_add - add a value to a refcount + * @i: the value to add to the refcount + * @r: the refcount + * + * Similar to atomic_add(), but will saturate at REFCOUNT_SATURATED and WARN. + * + * Provides no memory ordering, it is assumed the caller has guaranteed the + * object memory to be stable (RCU, etc.). It does provide a control dependency + * and thereby orders future stores. See the comment on top. + * + * Use of this function is not recommended for the normal reference counting + * use case in which references are taken and released one at a time. In these + * cases, refcount_inc(), or one of its variants, should instead be used to + * increment a reference count. + */ +static inline void refcount_add(int i, refcount_t *r) +{ + __refcount_add(i, r, NULL); +} + +static inline __must_check bool __refcount_inc_not_zero(refcount_t *r, int *oldp) +{ + return __refcount_add_not_zero(1, r, oldp); +} + +/** + * refcount_inc_not_zero - increment a refcount unless it is 0 + * @r: the refcount to increment + * + * Similar to atomic_inc_not_zero(), but will saturate at REFCOUNT_SATURATED + * and WARN. + * + * Provides no memory ordering, it is assumed the caller has guaranteed the + * object memory to be stable (RCU, etc.). It does provide a control dependency + * and thereby orders future stores. See the comment on top. + * + * Return: true if the increment was successful, false otherwise + */ +static inline __must_check bool refcount_inc_not_zero(refcount_t *r) +{ + return __refcount_inc_not_zero(r, NULL); +} + +static inline void __refcount_inc(refcount_t *r, int *oldp) +{ + __refcount_add(1, r, oldp); +} + +/** + * refcount_inc - increment a refcount + * @r: the refcount to increment + * + * Similar to atomic_inc(), but will saturate at REFCOUNT_SATURATED and WARN. + * + * Provides no memory ordering, it is assumed the caller already has a + * reference on the object. + * + * Will WARN if the refcount is 0, as this represents a possible use-after-free + * condition. + */ +static inline void refcount_inc(refcount_t *r) +{ + __refcount_inc(r, NULL); +} + +static inline __must_check bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp) +{ + int old = atomic_fetch_sub_release(i, &r->refs); + + if (oldp) + *oldp = old; + + if (old == i) + return true; + + if (unlikely(old < 0 || old - i < 0)) + refcount_warn_saturate(r, REFCOUNT_SUB_UAF); + + return false; +} + +/** + * refcount_sub_and_test - subtract from a refcount and test if it is 0 + * @i: amount to subtract from the refcount + * @r: the refcount + * + * Similar to atomic_dec_and_test(), but it will WARN, return false and + * ultimately leak on underflow and will fail to decrement when saturated + * at REFCOUNT_SATURATED. + * + * Provides release memory ordering, such that prior loads and stores are done + * before, and provides an acquire ordering on success such that free() + * must come after. + * + * Use of this function is not recommended for the normal reference counting + * use case in which references are taken and released one at a time. In these + * cases, refcount_dec(), or one of its variants, should instead be used to + * decrement a reference count. + * + * Return: true if the resulting refcount is 0, false otherwise + */ +static inline __must_check bool refcount_sub_and_test(int i, refcount_t *r) +{ + return __refcount_sub_and_test(i, r, NULL); +} + +static inline __must_check bool __refcount_dec_and_test(refcount_t *r, int *oldp) +{ + return __refcount_sub_and_test(1, r, oldp); +} + +/** + * refcount_dec_and_test - decrement a refcount and test if it is 0 + * @r: the refcount + * + * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to + * decrement when saturated at REFCOUNT_SATURATED. + * + * Provides release memory ordering, such that prior loads and stores are done + * before, and provides an acquire ordering on success such that free() + * must come after. + * + * Return: true if the resulting refcount is 0, false otherwise + */ +static inline __must_check bool refcount_dec_and_test(refcount_t *r) +{ + return __refcount_dec_and_test(r, NULL); +} + +static inline void __refcount_dec(refcount_t *r, int *oldp) +{ + int old = atomic_fetch_sub_release(1, &r->refs); + + if (oldp) + *oldp = old; + + if (unlikely(old <= 1)) + refcount_warn_saturate(r, REFCOUNT_DEC_LEAK); +} + +/** + * refcount_dec - decrement a refcount + * @r: the refcount + * + * Similar to atomic_dec(), it will WARN on underflow and fail to decrement + * when saturated at REFCOUNT_SATURATED. + * + * Provides release memory ordering, such that prior loads and stores are done + * before. + */ +static inline void refcount_dec(refcount_t *r) +{ + __refcount_dec(r, NULL); +} + +extern __must_check bool refcount_dec_if_one(refcount_t *r); +extern __must_check bool refcount_dec_not_one(refcount_t *r); + +#endif /* _LINUX_REFCOUNT_H */ diff --git a/include/linux/regmap.h b/include/linux/regmap.h new file mode 100644 index 0000000000..3ba0f852f6 --- /dev/null +++ b/include/linux/regmap.h @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __LINUX_REGMAP_H +#define __LINUX_REGMAP_H + +#include <linux/compiler.h> +#include <linux/iopoll.h> +#include <linux/types.h> + +enum regmap_endian { + /* Unspecified -> 0 -> Backwards compatible default */ + REGMAP_ENDIAN_DEFAULT = 0, + REGMAP_ENDIAN_BIG, + REGMAP_ENDIAN_LITTLE, + REGMAP_ENDIAN_NATIVE, +}; + +/** + * Configuration for the register map of a device. + * + * @name: Optional name of the regmap. Useful when a device has multiple + * register regions. + * + * @reg_bits: Number of bits in a register address, mandatory. + * @reg_stride: The register address stride. Valid register addresses are a + * multiple of this value. If set to 0, a value of 1 will be + * used. + * @pad_bits: Number of bits of padding between register and value. + * @val_bits: Number of bits in a register value, mandatory. + * + * @write: Write operation. + * @read: Read operation. Data is returned in the buffer used to transmit + * data. + * + * @max_register: Optional, specifies the maximum valid register index. + * This must be a valid register address and thus a multiple + * of the register stride returned by regmap_get_reg_stride() + * after registration. + * + * @read_flag_mask: Mask to be set in the top byte of the register when doing + * a read. + */ +struct regmap_config { + const char *name; + + int reg_bits; + int reg_stride; + int pad_bits; + int val_bits; + + unsigned int max_register; + + enum regmap_endian reg_format_endian; + enum regmap_endian val_format_endian; + + unsigned int read_flag_mask; + unsigned int write_flag_mask; +}; + +typedef int (*regmap_hw_write)(void *context, const void *data, + size_t count); +typedef int (*regmap_hw_read)(void *context, + const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size); +typedef int (*regmap_hw_reg_read)(void *context, unsigned int reg, + unsigned int *val); +typedef int (*regmap_hw_reg_write)(void *context, unsigned int reg, + unsigned int val); + +/** + * struct regmap_bus - Description of a hardware bus for the register map + * infrastructure. + * + * @reg_write: Write a single register value to the given register address. This + * write operation has to complete when returning from the function. + * @reg_read: Read a single register value from a given register address. + * @read: Read operation. Data is returned in the buffer used to transmit + * data. + * @write: Write operation. + * @read_flag_mask: Mask to be set in the top byte of the register when doing + * a read. + * @reg_format_endian_default: Default endianness for formatted register + * addresses. Used when the regmap_config specifies DEFAULT. If this is + * DEFAULT, BIG is assumed. + * @val_format_endian_default: Default endianness for formatted register + * values. Used when the regmap_config specifies DEFAULT. If this is + * DEFAULT, BIG is assumed. + */ +struct regmap_bus { + regmap_hw_reg_write reg_write; + regmap_hw_reg_read reg_read; + + int (*read)(void *context, + const void *reg_buf, size_t reg_size, + void *val_buf, size_t val_size); + int (*write)(void *context, const void *data, + size_t count); + + u8 read_flag_mask; + + enum regmap_endian reg_format_endian_default; + enum regmap_endian val_format_endian_default; +}; + +struct device; +struct device_node; + +struct regmap *regmap_init(struct device *dev, + const struct regmap_bus *bus, + void *bus_context, + const struct regmap_config *config); + +struct clk; + +/** + * regmap_init_mmio_clk() - Initialise register map with register clock + * + * @dev: Device that will be interacted with + * @clk_id: register clock consumer ID + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, + void __iomem *regs, + const struct regmap_config *config); + +/** + * regmap_init_i2c() - Initialise i2c register map + * + * @i2c: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. + */ +struct i2c_client; +struct regmap *regmap_init_i2c(struct i2c_client *i2c, + const struct regmap_config *config); + +struct regmap *regmap_init_i2c_smbus(struct i2c_client *client, + const struct regmap_config *config); + +/** + * regmap_init_spi() - Initialise spi register map + * + * @spi: Device that will be interacted with + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer + * to a struct regmap. + */ +struct spi_device; +struct regmap *regmap_init_spi(struct spi_device *dev, + const struct regmap_config *config); + +/** + * regmap_init_mmio() - Initialise register map + * + * @dev: Device that will be interacted with + * @regs: Pointer to memory-mapped IO region + * @config: Configuration for register map + * + * The return value will be an ERR_PTR() on error or a valid pointer to + * a struct regmap. + */ +#define regmap_init_mmio(dev, regs, config) \ + regmap_init_mmio_clk(dev, NULL, regs, config) + + +int regmap_mmio_attach_clk(struct regmap *map, struct clk *clk); +void regmap_mmio_detach_clk(struct regmap *map); + +void regmap_exit(struct regmap *map); + +struct regmap *dev_get_regmap(struct device *dev, const char *name); +struct device *regmap_get_device(struct regmap *map); + +int regmap_register_cdev(struct regmap *map, const char *name); + +/** + * regmap_multi_register_cdev() - Initialize cdev backed by multiple regmaps + * + * @map8: regmap for 8-bit wide accesses. NULL if such access + * should fail with -EINVAL + * @map16: regmap for 16-bit wide accesses. NULL if such access + * should fail with -EINVAL + * @map32: regmap for 32-bit wide accesses. NULL if such access + * should fail with -EINVAL + * @map64: regmap for 64-bit wide accesses. NULL if such access + * should fail with -EINVAL + * + * Registers a cdev that demultiplexes cdev accesses to one + * of the underlying regmaps according to the access size + * (e.g. mw -b => map8, mw -l => map32) + */ +int regmap_multi_register_cdev(struct regmap *map8, + struct regmap *map16, + struct regmap *map32, + struct regmap *map64); + +int regmap_write(struct regmap *map, unsigned int reg, unsigned int val); +int regmap_read(struct regmap *map, unsigned int reg, unsigned int *val); + +#ifndef regmap_bulk_read +#define regmap_bulk_read regmap_bulk_read +int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, + size_t val_count); +#endif +#ifndef regmap_bulk_write +#define regmap_bulk_write regmap_bulk_write +int regmap_bulk_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_count); +#endif + +int regmap_get_val_bytes(struct regmap *map); +int regmap_get_max_register(struct regmap *map); +int regmap_get_reg_stride(struct regmap *map); + +int regmap_write_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val); +int regmap_update_bits(struct regmap *map, unsigned int reg, + unsigned int mask, unsigned int val); + +static inline int regmap_set_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + return regmap_update_bits(map, reg, bits, bits); +} + +static inline int regmap_clear_bits(struct regmap *map, + unsigned int reg, unsigned int bits) +{ + return regmap_update_bits(map, reg, bits, 0); +} + +size_t regmap_size_bytes(struct regmap *map); + +/** + * regmap_read_poll_timeout - Poll until a condition is met or a timeout occurs + * + * @map: Regmap to read from + * @addr: Address to poll + * @val: Unsigned integer variable to read the value into + * @cond: Break condition (usually involving @val) + * @timeout_us: Timeout in us, 0 means never timeout + * + * Returns 0 on success and -ETIMEDOUT upon a timeout or the regmap_read + * error return value in case of a error read. In the two former cases, + * the last read value at @addr is stored in @val. Must not be called + * from atomic context if sleep_us or timeout_us are used. + * + * This is modelled after the readx_poll_timeout macros in linux/iopoll.h. + */ +#define regmap_read_poll_timeout(map, addr, val, cond, timeout_us) \ +({ \ + int __ret, __tmp; \ + __tmp = read_poll_timeout(regmap_read, __ret, __ret || (cond), \ + timeout_us, (map), (addr), &(val)); \ + __ret ?: __tmp; \ +}) + +#endif /* __LINUX_REGMAP_H */ diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h index de6d053e26..649e11db9f 100644 --- a/include/linux/regulator/of_regulator.h +++ b/include/linux/regulator/of_regulator.h @@ -8,7 +8,7 @@ #include <linux/types.h> -struct device_d; +struct device; struct regulator_desc; struct of_regulator_match { @@ -19,11 +19,11 @@ struct of_regulator_match { }; #if defined(CONFIG_OFDEVICE) -extern int of_regulator_match(struct device_d *dev, struct device_node *node, +extern int of_regulator_match(struct device *dev, struct device_node *node, struct of_regulator_match *matches, unsigned int num_matches); #else -static inline int of_regulator_match(struct device_d *dev, +static inline int of_regulator_match(struct device *dev, struct device_node *node, struct of_regulator_match *matches, unsigned int num_matches) diff --git a/include/linux/remoteproc.h b/include/linux/remoteproc.h index c6264d1c0a..33fe2f81b7 100644 --- a/include/linux/remoteproc.h +++ b/include/linux/remoteproc.h @@ -18,11 +18,6 @@ struct resource_table { u32 offset[0]; } __packed; -struct firmware { - size_t size; - const u8 *data; -}; - struct rproc; struct rproc_ops { @@ -37,13 +32,13 @@ struct rproc { const char *name; void *priv; struct rproc_ops *ops; - struct device_d dev; + struct device dev; void *fw_buf; size_t fw_buf_ofs; }; -struct rproc *rproc_alloc(struct device_d *dev, const char *name, +struct rproc *rproc_alloc(struct device *dev, const char *name, const struct rproc_ops *ops, int len); int rproc_add(struct rproc *rproc); diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h index aff03a9c62..a9047e947e 100644 --- a/include/linux/reset-controller.h +++ b/include/linux/reset-controller.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_RESET_CONTROLLER_H_ #define _LINUX_RESET_CONTROLLER_H_ @@ -12,11 +14,13 @@ struct reset_controller_dev; * things to reset the device * @assert: manually assert the reset line, if supported * @deassert: manually deassert the reset line, if supported + * @status: return the status of the reset line, if supported */ struct reset_control_ops { int (*reset)(struct reset_controller_dev *rcdev, unsigned long id); int (*assert)(struct reset_controller_dev *rcdev, unsigned long id); int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id); + int (*status)(struct reset_controller_dev *rcdev, unsigned long id); }; struct device_node; diff --git a/include/linux/reset.h b/include/linux/reset.h index 818b06412f..7db3d3162a 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -1,28 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_RESET_H_ #define _LINUX_RESET_H_ -struct device_d; +struct device; struct reset_control; #ifdef CONFIG_RESET_CONTROLLER +int reset_control_status(struct reset_control *rstc); int reset_control_reset(struct reset_control *rstc); int reset_control_assert(struct reset_control *rstc); int reset_control_deassert(struct reset_control *rstc); -struct reset_control *reset_control_get(struct device_d *dev, const char *id); +struct reset_control *reset_control_get(struct device *dev, const char *id); struct reset_control *of_reset_control_get(struct device_node *node, const char *id); void reset_control_put(struct reset_control *rstc); -int __must_check device_reset(struct device_d *dev); +int __must_check device_reset(struct device *dev); + +int __must_check device_reset_us(struct device *dev, int us); + +int __must_check device_reset_all(struct device *dev); -int __must_check device_reset_us(struct device_d *dev, int us); +int reset_control_get_count(struct device *dev); -int __must_check device_reset_all(struct device_d *dev); +struct reset_control *reset_control_array_get(struct device *dev); #else +static inline int reset_control_status(struct reset_control *rstc) +{ + return 0; +} + static inline int reset_control_reset(struct reset_control *rstc) { return 0; @@ -39,7 +51,13 @@ static inline int reset_control_deassert(struct reset_control *rstc) } static inline struct reset_control * -reset_control_get(struct device_d *dev, const char *id) +of_reset_control_get(struct device_node *node, const char *id) +{ + return NULL; +} + +static inline struct reset_control * +reset_control_get(struct device *dev, const char *id) { return NULL; } @@ -48,21 +66,38 @@ static inline void reset_control_put(struct reset_control *rstc) { } -static inline int device_reset_us(struct device_d *dev, int us) +static inline int device_reset_us(struct device *dev, int us) { return 0; } -static inline int device_reset(struct device_d *dev) +static inline int device_reset(struct device *dev) { return 0; } -static inline int device_reset_all(struct device_d *dev) +static inline int device_reset_all(struct device *dev) { return 0; } +static inline int reset_control_get_count(struct device *dev) +{ + return 0; +} + +static inline struct reset_control *reset_control_array_get(struct device *dev) +{ + return NULL; +} + #endif /* CONFIG_RESET_CONTROLLER */ +static inline struct reset_control *reset_control_get_optional(struct device *dev, + const char *id) +{ + struct reset_control *rstc = reset_control_get(dev, id); + return rstc == ERR_PTR(-ENOENT) ? NULL : rstc; +} + #endif diff --git a/include/linux/reset/reset-simple.h b/include/linux/reset/reset-simple.h new file mode 100644 index 0000000000..cb38a4b597 --- /dev/null +++ b/include/linux/reset/reset-simple.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Simple Reset Controller ops + * + * Based on Allwinner SoCs Reset Controller driver + * + * Copyright 2013 Maxime Ripard + * + * Maxime Ripard <maxime.ripard@free-electrons.com> + */ + +#ifndef __RESET_SIMPLE_H__ +#define __RESET_SIMPLE_H__ + +#include <io.h> +#include <linux/reset-controller.h> + +/** + * struct reset_simple_data - driver data for simple reset controllers + * @membase: memory mapped I/O register range + * @rcdev: reset controller device base structure + * @active_low: if true, bits are cleared to assert the reset. Otherwise, bits + * are set to assert the reset. Note that this says nothing about + * the voltage level of the actual reset line. + * @status_active_low: if true, bits read back as cleared while the reset is + * asserted. Otherwise, bits read back as set while the + * reset is asserted. + * @reset_us: Minimum delay in microseconds needed that needs to be + * waited for between an assert and a deassert to reset the + * device. If multiple consumers with different delay + * requirements are connected to this controller, it must + * be the largest minimum delay. 0 means that such a delay is + * unknown and the reset operation is unsupported. + */ +struct reset_simple_data { + void __iomem *membase; + struct reset_controller_dev rcdev; + bool active_low; + bool status_active_low; + unsigned int reset_us; +}; + +extern const struct reset_control_ops reset_simple_ops; + +#endif /* __RESET_SIMPLE_H__ */ diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 2dacb14239..def07548c5 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * Generic RTC interface. * This version contains the part of the user interface to the Real Time Clock @@ -22,8 +24,8 @@ extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm); struct rtc_class_ops; struct rtc_device { - struct device_d *dev; - struct device_d class_dev; + struct device *dev; + struct device class_dev; struct list_head list; const struct rtc_class_ops *ops; diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 5259957ed2..4ed693dc2c 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* rwsem.h: R/W semaphores, public interface * * Written by David Howells (dhowells@redhat.com). diff --git a/include/linux/sched.h b/include/linux/sched.h index 3375a09f2d..18b90ad884 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_SCHED_H #define _LINUX_SCHED_H diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h new file mode 100644 index 0000000000..a33cb497a1 --- /dev/null +++ b/include/linux/scmi_protocol.h @@ -0,0 +1,688 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * SCMI Message Protocol driver header + * + * Copyright (C) 2018-2021 ARM Ltd. + */ + +#ifndef _LINUX_SCMI_PROTOCOL_H +#define _LINUX_SCMI_PROTOCOL_H + +#include <linux/bitfield.h> +#include <linux/device.h> +#include <linux/ktime.h> +#include <notifier.h> +#include <linux/types.h> + +#define SCMI_MAX_STR_SIZE 64 +#define SCMI_SHORT_NAME_MAX_SIZE 16 +#define SCMI_MAX_NUM_RATES 16 + +/** + * struct scmi_revision_info - version information structure + * + * @major_ver: Major ABI version. Change here implies risk of backward + * compatibility break. + * @minor_ver: Minor ABI version. Change here implies new feature addition, + * or compatible change in ABI. + * @num_protocols: Number of protocols that are implemented, excluding the + * base protocol. + * @num_agents: Number of agents in the system. + * @impl_ver: A vendor-specific implementation version. + * @vendor_id: A vendor identifier(Null terminated ASCII string) + * @sub_vendor_id: A sub-vendor identifier(Null terminated ASCII string) + */ +struct scmi_revision_info { + u16 major_ver; + u16 minor_ver; + u8 num_protocols; + u8 num_agents; + u32 impl_ver; + char vendor_id[SCMI_SHORT_NAME_MAX_SIZE]; + char sub_vendor_id[SCMI_SHORT_NAME_MAX_SIZE]; +}; + +struct scmi_clock_info { + char name[SCMI_MAX_STR_SIZE]; + unsigned int enable_latency; + bool rate_discrete; + bool rate_changed_notifications; + bool rate_change_requested_notifications; + union { + struct { + int num_rates; + u64 rates[SCMI_MAX_NUM_RATES]; + } list; + struct { + u64 min_rate; + u64 max_rate; + u64 step_size; + } range; + }; +}; + +enum scmi_power_scale { + SCMI_POWER_BOGOWATTS, + SCMI_POWER_MILLIWATTS, + SCMI_POWER_MICROWATTS +}; + +struct scmi_handle; +struct scmi_device; +struct scmi_protocol_handle; + +/** + * struct scmi_clk_proto_ops - represents the various operations provided + * by SCMI Clock Protocol + * + * @count_get: get the count of clocks provided by SCMI + * @info_get: get the information of the specified clock + * @rate_get: request the current clock rate of a clock + * @rate_set: set the clock rate of a clock + * @enable: enables the specified clock + * @disable: disables the specified clock + */ +struct scmi_clk_proto_ops { + int (*count_get)(const struct scmi_protocol_handle *ph); + + const struct scmi_clock_info __must_check *(*info_get) + (const struct scmi_protocol_handle *ph, u32 clk_id); + int (*rate_get)(const struct scmi_protocol_handle *ph, u32 clk_id, + u64 *rate); + int (*rate_set)(const struct scmi_protocol_handle *ph, u32 clk_id, + u64 rate); + int (*enable)(const struct scmi_protocol_handle *ph, u32 clk_id); + int (*disable)(const struct scmi_protocol_handle *ph, u32 clk_id); + int (*enable_atomic)(const struct scmi_protocol_handle *ph, u32 clk_id); + int (*disable_atomic)(const struct scmi_protocol_handle *ph, + u32 clk_id); +}; + +/** + * struct scmi_perf_proto_ops - represents the various operations provided + * by SCMI Performance Protocol + * + * @limits_set: sets limits on the performance level of a domain + * @limits_get: gets limits on the performance level of a domain + * @level_set: sets the performance level of a domain + * @level_get: gets the performance level of a domain + * @device_domain_id: gets the scmi domain id for a given device + * @transition_latency_get: gets the DVFS transition latency for a given device + * @device_opps_add: adds all the OPPs for a given device + * @freq_set: sets the frequency for a given device using sustained frequency + * to sustained performance level mapping + * @freq_get: gets the frequency for a given device using sustained frequency + * to sustained performance level mapping + * @est_power_get: gets the estimated power cost for a given performance domain + * at a given frequency + * @fast_switch_possible: indicates if fast DVFS switching is possible or not + * for a given device + * @power_scale_mw_get: indicates if the power values provided are in milliWatts + * or in some other (abstract) scale + */ +struct scmi_perf_proto_ops { + int (*limits_set)(const struct scmi_protocol_handle *ph, u32 domain, + u32 max_perf, u32 min_perf); + int (*limits_get)(const struct scmi_protocol_handle *ph, u32 domain, + u32 *max_perf, u32 *min_perf); + int (*level_set)(const struct scmi_protocol_handle *ph, u32 domain, + u32 level, bool poll); + int (*level_get)(const struct scmi_protocol_handle *ph, u32 domain, + u32 *level, bool poll); + int (*device_domain_id)(struct device *dev); + int (*transition_latency_get)(const struct scmi_protocol_handle *ph, + struct device *dev); + int (*device_opps_add)(const struct scmi_protocol_handle *ph, + struct device *dev); + int (*freq_set)(const struct scmi_protocol_handle *ph, u32 domain, + unsigned long rate, bool poll); + int (*freq_get)(const struct scmi_protocol_handle *ph, u32 domain, + unsigned long *rate, bool poll); + int (*est_power_get)(const struct scmi_protocol_handle *ph, u32 domain, + unsigned long *rate, unsigned long *power); + bool (*fast_switch_possible)(const struct scmi_protocol_handle *ph, + struct device *dev); + enum scmi_power_scale (*power_scale_get)(const struct scmi_protocol_handle *ph); +}; + +/** + * struct scmi_power_proto_ops - represents the various operations provided + * by SCMI Power Protocol + * + * @num_domains_get: get the count of power domains provided by SCMI + * @name_get: gets the name of a power domain + * @state_set: sets the power state of a power domain + * @state_get: gets the power state of a power domain + */ +struct scmi_power_proto_ops { + int (*num_domains_get)(const struct scmi_protocol_handle *ph); + const char *(*name_get)(const struct scmi_protocol_handle *ph, + u32 domain); +#define SCMI_POWER_STATE_TYPE_SHIFT 30 +#define SCMI_POWER_STATE_ID_MASK (BIT(28) - 1) +#define SCMI_POWER_STATE_PARAM(type, id) \ + ((((type) & BIT(0)) << SCMI_POWER_STATE_TYPE_SHIFT) | \ + ((id) & SCMI_POWER_STATE_ID_MASK)) +#define SCMI_POWER_STATE_GENERIC_ON SCMI_POWER_STATE_PARAM(0, 0) +#define SCMI_POWER_STATE_GENERIC_OFF SCMI_POWER_STATE_PARAM(1, 0) + int (*state_set)(const struct scmi_protocol_handle *ph, u32 domain, + u32 state); + int (*state_get)(const struct scmi_protocol_handle *ph, u32 domain, + u32 *state); +}; + +/** + * struct scmi_sensor_reading - represent a timestamped read + * + * Used by @reading_get_timestamped method. + * + * @value: The signed value sensor read. + * @timestamp: An unsigned timestamp for the sensor read, as provided by + * SCMI platform. Set to zero when not available. + */ +struct scmi_sensor_reading { + long long value; + unsigned long long timestamp; +}; + +/** + * struct scmi_range_attrs - specifies a sensor or axis values' range + * @min_range: The minimum value which can be represented by the sensor/axis. + * @max_range: The maximum value which can be represented by the sensor/axis. + */ +struct scmi_range_attrs { + long long min_range; + long long max_range; +}; + +/** + * struct scmi_sensor_axis_info - describes one sensor axes + * @id: The axes ID. + * @type: Axes type. Chosen amongst one of @enum scmi_sensor_class. + * @scale: Power-of-10 multiplier applied to the axis unit. + * @name: NULL-terminated string representing axes name as advertised by + * SCMI platform. + * @extended_attrs: Flag to indicate the presence of additional extended + * attributes for this axes. + * @resolution: Extended attribute representing the resolution of the axes. + * Set to 0 if not reported by this axes. + * @exponent: Extended attribute representing the power-of-10 multiplier that + * is applied to the resolution field. Set to 0 if not reported by + * this axes. + * @attrs: Extended attributes representing minimum and maximum values + * measurable by this axes. Set to 0 if not reported by this sensor. + */ +struct scmi_sensor_axis_info { + unsigned int id; + unsigned int type; + int scale; + char name[SCMI_MAX_STR_SIZE]; + bool extended_attrs; + unsigned int resolution; + int exponent; + struct scmi_range_attrs attrs; +}; + +/** + * struct scmi_sensor_intervals_info - describes number and type of available + * update intervals + * @segmented: Flag for segmented intervals' representation. When True there + * will be exactly 3 intervals in @desc, with each entry + * representing a member of a segment in this order: + * {lowest update interval, highest update interval, step size} + * @count: Number of intervals described in @desc. + * @desc: Array of @count interval descriptor bitmask represented as detailed in + * the SCMI specification: it can be accessed using the accompanying + * macros. + * @prealloc_pool: A minimal preallocated pool of desc entries used to avoid + * lesser-than-64-bytes dynamic allocation for small @count + * values. + */ +struct scmi_sensor_intervals_info { + bool segmented; + unsigned int count; +#define SCMI_SENS_INTVL_SEGMENT_LOW 0 +#define SCMI_SENS_INTVL_SEGMENT_HIGH 1 +#define SCMI_SENS_INTVL_SEGMENT_STEP 2 + unsigned int *desc; +#define SCMI_SENS_INTVL_GET_SECS(x) FIELD_GET(GENMASK(20, 5), (x)) +#define SCMI_SENS_INTVL_GET_EXP(x) \ + ({ \ + int __signed_exp = FIELD_GET(GENMASK(4, 0), (x)); \ + \ + if (__signed_exp & BIT(4)) \ + __signed_exp |= GENMASK(31, 5); \ + __signed_exp; \ + }) +#define SCMI_MAX_PREALLOC_POOL 16 + unsigned int prealloc_pool[SCMI_MAX_PREALLOC_POOL]; +}; + +/** + * struct scmi_sensor_info - represents information related to one of the + * available sensors. + * @id: Sensor ID. + * @type: Sensor type. Chosen amongst one of @enum scmi_sensor_class. + * @scale: Power-of-10 multiplier applied to the sensor unit. + * @num_trip_points: Number of maximum configurable trip points. + * @update: Flag for continuouos update notification support. + * @timestamped: Flag for timestamped read support. + * @tstamp_scale: Power-of-10 multiplier applied to the sensor timestamps to + * represent it in seconds. + * @num_axis: Number of supported axis if any. Reported as 0 for scalar sensors. + * @axis: Pointer to an array of @num_axis descriptors. + * @intervals: Descriptor of available update intervals. + * @sensor_config: A bitmask reporting the current sensor configuration as + * detailed in the SCMI specification: it can accessed and + * modified through the accompanying macros. + * @name: NULL-terminated string representing sensor name as advertised by + * SCMI platform. + * @extended_scalar_attrs: Flag to indicate the presence of additional extended + * attributes for this sensor. + * @sensor_power: Extended attribute representing the average power + * consumed by the sensor in microwatts (uW) when it is active. + * Reported here only for scalar sensors. + * Set to 0 if not reported by this sensor. + * @resolution: Extended attribute representing the resolution of the sensor. + * Reported here only for scalar sensors. + * Set to 0 if not reported by this sensor. + * @exponent: Extended attribute representing the power-of-10 multiplier that is + * applied to the resolution field. + * Reported here only for scalar sensors. + * Set to 0 if not reported by this sensor. + * @scalar_attrs: Extended attributes representing minimum and maximum + * measurable values by this sensor. + * Reported here only for scalar sensors. + * Set to 0 if not reported by this sensor. + */ +struct scmi_sensor_info { + unsigned int id; + unsigned int type; + int scale; + unsigned int num_trip_points; + bool update; + bool timestamped; + int tstamp_scale; + unsigned int num_axis; + struct scmi_sensor_axis_info *axis; + struct scmi_sensor_intervals_info intervals; + unsigned int sensor_config; +#define SCMI_SENS_CFG_UPDATE_SECS_MASK GENMASK(31, 16) +#define SCMI_SENS_CFG_GET_UPDATE_SECS(x) \ + FIELD_GET(SCMI_SENS_CFG_UPDATE_SECS_MASK, (x)) + +#define SCMI_SENS_CFG_UPDATE_EXP_MASK GENMASK(15, 11) +#define SCMI_SENS_CFG_GET_UPDATE_EXP(x) \ + ({ \ + int __signed_exp = \ + FIELD_GET(SCMI_SENS_CFG_UPDATE_EXP_MASK, (x)); \ + \ + if (__signed_exp & BIT(4)) \ + __signed_exp |= GENMASK(31, 5); \ + __signed_exp; \ + }) + +#define SCMI_SENS_CFG_ROUND_MASK GENMASK(10, 9) +#define SCMI_SENS_CFG_ROUND_AUTO 2 +#define SCMI_SENS_CFG_ROUND_UP 1 +#define SCMI_SENS_CFG_ROUND_DOWN 0 + +#define SCMI_SENS_CFG_TSTAMP_ENABLED_MASK BIT(1) +#define SCMI_SENS_CFG_TSTAMP_ENABLE 1 +#define SCMI_SENS_CFG_TSTAMP_DISABLE 0 +#define SCMI_SENS_CFG_IS_TSTAMP_ENABLED(x) \ + FIELD_GET(SCMI_SENS_CFG_TSTAMP_ENABLED_MASK, (x)) + +#define SCMI_SENS_CFG_SENSOR_ENABLED_MASK BIT(0) +#define SCMI_SENS_CFG_SENSOR_ENABLE 1 +#define SCMI_SENS_CFG_SENSOR_DISABLE 0 + char name[SCMI_MAX_STR_SIZE]; +#define SCMI_SENS_CFG_IS_ENABLED(x) FIELD_GET(BIT(0), (x)) + bool extended_scalar_attrs; + unsigned int sensor_power; + unsigned int resolution; + int exponent; + struct scmi_range_attrs scalar_attrs; +}; + +/* + * Partial list from Distributed Management Task Force (DMTF) specification: + * DSP0249 (Platform Level Data Model specification) + */ +enum scmi_sensor_class { + NONE = 0x0, + UNSPEC = 0x1, + TEMPERATURE_C = 0x2, + TEMPERATURE_F = 0x3, + TEMPERATURE_K = 0x4, + VOLTAGE = 0x5, + CURRENT = 0x6, + POWER = 0x7, + ENERGY = 0x8, + CHARGE = 0x9, + VOLTAMPERE = 0xA, + NITS = 0xB, + LUMENS = 0xC, + LUX = 0xD, + CANDELAS = 0xE, + KPA = 0xF, + PSI = 0x10, + NEWTON = 0x11, + CFM = 0x12, + RPM = 0x13, + HERTZ = 0x14, + SECS = 0x15, + MINS = 0x16, + HOURS = 0x17, + DAYS = 0x18, + WEEKS = 0x19, + MILS = 0x1A, + INCHES = 0x1B, + FEET = 0x1C, + CUBIC_INCHES = 0x1D, + CUBIC_FEET = 0x1E, + METERS = 0x1F, + CUBIC_CM = 0x20, + CUBIC_METERS = 0x21, + LITERS = 0x22, + FLUID_OUNCES = 0x23, + RADIANS = 0x24, + STERADIANS = 0x25, + REVOLUTIONS = 0x26, + CYCLES = 0x27, + GRAVITIES = 0x28, + OUNCES = 0x29, + POUNDS = 0x2A, + FOOT_POUNDS = 0x2B, + OUNCE_INCHES = 0x2C, + GAUSS = 0x2D, + GILBERTS = 0x2E, + HENRIES = 0x2F, + FARADS = 0x30, + OHMS = 0x31, + SIEMENS = 0x32, + MOLES = 0x33, + BECQUERELS = 0x34, + PPM = 0x35, + DECIBELS = 0x36, + DBA = 0x37, + DBC = 0x38, + GRAYS = 0x39, + SIEVERTS = 0x3A, + COLOR_TEMP_K = 0x3B, + BITS = 0x3C, + BYTES = 0x3D, + WORDS = 0x3E, + DWORDS = 0x3F, + QWORDS = 0x40, + PERCENTAGE = 0x41, + PASCALS = 0x42, + COUNTS = 0x43, + GRAMS = 0x44, + NEWTON_METERS = 0x45, + HITS = 0x46, + MISSES = 0x47, + RETRIES = 0x48, + OVERRUNS = 0x49, + UNDERRUNS = 0x4A, + COLLISIONS = 0x4B, + PACKETS = 0x4C, + MESSAGES = 0x4D, + CHARS = 0x4E, + ERRORS = 0x4F, + CORRECTED_ERRS = 0x50, + UNCORRECTABLE_ERRS = 0x51, + SQ_MILS = 0x52, + SQ_INCHES = 0x53, + SQ_FEET = 0x54, + SQ_CM = 0x55, + SQ_METERS = 0x56, + RADIANS_SEC = 0x57, + BPM = 0x58, + METERS_SEC_SQUARED = 0x59, + METERS_SEC = 0x5A, + CUBIC_METERS_SEC = 0x5B, + MM_MERCURY = 0x5C, + RADIANS_SEC_SQUARED = 0x5D, + OEM_UNIT = 0xFF +}; + +/** + * struct scmi_sensor_proto_ops - represents the various operations provided + * by SCMI Sensor Protocol + * + * @count_get: get the count of sensors provided by SCMI + * @info_get: get the information of the specified sensor + * @trip_point_config: selects and configures a trip-point of interest + * @reading_get: gets the current value of the sensor + * @reading_get_timestamped: gets the current value and timestamp, when + * available, of the sensor. (as of v3.0 spec) + * Supports multi-axis sensors for sensors which + * supports it and if the @reading array size of + * @count entry equals the sensor num_axis + * @config_get: Get sensor current configuration + * @config_set: Set sensor current configuration + */ +struct scmi_sensor_proto_ops { + int (*count_get)(const struct scmi_protocol_handle *ph); + const struct scmi_sensor_info __must_check *(*info_get) + (const struct scmi_protocol_handle *ph, u32 sensor_id); + int (*trip_point_config)(const struct scmi_protocol_handle *ph, + u32 sensor_id, u8 trip_id, u64 trip_value); + int (*reading_get)(const struct scmi_protocol_handle *ph, u32 sensor_id, + u64 *value); + int (*reading_get_timestamped)(const struct scmi_protocol_handle *ph, + u32 sensor_id, u8 count, + struct scmi_sensor_reading *readings); + int (*config_get)(const struct scmi_protocol_handle *ph, + u32 sensor_id, u32 *sensor_config); + int (*config_set)(const struct scmi_protocol_handle *ph, + u32 sensor_id, u32 sensor_config); +}; + +/** + * struct scmi_reset_proto_ops - represents the various operations provided + * by SCMI Reset Protocol + * + * @num_domains_get: get the count of reset domains provided by SCMI + * @name_get: gets the name of a reset domain + * @latency_get: gets the reset latency for the specified reset domain + * @reset: resets the specified reset domain + * @assert: explicitly assert reset signal of the specified reset domain + * @deassert: explicitly deassert reset signal of the specified reset domain + */ +struct scmi_reset_proto_ops { + int (*num_domains_get)(const struct scmi_protocol_handle *ph); + const char *(*name_get)(const struct scmi_protocol_handle *ph, + u32 domain); + int (*latency_get)(const struct scmi_protocol_handle *ph, u32 domain); + int (*reset)(const struct scmi_protocol_handle *ph, u32 domain); + int (*assert)(const struct scmi_protocol_handle *ph, u32 domain); + int (*deassert)(const struct scmi_protocol_handle *ph, u32 domain); +}; + +enum scmi_voltage_level_mode { + SCMI_VOLTAGE_LEVEL_SET_AUTO, + SCMI_VOLTAGE_LEVEL_SET_SYNC, +}; + +/** + * struct scmi_voltage_info - describe one available SCMI Voltage Domain + * + * @id: the domain ID as advertised by the platform + * @segmented: defines the layout of the entries of array @levels_uv. + * - when True the entries are to be interpreted as triplets, + * each defining a segment representing a range of equally + * space voltages: <lowest_volts>, <highest_volt>, <step_uV> + * - when False the entries simply represent a single discrete + * supported voltage level + * @negative_volts_allowed: True if any of the entries of @levels_uv represent + * a negative voltage. + * @name: name assigned to the Voltage Domain by platform + * @num_levels: number of total entries in @levels_uv. + * @levels_uv: array of entries describing the available voltage levels for + * this domain. + */ +struct scmi_voltage_info { + unsigned int id; + bool segmented; + bool negative_volts_allowed; + char name[SCMI_MAX_STR_SIZE]; + unsigned int num_levels; +#define SCMI_VOLTAGE_SEGMENT_LOW 0 +#define SCMI_VOLTAGE_SEGMENT_HIGH 1 +#define SCMI_VOLTAGE_SEGMENT_STEP 2 + int *levels_uv; +}; + +/** + * struct scmi_voltage_proto_ops - represents the various operations provided + * by SCMI Voltage Protocol + * + * @num_domains_get: get the count of voltage domains provided by SCMI + * @info_get: get the information of the specified domain + * @config_set: set the config for the specified domain + * @config_get: get the config of the specified domain + * @level_set: set the voltage level for the specified domain + * @level_get: get the voltage level of the specified domain + */ +struct scmi_voltage_proto_ops { + int (*num_domains_get)(const struct scmi_protocol_handle *ph); + const struct scmi_voltage_info __must_check *(*info_get) + (const struct scmi_protocol_handle *ph, u32 domain_id); + int (*config_set)(const struct scmi_protocol_handle *ph, u32 domain_id, + u32 config); +#define SCMI_VOLTAGE_ARCH_STATE_OFF 0x0 +#define SCMI_VOLTAGE_ARCH_STATE_ON 0x7 + int (*config_get)(const struct scmi_protocol_handle *ph, u32 domain_id, + u32 *config); + int (*level_set)(const struct scmi_protocol_handle *ph, u32 domain_id, + enum scmi_voltage_level_mode mode, s32 volt_uV); + int (*level_get)(const struct scmi_protocol_handle *ph, u32 domain_id, + s32 *volt_uV); +}; + +/** + * struct scmi_handle - Handle returned to ARM SCMI clients for usage. + * + * @dev: pointer to the SCMI device + * @version: pointer to the structure containing SCMI version information + * @dev_protocol_acquire: get hold of a protocol, + * causing its initialization and related resource + * accounting + * @dev_protocol_get: devres managed method to acquire a protocol and get specific + * operations and a dedicated protocol handler + * @dev_protocol_put: devres managed method to release a protocol + * @is_transport_atomic: method to check if the underlying transport for this + * instance handle is configured to support atomic + * transactions for commands. + * Some users of the SCMI stack in the upper layers could + * be interested to know if they can assume SCMI + * command transactions associated to this handle will + * never sleep and act accordingly. + * An optional atomic threshold value could be returned + * where configured. + * @notify_ops: pointer to set of notifications related operations + */ +struct scmi_handle { + struct device *dev; + struct scmi_revision_info *version; + + int __must_check (*dev_protocol_acquire)(struct scmi_device *sdev, + u8 proto); + const void __must_check * + (*dev_protocol_get)(struct scmi_device *sdev, u8 proto, + struct scmi_protocol_handle **ph); + void (*dev_protocol_put)(struct scmi_device *sdev, u8 proto); + bool (*is_transport_atomic)(const struct scmi_handle *handle, + unsigned int *atomic_threshold); +}; + +enum scmi_std_protocol { + SCMI_PROTOCOL_BASE = 0x10, + SCMI_PROTOCOL_POWER = 0x11, + SCMI_PROTOCOL_SYSTEM = 0x12, + SCMI_PROTOCOL_PERF = 0x13, + SCMI_PROTOCOL_CLOCK = 0x14, + SCMI_PROTOCOL_SENSOR = 0x15, + SCMI_PROTOCOL_RESET = 0x16, + SCMI_PROTOCOL_VOLTAGE = 0x17, +}; + +enum scmi_system_events { + SCMI_SYSTEM_SHUTDOWN, + SCMI_SYSTEM_COLDRESET, + SCMI_SYSTEM_WARMRESET, + SCMI_SYSTEM_POWERUP, + SCMI_SYSTEM_SUSPEND, + SCMI_SYSTEM_MAX +}; + +struct scmi_device { + u8 protocol_id; + const char *name; + struct device dev; + struct scmi_handle *handle; +}; + +#define to_scmi_dev(d) container_of(d, struct scmi_device, dev) + +struct scmi_device_id { + u8 protocol_id; + const char *name; +}; + +struct scmi_driver { + const char *name; + int (*probe)(struct scmi_device *sdev); + const struct scmi_device_id *id_table; + + struct device_driver driver; +}; + +#define to_scmi_driver(d) container_of(d, struct scmi_driver, driver) + +#if IS_REACHABLE(CONFIG_ARM_SCMI_PROTOCOL) +int scmi_driver_register(struct scmi_driver *driver); +#else +static inline int +scmi_driver_register(struct scmi_driver *driver) +{ + return -EINVAL; +} + +#endif /* CONFIG_ARM_SCMI_PROTOCOL */ + +#define scmi_register(driver) \ + scmi_driver_register(driver) + +/** + * coredevice_scmi_driver() - Helper macro for registering a scmi driver + * @__scmi_driver: scmi_driver structure + * + * Helper macro for scmi drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define coredevice_scmi_driver(__scmi_driver) \ + register_driver_macro(coredevice,scmi,__scmi_driver) + +#define core_scmi_driver(__scmi_driver) \ + register_driver_macro(core,scmi,__scmi_driver) + +/** + * module_scmi_protocol() - Helper macro for registering a scmi protocol + * @__scmi_protocol: scmi_protocol structure + * + * Helper macro for scmi drivers to set up proper module init / exit + * functions. Replaces module_init() and module_exit() and keeps people from + * printing pointless things to the kernel log when their driver is loaded. + */ +#define module_scmi_protocol(__scmi_protocol) \ + module_driver(__scmi_protocol, \ + scmi_protocol_register, scmi_protocol_unregister) + +struct scmi_protocol; +int scmi_protocol_register(const struct scmi_protocol *proto); + +#endif /* _LINUX_SCMI_PROTOCOL_H */ diff --git a/include/linux/sizes.h b/include/linux/sizes.h index fbde0bc7e8..08fe344bc4 100644 --- a/include/linux/sizes.h +++ b/include/linux/sizes.h @@ -47,5 +47,20 @@ #define SZ_2G 0x80000000 #define SZ_4G _AC(0x100000000, ULL) +#define SZ_8G _AC(0x200000000, ULL) +#define SZ_16G _AC(0x400000000, ULL) +#define SZ_32G _AC(0x800000000, ULL) +#define SZ_64G _AC(0x1000000000, ULL) +#define SZ_128G _AC(0x2000000000, ULL) +#define SZ_256G _AC(0x4000000000, ULL) +#define SZ_512G _AC(0x8000000000, ULL) + +#define SZ_1T _AC(0x10000000000, ULL) +#define SZ_2T _AC(0x20000000000, ULL) +#define SZ_4T _AC(0x40000000000, ULL) +#define SZ_8T _AC(0x80000000000, ULL) +#define SZ_16T _AC(0x100000000000, ULL) +#define SZ_32T _AC(0x200000000000, ULL) +#define SZ_64T _AC(0x400000000000, ULL) #endif /* __LINUX_SIZES_H__ */ diff --git a/include/linux/slab.h b/include/linux/slab.h index 806d5bfb21..dc80808938 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -1,6 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_SLAB_H #define _LINUX_SLAB_H +#include <malloc.h> +#include <linux/string.h> + #define SLAB_CONSISTENCY_CHECKS 0 #define SLAB_RED_ZONE 0 #define SLAB_POISON 0 @@ -101,4 +106,17 @@ static inline void *kcalloc(size_t n, size_t size, gfp_t flags) return calloc(n, size); } +static inline void *krealloc(void *ptr, size_t size, gfp_t flags) +{ + return realloc(ptr, size); +} + +static inline char *kstrdup(const char *str, gfp_t flags) +{ + return strdup(str); +} + +#define kstrdup_const(str, flags) strdup(str) +#define kfree_const(ptr) kfree((void *)ptr) + #endif /* _LINUX_SLAB_H */ diff --git a/include/linux/smscphy.h b/include/linux/smscphy.h index ce718cbce4..45e1192384 100644 --- a/include/linux/smscphy.h +++ b/include/linux/smscphy.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_SMSCPHY_H__ #define __LINUX_SMSCPHY_H__ diff --git a/include/linux/spi/spi-mem.h b/include/linux/spi/spi-mem.h index f65104d2d1..b5dfb0ca84 100644 --- a/include/linux/spi/spi-mem.h +++ b/include/linux/spi/spi-mem.h @@ -280,7 +280,7 @@ struct spi_controller_mem_ops { * useless fields to the spi_device object. */ struct spi_mem_driver { - struct driver_d spidrv; + struct driver spidrv; int (*probe)(struct spi_mem *mem); int (*remove)(struct spi_mem *mem); }; diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h index b32114f4f0..6f90fb1cad 100644 --- a/include/linux/spinlock.h +++ b/include/linux/spinlock.h @@ -1,11 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_SPINLOCK_H #define __LINUX_SPINLOCK_H typedef int spinlock_t; #define spin_lock_init(...) #define spin_lock(...) +#define spin_lock_bh spin_lock #define spin_unlock(...) +#define spin_unlock_bh spin_unlock #define spin_lock_irqsave(lock, flags) do { flags = 0; } while (0) #define spin_unlock_irqrestore(lock, flags) do { flags = flags; } while (0) +#define DEFINE_SPINLOCK(lock) spinlock_t __always_unused lock + #endif /* __LINUX_SPINLOCK_H */ diff --git a/include/linux/stat.h b/include/linux/stat.h index f5043d8bce..fc3dd222a6 100644 --- a/include/linux/stat.h +++ b/include/linux/stat.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_STAT_H #define _LINUX_STAT_H @@ -47,11 +49,8 @@ extern "C" { struct stat { unsigned long st_ino; unsigned short st_mode; - unsigned short st_nlink; unsigned short st_uid; unsigned short st_gid; - unsigned short st_rdev; - unsigned short __pad2; loff_t st_size; }; diff --git a/include/linux/stddef.h b/include/linux/stddef.h index 680d0c7662..88ff6f1733 100644 --- a/include/linux/stddef.h +++ b/include/linux/stddef.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_STDDEF_H #define _LINUX_STDDEF_H @@ -20,6 +22,121 @@ enum { typedef unsigned short wchar_t; #undef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) + +/** + * sizeof_field() - Report the size of a struct field in bytes + * + * @TYPE: The structure containing the field of interest + * @MEMBER: The field to return the size of + */ +#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) + +/** + * offsetofend() - Report the offset of a struct field within the struct + * + * @TYPE: The type of the structure + * @MEMBER: The member within the structure to get the end offset of + */ +#define offsetofend(TYPE, MEMBER) \ + (offsetof(TYPE, MEMBER) + sizeof_field(TYPE, MEMBER)) + +/** + * __struct_group() - Create a mirrored named and anonyomous struct + * + * @TAG: The tag name for the named sub-struct (usually empty) + * @NAME: The identifier name of the mirrored sub-struct + * @ATTRS: Any struct attributes (usually empty) + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical layout + * and size: one anonymous and one named. The former's members can be used + * normally without sub-struct naming, and the latter can be used to + * reason about the start, end, and size of the group of struct members. + * The named struct can also be explicitly tagged for layer reuse, as well + * as both having struct attributes appended. + */ +#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \ + union { \ + struct { MEMBERS } ATTRS; \ + struct TAG { MEMBERS } ATTRS NAME; \ + } + +/** + * struct_group() - Wrap a set of declarations in a mirrored struct + * + * @NAME: The identifier name of the mirrored sub-struct + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical + * layout and size: one anonymous and one named. The former can be + * used normally without sub-struct naming, and the latter can be + * used to reason about the start, end, and size of the group of + * struct members. + */ +#define struct_group(NAME, MEMBERS...) \ + __struct_group(/* no tag */, NAME, /* no attrs */, MEMBERS) + +/** + * struct_group_attr() - Create a struct_group() with trailing attributes + * + * @NAME: The identifier name of the mirrored sub-struct + * @ATTRS: Any struct attributes to apply + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical + * layout and size: one anonymous and one named. The former can be + * used normally without sub-struct naming, and the latter can be + * used to reason about the start, end, and size of the group of + * struct members. Includes structure attributes argument. + */ +#define struct_group_attr(NAME, ATTRS, MEMBERS...) \ + __struct_group(/* no tag */, NAME, ATTRS, MEMBERS) + +/** + * struct_group_tagged() - Create a struct_group with a reusable tag + * + * @TAG: The tag name for the named sub-struct + * @NAME: The identifier name of the mirrored sub-struct + * @MEMBERS: The member declarations for the mirrored structs + * + * Used to create an anonymous union of two structs with identical + * layout and size: one anonymous and one named. The former can be + * used normally without sub-struct naming, and the latter can be + * used to reason about the start, end, and size of the group of + * struct members. Includes struct tag argument for the named copy, + * so the specified layout can be reused later. + */ +#define struct_group_tagged(TAG, NAME, MEMBERS...) \ + __struct_group(TAG, NAME, /* no attrs */, MEMBERS) + +/** + * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union + * + * @TYPE: The type of each flexible array element + * @NAME: The name of the flexible array member + * + * In order to have a flexible array member in a union or alone in a + * struct, it needs to be wrapped in an anonymous struct with at least 1 + * named member, but that member can be empty. + */ +#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __empty_ ## NAME; \ + TYPE NAME[]; \ + } + +/** + * DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union + * + * @TYPE: The type of each flexible array element + * @NAME: The name of the flexible array member + * + * In order to have a flexible array member in a union or alone in a + * struct, it needs to be wrapped in an anonymous struct with at least 1 + * named member, but that member can be empty. + */ +#define DECLARE_FLEX_ARRAY(TYPE, NAME) \ + __DECLARE_FLEX_ARRAY(TYPE, NAME) #endif diff --git a/include/linux/string.h b/include/linux/string.h index 47a27a391f..0d046f7832 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -1,8 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_STRING_H_ #define _LINUX_STRING_H_ #include <linux/types.h> /* for size_t */ #include <linux/stddef.h> /* for NULL */ +#include <linux/overflow.h> /* for array_size */ #ifdef __cplusplus extern "C" { @@ -43,6 +46,9 @@ extern char * strncpy(char *,const char *, __kernel_size_t); #ifndef __HAVE_ARCH_STRLCPY size_t strlcpy(char *, const char *, size_t); #endif +#ifndef __HAVE_ARCH_STRSCPY +ssize_t strscpy(char *, const char *, size_t); +#endif #ifndef __HAVE_ARCH_STRCAT extern char * strcat(char *, const char *); #endif @@ -55,9 +61,6 @@ extern int strcmp(const char *,const char *); #ifndef __HAVE_ARCH_STRNCMP extern int strncmp(const char *,const char *,__kernel_size_t); #endif -#ifndef __HAVE_ARCH_STRNICMP -extern int strnicmp(const char *, const char *, __kernel_size_t); -#endif #ifndef __HAVE_ARCH_STRCASECMP extern int strcasecmp(const char *s1, const char *s2); #endif @@ -112,6 +115,27 @@ extern char * skip_spaces(const char *); extern char *strim(char *); void *memchr_inv(const void *start, int c, size_t bytes); +char *strreplace(char *str, char old, char new); + +/** + * memzero_explicit - Fill a region of memory (e.g. sensitive + * keying data) with 0s. + * @s: Pointer to the start of the area. + * @count: The size of the area. + * + * Note: usually using memset() is just fine (!), but in cases + * where clearing out _local_ data at the end of a scope is + * necessary, memzero_explicit() should be used instead in + * order to prevent the compiler from optimising away zeroing. + * + * memzero_explicit() doesn't need an arch-specific version as + * it just invokes the one of memset() implicitly. + */ +static inline void memzero_explicit(void *s, size_t count) +{ + memset(s, 0, count); + barrier_data(s); +} /** * kbasename - return the last part of a pathname. @@ -131,6 +155,8 @@ static inline const char *kbasename(const char *path) void *memdup(const void *, size_t); +#define memdup_array(arr, count) memdup(arr, array_size(count, sizeof(*arr))); + static inline void *kmemdup(const void *src, size_t len, gfp_t gfp) { return memdup(src, len); @@ -150,4 +176,25 @@ static inline bool strstarts(const char *str, const char *prefix) return strncmp(str, prefix, strlen(prefix)) == 0; } +/** + * str_has_prefix - Test if a string has a given prefix + * @str: The string to test + * @prefix: The string to see if @str starts with + * + * A common way to test a prefix of a string is to do: + * strncmp(str, prefix, sizeof(prefix) - 1) + * + * But this can lead to bugs due to typos, or if prefix is a pointer + * and not a constant. Instead use str_has_prefix(). + * + * Returns: + * * strlen(@prefix) if @str starts with @prefix + * * 0 if @str does not start with @prefix + */ +static __always_inline size_t str_has_prefix(const char *str, const char *prefix) +{ + size_t len = strlen(prefix); + return strncmp(str, prefix, len) == 0 ? len : 0; +} + #endif /* _LINUX_STRING_H_ */ diff --git a/include/linux/string_helpers.h b/include/linux/string_helpers.h new file mode 100644 index 0000000000..5a8a469be7 --- /dev/null +++ b/include/linux/string_helpers.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_STRING_HELPERS_H_ +#define _LINUX_STRING_HELPERS_H_ + +#include <linux/string.h> +#include <linux/types.h> + +static inline bool string_is_terminated(const char *s, int len) +{ + return memchr(s, '\0', len) ? true : false; +} + +#endif diff --git a/include/linux/stringify.h b/include/linux/stringify.h index 841cec8ed5..55f6d04d48 100644 --- a/include/linux/stringify.h +++ b/include/linux/stringify.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef __LINUX_STRINGIFY_H #define __LINUX_STRINGIFY_H diff --git a/include/linux/swab.h b/include/linux/swab.h index ea0c02fd51..243315184e 100644 --- a/include/linux/swab.h +++ b/include/linux/swab.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_SWAB_H #define _LINUX_SWAB_H diff --git a/include/linux/sys_soc.h b/include/linux/sys_soc.h new file mode 100644 index 0000000000..fd597ae540 --- /dev/null +++ b/include/linux/sys_soc.h @@ -0,0 +1,39 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) ST-Ericsson SA 2011 + * Author: Lee Jones <lee.jones@linaro.org> for ST-Ericsson. + */ +#ifndef __SOC_BUS_H +#define __SOC_BUS_H + +#include <linux/device.h> + +struct soc_device_attribute { + const char *machine; + const char *family; + const char *revision; + const char *serial_number; + const char *soc_id; + const void *data; +}; + +/** + * soc_device_register - register SoC as a device + * @soc_plat_dev_attr: Attributes passed from platform to be attributed to a SoC + */ +struct soc_device *soc_device_register( + struct soc_device_attribute *soc_plat_dev_attr); + +/** + * soc_device_unregister - unregister SoC device + * @dev: SoC device to be unregistered + */ +void soc_device_unregister(struct soc_device *soc_dev); + +/** + * soc_device_to_device - helper function to fetch struct device + * @soc: Previously registered SoC device container + */ +struct device *soc_device_to_device(struct soc_device *soc); + +#endif /* __SOC_BUS_H */ diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h new file mode 100644 index 0000000000..4a5cb0f0a5 --- /dev/null +++ b/include/linux/tee_drv.h @@ -0,0 +1,418 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015-2022 Linaro Limited + */ + +#ifndef __TEE_DRV_H +#define __TEE_DRV_H + +#include <linux/device.h> +#include <linux/idr.h> +#include <linux/kref.h> +#include <linux/list.h> +#include <linux/mod_devicetable.h> +#include <linux/tee.h> +#include <linux/types.h> +#include <linux/uuid.h> + +/* + * The file describes the API provided by the generic TEE driver to the + * specific TEE driver. + */ + +#define TEE_SHM_DYNAMIC BIT(0) /* Dynamic shared memory registered */ + /* in secure world */ +#define TEE_SHM_USER_MAPPED BIT(1) /* Memory mapped in user space */ +#define TEE_SHM_POOL BIT(2) /* Memory allocated from pool */ +#define TEE_SHM_PRIV BIT(3) /* Memory private to TEE driver */ + +struct device; +struct tee_device; +struct tee_shm; + +/** + * struct tee_context - driver specific context on file pointer data + * @teedev: pointer to this drivers struct tee_device + * @list_shm: List of shared memory object owned by this context + * @data: driver specific context data, managed by the driver + * @refcount: reference counter for this structure + * @releasing: flag that indicates if context is being released right now. + * It is needed to break circular dependency on context during + * shared memory release. + * @cap_memref_null: flag indicating if the TEE Client support shared + * memory buffer with a NULL pointer. + */ +struct tee_context { + struct tee_device *teedev; + struct list_head list_shm; + void *data; + struct kref refcount; + bool releasing; + bool cap_memref_null; +}; + +struct tee_param_memref { + size_t shm_offs; + size_t size; + struct tee_shm *shm; +}; + +struct tee_param_value { + u64 a; + u64 b; + u64 c; +}; + +struct tee_param { + u64 attr; + union { + struct tee_param_memref memref; + struct tee_param_value value; + } u; +}; + +/** + * struct tee_driver_ops - driver operations vtable + * @get_version: returns version of driver + * @open: called when the device file is opened + * @release: release this open file + * @open_session: open a new session + * @close_session: close a session + * @invoke_func: invoke a trusted function + * @shm_register: register shared memory buffer in TEE + * @shm_unregister: unregister shared memory buffer in TEE + */ +struct tee_driver_ops { + void (*get_version)(struct tee_device *teedev, + struct tee_ioctl_version_data *vers); + int (*open)(struct tee_context *ctx); + void (*release)(struct tee_context *ctx); + int (*open_session)(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param); + int (*close_session)(struct tee_context *ctx, u32 session); + int (*invoke_func)(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param); + int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm); + int (*shm_unregister)(struct tee_context *ctx, struct tee_shm *shm); +}; + +/** + * struct tee_desc - Describes the TEE driver to the subsystem + * @name: name of driver + * @ops: driver operations vtable + * @owner: module providing the driver + * @flags: Extra properties of driver, defined by TEE_DESC_* below + */ +#define TEE_DESC_PRIVILEGED 0x1 +struct tee_desc { + const char *name; + const struct tee_driver_ops *ops; + struct module *owner; + u32 flags; +}; + +/** + * tee_device_alloc() - Allocate a new struct tee_device instance + * @teedesc: Descriptor for this driver + * @dev: Parent device for this device + * @driver_data: Private driver data for this device + * + * Allocates a new struct tee_device instance. The device is + * removed by tee_device_unregister(). + * + * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure + */ +struct tee_device *tee_device_alloc(const struct tee_desc *teedesc, + struct device *dev, + void *driver_data); + +/** + * tee_device_release() - Releases new struct tee_device instance + * @teedev: Device allocated with tee_device_alloc() + * + * Frees a struct tee_device. + */ +void tee_device_release(struct tee_device *teedev); + +/** + * tee_device_register() - Registers a TEE device + * @teedev: Device to register + * + * tee_device_unregister() need to be called to remove the @teedev if + * this function fails. + * + * @returns < 0 on failure + */ +int tee_device_register(struct tee_device *teedev); + +/** + * tee_device_unregister() - Removes a TEE device + * @teedev: Device to unregister + * + * This function should be called to remove the @teedev even if + * tee_device_register() hasn't been called yet. Does nothing if + * @teedev is NULL. + */ +void tee_device_unregister(struct tee_device *teedev); + +/** + * tee_session_calc_client_uuid() - Calculates client UUID for session + * @uuid: Resulting UUID + * @connection_method: Connection method for session (TEE_IOCTL_LOGIN_*) + * @connectuon_data: Connection data for opening session + * + * Based on connection method calculates UUIDv5 based client UUID. + * + * For group based logins verifies that calling process has specified + * credentials. + * + * @return < 0 on failure + */ +int tee_session_calc_client_uuid(uuid_t *uuid, u32 connection_method, + const u8 connection_data[TEE_IOCTL_UUID_LEN]); + +/** + * struct tee_shm - shared memory object + * @ctx: context using the object + * @paddr: physical address of the shared memory + * @kaddr: virtual address of the shared memory + * @size: size of shared memory + * @refcount: reference counter + * @flags: defined by TEE_SHM_* in tee_drv.h + * @link: list head for registering object globally + * @fd: file descriptor for use in userspace + * @dev: device for registering shared memory + * @res: resource to be associated with device + * + * This pool is only supposed to be accessed directly from the TEE + * subsystem and from drivers that implements their own shm pool manager. + */ +struct tee_shm { + struct tee_context *ctx; + phys_addr_t paddr; + void *kaddr; + size_t size; + refcount_t refcount; + u32 flags; + struct list_head link; + + int fd; + struct device_d dev; + struct cdev cdev; + struct resource res; +}; + +/** + * tee_get_drvdata() - Return driver_data pointer + * @returns the driver_data pointer supplied to tee_register(). + */ +void *tee_get_drvdata(struct tee_device *teedev); + +struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size); +struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size); + +struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size); +struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx, + unsigned long addr, size_t length); + +/** + * tee_shm_is_dynamic() - Check if shared memory object is of the dynamic kind + * @shm: Shared memory handle + * @returns true if object is dynamic shared memory + */ +static inline bool tee_shm_is_dynamic(struct tee_shm *shm) +{ + return shm && (shm->flags & TEE_SHM_DYNAMIC); +} + +/** + * tee_shm_free() - Free shared memory + * @shm: Handle to shared memory to free + */ +void tee_shm_free(struct tee_shm *shm); + +/** + * tee_shm_put() - Decrease reference count on a shared memory handle + * @shm: Shared memory handle + */ +void tee_shm_put(struct tee_shm *shm); + +/** + * tee_shm_get_va() - Get virtual address of a shared memory plus an offset + * @shm: Shared memory handle + * @offs: Offset from start of this shared memory + * @returns virtual address of the shared memory + offs if offs is within + * the bounds of this shared memory, else an ERR_PTR + */ +void *tee_shm_get_va(struct tee_shm *shm, size_t offs); + +/** + * tee_shm_get_pa() - Get physical address of a shared memory plus an offset + * @shm: Shared memory handle + * @offs: Offset from start of this shared memory + * @pa: Physical address to return + * @returns 0 if offs is within the bounds of this shared memory, else an + * error code. + */ +int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa); + +/** + * tee_shm_get_size() - Get size of shared memory buffer + * @shm: Shared memory handle + * @returns size of shared memory + */ +static inline size_t tee_shm_get_size(struct tee_shm *shm) +{ + return shm->size; +} + +/** + * tee_shm_get_id() - Get id of a shared memory object + * @shm: Shared memory handle + * @returns id + */ +static inline int tee_shm_get_id(struct tee_shm *shm) +{ + /* Only call on non-private SHMs */ + BUG_ON(shm->dev.id < 0); + return shm->dev.id; +} + +/** + * tee_shm_get_from_id() - Find shared memory object and increase reference + * count + * @ctx: Context owning the shared memory + * @id: Id of shared memory object + * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure + */ +struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id); + +/** + * tee_client_open_context() - Open a TEE context + * @start: if not NULL, continue search after this context + * @match: function to check TEE device + * @data: data for match function + * @vers: if not NULL, version data of TEE device of the context returned + * + * This function does an operation similar to open("/dev/teeX") in user space. + * A returned context must be released with tee_client_close_context(). + * + * Returns a TEE context of the first TEE device matched by the match() + * callback or an ERR_PTR. + */ +struct tee_context * +tee_client_open_context(struct tee_context *start, + int (*match)(struct tee_ioctl_version_data *, + const void *), + const void *data, struct tee_ioctl_version_data *vers); + +/** + * tee_client_close_context() - Close a TEE context + * @ctx: TEE context to close + * + * Note that all sessions previously opened with this context will be + * closed when this function is called. + */ +void tee_client_close_context(struct tee_context *ctx); + +/** + * tee_client_get_version() - Query version of TEE + * @ctx: TEE context to TEE to query + * @vers: Pointer to version data + */ +void tee_client_get_version(struct tee_context *ctx, + struct tee_ioctl_version_data *vers); + +/** + * tee_client_open_session() - Open a session to a Trusted Application + * @ctx: TEE context + * @arg: Open session arguments, see description of + * struct tee_ioctl_open_session_arg + * @param: Parameters passed to the Trusted Application + * + * Returns < 0 on error else see @arg->ret for result. If @arg->ret + * is TEEC_SUCCESS the session identifier is available in @arg->session. + */ +int tee_client_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param); + +/** + * tee_client_close_session() - Close a session to a Trusted Application + * @ctx: TEE Context + * @session: Session id + * + * Return < 0 on error else 0, regardless the session will not be + * valid after this function has returned. + */ +int tee_client_close_session(struct tee_context *ctx, u32 session); + +/** + * tee_client_invoke_func() - Invoke a function in a Trusted Application + * @ctx: TEE Context + * @arg: Invoke arguments, see description of + * struct tee_ioctl_invoke_arg + * @param: Parameters passed to the Trusted Application + * + * Returns < 0 on error else see @arg->ret for result. + */ +int tee_client_invoke_func(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param); + +static inline bool tee_param_is_memref(struct tee_param *param) +{ + switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) { + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: + case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: + return true; + default: + return false; + } +} + +extern struct bus_type tee_bus_type; + +/** + * struct tee_client_device - tee based device + * @id: device identifier + * @dev: device structure + */ +struct tee_client_device { + struct tee_client_device_id id; + struct device dev; +}; + +#define to_tee_client_device(d) container_of(d, struct tee_client_device, dev) + +/** + * struct tee_client_driver - tee client driver + * @id_table: device id table supported by this driver + * @driver: driver structure + */ +struct tee_client_driver { + const struct tee_client_device_id *id_table; + struct device_driver driver; +}; + +#define to_tee_client_driver(d) \ + container_of(d, struct tee_client_driver, driver) + +/** + * teedev_open() - Open a struct tee_device + * @teedev: Device to open + * + * @return a pointer to struct tee_context on success or an ERR_PTR on failure. + */ +struct tee_context *teedev_open(struct tee_device *teedev); + +/** + * teedev_close_context() - closes a struct tee_context + * @ctx: The struct tee_context to close + */ +void teedev_close_context(struct tee_context *ctx); + +#endif /*__TEE_DRV_H*/ diff --git a/include/linux/time.h b/include/linux/time.h index 7903139a65..ebb7cb82ee 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_TIME_H #define _LINUX_TIME_H diff --git a/include/linux/types.h b/include/linux/types.h index dfef336c19..aee9dfa87e 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_TYPES_H #define _LINUX_TYPES_H #ifndef __ASSEMBLY__ @@ -214,5 +216,7 @@ struct hlist_node { struct hlist_node *next, **pprev; }; +typedef int (*cmp_func_t)(const void *a, const void *b); + #endif #endif /* _LINUX_TYPES_H */ diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h new file mode 100644 index 0000000000..94d59dcc44 --- /dev/null +++ b/include/linux/uaccess.h @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_UACCESS_H__ +#define __LINUX_UACCESS_H__ + +#include <asm-generic/uaccess.h> + + +/* + * Check at compile time that something is of a particular type. + * Always evaluates to 1 so you may use it easily in comparisons. + */ +#define typecheck(type,x) \ +({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ +}) + +#define u64_to_user_ptr(x) ( \ +{ \ + typecheck(u64, (x)); \ + (void __user *)(uintptr_t)(x); \ +} \ +) + +static __always_inline unsigned long __must_check +copy_from_user(void *to, const void __user *from, unsigned long n) +{ + return raw_copy_from_user(to, from, n); +} + +static __always_inline unsigned long __must_check +copy_to_user(void __user *to, const void *from, unsigned long n) +{ + return raw_copy_to_user(to, from, n); +} + +#endif /* __LINUX_UACCESS_H__ */ diff --git a/include/linux/unaligned/access_ok.h b/include/linux/unaligned/access_ok.h index 99c1b4d20b..7039ec8ed0 100644 --- a/include/linux/unaligned/access_ok.h +++ b/include/linux/unaligned/access_ok.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_ACCESS_OK_H #define _LINUX_UNALIGNED_ACCESS_OK_H diff --git a/include/linux/unaligned/be_byteshift.h b/include/linux/unaligned/be_byteshift.h index 9356b24223..632a7308b5 100644 --- a/include/linux/unaligned/be_byteshift.h +++ b/include/linux/unaligned/be_byteshift.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H #define _LINUX_UNALIGNED_BE_BYTESHIFT_H diff --git a/include/linux/unaligned/be_memmove.h b/include/linux/unaligned/be_memmove.h index c2a76c5c9e..0723c286fc 100644 --- a/include/linux/unaligned/be_memmove.h +++ b/include/linux/unaligned/be_memmove.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_BE_MEMMOVE_H #define _LINUX_UNALIGNED_BE_MEMMOVE_H diff --git a/include/linux/unaligned/be_struct.h b/include/linux/unaligned/be_struct.h index 132415836c..3cc8fcd68d 100644 --- a/include/linux/unaligned/be_struct.h +++ b/include/linux/unaligned/be_struct.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_BE_STRUCT_H #define _LINUX_UNALIGNED_BE_STRUCT_H diff --git a/include/linux/unaligned/generic.h b/include/linux/unaligned/generic.h index 43d5f2af24..298e977fb7 100644 --- a/include/linux/unaligned/generic.h +++ b/include/linux/unaligned/generic.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_GENERIC_H #define _LINUX_UNALIGNED_GENERIC_H diff --git a/include/linux/unaligned/le_byteshift.h b/include/linux/unaligned/le_byteshift.h index be376fb79b..aa425707f8 100644 --- a/include/linux/unaligned/le_byteshift.h +++ b/include/linux/unaligned/le_byteshift.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_LE_BYTESHIFT_H #define _LINUX_UNALIGNED_LE_BYTESHIFT_H diff --git a/include/linux/unaligned/le_memmove.h b/include/linux/unaligned/le_memmove.h index 269849bee4..e21fccc9b9 100644 --- a/include/linux/unaligned/le_memmove.h +++ b/include/linux/unaligned/le_memmove.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_LE_MEMMOVE_H #define _LINUX_UNALIGNED_LE_MEMMOVE_H diff --git a/include/linux/unaligned/le_struct.h b/include/linux/unaligned/le_struct.h index 088c4572fa..4bbeba5778 100644 --- a/include/linux/unaligned/le_struct.h +++ b/include/linux/unaligned/le_struct.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_LE_STRUCT_H #define _LINUX_UNALIGNED_LE_STRUCT_H diff --git a/include/linux/unaligned/memmove.h b/include/linux/unaligned/memmove.h index eeb5a779a4..c44dff67ab 100644 --- a/include/linux/unaligned/memmove.h +++ b/include/linux/unaligned/memmove.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_MEMMOVE_H #define _LINUX_UNALIGNED_MEMMOVE_H diff --git a/include/linux/unaligned/packed_struct.h b/include/linux/unaligned/packed_struct.h index 2498bb9fe0..7caf433fae 100644 --- a/include/linux/unaligned/packed_struct.h +++ b/include/linux/unaligned/packed_struct.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_UNALIGNED_PACKED_STRUCT_H #define _LINUX_UNALIGNED_PACKED_STRUCT_H diff --git a/include/linux/units.h b/include/linux/units.h new file mode 100644 index 0000000000..120a2fc87b --- /dev/null +++ b/include/linux/units.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_UNITS_H +#define _LINUX_UNITS_H + +#include <linux/kernel.h> + +/* Metric prefixes in accordance with Système international (d'unités) */ +#define PETA 1000000000000000ULL +#define TERA 1000000000000ULL +#define GIGA 1000000000UL +#define MEGA 1000000UL +#define KILO 1000UL +#define HECTO 100UL +#define DECA 10UL +#define DECI 10UL +#define CENTI 100UL +#define MILLI 1000UL +#define MICRO 1000000UL +#define NANO 1000000000UL +#define PICO 1000000000000ULL +#define FEMTO 1000000000000000ULL + +#define NANOHZ_PER_HZ 1000000000UL +#define MICROHZ_PER_HZ 1000000UL +#define MILLIHZ_PER_HZ 1000UL +#define HZ_PER_KHZ 1000UL +#define KHZ_PER_MHZ 1000UL +#define HZ_PER_MHZ 1000000UL + +#define MILLIWATT_PER_WATT 1000UL +#define MICROWATT_PER_MILLIWATT 1000UL +#define MICROWATT_PER_WATT 1000000UL + +#define ABSOLUTE_ZERO_MILLICELSIUS -273150 + +static inline long milli_kelvin_to_millicelsius(long t) +{ + return t + ABSOLUTE_ZERO_MILLICELSIUS; +} + +static inline long millicelsius_to_milli_kelvin(long t) +{ + return t - ABSOLUTE_ZERO_MILLICELSIUS; +} + +#define MILLIDEGREE_PER_DEGREE 1000 +#define MILLIDEGREE_PER_DECIDEGREE 100 + +static inline long kelvin_to_millicelsius(long t) +{ + return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DEGREE); +} + +static inline long millicelsius_to_kelvin(long t) +{ + t = millicelsius_to_milli_kelvin(t); + + return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE); +} + +static inline long deci_kelvin_to_celsius(long t) +{ + t = milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE); + + return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DEGREE); +} + +static inline long celsius_to_deci_kelvin(long t) +{ + t = millicelsius_to_milli_kelvin(t * MILLIDEGREE_PER_DEGREE); + + return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE); +} + +/** + * deci_kelvin_to_millicelsius_with_offset - convert Kelvin to Celsius + * @t: temperature value in decidegrees Kelvin + * @offset: difference between Kelvin and Celsius in millidegrees + * + * Return: temperature value in millidegrees Celsius + */ +static inline long deci_kelvin_to_millicelsius_with_offset(long t, long offset) +{ + return t * MILLIDEGREE_PER_DECIDEGREE - offset; +} + +static inline long deci_kelvin_to_millicelsius(long t) +{ + return milli_kelvin_to_millicelsius(t * MILLIDEGREE_PER_DECIDEGREE); +} + +static inline long millicelsius_to_deci_kelvin(long t) +{ + t = millicelsius_to_milli_kelvin(t); + + return DIV_ROUND_CLOSEST(t, MILLIDEGREE_PER_DECIDEGREE); +} + +static inline long kelvin_to_celsius(long t) +{ + return t + DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, + MILLIDEGREE_PER_DEGREE); +} + +static inline long celsius_to_kelvin(long t) +{ + return t - DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, + MILLIDEGREE_PER_DEGREE); +} + +#endif /* _LINUX_UNITS_H */ diff --git a/include/linux/usb/cdc.h b/include/linux/usb/cdc.h new file mode 100644 index 0000000000..e29429d783 --- /dev/null +++ b/include/linux/usb/cdc.h @@ -0,0 +1,252 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * USB Communications Device Class (CDC) definitions + * + * CDC says how to talk to lots of different types of network adapters, + * notably ethernet adapters and various modems. It's used mostly with + * firmware based USB peripherals. + */ + +#ifndef __LINUX_USB_CDC_H +#define __LINUX_USB_CDC_H + +#include <linux/types.h> + +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ETHERNET 0x06 +#define USB_CDC_SUBCLASS_WHCM 0x08 +#define USB_CDC_SUBCLASS_DMM 0x09 +#define USB_CDC_SUBCLASS_MDLM 0x0a +#define USB_CDC_SUBCLASS_OBEX 0x0b +#define USB_CDC_SUBCLASS_EEM 0x0c + +#define USB_CDC_PROTO_NONE 0 + +#define USB_CDC_ACM_PROTO_AT_V25TER 1 +#define USB_CDC_ACM_PROTO_AT_PCCA101 2 +#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3 +#define USB_CDC_ACM_PROTO_AT_GSM 4 +#define USB_CDC_ACM_PROTO_AT_3G 5 +#define USB_CDC_ACM_PROTO_AT_CDMA 6 +#define USB_CDC_ACM_PROTO_VENDOR 0xff + +#define USB_CDC_PROTO_EEM 7 + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific descriptors ... there are a couple dozen of them + */ + +#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */ +#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */ +#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */ +#define USB_CDC_UNION_TYPE 0x06 /* union_desc */ +#define USB_CDC_COUNTRY_TYPE 0x07 +#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */ +#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ +#define USB_CDC_WHCM_TYPE 0x11 +#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ +#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ +#define USB_CDC_DMM_TYPE 0x14 +#define USB_CDC_OBEX_TYPE 0x15 + +/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ +struct usb_cdc_header_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdCDC; +} __attribute__ ((packed)); + +/* "Call Management Descriptor" from CDC spec 5.2.3.2 */ +struct usb_cdc_call_mgmt_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 +#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 + + __u8 bDataInterface; +} __attribute__ ((packed)); + +/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */ +struct usb_cdc_acm_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +} __attribute__ ((packed)); + +/* capabilities from 5.2.3.3 */ + +#define USB_CDC_COMM_FEATURE 0x01 +#define USB_CDC_CAP_LINE 0x02 +#define USB_CDC_CAP_BRK 0x04 +#define USB_CDC_CAP_NOTIFY 0x08 + +/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ +struct usb_cdc_union_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bMasterInterface0; + __u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__ ((packed)); + +/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */ +struct usb_cdc_country_functional_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iCountryCodeRelDate; + __le16 wCountyCode0; + /* ... and there can be a lot of country codes */ +} __attribute__ ((packed)); + +/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */ +struct usb_cdc_network_terminal_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bEntityId; + __u8 iName; + __u8 bChannelIndex; + __u8 bPhysicalInterface; +} __attribute__ ((packed)); + +/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ +struct usb_cdc_ether_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iMACAddress; + __le32 bmEthernetStatistics; + __le16 wMaxSegmentSize; + __le16 wNumberMCFilters; + __u8 bNumberPowerFilters; +} __attribute__ ((packed)); + +/* "Telephone Control Model Functional Descriptor" from CDC WMC spec 6.3..3 */ +struct usb_cdc_dmm_desc { + __u8 bFunctionLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u16 bcdVersion; + __le16 wMaxCommand; +} __attribute__ ((packed)); + +/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ +struct usb_cdc_mdlm_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; + __u8 bGUID[16]; +} __attribute__ ((packed)); + +/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ +struct usb_cdc_mdlm_detail_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + /* type is associated with mdlm_desc.bGUID */ + __u8 bGuidDescriptorType; + __u8 bDetailData[0]; +} __attribute__ ((packed)); + +/* "OBEX Control Model Functional Descriptor" */ +struct usb_cdc_obex_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; +} __attribute__ ((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Control Requests (6.2) + * + * section 3.6.2.1 table 4 has the ACM profile, for modems. + * section 3.8.2 table 10 has the ethernet profile. + * + * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant, + * heavily dependent on the encapsulated (proprietary) command mechanism. + */ + +#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +#define USB_CDC_REQ_GET_LINE_CODING 0x21 +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 +#define USB_CDC_REQ_SEND_BREAK 0x23 +#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 +#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 +#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define USB_CDC_GET_ETHERNET_STATISTIC 0x44 + +/* Line Coding Structure from CDC spec 6.2.13 */ +struct usb_cdc_line_coding { + __le32 dwDTERate; + __u8 bCharFormat; +#define USB_CDC_1_STOP_BITS 0 +#define USB_CDC_1_5_STOP_BITS 1 +#define USB_CDC_2_STOP_BITS 2 + + __u8 bParityType; +#define USB_CDC_NO_PARITY 0 +#define USB_CDC_ODD_PARITY 1 +#define USB_CDC_EVEN_PARITY 2 +#define USB_CDC_MARK_PARITY 3 +#define USB_CDC_SPACE_PARITY 4 + + __u8 bDataBits; +} __attribute__ ((packed)); + +/* table 62; bits in multicast filter */ +#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0) +#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ +#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2) +#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3) +#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ + + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Notifications (6.3) sent by interrupt transfers + * + * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications + * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS + * RNDIS also defines its own bit-incompatible notifications + */ + +#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00 +#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 +#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a + +struct usb_cdc_notification { + __u8 bmRequestType; + __u8 bNotificationType; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +} __attribute__ ((packed)); + +#endif /* __LINUX_USB_CDC_H */ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h new file mode 100644 index 0000000000..019b6c87e4 --- /dev/null +++ b/include/linux/usb/ch9.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This file holds USB constants and structures that are needed for + * USB device APIs. These are used by the USB device model, which is + * defined in chapter 9 of the USB 2.0 specification and in the + * Wireless USB 1.0 (spread around). Linux has several APIs in C that + * need these: + * + * - the host side Linux-USB kernel driver API; + * - the "usbfs" user space API; and + * - the Linux "gadget" device/peripheral side driver API. + * + * USB 2.0 adds an additional "On The Go" (OTG) mode, which lets systems + * act either as a USB host or as a USB device. That means the host and + * device side APIs benefit from working well together. + * + * There's also "Wireless USB", using low power short range radios for + * peripheral interconnection but otherwise building on the USB framework. + * + * Note all descriptors are declared '__attribute__((packed))' so that: + * + * [a] they never get padded, either internally (USB spec writers + * probably handled that) or externally; + * + * [b] so that accessing bigger-than-a-bytes fields will never + * generate bus errors on any platform, even when the location of + * its descriptor inside a bundle isn't "naturally aligned", and + * + * [c] for consistency, removing all doubt even when it appears to + * someone that the two other points are non-issues for that + * particular descriptor type. + */ +#ifndef __LINUX_USB_CH9_H +#define __LINUX_USB_CH9_H + +#include <uapi/linux/usb/ch9.h> + +/* USB 3.2 SuperSpeed Plus phy signaling rate generation and lane count */ + +enum usb_ssp_rate { + USB_SSP_GEN_UNKNOWN = 0, + USB_SSP_GEN_2x1, + USB_SSP_GEN_1x2, + USB_SSP_GEN_2x2, +}; + +extern const char *usb_speed_string(enum usb_device_speed speed); + +/** + * usb_speed_by_string() - Get speed from human readable name. + * @string: The human readable name for the speed. If it is not one of known + * names, USB_SPEED_UNKNOWN will be returned. + */ +enum usb_device_speed usb_speed_by_string(const char *string); + +#endif /* __LINUX_USB_CH9_H */ diff --git a/include/linux/usb/chipidea-imx.h b/include/linux/usb/chipidea-imx.h new file mode 100644 index 0000000000..99dbd407e5 --- /dev/null +++ b/include/linux/usb/chipidea-imx.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __USB_CHIPIDEA_IMX_H +#define __USB_CHIPIDEA_IMX_H + +#include <linux/usb/phy.h> + +/* + * POTSC flags + */ +#define MXC_EHCI_SERIAL (1 << 29) +#define MXC_EHCI_MODE_UTMI_8BIT (0 << 30) +#define MXC_EHCI_MODE_UTMI_16_BIT ((0 << 30) | (1 << 28)) +#define MXC_EHCI_MODE_PHILIPS (1 << 30) +#define MXC_EHCI_MODE_ULPI (2 << 30) +#define MXC_EHCI_MODE_HSIC (1 << 25) +#define MXC_EHCI_MODE_SERIAL (3 << 30) +#define MXC_EHCI_PFSC (1 << 24) + +/* + * USB misc flags + */ +#define MXC_EHCI_INTERFACE_DIFF_UNI (0 << 0) +#define MXC_EHCI_INTERFACE_DIFF_BI (1 << 0) +#define MXC_EHCI_INTERFACE_SINGLE_UNI (2 << 0) +#define MXC_EHCI_INTERFACE_SINGLE_BI (3 << 0) +#define MXC_EHCI_INTERFACE_MASK (0xf) + +#define MXC_EHCI_POWER_PINS_ENABLED (1 << 5) +#define MXC_EHCI_PWR_PIN_ACTIVE_HIGH (1 << 6) +#define MXC_EHCI_OC_PIN_ACTIVE_LOW (1 << 7) +#define MXC_EHCI_TLL_ENABLED (1 << 8) + +#define MXC_EHCI_INTERNAL_PHY (1 << 9) +#define MXC_EHCI_IPPUE_DOWN (1 << 10) +#define MXC_EHCI_IPPUE_UP (1 << 11) +#define MXC_EHCI_WAKEUP_ENABLED (1 << 12) +#define MXC_EHCI_ITC_NO_THRESHOLD (1 << 13) + +#define MXC_EHCI_DISABLE_OVERCURRENT (1 << 14) + +struct imxusb_platformdata { + unsigned long flags; + enum usb_phy_interface phymode; + enum usb_dr_mode mode; +}; + +#ifdef CONFIG_USB_IMX_CHIPIDEA_USBMISC +int imx_usbmisc_port_init(struct device *dev, int port, unsigned flags); +int imx_usbmisc_port_post_init(struct device *dev, int port, unsigned flags); +#else +static inline int imx_usbmisc_port_init(struct device *dev, int port, + unsigned flags) +{ + return 0; +} +static inline int imx_usbmisc_port_post_init(struct device *dev, int port, + unsigned flags) +{ + return 0; +} +#endif + +#endif /* __USB_CHIPIDEA_IMX_H */ diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h new file mode 100644 index 0000000000..c3ee403abf --- /dev/null +++ b/include/linux/usb/composite.h @@ -0,0 +1,644 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * composite.h -- framework for usb gadgets which are composite devices + * + * Copyright (C) 2006-2008 David Brownell + */ + +#ifndef __LINUX_USB_COMPOSITE_H +#define __LINUX_USB_COMPOSITE_H + +/* + * This framework is an optional layer on top of the USB Gadget interface, + * making it easier to build (a) Composite devices, supporting multiple + * functions within any single configuration, and (b) Multi-configuration + * devices, also supporting multiple functions but without necessarily + * having more than one function per configuration. + * + * Example: a device with a single configuration supporting both network + * link and mass storage functions is a composite device. Those functions + * might alternatively be packaged in individual configurations, but in + * the composite model the host can use both functions at the same time. + */ + +#include <init.h> +#include <linux/usb/ch9.h> +#include <linux/usb/gadget.h> +#include <linux/log2.h> +#include <linux/stringify.h> +#include <linux/spinlock.h> +#include <linux/bcd.h> +#include <linux/usb/webusb.h> + +/* + * USB function drivers should return USB_GADGET_DELAYED_STATUS if they + * wish to delay the data/status stages of the control transfer till they + * are ready. The control transfer will then be kept from completing till + * all the function drivers that requested for USB_GADGET_DELAYED_STAUS + * invoke usb_composite_setup_continue(). + */ +#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */ + +/* big enough to hold our biggest descriptor */ +#define USB_COMP_EP0_BUFSIZ 4096 + +/* OS feature descriptor length <= 4kB */ +#define USB_COMP_EP0_OS_DESC_BUFSIZ 4096 + +#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1) +struct usb_configuration; + +/** + * struct usb_os_desc_ext_prop - describes one "Extended Property" + * @entry: used to keep a list of extended properties + * @type: Extended Property type + * @name_len: Extended Property unicode name length, including terminating '\0' + * @name: Extended Property name + * @data_len: Length of Extended Property blob (for unicode store double len) + * @data: Extended Property blob + * @item: Represents this Extended Property in configfs + */ +struct usb_os_desc_ext_prop { + struct list_head entry; + u8 type; + int name_len; + char *name; + int data_len; + char *data; +}; + +/** + * struct usb_os_desc - describes OS descriptors associated with one interface + * @ext_compat_id: 16 bytes of "Compatible ID" and "Subcompatible ID" + * @ext_prop: Extended Properties list + * @ext_prop_len: Total length of Extended Properties blobs + * @ext_prop_count: Number of Extended Properties + * @opts_mutex: Optional mutex protecting config data of a usb_function_instance + * @group: Represents OS descriptors associated with an interface in configfs + * @owner: Module associated with this OS descriptor + */ +struct usb_os_desc { + char *ext_compat_id; + struct list_head ext_prop; + int ext_prop_len; + int ext_prop_count; + struct mutex *opts_mutex; + struct module *owner; +}; + +/** + * struct usb_os_desc_table - describes OS descriptors associated with one + * interface of a usb_function + * @if_id: Interface id + * @os_desc: "Extended Compatibility ID" and "Extended Properties" of the + * interface + * + * Each interface can have at most one "Extended Compatibility ID" and a + * number of "Extended Properties". + */ +struct usb_os_desc_table { + int if_id; + struct usb_os_desc *os_desc; +}; + +/** + * struct usb_function - describes one function of a configuration + * @name: For diagnostics, identifies the function. + * @strings: tables of strings, keyed by identifiers assigned during bind() + * and by language IDs provided in control requests + * @fs_descriptors: Table of full (or low) speed descriptors, using interface and + * string identifiers assigned during @bind(). If this pointer is null, + * the function will not be available at full speed (or at low speed). + * @hs_descriptors: Table of high speed descriptors, using interface and + * string identifiers assigned during @bind(). If this pointer is null, + * the function will not be available at high speed. + * @ss_descriptors: Table of super speed descriptors, using interface and + * string identifiers assigned during @bind(). If this + * pointer is null after initiation, the function will not + * be available at super speed. + * @ssp_descriptors: Table of super speed plus descriptors, using + * interface and string identifiers assigned during @bind(). If + * this pointer is null after initiation, the function will not + * be available at super speed plus. + * @config: assigned when @usb_add_function() is called; this is the + * configuration with which this function is associated. + * @os_desc_table: Table of (interface id, os descriptors) pairs. The function + * can expose more than one interface. If an interface is a member of + * an IAD, only the first interface of IAD has its entry in the table. + * @os_desc_n: Number of entries in os_desc_table + * @bind: Before the gadget can register, all of its functions bind() to the + * available resources including string and interface identifiers used + * in interface or class descriptors; endpoints; I/O buffers; and so on. + * @unbind: Reverses @bind; called as a side effect of unregistering the + * driver which added this function. + * @free_func: free the struct usb_function. + * @mod: (internal) points to the module that created this structure. + * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may + * initialize usb_ep.driver data at this time (when it is used). + * Note that setting an interface to its current altsetting resets + * interface state, and that all interfaces have a disabled state. + * @get_alt: Returns the active altsetting. If this is not provided, + * then only altsetting zero is supported. + * @disable: (REQUIRED) Indicates the function should be disabled. Reasons + * include host resetting or reconfiguring the gadget, and disconnection. + * @setup: Used for interface-specific control requests. + * @req_match: Tests if a given class request can be handled by this function. + * @suspend: Notifies functions when the host stops sending USB traffic. + * @resume: Notifies functions when the host restarts USB traffic. + * @get_status: Returns function status as a reply to + * GetStatus() request when the recipient is Interface. + * @func_suspend: callback to be called when + * SetFeature(FUNCTION_SUSPEND) is reseived + * + * A single USB function uses one or more interfaces, and should in most + * cases support operation at both full and high speeds. Each function is + * associated by @usb_add_function() with a one configuration; that function + * causes @bind() to be called so resources can be allocated as part of + * setting up a gadget driver. Those resources include endpoints, which + * should be allocated using @usb_ep_autoconfig(). + * + * To support dual speed operation, a function driver provides descriptors + * for both high and full speed operation. Except in rare cases that don't + * involve bulk endpoints, each speed needs different endpoint descriptors. + * + * Function drivers choose their own strategies for managing instance data. + * The simplest strategy just declares it "static', which means the function + * can only be activated once. If the function needs to be exposed in more + * than one configuration at a given speed, it needs to support multiple + * usb_function structures (one for each configuration). + * + * A more complex strategy might encapsulate a @usb_function structure inside + * a driver-specific instance structure to allows multiple activations. An + * example of multiple activations might be a CDC ACM function that supports + * two or more distinct instances within the same configuration, providing + * several independent logical data links to a USB host. + */ + +struct usb_function { + const char *name; + struct usb_gadget_strings **strings; + struct usb_descriptor_header **fs_descriptors; + struct usb_descriptor_header **hs_descriptors; + struct usb_descriptor_header **ss_descriptors; + struct usb_descriptor_header **ssp_descriptors; + + struct usb_configuration *config; + + struct usb_os_desc_table *os_desc_table; + unsigned os_desc_n; + + /* REVISIT: bind() functions can be marked __init, which + * makes trouble for section mismatch analysis. See if + * we can't restructure things to avoid mismatching. + * Related: unbind() may kfree() but bind() won't... + */ + + /* configuration management: bind/unbind */ + int (*bind)(struct usb_configuration *, + struct usb_function *); + void (*unbind)(struct usb_configuration *, + struct usb_function *); + void (*free_func)(struct usb_function *f); + struct module *mod; + + /* runtime state management */ + int (*set_alt)(struct usb_function *, + unsigned interface, unsigned alt); + int (*get_alt)(struct usb_function *, + unsigned interface); + void (*disable)(struct usb_function *); + int (*setup)(struct usb_function *, + const struct usb_ctrlrequest *); + bool (*req_match)(struct usb_function *, + const struct usb_ctrlrequest *, + bool config0); + void (*suspend)(struct usb_function *); + void (*resume)(struct usb_function *); + + /* USB 3.0 additions */ + int (*get_status)(struct usb_function *); + int (*func_suspend)(struct usb_function *, + u8 suspend_opt); + /* private: */ + /* internals */ + struct list_head list; + DECLARE_BITMAP(endpoints, 32); + const struct usb_function_instance *fi; + + unsigned int bind_deactivated:1; +}; + +int usb_add_function(struct usb_configuration *, struct usb_function *); + +int usb_function_deactivate(struct usb_function *); +int usb_function_activate(struct usb_function *); + +int usb_interface_id(struct usb_configuration *, struct usb_function *); + +int config_ep_by_speed_and_alt(struct usb_gadget *g, struct usb_function *f, + struct usb_ep *_ep, u8 alt); + +int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, + struct usb_ep *_ep); + +#define MAX_CONFIG_INTERFACES 16 /* arbitrary; max 255 */ + +/** + * struct usb_configuration - represents one gadget configuration + * @label: For diagnostics, describes the configuration. + * @strings: Tables of strings, keyed by identifiers assigned during @bind() + * and by language IDs provided in control requests. + * @descriptors: Table of descriptors preceding all function descriptors. + * Examples include OTG and vendor-specific descriptors. + * @unbind: Reverses @bind; called as a side effect of unregistering the + * driver which added this configuration. + * @setup: Used to delegate control requests that aren't handled by standard + * device infrastructure or directed at a specific interface. + * @bConfigurationValue: Copied into configuration descriptor. + * @iConfiguration: Copied into configuration descriptor. + * @bmAttributes: Copied into configuration descriptor. + * @MaxPower: Power consumption in mA. Used to compute bMaxPower in the + * configuration descriptor after considering the bus speed. + * @cdev: assigned by @usb_add_config() before calling @bind(); this is + * the device associated with this configuration. + * + * Configurations are building blocks for gadget drivers structured around + * function drivers. Simple USB gadgets require only one function and one + * configuration, and handle dual-speed hardware by always providing the same + * functionality. Slightly more complex gadgets may have more than one + * single-function configuration at a given speed; or have configurations + * that only work at one speed. + * + * Composite devices are, by definition, ones with configurations which + * include more than one function. + * + * The lifecycle of a usb_configuration includes allocation, initialization + * of the fields described above, and calling @usb_add_config() to set up + * internal data and bind it to a specific device. The configuration's + * @bind() method is then used to initialize all the functions and then + * call @usb_add_function() for them. + * + * Those functions would normally be independent of each other, but that's + * not mandatory. CDC WMC devices are an example where functions often + * depend on other functions, with some functions subsidiary to others. + * Such interdependency may be managed in any way, so long as all of the + * descriptors complete by the time the composite driver returns from + * its bind() routine. + */ +struct usb_configuration { + const char *label; + struct usb_gadget_strings **strings; + const struct usb_descriptor_header **descriptors; + + /* REVISIT: bind() functions can be marked __init, which + * makes trouble for section mismatch analysis. See if + * we can't restructure things to avoid mismatching... + */ + + /* configuration management: unbind/setup */ + void (*unbind)(struct usb_configuration *); + int (*setup)(struct usb_configuration *, + const struct usb_ctrlrequest *); + + /* fields in the config descriptor */ + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u16 MaxPower; + + struct usb_composite_dev *cdev; + + /* private: */ + /* internals */ + struct list_head list; + struct list_head functions; + u8 next_interface_id; + unsigned superspeed:1; + unsigned highspeed:1; + unsigned fullspeed:1; + unsigned superspeed_plus:1; + struct usb_function *interface[MAX_CONFIG_INTERFACES]; +}; + +int usb_add_config(struct usb_composite_dev *, + struct usb_configuration *, + int (*)(struct usb_configuration *)); + +void usb_remove_config(struct usb_composite_dev *, + struct usb_configuration *); + +/* predefined index for usb_composite_driver */ +enum { + USB_GADGET_MANUFACTURER_IDX = 0, + USB_GADGET_PRODUCT_IDX, + USB_GADGET_SERIAL_IDX, + USB_GADGET_FIRST_AVAIL_IDX, +}; + +/** + * struct usb_composite_driver - groups configurations into a gadget + * @name: For diagnostics, identifies the driver. + * @dev: Template descriptor for the device, including default device + * identifiers. + * @strings: tables of strings, keyed by identifiers assigned during @bind + * and language IDs provided in control requests. Note: The first entries + * are predefined. The first entry that may be used is + * USB_GADGET_FIRST_AVAIL_IDX + * @max_speed: Highest speed the driver supports. + * @needs_serial: set to 1 if the gadget needs userspace to provide + * a serial number. If one is not provided, warning will be printed. + * @bind: (REQUIRED) Used to allocate resources that are shared across the + * whole device, such as string IDs, and add its configurations using + * @usb_add_config(). This may fail by returning a negative errno + * value; it should return zero on successful initialization. + * @unbind: Reverses @bind; called as a side effect of unregistering + * this driver. + * @disconnect: optional driver disconnect method + * @suspend: Notifies when the host stops sending USB traffic, + * after function notifications + * @resume: Notifies configuration when the host restarts USB traffic, + * before function notifications + * @gadget_driver: Gadget driver controlling this driver + * + * Devices default to reporting self powered operation. Devices which rely + * on bus powered operation should report this in their @bind method. + * + * Before returning from @bind, various fields in the template descriptor + * may be overridden. These include the idVendor/idProduct/bcdDevice values + * normally to bind the appropriate host side driver, and the three strings + * (iManufacturer, iProduct, iSerialNumber) normally used to provide user + * meaningful device identifiers. (The strings will not be defined unless + * they are defined in @dev and @strings.) The correct ep0 maxpacket size + * is also reported, as defined by the underlying controller driver. + */ +struct usb_composite_driver { + const char *name; + const struct usb_device_descriptor *dev; + struct usb_gadget_strings **strings; + enum usb_device_speed max_speed; + unsigned needs_serial:1; + + int (*bind)(struct usb_composite_dev *cdev); + int (*unbind)(struct usb_composite_dev *); + + void (*disconnect)(struct usb_composite_dev *); + + /* global suspend hooks */ + void (*suspend)(struct usb_composite_dev *); + void (*resume)(struct usb_composite_dev *); + struct usb_gadget_driver gadget_driver; +}; + +extern int usb_composite_probe(struct usb_composite_driver *driver); +extern void usb_composite_unregister(struct usb_composite_driver *driver); + +/** + * module_usb_composite_driver() - Helper macro for registering a USB gadget + * composite driver + * @__usb_composite_driver: usb_composite_driver struct + * + * Helper macro for USB gadget composite 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_usb_composite_driver(__usb_composite_driver) \ + module_driver(__usb_composite_driver, usb_composite_probe, \ + usb_composite_unregister) + +extern void usb_composite_setup_continue(struct usb_composite_dev *cdev); +extern int composite_dev_prepare(struct usb_composite_driver *composite, + struct usb_composite_dev *cdev); +extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, + struct usb_ep *ep0); +void composite_dev_cleanup(struct usb_composite_dev *cdev); + +static inline struct usb_composite_driver *to_cdriver( + struct usb_gadget_driver *gdrv) +{ + return container_of(gdrv, struct usb_composite_driver, gadget_driver); +} + +#define OS_STRING_QW_SIGN_LEN 14 +#define OS_STRING_IDX 0xEE + +/** + * struct usb_composite_dev - represents one composite usb gadget + * @gadget: read-only, abstracts the gadget's usb peripheral controller + * @req: used for control responses; buffer is pre-allocated + * @os_desc_req: used for OS descriptors responses; buffer is pre-allocated + * @config: the currently active configuration + * @qw_sign: qwSignature part of the OS string + * @b_vendor_code: bMS_VendorCode part of the OS string + * @use_os_string: false by default, interested gadgets set it + * @bcd_webusb_version: 0x0100 by default, WebUSB specification version + * @b_webusb_vendor_code: 0x0 by default, vendor code for WebUSB + * @landing_page: empty by default, landing page to announce in WebUSB + * @use_webusb:: false by default, interested gadgets set it + * @os_desc_config: the configuration to be used with OS descriptors + * @setup_pending: true when setup request is queued but not completed + * @os_desc_pending: true when os_desc request is queued but not completed + * + * One of these devices is allocated and initialized before the + * associated device driver's bind() is called. + * + * OPEN ISSUE: it appears that some WUSB devices will need to be + * built by combining a normal (wired) gadget with a wireless one. + * This revision of the gadget framework should probably try to make + * sure doing that won't hurt too much. + * + * One notion for how to handle Wireless USB devices involves: + * + * (a) a second gadget here, discovery mechanism TBD, but likely + * needing separate "register/unregister WUSB gadget" calls; + * (b) updates to usb_gadget to include flags "is it wireless", + * "is it wired", plus (presumably in a wrapper structure) + * bandgroup and PHY info; + * (c) presumably a wireless_ep wrapping a usb_ep, and reporting + * wireless-specific parameters like maxburst and maxsequence; + * (d) configurations that are specific to wireless links; + * (e) function drivers that understand wireless configs and will + * support wireless for (additional) function instances; + * (f) a function to support association setup (like CBAF), not + * necessarily requiring a wireless adapter; + * (g) composite device setup that can create one or more wireless + * configs, including appropriate association setup support; + * (h) more, TBD. + */ +struct usb_composite_dev { + struct usb_gadget *gadget; + struct usb_request *req; + struct usb_request *os_desc_req; + + struct usb_configuration *config; + + /* OS String is a custom (yet popular) extension to the USB standard. */ + u8 qw_sign[OS_STRING_QW_SIGN_LEN]; + u8 b_vendor_code; + struct usb_configuration *os_desc_config; + unsigned int use_os_string:1; + + /* WebUSB */ + u16 bcd_webusb_version; + u8 b_webusb_vendor_code; + char landing_page[WEBUSB_URL_RAW_MAX_LENGTH]; + unsigned int use_webusb:1; + + /* private: */ + /* internals */ + unsigned int suspended:1; + struct usb_device_descriptor desc; + struct list_head configs; + struct list_head gstrings; + struct usb_composite_driver *driver; + u8 next_string_id; + char *def_manufacturer; + struct usb_string *usb_strings; + + /* the gadget driver won't enable the data pullup + * while the deactivation count is nonzero. + */ + unsigned deactivations; + + /* the composite driver won't complete the control transfer's + * data/status stages till delayed_status is zero. + */ + int delayed_status; + + /* protects deactivations and delayed_status counts*/ + spinlock_t lock; + + /* public: */ + unsigned int setup_pending:1; + unsigned int os_desc_pending:1; +}; + +extern int usb_string_id(struct usb_composite_dev *c); +extern int usb_string_ids_tab(struct usb_composite_dev *c, + struct usb_string *str); +extern struct usb_string *usb_gstrings_attach(struct usb_composite_dev *cdev, + struct usb_gadget_strings **sp, unsigned n_strings); + +extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n); + +extern void composite_disconnect(struct usb_gadget *gadget); +extern void composite_reset(struct usb_gadget *gadget); + +extern int composite_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl); +extern void composite_suspend(struct usb_gadget *gadget); +extern void composite_resume(struct usb_gadget *gadget); + +/* + * Some systems will need runtime overrides for the product identifiers + * published in the device descriptor, either numbers or strings or both. + * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). + */ +struct usb_composite_overwrite { + u16 idVendor; + u16 idProduct; + u16 bcdDevice; + char *serial_number; + char *manufacturer; + char *product; +}; +#define USB_GADGET_COMPOSITE_OPTIONS() \ + static struct usb_composite_overwrite coverwrite; \ + \ + module_param_named(idVendor, coverwrite.idVendor, ushort, S_IRUGO); \ + MODULE_PARM_DESC(idVendor, "USB Vendor ID"); \ + \ + module_param_named(idProduct, coverwrite.idProduct, ushort, S_IRUGO); \ + MODULE_PARM_DESC(idProduct, "USB Product ID"); \ + \ + module_param_named(bcdDevice, coverwrite.bcdDevice, ushort, S_IRUGO); \ + MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); \ + \ + module_param_named(iSerialNumber, coverwrite.serial_number, charp, \ + S_IRUGO); \ + MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); \ + \ + module_param_named(iManufacturer, coverwrite.manufacturer, charp, \ + S_IRUGO); \ + MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); \ + \ + module_param_named(iProduct, coverwrite.product, charp, S_IRUGO); \ + MODULE_PARM_DESC(iProduct, "USB Product string") + +void usb_composite_overwrite_options(struct usb_composite_dev *cdev, + struct usb_composite_overwrite *covr); + +static inline u16 get_default_bcdDevice(void) +{ + u16 bcdDevice; +#define LINUX_VERSION_MAJOR 6 +#define LINUX_VERSION_PATCHLEVEL 2 + bcdDevice = bin2bcd(LINUX_VERSION_MAJOR) << 8; + bcdDevice |= bin2bcd(LINUX_VERSION_PATCHLEVEL); + return bcdDevice; +} + +struct usb_function_driver { + const char *name; + struct module *mod; + struct list_head list; + struct usb_function_instance *(*alloc_inst)(void); + struct usb_function *(*alloc_func)(struct usb_function_instance *inst); +}; + +struct usb_function_instance { + struct list_head cfs_list; + struct usb_function_driver *fd; + int (*set_inst_name)(struct usb_function_instance *inst, + const char *name); + void (*free_func_inst)(struct usb_function_instance *inst); +}; + +void usb_function_unregister(struct usb_function_driver *f); +int usb_function_register(struct usb_function_driver *newf); +void usb_put_function_instance(struct usb_function_instance *fi); +void usb_put_function(struct usb_function *f); +struct usb_function_instance *usb_get_function_instance(const char *name); +struct usb_function *usb_get_function(struct usb_function_instance *fi); + +struct usb_configuration *usb_get_config(struct usb_composite_dev *cdev, + int val); +int usb_add_config_only(struct usb_composite_dev *cdev, + struct usb_configuration *config); +void usb_remove_function(struct usb_configuration *c, struct usb_function *f); + +#define DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \ + static struct usb_function_driver _name ## usb_func = { \ + .name = __stringify(_name), \ + .mod = THIS_MODULE, \ + .alloc_inst = _inst_alloc, \ + .alloc_func = _func_alloc, \ + }; \ + MODULE_ALIAS("usbfunc:"__stringify(_name)); + +#define DECLARE_USB_FUNCTION_INIT(_name, _inst_alloc, _func_alloc) \ + DECLARE_USB_FUNCTION(_name, _inst_alloc, _func_alloc) \ + static int __init _name ## mod_init(void) \ + { \ + return usb_function_register(&_name ## usb_func); \ + } \ + static void __exit _name ## mod_exit(void) \ + { \ + usb_function_unregister(&_name ## usb_func); \ + } \ + module_init(_name ## mod_init); \ + module_exit(_name ## mod_exit) + +/* messaging utils */ +#define DBG(d, fmt, args...) \ + dev_dbg(&(d)->gadget->dev , fmt , ## args) +#define VDBG(d, fmt, args...) \ + dev_vdbg(&(d)->gadget->dev , fmt , ## args) +#define ERROR(d, fmt, args...) \ + dev_err(&(d)->gadget->dev , fmt , ## args) +#define WARNING(d, fmt, args...) \ + dev_warn(&(d)->gadget->dev , fmt , ## args) +#define INFO(d, fmt, args...) \ + dev_info(&(d)->gadget->dev , fmt , ## args) + +#endif /* __LINUX_USB_COMPOSITE_H */ diff --git a/include/linux/usb/dfu.h b/include/linux/usb/dfu.h new file mode 100644 index 0000000000..3bc4204500 --- /dev/null +++ b/include/linux/usb/dfu.h @@ -0,0 +1,34 @@ +#ifndef _USB_DFU_H +#define _USB_DFU_H +/* USB Device Firmware Update Implementation for OpenPCD + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + * Protocol definitions for USB DFU + * + * This ought to be compliant to the USB DFU Spec 1.0 as available from + * http://www.usb.org/developers/devclass_docs/usbdfu10.pdf + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/types.h> +#include <file-list.h> +#include <linux/usb/composite.h> + +struct f_dfu_opts { + struct usb_function_instance func_inst; + struct file_list *files; +}; + +int usb_dfu_detached(void); + +#endif /* _USB_DFU_H */ diff --git a/include/linux/usb/ehci.h b/include/linux/usb/ehci.h new file mode 100644 index 0000000000..9ce6c98ace --- /dev/null +++ b/include/linux/usb/ehci.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __USB_EHCI_H +#define __USB_EHCI_H + +#define EHCI_HAS_TT (1 << 0) + +struct ehci_platform_data { + unsigned long flags; +}; + +struct ehci_data { + void __iomem *hccr; + void __iomem *hcor; + unsigned long flags; + struct usb_phy *usbphy; + + /* platform specific init functions */ + int (*init)(void *drvdata); + int (*post_init)(void *drvdata); + void *drvdata; +}; + +struct ehci_host; + +#ifdef CONFIG_USB_EHCI +struct ehci_host *ehci_register(struct device *dev, struct ehci_data *data); +void ehci_unregister(struct ehci_host *); +#else +static inline struct ehci_host *ehci_register(struct device *dev, + struct ehci_data *data) +{ + return ERR_PTR(-ENOSYS); +} + +static inline void ehci_unregister(struct ehci_host *ehci) +{ +} +#endif + +#endif /* __USB_EHCI_H */ diff --git a/include/linux/usb/fastboot.h b/include/linux/usb/fastboot.h new file mode 100644 index 0000000000..d0dbd0b7b7 --- /dev/null +++ b/include/linux/usb/fastboot.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _USB_FASTBOOT_H +#define _USB_FASTBOOT_H + +#include <linux/usb/composite.h> +#include <fastboot.h> + +/** + * struct f_fastboot_opts - options to configure the fastboot gadget + * @common: Options common to all fastboot protocol variants + * @func_inst: The USB function instance to register on + */ +struct f_fastboot_opts { + struct fastboot_opts common; + struct usb_function_instance func_inst; +}; + +#endif /* _USB_FASTBOOT_H */ diff --git a/include/linux/usb/fsl_usb2.h b/include/linux/usb/fsl_usb2.h new file mode 100644 index 0000000000..1d5effb0d6 --- /dev/null +++ b/include/linux/usb/fsl_usb2.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __USB_FSL_USB2_H +#define __USB_FSL_USB2_H + +enum fsl_usb2_operating_modes { + FSL_USB2_MPH_HOST, + FSL_USB2_DR_HOST, + FSL_USB2_DR_DEVICE, + FSL_USB2_DR_OTG, +}; + +enum fsl_usb2_phy_modes { + FSL_USB2_PHY_NONE, + FSL_USB2_PHY_ULPI, + FSL_USB2_PHY_UTMI, + FSL_USB2_PHY_UTMI_WIDE, + FSL_USB2_PHY_SERIAL, +}; + +struct fsl_usb2_platform_data { + /* board specific information */ + enum fsl_usb2_operating_modes operating_mode; + enum fsl_usb2_phy_modes phy_mode; + unsigned int port_enables; +}; + +struct fsl_udc; + +struct fsl_udc *ci_udc_register(struct device *dev, void __iomem *regs); +void ci_udc_unregister(struct fsl_udc *); + +#endif /* __USB_FSL_USB2_H */ diff --git a/include/linux/usb/gadget-multi.h b/include/linux/usb/gadget-multi.h new file mode 100644 index 0000000000..1027a10082 --- /dev/null +++ b/include/linux/usb/gadget-multi.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __USB_GADGET_MULTI_H +#define __USB_GADGET_MULTI_H + +#include <linux/types.h> +#include <linux/usb/fastboot.h> +#include <linux/usb/dfu.h> +#include <linux/usb/usbserial.h> +#include <linux/usb/mass_storage.h> + +struct f_multi_opts { + struct fastboot_opts fastboot_opts; + struct f_dfu_opts dfu_opts; + struct f_ums_opts ums_opts; + bool create_acm; + void (*release)(struct f_multi_opts *opts); +}; + +int usb_multi_register(struct f_multi_opts *opts); +void usb_multi_unregister(void); +void usb_multi_opts_release(struct f_multi_opts *opts); +unsigned usb_multi_count_functions(struct f_multi_opts *opts); + +#define USBGADGET_EXPORT_BBU (1 << 0) +#define USBGADGET_ACM (1 << 1) +#define USBGADGET_DFU (1 << 2) +#define USBGADGET_FASTBOOT (1 << 3) +#define USBGADGET_MASS_STORAGE (1 << 4) + +struct usbgadget_funcs { + int flags; + const char *fastboot_opts; + const char *dfu_opts; + const char *ums_opts; +}; + +int usbgadget_register(const struct usbgadget_funcs *funcs); + +void usbgadget_autostart(bool enable); + +#endif /* __USB_GADGET_MULTI_H */ diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h new file mode 100644 index 0000000000..d4c02cb37c --- /dev/null +++ b/include/linux/usb/gadget.h @@ -0,0 +1,950 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * <linux/usb/gadget.h> + * + * We call the USB code inside a Linux-based peripheral device a "gadget" + * driver, except for the hardware-specific bus glue. One USB host can + * talk to many USB gadgets, but the gadgets are only able to communicate + * to one host. + * + * + * (C) Copyright 2002-2004 by David Brownell + * All Rights Reserved. + */ + +#ifndef __LINUX_USB_GADGET_H +#define __LINUX_USB_GADGET_H + +#include <common.h> +#include <malloc.h> +#include <driver.h> +#include <linux/list.h> +#include <linux/usb/ch9.h> +#include <linux/mutex.h> +#include <work.h> + +#define UDC_TRACE_STR_MAX 512 + +struct usb_ep; + +/** + * struct usb_request - describes one i/o request + * @buf: Buffer used for data. Always provide this; some controllers + * only use PIO, or don't use DMA for some endpoints. + * @dma: DMA address corresponding to 'buf'. If you don't set this + * field, and the usb controller needs one, it is responsible + * for mapping and unmapping the buffer. + * @sg: a scatterlist for SG-capable controllers. + * @num_sgs: number of SG entries + * @num_mapped_sgs: number of SG entries mapped to DMA (internal) + * @length: Length of that data + * @stream_id: The stream id, when USB3.0 bulk streams are being used + * @is_last: Indicates if this is the last request of a stream_id before + * switching to a different stream (required for DWC3 controllers). + * @no_interrupt: If true, hints that no completion irq is needed. + * Helpful sometimes with deep request queues that are handled + * directly by DMA controllers. + * @zero: If true, when writing data, makes the last packet be "short" + * by adding a zero length packet as needed; + * @short_not_ok: When reading data, makes short packets be + * treated as errors (queue stops advancing till cleanup). + * @dma_mapped: Indicates if request has been mapped to DMA (internal) + * @complete: Function called when request completes, so this request and + * its buffer may be re-used. The function will always be called with + * interrupts disabled, and it must not sleep. + * Reads terminate with a short packet, or when the buffer fills, + * whichever comes first. When writes terminate, some data bytes + * will usually still be in flight (often in a hardware fifo). + * Errors (for reads or writes) stop the queue from advancing + * until the completion function returns, so that any transfers + * invalidated by the error may first be dequeued. + * @context: For use by the completion callback + * @list: For use by the gadget driver. + * @frame_number: Reports the interval number in (micro)frame in which the + * isochronous transfer was transmitted or received. + * @status: Reports completion code, zero or a negative errno. + * Normally, faults block the transfer queue from advancing until + * the completion callback returns. + * Code "-ESHUTDOWN" indicates completion caused by device disconnect, + * or when the driver disabled the endpoint. + * @actual: Reports bytes transferred to/from the buffer. For reads (OUT + * transfers) this may be less than the requested length. If the + * short_not_ok flag is set, short reads are treated as errors + * even when status otherwise indicates successful completion. + * Note that for writes (IN transfers) some data bytes may still + * reside in a device-side FIFO when the request is reported as + * complete. + * + * These are allocated/freed through the endpoint they're used with. The + * hardware's driver can add extra per-request data to the memory it returns, + * which often avoids separate memory allocations (potential failures), + * later when the request is queued. + * + * Request flags affect request handling, such as whether a zero length + * packet is written (the "zero" flag), whether a short read should be + * treated as an error (blocking request queue advance, the "short_not_ok" + * flag), or hinting that an interrupt is not required (the "no_interrupt" + * flag, for use with deep request queues). + * + * Bulk endpoints can use any size buffers, and can also be used for interrupt + * transfers. interrupt-only endpoints can be much less functional. + * + * NOTE: this is analogous to 'struct urb' on the host side, except that + * it's thinner and promotes more pre-allocation. + */ + +struct usb_request { + void *buf; + unsigned length; + dma_addr_t dma; + + struct scatterlist *sg; + unsigned num_sgs; + unsigned num_mapped_sgs; + + unsigned stream_id:16; + unsigned is_last:1; + unsigned no_interrupt:1; + unsigned zero:1; + unsigned short_not_ok:1; + unsigned dma_mapped:1; + + void (*complete)(struct usb_ep *ep, + struct usb_request *req); + void *context; + struct list_head list; + + unsigned frame_number; /* ISO ONLY */ + + int status; + unsigned actual; +}; + +/*-------------------------------------------------------------------------*/ + +/* endpoint-specific parts of the api to the usb controller hardware. + * unlike the urb model, (de)multiplexing layers are not required. + * (so this api could slash overhead if used on the host side...) + * + * note that device side usb controllers commonly differ in how many + * endpoints they support, as well as their capabilities. + */ +struct usb_ep_ops { + int (*enable) (struct usb_ep *ep, + const struct usb_endpoint_descriptor *desc); + int (*disable) (struct usb_ep *ep); + void (*dispose) (struct usb_ep *ep); + + struct usb_request *(*alloc_request) (struct usb_ep *ep); + void (*free_request) (struct usb_ep *ep, struct usb_request *req); + + int (*queue) (struct usb_ep *ep, struct usb_request *req); + int (*dequeue) (struct usb_ep *ep, struct usb_request *req); + + int (*set_halt) (struct usb_ep *ep, int value); + int (*set_wedge) (struct usb_ep *ep); + + int (*fifo_status) (struct usb_ep *ep); + void (*fifo_flush) (struct usb_ep *ep); +}; + +/** + * struct usb_ep_caps - endpoint capabilities description + * @type_control:Endpoint supports control type (reserved for ep0). + * @type_iso:Endpoint supports isochronous transfers. + * @type_bulk:Endpoint supports bulk transfers. + * @type_int:Endpoint supports interrupt transfers. + * @dir_in:Endpoint supports IN direction. + * @dir_out:Endpoint supports OUT direction. + */ +struct usb_ep_caps { + unsigned type_control:1; + unsigned type_iso:1; + unsigned type_bulk:1; + unsigned type_int:1; + unsigned dir_in:1; + unsigned dir_out:1; +}; + +#define USB_EP_CAPS_TYPE_CONTROL 0x01 +#define USB_EP_CAPS_TYPE_ISO 0x02 +#define USB_EP_CAPS_TYPE_BULK 0x04 +#define USB_EP_CAPS_TYPE_INT 0x08 +#define USB_EP_CAPS_TYPE_ALL \ + (USB_EP_CAPS_TYPE_ISO | USB_EP_CAPS_TYPE_BULK | USB_EP_CAPS_TYPE_INT) +#define USB_EP_CAPS_DIR_IN 0x01 +#define USB_EP_CAPS_DIR_OUT 0x02 +#define USB_EP_CAPS_DIR_ALL (USB_EP_CAPS_DIR_IN | USB_EP_CAPS_DIR_OUT) + +#define USB_EP_CAPS(_type, _dir) \ + { \ + .type_control = !!(_type & USB_EP_CAPS_TYPE_CONTROL), \ + .type_iso = !!(_type & USB_EP_CAPS_TYPE_ISO), \ + .type_bulk = !!(_type & USB_EP_CAPS_TYPE_BULK), \ + .type_int = !!(_type & USB_EP_CAPS_TYPE_INT), \ + .dir_in = !!(_dir & USB_EP_CAPS_DIR_IN), \ + .dir_out = !!(_dir & USB_EP_CAPS_DIR_OUT), \ + } + +/** + * struct usb_ep - device side representation of USB endpoint + * @name:identifier for the endpoint, such as "ep-a" or "ep9in-bulk" + * @ops: Function pointers used to access hardware-specific operations. + * @ep_list:the gadget's ep_list holds all of its endpoints + * @caps:The structure describing types and directions supported by endpoint. + * @enabled: The current endpoint enabled/disabled state. + * @claimed: True if this endpoint is claimed by a function. + * @maxpacket:The maximum packet size used on this endpoint. The initial + * value can sometimes be reduced (hardware allowing), according to + * the endpoint descriptor used to configure the endpoint. + * @maxpacket_limit:The maximum packet size value which can be handled by this + * endpoint. It's set once by UDC driver when endpoint is initialized, and + * should not be changed. Should not be confused with maxpacket. + * @max_streams: The maximum number of streams supported + * by this EP (0 - 16, actual number is 2^n) + * @mult: multiplier, 'mult' value for SS Isoc EPs + * @maxburst: the maximum number of bursts supported by this EP (for usb3) + * @driver_data:for use by the gadget driver. + * @address: used to identify the endpoint when finding descriptor that + * matches connection speed + * @desc: endpoint descriptor. This pointer is set before the endpoint is + * enabled and remains valid until the endpoint is disabled. + * @comp_desc: In case of SuperSpeed support, this is the endpoint companion + * descriptor that is used to configure the endpoint + * + * the bus controller driver lists all the general purpose endpoints in + * gadget->ep_list. the control endpoint (gadget->ep0) is not in that list, + * and is accessed only in response to a driver setup() callback. + */ + +struct usb_ep { + void *driver_data; + + const char *name; + const struct usb_ep_ops *ops; + struct list_head ep_list; + struct usb_ep_caps caps; + bool claimed; + bool enabled; + unsigned maxpacket:16; + unsigned maxpacket_limit:16; + unsigned max_streams:16; + unsigned mult:2; + unsigned maxburst:5; + u8 address; + const struct usb_endpoint_descriptor *desc; + const struct usb_ss_ep_comp_descriptor *comp_desc; +}; + +/*-------------------------------------------------------------------------*/ + +#if IS_ENABLED(CONFIG_USB_GADGET) +void usb_ep_set_maxpacket_limit(struct usb_ep *ep, unsigned maxpacket_limit); +int usb_ep_enable(struct usb_ep *ep); +int usb_ep_disable(struct usb_ep *ep); +struct usb_request *usb_ep_alloc_request(struct usb_ep *ep); +void usb_ep_free_request(struct usb_ep *ep, struct usb_request *req); +int usb_ep_queue(struct usb_ep *ep, struct usb_request *req); +int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req); +int usb_ep_set_halt(struct usb_ep *ep); +int usb_ep_clear_halt(struct usb_ep *ep); +int usb_ep_set_wedge(struct usb_ep *ep); +int usb_ep_fifo_status(struct usb_ep *ep); +void usb_ep_fifo_flush(struct usb_ep *ep); +#else +static inline void usb_ep_set_maxpacket_limit(struct usb_ep *ep, + unsigned maxpacket_limit) +{ } +static inline int usb_ep_enable(struct usb_ep *ep) +{ return 0; } +static inline int usb_ep_disable(struct usb_ep *ep) +{ return 0; } +static inline struct usb_request *usb_ep_alloc_request(struct usb_ep *ep, + gfp_t gfp_flags) +{ return NULL; } +static inline void usb_ep_free_request(struct usb_ep *ep, + struct usb_request *req) +{ } +static inline int usb_ep_queue(struct usb_ep *ep, struct usb_request *req, + gfp_t gfp_flags) +{ return 0; } +static inline int usb_ep_dequeue(struct usb_ep *ep, struct usb_request *req) +{ return 0; } +static inline int usb_ep_set_halt(struct usb_ep *ep) +{ return 0; } +static inline int usb_ep_clear_halt(struct usb_ep *ep) +{ return 0; } +static inline int usb_ep_set_wedge(struct usb_ep *ep) +{ return 0; } +static inline int usb_ep_fifo_status(struct usb_ep *ep) +{ return 0; } +static inline void usb_ep_fifo_flush(struct usb_ep *ep) +{ } +#endif /* USB_GADGET */ + +/*-------------------------------------------------------------------------*/ + +struct usb_dcd_config_params { + __u8 bU1devExitLat; /* U1 Device exit Latency */ +#define USB_DEFAULT_U1_DEV_EXIT_LAT 0x01 /* Less then 1 microsec */ + __le16 bU2DevExitLat; /* U2 Device exit Latency */ +#define USB_DEFAULT_U2_DEV_EXIT_LAT 0x1F4 /* Less then 500 microsec */ + __u8 besl_baseline; /* Recommended baseline BESL (0-15) */ + __u8 besl_deep; /* Recommended deep BESL (0-15) */ +#define USB_DEFAULT_BESL_UNSPECIFIED 0xFF /* No recommended value */ +}; + + +struct usb_gadget; +struct usb_gadget_driver; +struct usb_udc; + +/* the rest of the api to the controller hardware: device operations, + * which don't involve endpoints (or i/o). + */ +struct usb_gadget_ops { + int (*get_frame)(struct usb_gadget *); + int (*wakeup)(struct usb_gadget *); + int (*set_selfpowered) (struct usb_gadget *, int is_selfpowered); + int (*vbus_session) (struct usb_gadget *, int is_active); + int (*vbus_draw) (struct usb_gadget *, unsigned mA); + int (*pullup) (struct usb_gadget *, int is_on); + int (*ioctl)(struct usb_gadget *, + unsigned code, unsigned long param); + void (*get_config_params)(struct usb_gadget *, + struct usb_dcd_config_params *); + int (*udc_start)(struct usb_gadget *, + struct usb_gadget_driver *); + int (*udc_stop)(struct usb_gadget *); + void (*udc_poll)(struct usb_gadget *); + void (*udc_set_speed)(struct usb_gadget *, enum usb_device_speed); + void (*udc_set_ssp_rate)(struct usb_gadget *gadget, + enum usb_ssp_rate rate); + void (*udc_async_callbacks)(struct usb_gadget *gadget, bool enable); + struct usb_ep *(*match_ep)(struct usb_gadget *, + struct usb_endpoint_descriptor *, + struct usb_ss_ep_comp_descriptor *); + int (*check_config)(struct usb_gadget *gadget); +}; + +/** + * struct usb_gadget - represents a usb device + * @work: (internal use) Workqueue to be used for sysfs_notify() + * @udc: struct usb_udc pointer for this gadget + * @ops: Function pointers used to access hardware-specific operations. + * @ep0: Endpoint zero, used when reading or writing responses to + * driver setup() requests + * @ep_list: List of other endpoints supported by the device. + * @speed: Speed of current connection to USB host. + * @max_speed: Maximal speed the UDC can handle. UDC must support this + * and all slower speeds. + * @ssp_rate: Current connected SuperSpeed Plus signaling rate and lane count. + * @max_ssp_rate: Maximum SuperSpeed Plus signaling rate and lane count the UDC + * can handle. The UDC must support this and all slower speeds and lower + * number of lanes. + * @state: the state we are now (attached, suspended, configured, etc) + * @name: Identifies the controller hardware type. Used in diagnostics + * and sometimes configuration. + * @dev: Driver model state for this abstract device. + * @isoch_delay: value from Set Isoch Delay request. Only valid on SS/SSP + * @out_epnum: last used out ep number + * @in_epnum: last used in ep number + * @mA: last set mA value + * @otg_caps: OTG capabilities of this gadget. + * @sg_supported: true if we can handle scatter-gather + * @is_otg: True if the USB device port uses a Mini-AB jack, so that the + * gadget driver must provide a USB OTG descriptor. + * @is_a_peripheral: False unless is_otg, the "A" end of a USB cable + * is in the Mini-AB jack, and HNP has been used to switch roles + * so that the "A" device currently acts as A-Peripheral, not A-Host. + * @a_hnp_support: OTG device feature flag, indicating that the A-Host + * supports HNP at this port. + * @a_alt_hnp_support: OTG device feature flag, indicating that the A-Host + * only supports HNP on a different root port. + * @b_hnp_enable: OTG device feature flag, indicating that the A-Host + * enabled HNP support. + * @hnp_polling_support: OTG device feature flag, indicating if the OTG device + * in peripheral mode can support HNP polling. + * @host_request_flag: OTG device feature flag, indicating if A-Peripheral + * or B-Peripheral wants to take host role. + * @quirk_ep_out_aligned_size: epout requires buffer size to be aligned to + * MaxPacketSize. + * @quirk_altset_not_supp: UDC controller doesn't support alt settings. + * @quirk_stall_not_supp: UDC controller doesn't support stalling. + * @quirk_zlp_not_supp: UDC controller doesn't support ZLP. + * @quirk_avoids_skb_reserve: udc/platform wants to avoid skb_reserve() in + * u_ether.c to improve performance. + * @is_selfpowered: if the gadget is self-powered. + * @deactivated: True if gadget is deactivated - in deactivated state it cannot + * be connected. + * @connected: True if gadget is connected. + * @lpm_capable: If the gadget max_speed is FULL or HIGH, this flag + * indicates that it supports LPM as per the LPM ECN & errata. + * @irq: the interrupt number for device controller. + * @id_number: a unique ID number for ensuring that gadget names are distinct + * + * Gadgets have a mostly-portable "gadget driver" implementing device + * functions, handling all usb configurations and interfaces. Gadget + * drivers talk to hardware-specific code indirectly, through ops vectors. + * That insulates the gadget driver from hardware details, and packages + * the hardware endpoints through generic i/o queues. The "usb_gadget" + * and "usb_ep" interfaces provide that insulation from the hardware. + * + * Except for the driver data, all fields in this structure are + * read-only to the gadget driver. That driver data is part of the + * "driver model" infrastructure in 2.6 (and later) kernels, and for + * earlier systems is grouped in a similar structure that's not known + * to the rest of the kernel. + * + * Values of the three OTG device feature flags are updated before the + * setup() call corresponding to USB_REQ_SET_CONFIGURATION, and before + * driver suspend() calls. They are valid only when is_otg, and when the + * device is acting as a B-Peripheral (so is_a_peripheral is false). + */ +struct usb_gadget { + struct work_struct work; + struct usb_udc *udc; + /* readonly to gadget driver */ + const struct usb_gadget_ops *ops; + struct usb_ep *ep0; + struct list_head ep_list; /* of usb_ep */ + enum usb_device_speed speed; + enum usb_device_speed max_speed; + + /* USB SuperSpeed Plus only */ + enum usb_ssp_rate ssp_rate; + enum usb_ssp_rate max_ssp_rate; + + enum usb_device_state state; + const char *name; + struct device dev; + unsigned isoch_delay; + unsigned out_epnum; + unsigned in_epnum; + unsigned mA; + struct usb_otg_caps *otg_caps; + + unsigned sg_supported:1; + unsigned is_otg:1; + unsigned is_a_peripheral:1; + unsigned b_hnp_enable:1; + unsigned a_hnp_support:1; + unsigned a_alt_hnp_support:1; + unsigned hnp_polling_support:1; + unsigned host_request_flag:1; + unsigned quirk_ep_out_aligned_size:1; + unsigned quirk_altset_not_supp:1; + unsigned quirk_stall_not_supp:1; + unsigned quirk_zlp_not_supp:1; + unsigned quirk_avoids_skb_reserve:1; + unsigned is_selfpowered:1; + unsigned deactivated:1; + unsigned connected:1; + unsigned lpm_capable:1; + int irq; + int id_number; + + uint32_t vendor_id; + uint32_t product_id; + char *manufacturer; + char *productname; + char *serialnumber; + + void *drvdata; +}; +#define work_to_gadget(w) (container_of((w), struct usb_gadget, work)) + +/* Interface to the device model */ +static inline void set_gadget_data(struct usb_gadget *gadget, void *data) + { gadget->drvdata = data; } +static inline void *get_gadget_data(struct usb_gadget *gadget) + { return gadget->drvdata; } +static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev) +{ + return container_of(dev, struct usb_gadget, dev); +} +static inline struct usb_gadget *usb_get_gadget(struct usb_gadget *gadget) +{ + return gadget; +} +static inline void usb_put_gadget(struct usb_gadget *gadget) +{ +} +extern void usb_initialize_gadget(struct device *parent, + struct usb_gadget *gadget, void (*release)(struct device *dev)); +extern int usb_add_gadget(struct usb_gadget *gadget); +extern void usb_del_gadget(struct usb_gadget *gadget); + +/* Legacy device-model interface */ +extern int usb_add_gadget_udc_release(struct device *parent, + struct usb_gadget *gadget, void (*release)(struct device *dev)); +extern int usb_add_gadget_udc(struct device *parent, struct usb_gadget *gadget); +extern void usb_del_gadget_udc(struct usb_gadget *gadget); +extern char *usb_get_gadget_udc_name(void); + +/* iterates the non-control endpoints; 'tmp' is a struct usb_ep pointer */ +#define gadget_for_each_ep(tmp, gadget) \ + list_for_each_entry(tmp, &(gadget)->ep_list, ep_list) + +/** + * usb_ep_align - returns @len aligned to ep's maxpacketsize. + * @ep: the endpoint whose maxpacketsize is used to align @len + * @len: buffer size's length to align to @ep's maxpacketsize + * + * This helper is used to align buffer's size to an ep's maxpacketsize. + */ +static inline size_t usb_ep_align(struct usb_ep *ep, size_t len) +{ + int max_packet_size = (size_t)usb_endpoint_maxp(ep->desc); + + return round_up(len, max_packet_size); +} + +/** + * usb_ep_align_maybe - returns @len aligned to ep's maxpacketsize if gadget + * requires quirk_ep_out_aligned_size, otherwise returns len. + * @g: controller to check for quirk + * @ep: the endpoint whose maxpacketsize is used to align @len + * @len: buffer size's length to align to @ep's maxpacketsize + * + * This helper is used in case it's required for any reason to check and maybe + * align buffer's size to an ep's maxpacketsize. + */ +static inline size_t +usb_ep_align_maybe(struct usb_gadget *g, struct usb_ep *ep, size_t len) +{ + return g->quirk_ep_out_aligned_size ? usb_ep_align(ep, len) : len; +} + +/** + * gadget_is_altset_supported - return true iff the hardware supports + * altsettings + * @g: controller to check for quirk + */ +static inline int gadget_is_altset_supported(struct usb_gadget *g) +{ + return !g->quirk_altset_not_supp; +} + +/** + * gadget_is_stall_supported - return true iff the hardware supports stalling + * @g: controller to check for quirk + */ +static inline int gadget_is_stall_supported(struct usb_gadget *g) +{ + return !g->quirk_stall_not_supp; +} + +/** + * gadget_is_zlp_supported - return true iff the hardware supports zlp + * @g: controller to check for quirk + */ +static inline int gadget_is_zlp_supported(struct usb_gadget *g) +{ + return !g->quirk_zlp_not_supp; +} + +/** + * gadget_avoids_skb_reserve - return true iff the hardware would like to avoid + * skb_reserve to improve performance. + * @g: controller to check for quirk + */ +static inline int gadget_avoids_skb_reserve(struct usb_gadget *g) +{ + return g->quirk_avoids_skb_reserve; +} + +/** + * gadget_is_dualspeed - return true iff the hardware handles high speed + * @g: controller that might support both high and full speeds + */ +static inline int gadget_is_dualspeed(struct usb_gadget *g) +{ + return g->max_speed >= USB_SPEED_HIGH; +} + +/** + * gadget_is_superspeed() - return true if the hardware handles superspeed + * @g: controller that might support superspeed + */ +static inline int gadget_is_superspeed(struct usb_gadget *g) +{ + return g->max_speed >= USB_SPEED_SUPER; +} + +/** + * gadget_is_superspeed_plus() - return true if the hardware handles + * superspeed plus + * @g: controller that might support superspeed plus + */ +static inline int gadget_is_superspeed_plus(struct usb_gadget *g) +{ + return g->max_speed >= USB_SPEED_SUPER_PLUS; +} + +/** + * gadget_is_otg - return true iff the hardware is OTG-ready + * @g: controller that might have a Mini-AB connector + * + * This is a runtime test, since kernels with a USB-OTG stack sometimes + * run on boards which only have a Mini-B (or Mini-A) connector. + */ +static inline int gadget_is_otg(struct usb_gadget *g) +{ +#ifdef CONFIG_USB_OTG + return g->is_otg; +#else + return 0; +#endif +} + +/*-------------------------------------------------------------------------*/ + +#if IS_ENABLED(CONFIG_USB_GADGET) +int usb_gadget_frame_number(struct usb_gadget *gadget); +int usb_gadget_wakeup(struct usb_gadget *gadget); +int usb_gadget_set_selfpowered(struct usb_gadget *gadget); +int usb_gadget_clear_selfpowered(struct usb_gadget *gadget); +int usb_gadget_vbus_connect(struct usb_gadget *gadget); +int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA); +int usb_gadget_vbus_disconnect(struct usb_gadget *gadget); +int usb_gadget_connect(struct usb_gadget *gadget); +int usb_gadget_disconnect(struct usb_gadget *gadget); +int usb_gadget_deactivate(struct usb_gadget *gadget); +int usb_gadget_activate(struct usb_gadget *gadget); +int usb_gadget_check_config(struct usb_gadget *gadget); +#else +static inline int usb_gadget_frame_number(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_wakeup(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_vbus_connect(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_vbus_draw(struct usb_gadget *gadget, unsigned mA) +{ return 0; } +static inline int usb_gadget_vbus_disconnect(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_connect(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_disconnect(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_deactivate(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_activate(struct usb_gadget *gadget) +{ return 0; } +static inline int usb_gadget_check_config(struct usb_gadget *gadget) +{ return 0; } +#endif /* CONFIG_USB_GADGET */ + +/*-------------------------------------------------------------------------*/ + +/** + * struct usb_gadget_driver - driver for usb gadget devices + * @function: String describing the gadget's function + * @max_speed: Highest speed the driver handles. + * @setup: Invoked for ep0 control requests that aren't handled by + * the hardware level driver. Most calls must be handled by + * the gadget driver, including descriptor and configuration + * management. The 16 bit members of the setup data are in + * USB byte order. Called in_interrupt; this may not sleep. Driver + * queues a response to ep0, or returns negative to stall. + * @disconnect: Invoked after all transfers have been stopped, + * when the host is disconnected. May be called in_interrupt; this + * may not sleep. Some devices can't detect disconnect, so this might + * not be called except as part of controller shutdown. + * @bind: the driver's bind callback + * @unbind: Invoked when the driver is unbound from a gadget, + * usually from rmmod (after a disconnect is reported). + * Called in a context that permits sleeping. + * @suspend: Invoked on USB suspend. May be called in_interrupt. + * @resume: Invoked on USB resume. May be called in_interrupt. + * @reset: Invoked on USB bus reset. It is mandatory for all gadget drivers + * and should be called in_interrupt. + * @driver: Driver model state for this driver. + * @udc_name: A name of UDC this driver should be bound to. If udc_name is NULL, + * this driver will be bound to any available UDC. + * @match_existing_only: If udc is not found, return an error and fail + * the driver registration + * @is_bound: Allow a driver to be bound to only one gadget + * + * Devices are disabled till a gadget driver successfully bind()s, which + * means the driver will handle setup() requests needed to enumerate (and + * meet "chapter 9" requirements) then do some useful work. + * + * If gadget->is_otg is true, the gadget driver must provide an OTG + * descriptor during enumeration, or else fail the bind() call. In such + * cases, no USB traffic may flow until both bind() returns without + * having called usb_gadget_disconnect(), and the USB host stack has + * initialized. + * + * Drivers use hardware-specific knowledge to configure the usb hardware. + * endpoint addressing is only one of several hardware characteristics that + * are in descriptors the ep0 implementation returns from setup() calls. + * + * Except for ep0 implementation, most driver code shouldn't need change to + * run on top of different usb controllers. It'll use endpoints set up by + * that ep0 implementation. + * + * The usb controller driver handles a few standard usb requests. Those + * include set_address, and feature flags for devices, interfaces, and + * endpoints (the get_status, set_feature, and clear_feature requests). + * + * Accordingly, the driver's setup() callback must always implement all + * get_descriptor requests, returning at least a device descriptor and + * a configuration descriptor. Drivers must make sure the endpoint + * descriptors match any hardware constraints. Some hardware also constrains + * other descriptors. (The pxa250 allows only configurations 1, 2, or 3). + * + * The driver's setup() callback must also implement set_configuration, + * and should also implement set_interface, get_configuration, and + * get_interface. Setting a configuration (or interface) is where + * endpoints should be activated or (config 0) shut down. + * + * (Note that only the default control endpoint is supported. Neither + * hosts nor devices generally support control traffic except to ep0.) + * + * Most devices will ignore USB suspend/resume operations, and so will + * not provide those callbacks. However, some may need to change modes + * when the host is not longer directing those activities. For example, + * local controls (buttons, dials, etc) may need to be re-enabled since + * the (remote) host can't do that any longer; or an error state might + * be cleared, to make the device behave identically whether or not + * power is maintained. + */ +struct usb_gadget_driver { + char *function; + enum usb_device_speed max_speed; + int (*bind)(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); + void (*unbind)(struct usb_gadget *); + int (*setup)(struct usb_gadget *, + const struct usb_ctrlrequest *); + void (*disconnect)(struct usb_gadget *); + void (*suspend)(struct usb_gadget *); + void (*resume)(struct usb_gadget *); + void (*reset)(struct usb_gadget *); + + /* FIXME support safe rmmod */ + struct driver driver; + + char *udc_name; + unsigned match_existing_only:1; + bool is_bound:1; +}; + + + +/*-------------------------------------------------------------------------*/ + +/* driver modules register and unregister, as usual. + * these calls must be made in a context that can sleep. + * + * A gadget driver can be bound to only one gadget at a time. + */ + +/** + * usb_gadget_register_driver - register a gadget driver + * @driver: the driver being registered + * Context: can sleep + * + * Call this in your gadget driver's module initialization function, + * to tell the underlying UDC controller driver about your driver. + * The @bind() function will be called to bind it to a gadget before this + * registration call returns. It's expected that the @bind() function will + * be in init sections. + * + * Use the macro defined below instead of calling this directly. + */ +int usb_gadget_register_driver(struct usb_gadget_driver *driver); + +/** + * usb_gadget_unregister_driver - unregister a gadget driver + * @driver:the driver being unregistered + * Context: can sleep + * + * Call this in your gadget driver's module cleanup function, + * to tell the underlying usb controller that your driver is + * going away. If the controller is connected to a USB host, + * it will first disconnect(). The driver is also requested + * to unbind() and clean up any device state, before this procedure + * finally returns. It's expected that the unbind() functions + * will be in exit sections, so may not be linked in some kernels. + */ +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver); + +/*-------------------------------------------------------------------------*/ + +/* utility to simplify dealing with string descriptors */ + +/** + * struct usb_string - wraps a C string and its USB id + * @id:the (nonzero) ID for this string + * @s:the string, in UTF-8 encoding + * + * If you're using usb_gadget_get_string(), use this to wrap a string + * together with its ID. + */ +struct usb_string { + u8 id; + const char *s; +}; + +/** + * struct usb_gadget_strings - a set of USB strings in a given language + * @language:identifies the strings' language (0x0409 for en-us) + * @strings:array of strings with their ids + * + * If you're using usb_gadget_get_string(), use this to wrap all the + * strings for a given language. + */ +struct usb_gadget_strings { + u16 language; /* 0x0409 for en-us */ + struct usb_string *strings; +}; + +struct usb_gadget_string_container { + struct list_head list; + u8 *stash[]; +}; + +/* put descriptor for string with that id into buf (buflen >= 256) */ +int usb_gadget_get_string(const struct usb_gadget_strings *table, int id, u8 *buf); + +/* check if the given language identifier is valid */ +bool usb_validate_langid(u16 langid); + +struct gadget_string { + struct list_head list; + char string[USB_MAX_STRING_LEN]; + struct usb_string usb_string; +}; + +#define to_gadget_string(str_item)\ +container_of(str_item, struct gadget_string, item) + +/*-------------------------------------------------------------------------*/ + +/* utility to simplify managing config descriptors */ + +/* write vector of descriptors into buffer */ +int usb_descriptor_fillbuf(void *, unsigned, + const struct usb_descriptor_header **); + +/* build config descriptor from single descriptor vector */ +int usb_gadget_config_buf(const struct usb_config_descriptor *config, + void *buf, unsigned buflen, const struct usb_descriptor_header **desc); + +/* copy a NULL-terminated vector of descriptors */ +struct usb_descriptor_header **usb_copy_descriptors( + struct usb_descriptor_header **); + +/** + * usb_free_descriptors - free descriptors returned by usb_copy_descriptors() + * @v: vector of descriptors + */ +static inline void usb_free_descriptors(struct usb_descriptor_header **v) +{ + kfree(v); +} + +struct usb_function; +int usb_assign_descriptors(struct usb_function *f, + struct usb_descriptor_header **fs, + struct usb_descriptor_header **hs, + struct usb_descriptor_header **ss, + struct usb_descriptor_header **ssp); +void usb_free_all_descriptors(struct usb_function *f); + +struct usb_descriptor_header *usb_otg_descriptor_alloc( + struct usb_gadget *gadget); +int usb_otg_descriptor_init(struct usb_gadget *gadget, + struct usb_descriptor_header *otg_desc); +/*-------------------------------------------------------------------------*/ + +/* utility to simplify map/unmap of usb_requests to/from DMA */ + +#ifdef CONFIG_HAS_DMA +extern int usb_gadget_map_request_by_dev(struct device *dev, + struct usb_request *req, int is_in); +extern int usb_gadget_map_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in); + +extern void usb_gadget_unmap_request_by_dev(struct device *dev, + struct usb_request *req, int is_in); +extern void usb_gadget_unmap_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in); +#else /* !CONFIG_HAS_DMA */ +static inline int usb_gadget_map_request_by_dev(struct device *dev, + struct usb_request *req, int is_in) { return -ENOSYS; } +static inline int usb_gadget_map_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) { return -ENOSYS; } + +static inline void usb_gadget_unmap_request_by_dev(struct device *dev, + struct usb_request *req, int is_in) { } +static inline void usb_gadget_unmap_request(struct usb_gadget *gadget, + struct usb_request *req, int is_in) { } +#endif /* !CONFIG_HAS_DMA */ + +/*-------------------------------------------------------------------------*/ + +/* utility to set gadget state properly */ + +extern void usb_gadget_set_state(struct usb_gadget *gadget, + enum usb_device_state state); + +/*-------------------------------------------------------------------------*/ + +/* utility to tell udc core that the bus reset occurs */ +extern void usb_gadget_udc_reset(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); + +/*-------------------------------------------------------------------------*/ + +/* utility to give requests back to the gadget layer */ + +extern void usb_gadget_giveback_request(struct usb_ep *ep, + struct usb_request *req); + +/*-------------------------------------------------------------------------*/ + +/* utility to find endpoint by name */ + +extern struct usb_ep *gadget_find_ep_by_name(struct usb_gadget *g, + const char *name); + +/*-------------------------------------------------------------------------*/ + +/* utility to check if endpoint caps match descriptor needs */ + +extern int usb_gadget_ep_match_desc(struct usb_gadget *gadget, + struct usb_ep *ep, struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp); + +/*-------------------------------------------------------------------------*/ + +/* utility to update vbus status for udc core, it may be scheduled */ +extern void usb_udc_vbus_handler(struct usb_gadget *gadget, bool status); + +/*-------------------------------------------------------------------------*/ + +/* utility wrapping a simple endpoint selection policy */ + +extern struct usb_ep *usb_ep_autoconfig(struct usb_gadget *, + struct usb_endpoint_descriptor *); + + +extern struct usb_ep *usb_ep_autoconfig_ss(struct usb_gadget *, + struct usb_endpoint_descriptor *, + struct usb_ss_ep_comp_descriptor *); + +extern void usb_ep_autoconfig_release(struct usb_ep *); + +extern void usb_ep_autoconfig_reset(struct usb_gadget *); + +int usb_gadget_poll(void); + +#endif /* __LINUX_USB_GADGET_H */ diff --git a/include/linux/usb/mass_storage.h b/include/linux/usb/mass_storage.h new file mode 100644 index 0000000000..5bf7fea2f3 --- /dev/null +++ b/include/linux/usb/mass_storage.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2011 Samsung Electrnoics + * Lukasz Majewski <l.majewski@samsung.com> + */ + +#ifndef __USB_MASS_STORAGE_H__ +#define __USB_MASS_STORAGE_H__ + +#include <linux/usb/composite.h> + +/* Wait at maximum 60 seconds for cable connection */ +#define UMS_CABLE_READY_TIMEOUT 60 + +struct fsg_common; + +struct f_ums_opts { + struct usb_function_instance func_inst; + struct fsg_common *common; + struct file_list *files; + unsigned int num_sectors; + int fd; + int refcnt; + char name[16]; +}; + +int usb_ums_register(struct f_ums_opts *); + +#endif /* __USB_MASS_STORAGE_H__ */ diff --git a/include/linux/usb/musb.h b/include/linux/usb/musb.h new file mode 100644 index 0000000000..fb846dd30b --- /dev/null +++ b/include/linux/usb/musb.h @@ -0,0 +1,146 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * This is used to for host and peripheral modes of the driver for + * Inventra (Multidrop) Highspeed Dual-Role Controllers: (M)HDRC. + * + * Board initialization should put one of these into dev->platform_data, + * probably on some platform_device named "musb-hdrc". It encapsulates + * key configuration differences between boards. + */ + +#ifndef __LINUX_USB_MUSB_H +#define __LINUX_USB_MUSB_H + +/* The USB role is defined by the connector used on the board, so long as + * standards are being followed. (Developer boards sometimes won't.) + */ +enum musb_mode { + MUSB_UNDEFINED = 0, + MUSB_HOST, /* A or Mini-A connector */ + MUSB_PERIPHERAL, /* B or Mini-B connector */ + MUSB_OTG /* Mini-AB connector */ +}; + +struct clk; + +enum musb_fifo_style { + FIFO_RXTX, + FIFO_TX, + FIFO_RX +} __attribute__ ((packed)); + +enum musb_buf_mode { + BUF_SINGLE, + BUF_DOUBLE +} __attribute__ ((packed)); + +struct musb_fifo_cfg { + u8 hw_ep_num; + enum musb_fifo_style style; + enum musb_buf_mode mode; + u16 maxpacket; +}; + +#define MUSB_EP_FIFO(ep, st, m, pkt) \ +{ \ + .hw_ep_num = ep, \ + .style = st, \ + .mode = m, \ + .maxpacket = pkt, \ +} + +#define MUSB_EP_FIFO_SINGLE(ep, st, pkt) \ + MUSB_EP_FIFO(ep, st, BUF_SINGLE, pkt) + +#define MUSB_EP_FIFO_DOUBLE(ep, st, pkt) \ + MUSB_EP_FIFO(ep, st, BUF_DOUBLE, pkt) + +struct musb_hdrc_eps_bits { + const char name[16]; + u8 bits; +}; + +struct musb_hdrc_config { + struct musb_fifo_cfg *fifo_cfg; /* board fifo configuration */ + unsigned fifo_cfg_size; /* size of the fifo configuration */ + + /* MUSB configuration-specific details */ + unsigned multipoint:1; /* multipoint device */ + unsigned dyn_fifo:1 __deprecated; /* supports dynamic fifo sizing */ + unsigned soft_con:1 __deprecated; /* soft connect required */ + unsigned utm_16:1 __deprecated; /* utm data witdh is 16 bits */ + unsigned big_endian:1; /* true if CPU uses big-endian */ + unsigned mult_bulk_tx:1; /* Tx ep required for multbulk pkts */ + unsigned mult_bulk_rx:1; /* Rx ep required for multbulk pkts */ + unsigned high_iso_tx:1; /* Tx ep required for HB iso */ + unsigned high_iso_rx:1; /* Rx ep required for HD iso */ + unsigned dma:1 __deprecated; /* supports DMA */ + unsigned vendor_req:1 __deprecated; /* vendor registers required */ + + u8 num_eps; /* number of endpoints _with_ ep0 */ + u8 dma_channels __deprecated; /* number of dma channels */ + u8 dyn_fifo_size; /* dynamic size in bytes */ + u8 vendor_ctrl __deprecated; /* vendor control reg width */ + u8 vendor_stat __deprecated; /* vendor status reg witdh */ + u8 dma_req_chan __deprecated; /* bitmask for required dma channels */ + u8 ram_bits; /* ram address size */ + + struct musb_hdrc_eps_bits *eps_bits __deprecated; +}; + +struct musb_hdrc_platform_data { + /* MUSB_HOST, MUSB_PERIPHERAL, or MUSB_OTG */ + u8 mode; + + /* for clk_get() */ + const char *clock; + + /* (HOST or OTG) switch VBUS on/off */ + int (*set_vbus)(struct device *dev, int is_on); + + /* (HOST or OTG) mA/2 power supplied on (default = 8mA) */ + u8 power; + + /* (PERIPHERAL) mA/2 max power consumed (default = 100mA) */ + u8 min_power; + + /* (HOST or OTG) msec/2 after VBUS on till power good */ + u8 potpgt; + + /* (HOST or OTG) program PHY for external Vbus */ + unsigned extvbus:1; + + /* Power the device on or off */ + int (*set_power)(int state); + + /* MUSB configuration-specific details */ + struct musb_hdrc_config *config; + + /* Architecture specific board data */ + void *board_data; + + /* Platform specific struct musb_ops pointer */ + const void *platform_ops; +}; + + +/* TUSB 6010 support */ + +#define TUSB6010_OSCCLK_60 16667 /* psec/clk @ 60.0 MHz */ +#define TUSB6010_REFCLK_24 41667 /* psec/clk @ 24.0 MHz XI */ +#define TUSB6010_REFCLK_19 52083 /* psec/clk @ 19.2 MHz CLKIN */ + +#ifdef CONFIG_ARCH_OMAP2 + +extern int __init tusb6010_setup_interface( + struct musb_hdrc_platform_data *data, + unsigned ps_refclk, unsigned waitpin, + unsigned async_cs, unsigned sync_cs, + unsigned irq, unsigned dmachan); + +extern int tusb6010_platform_retime(unsigned is_refclk); + +#endif /* OMAP2 */ + +#endif /* __LINUX_USB_MUSB_H */ diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h new file mode 100644 index 0000000000..651a8824f3 --- /dev/null +++ b/include/linux/usb/phy.h @@ -0,0 +1,222 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* USB OTG (On The Go) defines */ +/* + * + * These APIs may be used between USB controllers. USB device drivers + * (for either host or peripheral roles) don't use these calls; they + * continue to use just usb_device and usb_gadget. + */ + +#ifndef __LINUX_USB_PHY_H +#define __LINUX_USB_PHY_H + +#include <notifier.h> +#include <linux/usb/usb.h> +#include <linux/err.h> + +enum usb_phy_interface { + USBPHY_INTERFACE_MODE_UNKNOWN, + USBPHY_INTERFACE_MODE_UTMI, + USBPHY_INTERFACE_MODE_UTMIW, + USBPHY_INTERFACE_MODE_ULPI, + USBPHY_INTERFACE_MODE_SERIAL, + USBPHY_INTERFACE_MODE_HSIC, +}; + +enum usb_phy_events { + USB_EVENT_NONE, /* no events or cable disconnected */ + USB_EVENT_VBUS, /* vbus valid event */ + USB_EVENT_ID, /* id was grounded */ + USB_EVENT_CHARGER, /* usb dedicated charger */ + USB_EVENT_ENUMERATED, /* gadget driver enumerated */ +}; + +/* associate a type with PHY */ +enum usb_phy_type { + USB_PHY_TYPE_UNDEFINED, + USB_PHY_TYPE_USB2, + USB_PHY_TYPE_USB3, +}; + +struct usb_phy; + +/* for transceivers connected thru an ULPI interface, the user must + * provide access ops + */ +struct usb_phy_io_ops { + int (*read)(struct usb_phy *x, u32 reg); + int (*write)(struct usb_phy *x, u32 val, u32 reg); +}; + +struct usb_phy { + struct device *dev; + const char *label; + unsigned int flags; + + enum usb_phy_type type; + enum usb_phy_events last_event; + + struct usb_phy_io_ops *io_ops; + void __iomem *io_priv; + + /* to pass extra port status to the root hub */ + u16 port_status; + u16 port_change; + + /* to support controllers that have multiple transceivers */ + struct list_head head; + + /* initialize/shutdown the OTG controller */ + int (*init)(struct usb_phy *x); + void (*shutdown)(struct usb_phy *x); + + /* enable/disable VBUS */ + int (*set_vbus)(struct usb_phy *x, int on); + + /* effective for B devices, ignored for A-peripheral */ + int (*set_power)(struct usb_phy *x, + unsigned mA); + + /* for non-OTG B devices: set transceiver into suspend mode */ + int (*set_suspend)(struct usb_phy *x, + int suspend); + + /* + * Set wakeup enable for PHY, in that case, the PHY can be + * woken up from suspend status due to external events, + * like vbus change, dp/dm change and id. + */ + int (*set_wakeup)(struct usb_phy *x, bool enabled); + + /* notify phy connect status change */ + int (*notify_connect)(struct usb_phy *x, + enum usb_device_speed speed); + int (*notify_disconnect)(struct usb_phy *x, + enum usb_device_speed speed); +}; + +/** + * struct usb_phy_bind - represent the binding for the phy + * @dev_name: the device name of the device that will bind to the phy + * @phy_dev_name: the device name of the phy + * @index: used if a single controller uses multiple phys + * @phy: reference to the phy + * @list: to maintain a linked list of the binding information + */ +struct usb_phy_bind { + const char *dev_name; + const char *phy_dev_name; + u8 index; + struct usb_phy *phy; + struct list_head list; +}; + +/* helpers for direct access thru low-level io interface */ +static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) +{ + if (x && x->io_ops && x->io_ops->read) + return x->io_ops->read(x, reg); + + return -EINVAL; +} + +static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg) +{ + if (x && x->io_ops && x->io_ops->write) + return x->io_ops->write(x, val, reg); + + return -EINVAL; +} + +static inline int +usb_phy_init(struct usb_phy *x) +{ + if (x && x->init) + return x->init(x); + + return 0; +} + +static inline void +usb_phy_shutdown(struct usb_phy *x) +{ + if (x && x->shutdown) + x->shutdown(x); +} + +static inline int +usb_phy_vbus_on(struct usb_phy *x) +{ + if (!x || !x->set_vbus) + return 0; + + return x->set_vbus(x, true); +} + +static inline int +usb_phy_vbus_off(struct usb_phy *x) +{ + if (!x || !x->set_vbus) + return 0; + + return x->set_vbus(x, false); +} + +static inline int +usb_phy_set_power(struct usb_phy *x, unsigned mA) +{ + if (x && x->set_power) + return x->set_power(x, mA); + return 0; +} + +/* Context: can sleep */ +static inline int +usb_phy_set_suspend(struct usb_phy *x, int suspend) +{ + if (x && x->set_suspend != NULL) + return x->set_suspend(x, suspend); + else + return 0; +} + +static inline int +usb_phy_set_wakeup(struct usb_phy *x, bool enabled) +{ + if (x && x->set_wakeup) + return x->set_wakeup(x, enabled); + else + return 0; +} + +static inline int +usb_phy_notify_connect(struct usb_phy *x, enum usb_device_speed speed) +{ + if (x && x->notify_connect) + return x->notify_connect(x, speed); + else + return 0; +} + +static inline int +usb_phy_notify_disconnect(struct usb_phy *x, enum usb_device_speed speed) +{ + if (x && x->notify_disconnect) + return x->notify_disconnect(x, speed); + else + return 0; +} + +static inline const char *usb_phy_type_string(enum usb_phy_type type) +{ + switch (type) { + case USB_PHY_TYPE_USB2: + return "USB2 PHY"; + case USB_PHY_TYPE_USB3: + return "USB3 PHY"; + default: + return "UNKNOWN PHY TYPE"; + } +} +#endif /* __LINUX_USB_PHY_H */ diff --git a/include/linux/usb/role.h b/include/linux/usb/role.h new file mode 100644 index 0000000000..bf78db7e6f --- /dev/null +++ b/include/linux/usb/role.h @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 + +#ifndef __LINUX_USB_ROLE_H +#define __LINUX_USB_ROLE_H + +enum usb_role { + USB_ROLE_NONE, + USB_ROLE_HOST, + USB_ROLE_DEVICE, +}; + +#endif /* __LINUX_USB_ROLE_H */ diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h new file mode 100644 index 0000000000..e0240f8645 --- /dev/null +++ b/include/linux/usb/storage.h @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: GPL-2.0 +#ifndef __LINUX_USB_STORAGE_H +#define __LINUX_USB_STORAGE_H + +/* + * linux/usb/storage.h + * + * Copyright Matthew Wilcox for Intel Corp, 2010 + * + * This file contains definitions taken from the + * USB Mass Storage Class Specification Overview + * + * Distributed under the terms of the GNU GPL, version two. + */ + +/* Storage subclass codes */ + +#define USB_SC_RBC 0x01 /* Typically, flash devices */ +#define USB_SC_8020 0x02 /* CD-ROM */ +#define USB_SC_QIC 0x03 /* QIC-157 Tapes */ +#define USB_SC_UFI 0x04 /* Floppy */ +#define USB_SC_8070 0x05 /* Removable media */ +#define USB_SC_SCSI 0x06 /* Transparent */ +#define USB_SC_LOCKABLE 0x07 /* Password-protected */ + +#define USB_SC_ISD200 0xf0 /* ISD200 ATA */ +#define USB_SC_CYP_ATACB 0xf1 /* Cypress ATACB */ +#define USB_SC_DEVICE 0xff /* Use device's value */ + +/* Storage protocol codes */ + +#define USB_PR_CBI 0x00 /* Control/Bulk/Interrupt */ +#define USB_PR_CB 0x01 /* Control/Bulk w/o interrupt */ +#define USB_PR_BULK 0x50 /* bulk only */ +#define USB_PR_UAS 0x62 /* USB Attached SCSI */ + +#define USB_PR_USBAT 0x80 /* SCM-ATAPI bridge */ +#define USB_PR_EUSB_SDDR09 0x81 /* SCM-SCSI bridge for SDDR-09 */ +#define USB_PR_SDDR55 0x82 /* SDDR-55 (made up) */ +#define USB_PR_DPCM_USB 0xf0 /* Combination CB/SDDR09 */ +#define USB_PR_FREECOM 0xf1 /* Freecom */ +#define USB_PR_DATAFAB 0xf2 /* Datafab chipsets */ +#define USB_PR_JUMPSHOT 0xf3 /* Lexar Jumpshot */ +#define USB_PR_ALAUDA 0xf4 /* Alauda chipsets */ +#define USB_PR_KARMA 0xf5 /* Rio Karma */ + +#define USB_PR_DEVICE 0xff /* Use device's value */ + +/* + * Bulk only data structures + */ + +/* command block wrapper */ +struct bulk_cb_wrap { + __le32 Signature; /* contains 'USBC' */ + __u32 Tag; /* unique per command id */ + __le32 DataTransferLength; /* size of data */ + __u8 Flags; /* direction in bit 0 */ + __u8 Lun; /* LUN normally 0 */ + __u8 Length; /* length of the CDB */ + __u8 CDB[16]; /* max command */ +}; + +#define US_BULK_CB_WRAP_LEN 31 +#define US_BULK_CB_SIGN 0x43425355 /* spells out 'USBC' */ +#define US_BULK_FLAG_IN (1 << 7) +#define US_BULK_FLAG_OUT 0 + +/* command status wrapper */ +struct bulk_cs_wrap { + __le32 Signature; /* contains 'USBS' */ + __u32 Tag; /* same as original command */ + __le32 Residue; /* amount not transferred */ + __u8 Status; /* see below */ +}; + +#define US_BULK_CS_WRAP_LEN 13 +#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ +#define US_BULK_STAT_OK 0 +#define US_BULK_STAT_FAIL 1 +#define US_BULK_STAT_PHASE 2 + +/* bulk-only class specific requests */ +#define US_BULK_RESET_REQUEST 0xff +#define US_BULK_GET_MAX_LUN 0xfe + +#endif diff --git a/include/linux/usb/twl4030.h b/include/linux/usb/twl4030.h new file mode 100644 index 0000000000..66f5156f9e --- /dev/null +++ b/include/linux/usb/twl4030.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de> + * Copyright (C) 2010 Sascha Hauer <sha@pengutronix.de> + * + * This file is released under the GPLv2 + * + */ + +#ifndef __USB_TWL4030_H +#define __USB_TWL4030_H + +/* Defines for bits in registers */ +#define OPMODE_MASK (3 << 3) +#define XCVRSELECT_MASK (3 << 0) +#define CARKITMODE (1 << 2) +#define OTG_ENAB (1 << 5) +#define PHYPWD (1 << 0) +#define CLOCKGATING_EN (1 << 2) +#define CLK32K_EN (1 << 1) +#define REQ_PHY_DPLL_CLK (1 << 0) +#define PHY_DPLL_CLK (1 << 0) + +/* + * USB + */ +int twl4030_usb_ulpi_init(void); + +#endif /* __USB_TWL4030_H */ diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h new file mode 100644 index 0000000000..315dee95e4 --- /dev/null +++ b/include/linux/usb/typec.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __LINUX_USB_TYPEC_H +#define __LINUX_USB_TYPEC_H + +#include <linux/types.h> +#include <linux/usb/role.h> + +struct typec_port; + +struct device; +struct device_node; + +enum typec_role { + TYPEC_SINK, + TYPEC_SOURCE, +}; + +enum typec_accessory { + TYPEC_ACCESSORY_NONE, + TYPEC_ACCESSORY_AUDIO, + TYPEC_ACCESSORY_DEBUG, +}; + +struct typec_operations { + int (*poll)(struct typec_port *port); +}; + +/* + * struct typec_capability - USB Type-C Port Capabilities + * @driver_data: Private pointer for driver specific info + * @ops: Port operations vector + * + * Static capabilities of a single USB Type-C port. + */ +struct typec_capability { + void *driver_data; + + const struct typec_operations *ops; + struct device_node *of_node; +}; + +struct typec_port *typec_register_port(struct device *parent, + const struct typec_capability *cap); + +void typec_set_pwr_role(struct typec_port *port, enum typec_role role); + +int typec_set_mode(struct typec_port *port, int mode); + +int typec_set_role(struct typec_port *port, enum usb_role role); + +void *typec_get_drvdata(struct typec_port *port); + +#endif /* __LINUX_USB_TYPEC_H */ diff --git a/include/linux/usb/typec_altmode.h b/include/linux/usb/typec_altmode.h new file mode 100644 index 0000000000..ffa4a8f754 --- /dev/null +++ b/include/linux/usb/typec_altmode.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __USB_TYPEC_ALTMODE_H +#define __USB_TYPEC_ALTMODE_H + +/* + * These are the connector states (USB, Safe and Alt Mode) defined in USB Type-C + * Specification. SVID specific connector states are expected to follow and + * start from the value TYPEC_STATE_MODAL. + */ +enum { + TYPEC_STATE_SAFE, /* USB Safe State */ + TYPEC_STATE_USB, /* USB Operation */ + TYPEC_STATE_MODAL, /* Alternate Modes */ +}; + +/* + * For the muxes there is no difference between Accessory Modes and Alternate + * Modes, so the Accessory Modes are supplied with specific modal state values + * here. Unlike with Alternate Modes, where the mux will be linked with the + * alternate mode device, the mux for Accessory Modes will be linked with the + * port device instead. + * + * Port drivers can use TYPEC_MODE_AUDIO and TYPEC_MODE_DEBUG as the mode + * value for typec_set_mode() when accessory modes are supported. + * + * USB4 also requires that the pins on the connector are repurposed, just like + * Alternate Modes. USB4 mode is however not entered with the Enter Mode Command + * like the Alternate Modes are, but instead with a special Enter_USB Message. + * The Enter_USB Message can also be used for setting to connector to operate in + * USB 3.2 or in USB 2.0 mode instead of USB4. + * + * The Enter_USB specific "USB Modes" are also supplied here as special modal + * state values, just like the Accessory Modes. + */ +enum { + TYPEC_MODE_USB2 = TYPEC_STATE_MODAL, /* USB 2.0 mode */ + TYPEC_MODE_USB3, /* USB 3.2 mode */ + TYPEC_MODE_USB4, /* USB4 mode */ + TYPEC_MODE_AUDIO, /* Audio Accessory */ + TYPEC_MODE_DEBUG, /* Debug Accessory */ +}; + +#endif /* __USB_TYPEC_ALTMODE_H */ diff --git a/include/linux/usb/ulpi.h b/include/linux/usb/ulpi.h new file mode 100644 index 0000000000..efbfc63208 --- /dev/null +++ b/include/linux/usb/ulpi.h @@ -0,0 +1,61 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef __MACH_ULPI_H +#define __MACH_ULPI_H + +int ulpi_write(u8 bits, int reg, void __iomem *view); +int ulpi_set(u8 bits, int reg, void __iomem *view); +int ulpi_clear(u8 bits, int reg, void __iomem *view); +int ulpi_read(int reg, void __iomem *view); +int ulpi_setup(void __iomem *view, int on); + +/* ULPI register addresses */ +#define ULPI_VID_LOW 0x00 /* Vendor ID low */ +#define ULPI_VID_HIGH 0x01 /* Vendor ID high */ +#define ULPI_PID_LOW 0x02 /* Product ID low */ +#define ULPI_PID_HIGH 0x03 /* Product ID high */ +#define ULPI_FUNCTION_CTRL 0x04 +#define ULPI_ITFCTL 0x07 /* Interface Control */ +#define ULPI_OTGCTL 0x0A /* OTG Control */ + +/* add to above register address to access Set/Clear functions */ +#define ULPI_REG_SET 0x01 +#define ULPI_REG_CLEAR 0x02 + +/* Function Control */ +#define ULPI_FC_XCVRSEL_MASK (3 << 0) +#define ULPI_FC_HIGH_SPEED (0 << 0) +#define ULPI_FC_FULL_SPEED (1 << 0) +#define ULPI_FC_LOW_SPEED (2 << 0) +#define ULPI_FC_FS4LS (3 << 0) +#define ULPI_FC_TERMSELECT (1 << 2) +#define ULPI_FC_OPMODE_MASK (3 << 3) +#define ULPI_FC_OPMODE_NORMAL (0 << 3) +#define ULPI_FC_OPMODE_NONDRIVING (1 << 3) +#define ULPI_FC_OPMODE_DISABLE_NRZI (2 << 3) +#define ULPI_FC_OPMODE_NOSYNC_NOEOP (3 << 3) +#define ULPI_FC_RESET (1 << 5) +#define ULPI_FC_SUSPENDM (1 << 6) + +/* Interface Control */ +#define ULPI_IFACE_6_PIN_SERIAL_MODE (1 << 0) +#define ULPI_IFACE_3_PIN_SERIAL_MODE (1 << 1) +#define ULPI_IFACE_CARKITMODE (1 << 2) +#define ULPI_IFACE_CLOCKSUSPENDM (1 << 3) +#define ULPI_IFACE_AUTORESUME (1 << 4) +#define ULPI_IFACE_EXTVBUS_COMPLEMENT (1 << 5) +#define ULPI_IFACE_PASSTHRU (1 << 6) +#define ULPI_IFACE_PROTECT_IFC_DISABLE (1 << 7) + +/* ULPI OTG Control Register bits */ +#define ULPI_OTG_USE_EXT_VBUS_IND (1 << 7) /* Use ext. Vbus indicator */ +#define ULPI_OTG_DRV_VBUS_EXT (1 << 6) /* Drive Vbus external */ +#define ULPI_OTG_DRV_VBUS (1 << 5) /* Drive Vbus */ +#define ULPI_OTG_CHRG_VBUS (1 << 4) /* Charge Vbus */ +#define ULPI_OTG_DISCHRG_VBUS (1 << 3) /* Discharge Vbus */ +#define ULPI_OTG_DM_PULL_DOWN (1 << 2) /* enable DM Pull Down */ +#define ULPI_OTG_DP_PULL_DOWN (1 << 1) /* enable DP Pull Down */ +#define ULPI_OTG_ID_PULL_UP (1 << 0) /* enable ID Pull Up */ + +#endif /* __MACH_ULPI_H */ + diff --git a/include/linux/usb/usb.h b/include/linux/usb/usb.h new file mode 100644 index 0000000000..4ad2fd32d2 --- /dev/null +++ b/include/linux/usb/usb.h @@ -0,0 +1,499 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_H_ +#define _USB_H_ + +#include <driver.h> +#include <slice.h> +#include <linux/usb/ch9.h> +#include <uapi/linux/usb/ch11.h> +#include <linux/usb/usb_defs.h> +#include <asm/byteorder.h> + +/* Everything is aribtrary */ +#define USB_ALTSETTINGALLOC 4 +#define USB_MAXALTSETTING 128 /* Hard limit */ + +#define USB_MAX_DEVICE 32 +#define USB_MAXCONFIG 8 +#define USB_MAXINTERFACES 16 +#define USB_MAXENDPOINTS 16 +#define USB_MAXCHILDREN 8 /* This is arbitrary */ +#define USB_MAX_HUB 16 + +#define USB_CNTL_TIMEOUT 5000 /* 5000ms timeout */ + +/* device request (setup) */ +struct devrequest { + unsigned char requesttype; + unsigned char request; + unsigned short value; + unsigned short index; + unsigned short length; +} __attribute__ ((packed)); + +enum { + /* Maximum packet size; encoded as 0,1,2,3 = 8,16,32,64 */ + PACKET_SIZE_8 = 0, + PACKET_SIZE_16 = 1, + PACKET_SIZE_32 = 2, + PACKET_SIZE_64 = 3, +}; + +struct usb_interface { + struct usb_interface_descriptor desc; + + unsigned char no_of_ep; + unsigned char num_altsetting; + unsigned char act_altsetting; + + struct usb_endpoint_descriptor ep_desc[USB_MAXENDPOINTS]; + /* + * Super Speed Device will have Super Speed Endpoint + * Companion Descriptor (section 9.6.7 of usb 3.0 spec) + * Revision 1.0 June 6th 2011 + */ + struct usb_ss_ep_comp_descriptor ss_ep_comp_desc[USB_MAXENDPOINTS]; +}; + +struct usb_config { + struct usb_config_descriptor desc; + + unsigned char no_of_if; /* number of interfaces */ + struct usb_interface interface[USB_MAXINTERFACES]; +}; + +struct usb_device { + int devnum; /* Device number on USB bus */ + int speed; /* full/low/high */ + char mf[32]; /* manufacturer */ + char prod[32]; /* product */ + char serial[32]; /* serial number */ + + /* Maximum packet size; one of: PACKET_SIZE_* */ + int maxpacketsize; + /* one bit for each endpoint ([0] = IN, [1] = OUT) */ + unsigned int toggle[2]; + /* endpoint halts; one bit per endpoint # & direction; + * [0] = IN, [1] = OUT + */ + unsigned int halted[2]; + int epmaxpacketin[16]; /* INput endpoint specific maximums */ + int epmaxpacketout[16]; /* OUTput endpoint specific maximums */ + + int configno; /* selected config number */ + struct usb_device_descriptor *descriptor; /* Device Descriptor */ + struct usb_config config; /* config descriptor */ + struct devrequest *setup_packet; + + int have_langid; /* whether string_langid is valid yet */ + int string_langid; /* language ID for strings */ + /* + * Child devices - if this is a hub device + * Each instance needs its own set of data structures. + */ + unsigned long status; + int act_len; /* transfered bytes */ + int maxchild; /* Number of ports if hub */ + int portnr; + int level; + struct usb_device *parent; + struct usb_device *children[USB_MAXCHILDREN]; + + struct device dev; + + struct usb_host *host; + + struct list_head list; + void *drv_data; + struct usb_hub_device *hub; + + /* slot_id - for xHCI enabled devices */ + unsigned int slot_id; +}; + +struct usb_device_id; + +struct usb_driver { + const char *name; + int (*probe) (struct usb_device *, const struct usb_device_id *); + void (*disconnect)(struct usb_device *); + + const struct usb_device_id *id_table; + + struct driver driver; +}; + +extern struct bus_type usb_bus_type; + +int usb_driver_register(struct usb_driver *); + +struct usb_host { + int (*init)(struct usb_host *); + int (*exit)(struct usb_host *); + int (*submit_bulk_msg)(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, int timeout_ms); + int (*submit_control_msg)(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int timeout_ms); + int (*submit_int_msg)(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval); + void (*usb_event_poll)(void); + int (*alloc_device)(struct usb_device *dev); + int (*update_hub_device)(struct usb_device *dev); + + bool no_desc_before_addr; + + struct list_head list; + + struct device *hw_dev; + int busnum; + struct usb_device *root_dev; + struct usb_phy *usbphy; + struct slice slice; +}; + +int usb_register_host(struct usb_host *); +void usb_unregister_host(struct usb_host *host); + +static inline struct slice *usb_device_slice(struct usb_device *udev) +{ + return &udev->host->slice; +} + +int usb_host_detect(struct usb_host *host); + +int usb_set_protocol(struct usb_device *dev, int ifnum, int protocol); +int usb_set_idle(struct usb_device *dev, int ifnum, int duration, + int report_id); +int usb_control_msg(struct usb_device *dev, unsigned int pipe, + unsigned char request, unsigned char requesttype, + unsigned short value, unsigned short index, + void *data, unsigned short size, int timeout_ms); +int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout_ms); +int usb_submit_int_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, int interval); +int usb_maxpacket(struct usb_device *dev, unsigned long pipe); +int usb_get_configuration_no(struct usb_device *dev, unsigned char *buffer, + int cfgno); +int usb_get_report(struct usb_device *dev, int ifnum, unsigned char type, + unsigned char id, void *buf, int size); +int usb_get_class_descriptor(struct usb_device *dev, int ifnum, + unsigned char type, unsigned char id, void *buf, + int size); +int usb_clear_halt(struct usb_device *dev, int pipe); +int usb_string(struct usb_device *dev, int index, char *buf, size_t size); +int usb_set_interface(struct usb_device *dev, int interface, int alternate); + +int usb_rescan(void); + +/* big endian -> little endian conversion */ +/* some CPUs are already little endian e.g. the ARM920T */ +#define __swap_16(x) \ + ({ unsigned short x_ = (unsigned short)x; \ + (unsigned short)( \ + ((x_ & 0x00FFU) << 8) | ((x_ & 0xFF00U) >> 8)); \ + }) +#define __swap_32(x) \ + ({ unsigned long x_ = (unsigned long)x; \ + (unsigned long)( \ + ((x_ & 0x000000FFUL) << 24) | \ + ((x_ & 0x0000FF00UL) << 8) | \ + ((x_ & 0x00FF0000UL) >> 8) | \ + ((x_ & 0xFF000000UL) >> 24)); \ + }) + +#ifdef __LITTLE_ENDIAN +# define swap_16(x) (x) +# define swap_32(x) (x) +#elif defined __BIG_ENDIAN +# define swap_16(x) __swap_16(x) +# define swap_32(x) __swap_32(x) +#else +#error "could not determine byte order" +#endif + +/* + * Calling this entity a "pipe" is glorifying it. A USB pipe + * is something embarrassingly simple: it basically consists + * of the following information: + * - device number (7 bits) + * - endpoint number (4 bits) + * - current Data0/1 state (1 bit) + * - direction (1 bit) + * - speed (2 bits) + * - max packet size (2 bits: 8, 16, 32 or 64) + * - pipe type (2 bits: control, interrupt, bulk, isochronous) + * + * That's 18 bits. Really. Nothing more. And the USB people have + * documented these eighteen bits as some kind of glorious + * virtual data structure. + * + * Let's not fall in that trap. We'll just encode it as a simple + * unsigned int. The encoding is: + * + * - max size: bits 0-1 (00 = 8, 01 = 16, 10 = 32, 11 = 64) + * - direction: bit 7 (0 = Host-to-Device [Out], + * (1 = Device-to-Host [In]) + * - device: bits 8-14 + * - endpoint: bits 15-18 + * - Data0/1: bit 19 + * - speed: bit 26 (0 = Full, 1 = Low Speed, 2 = High) + * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt, + * 10 = control, 11 = bulk) + * + * Why? Because it's arbitrary, and whatever encoding we select is really + * up to us. This one happens to share a lot of bit positions with the UHCI + * specification, so that much of the uhci driver can just mask the bits + * appropriately. + */ +/* Create various pipes... */ +#define create_pipe(dev,endpoint) \ + (((dev)->devnum << 8) | ((endpoint) << 15) | \ + ((dev)->speed << 26) | (dev)->maxpacketsize) +#define default_pipe(dev) ((dev)->speed << 26) + +#define usb_sndctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \ + create_pipe(dev, (endpoint))) +#define usb_rcvctrlpipe(dev, endpoint) ((PIPE_CONTROL << 30) | \ + create_pipe(dev, (endpoint)) | \ + USB_DIR_IN) +#define usb_sndisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \ + create_pipe(dev, (endpoint))) +#define usb_rcvisocpipe(dev, endpoint) ((PIPE_ISOCHRONOUS << 30) | \ + create_pipe(dev, (endpoint)) | \ + USB_DIR_IN) +#define usb_sndbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \ + create_pipe(dev, (endpoint))) +#define usb_rcvbulkpipe(dev, endpoint) ((PIPE_BULK << 30) | \ + create_pipe(dev, (endpoint)) | \ + USB_DIR_IN) +#define usb_sndintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \ + create_pipe(dev, (endpoint))) +#define usb_rcvintpipe(dev, endpoint) ((PIPE_INTERRUPT << 30) | \ + create_pipe(dev, (endpoint)) | \ + USB_DIR_IN) +#define usb_snddefctrl(dev) ((PIPE_CONTROL << 30) | \ + default_pipe(dev)) +#define usb_rcvdefctrl(dev) ((PIPE_CONTROL << 30) | \ + default_pipe(dev) | \ + USB_DIR_IN) + +/* The D0/D1 toggle bits */ +#define usb_gettoggle(dev, ep, out) (((dev)->toggle[out] >> ep) & 1) +#define usb_dotoggle(dev, ep, out) ((dev)->toggle[out] ^= (1 << ep)) +#define usb_settoggle(dev, ep, out, bit) ((dev)->toggle[out] = \ + ((dev)->toggle[out] & \ + ~(1 << ep)) | ((bit) << ep)) + +/* Endpoint halt control/status */ +#define usb_endpoint_out(ep_dir) (((ep_dir >> 7) & 1) ^ 1) +#define usb_endpoint_halt(dev, ep, out) ((dev)->halted[out] |= (1 << (ep))) +#define usb_endpoint_running(dev, ep, out) ((dev)->halted[out] &= ~(1 << (ep))) +#define usb_endpoint_halted(dev, ep, out) ((dev)->halted[out] & (1 << (ep))) + +#define usb_packetid(pipe) (((pipe) & USB_DIR_IN) ? USB_PID_IN : \ + USB_PID_OUT) + +#define usb_pipeout(pipe) ((((pipe) >> 7) & 1) ^ 1) +#define usb_pipein(pipe) (((pipe) >> 7) & 1) +#define usb_pipedevice(pipe) (((pipe) >> 8) & 0x7f) +#define usb_pipe_endpdev(pipe) (((pipe) >> 8) & 0x7ff) +#define usb_pipeendpoint(pipe) (((pipe) >> 15) & 0xf) +#define usb_pipedata(pipe) (((pipe) >> 19) & 1) +#define usb_pipetype(pipe) (((pipe) >> 30) & 3) +#define usb_pipeisoc(pipe) (usb_pipetype((pipe)) == PIPE_ISOCHRONOUS) +#define usb_pipeint(pipe) (usb_pipetype((pipe)) == PIPE_INTERRUPT) +#define usb_pipecontrol(pipe) (usb_pipetype((pipe)) == PIPE_CONTROL) +#define usb_pipebulk(pipe) (usb_pipetype((pipe)) == PIPE_BULK) + +#define usb_pipe_ep_index(pipe) \ + usb_pipecontrol(pipe) ? (usb_pipeendpoint(pipe) * 2) : \ + ((usb_pipeendpoint(pipe) * 2) - \ + (usb_pipein(pipe) ? 0 : 1)) + +/* + * As of USB 2.0, full/low speed devices are segregated into trees. + * One type grows from USB 1.1 host controllers (OHCI, UHCI etc). + * The other type grows from high speed hubs when they connect to + * full/low speed devices using "Transaction Translators" (TTs). + */ +struct usb_tt { + bool multi; /* true means one TT per port */ + unsigned think_time; /* think time in ns */ +}; + +/************************************************************************* + * Hub Stuff + */ +struct usb_hub_device { + struct usb_device *pusb_dev; + struct usb_hub_descriptor desc; + uint64_t connect_timeout; /* Device connection timeout in ns */ + uint64_t query_delay; /* Device query delay in ns */ + int overcurrent_count[USB_MAXCHILDREN]; /* Over-current counter */ + struct usb_tt tt; /* Transaction Translator */ +}; + +/** + * struct usb_device_id - identifies USB devices for probing and hotplugging + * @match_flags: Bit mask controlling of the other fields are used to match + * against new devices. Any field except for driver_info may be used, + * although some only make sense in conjunction with other fields. + * This is usually set by a USB_DEVICE_*() macro, which sets all + * other fields in this structure except for driver_info. + * @idVendor: USB vendor ID for a device; numbers are assigned + * by the USB forum to its members. + * @idProduct: Vendor-assigned product ID. + * @bcdDevice_lo: Low end of range of vendor-assigned product version numbers. + * This is also used to identify individual product versions, for + * a range consisting of a single device. + * @bcdDevice_hi: High end of version number range. The range of product + * versions is inclusive. + * @bDeviceClass: Class of device; numbers are assigned + * by the USB forum. Products may choose to implement classes, + * or be vendor-specific. Device classes specify behavior of all + * the interfaces on a devices. + * @bDeviceSubClass: Subclass of device; associated with bDeviceClass. + * @bDeviceProtocol: Protocol of device; associated with bDeviceClass. + * @bInterfaceClass: Class of interface; numbers are assigned + * by the USB forum. Products may choose to implement classes, + * or be vendor-specific. Interface classes specify behavior only + * of a given interface; other interfaces may support other classes. + * @bInterfaceSubClass: Subclass of interface; associated with bInterfaceClass. + * @bInterfaceProtocol: Protocol of interface; associated with bInterfaceClass. + * @driver_info: Holds information used by the driver. Usually it holds + * a pointer to a descriptor understood by the driver, or perhaps + * device flags. + * + * In most cases, drivers will create a table of device IDs by using + * USB_DEVICE(), or similar macros designed for that purpose. + * They will then export it to userspace using MODULE_DEVICE_TABLE(), + * and provide it to the USB core through their usb_driver structure. + * + * See the usb_match_id() function for information about how matches are + * performed. Briefly, you will normally use one of several macros to help + * construct these entries. Each entry you provide will either identify + * one or more specific products, or will identify a class of products + * which have agreed to behave the same. You should put the more specific + * matches towards the beginning of your table, so that driver_info can + * record quirks of specific products. + */ +struct usb_device_id { + /* which fields to match against? */ + __u16 match_flags; + + /* Used for product specific matches; range is inclusive */ + __u16 idVendor; + __u16 idProduct; + __u16 bcdDevice_lo; + __u16 bcdDevice_hi; + + /* Used for device class matches */ + __u8 bDeviceClass; + __u8 bDeviceSubClass; + __u8 bDeviceProtocol; + + /* Used for interface class matches */ + __u8 bInterfaceClass; + __u8 bInterfaceSubClass; + __u8 bInterfaceProtocol; + + const void *driver_info; +}; + +#define USB_DEVICE_ID_MATCH_PRODUCT 0x0002 +#define USB_DEVICE_ID_MATCH_VENDOR 0x0001 +#define USB_DEVICE_ID_MATCH_DEVICE \ + (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 +#define USB_DEVICE_ID_MATCH_INT_INFO \ + (USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_SUBCLASS | \ + USB_DEVICE_ID_MATCH_INT_PROTOCOL) + +/** + * USB_DEVICE - macro used to describe a specific usb device + * @vend: the 16 bit USB Vendor ID + * @prod: the 16 bit USB Product ID + * + * This macro is used to create a struct usb_device_id that matches a + * specific device. + */ +#define USB_DEVICE(vend,prod) \ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \ + .idVendor = (vend), \ + .idProduct = (prod) + +/** + * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces + * @cl: bInterfaceClass value + * @sc: bInterfaceSubClass value + * @pr: bInterfaceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific class of interfaces. + */ +#define USB_INTERFACE_INFO(cl, sc, pr) \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \ + .bInterfaceClass = (cl), \ + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + +#define USB_CTRL_SET_TIMEOUT 5000 +#define USB_CTRL_GET_TIMEOUT 5000 + +enum usb_dr_mode of_usb_get_dr_mode(struct device_node *np, + const char *propname); + +enum usb_dr_mode { + USB_DR_MODE_UNKNOWN, + USB_DR_MODE_HOST, + USB_DR_MODE_PERIPHERAL, + USB_DR_MODE_OTG, +}; + +enum usb_phy_interface of_usb_get_phy_mode(struct device_node *np, + const char *propname); + +enum usb_device_speed of_usb_get_maximum_speed(struct device_node *np, + const char *propname); + +int usb_register_otg_device(struct device *parent, + int (*set_mode)(void *ctx, enum usb_dr_mode mode), void *ctx); + +int otg_device_get_mode(struct device *dev); + +extern struct bus_type otg_bus_type; + +extern struct list_head usb_device_list; + +bool usb_hub_is_root_hub(struct usb_device *hdev); + +#ifdef CONFIG_USB_ONBOARD_HUB +void of_usb_host_probe_hubs(struct usb_host *host); +#else +static inline void of_usb_host_probe_hubs(struct usb_host *host) +{ +} +#endif + +#endif /*_USB_H_ */ diff --git a/include/linux/usb/usb_defs.h b/include/linux/usb/usb_defs.h new file mode 100644 index 0000000000..731bc51c76 --- /dev/null +++ b/include/linux/usb/usb_defs.h @@ -0,0 +1,150 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * + * Note: Part of this code has been derived from linux + * + */ +#ifndef _USB_DEFS_H_ +#define _USB_DEFS_H_ + +/* USB constants */ + +/* some HID sub classes */ +#define USB_SUB_HID_NONE 0 +#define USB_SUB_HID_BOOT 1 + +/* some UID Protocols */ +#define USB_PROT_HID_NONE 0 +#define USB_PROT_HID_KEYBOARD 1 +#define USB_PROT_HID_MOUSE 2 + + +/* Sub STORAGE Classes */ +#define US_SC_RBC 1 /* Typically, flash devices */ +#define US_SC_8020 2 /* CD-ROM */ +#define US_SC_QIC 3 /* QIC-157 Tapes */ +#define US_SC_UFI 4 /* Floppy */ +#define US_SC_8070 5 /* Removable media */ +#define US_SC_SCSI 6 /* Transparent */ +#define US_SC_MIN US_SC_RBC +#define US_SC_MAX US_SC_SCSI + +/* STORAGE Protocols */ +#define US_PR_CB 1 /* Control/Bulk w/o interrupt */ +#define US_PR_CBI 0 /* Control/Bulk/Interrupt */ +#define US_PR_BULK 0x50 /* bulk only */ + +/* Descriptor types */ +#define USB_DT_HID (USB_TYPE_CLASS | 0x01) +#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02) +#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) + +/* Descriptor sizes per descriptor type */ +#define USB_DT_HID_SIZE 9 + +/* USB Packet IDs (PIDs) */ +#define USB_PID_UNDEF_0 0xf0 +#define USB_PID_OUT 0xe1 +#define USB_PID_ACK 0xd2 +#define USB_PID_DATA0 0xc3 +#define USB_PID_UNDEF_4 0xb4 +#define USB_PID_SOF 0xa5 +#define USB_PID_UNDEF_6 0x96 +#define USB_PID_UNDEF_7 0x87 +#define USB_PID_UNDEF_8 0x78 +#define USB_PID_IN 0x69 +#define USB_PID_NAK 0x5a +#define USB_PID_DATA1 0x4b +#define USB_PID_PREAMBLE 0x3c +#define USB_PID_SETUP 0x2d +#define USB_PID_STALL 0x1e +#define USB_PID_UNDEF_F 0x0f + +/* HID requests */ +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_GET_IDLE 0x02 +#define USB_REQ_GET_PROTOCOL 0x03 +#define USB_REQ_SET_REPORT 0x09 +#define USB_REQ_SET_IDLE 0x0A +#define USB_REQ_SET_PROTOCOL 0x0B + + +/* "pipe" definitions */ + +#define PIPE_ISOCHRONOUS 0 +#define PIPE_INTERRUPT 1 +#define PIPE_CONTROL 2 +#define PIPE_BULK 3 +#define PIPE_DEVEP_MASK 0x0007ff00 + +#define USB_ISOCHRONOUS 0 +#define USB_INTERRUPT 1 +#define USB_CONTROL 2 +#define USB_BULK 3 + +/* USB-status codes: */ +#define USB_ST_ACTIVE 0x1 /* TD is active */ +#define USB_ST_STALLED 0x2 /* TD is stalled */ +#define USB_ST_BUF_ERR 0x4 /* buffer error */ +#define USB_ST_BABBLE_DET 0x8 /* Babble detected */ +#define USB_ST_NAK_REC 0x10 /* NAK Received*/ +#define USB_ST_CRC_ERR 0x20 /* CRC/timeout Error */ +#define USB_ST_BIT_ERR 0x40 /* Bitstuff error */ +#define USB_ST_NOT_PROC 0x80000000L /* Not yet processed */ + + +/************************************************************************* + * Hub defines + */ + +/* + * Port feature numbers + */ +#define USB_PORT_FEAT_HIGHSPEED 10 + +/* wPortStatus bits */ +#define USB_PORT_STAT_SPEED \ + (USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED) + +/* (shifted) direction/type/recipient from the USB 2.0 spec, table 9.2 */ +#define DeviceRequest \ + ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8) + +#define DeviceOutRequest \ + ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE) << 8) + +#define InterfaceRequest \ + ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) + +#define EndpointRequest \ + ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) + +#define EndpointOutRequest \ + ((USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8) + +/* class requests from the USB 2.0 hub spec, table 11-15 */ +/* GetBusState and SetHubDescriptor are optional, omitted */ +#define ClearHubFeature (0x2000 | USB_REQ_CLEAR_FEATURE) +#define ClearPortFeature (0x2300 | USB_REQ_CLEAR_FEATURE) +#define GetHubDescriptor (0xa000 | USB_REQ_GET_DESCRIPTOR) +#define GetHubStatus (0xa000 | USB_REQ_GET_STATUS) +#define GetPortStatus (0xa300 | USB_REQ_GET_STATUS) +#define SetHubFeature (0x2000 | USB_REQ_SET_FEATURE) +#define SetPortFeature (0x2300 | USB_REQ_SET_FEATURE) + +#define USB_PORT_STAT_SUPER_SPEED 0x0600 /* faking support to XHCI */ +#define USB_PORT_STAT_SPEED_MASK (USB_PORT_STAT_LOW_SPEED | USB_PORT_STAT_HIGH_SPEED) + +#endif /*_USB_DEFS_H_ */ diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h new file mode 100644 index 0000000000..450db47b40 --- /dev/null +++ b/include/linux/usb/usbnet.h @@ -0,0 +1,183 @@ +/* + * USB Networking Link Interface + * + * Copyright (C) 2000-2005 by David Brownell <dbrownell@users.sourceforge.net> + * Copyright (C) 2003-2005 David Hollis <dhollis@davehollis.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __LINUX_USB_USBNET_H +#define __LINUX_USB_USBNET_H + +#include <net.h> +#include <linux/phy.h> + +/* interface from usbnet core to each USB networking link we handle */ +struct usbnet { + /* housekeeping */ + struct usb_device *udev; + struct usb_interface *intf; + struct driver_info *driver_info; + const char *driver_name; + void *driver_priv; + + /* i/o info: pipes etc */ + unsigned in, out, status; + unsigned maxpacket; + + /* protocol/interface state */ + struct eth_device edev; + struct mii_bus miibus; + int phy_addr; + + int msg_enable; + unsigned long data [5]; + u32 xid; + u32 hard_mtu; /* count any extra framing */ + size_t rx_urb_size; /* size for rx urbs */ + void *rx_buf; + void *tx_buf; + + unsigned long flags; +# define EVENT_TX_HALT 0 +# define EVENT_RX_HALT 1 +# define EVENT_RX_MEMORY 2 +# define EVENT_STS_SPLIT 3 +# define EVENT_LINK_RESET 4 +}; + +#if 0 +static inline struct usb_driver *driver_of(struct usb_interface *intf) +{ + return to_usb_driver(intf->dev.driver); +} +#endif + +/* interface from the device/framing level "minidriver" to core */ +struct driver_info { + char *description; + + int flags; +/* framing is CDC Ethernet, not writing ZLPs (hw issues), or optionally: */ +#define FLAG_FRAMING_NC 0x0001 /* guard against device dropouts */ +#define FLAG_FRAMING_GL 0x0002 /* genelink batches packets */ +#define FLAG_FRAMING_Z 0x0004 /* zaurus adds a trailer */ +#define FLAG_FRAMING_RN 0x0008 /* RNDIS batches, plus huge header */ + +#define FLAG_NO_SETINT 0x0010 /* device can't set_interface() */ +#define FLAG_ETHER 0x0020 /* maybe use "eth%d" names */ + +#define FLAG_FRAMING_AX 0x0040 /* AX88772/178 packets */ +#define FLAG_WLAN 0x0080 /* use "wlan%d" names */ + + + /* init device ... can sleep, or cause probe() failure */ + int (*bind)(struct usbnet *); + + /* cleanup device ... can sleep, but can't fail */ + void (*unbind)(struct usbnet *); + + /* reset device ... can sleep */ + int (*reset)(struct usbnet *); + + /* see if peer is connected ... can sleep */ + int (*check_connect)(struct usbnet *); + + /* for status polling */ +// void (*status)(struct usbnet *, struct urb *); + + /* link reset handling, called from defer_kevent */ + int (*link_reset)(struct usbnet *); + + /* fixup rx packet (strip framing) */ + int (*rx_fixup)(struct usbnet *dev, void *buf, int len); + + int (*tx_fixup)(struct usbnet *dev, void *buf, int len, void *nbuf, int *nlen); + + /* early initialization code, can sleep. This is for minidrivers + * having 'subminidrivers' that need to do extra initialization + * right after minidriver have initialized hardware. */ + int (*early_init)(struct usbnet *dev); + + /* called by minidriver when link state changes, state: 0=disconnect, + * 1=connect */ + void (*link_change)(struct usbnet *dev, int state); + + /* for new devices, use the descriptor-reading code instead */ + int in; /* rx endpoint */ + int out; /* tx endpoint */ + + unsigned long data; /* Misc driver specific data */ +}; + +/* Minidrivers are just drivers using the "usbnet" core as a powerful + * network-specific subroutine library ... that happens to do pretty + * much everything except custom framing and chip-specific stuff. + */ +extern int usbnet_probe(struct usb_device *, const struct usb_device_id *); +extern void usbnet_disconnect(struct usb_device *); + + +/* Drivers that reuse some of the standard USB CDC infrastructure + * (notably, using multiple interfaces according to the CDC + * union descriptor) get some helper code. + */ +struct cdc_state { + struct usb_cdc_header_desc *header; + struct usb_cdc_union_desc *u; + struct usb_cdc_ether_desc *ether; + struct usb_interface *control; + struct usb_interface *data; +}; + +extern int usbnet_generic_cdc_bind (struct usbnet *, struct usb_device *); +extern void usbnet_cdc_unbind (struct usbnet *, struct usb_device *); + +/* CDC and RNDIS support the same host-chosen packet filters for IN transfers */ +#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) + + +/* we record the state for each of our queued skbs */ +enum skb_state { + illegal = 0, + tx_start, tx_done, + rx_start, rx_done, rx_cleanup +}; + +struct skb_data { /* skb->cb is one of these */ + struct urb *urb; + struct usbnet *dev; + enum skb_state state; + size_t length; +}; + + +extern int usbnet_get_endpoints(struct usbnet *dev); +#if 0 +extern void usbnet_defer_kevent (struct usbnet *, int); +extern void usbnet_skb_return (struct usbnet *, struct sk_buff *); +extern void usbnet_unlink_rx_urbs(struct usbnet *); + +extern int usbnet_get_settings (struct net_device *net, struct ethtool_cmd *cmd); +extern int usbnet_set_settings (struct net_device *net, struct ethtool_cmd *cmd); +extern u32 usbnet_get_link (struct net_device *net); +extern u32 usbnet_get_msglevel (struct net_device *); +extern void usbnet_set_msglevel (struct net_device *, u32); +extern void usbnet_get_drvinfo (struct net_device *, struct ethtool_drvinfo *); +extern int usbnet_nway_reset(struct net_device *net); +#endif + +#endif /* __LINUX_USB_USBNET_H */ diff --git a/include/linux/usb/usbroothubdes.h b/include/linux/usb/usbroothubdes.h new file mode 100644 index 0000000000..e743555d8e --- /dev/null +++ b/include/linux/usb/usbroothubdes.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * USB virtual root hub descriptors + * + * (C) Copyright 2014 + * Stephen Warren swarren@wwwdotorg.org + * + * Based on ohci-hcd.c + */ + +#ifndef __USBROOTHUBDES_H__ +#define __USBROOTHUBDES_H__ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = { + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x01, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01, /* __u8 bNumConfigurations; */ +}; + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = { + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + * Bit 7: Bus-powered + * 6: Self-powered, + * 5 Remote-wakwup, + * 4..0: resvd + */ + 0x00, /* __u8 MaxPower; */ + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x00, + 0xff, /* __u8 ep_bInterval; 255 ms */ +}; + +#ifdef WANT_USB_ROOT_HUB_HUB_DES +static unsigned char root_hub_hub_des[] = { + 0x09, /* __u8 bLength; */ + 0x29, /* __u8 bDescriptorType; Hub-descriptor */ + 0x02, /* __u8 bNbrPorts; */ + 0x00, /* __u16 wHubCharacteristics; */ + 0x00, + 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ + 0x00, /* __u8 bHubContrCurrent; 0 mA */ + 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ + 0xff, /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ +}; +#endif + +static unsigned char root_hub_str_index0[] = { + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = { + 32, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'U', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + '-', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'B', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + +#endif diff --git a/include/linux/usb/usbserial.h b/include/linux/usb/usbserial.h new file mode 100644 index 0000000000..e1375c489a --- /dev/null +++ b/include/linux/usb/usbserial.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _USB_SERIAL_H +#define _USB_SERIAL_H + +struct usb_serial_pdata { + bool acm; +}; + +int usb_serial_register(struct usb_serial_pdata *pdata); +void usb_serial_unregister(void); + +#endif /* _USB_SERIAL_H */ diff --git a/include/linux/usb/webusb.h b/include/linux/usb/webusb.h new file mode 100644 index 0000000000..f10debc924 --- /dev/null +++ b/include/linux/usb/webusb.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * WebUSB descriptors and constants + * + * Copyright (C) 2023 Jó Ágila Bitsch <jgilab@gmail.com> + */ + +#ifndef __LINUX_USB_WEBUSB_H +#define __LINUX_USB_WEBUSB_H + +#include "linux/usb/ch9.h" + +/* + * Little Endian PlatformCapablityUUID for WebUSB + * 3408b638-09a9-47a0-8bfd-a0768815b665 + * to identify Platform Device Capability descriptors as referring to WebUSB. + */ +#define WEBUSB_UUID \ + GUID_INIT(0x3408b638, 0x09a9, 0x47a0, 0x8b, 0xfd, 0xa0, 0x76, 0x88, 0x15, 0xb6, 0x65) + +/* + * WebUSB Platform Capability data + * + * A device announces support for the + * WebUSB command set by including the following Platform Descriptor Data in its + * Binary Object Store associated with the WebUSB_UUID above. + * See: https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + */ +struct usb_webusb_cap_data { + __le16 bcdVersion; +#define WEBUSB_VERSION_1_00 cpu_to_le16(0x0100) /* currently only version 1.00 is defined */ + u8 bVendorCode; + u8 iLandingPage; +#define WEBUSB_LANDING_PAGE_NOT_PRESENT 0 +#define WEBUSB_LANDING_PAGE_PRESENT 1 /* we chose the fixed index 1 for the URL descriptor */ +} __packed; + +#define USB_WEBUSB_CAP_DATA_SIZE 4 + +/* + * Get URL Request + * + * The request to fetch an URL is defined in https://wicg.github.io/webusb/#get-url as: + * bmRequestType: (USB_DIR_IN | USB_TYPE_VENDOR) = 11000000B + * bRequest: bVendorCode + * wValue: iLandingPage + * wIndex: GET_URL = 2 + * wLength: Descriptor Length (typically U8_MAX = 255) + * Data: URL Descriptor + */ +#define WEBUSB_GET_URL 2 + +/* + * This descriptor contains a single URL and is returned by the Get URL request. + * + * See: https://wicg.github.io/webusb/#url-descriptor + */ +struct webusb_url_descriptor { + u8 bLength; +#define WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH 3 + u8 bDescriptorType; +#define WEBUSB_URL_DESCRIPTOR_TYPE 3 + u8 bScheme; +#define WEBUSB_URL_SCHEME_HTTP 0 +#define WEBUSB_URL_SCHEME_HTTPS 1 +#define WEBUSB_URL_SCHEME_NONE 255 + u8 URL[U8_MAX - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH]; +} __packed; + +/* + * Buffer size to hold the longest URL that can be in an URL descriptor + * + * The descriptor can be U8_MAX bytes long. + * WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH bytes are used for a header. + * Since the longest prefix that might be stripped is "https://", we may accommodate an additional + * 8 bytes. + */ +#define WEBUSB_URL_RAW_MAX_LENGTH (U8_MAX - WEBUSB_URL_DESCRIPTOR_HEADER_LENGTH + 8) + +#endif /* __LINUX_USB_USBNET_H */ diff --git a/include/linux/usb/xhci.h b/include/linux/usb/xhci.h new file mode 100644 index 0000000000..b1ad0185b9 --- /dev/null +++ b/include/linux/usb/xhci.h @@ -0,0 +1,27 @@ +/* + * xHCI host controller driver + * + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> + * + * Some code borrowed from the Linux xHCI driver + * Author: Sarah Sharp + * Copyright (C) 2008 Intel Corp. + * + * 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. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __XHCI_HCD_H +#define __XHCI_HCD_H + +#endif diff --git a/include/linux/uuid.h b/include/linux/uuid.h index d9c4a6cce3..1e4ffb3434 100644 --- a/include/linux/uuid.h +++ b/include/linux/uuid.h @@ -1,30 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ /* * UUID/GUID definition * * Copyright (C) 2010, 2016 Intel Corp. * Huang Ying <ying.huang@intel.com> - * - * 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; - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. */ #ifndef _LINUX_UUID_H_ #define _LINUX_UUID_H_ -#include <uapi/linux/uuid.h> #include <linux/string.h> #define UUID_SIZE 16 typedef struct { __u8 b[UUID_SIZE]; +} guid_t; + +typedef struct { + __u8 b[UUID_SIZE]; } uuid_t; +#define GUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ +((guid_t) \ +{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + #define UUID_INIT(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ ((uuid_t) \ {{ ((a) >> 24) & 0xff, ((a) >> 16) & 0xff, ((a) >> 8) & 0xff, (a) & 0xff, \ @@ -51,6 +53,16 @@ static inline void guid_copy(guid_t *dst, const guid_t *src) memcpy(dst, src, sizeof(guid_t)); } +static inline void import_guid(guid_t *dst, const __u8 *src) +{ + memcpy(dst, src, sizeof(guid_t)); +} + +static inline void export_guid(__u8 *dst, const guid_t *src) +{ + memcpy(dst, src, sizeof(guid_t)); +} + static inline bool guid_is_null(const guid_t *guid) { return guid_equal(guid, &guid_null); @@ -66,12 +78,23 @@ static inline void uuid_copy(uuid_t *dst, const uuid_t *src) memcpy(dst, src, sizeof(uuid_t)); } +static inline void import_uuid(uuid_t *dst, const __u8 *src) +{ + memcpy(dst, src, sizeof(uuid_t)); +} + +static inline void export_uuid(__u8 *dst, const uuid_t *src) +{ + memcpy(dst, src, sizeof(uuid_t)); +} + static inline bool uuid_is_null(const uuid_t *uuid) { return uuid_equal(uuid, &uuid_null); } void generate_random_uuid(unsigned char uuid[16]); +void generate_random_guid(unsigned char guid[16]); extern void guid_gen(guid_t *u); extern void uuid_gen(uuid_t *u); @@ -84,13 +107,15 @@ extern const u8 uuid_index[16]; int guid_parse(const char *uuid, guid_t *u); int uuid_parse(const char *uuid, uuid_t *u); -/* backwards compatibility, don't use in new code */ -#define uuid_le_gen(u) guid_gen(u) -#define uuid_le_to_bin(guid, u) guid_parse(guid, u) +static inline void uuid_make_v4(uuid_t *u) { + /* Set UUID version to 4 --- truly random generation */ + u->b[6] = (u->b[6] & 0x0F) | 0x40; -static inline int uuid_le_cmp(const guid_t u1, const guid_t u2) -{ - return memcmp(&u1, &u2, sizeof(guid_t)); + /* Set the UUID variant to DCE */ + u->b[8] = (u->b[8] & 0x3F) | 0x80; } +/* MEI UUID type, don't use anywhere else */ +#include <uapi/linux/uuid.h> + #endif diff --git a/include/linux/virtio.h b/include/linux/virtio.h index 719f45c975..a4a54531ca 100644 --- a/include/linux/virtio.h +++ b/include/linux/virtio.h @@ -52,7 +52,7 @@ struct virtio_device { bool failed; bool config_enabled; bool config_change_pending; - struct device_d dev; + struct device dev; struct virtio_device_id id; const struct virtio_config_ops *config; struct list_head vqs; @@ -61,7 +61,7 @@ struct virtio_device { u32 status_param; }; -static inline struct virtio_device *dev_to_virtio(struct device_d *_dev) +static inline struct virtio_device *dev_to_virtio(struct device *_dev) { return container_of(_dev, struct virtio_device, dev); } @@ -69,7 +69,7 @@ static inline struct virtio_device *dev_to_virtio(struct device_d *_dev) void virtio_add_status(struct virtio_device *dev, unsigned int status); int register_virtio_device(struct virtio_device *dev); void unregister_virtio_device(struct virtio_device *dev); -bool is_virtio_device(struct device_d *dev); +bool is_virtio_device(struct device *dev); void virtio_break_device(struct virtio_device *dev); @@ -101,7 +101,7 @@ size_t virtio_max_dma_size(struct virtio_device *vdev); * @restore: optional function to call on resume. */ struct virtio_driver { - struct driver_d driver; + struct driver driver; const struct virtio_device_id *id_table; const unsigned int *feature_table; unsigned int feature_table_size; @@ -114,7 +114,7 @@ struct virtio_driver { void (*config_changed)(struct virtio_device *dev); }; -static inline struct virtio_driver *drv_to_virtio(struct driver_d *drv) +static inline struct virtio_driver *drv_to_virtio(struct driver *drv) { return container_of(drv, struct virtio_driver, driver); } diff --git a/include/linux/wait.h b/include/linux/wait.h index e2df8878ed..e4b0e2a492 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + #ifndef _LINUX_WAIT_H #define _LINUX_WAIT_H /* diff --git a/include/linux/xz.h b/include/linux/xz.h index d1afab0562..6480877f86 100644 --- a/include/linux/xz.h +++ b/include/linux/xz.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* * XZ decompressor * @@ -262,10 +264,10 @@ XZ_EXTERN void xz_crc32_init(void); XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc); #endif -STATIC int decompress_unxz(unsigned char *in, int in_size, - int (*fill)(void *dest, unsigned int size), - int (*flush)(void *src, unsigned int size), - unsigned char *out, int *in_used, +STATIC int decompress_unxz(unsigned char *in, long in_size, + long (*fill)(void *dest, unsigned long size), + long (*flush)(void *src, unsigned long size), + unsigned char *out, long *in_used, void (*error)(char *x)); #endif diff --git a/include/linux/zutil.h b/include/linux/zutil.h index 6adfa9a6ff..b10b50d097 100644 --- a/include/linux/zutil.h +++ b/include/linux/zutil.h @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + /* zutil.h -- internal interface and configuration of the compression library * Copyright (C) 1995-1998 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h |