summaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/amba/bus.h17
-rw-r--r--include/linux/amba/mmci.h2
-rw-r--r--include/linux/amba/pl061.h2
-rw-r--r--include/linux/amba/serial.h19
-rw-r--r--include/linux/arm-smccc.h363
-rw-r--r--include/linux/atomic.h70
-rw-r--r--include/linux/barebox-wrapper.h21
-rw-r--r--include/linux/basic_mmio_gpio.h16
-rw-r--r--include/linux/bcd.h2
-rw-r--r--include/linux/bitfield.h2
-rw-r--r--include/linux/bitmap.h110
-rw-r--r--include/linux/bitops.h53
-rw-r--r--include/linux/bitrev.h2
-rw-r--r--include/linux/bits.h30
-rw-r--r--include/linux/bsearch.h33
-rw-r--r--include/linux/bug.h19
-rw-r--r--include/linux/build_bug.h19
-rw-r--r--include/linux/byteorder/big_endian.h2
-rw-r--r--include/linux/byteorder/generic.h2
-rw-r--r--include/linux/byteorder/little_endian.h2
-rw-r--r--include/linux/circ_buf.h2
-rw-r--r--include/linux/clk-provider.h185
-rw-r--r--include/linux/clk.h835
-rw-r--r--include/linux/clk/analogbits-wrpll-cln28hpc.h79
-rw-r--r--include/linux/clk/at91_pmc.h118
-rw-r--r--include/linux/clkdev.h4
-rw-r--r--include/linux/compiler-gcc.h8
-rw-r--r--include/linux/compiler.h11
-rw-r--r--include/linux/compiler_types.h78
-rw-r--r--include/linux/completion.h55
-rw-r--r--include/linux/const.h21
-rw-r--r--include/linux/container_of.h40
-rw-r--r--include/linux/crc8.h2
-rw-r--r--include/linux/ctype.h2
-rw-r--r--include/linux/dcache.h2
-rw-r--r--include/linux/decompress/mm.h13
-rw-r--r--include/linux/decompress/unlz4.h10
-rw-r--r--include/linux/decompress/unzstd.h11
-rw-r--r--include/linux/device.h78
-rw-r--r--include/linux/err.h6
-rw-r--r--include/linux/errno.h36
-rw-r--r--include/linux/ethtool.h2
-rw-r--r--include/linux/export.h42
-rw-r--r--include/linux/fixp-arith.h144
-rw-r--r--include/linux/font.h8
-rw-r--r--include/linux/fs.h2
-rw-r--r--include/linux/fsl_ifc.h305
-rw-r--r--include/linux/gcd.h2
-rw-r--r--include/linux/genalloc.h36
-rw-r--r--include/linux/gpio/consumer.h224
-rw-r--r--include/linux/hash.h2
-rw-r--r--include/linux/hidden.h19
-rw-r--r--include/linux/hw_random.h19
-rw-r--r--include/linux/idr.h72
-rw-r--r--include/linux/if_bridge.h9
-rw-r--r--include/linux/if_vlan.h56
-rw-r--r--include/linux/instruction_pointer.h11
-rw-r--r--include/linux/io.h9
-rw-r--r--include/linux/iopoll.h33
-rw-r--r--include/linux/ioport.h26
-rw-r--r--include/linux/jffs2.h2
-rw-r--r--include/linux/kasan.h89
-rw-r--r--include/linux/kbuild.h2
-rw-r--r--include/linux/kernel.h162
-rw-r--r--include/linux/kref.h90
-rw-r--r--include/linux/ktime.h212
-rw-r--r--include/linux/libfdt.h2
-rw-r--r--include/linux/libfdt_env.h7
-rw-r--r--include/linux/limits.h5
-rw-r--r--include/linux/linkage.h317
-rw-r--r--include/linux/list.h700
-rw-r--r--include/linux/list_sort.h2
-rw-r--r--include/linux/magic.h2
-rw-r--r--include/linux/math64.h212
-rw-r--r--include/linux/mdio-bitbang.h5
-rw-r--r--include/linux/mdio-mux.h2
-rw-r--r--include/linux/mdio.h344
-rw-r--r--include/linux/mfd/axp20x.h485
-rw-r--r--include/linux/mfd/core.h24
-rw-r--r--include/linux/mfd/rk808.h721
-rw-r--r--include/linux/mfd/stm32-timers.h98
-rw-r--r--include/linux/mfd/syscon/atmel-matrix.h112
-rw-r--r--include/linux/mfd/syscon/atmel-smc.h120
-rw-r--r--include/linux/micrel_phy.h49
-rw-r--r--include/linux/mii.h2
-rw-r--r--include/linux/minmax.h189
-rw-r--r--include/linux/mod_devicetable.h14
-rw-r--r--include/linux/mount.h2
-rw-r--r--include/linux/mtd/bbm.h2
-rw-r--r--include/linux/mtd/jedec.h91
-rw-r--r--include/linux/mtd/mtd-abi.h5
-rw-r--r--include/linux/mtd/mtd.h186
-rw-r--r--include/linux/mtd/nand.h1376
-rw-r--r--include/linux/mtd/nand_bch.h24
-rw-r--r--include/linux/mtd/nand_ecc.h37
-rw-r--r--include/linux/mtd/nand_mxs.h4
-rw-r--r--include/linux/mtd/nftl.h2
-rw-r--r--include/linux/mtd/onfi.h178
-rw-r--r--include/linux/mtd/partitions.h115
-rw-r--r--include/linux/mtd/rawnand.h1495
-rw-r--r--include/linux/mtd/spi-nor.h4
-rw-r--r--include/linux/mutex.h4
-rw-r--r--include/linux/namei.h17
-rw-r--r--include/linux/nls.h3
-rw-r--r--include/linux/notifier.h16
-rw-r--r--include/linux/nvmem-consumer.h66
-rw-r--r--include/linux/nvmem-provider.h49
-rw-r--r--include/linux/overflow.h312
-rw-r--r--include/linux/pagemap.h11
-rw-r--r--include/linux/path.h2
-rw-r--r--include/linux/pci.h29
-rw-r--r--include/linux/pci_regs.h52
-rw-r--r--include/linux/pe.h482
-rw-r--r--include/linux/phy.h230
-rw-r--r--include/linux/phy/phy.h90
-rw-r--r--include/linux/platform_data/simplefb.h46
-rw-r--r--include/linux/poison.h26
-rw-r--r--include/linux/posix_types.h2
-rw-r--r--include/linux/printk.h240
-rw-r--r--include/linux/processor.h29
-rw-r--r--include/linux/pstore.h2
-rw-r--r--include/linux/rational.h20
-rw-r--r--include/linux/reboot-mode.h38
-rw-r--r--include/linux/refcount.h271
-rw-r--r--include/linux/regmap.h264
-rw-r--r--include/linux/regulator/machine.h207
-rw-r--r--include/linux/regulator/of_regulator.h19
-rw-r--r--include/linux/remoteproc.h9
-rw-r--r--include/linux/reset-controller.h4
-rw-r--r--include/linux/reset.h65
-rw-r--r--include/linux/reset/reset-simple.h45
-rw-r--r--include/linux/rtc.h6
-rw-r--r--include/linux/rwsem.h2
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/scmi_protocol.h688
-rw-r--r--include/linux/sizes.h15
-rw-r--r--include/linux/slab.h18
-rw-r--r--include/linux/smscphy.h2
-rw-r--r--include/linux/spi/spi-mem.h2
-rw-r--r--include/linux/spinlock.h6
-rw-r--r--include/linux/stat.h17
-rw-r--r--include/linux/stddef.h119
-rw-r--r--include/linux/string.h71
-rw-r--r--include/linux/string_helpers.h13
-rw-r--r--include/linux/stringify.h2
-rw-r--r--include/linux/swab.h2
-rw-r--r--include/linux/sys_soc.h39
-rw-r--r--include/linux/tee_drv.h418
-rw-r--r--include/linux/time.h2
-rw-r--r--include/linux/typecheck.h25
-rw-r--r--include/linux/types.h23
-rw-r--r--include/linux/uaccess.h38
-rw-r--r--include/linux/unaligned/access_ok.h2
-rw-r--r--include/linux/unaligned/be_byteshift.h2
-rw-r--r--include/linux/unaligned/be_memmove.h2
-rw-r--r--include/linux/unaligned/be_struct.h2
-rw-r--r--include/linux/unaligned/generic.h2
-rw-r--r--include/linux/unaligned/le_byteshift.h2
-rw-r--r--include/linux/unaligned/le_memmove.h2
-rw-r--r--include/linux/unaligned/le_struct.h2
-rw-r--r--include/linux/unaligned/memmove.h2
-rw-r--r--include/linux/unaligned/packed_struct.h2
-rw-r--r--include/linux/units.h111
-rw-r--r--include/linux/usb/cdc.h252
-rw-r--r--include/linux/usb/ch9.h56
-rw-r--r--include/linux/usb/chipidea-imx.h64
-rw-r--r--include/linux/usb/composite.h644
-rw-r--r--include/linux/usb/dfu.h34
-rw-r--r--include/linux/usb/ehci.h41
-rw-r--r--include/linux/usb/fastboot.h19
-rw-r--r--include/linux/usb/fsl_usb2.h33
-rw-r--r--include/linux/usb/gadget-multi.h42
-rw-r--r--include/linux/usb/gadget.h950
-rw-r--r--include/linux/usb/mass_storage.h29
-rw-r--r--include/linux/usb/musb.h146
-rw-r--r--include/linux/usb/phy.h222
-rw-r--r--include/linux/usb/role.h12
-rw-r--r--include/linux/usb/storage.h87
-rw-r--r--include/linux/usb/twl4030.h28
-rw-r--r--include/linux/usb/typec.h54
-rw-r--r--include/linux/usb/typec_altmode.h44
-rw-r--r--include/linux/usb/ulpi.h61
-rw-r--r--include/linux/usb/usb.h499
-rw-r--r--include/linux/usb/usb_defs.h150
-rw-r--r--include/linux/usb/usbnet.h183
-rw-r--r--include/linux/usb/usbroothubdes.h128
-rw-r--r--include/linux/usb/usbserial.h13
-rw-r--r--include/linux/usb/webusb.h80
-rw-r--r--include/linux/usb/xhci.h27
-rw-r--r--include/linux/uuid.h57
-rw-r--r--include/linux/virtio.h135
-rw-r--r--include/linux/virtio_byteorder.h64
-rw-r--r--include/linux/virtio_config.h538
-rw-r--r--include/linux/virtio_ring.h366
-rw-r--r--include/linux/wait.h2
-rw-r--r--include/linux/xz.h10
-rw-r--r--include/linux/zutil.h2
197 files changed, 18431 insertions, 1825 deletions
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index 7b3e603322..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;
@@ -60,6 +60,13 @@ extern struct bus_type amba_bustype;
#define to_amba_device(d) container_of(d, struct amba_device, dev)
+#define device_amba_driver(drv) \
+ register_driver_macro(device,amba,drv)
+#define coredevice_amba_driver(drv) \
+ register_driver_macro(coredevice,amba,drv)
+#define console_amba_driver(drv) \
+ register_driver_macro(console,amba,drv)
+
int amba_driver_register(struct amba_driver *);
void amba_driver_unregister(struct amba_driver *);
struct amba_device *amba_device_alloc(const char *, int id, resource_size_t, size_t);
@@ -68,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)
{
@@ -82,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/amba/serial.h b/include/linux/amba/serial.h
index 8ff22d5c8c..88ca17c2c3 100644
--- a/include/linux/amba/serial.h
+++ b/include/linux/amba/serial.h
@@ -1,22 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/* SPDX-FileCopyrightText: ARM Limited */
+/* SPDX-FileCopyrightText: 2000 Deep Blue Solutions Ltd. */
+
/*
* linux/include/linux/amba/serial.h
*
* Internal header file for AMBA serial ports
- *
- * Copyright (C) ARM Limited
- * Copyright (C) 2000 Deep Blue Solutions Ltd.
- *
- * 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 ASM_ARM_HARDWARE_SERIAL_AMBA_H
#define ASM_ARM_HARDWARE_SERIAL_AMBA_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 e998932d12..5d311e1d70 100644
--- a/include/linux/barebox-wrapper.h
+++ b/include/linux/barebox-wrapper.h
@@ -4,6 +4,7 @@
#include <malloc.h>
#include <xfuncs.h>
#include <linux/slab.h>
+#include <printk.h>
#define vmalloc(len) malloc(len)
#define __vmalloc(len, mode, pgsz) malloc(len)
@@ -13,26 +14,16 @@ static inline void vfree(const void *addr)
free((void *)addr);
}
-#define KERN_EMERG "" /* system is unusable */
-#define KERN_ALERT "" /* action must be taken immediately */
-#define KERN_CRIT "" /* critical conditions */
-#define KERN_ERR "" /* error conditions */
-#define KERN_WARNING "" /* warning conditions */
-#define KERN_NOTICE "" /* normal but significant condition */
-#define KERN_INFO "" /* informational */
-#define KERN_DEBUG "" /* debug-level messages */
-#define KERN_CONT ""
-
-#define printk printf
-
-#define pr_warn pr_warning
-
#define __init
#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
@@ -52,4 +43,6 @@ typedef int irqreturn_t;
#define __clk_get_rate clk_get_rate
#define __clk_get_parent clk_get_parent
+#define cpu_relax() barrier()
+
#endif /* __INCLUDE_LINUX_BAREBOX_WRAPPER_H */
diff --git a/include/linux/basic_mmio_gpio.h b/include/linux/basic_mmio_gpio.h
index e927194b51..8917f99ccb 100644
--- a/include/linux/basic_mmio_gpio.h
+++ b/include/linux/basic_mmio_gpio.h
@@ -27,13 +27,17 @@ struct bgpio_chip {
struct gpio_chip gc;
struct gpio_ops ops;
- unsigned int (*read_reg)(void __iomem *reg);
- void (*write_reg)(void __iomem *reg, unsigned int data);
+ unsigned long (*read_reg)(void __iomem *reg);
+ void (*write_reg)(void __iomem *reg, unsigned long data);
void __iomem *reg_dat;
void __iomem *reg_set;
void __iomem *reg_clr;
- void __iomem *reg_dir;
+ void __iomem *reg_dir_out;
+ void __iomem *reg_dir_in;
+
+ bool dir_unreadable;
+ bool be_bits;
/* Number of bits (GPIOs): <register width> * 8. */
int bits;
@@ -56,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);
@@ -65,5 +69,9 @@ void bgpio_remove(struct bgpio_chip *bgc);
#define BGPIOF_BIG_ENDIAN BIT(0)
#define BGPIOF_UNREADABLE_REG_SET BIT(1) /* reg_set is unreadable */
#define BGPIOF_UNREADABLE_REG_DIR BIT(2) /* reg_dir is unreadable */
+#define BGPIOF_BIG_ENDIAN_BYTE_ORDER BIT(3)
+#define BGPIOF_READ_OUTPUT_REG_SET BIT(4) /* reg_set stores output value */
+#define BGPIOF_NO_OUTPUT BIT(5) /* only input */
+#define BGPIOF_NO_SET_ON_INPUT BIT(6)
#endif /* __BASIC_MMIO_GPIO_H */
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 31345c219d..7646e15634 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -1,34 +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))))
-
-extern unsigned int __sw_hweight8(unsigned int w);
-extern unsigned int __sw_hweight16(unsigned int w);
-extern unsigned int __sw_hweight32(unsigned int w);
-extern unsigned long __sw_hweight64(__u64 w);
-
+#ifndef __ASSEMBLY__
/*
* Include this here because some architectures need generic_ffs/fls in
* scope
@@ -197,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
@@ -226,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/build_bug.h b/include/linux/build_bug.h
index 43d1fd50d4..40cd504f63 100644
--- a/include/linux/build_bug.h
+++ b/include/linux/build_bug.h
@@ -80,4 +80,23 @@
#endif /* __CHECKER__ */
+/**
+ * static_assert - check integer constant expression at build time
+ *
+ * static_assert() is a wrapper for the C11 _Static_assert, with a
+ * little macro magic to make the message optional (defaulting to the
+ * stringification of the tested expression).
+ *
+ * Contrary to BUILD_BUG_ON(), static_assert() can be used at global
+ * scope, but requires the expression to be an integer constant
+ * expression (i.e., it is not enough that __builtin_constant_p() is
+ * true for expr).
+ *
+ * Also note that BUILD_BUG_ON() fails the build if the condition is
+ * true, while static_assert() fails the build if the expression is
+ * false.
+ */
+#define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr)
+#define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
+
#endif /* _LINUX_BUILD_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 c3aeea80dd..7ba0679d03 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -1,20 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* SPDX-FileCopyrightText: 2004 ARM Limited */
+
/*
* linux/include/linux/clk.h
*
- * Copyright (C) 2004 ARM Limited.
* Written by Deep Blue Solutions Limited.
- *
- * 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.
*/
+
#ifndef __LINUX_CLK_H
#define __LINUX_CLK_H
#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.
@@ -24,6 +27,7 @@ struct device_d;
* struct clk - an machine class defined object / cookie.
*/
struct clk;
+struct clk_hw;
/**
* struct clk_bulk_data - Data used for bulk clk operations.
@@ -58,30 +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);
+struct clk *clk_get(struct device *dev, const char *id);
/**
* clk_enable - inform the system when the clock source should be running.
@@ -94,18 +75,6 @@ int __must_check clk_bulk_get(struct device_d *dev, int num_clks,
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
*
@@ -120,42 +89,12 @@ 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
*/
unsigned long clk_get_rate(struct clk *clk);
-
-/**
- * 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);
+unsigned long clk_hw_get_rate(struct clk_hw *hw);
/*
* The remaining APIs are optional for machine class support.
@@ -170,7 +109,7 @@ void clk_bulk_put(int num_clks, struct clk_bulk_data *clks);
* Returns rounded clock rate in Hz, or negative errno.
*/
long clk_round_rate(struct clk *clk, unsigned long rate);
-
+long clk_hw_round_rate(struct clk_hw *hw, unsigned long rate);
/**
* clk_set_rate - set the clock rate for a clock source
* @clk: clock source
@@ -179,6 +118,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate);
* Returns success (0) or negative errno.
*/
int clk_set_rate(struct clk *clk, unsigned long rate);
+int clk_hw_set_rate(struct clk_hw *hw, unsigned long rate);
/**
* clk_set_parent - set the parent clock source for this clock
@@ -188,6 +128,8 @@ int clk_set_rate(struct clk *clk, unsigned long rate);
* Returns success (0) or negative errno.
*/
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
@@ -197,6 +139,11 @@ int clk_set_parent(struct clk *clk, struct clk *parent);
* valid IS_ERR() condition containing errno.
*/
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);
/**
* clk_get_sys - get a clock based upon the device name
@@ -226,29 +173,26 @@ 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)
+static inline struct clk *clk_get_parent(struct clk *clk)
{
- return 0;
+ return NULL;
}
-static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
-
-static inline int clk_enable(struct clk *clk)
+static inline int clk_hw_get_parent_index(struct clk_hw *hw)
{
- return 0;
+ return -EINVAL;
}
-static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks)
+static inline int clk_enable(struct clk *clk)
{
return 0;
}
@@ -257,9 +201,6 @@ 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;
@@ -276,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)
{
}
@@ -286,26 +230,122 @@ static inline void clk_put(struct clk *clk)
#define CLK_SET_RATE_PARENT (1 << 0) /* propagate rate change up one level */
#define CLK_IGNORE_UNUSED (1 << 3) /* do not gate even if unused */
+#define CLK_GET_RATE_NOCACHE (1 << 6) /* do not use the cached clk rate */
#define CLK_SET_RATE_NO_REPARENT (1 << 7) /* don't re-parent on rate change */
+#define CLK_SET_RATE_UNGATE (1 << 10) /* clock needs to run to set rate */
#define CLK_IS_CRITICAL (1 << 11) /* do not gate, ever */
/* parents need enable during gate/ungate, set rate and re-parent */
#define CLK_OPS_PARENT_ENABLE (1 << 12)
-#define CLK_GATE_INVERTED (1 << 0)
+#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 (*enable)(struct clk *clk);
- void (*disable)(struct clk *clk);
- int (*is_enabled)(struct clk *clk);
- unsigned long (*recalc_rate)(struct clk *clk,
+ int (*init)(struct clk_hw *hw);
+ int (*enable)(struct clk_hw *hw);
+ void (*disable)(struct clk_hw *hw);
+ int (*is_enabled)(struct clk_hw *hw);
+ unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
- long (*round_rate)(struct clk *clk, unsigned long,
+ long (*round_rate)(struct clk_hw *hw, unsigned long,
unsigned long *);
- int (*set_parent)(struct clk *clk, u8 index);
- int (*get_parent)(struct clk *clk);
- int (*set_rate)(struct clk *clk, unsigned long,
+ int (*set_parent)(struct clk_hw *hw, u8 index);
+ int (*get_parent)(struct clk_hw *hw);
+ int (*set_rate)(struct clk_hw *hw, unsigned long,
unsigned long);
+ int (*set_phase)(struct clk_hw *hw, int degrees);
+ int (*get_phase)(struct clk_hw *hw);
+};
+
+/**
+ * struct clk_init_data - holds init data that's common to all clocks and is
+ * shared between the clock provider and the common clock framework.
+ *
+ * @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
+ */
+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;
};
struct clk {
@@ -320,15 +360,56 @@ struct clk {
unsigned long flags;
};
+/**
+ * struct clk_hw - handle for traversing from a struct clk to its corresponding
+ * hardware-specific structure. struct clk_hw should be declared within struct
+ * clk_foo and then referenced by the struct clk instance that uses struct
+ * clk_foo's clk_ops
+ *
+ * @clk: pointer to the per-user struct clk instance that can be used to call
+ * into the clk API
+ *
+ * @init: pointer to struct clk_init_data that contains the init data shared
+ * with the common clock framework.
+ */
+struct clk_hw {
+ struct clk clk;
+ const struct clk_init_data *init;
+};
+
+static inline struct clk *clk_hw_to_clk(const struct clk_hw *hw)
+{
+ return IS_ERR(hw) ? ERR_CAST(hw) : (struct clk *)&hw->clk;
+}
+
+static inline struct clk_hw *clk_to_clk_hw(const struct clk *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;
unsigned int div;
};
-struct clk *clk_fixed(const char *name, int rate);
+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);
+}
struct clk_divider {
- struct clk clk;
+ struct clk_hw hw;
u8 shift;
u8 width;
void __iomem *reg;
@@ -338,18 +419,33 @@ struct clk_divider {
const struct clk_div_table *table;
int max_div_index;
int table_size;
+ spinlock_t *lock;
};
+#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+
#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)
#define CLK_MUX_HIWORD_MASK (1 << 2)
#define CLK_MUX_READ_ONLY (1 << 3) /* mux can't be changed */
-extern struct clk_ops clk_divider_ops;
+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,
@@ -371,6 +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 *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);
@@ -378,9 +478,99 @@ 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 *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;
+ int mult;
+ int div;
+ const char *parent;
+};
+
+static inline struct clk_fixed_factor *to_clk_fixed_factor(struct clk_hw *hw)
+{
+ return container_of(hw, struct clk_fixed_factor, hw);
+}
+
+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 *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
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @reg: register containing the divider
+ * @mshift: shift to the numerator bit field
+ * @mwidth: width of the numerator bit field
+ * @nshift: shift to the denominator bit field
+ * @nwidth: width of the denominator bit field
+ *
+ * Clock with adjustable fractional divider affecting its output frequency.
+ *
+ * Flags:
+ * CLK_FRAC_DIVIDER_ZERO_BASED - by default the numerator and denominator
+ * is the value read from the register. If CLK_FRAC_DIVIDER_ZERO_BASED
+ * is set then the numerator and denominator are both the value read
+ * plus one.
+ * CLK_FRAC_DIVIDER_BIG_ENDIAN - By default little endian register accesses are
+ * used for the divider register. Setting this flag makes the register
+ * accesses big endian.
+ */
+struct clk_fractional_divider {
+ struct clk_hw hw;
+ void __iomem *reg;
+ u8 mshift;
+ u8 mwidth;
+ u32 mmask;
+ u8 nshift;
+ u8 nwidth;
+ u32 nmask;
+ u8 flags;
+ void (*approximation)(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate,
+ unsigned long *m, unsigned long *n);
+ spinlock_t *lock;
+};
+
+#define CLK_FRAC_DIVIDER_ZERO_BASED BIT(0)
+#define CLK_FRAC_DIVIDER_BIG_ENDIAN BIT(1)
+
struct clk *clk_fractional_divider_alloc(
const char *name, const char *parent_name, unsigned long flags,
void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
@@ -391,17 +581,24 @@ struct clk *clk_fractional_divider(
u8 clk_divider_flags);
void clk_fractional_divider_free(struct clk *clk_fd);
+#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
+
+extern const struct clk_ops clk_fractional_divider_ops;
+
struct clk_mux {
- struct clk clk;
+ struct clk_hw hw;
void __iomem *reg;
int shift;
int width;
unsigned flags;
+ u32 *table;
+ spinlock_t *lock;
};
-#define to_clk_mux(_clk) container_of(_clk, struct clk_mux, clk)
+#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
-extern struct clk_ops clk_mux_ops;
+extern const struct clk_ops clk_mux_ops;
+extern const struct clk_ops clk_mux_ro_ops;
struct clk *clk_mux_alloc(const char *name, unsigned clk_flags,
void __iomem *reg, u8 shift, u8 width,
@@ -411,18 +608,55 @@ 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 *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 clk;
+ struct clk_hw hw;
void __iomem *reg;
int shift;
const char *parent;
unsigned flags;
+ spinlock_t *lock;
};
-int clk_gate_is_enabled(struct clk *clk);
+int clk_gate_is_enabled(struct clk_hw *hw);
-#define to_clk_gate(_clk) container_of(_clk, struct clk_gate, clk)
+#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
extern struct clk_ops clk_gate_ops;
@@ -436,20 +670,46 @@ 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 *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);
-int clk_is_enabled_always(struct clk *clk);
-long clk_parent_round_rate(struct clk *clk, unsigned long rate,
+int clk_is_enabled_always(struct clk_hw *hw);
+long clk_parent_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate);
-int clk_parent_set_rate(struct clk *clk, unsigned long rate,
+int clk_parent_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate);
-int clk_register(struct clk *clk);
+int bclk_register(struct clk *clk);
+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);
void clk_dump(int verbose);
+void clk_dump_one(struct clk *clk, int verbose);
struct clk *clk_register_composite(const char *name,
const char * const *parent_names, int num_parents,
@@ -457,6 +717,37 @@ struct clk *clk_register_composite(const char *name,
struct clk *rate_clk,
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);
+
#endif
struct device_node;
@@ -468,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);
@@ -481,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);
@@ -488,16 +786,17 @@ 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
@@ -515,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);
@@ -529,8 +838,12 @@ static inline struct clk *of_clk_get_by_name(struct device_node *np,
{
return ERR_PTR(-ENOENT);
}
-static inline int of_clk_init(struct device_node *root,
- const struct of_device_id *matches)
+static inline unsigned int of_clk_get_parent_count(struct device_node *np)
+{
+ return 0;
+}
+
+static inline int of_clk_init(void)
{
return 0;
}
@@ -541,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)
@@ -549,6 +870,284 @@ struct string_list;
int clk_name_complete(struct string_list *sl, char *instr);
-char *of_clk_get_parent_name(struct device_node *np, unsigned int index);
+char *of_clk_get_parent_name(const struct device_node *np, int index);
+
+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/analogbits-wrpll-cln28hpc.h b/include/linux/clk/analogbits-wrpll-cln28hpc.h
new file mode 100644
index 0000000000..03279097e1
--- /dev/null
+++ b/include/linux/clk/analogbits-wrpll-cln28hpc.h
@@ -0,0 +1,79 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2018-2019 SiFive, Inc.
+ * Wesley Terpstra
+ * Paul Walmsley
+ */
+
+#ifndef __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
+#define __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H
+
+#include <linux/types.h>
+
+/* DIVQ_VALUES: number of valid DIVQ values */
+#define DIVQ_VALUES 6
+
+/*
+ * Bit definitions for struct wrpll_cfg.flags
+ *
+ * WRPLL_FLAGS_BYPASS_FLAG: if set, the PLL is either in bypass, or should be
+ * programmed to enter bypass
+ * WRPLL_FLAGS_RESET_FLAG: if set, the PLL is in reset
+ * WRPLL_FLAGS_INT_FEEDBACK_FLAG: if set, the PLL is configured for internal
+ * feedback mode
+ * WRPLL_FLAGS_EXT_FEEDBACK_FLAG: if set, the PLL is configured for external
+ * feedback mode (not yet supported by this driver)
+ */
+#define WRPLL_FLAGS_BYPASS_SHIFT 0
+#define WRPLL_FLAGS_BYPASS_MASK BIT(WRPLL_FLAGS_BYPASS_SHIFT)
+#define WRPLL_FLAGS_RESET_SHIFT 1
+#define WRPLL_FLAGS_RESET_MASK BIT(WRPLL_FLAGS_RESET_SHIFT)
+#define WRPLL_FLAGS_INT_FEEDBACK_SHIFT 2
+#define WRPLL_FLAGS_INT_FEEDBACK_MASK BIT(WRPLL_FLAGS_INT_FEEDBACK_SHIFT)
+#define WRPLL_FLAGS_EXT_FEEDBACK_SHIFT 3
+#define WRPLL_FLAGS_EXT_FEEDBACK_MASK BIT(WRPLL_FLAGS_EXT_FEEDBACK_SHIFT)
+
+/**
+ * struct wrpll_cfg - WRPLL configuration values
+ * @divr: reference divider value (6 bits), as presented to the PLL signals
+ * @divf: feedback divider value (9 bits), as presented to the PLL signals
+ * @divq: output divider value (3 bits), as presented to the PLL signals
+ * @flags: PLL configuration flags. See above for more information
+ * @range: PLL loop filter range. See below for more information
+ * @output_rate_cache: cached output rates, swept across DIVQ
+ * @parent_rate: PLL refclk rate for which values are valid
+ * @max_r: maximum possible R divider value, given @parent_rate
+ * @init_r: initial R divider value to start the search from
+ *
+ * @divr, @divq, @divq, @range represent what the PLL expects to see
+ * on its input signals. Thus @divr and @divf are the actual divisors
+ * minus one. @divq is a power-of-two divider; for example, 1 =
+ * divide-by-2 and 6 = divide-by-64. 0 is an invalid @divq value.
+ *
+ * When initially passing a struct wrpll_cfg record, the
+ * record should be zero-initialized with the exception of the @flags
+ * field. The only flag bits that need to be set are either
+ * WRPLL_FLAGS_INT_FEEDBACK or WRPLL_FLAGS_EXT_FEEDBACK.
+ */
+struct wrpll_cfg {
+ u8 divr;
+ u8 divq;
+ u8 range;
+ u8 flags;
+ u16 divf;
+/* private: */
+ u32 output_rate_cache[DIVQ_VALUES];
+ unsigned long parent_rate;
+ u8 max_r;
+ u8 init_r;
+};
+
+int wrpll_configure_for_rate(struct wrpll_cfg *c, u32 target_rate,
+ unsigned long parent_rate);
+
+unsigned int wrpll_calc_max_lock_us(const struct wrpll_cfg *c);
+
+unsigned long wrpll_calc_output_rate(const struct wrpll_cfg *c,
+ unsigned long parent_rate);
+
+#endif /* __LINUX_CLK_ANALOGBITS_WRPLL_CLN28HPC_H */
diff --git a/include/linux/clk/at91_pmc.h b/include/linux/clk/at91_pmc.h
index 17f413bbbe..7af499bdbe 100644
--- a/include/linux/clk/at91_pmc.h
+++ b/include/linux/clk/at91_pmc.h
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* include/linux/clk/at91_pmc.h
*
@@ -6,16 +7,16 @@
*
* Power Management Controller (PMC) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
- *
- * 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 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 */
@@ -34,21 +35,42 @@
#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 */
+#define AT91_PMC_WAITMODE (1 << 2) /* Wait Mode Command */
#define AT91_PMC_MOSCRCEN (1 << 3) /* Main On-Chip RC Oscillator Enable [some SAM9] */
#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */
+#define AT91_PMC_KEY_MASK (0xff << 16)
#define AT91_PMC_KEY (0x37 << 16) /* MOR Writing Key */
#define AT91_PMC_MOSCSEL (1 << 24) /* Main Oscillator Selection [some SAM9] */
#define AT91_PMC_CFDEN (1 << 25) /* Clock Failure Detector Enable [some SAM9] */
@@ -58,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 */
@@ -72,6 +98,8 @@
#define AT91_PMC_USBDIV_4 (2 << 28)
#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */
+#define AT91_PMC_CPU_CKR 0x28 /* CPU Clock Register */
+
#define AT91_PMC_MCKR 0x30 /* Master Clock Register */
#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */
#define AT91_PMC_CSS_SLOW (0 << 0)
@@ -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,8 +209,23 @@
#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 */
+#define AT91_PMC_FSTT(n) BIT(n)
+#define AT91_PMC_RTTAL BIT(16)
+#define AT91_PMC_RTCAL BIT(17) /* RTC Alarm Enable */
+#define AT91_PMC_USBAL BIT(18) /* USB Resume Enable */
+#define AT91_PMC_SDMMC_CD BIT(19) /* SDMMC Card Detect Enable */
+#define AT91_PMC_LPM BIT(20) /* Low-power Mode */
+#define AT91_PMC_RXLP_MCE BIT(24) /* Backup UART Receive Enable */
+#define AT91_PMC_ACC_CE BIT(25) /* ACC Enable */
+
+#define AT91_PMC_FSPR 0x74 /* Fast Startup Polarity Reg */
+
+#define AT91_PMC_FS_INPUT_MASK 0x7ff
+
#define AT91_PMC_PLLICPR 0x80 /* PLL Charge Pump Current Register */
#define AT91_PMC_PROT 0xe4 /* Write Protect Mode Register [some SAM9] */
@@ -166,23 +237,42 @@
#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 */
#define AT91_PMC_PCR 0x10c /* Peripheral Control Register [some SAM9 and SAMA5] */
#define AT91_PMC_PCR_PID_MASK 0x3f
-#define AT91_PMC_PCR_GCKCSS_OFFSET 8
-#define AT91_PMC_PCR_GCKCSS_MASK (0x7 << AT91_PMC_PCR_GCKCSS_OFFSET)
-#define AT91_PMC_PCR_GCKCSS(n) ((n) << AT91_PMC_PCR_GCKCSS_OFFSET) /* GCK Clock Source Selection */
#define AT91_PMC_PCR_CMD (0x1 << 12) /* Command (read=0, write=1) */
-#define AT91_PMC_PCR_DIV_OFFSET 16
-#define AT91_PMC_PCR_DIV_MASK (0x3 << AT91_PMC_PCR_DIV_OFFSET)
-#define AT91_PMC_PCR_DIV(n) ((n) << AT91_PMC_PCR_DIV_OFFSET) /* Divisor Value */
-#define AT91_PMC_PCR_GCKDIV_OFFSET 20
-#define AT91_PMC_PCR_GCKDIV_MASK (0xff << AT91_PMC_PCR_GCKDIV_OFFSET)
-#define AT91_PMC_PCR_GCKDIV(n) ((n) << AT91_PMC_PCR_GCKDIV_OFFSET) /* Generated Clock Divisor Value */
+#define AT91_PMC_PCR_GCKDIV_MASK GENMASK(27, 20)
#define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */
#define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */
+#define AT91_PMC_AUDIO_PLL0 0x14c
+#define AT91_PMC_AUDIO_PLL_PLLEN (1 << 0)
+#define AT91_PMC_AUDIO_PLL_PADEN (1 << 1)
+#define AT91_PMC_AUDIO_PLL_PMCEN (1 << 2)
+#define AT91_PMC_AUDIO_PLL_RESETN (1 << 3)
+#define AT91_PMC_AUDIO_PLL_ND_OFFSET 8
+#define AT91_PMC_AUDIO_PLL_ND_MASK (0x7f << AT91_PMC_AUDIO_PLL_ND_OFFSET)
+#define AT91_PMC_AUDIO_PLL_ND(n) ((n) << AT91_PMC_AUDIO_PLL_ND_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPMC_OFFSET 16
+#define AT91_PMC_AUDIO_PLL_QDPMC_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPMC(n) ((n) << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET)
+
+#define AT91_PMC_AUDIO_PLL1 0x150
+#define AT91_PMC_AUDIO_PLL_FRACR_MASK 0x3fffff
+#define AT91_PMC_AUDIO_PLL_QDPAD_OFFSET 24
+#define AT91_PMC_AUDIO_PLL_QDPAD_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET AT91_PMC_AUDIO_PLL_QDPAD_OFFSET
+#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK (0x3 << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_DIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET 26
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX 0x1f
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET)
+#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET)
+
#endif
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 f597c7abae..6654c164f5 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -250,7 +250,6 @@ static __always_inline void __write_once_size(volatile void *p, void *res, int s
__read_once_size(&(x), __u.__c, sizeof(x)); \
else \
__read_once_size_nocheck(&(x), __u.__c, sizeof(x)); \
- smp_read_barrier_depends(); /* Enforce dependency ordering from x */ \
__u.__val; \
})
#define READ_ONCE(x) __READ_ONCE(x, 1)
@@ -277,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/completion.h b/include/linux/completion.h
new file mode 100644
index 0000000000..e897e4f65b
--- /dev/null
+++ b/include/linux/completion.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * (C) Copyright 2021 Ahmad Fatoum
+ *
+ * Async wait-for-completion handler data structures.
+ * This allows one bthread to wait for another
+ */
+
+#ifndef __LINUX_COMPLETION_H
+#define __LINUX_COMPLETION_H
+
+#include <stdio.h>
+#include <errno.h>
+#include <bthread.h>
+
+struct completion {
+ unsigned int done;
+};
+
+static inline void init_completion(struct completion *x)
+{
+ x->done = 0;
+}
+
+static inline void reinit_completion(struct completion *x)
+{
+ x->done = 0;
+}
+
+static inline int wait_for_completion_interruptible(struct completion *x)
+{
+ while (!x->done) {
+ switch (bthread_should_stop()) {
+ case -EINTR:
+ if (!ctrlc())
+ continue;
+ case 1:
+ return -ERESTARTSYS;
+ }
+ }
+
+ return 0;
+}
+
+static inline bool completion_done(struct completion *x)
+{
+ return x->done;
+}
+
+static inline void complete(struct completion *x)
+{
+ x->done = 1;
+}
+
+#endif
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
new file mode 100644
index 0000000000..a136d727d1
--- /dev/null
+++ b/include/linux/export.h
@@ -0,0 +1,42 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef _LINUX_EXPORT_H
+#define _LINUX_EXPORT_H
+
+#ifndef __ASSEMBLY__
+
+#define THIS_MODULE 0
+
+#if defined(CONFIG_MODULES) && !defined(__DISABLE_EXPORTS)
+
+struct kernel_symbol
+{
+ unsigned long value;
+ const char *name;
+};
+
+/* For every exported symbol, place a struct in the __ksymtab section */
+#define __EXPORT_SYMBOL(sym) \
+ extern typeof(sym) sym; \
+ static const char __ustrtab_##sym[] \
+ __ll_elem(__usymtab_strings) \
+ = MODULE_SYMBOL_PREFIX #sym; \
+ static const struct kernel_symbol __usymtab_##sym \
+ __ll_elem(__usymtab) \
+ = { (unsigned long)&sym, __ustrtab_##sym }
+
+#define EXPORT_SYMBOL(sym) \
+ __EXPORT_SYMBOL(sym)
+
+#define EXPORT_SYMBOL_GPL(sym) \
+ __EXPORT_SYMBOL(sym)
+
+#else
+
+#define EXPORT_SYMBOL(sym)
+#define EXPORT_SYMBOL_GPL(sym)
+
+#endif /* CONFIG_MODULES */
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _LINUX_EXPORT_H */
diff --git a/include/linux/fixp-arith.h b/include/linux/fixp-arith.h
new file mode 100644
index 0000000000..8396013785
--- /dev/null
+++ b/include/linux/fixp-arith.h
@@ -0,0 +1,144 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef _FIXP_ARITH_H
+#define _FIXP_ARITH_H
+
+#include <linux/math64.h>
+
+/*
+ * Simplistic fixed-point arithmetics.
+ * Hmm, I'm probably duplicating some code :(
+ *
+ * Copyright (c) 2002 Johann Deneux
+ */
+
+/*
+ *
+ * Should you need to contact me, the author, you can do so by
+ * e-mail - mail your message to <johann.deneux@gmail.com>
+ */
+
+#include <linux/types.h>
+
+static const s32 sin_table[] = {
+ 0x00000000, 0x023be165, 0x04779632, 0x06b2f1d2, 0x08edc7b6, 0x0b27eb5c,
+ 0x0d61304d, 0x0f996a26, 0x11d06c96, 0x14060b67, 0x163a1a7d, 0x186c6ddd,
+ 0x1a9cd9ac, 0x1ccb3236, 0x1ef74bf2, 0x2120fb82, 0x234815ba, 0x256c6f9e,
+ 0x278dde6e, 0x29ac379f, 0x2bc750e8, 0x2ddf003f, 0x2ff31bdd, 0x32037a44,
+ 0x340ff241, 0x36185aee, 0x381c8bb5, 0x3a1c5c56, 0x3c17a4e7, 0x3e0e3ddb,
+ 0x3fffffff, 0x41ecc483, 0x43d464fa, 0x45b6bb5d, 0x4793a20f, 0x496af3e1,
+ 0x4b3c8c11, 0x4d084650, 0x4ecdfec6, 0x508d9210, 0x5246dd48, 0x53f9be04,
+ 0x55a6125a, 0x574bb8e5, 0x58ea90c2, 0x5a827999, 0x5c135399, 0x5d9cff82,
+ 0x5f1f5ea0, 0x609a52d1, 0x620dbe8a, 0x637984d3, 0x64dd894f, 0x6639b039,
+ 0x678dde6d, 0x68d9f963, 0x6a1de735, 0x6b598ea1, 0x6c8cd70a, 0x6db7a879,
+ 0x6ed9eba0, 0x6ff389de, 0x71046d3c, 0x720c8074, 0x730baeec, 0x7401e4bf,
+ 0x74ef0ebb, 0x75d31a5f, 0x76adf5e5, 0x777f903b, 0x7847d908, 0x7906c0af,
+ 0x79bc384c, 0x7a6831b8, 0x7b0a9f8c, 0x7ba3751c, 0x7c32a67c, 0x7cb82884,
+ 0x7d33f0c8, 0x7da5f5a3, 0x7e0e2e31, 0x7e6c924f, 0x7ec11aa3, 0x7f0bc095,
+ 0x7f4c7e52, 0x7f834ecf, 0x7fb02dc4, 0x7fd317b3, 0x7fec09e1, 0x7ffb025e,
+ 0x7fffffff
+};
+
+/**
+ * __fixp_sin32() returns the sin of an angle in degrees
+ *
+ * @degrees: angle, in degrees, from 0 to 360.
+ *
+ * The returned value ranges from -0x7fffffff to +0x7fffffff.
+ */
+static inline s32 __fixp_sin32(int degrees)
+{
+ s32 ret;
+ bool negative = false;
+
+ if (degrees > 180) {
+ negative = true;
+ degrees -= 180;
+ }
+ if (degrees > 90)
+ degrees = 180 - degrees;
+
+ ret = sin_table[degrees];
+
+ return negative ? -ret : ret;
+}
+
+/**
+ * fixp_sin32() returns the sin of an angle in degrees
+ *
+ * @degrees: angle, in degrees. The angle can be positive or negative
+ *
+ * The returned value ranges from -0x7fffffff to +0x7fffffff.
+ */
+static inline s32 fixp_sin32(int degrees)
+{
+ degrees = (degrees % 360 + 360) % 360;
+
+ return __fixp_sin32(degrees);
+}
+
+/* cos(x) = sin(x + 90 degrees) */
+#define fixp_cos32(v) fixp_sin32((v) + 90)
+
+/*
+ * 16 bits variants
+ *
+ * The returned value ranges from -0x7fff to 0x7fff
+ */
+
+#define fixp_sin16(v) (fixp_sin32(v) >> 16)
+#define fixp_cos16(v) (fixp_cos32(v) >> 16)
+
+/**
+ * fixp_sin32_rad() - calculates the sin of an angle in radians
+ *
+ * @radians: angle, in radians
+ * @twopi: value to be used for 2*pi
+ *
+ * Provides a variant for the cases where just 360
+ * values is not enough. This function uses linear
+ * interpolation to a wider range of values given by
+ * twopi var.
+ *
+ * Experimental tests gave a maximum difference of
+ * 0.000038 between the value calculated by sin() and
+ * the one produced by this function, when twopi is
+ * equal to 360000. That seems to be enough precision
+ * for practical purposes.
+ *
+ * Please notice that two high numbers for twopi could cause
+ * overflows, so the routine will not allow values of twopi
+ * bigger than 1^18.
+ */
+static inline s32 fixp_sin32_rad(u32 radians, u32 twopi)
+{
+ int degrees;
+ s32 v1, v2, dx, dy;
+ s64 tmp;
+
+ /*
+ * Avoid too large values for twopi, as we don't want overflows.
+ */
+ BUG_ON(twopi > 1 << 18);
+
+ degrees = (radians * 360) / twopi;
+ tmp = radians - (degrees * twopi) / 360;
+
+ degrees = (degrees % 360 + 360) % 360;
+ v1 = __fixp_sin32(degrees);
+
+ v2 = fixp_sin32(degrees + 1);
+
+ dx = twopi / 360;
+ dy = v2 - v1;
+
+ tmp *= dy;
+
+ return v1 + div_s64(tmp, dx);
+}
+
+/* cos(x) = sin(x + pi/2 radians) */
+
+#define fixp_cos32_rad(rad, twopi) \
+ fixp_sin32_rad(rad + twopi / 4, twopi)
+
+#endif
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/fsl_ifc.h b/include/linux/fsl_ifc.h
new file mode 100644
index 0000000000..2ff0626357
--- /dev/null
+++ b/include/linux/fsl_ifc.h
@@ -0,0 +1,305 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright 2010-2011 Freescale Semiconductor, Inc.
+ * Author: Dipen Dudhat <dipen.dudhat@freescale.com>
+ *
+ */
+
+#ifndef __FSL_IFC_H
+#define __FSL_IFC_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+#include <linux/log2.h>
+
+/* Big-Endian */
+#define ifc_in32(a) ioread32be(a)
+#define ifc_out32(a, v) iowrite32be(v, a)
+#define ifc_in16(a) ioread16be(a)
+#define ifc_out16(a, v) iowrite16be(v, a)
+
+/*
+ * CSPR - Chip Select Property Register
+ */
+#define CSPR_BA 0xFFFF0000
+#define CSPR_BA_SHIFT 16
+#define CSPR_PORT_SIZE 0x00000180
+#define CSPR_PORT_SIZE_SHIFT 7
+#define CSPR_PORT_SIZE_8 0x00000080
+#define CSPR_PORT_SIZE_16 0x00000100
+#define CSPR_PORT_SIZE_32 0x00000180
+/* Write Protect */
+#define CSPR_WP 0x00000040
+#define CSPR_WP_SHIFT 6
+#define CSPR_MSEL 0x00000006
+#define CSPR_MSEL_SHIFT 1
+#define CSPR_MSEL_NOR 0x00000000
+#define CSPR_MSEL_NAND 0x00000002
+#define CSPR_MSEL_GPCM 0x00000004
+#define CSPR_V 0x00000001
+#define CSPR_V_SHIFT 0
+
+/* Convert an address into the right format for the CSPR Registers */
+#define CSPR_PHYS_ADDR(x) (((uint64_t)x) & 0xffff0000)
+
+/*
+ * Address Mask Register
+ */
+#define IFC_AMASK_MASK 0xFFFF0000
+#define IFC_AMASK_SHIFT 16
+#define IFC_AMASK(n) (IFC_AMASK_MASK << \
+ (ilog2(n) - IFC_AMASK_SHIFT))
+
+/*
+ * Chip Select Option Register IFC_NAND Machine
+ */
+#define CSOR_NAND_ECC_ENC_EN 0x80000000
+#define CSOR_NAND_ECC_MODE_MASK 0x30000000
+/* 4 bit correction per 520 Byte sector */
+#define CSOR_NAND_ECC_MODE_4 0x00000000
+/* 8 bit correction per 528 Byte sector */
+#define CSOR_NAND_ECC_MODE_8 0x10000000
+#define CSOR_NAND_ECC_DEC_EN 0x04000000
+/* Row Address Length */
+#define CSOR_NAND_RAL_MASK 0x01800000
+#define CSOR_NAND_RAL_SHIFT 20
+#define CSOR_NAND_RAL_1 0x00000000
+#define CSOR_NAND_RAL_2 0x00800000
+#define CSOR_NAND_RAL_3 0x01000000
+#define CSOR_NAND_RAL_4 0x01800000
+/* Page Size 512b, 2k, 4k */
+#define CSOR_NAND_PGS_MASK 0x00180000
+#define CSOR_NAND_PGS_SHIFT 16
+#define CSOR_NAND_PGS_512 0x00000000
+#define CSOR_NAND_PGS_2K 0x00080000
+#define CSOR_NAND_PGS_4K 0x00100000
+#define CSOR_NAND_PGS_8K 0x00180000
+/* Spare region Size */
+#define CSOR_NAND_SPRZ_MASK 0x0000E000
+#define CSOR_NAND_SPRZ_SHIFT 13
+#define CSOR_NAND_SPRZ_16 0x00000000
+#define CSOR_NAND_SPRZ_64 0x00002000
+#define CSOR_NAND_SPRZ_128 0x00004000
+#define CSOR_NAND_SPRZ_210 0x00006000
+#define CSOR_NAND_SPRZ_218 0x00008000
+#define CSOR_NAND_SPRZ_224 0x0000A000
+#define CSOR_NAND_SPRZ_CSOR_EXT 0x0000C000
+/* Pages Per Block */
+#define CSOR_NAND_PB_MASK 0x00000700
+#define CSOR_NAND_PB_SHIFT 8
+#define CSOR_NAND_PB(n) ((ilog2(n) - 5) << CSOR_NAND_PB_SHIFT)
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NAND_TRHZ_MASK 0x0000001C
+#define CSOR_NAND_TRHZ_SHIFT 2
+#define CSOR_NAND_TRHZ_20 0x00000000
+#define CSOR_NAND_TRHZ_40 0x00000004
+#define CSOR_NAND_TRHZ_60 0x00000008
+#define CSOR_NAND_TRHZ_80 0x0000000C
+#define CSOR_NAND_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_NAND_BCTLD 0x00000001
+
+/*
+ * Chip Select Option Register - NOR Flash Mode
+ */
+/* Enable Address shift Mode */
+#define CSOR_NOR_ADM_SHFT_MODE_EN 0x80000000
+/* Page Read Enable from NOR device */
+#define CSOR_NOR_PGRD_EN 0x10000000
+/* AVD Toggle Enable during Burst Program */
+#define CSOR_NOR_AVD_TGL_PGM_EN 0x01000000
+/* Address Data Multiplexing Shift */
+#define CSOR_NOR_ADM_MASK 0x0003E000
+#define CSOR_NOR_ADM_SHIFT_SHIFT 13
+#define CSOR_NOR_ADM_SHIFT(n) ((n) << CSOR_NOR_ADM_SHIFT_SHIFT)
+/* Type of the NOR device hooked */
+#define CSOR_NOR_NOR_MODE_ASYNC_NOR 0x00000000
+#define CSOR_NOR_NOR_MODE_AVD_NOR 0x00000020
+/* Time for Read Enable High to Output High Impedance */
+#define CSOR_NOR_TRHZ_MASK 0x0000001C
+#define CSOR_NOR_TRHZ_SHIFT 2
+#define CSOR_NOR_TRHZ_20 0x00000000
+#define CSOR_NOR_TRHZ_40 0x00000004
+#define CSOR_NOR_TRHZ_60 0x00000008
+#define CSOR_NOR_TRHZ_80 0x0000000C
+#define CSOR_NOR_TRHZ_100 0x00000010
+/* Buffer control disable */
+#define CSOR_NOR_BCTLD 0x00000001
+
+/*
+ * Flash Timing Registers (FTIM0 - FTIM2_CSn)
+ */
+/*
+ * FTIM0 - NAND Flash Mode
+ */
+#define FTIM0_NAND 0x7EFF3F3F
+#define FTIM0_NAND_TCCST_SHIFT 25
+#define FTIM0_NAND_TCCST(n) ((n) << FTIM0_NAND_TCCST_SHIFT)
+#define FTIM0_NAND_TWP_SHIFT 16
+#define FTIM0_NAND_TWP(n) ((n) << FTIM0_NAND_TWP_SHIFT)
+#define FTIM0_NAND_TWCHT_SHIFT 8
+#define FTIM0_NAND_TWCHT(n) ((n) << FTIM0_NAND_TWCHT_SHIFT)
+#define FTIM0_NAND_TWH_SHIFT 0
+#define FTIM0_NAND_TWH(n) ((n) << FTIM0_NAND_TWH_SHIFT)
+/*
+ * FTIM1 - NAND Flash Mode
+ */
+#define FTIM1_NAND 0xFFFF3FFF
+#define FTIM1_NAND_TADLE_SHIFT 24
+#define FTIM1_NAND_TADLE(n) ((n) << FTIM1_NAND_TADLE_SHIFT)
+#define FTIM1_NAND_TWBE_SHIFT 16
+#define FTIM1_NAND_TWBE(n) ((n) << FTIM1_NAND_TWBE_SHIFT)
+#define FTIM1_NAND_TRR_SHIFT 8
+#define FTIM1_NAND_TRR(n) ((n) << FTIM1_NAND_TRR_SHIFT)
+#define FTIM1_NAND_TRP_SHIFT 0
+#define FTIM1_NAND_TRP(n) ((n) << FTIM1_NAND_TRP_SHIFT)
+/*
+ * FTIM2 - NAND Flash Mode
+ */
+#define FTIM2_NAND 0x1FE1F8FF
+#define FTIM2_NAND_TRAD_SHIFT 21
+#define FTIM2_NAND_TRAD(n) ((n) << FTIM2_NAND_TRAD_SHIFT)
+#define FTIM2_NAND_TREH_SHIFT 11
+#define FTIM2_NAND_TREH(n) ((n) << FTIM2_NAND_TREH_SHIFT)
+#define FTIM2_NAND_TWHRE_SHIFT 0
+#define FTIM2_NAND_TWHRE(n) ((n) << FTIM2_NAND_TWHRE_SHIFT)
+/*
+ * FTIM0 - NOR Flash Mode
+ */
+#define FTIM0_NOR 0xF03F3F3F
+#define FTIM0_NOR_TACSE_SHIFT 28
+#define FTIM0_NOR_TACSE(n) ((n) << FTIM0_NOR_TACSE_SHIFT)
+#define FTIM0_NOR_TEADC_SHIFT 16
+#define FTIM0_NOR_TEADC(n) ((n) << FTIM0_NOR_TEADC_SHIFT)
+#define FTIM0_NOR_TAVDS_SHIFT 8
+#define FTIM0_NOR_TAVDS(n) ((n) << FTIM0_NOR_TAVDS_SHIFT)
+#define FTIM0_NOR_TEAHC_SHIFT 0
+#define FTIM0_NOR_TEAHC(n) ((n) << FTIM0_NOR_TEAHC_SHIFT)
+/*
+ * FTIM1 - NOR Flash Mode
+ */
+#define FTIM1_NOR 0xFF003F3F
+#define FTIM1_NOR_TACO_SHIFT 24
+#define FTIM1_NOR_TACO(n) ((n) << FTIM1_NOR_TACO_SHIFT)
+#define FTIM1_NOR_TRAD_NOR_SHIFT 8
+#define FTIM1_NOR_TRAD_NOR(n) ((n) << FTIM1_NOR_TRAD_NOR_SHIFT)
+#define FTIM1_NOR_TSEQRAD_NOR_SHIFT 0
+#define FTIM1_NOR_TSEQRAD_NOR(n) ((n) << FTIM1_NOR_TSEQRAD_NOR_SHIFT)
+/*
+ * FTIM2 - NOR Flash Mode
+ */
+#define FTIM2_NOR 0x0F3CFCFF
+#define FTIM2_NOR_TCS_SHIFT 24
+#define FTIM2_NOR_TCS(n) ((n) << FTIM2_NOR_TCS_SHIFT)
+#define FTIM2_NOR_TCH_SHIFT 18
+#define FTIM2_NOR_TCH(n) ((n) << FTIM2_NOR_TCH_SHIFT)
+#define FTIM2_NOR_TWPH_SHIFT 10
+#define FTIM2_NOR_TWPH(n) ((n) << FTIM2_NOR_TWPH_SHIFT)
+#define FTIM2_NOR_TWP_SHIFT 0
+#define FTIM2_NOR_TWP(n) ((n) << FTIM2_NOR_TWP_SHIFT)
+
+/*
+ * FTIM0 - Normal GPCM Mode
+ */
+#define FTIM0_GPCM 0xF03F3F3F
+#define FTIM0_GPCM_TACSE_SHIFT 28
+#define FTIM0_GPCM_TACSE(n) ((n) << FTIM0_GPCM_TACSE_SHIFT)
+#define FTIM0_GPCM_TEADC_SHIFT 16
+#define FTIM0_GPCM_TEADC(n) ((n) << FTIM0_GPCM_TEADC_SHIFT)
+#define FTIM0_GPCM_TAVDS_SHIFT 8
+#define FTIM0_GPCM_TAVDS(n) ((n) << FTIM0_GPCM_TAVDS_SHIFT)
+#define FTIM0_GPCM_TEAHC_SHIFT 0
+#define FTIM0_GPCM_TEAHC(n) ((n) << FTIM0_GPCM_TEAHC_SHIFT)
+/*
+ * FTIM1 - Normal GPCM Mode
+ */
+#define FTIM1_GPCM 0xFF003F00
+#define FTIM1_GPCM_TACO_SHIFT 24
+#define FTIM1_GPCM_TACO(n) ((n) << FTIM1_GPCM_TACO_SHIFT)
+#define FTIM1_GPCM_TRAD_SHIFT 8
+#define FTIM1_GPCM_TRAD(n) ((n) << FTIM1_GPCM_TRAD_SHIFT)
+/*
+ * FTIM2 - Normal GPCM Mode
+ */
+#define FTIM2_GPCM 0x0F3C00FF
+#define FTIM2_GPCM_TCS_SHIFT 24
+#define FTIM2_GPCM_TCS(n) ((n) << FTIM2_GPCM_TCS_SHIFT)
+#define FTIM2_GPCM_TCH_SHIFT 18
+#define FTIM2_GPCM_TCH(n) ((n) << FTIM2_GPCM_TCH_SHIFT)
+#define FTIM2_GPCM_TWP_SHIFT 0
+#define FTIM2_GPCM_TWP(n) ((n) << FTIM2_GPCM_TWP_SHIFT)
+
+/*
+ * General Control Register (GCR)
+ */
+#define IFC_GCR_MASK 0x8000F800
+/* reset all IFC hardware */
+#define IFC_GCR_SOFT_RST_ALL 0x80000000
+/* Turnaroud Time of external buffer */
+#define IFC_GCR_TBCTL_TRN_TIME 0x0000F800
+#define IFC_GCR_TBCTL_TRN_TIME_SHIFT 11
+
+/*
+ * Clock Control Register (CCR)
+ */
+#define IFC_CCR_MASK 0x0F0F8800
+/* Clock division ratio */
+#define IFC_CCR_CLK_DIV_MASK 0x0F000000
+#define IFC_CCR_CLK_DIV_SHIFT 24
+#define IFC_CCR_CLK_DIV(n) ((n-1) << IFC_CCR_CLK_DIV_SHIFT)
+/* IFC Clock Delay */
+#define IFC_CCR_CLK_DLY_MASK 0x000F0000
+#define IFC_CCR_CLK_DLY_SHIFT 16
+#define IFC_CCR_CLK_DLY(n) ((n) << IFC_CCR_CLK_DLY_SHIFT)
+
+#ifndef __ASSEMBLY__
+#include <asm/io.h>
+
+#define FSL_IFC_CSPRX(i) (0x10 + ((i) * 0xc))
+#define FSL_IFC_CSORX(i) (0x130 + ((i) * 0xc))
+#define FSL_IFC_CSORX_EXT(i) (0x134 + ((i) * 0xc))
+#define FSL_IFC_AMASKX(i) (0xa0 + ((i) * 0xc))
+#define FSL_IFC_CSX_FTIMY(i, j) ((0x1c0 + ((i) * 0x30)) + ((j) * 4))
+
+#define get_ifc_cspr(base, i) (ifc_in32(base + FSL_IFC_CSPRX(i)))
+#define get_ifc_csor(base, i) (ifc_in32(base + FSL_IFC_CSORX(i)))
+#define get_ifc_csor_ext(base, i) (ifc_in32(base + FSL_IFC_CSORX_EXT(i)))
+#define get_ifc_amask(base, i) (ifc_in32(base + FSL_IFC_AMASKX(i)))
+#define get_ifc_ftim(base, i, j) (ifc_in32(base + FSL_IFC_CSX_FTIMY(i, j)))
+
+#define set_ifc_cspr(base, i, v) (ifc_out32(base + FSL_IFC_CSPRX(i), v))
+#define set_ifc_csor(base, i, v) (ifc_out32(base + FSL_IFC_CSORX(i), v))
+#define set_ifc_csor_ext(base, i, v) (ifc_out32(base + FSL_IFC_CSORX_EXT(i),\
+ v))
+#define set_ifc_amask(base, i, v) (ifc_out32(base + FSL_IFC_AMASKX(i), v))
+#define set_ifc_ftim(base, i, j, v) \
+ (ifc_out32(base + FSL_IFC_CSX_FTIMY(i, j), v))
+
+#define FSL_IFC_GCR_OFFSET 0x40c
+#define FSL_IFC_CCR_OFFSET 0x44c
+
+enum ifc_chip_sel {
+ IFC_CS0,
+ IFC_CS1,
+ IFC_CS2,
+ IFC_CS3,
+ IFC_CS4,
+ IFC_CS5,
+ IFC_CS6,
+ IFC_CS7,
+};
+
+enum ifc_ftims {
+ IFC_FTIM0,
+ IFC_FTIM1,
+ IFC_FTIM2,
+ IFC_FTIM3,
+};
+
+#ifdef CONFIG_FSL_ERRATUM_IFC_A002769
+#undef CSPR_MSEL_NOR
+#define CSPR_MSEL_NOR CSPR_MSEL_GPCM
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* __FSL_IFC_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 bae442166c..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,18 +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 66c8f652ca..96b17dee48 100644
--- a/include/linux/iopoll.h
+++ b/include/linux/iopoll.h
@@ -13,12 +13,12 @@
#include <pbl.h>
/**
- * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+ * read_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
* @op: accessor function (takes @addr as its only argument)
- * @addr: Address to poll
* @val: Variable to read the value into
* @cond: Break condition (usually involving @val)
* @timeout_us: Timeout in us, 0 means never timeout
+ * @args: arguments for @op poll
*
* Returns 0 on success and -ETIMEDOUT upon a timeout. In either
* case, the last read value at @addr is stored in @val.
@@ -29,24 +29,43 @@
* We do not have timing functions in the PBL, so ignore the timeout value and
* loop infinitely here.
*/
-#define readx_poll_timeout(op, addr, val, cond, timeout_us) \
+#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(addr); \
+ (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(addr); \
+ (val) = op(args); \
break; \
} \
} \
(cond) ? 0 : -ETIMEDOUT; \
})
+/**
+ * readx_poll_timeout - Periodically poll an address until a condition is met or a timeout occurs
+ * @op: accessor function (takes @addr as its only argument)
+ * @addr: Address to poll
+ * @val: 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. In either
+ * case, the last read value at @addr is stored in @val.
+ *
+ * When available, you'll probably want to use one of the specialized
+ * macros defined below rather than this macro directly.
+ *
+ * We do not have timing functions in the PBL, so ignore the timeout value and
+ * loop infinitely here.
+ */
+#define readx_poll_timeout(op, addr, val, cond, timeout_us) \
+ read_poll_timeout(op, val, cond, timeout_us, addr)
#define readb_poll_timeout(addr, val, cond, timeout_us) \
readx_poll_timeout(readb, addr, val, cond, timeout_us)
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index 3d375a8740..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.
@@ -130,14 +132,34 @@ static inline unsigned long resource_type(const struct resource *res)
return res->flags & IORESOURCE_TYPE_BITS;
}
+/* True iff r1 completely contains r2 */
+static inline bool resource_contains(struct resource *r1, struct resource *r2)
+{
+ if (resource_type(r1) != resource_type(r2))
+ return false;
+ if (r1->flags & IORESOURCE_UNSET || r2->flags & IORESOURCE_UNSET)
+ return false;
+ return r1->start <= r2->start && r1->end >= r2->end;
+}
+
+/* True if r1 and r2 are adjacent to each other */
+static inline bool resource_adjacent(struct resource *r1, struct resource *r2)
+{
+ return (r1->end != ~(resource_size_t)0 && r1->end + 1 == r2->start) ||
+ (r2->end != ~(resource_size_t)0 && r2->end + 1 == r1->start);
+}
+
struct resource *request_iomem_region(const char *name,
resource_size_t start, resource_size_t end);
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);
int release_region(struct resource *res);
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
new file mode 100644
index 0000000000..5fa0bebb79
--- /dev/null
+++ b/include/linux/kasan.h
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KASAN_H
+#define _LINUX_KASAN_H
+
+#include <linux/types.h>
+
+/*
+ * On 64bit architectures tlsf aligns all allocations to a 64bit
+ * boundary, otherwise they are only 32bit aligned.
+ */
+#ifdef CONFIG_64BIT
+#define KASAN_SHADOW_SCALE_SHIFT 3
+#else
+#define KASAN_SHADOW_SCALE_SHIFT 2
+#endif
+
+#define KASAN_TAG_KERNEL 0xFF /* native kernel pointers tag */
+#define KASAN_TAG_INVALID 0xFE /* inaccessible memory tag */
+#define KASAN_TAG_MAX 0xFD /* maximum value for random tags */
+
+#define KASAN_FREE_PAGE 0xFF /* page was freed */
+#define KASAN_PAGE_REDZONE 0xFE /* redzone for kmalloc_large allocations */
+#define KASAN_KMALLOC_REDZONE 0xFC /* redzone inside slub object */
+#define KASAN_KMALLOC_FREE 0xFB /* object was freed (kmem_cache_free/kfree) */
+#define KASAN_KMALLOC_FREETRACK 0xFA /* object was freed and has free track set */
+
+#define KASAN_GLOBAL_REDZONE 0xF9 /* redzone for global variable */
+#define KASAN_VMALLOC_INVALID 0xF8 /* unallocated space in vmapped page */
+
+/*
+ * Stack redzone shadow values
+ * (Those are compiler's ABI, don't change them)
+ */
+#define KASAN_STACK_LEFT 0xF1
+#define KASAN_STACK_MID 0xF2
+#define KASAN_STACK_RIGHT 0xF3
+#define KASAN_STACK_PARTIAL 0xF4
+
+/*
+ * alloca redzone shadow values
+ */
+#define KASAN_ALLOCA_LEFT 0xCA
+#define KASAN_ALLOCA_RIGHT 0xCB
+
+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;
+
+ a -= kasan_shadow_start;
+ a >>= KASAN_SHADOW_SCALE_SHIFT;
+ a += kasan_shadow_base;
+
+ return (void *)a;
+}
+
+void kasan_init(unsigned long membase, unsigned long memsize,
+ unsigned long shadow_base);
+
+/* Enable reporting bugs after kasan_disable_current() */
+extern void kasan_enable_current(void);
+
+/* Disable reporting bugs for current task */
+extern void kasan_disable_current(void);
+
+void kasan_poison_shadow(const void *address, size_t size, u8 value);
+void kasan_unpoison_shadow(const void *address, size_t size);
+
+bool kasan_save_enable_multi_shot(void);
+void kasan_restore_multi_shot(bool enabled);
+
+#else /* CONFIG_KASAN */
+
+static inline void kasan_poison_shadow(const void *address, size_t size, u8 value) {}
+static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
+
+static inline void kasan_enable_current(void) {}
+static inline void kasan_disable_current(void) {}
+
+static inline void kasan_init(unsigned long membase, unsigned long memsize,
+ unsigned long shadow_base) {}
+
+#endif /* CONFIG_KASAN */
+
+#endif /* LINUX_KASAN_H */
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 b320f7e902..4e50f60751 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -6,14 +6,29 @@
#include <linux/bug.h>
#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))
+#define ARRAY_AND_SIZE(x) (x), ARRAY_SIZE(x)
/*
* This looks more complex than it should be. But we need to
@@ -41,6 +56,18 @@
(((x) + ((__divisor) / 2)) / (__divisor)); \
} \
)
+/*
+ * Same as above but for u64 dividends. divisor must be a 32-bit
+ * number.
+ */
+#define DIV_ROUND_CLOSEST_ULL(x, divisor)( \
+{ \
+ typeof(divisor) __d = divisor; \
+ unsigned long long _tmp = (x) + (__d) / 2; \
+ do_div(_tmp, __d); \
+ _tmp; \
+} \
+)
/**
* upper_32_bits - return bits 32-63 of a number
@@ -68,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) ( \
{ \
@@ -242,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/libfdt.h b/include/linux/libfdt.h
index ef2467213b..90ed4ebfa6 100644
--- a/include/linux/libfdt.h
+++ b/include/linux/libfdt.h
@@ -3,6 +3,6 @@
#define _INCLUDE_LIBFDT_H_
#include <linux/libfdt_env.h>
-#include "../scripts/dtc/libfdt/libfdt.h"
+#include "../../scripts/dtc/libfdt/libfdt.h"
#endif /* _INCLUDE_LIBFDT_H_ */
diff --git a/include/linux/libfdt_env.h b/include/linux/libfdt_env.h
index bac4670d6d..cea8574a29 100644
--- a/include/linux/libfdt_env.h
+++ b/include/linux/libfdt_env.h
@@ -2,11 +2,14 @@
#ifndef LIBFDT_ENV_H
#define LIBFDT_ENV_H
-#include <linux/kernel.h> /* For INT_MAX */
+#include <linux/limits.h> /* For INT_MAX */
#include <linux/string.h>
#include <asm/byteorder.h>
+#define INT32_MAX S32_MAX
+#define UINT32_MAX U32_MAX
+
typedef __be16 fdt16_t;
typedef __be32 fdt32_t;
typedef __be64 fdt64_t;
@@ -16,6 +19,4 @@ typedef __be64 fdt64_t;
#define fdt64_to_cpu(x) be64_to_cpu(x)
#define cpu_to_fdt64(x) cpu_to_be64(x)
-#define INT32_MAX 2147483647
-
#endif /* LIBFDT_ENV_H */
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 af5edc9a76..60b0111f46 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -1,7 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_LIST_H
#define _LINUX_LIST_H
-#include <linux/stddef.h> /* for NULL */
+#include <linux/types.h>
+#include <linux/stddef.h>
+#include <linux/poison.h>
+#include <linux/const.h>
#include <linux/kernel.h>
/*
@@ -14,46 +18,60 @@
* using the generic single-entry routines.
*/
-#define LIST_POISON1 ((void *) 0x00100100)
-#define LIST_POISON2 ((void *) 0x00200200)
-static inline void prefetch(const void *x) {;}
-
-struct list_head {
- struct list_head *next, *prev;
-};
-
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
+/**
+ * INIT_LIST_HEAD - Initialize a list_head structure
+ * @list: list_head structure to be initialized.
+ *
+ * Initializes the list_head to point to itself. If it is a list header,
+ * the result is an empty list.
+ */
static inline void INIT_LIST_HEAD(struct list_head *list)
{
- list->next = list;
+ WRITE_ONCE(list->next, list);
list->prev = list;
}
+#ifdef CONFIG_DEBUG_LIST
+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_or_report(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ return true;
+}
+static inline bool __list_del_entry_valid_or_report(struct list_head *entry)
+{
+ return true;
+}
+#endif
+
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
+ if (!__list_add_valid_or_report(new, prev, next))
+ return;
+
next->prev = new;
new->next = next;
new->prev = prev;
- prev->next = new;
+ WRITE_ONCE(prev->next, new);
}
-#else
-extern void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next);
-#endif
/**
* list_add - add a new entry
@@ -63,14 +81,10 @@ extern void __list_add(struct list_head *new,
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void list_add(struct list_head *new, struct list_head *head)
{
__list_add(new, head, head->next);
}
-#else
-extern void list_add(struct list_head *new, struct list_head *head);
-#endif
/**
@@ -96,7 +110,29 @@ static inline void list_add_tail(struct list_head *new, struct list_head *head)
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
- prev->next = next;
+ WRITE_ONCE(prev->next, next);
+}
+
+/*
+ * Delete a list entry and clear the 'prev' pointer.
+ *
+ * This is a special-purpose list clearing method used in the networking code
+ * for lists allocated as per-cpu, where we don't want to incur the extra
+ * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this
+ * needs to check the node 'prev' pointer instead of calling list_empty().
+ */
+static inline void __list_del_clearprev(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->prev = NULL;
+}
+
+static inline void __list_del_entry(struct list_head *entry)
+{
+ if (!__list_del_entry_valid_or_report(entry))
+ return;
+
+ __list_del(entry->prev, entry->next);
}
/**
@@ -105,16 +141,12 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
+ __list_del_entry(entry);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
-#else
-extern void list_del(struct list_head *entry);
-#endif
/**
* list_replace - replace old entry by new one
@@ -132,20 +164,44 @@ static inline void list_replace(struct list_head *old,
new->prev->next = new;
}
+/**
+ * list_replace_init - replace old entry by new one and initialize the old one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
static inline void list_replace_init(struct list_head *old,
- struct list_head *new)
+ struct list_head *new)
{
list_replace(old, new);
INIT_LIST_HEAD(old);
}
/**
+ * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position
+ * @entry1: the location to place entry2
+ * @entry2: the location to place entry1
+ */
+static inline void list_swap(struct list_head *entry1,
+ struct list_head *entry2)
+{
+ struct list_head *pos = entry2->prev;
+
+ list_del(entry2);
+ list_replace(entry1, entry2);
+ if (pos == entry1)
+ pos = entry2;
+ list_add(entry1, pos);
+}
+
+/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
+ __list_del_entry(entry);
INIT_LIST_HEAD(entry);
}
@@ -156,7 +212,7 @@ static inline void list_del_init(struct list_head *entry)
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
- __list_del(list->prev, list->next);
+ __list_del_entry(list);
list_add(list, head);
}
@@ -168,11 +224,45 @@ static inline void list_move(struct list_head *list, struct list_head *head)
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
- __list_del(list->prev, list->next);
+ __list_del_entry(list);
list_add_tail(list, head);
}
/**
+ * list_bulk_move_tail - move a subsection of a list to its tail
+ * @head: the head that will follow our entry
+ * @first: first entry to move
+ * @last: last entry to move, can be the same as first
+ *
+ * Move all entries between @first and including @last before @head.
+ * All three entries must belong to the same linked list.
+ */
+static inline void list_bulk_move_tail(struct list_head *head,
+ struct list_head *first,
+ struct list_head *last)
+{
+ first->prev->next = last->next;
+ last->next->prev = first->prev;
+
+ head->prev->next = first;
+ first->prev = head->prev;
+
+ last->next = head;
+ head->prev = last;
+}
+
+/**
+ * list_is_first -- tests whether @list is the first entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_first(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->prev == head;
+}
+
+/**
* list_is_last - tests whether @list is the last entry in list @head
* @list: the entry to test
* @head: the head of the list
@@ -189,7 +279,7 @@ static inline int list_is_last(const struct list_head *list,
*/
static inline int list_empty(const struct list_head *head)
{
- return head->next == head;
+ return READ_ONCE(head->next) == head;
}
/**
@@ -212,6 +302,38 @@ static inline int list_empty_careful(const struct list_head *head)
}
/**
+ * list_rotate_left - rotate the list to the left
+ * @head: the head of the list
+ */
+static inline void list_rotate_left(struct list_head *head)
+{
+ struct list_head *first;
+
+ if (!list_empty(head)) {
+ first = head->next;
+ list_move_tail(first, head);
+ }
+}
+
+/**
+ * list_rotate_to_front() - Rotate list to specific item.
+ * @list: The desired new front of the list.
+ * @head: The head of the list.
+ *
+ * Rotates list so that @list becomes the new front of the list.
+ */
+static inline void list_rotate_to_front(struct list_head *list,
+ struct list_head *head)
+{
+ /*
+ * Deletes the list head from the list denoted by @head and
+ * places it as the tail of @list, this effectively rotates the
+ * list so that @list is at the front.
+ */
+ list_move_tail(head, list);
+}
+
+/**
* list_is_singular - tests whether a list has just one entry.
* @head: the list to test.
*/
@@ -220,29 +342,112 @@ static inline int list_is_singular(const struct list_head *head)
return !list_empty(head) && (head->next == head->prev);
}
-static inline void __list_splice(struct list_head *list,
- struct list_head *head)
+static inline void __list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ struct list_head *new_first = entry->next;
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ * and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ INIT_LIST_HEAD(list);
+ else
+ __list_cut_position(list, head, entry);
+}
+
+/**
+ * list_cut_before - cut a list into two, before given entry
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ *
+ * This helper moves the initial part of @head, up to but
+ * excluding @entry, from @head to @list. You should pass
+ * in @entry an element you know is on @head. @list should
+ * be an empty list or a list you do not care about losing
+ * its data.
+ * If @entry == @head, all entries on @head are moved to
+ * @list.
+ */
+static inline void list_cut_before(struct list_head *list,
+ struct list_head *head,
+ struct list_head *entry)
+{
+ if (head->next == entry) {
+ INIT_LIST_HEAD(list);
+ return;
+ }
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry->prev;
+ list->prev->next = list;
+ head->next = entry;
+ entry->prev = head;
+}
+
+static inline void __list_splice(const struct list_head *list,
+ struct list_head *prev,
+ struct list_head *next)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
- struct list_head *at = head->next;
- first->prev = head;
- head->next = first;
+ first->prev = prev;
+ prev->next = first;
- last->next = at;
- at->prev = last;
+ last->next = next;
+ next->prev = last;
}
/**
- * list_splice - join two lists
+ * list_splice - join two lists, this is designed for stacks
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
-static inline void list_splice(struct list_head *list, struct list_head *head)
+static inline void list_splice(const struct list_head *list,
+ struct list_head *head)
{
if (!list_empty(list))
- __list_splice(list, head);
+ __list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
}
/**
@@ -256,7 +461,24 @@ static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
- __list_splice(list, head);
+ __list_splice(list, head, head->next);
+ INIT_LIST_HEAD(list);
+ }
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
INIT_LIST_HEAD(list);
}
}
@@ -265,7 +487,7 @@ static inline void list_splice_init(struct list_head *list,
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*/
#define list_entry(ptr, type, member) \
container_of(ptr, type, member)
@@ -274,7 +496,7 @@ static inline void list_splice_init(struct list_head *list,
* list_first_entry - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
@@ -283,25 +505,44 @@ static inline void list_splice_init(struct list_head *list,
/**
* list_last_entry - get the last element from a list
- * @head: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_head within the struct.
*
* Note, that list is expected to be not empty.
*/
-#define list_last_entry(head, type, member) \
- list_entry((head)->prev, type, member)
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
/**
* list_first_entry_or_null - get the first element from a list
* @ptr: the list head to take the element from.
* @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Note that if the list is empty, it returns NULL.
*/
-#define list_first_entry_or_null(ptr, type, member) \
- (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+#define list_first_entry_or_null(ptr, type, member) ({ \
+ struct list_head *head__ = (ptr); \
+ struct list_head *pos__ = READ_ONCE(head__->next); \
+ pos__ != head__ ? list_entry(pos__, type, member) : NULL; \
+})
+
+/**
+ * list_next_entry - get the next element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_next_entry(pos, member) \
+ list_entry((pos)->member.next, typeof(*(pos)), member)
+
+/**
+ * list_prev_entry - get the prev element in list
+ * @pos: the type * to cursor
+ * @member: the name of the list_head within the struct.
+ */
+#define list_prev_entry(pos, member) \
+ list_entry((pos)->member.prev, typeof(*(pos)), member)
/**
* list_for_each - iterate over a list
@@ -309,21 +550,17 @@ static inline void list_splice_init(struct list_head *list,
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
- for (pos = (head)->next; prefetch(pos->next), pos != (head); \
- pos = pos->next)
+ for (pos = (head)->next; pos != (head); pos = pos->next)
/**
- * __list_for_each - iterate over a list
+ * list_for_each_continue - continue iteration over a list
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
*
- * This variant differs from list_for_each() in that it's the
- * simplest possible list iteration code, no prefetching is done.
- * Use this for code that knows the list to be very short (empty
- * or 1 entry) most of the time.
+ * Continue to iterate over a list, continuing after the current position.
*/
-#define __list_for_each(pos, head) \
- for (pos = (head)->next; pos != (head); pos = pos->next)
+#define list_for_each_continue(pos, head) \
+ for (pos = pos->next; pos != (head); pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
@@ -331,8 +568,7 @@ static inline void list_splice_init(struct list_head *list,
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
- for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \
- pos = pos->prev)
+ for (pos = (head)->prev; pos != (head); pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
@@ -345,32 +581,43 @@ static inline void list_splice_init(struct list_head *list,
pos = n, n = pos->next)
/**
+ * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
+ * @pos: the &struct list_head to use as a loop cursor.
+ * @n: another &struct list_head to use as temporary storage
+ * @head: the head for your list.
+ */
+#define list_for_each_prev_safe(pos, n, head) \
+ for (pos = (head)->prev, n = pos->prev; \
+ pos != (head); \
+ pos = n, n = pos->prev)
+
+/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*/
#define list_for_each_entry(pos, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
+ for (pos = list_first_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
/**
* list_for_each_entry_reverse - iterate backwards over list of given type.
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_reverse(pos, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member); \
- prefetch(pos->member.prev), &pos->member != (head); \
- pos = list_entry(pos->member.prev, typeof(*pos), member))
+ for (pos = list_last_entry(head, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_prev_entry(pos, member))
/**
* list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
* @pos: the type * to use as a start point
* @head: the head of the list
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Prepares a pos entry for use as a start point in list_for_each_entry_continue().
*/
@@ -381,87 +628,129 @@ static inline void list_splice_init(struct list_head *list,
* list_for_each_entry_continue - continue iteration over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Continue to iterate over list of given type, continuing after
* the current position.
*/
#define list_for_each_entry_continue(pos, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member); \
- prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
+ for (pos = list_next_entry(pos, member); \
+ &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_prev_entry(pos, member); \
+ &pos->member != (head); \
+ pos = list_prev_entry(pos, member))
/**
* list_for_each_entry_from - iterate over list of given type from the current point
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing from current position.
*/
#define list_for_each_entry_from(pos, head, member) \
- for (; prefetch(pos->member.next), &pos->member != (head); \
- pos = list_entry(pos->member.next, typeof(*pos), member))
+ for (; &pos->member != (head); \
+ pos = list_next_entry(pos, member))
+
+/**
+ * list_for_each_entry_from_reverse - iterate backwards over list of given type
+ * from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_head within the struct.
+ *
+ * Iterate backwards over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from_reverse(pos, head, member) \
+ for (; &pos->member != (head); \
+ pos = list_prev_entry(pos, member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
- for (pos = list_entry((head)->next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
+ for (pos = list_first_entry(head, typeof(*pos), member), \
+ n = list_next_entry(pos, member); \
&pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
+ pos = n, n = list_next_entry(n, member))
/**
- * list_for_each_entry_safe_continue
+ * list_for_each_entry_safe_continue - continue list iteration safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Iterate over list of given type, continuing after current point,
* safe against removal of list entry.
*/
#define list_for_each_entry_safe_continue(pos, n, head, member) \
- for (pos = list_entry(pos->member.next, typeof(*pos), member), \
- n = list_entry(pos->member.next, typeof(*pos), member); \
+ for (pos = list_next_entry(pos, member), \
+ n = list_next_entry(pos, member); \
&pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
+ pos = n, n = list_next_entry(n, member))
/**
- * list_for_each_entry_safe_from
+ * list_for_each_entry_safe_from - iterate over list from current point safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Iterate over list of given type from current point, safe against
* removal of list entry.
*/
#define list_for_each_entry_safe_from(pos, n, head, member) \
- for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ for (n = list_next_entry(pos, member); \
&pos->member != (head); \
- pos = n, n = list_entry(n->member.next, typeof(*n), member))
+ pos = n, n = list_next_entry(n, member))
/**
- * list_for_each_entry_safe_reverse
+ * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
* @pos: the type * to use as a loop cursor.
* @n: another type * to use as temporary storage
* @head: the head for your list.
- * @member: the name of the list_struct within the struct.
+ * @member: the name of the list_head within the struct.
*
* Iterate backwards over list of given type, safe against removal
* of list entry.
*/
#define list_for_each_entry_safe_reverse(pos, n, head, member) \
- for (pos = list_entry((head)->prev, typeof(*pos), member), \
- n = list_entry(pos->member.prev, typeof(*pos), member); \
+ for (pos = list_last_entry(head, typeof(*pos), member), \
+ n = list_prev_entry(pos, member); \
&pos->member != (head); \
- pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+ pos = n, n = list_prev_entry(n, member))
+
+/**
+ * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
+ * @pos: the loop cursor used in the list_for_each_entry_safe loop
+ * @n: temporary storage used in list_for_each_entry_safe
+ * @member: the name of the list_head within the struct.
+ *
+ * list_safe_reset_next is not safe to use in general if the list may be
+ * modified concurrently (eg. the lock is dropped in the loop body). An
+ * exception to this is if the cursor element (pos) is pinned in the list,
+ * and list_safe_reset_next is called after re-taking the lock and before
+ * completing the current iteration of the loop body.
+ */
+#define list_safe_reset_next(pos, n, member) \
+ n = list_next_entry(pos, member)
/**
* list_add_sort - add a new entry to a sorted list
@@ -473,7 +762,7 @@ static inline void list_splice_init(struct list_head *list,
* This is useful for implementing queues.
*/
static inline void list_add_sort(struct list_head *new, struct list_head *head,
- int (*compare)(struct list_head *a, struct list_head *b))
+ int (*compare)(struct list_head *a, struct list_head *b))
{
struct list_head *pos, *insert = head;
@@ -494,14 +783,6 @@ static inline void list_add_sort(struct list_head *new, struct list_head *head,
* You lose the ability to access the tail in O(1).
*/
-struct hlist_head {
- struct hlist_node *first;
-};
-
-struct hlist_node {
- struct hlist_node *next, **pprev;
-};
-
#define HLIST_HEAD_INIT { .first = NULL }
#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
#define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
@@ -511,25 +792,58 @@ static inline void INIT_HLIST_NODE(struct hlist_node *h)
h->pprev = NULL;
}
+/**
+ * hlist_unhashed - Has node been removed from list and reinitialized?
+ * @h: Node to be checked
+ *
+ * Not that not all removal functions will leave a node in unhashed
+ * state. For example, hlist_nulls_del_init_rcu() does leave the
+ * node in unhashed state, but hlist_nulls_del() does not.
+ */
static inline int hlist_unhashed(const struct hlist_node *h)
{
return !h->pprev;
}
+/**
+ * hlist_unhashed_lockless - Version of hlist_unhashed for lockless use
+ * @h: Node to be checked
+ *
+ * This variant of hlist_unhashed() must be used in lockless contexts
+ * to avoid potential load-tearing. The READ_ONCE() is paired with the
+ * various WRITE_ONCE() in hlist helpers that are defined below.
+ */
+static inline int hlist_unhashed_lockless(const struct hlist_node *h)
+{
+ return !READ_ONCE(h->pprev);
+}
+
+/**
+ * hlist_empty - Is the specified hlist_head structure an empty hlist?
+ * @h: Structure to check.
+ */
static inline int hlist_empty(const struct hlist_head *h)
{
- return !h->first;
+ return !READ_ONCE(h->first);
}
static inline void __hlist_del(struct hlist_node *n)
{
struct hlist_node *next = n->next;
struct hlist_node **pprev = n->pprev;
- *pprev = next;
+
+ WRITE_ONCE(*pprev, next);
if (next)
- next->pprev = pprev;
+ WRITE_ONCE(next->pprev, pprev);
}
+/**
+ * hlist_del - Delete the specified hlist_node from its list
+ * @n: Node to delete.
+ *
+ * Note that this function leaves the node in hashed state. Use
+ * hlist_del_init() or similar instead to unhash @n.
+ */
static inline void hlist_del(struct hlist_node *n)
{
__hlist_del(n);
@@ -537,6 +851,12 @@ static inline void hlist_del(struct hlist_node *n)
n->pprev = LIST_POISON2;
}
+/**
+ * hlist_del_init - Delete the specified hlist_node from its list and initialize
+ * @n: Node to delete.
+ *
+ * Note that this function leaves the node in unhashed state.
+ */
static inline void hlist_del_init(struct hlist_node *n)
{
if (!hlist_unhashed(n)) {
@@ -545,95 +865,161 @@ static inline void hlist_del_init(struct hlist_node *n)
}
}
+/**
+ * hlist_add_head - add a new entry at the beginning of the hlist
+ * @n: new entry to be added
+ * @h: hlist head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
{
struct hlist_node *first = h->first;
- n->next = first;
+ WRITE_ONCE(n->next, first);
if (first)
- first->pprev = &n->next;
- h->first = n;
- n->pprev = &h->first;
+ WRITE_ONCE(first->pprev, &n->next);
+ WRITE_ONCE(h->first, n);
+ WRITE_ONCE(n->pprev, &h->first);
}
-/* next must be != NULL */
+/**
+ * hlist_add_before - add a new entry before the one specified
+ * @n: new entry to be added
+ * @next: hlist node to add it before, which must be non-NULL
+ */
static inline void hlist_add_before(struct hlist_node *n,
- struct hlist_node *next)
+ struct hlist_node *next)
{
- n->pprev = next->pprev;
- n->next = next;
- next->pprev = &n->next;
- *(n->pprev) = n;
+ WRITE_ONCE(n->pprev, next->pprev);
+ WRITE_ONCE(n->next, next);
+ WRITE_ONCE(next->pprev, &n->next);
+ WRITE_ONCE(*(n->pprev), n);
}
-static inline void hlist_add_after(struct hlist_node *n,
- struct hlist_node *next)
+/**
+ * hlist_add_behing - add a new entry after the one specified
+ * @n: new entry to be added
+ * @prev: hlist node to add it after, which must be non-NULL
+ */
+static inline void hlist_add_behind(struct hlist_node *n,
+ struct hlist_node *prev)
{
- next->next = n->next;
- n->next = next;
- next->pprev = &n->next;
+ WRITE_ONCE(n->next, prev->next);
+ WRITE_ONCE(prev->next, n);
+ WRITE_ONCE(n->pprev, &prev->next);
- if(next->next)
- next->next->pprev = &next->next;
+ if (n->next)
+ WRITE_ONCE(n->next->pprev, &n->next);
+}
+
+/**
+ * hlist_add_fake - create a fake hlist consisting of a single headless node
+ * @n: Node to make a fake list out of
+ *
+ * This makes @n appear to be its own predecessor on a headless hlist.
+ * The point of this is to allow things like hlist_del() to work correctly
+ * in cases where there is no list.
+ */
+static inline void hlist_add_fake(struct hlist_node *n)
+{
+ n->pprev = &n->next;
+}
+
+/**
+ * hlist_fake: Is this node a fake hlist?
+ * @h: Node to check for being a self-referential fake hlist.
+ */
+static inline bool hlist_fake(struct hlist_node *h)
+{
+ return h->pprev == &h->next;
+}
+
+/**
+ * hlist_is_singular_node - is node the only element of the specified hlist?
+ * @n: Node to check for singularity.
+ * @h: Header for potentially singular list.
+ *
+ * Check whether the node is the only node of the head without
+ * accessing head, thus avoiding unnecessary cache misses.
+ */
+static inline bool
+hlist_is_singular_node(struct hlist_node *n, struct hlist_head *h)
+{
+ return !n->next && n->pprev == &h->first;
+}
+
+/**
+ * hlist_move_list - Move an hlist
+ * @old: hlist_head for old list.
+ * @new: hlist_head for new list.
+ *
+ * Move a list from one list head to another. Fixup the pprev
+ * reference of the first entry if it exists.
+ */
+static inline void hlist_move_list(struct hlist_head *old,
+ struct hlist_head *new)
+{
+ new->first = old->first;
+ if (new->first)
+ new->first->pprev = &new->first;
+ old->first = NULL;
}
#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
#define hlist_for_each(pos, head) \
- for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
- pos = pos->next)
+ for (pos = (head)->first; pos ; pos = pos->next)
#define hlist_for_each_safe(pos, n, head) \
for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
pos = n)
+#define hlist_entry_safe(ptr, type, member) \
+ ({ typeof(ptr) ____ptr = (ptr); \
+ ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+ })
+
/**
* hlist_for_each_entry - iterate over list of given type
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
+ * @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry(tpos, pos, head, member) \
- for (pos = (head)->first; \
- pos && ({ prefetch(pos->next); 1;}) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = pos->next)
+#define hlist_for_each_entry(pos, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
/**
* hlist_for_each_entry_continue - iterate over a hlist continuing after current point
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
+ * @pos: the type * to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry_continue(tpos, pos, member) \
- for (pos = (pos)->next; \
- pos && ({ prefetch(pos->next); 1;}) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = pos->next)
+#define hlist_for_each_entry_continue(pos, member) \
+ for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);\
+ pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
/**
* hlist_for_each_entry_from - iterate over a hlist continuing from current point
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
+ * @pos: the type * to use as a loop cursor.
* @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry_from(tpos, pos, member) \
- for (; pos && ({ prefetch(pos->next); 1;}) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = pos->next)
+#define hlist_for_each_entry_from(pos, member) \
+ for (; pos; \
+ pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
/**
* hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
- * @tpos: the type * to use as a loop cursor.
- * @pos: the &struct hlist_node to use as a loop cursor.
- * @n: another &struct hlist_node to use as temporary storage
+ * @pos: the type * to use as a loop cursor.
+ * @n: a &struct hlist_node to use as temporary storage
* @head: the head for your list.
* @member: the name of the hlist_node within the struct.
*/
-#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
- for (pos = (head)->first; \
- pos && ({ n = pos->next; 1; }) && \
- ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
- pos = n)
+#define hlist_for_each_entry_safe(pos, n, head, member) \
+ for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);\
+ pos && ({ n = pos->member.next; 1; }); \
+ pos = hlist_entry_safe(n, typeof(*pos), member))
#endif
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/math64.h b/include/linux/math64.h
index 71dd6d7109..8537c0412d 100644
--- a/include/linux/math64.h
+++ b/include/linux/math64.h
@@ -1,15 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_MATH64_H
#define _LINUX_MATH64_H
#include <linux/types.h>
+#include <linux/compiler.h>
#include <asm-generic/div64.h>
#if BITS_PER_LONG == 64
-#define div64_long(x,y) div64_s64((x),(y))
+#define div64_long(x, y) div64_s64((x), (y))
+#define div64_ul(x, y) div64_u64((x), (y))
/**
* div_u64_rem - unsigned 64bit divide with 32bit divisor with remainder
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 32bit divisor
+ * @remainder: pointer to unsigned 32bit remainder
+ *
+ * Return: sets ``*remainder``, then returns dividend / divisor
*
* This is commonly provided by 32bit archs to provide an optimized 64bit
* divide.
@@ -20,8 +28,13 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
return dividend / divisor;
}
-/**
+/*
* div_s64_rem - signed 64bit divide with 32bit divisor with remainder
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
+ * @remainder: pointer to signed 32bit remainder
+ *
+ * Return: sets ``*remainder``, then returns dividend / divisor
*/
static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
{
@@ -29,16 +42,38 @@ static inline s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder)
return dividend / divisor;
}
-/**
+/*
+ * div64_u64_rem - unsigned 64bit divide with 64bit divisor and remainder
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ * @remainder: pointer to unsigned 64bit remainder
+ *
+ * Return: sets ``*remainder``, then returns dividend / divisor
+ */
+static inline u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder)
+{
+ *remainder = dividend % divisor;
+ return dividend / divisor;
+}
+
+/*
* div64_u64 - unsigned 64bit divide with 64bit divisor
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ *
+ * Return: dividend / divisor
*/
static inline u64 div64_u64(u64 dividend, u64 divisor)
{
return dividend / divisor;
}
-/**
+/*
* div64_s64 - signed 64bit divide with 64bit divisor
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 64bit divisor
+ *
+ * Return: dividend / divisor
*/
static inline s64 div64_s64(s64 dividend, s64 divisor)
{
@@ -47,7 +82,8 @@ static inline s64 div64_s64(s64 dividend, s64 divisor)
#elif BITS_PER_LONG == 32
-#define div64_long(x,y) div_s64((x),(y))
+#define div64_long(x, y) div_s64((x), (y))
+#define div64_ul(x, y) div_u64((x), (y))
#ifndef div_u64_rem
static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
@@ -61,6 +97,10 @@ static inline u64 div_u64_rem(u64 dividend, u32 divisor, u32 *remainder)
extern s64 div_s64_rem(s64 dividend, s32 divisor, s32 *remainder);
#endif
+#ifndef div64_u64_rem
+extern u64 div64_u64_rem(u64 dividend, u64 divisor, u64 *remainder);
+#endif
+
#ifndef div64_u64
extern u64 div64_u64(u64 dividend, u64 divisor);
#endif
@@ -73,6 +113,8 @@ extern s64 div64_s64(s64 dividend, s64 divisor);
/**
* div_u64 - unsigned 64bit divide with 32bit divisor
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 32bit divisor
*
* This is the most common 64bit divide and should be used if possible,
* as many 32bit archs can optimize this variant better than a full 64bit
@@ -88,6 +130,8 @@ static inline u64 div_u64(u64 dividend, u32 divisor)
/**
* div_s64 - signed 64bit divide with 32bit divisor
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
*/
#ifndef div_s64
static inline s64 div_s64(s64 dividend, s32 divisor)
@@ -99,6 +143,164 @@ static inline s64 div_s64(s64 dividend, s32 divisor)
u32 iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder);
+#ifndef mul_u32_u32
+/*
+ * Many a GCC version messes this up and generates a 64x64 mult :-(
+ */
+static inline u64 mul_u32_u32(u32 a, u32 b)
+{
+ return (u64)a * b;
+}
+#endif
+
+#if defined(CONFIG_ARCH_SUPPORTS_INT128) && defined(__SIZEOF_INT128__)
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+ return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 mul, unsigned int shift)
+{
+ return (u64)(((unsigned __int128)a * mul) >> shift);
+}
+#endif /* mul_u64_u64_shr */
+
+#else
+
+#ifndef mul_u64_u32_shr
+static inline u64 mul_u64_u32_shr(u64 a, u32 mul, unsigned int shift)
+{
+ u32 ah, al;
+ u64 ret;
+
+ al = a;
+ ah = a >> 32;
+
+ ret = mul_u32_u32(al, mul) >> shift;
+ if (ah)
+ ret += mul_u32_u32(ah, mul) << (32 - shift);
+
+ return ret;
+}
+#endif /* mul_u64_u32_shr */
+
+#ifndef mul_u64_u64_shr
+static inline u64 mul_u64_u64_shr(u64 a, u64 b, unsigned int shift)
+{
+ union {
+ u64 ll;
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 high, low;
+#else
+ u32 low, high;
+#endif
+ } l;
+ } rl, rm, rn, rh, a0, b0;
+ u64 c;
+
+ a0.ll = a;
+ b0.ll = b;
+
+ rl.ll = mul_u32_u32(a0.l.low, b0.l.low);
+ rm.ll = mul_u32_u32(a0.l.low, b0.l.high);
+ rn.ll = mul_u32_u32(a0.l.high, b0.l.low);
+ rh.ll = mul_u32_u32(a0.l.high, b0.l.high);
+
+ /*
+ * Each of these lines computes a 64-bit intermediate result into "c",
+ * starting at bits 32-95. The low 32-bits go into the result of the
+ * multiplication, the high 32-bits are carried into the next step.
+ */
+ rl.l.high = c = (u64)rl.l.high + rm.l.low + rn.l.low;
+ rh.l.low = c = (c >> 32) + rm.l.high + rn.l.high + rh.l.low;
+ rh.l.high = (c >> 32) + rh.l.high;
+
+ /*
+ * The 128-bit result of the multiplication is in rl.ll and rh.ll,
+ * shift it right and throw away the high part of the result.
+ */
+ if (shift == 0)
+ return rl.ll;
+ if (shift < 64)
+ return (rl.ll >> shift) | (rh.ll << (64 - shift));
+ return rh.ll >> (shift & 63);
+}
+#endif /* mul_u64_u64_shr */
+
+#endif
+
+#ifndef mul_u64_u32_div
+static inline u64 mul_u64_u32_div(u64 a, u32 mul, u32 divisor)
+{
+ union {
+ u64 ll;
+ struct {
+#ifdef __BIG_ENDIAN
+ u32 high, low;
+#else
+ u32 low, high;
+#endif
+ } l;
+ } u, rl, rh;
+
+ u.ll = a;
+ rl.ll = mul_u32_u32(u.l.low, mul);
+ rh.ll = mul_u32_u32(u.l.high, mul) + rl.l.high;
+
+ /* Bits 32-63 of the result will be in rh.l.low. */
+ rl.l.high = do_div(rh.ll, divisor);
+
+ /* Bits 0-31 of the result will be in rl.l.low. */
+ do_div(rl.ll, divisor);
+
+ rl.l.high = rh.l.low;
+ return rl.ll;
+}
+#endif /* mul_u64_u32_div */
+
+u64 mul_u64_u64_div_u64(u64 a, u64 mul, u64 div);
+
+#define DIV64_U64_ROUND_UP(ll, d) \
+ ({ u64 _tmp = (d); div64_u64((ll) + _tmp - 1, _tmp); })
+
+/**
+ * DIV64_U64_ROUND_CLOSEST - unsigned 64bit divide with 64bit divisor rounded to nearest integer
+ * @dividend: unsigned 64bit dividend
+ * @divisor: unsigned 64bit divisor
+ *
+ * Divide unsigned 64bit dividend by unsigned 64bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV64_U64_ROUND_CLOSEST(dividend, divisor) \
+ ({ u64 _tmp = (divisor); div64_u64((dividend) + _tmp / 2, _tmp); })
+
+/*
+ * DIV_S64_ROUND_CLOSEST - signed 64bit divide with 32bit divisor rounded to nearest integer
+ * @dividend: signed 64bit dividend
+ * @divisor: signed 32bit divisor
+ *
+ * Divide signed 64bit dividend by signed 32bit divisor
+ * and round to closest integer.
+ *
+ * Return: dividend / divisor rounded to nearest integer
+ */
+#define DIV_S64_ROUND_CLOSEST(dividend, divisor)( \
+{ \
+ s64 __x = (dividend); \
+ s32 __d = (divisor); \
+ ((__x > 0) == (__d > 0)) ? \
+ div_s64((__x + (__d / 2)), __d) : \
+ div_s64((__x - (__d / 2)), __d); \
+} \
+)
+
static __always_inline u32
__iter_div_u64_rem(u64 dividend, u32 divisor, u64 *remainder)
{
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
new file mode 100644
index 0000000000..c441a074ec
--- /dev/null
+++ b/include/linux/mdio.h
@@ -0,0 +1,344 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * linux/mdio.h: definitions for MDIO (clause 45) transceivers
+ * Copyright 2006-2009 Solarflare Communications Inc.
+ *
+ * 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, incorporated herein by reference.
+ */
+
+#ifndef _UAPI__LINUX_MDIO_H__
+#define _UAPI__LINUX_MDIO_H__
+
+#include <linux/types.h>
+#include <linux/mii.h>
+#include <init.h>
+
+/* MDIO Manageable Devices (MMDs). */
+#define MDIO_MMD_PMAPMD 1 /* Physical Medium Attachment/
+ * Physical Medium Dependent */
+#define MDIO_MMD_WIS 2 /* WAN Interface Sublayer */
+#define MDIO_MMD_PCS 3 /* Physical Coding Sublayer */
+#define MDIO_MMD_PHYXS 4 /* PHY Extender Sublayer */
+#define MDIO_MMD_DTEXS 5 /* DTE Extender Sublayer */
+#define MDIO_MMD_TC 6 /* Transmission Convergence */
+#define MDIO_MMD_AN 7 /* Auto-Negotiation */
+#define MDIO_MMD_C22EXT 29 /* Clause 22 extension */
+#define MDIO_MMD_VEND1 30 /* Vendor specific 1 */
+#define MDIO_MMD_VEND2 31 /* Vendor specific 2 */
+
+/* Generic MDIO registers. */
+#define MDIO_CTRL1 MII_BMCR
+#define MDIO_STAT1 MII_BMSR
+#define MDIO_DEVID1 MII_PHYSID1
+#define MDIO_DEVID2 MII_PHYSID2
+#define MDIO_SPEED 4 /* Speed ability */
+#define MDIO_DEVS1 5 /* Devices in package */
+#define MDIO_DEVS2 6
+#define MDIO_CTRL2 7 /* 10G control 2 */
+#define MDIO_STAT2 8 /* 10G status 2 */
+#define MDIO_PMA_TXDIS 9 /* 10G PMA/PMD transmit disable */
+#define MDIO_PMA_RXDET 10 /* 10G PMA/PMD receive signal detect */
+#define MDIO_PMA_EXTABLE 11 /* 10G PMA/PMD extended ability */
+#define MDIO_PKGID1 14 /* Package identifier */
+#define MDIO_PKGID2 15
+#define MDIO_AN_ADVERTISE 16 /* AN advertising (base page) */
+#define MDIO_AN_LPA 19 /* AN LP abilities (base page) */
+#define MDIO_PCS_EEE_ABLE 20 /* EEE Capability register */
+#define MDIO_PCS_EEE_ABLE2 21 /* EEE Capability register 2 */
+#define MDIO_PMA_NG_EXTABLE 21 /* 2.5G/5G PMA/PMD extended ability */
+#define MDIO_PCS_EEE_WK_ERR 22 /* EEE wake error counter */
+#define MDIO_PHYXS_LNSTAT 24 /* PHY XGXS lane state */
+#define MDIO_AN_EEE_ADV 60 /* EEE advertisement */
+#define MDIO_AN_EEE_LPABLE 61 /* EEE link partner ability */
+#define MDIO_AN_EEE_ADV2 62 /* EEE advertisement 2 */
+#define MDIO_AN_EEE_LPABLE2 63 /* EEE link partner ability 2 */
+
+/* Media-dependent registers. */
+#define MDIO_PMA_10GBT_SWAPPOL 130 /* 10GBASE-T pair swap & polarity */
+#define MDIO_PMA_10GBT_TXPWR 131 /* 10GBASE-T TX power control */
+#define MDIO_PMA_10GBT_SNR 133 /* 10GBASE-T SNR margin, lane A.
+ * Lanes B-D are numbered 134-136. */
+#define MDIO_PMA_10GBR_FECABLE 170 /* 10GBASE-R FEC ability */
+#define MDIO_PCS_10GBX_STAT1 24 /* 10GBASE-X PCS status 1 */
+#define MDIO_PCS_10GBRT_STAT1 32 /* 10GBASE-R/-T PCS status 1 */
+#define MDIO_PCS_10GBRT_STAT2 33 /* 10GBASE-R/-T PCS status 2 */
+#define MDIO_AN_10GBT_CTRL 32 /* 10GBASE-T auto-negotiation control */
+#define MDIO_AN_10GBT_STAT 33 /* 10GBASE-T auto-negotiation status */
+
+/* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */
+#define MDIO_PMA_LASI_RXCTRL 0x9000 /* RX_ALARM control */
+#define MDIO_PMA_LASI_TXCTRL 0x9001 /* TX_ALARM control */
+#define MDIO_PMA_LASI_CTRL 0x9002 /* LASI control */
+#define MDIO_PMA_LASI_RXSTAT 0x9003 /* RX_ALARM status */
+#define MDIO_PMA_LASI_TXSTAT 0x9004 /* TX_ALARM status */
+#define MDIO_PMA_LASI_STAT 0x9005 /* LASI status */
+
+/* Control register 1. */
+/* Enable extended speed selection */
+#define MDIO_CTRL1_SPEEDSELEXT (BMCR_SPEED1000 | BMCR_SPEED100)
+/* All speed selection bits */
+#define MDIO_CTRL1_SPEEDSEL (MDIO_CTRL1_SPEEDSELEXT | 0x003c)
+#define MDIO_CTRL1_FULLDPLX BMCR_FULLDPLX
+#define MDIO_CTRL1_LPOWER BMCR_PDOWN
+#define MDIO_CTRL1_RESET BMCR_RESET
+#define MDIO_PMA_CTRL1_LOOPBACK 0x0001
+#define MDIO_PMA_CTRL1_SPEED1000 BMCR_SPEED1000
+#define MDIO_PMA_CTRL1_SPEED100 BMCR_SPEED100
+#define MDIO_PCS_CTRL1_LOOPBACK BMCR_LOOPBACK
+#define MDIO_PHYXS_CTRL1_LOOPBACK BMCR_LOOPBACK
+#define MDIO_AN_CTRL1_RESTART BMCR_ANRESTART
+#define MDIO_AN_CTRL1_ENABLE BMCR_ANENABLE
+#define MDIO_AN_CTRL1_XNP 0x2000 /* Enable extended next page */
+#define MDIO_PCS_CTRL1_CLKSTOP_EN 0x400 /* Stop the clock during LPI */
+
+/* 10 Gb/s */
+#define MDIO_CTRL1_SPEED10G (MDIO_CTRL1_SPEEDSELEXT | 0x00)
+/* 10PASS-TS/2BASE-TL */
+#define MDIO_CTRL1_SPEED10P2B (MDIO_CTRL1_SPEEDSELEXT | 0x04)
+/* 2.5 Gb/s */
+#define MDIO_CTRL1_SPEED2_5G (MDIO_CTRL1_SPEEDSELEXT | 0x18)
+/* 5 Gb/s */
+#define MDIO_CTRL1_SPEED5G (MDIO_CTRL1_SPEEDSELEXT | 0x1c)
+
+/* Status register 1. */
+#define MDIO_STAT1_LPOWERABLE 0x0002 /* Low-power ability */
+#define MDIO_STAT1_LSTATUS BMSR_LSTATUS
+#define MDIO_STAT1_FAULT 0x0080 /* Fault */
+#define MDIO_AN_STAT1_LPABLE 0x0001 /* Link partner AN ability */
+#define MDIO_AN_STAT1_ABLE BMSR_ANEGCAPABLE
+#define MDIO_AN_STAT1_RFAULT BMSR_RFAULT
+#define MDIO_AN_STAT1_COMPLETE BMSR_ANEGCOMPLETE
+#define MDIO_AN_STAT1_PAGE 0x0040 /* Page received */
+#define MDIO_AN_STAT1_XNP 0x0080 /* Extended next page status */
+
+/* Speed register. */
+#define MDIO_SPEED_10G 0x0001 /* 10G capable */
+#define MDIO_PMA_SPEED_2B 0x0002 /* 2BASE-TL capable */
+#define MDIO_PMA_SPEED_10P 0x0004 /* 10PASS-TS capable */
+#define MDIO_PMA_SPEED_1000 0x0010 /* 1000M capable */
+#define MDIO_PMA_SPEED_100 0x0020 /* 100M capable */
+#define MDIO_PMA_SPEED_10 0x0040 /* 10M capable */
+#define MDIO_PCS_SPEED_10P2B 0x0002 /* 10PASS-TS/2BASE-TL capable */
+
+/* Device present registers. */
+#define MDIO_DEVS_PRESENT(devad) (1 << (devad))
+#define MDIO_DEVS_C22PRESENT MDIO_DEVS_PRESENT(0)
+#define MDIO_DEVS_PMAPMD MDIO_DEVS_PRESENT(MDIO_MMD_PMAPMD)
+#define MDIO_DEVS_WIS MDIO_DEVS_PRESENT(MDIO_MMD_WIS)
+#define MDIO_DEVS_PCS MDIO_DEVS_PRESENT(MDIO_MMD_PCS)
+#define MDIO_DEVS_PHYXS MDIO_DEVS_PRESENT(MDIO_MMD_PHYXS)
+#define MDIO_DEVS_DTEXS MDIO_DEVS_PRESENT(MDIO_MMD_DTEXS)
+#define MDIO_DEVS_TC MDIO_DEVS_PRESENT(MDIO_MMD_TC)
+#define MDIO_DEVS_AN MDIO_DEVS_PRESENT(MDIO_MMD_AN)
+#define MDIO_DEVS_C22EXT MDIO_DEVS_PRESENT(MDIO_MMD_C22EXT)
+#define MDIO_DEVS_VEND1 MDIO_DEVS_PRESENT(MDIO_MMD_VEND1)
+#define MDIO_DEVS_VEND2 MDIO_DEVS_PRESENT(MDIO_MMD_VEND2)
+
+/* Control register 2. */
+#define MDIO_PMA_CTRL2_TYPE 0x000f /* PMA/PMD type selection */
+#define MDIO_PMA_CTRL2_10GBCX4 0x0000 /* 10GBASE-CX4 type */
+#define MDIO_PMA_CTRL2_10GBEW 0x0001 /* 10GBASE-EW type */
+#define MDIO_PMA_CTRL2_10GBLW 0x0002 /* 10GBASE-LW type */
+#define MDIO_PMA_CTRL2_10GBSW 0x0003 /* 10GBASE-SW type */
+#define MDIO_PMA_CTRL2_10GBLX4 0x0004 /* 10GBASE-LX4 type */
+#define MDIO_PMA_CTRL2_10GBER 0x0005 /* 10GBASE-ER type */
+#define MDIO_PMA_CTRL2_10GBLR 0x0006 /* 10GBASE-LR type */
+#define MDIO_PMA_CTRL2_10GBSR 0x0007 /* 10GBASE-SR type */
+#define MDIO_PMA_CTRL2_10GBLRM 0x0008 /* 10GBASE-LRM type */
+#define MDIO_PMA_CTRL2_10GBT 0x0009 /* 10GBASE-T type */
+#define MDIO_PMA_CTRL2_10GBKX4 0x000a /* 10GBASE-KX4 type */
+#define MDIO_PMA_CTRL2_10GBKR 0x000b /* 10GBASE-KR type */
+#define MDIO_PMA_CTRL2_1000BT 0x000c /* 1000BASE-T type */
+#define MDIO_PMA_CTRL2_1000BKX 0x000d /* 1000BASE-KX type */
+#define MDIO_PMA_CTRL2_100BTX 0x000e /* 100BASE-TX type */
+#define MDIO_PMA_CTRL2_10BT 0x000f /* 10BASE-T type */
+#define MDIO_PMA_CTRL2_2_5GBT 0x0030 /* 2.5GBaseT type */
+#define MDIO_PMA_CTRL2_5GBT 0x0031 /* 5GBaseT type */
+#define MDIO_PCS_CTRL2_TYPE 0x0003 /* PCS type selection */
+#define MDIO_PCS_CTRL2_10GBR 0x0000 /* 10GBASE-R type */
+#define MDIO_PCS_CTRL2_10GBX 0x0001 /* 10GBASE-X type */
+#define MDIO_PCS_CTRL2_10GBW 0x0002 /* 10GBASE-W type */
+#define MDIO_PCS_CTRL2_10GBT 0x0003 /* 10GBASE-T type */
+
+/* Status register 2. */
+#define MDIO_STAT2_RXFAULT 0x0400 /* Receive fault */
+#define MDIO_STAT2_TXFAULT 0x0800 /* Transmit fault */
+#define MDIO_STAT2_DEVPRST 0xc000 /* Device present */
+#define MDIO_STAT2_DEVPRST_VAL 0x8000 /* Device present value */
+#define MDIO_PMA_STAT2_LBABLE 0x0001 /* PMA loopback ability */
+#define MDIO_PMA_STAT2_10GBEW 0x0002 /* 10GBASE-EW ability */
+#define MDIO_PMA_STAT2_10GBLW 0x0004 /* 10GBASE-LW ability */
+#define MDIO_PMA_STAT2_10GBSW 0x0008 /* 10GBASE-SW ability */
+#define MDIO_PMA_STAT2_10GBLX4 0x0010 /* 10GBASE-LX4 ability */
+#define MDIO_PMA_STAT2_10GBER 0x0020 /* 10GBASE-ER ability */
+#define MDIO_PMA_STAT2_10GBLR 0x0040 /* 10GBASE-LR ability */
+#define MDIO_PMA_STAT2_10GBSR 0x0080 /* 10GBASE-SR ability */
+#define MDIO_PMD_STAT2_TXDISAB 0x0100 /* PMD TX disable ability */
+#define MDIO_PMA_STAT2_EXTABLE 0x0200 /* Extended abilities */
+#define MDIO_PMA_STAT2_RXFLTABLE 0x1000 /* Receive fault ability */
+#define MDIO_PMA_STAT2_TXFLTABLE 0x2000 /* Transmit fault ability */
+#define MDIO_PCS_STAT2_10GBR 0x0001 /* 10GBASE-R capable */
+#define MDIO_PCS_STAT2_10GBX 0x0002 /* 10GBASE-X capable */
+#define MDIO_PCS_STAT2_10GBW 0x0004 /* 10GBASE-W capable */
+#define MDIO_PCS_STAT2_RXFLTABLE 0x1000 /* Receive fault ability */
+#define MDIO_PCS_STAT2_TXFLTABLE 0x2000 /* Transmit fault ability */
+
+/* Transmit disable register. */
+#define MDIO_PMD_TXDIS_GLOBAL 0x0001 /* Global PMD TX disable */
+#define MDIO_PMD_TXDIS_0 0x0002 /* PMD TX disable 0 */
+#define MDIO_PMD_TXDIS_1 0x0004 /* PMD TX disable 1 */
+#define MDIO_PMD_TXDIS_2 0x0008 /* PMD TX disable 2 */
+#define MDIO_PMD_TXDIS_3 0x0010 /* PMD TX disable 3 */
+
+/* Receive signal detect register. */
+#define MDIO_PMD_RXDET_GLOBAL 0x0001 /* Global PMD RX signal detect */
+#define MDIO_PMD_RXDET_0 0x0002 /* PMD RX signal detect 0 */
+#define MDIO_PMD_RXDET_1 0x0004 /* PMD RX signal detect 1 */
+#define MDIO_PMD_RXDET_2 0x0008 /* PMD RX signal detect 2 */
+#define MDIO_PMD_RXDET_3 0x0010 /* PMD RX signal detect 3 */
+
+/* Extended abilities register. */
+#define MDIO_PMA_EXTABLE_10GCX4 0x0001 /* 10GBASE-CX4 ability */
+#define MDIO_PMA_EXTABLE_10GBLRM 0x0002 /* 10GBASE-LRM ability */
+#define MDIO_PMA_EXTABLE_10GBT 0x0004 /* 10GBASE-T ability */
+#define MDIO_PMA_EXTABLE_10GBKX4 0x0008 /* 10GBASE-KX4 ability */
+#define MDIO_PMA_EXTABLE_10GBKR 0x0010 /* 10GBASE-KR ability */
+#define MDIO_PMA_EXTABLE_1000BT 0x0020 /* 1000BASE-T ability */
+#define MDIO_PMA_EXTABLE_1000BKX 0x0040 /* 1000BASE-KX ability */
+#define MDIO_PMA_EXTABLE_100BTX 0x0080 /* 100BASE-TX ability */
+#define MDIO_PMA_EXTABLE_10BT 0x0100 /* 10BASE-T ability */
+#define MDIO_PMA_EXTABLE_NBT 0x4000 /* 2.5/5GBASE-T ability */
+
+/* PHY XGXS lane state register. */
+#define MDIO_PHYXS_LNSTAT_SYNC0 0x0001
+#define MDIO_PHYXS_LNSTAT_SYNC1 0x0002
+#define MDIO_PHYXS_LNSTAT_SYNC2 0x0004
+#define MDIO_PHYXS_LNSTAT_SYNC3 0x0008
+#define MDIO_PHYXS_LNSTAT_ALIGN 0x1000
+
+/* PMA 10GBASE-T pair swap & polarity */
+#define MDIO_PMA_10GBT_SWAPPOL_ABNX 0x0001 /* Pair A/B uncrossed */
+#define MDIO_PMA_10GBT_SWAPPOL_CDNX 0x0002 /* Pair C/D uncrossed */
+#define MDIO_PMA_10GBT_SWAPPOL_AREV 0x0100 /* Pair A polarity reversed */
+#define MDIO_PMA_10GBT_SWAPPOL_BREV 0x0200 /* Pair B polarity reversed */
+#define MDIO_PMA_10GBT_SWAPPOL_CREV 0x0400 /* Pair C polarity reversed */
+#define MDIO_PMA_10GBT_SWAPPOL_DREV 0x0800 /* Pair D polarity reversed */
+
+/* PMA 10GBASE-T TX power register. */
+#define MDIO_PMA_10GBT_TXPWR_SHORT 0x0001 /* Short-reach mode */
+
+/* PMA 10GBASE-T SNR registers. */
+/* Value is SNR margin in dB, clamped to range [-127, 127], plus 0x8000. */
+#define MDIO_PMA_10GBT_SNR_BIAS 0x8000
+#define MDIO_PMA_10GBT_SNR_MAX 127
+
+/* PMA 10GBASE-R FEC ability register. */
+#define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */
+#define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */
+
+/* PCS 10GBASE-R/-T status register 1. */
+#define MDIO_PCS_10GBRT_STAT1_BLKLK 0x0001 /* Block lock attained */
+
+/* PCS 10GBASE-R/-T status register 2. */
+#define MDIO_PCS_10GBRT_STAT2_ERR 0x00ff
+#define MDIO_PCS_10GBRT_STAT2_BER 0x3f00
+
+/* AN 10GBASE-T control register. */
+#define MDIO_AN_10GBT_CTRL_ADV2_5G 0x0080 /* Advertise 2.5GBASE-T */
+#define MDIO_AN_10GBT_CTRL_ADV5G 0x0100 /* Advertise 5GBASE-T */
+#define MDIO_AN_10GBT_CTRL_ADV10G 0x1000 /* Advertise 10GBASE-T */
+
+/* AN 10GBASE-T status register. */
+#define MDIO_AN_10GBT_STAT_LP2_5G 0x0020 /* LP is 2.5GBT capable */
+#define MDIO_AN_10GBT_STAT_LP5G 0x0040 /* LP is 5GBT capable */
+#define MDIO_AN_10GBT_STAT_LPTRR 0x0200 /* LP training reset req. */
+#define MDIO_AN_10GBT_STAT_LPLTABLE 0x0400 /* LP loop timing ability */
+#define MDIO_AN_10GBT_STAT_LP10G 0x0800 /* LP is 10GBT capable */
+#define MDIO_AN_10GBT_STAT_REMOK 0x1000 /* Remote OK */
+#define MDIO_AN_10GBT_STAT_LOCOK 0x2000 /* Local OK */
+#define MDIO_AN_10GBT_STAT_MS 0x4000 /* Master/slave config */
+#define MDIO_AN_10GBT_STAT_MSFLT 0x8000 /* Master/slave config fault */
+
+/* EEE Supported/Advertisement/LP Advertisement registers.
+ *
+ * EEE capability Register (3.20), Advertisement (7.60) and
+ * Link partner ability (7.61) registers have and can use the same identical
+ * bit masks.
+ */
+#define MDIO_AN_EEE_ADV_100TX 0x0002 /* Advertise 100TX EEE cap */
+#define MDIO_AN_EEE_ADV_1000T 0x0004 /* Advertise 1000T EEE cap */
+/* Note: the two defines above can be potentially used by the user-land
+ * and cannot remove them now.
+ * So, we define the new generic MDIO_EEE_100TX and MDIO_EEE_1000T macros
+ * using the previous ones (that can be considered obsolete).
+ */
+#define MDIO_EEE_100TX MDIO_AN_EEE_ADV_100TX /* 100TX EEE cap */
+#define MDIO_EEE_1000T MDIO_AN_EEE_ADV_1000T /* 1000T EEE cap */
+#define MDIO_EEE_10GT 0x0008 /* 10GT EEE cap */
+#define MDIO_EEE_1000KX 0x0010 /* 1000KX EEE cap */
+#define MDIO_EEE_10GKX4 0x0020 /* 10G KX4 EEE cap */
+#define MDIO_EEE_10GKR 0x0040 /* 10G KR EEE cap */
+#define MDIO_EEE_40GR_FW 0x0100 /* 40G R fast wake */
+#define MDIO_EEE_40GR_DS 0x0200 /* 40G R deep sleep */
+#define MDIO_EEE_100GR_FW 0x1000 /* 100G R fast wake */
+#define MDIO_EEE_100GR_DS 0x2000 /* 100G R deep sleep */
+
+#define MDIO_EEE_2_5GT 0x0001 /* 2.5GT EEE cap */
+#define MDIO_EEE_5GT 0x0002 /* 5GT EEE cap */
+
+/* 2.5G/5G Extended abilities register. */
+#define MDIO_PMA_NG_EXTABLE_2_5GBT 0x0001 /* 2.5GBASET ability */
+#define MDIO_PMA_NG_EXTABLE_5GBT 0x0002 /* 5GBASET ability */
+
+/* LASI RX_ALARM control/status registers. */
+#define MDIO_PMA_LASI_RX_PHYXSLFLT 0x0001 /* PHY XS RX local fault */
+#define MDIO_PMA_LASI_RX_PCSLFLT 0x0008 /* PCS RX local fault */
+#define MDIO_PMA_LASI_RX_PMALFLT 0x0010 /* PMA/PMD RX local fault */
+#define MDIO_PMA_LASI_RX_OPTICPOWERFLT 0x0020 /* RX optical power fault */
+#define MDIO_PMA_LASI_RX_WISLFLT 0x0200 /* WIS local fault */
+
+/* LASI TX_ALARM control/status registers. */
+#define MDIO_PMA_LASI_TX_PHYXSLFLT 0x0001 /* PHY XS TX local fault */
+#define MDIO_PMA_LASI_TX_PCSLFLT 0x0008 /* PCS TX local fault */
+#define MDIO_PMA_LASI_TX_PMALFLT 0x0010 /* PMA/PMD TX local fault */
+#define MDIO_PMA_LASI_TX_LASERPOWERFLT 0x0080 /* Laser output power fault */
+#define MDIO_PMA_LASI_TX_LASERTEMPFLT 0x0100 /* Laser temperature fault */
+#define MDIO_PMA_LASI_TX_LASERBICURRFLT 0x0200 /* Laser bias current fault */
+
+/* LASI control/status registers. */
+#define MDIO_PMA_LASI_LSALARM 0x0001 /* LS_ALARM enable/status */
+#define MDIO_PMA_LASI_TXALARM 0x0002 /* TX_ALARM enable/status */
+#define MDIO_PMA_LASI_RXALARM 0x0004 /* RX_ALARM enable/status */
+
+/* Mapping between MDIO PRTAD/DEVAD and mii_ioctl_data::phy_id */
+
+#define MDIO_PHY_ID_C45 0x8000
+#define MDIO_PHY_ID_PRTAD 0x03e0
+#define MDIO_PHY_ID_DEVAD 0x001f
+#define MDIO_PHY_ID_C45_MASK \
+ (MDIO_PHY_ID_C45 | MDIO_PHY_ID_PRTAD | MDIO_PHY_ID_DEVAD)
+
+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
new file mode 100644
index 0000000000..35aa0681ba
--- /dev/null
+++ b/include/linux/mfd/stm32-timers.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) STMicroelectronics 2016
+ * Author: Benjamin Gaignard <benjamin.gaignard@st.com>
+ */
+
+#ifndef _LINUX_STM32_GPTIMER_H_
+#define _LINUX_STM32_GPTIMER_H_
+
+#include <clock.h>
+
+#define TIM_CR1 0x00 /* Control Register 1 */
+#define TIM_CR2 0x04 /* Control Register 2 */
+#define TIM_SMCR 0x08 /* Slave mode control reg */
+#define TIM_DIER 0x0C /* DMA/interrupt register */
+#define TIM_SR 0x10 /* Status register */
+#define TIM_EGR 0x14 /* Event Generation Reg */
+#define TIM_CCMR1 0x18 /* Capt/Comp 1 Mode Reg */
+#define TIM_CCMR2 0x1C /* Capt/Comp 2 Mode Reg */
+#define TIM_CCER 0x20 /* Capt/Comp Enable Reg */
+#define TIM_CNT 0x24 /* Counter */
+#define TIM_PSC 0x28 /* Prescaler */
+#define TIM_ARR 0x2c /* Auto-Reload Register */
+#define TIM_CCR1 0x34 /* Capt/Comp Register 1 */
+#define TIM_CCR2 0x38 /* Capt/Comp Register 2 */
+#define TIM_CCR3 0x3C /* Capt/Comp Register 3 */
+#define TIM_CCR4 0x40 /* Capt/Comp Register 4 */
+#define TIM_BDTR 0x44 /* Break and Dead-Time Reg */
+#define TIM_DCR 0x48 /* DMA control register */
+#define TIM_DMAR 0x4C /* DMA register for transfer */
+
+#define TIM_CR1_CEN BIT(0) /* Counter Enable */
+#define TIM_CR1_DIR BIT(4) /* Counter Direction */
+#define TIM_CR1_ARPE BIT(7) /* Auto-reload Preload Ena */
+#define TIM_CR2_MMS (BIT(4) | BIT(5) | BIT(6)) /* Master mode selection */
+#define TIM_CR2_MMS2 GENMASK(23, 20) /* Master mode selection 2 */
+#define TIM_SMCR_SMS (BIT(0) | BIT(1) | BIT(2)) /* Slave mode selection */
+#define TIM_SMCR_TS (BIT(4) | BIT(5) | BIT(6)) /* Trigger selection */
+#define TIM_DIER_UIE BIT(0) /* Update interrupt */
+#define TIM_DIER_UDE BIT(8) /* Update DMA request Enable */
+#define TIM_DIER_CC1DE BIT(9) /* CC1 DMA request Enable */
+#define TIM_DIER_CC2DE BIT(10) /* CC2 DMA request Enable */
+#define TIM_DIER_CC3DE BIT(11) /* CC3 DMA request Enable */
+#define TIM_DIER_CC4DE BIT(12) /* CC4 DMA request Enable */
+#define TIM_DIER_COMDE BIT(13) /* COM DMA request Enable */
+#define TIM_DIER_TDE BIT(14) /* Trigger DMA request Enable */
+#define TIM_SR_UIF BIT(0) /* Update interrupt flag */
+#define TIM_EGR_UG BIT(0) /* Update Generation */
+#define TIM_CCMR_PE BIT(3) /* Channel Preload Enable */
+#define TIM_CCMR_M1 (BIT(6) | BIT(5)) /* Channel PWM Mode 1 */
+#define TIM_CCMR_CC1S (BIT(0) | BIT(1)) /* Capture/compare 1 sel */
+#define TIM_CCMR_IC1PSC GENMASK(3, 2) /* Input capture 1 prescaler */
+#define TIM_CCMR_CC2S (BIT(8) | BIT(9)) /* Capture/compare 2 sel */
+#define TIM_CCMR_IC2PSC GENMASK(11, 10) /* Input capture 2 prescaler */
+#define TIM_CCMR_CC1S_TI1 BIT(0) /* IC1/IC3 selects TI1/TI3 */
+#define TIM_CCMR_CC1S_TI2 BIT(1) /* IC1/IC3 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI2 BIT(8) /* IC2/IC4 selects TI2/TI4 */
+#define TIM_CCMR_CC2S_TI1 BIT(9) /* IC2/IC4 selects TI1/TI3 */
+#define TIM_CCER_CC1E BIT(0) /* Capt/Comp 1 out Ena */
+#define TIM_CCER_CC1P BIT(1) /* Capt/Comp 1 Polarity */
+#define TIM_CCER_CC1NE BIT(2) /* Capt/Comp 1N out Ena */
+#define TIM_CCER_CC1NP BIT(3) /* Capt/Comp 1N Polarity */
+#define TIM_CCER_CC2E BIT(4) /* Capt/Comp 2 out Ena */
+#define TIM_CCER_CC2P BIT(5) /* Capt/Comp 2 Polarity */
+#define TIM_CCER_CC3E BIT(8) /* Capt/Comp 3 out Ena */
+#define TIM_CCER_CC3P BIT(9) /* Capt/Comp 3 Polarity */
+#define TIM_CCER_CC4E BIT(12) /* Capt/Comp 4 out Ena */
+#define TIM_CCER_CC4P BIT(13) /* Capt/Comp 4 Polarity */
+#define TIM_CCER_CCXE (BIT(0) | BIT(4) | BIT(8) | BIT(12))
+#define TIM_BDTR_BKE BIT(12) /* Break input enable */
+#define TIM_BDTR_BKP BIT(13) /* Break input polarity */
+#define TIM_BDTR_AOE BIT(14) /* Automatic Output Enable */
+#define TIM_BDTR_MOE BIT(15) /* Main Output Enable */
+#define TIM_BDTR_BKF (BIT(16) | BIT(17) | BIT(18) | BIT(19))
+#define TIM_BDTR_BK2F (BIT(20) | BIT(21) | BIT(22) | BIT(23))
+#define TIM_BDTR_BK2E BIT(24) /* Break 2 input enable */
+#define TIM_BDTR_BK2P BIT(25) /* Break 2 input polarity */
+#define TIM_DCR_DBA GENMASK(4, 0) /* DMA base addr */
+#define TIM_DCR_DBL GENMASK(12, 8) /* DMA burst len */
+
+#define MAX_TIM_PSC 0xFFFF
+#define MAX_TIM_ICPSC 0x3
+#define TIM_CR2_MMS_SHIFT 4
+#define TIM_CR2_MMS2_SHIFT 20
+#define TIM_SMCR_TS_SHIFT 4
+#define TIM_BDTR_BKF_MASK 0xF
+#define TIM_BDTR_BKF_SHIFT 16
+#define TIM_BDTR_BK2F_SHIFT 20
+
+struct regmap;
+
+struct stm32_timers {
+ struct clk *clk;
+ struct regmap *regmap;
+ u32 max_arr;
+};
+
+#endif
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 1fbb3dc5c1..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)
@@ -21,8 +24,17 @@ struct pci_device_id {
#define SPI_NAME_SIZE 32
struct spi_device_id {
- char name[SPI_NAME_SIZE];
+ const char *name;
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/bbm.h b/include/linux/mtd/bbm.h
index 36bb6a503f..1e39883a2d 100644
--- a/include/linux/mtd/bbm.h
+++ b/include/linux/mtd/bbm.h
@@ -159,7 +159,7 @@ struct bbm_info {
int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt);
- /* TODO Add more NAND specific fileds */
+ /* TODO Add more NAND specific fields */
struct nand_bbt_descr *badblock_pattern;
void *priv;
diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h
new file mode 100644
index 0000000000..0b6b59f7cf
--- /dev/null
+++ b/include/linux/mtd/jedec.h
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ * Steven J. Hill <sjhill@realitydiluted.com>
+ * Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Contains all JEDEC related definitions
+ */
+
+#ifndef __LINUX_MTD_JEDEC_H
+#define __LINUX_MTD_JEDEC_H
+
+struct jedec_ecc_info {
+ u8 ecc_bits;
+ u8 codeword_size;
+ __le16 bb_per_lun;
+ __le16 block_endurance;
+ u8 reserved[2];
+} __packed;
+
+/* JEDEC features */
+#define JEDEC_FEATURE_16_BIT_BUS (1 << 0)
+
+struct nand_jedec_params {
+ /* rev info and features block */
+ /* 'J' 'E' 'S' 'D' */
+ u8 sig[4];
+ __le16 revision;
+ __le16 features;
+ u8 opt_cmd[3];
+ __le16 sec_cmd;
+ u8 num_of_param_pages;
+ u8 reserved0[18];
+
+ /* manufacturer information block */
+ char manufacturer[12];
+ char model[20];
+ u8 jedec_id[6];
+ u8 reserved1[10];
+
+ /* memory organization block */
+ __le32 byte_per_page;
+ __le16 spare_bytes_per_page;
+ u8 reserved2[6];
+ __le32 pages_per_block;
+ __le32 blocks_per_lun;
+ u8 lun_count;
+ u8 addr_cycles;
+ u8 bits_per_cell;
+ u8 programs_per_page;
+ u8 multi_plane_addr;
+ u8 multi_plane_op_attr;
+ u8 reserved3[38];
+
+ /* electrical parameter block */
+ __le16 async_sdr_speed_grade;
+ __le16 toggle_ddr_speed_grade;
+ __le16 sync_ddr_speed_grade;
+ u8 async_sdr_features;
+ u8 toggle_ddr_features;
+ u8 sync_ddr_features;
+ __le16 t_prog;
+ __le16 t_bers;
+ __le16 t_r;
+ __le16 t_r_multi_plane;
+ __le16 t_ccs;
+ __le16 io_pin_capacitance_typ;
+ __le16 input_pin_capacitance_typ;
+ __le16 clk_pin_capacitance_typ;
+ u8 driver_strength_support;
+ __le16 t_adl;
+ u8 reserved4[36];
+
+ /* ECC and endurance block */
+ u8 guaranteed_good_blocks;
+ __le16 guaranteed_block_endurance;
+ struct jedec_ecc_info ecc_info[4];
+ u8 reserved5[29];
+
+ /* reserved */
+ u8 reserved6[148];
+
+ /* vendor */
+ __le16 vendor_rev_num;
+ u8 reserved7[88];
+
+ /* CRC for Parameter Page */
+ __le16 crc;
+} __packed;
+
+#endif /* __LINUX_MTD_JEDEC_H */
diff --git a/include/linux/mtd/mtd-abi.h b/include/linux/mtd/mtd-abi.h
index dfcb3554fb..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 $
*
@@ -7,7 +9,7 @@
#ifndef __MTD_ABI_H__
#define __MTD_ABI_H__
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
struct erase_info_user {
uint64_t start;
@@ -46,6 +48,7 @@ enum {
#define MTD_NANDFLASH 4
#define MTD_DATAFLASH 6
#define MTD_UBIVOLUME 7
+#define MTD_MLCNANDFLASH 8 /* MLC NAND (including TLC) */
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 16725ac4bc..54cb2ec64c 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -11,21 +11,16 @@
#include <driver.h>
#include <errno.h>
+#include <linux/printk.h>
#include <linux/types.h>
#include <linux/list.h>
#include <linux/mtd/mtd-abi.h>
-#include <asm-generic/div64.h>
+#include <linux/math64.h>
#define MTD_CHAR_MAJOR 90
#define MTD_BLOCK_MAJOR 31
#define MAX_MTD_DEVICES 32
-#define MTD_ERASE_PENDING 0x01
-#define MTD_ERASING 0x02
-#define MTD_ERASE_SUSPEND 0x04
-#define MTD_ERASE_DONE 0x08
-#define MTD_ERASE_FAILED 0x10
-
#define MTD_FAIL_ADDR_UNKNOWN -1LL
/* If the erase fails, fail_addr might indicate exactly which block failed. If
@@ -40,9 +35,7 @@ struct erase_info {
u_long retries;
u_int dev;
u_int cell;
- void (*callback) (struct erase_info *self);
u_long priv;
- u_char state;
struct erase_info *next;
};
@@ -83,6 +76,39 @@ struct mtd_oob_ops {
uint8_t *oobbuf;
};
+#define MTD_MAX_OOBFREE_ENTRIES_LARGE 32
+#define MTD_MAX_ECCPOS_ENTRIES_LARGE 640
+/**
+ * struct mtd_oob_region - oob region definition
+ * @offset: region offset
+ * @length: region length
+ *
+ * This structure describes a region of the OOB area, and is used
+ * to retrieve ECC or free bytes sections.
+ * Each section is defined by an offset within the OOB area and a
+ * length.
+ */
+struct mtd_oob_region {
+ u32 offset;
+ u32 length;
+};
+
+/*
+ * struct mtd_ooblayout_ops - NAND OOB layout operations
+ * @ecc: function returning an ECC region in the OOB area.
+ * Should return -ERANGE if %section exceeds the total number of
+ * ECC sections.
+ * @free: function returning a free region in the OOB area.
+ * Should return -ERANGE if %section exceeds the total number of
+ * free sections.
+ */
+struct mtd_ooblayout_ops {
+ int (*ecc)(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobecc);
+ int (*free)(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobfree);
+};
+
struct mtd_info {
u_char type;
u_int32_t flags;
@@ -131,6 +157,11 @@ struct mtd_info {
/* ecc layout structure pointer - read only ! */
struct nand_ecclayout *ecclayout;
+ /* OOB layout description */
+ const struct mtd_ooblayout_ops *ooblayout;
+
+ /* the ecc step size. */
+ unsigned int ecc_step_size;
/* max number of correctible bit errors per ecc step */
unsigned int ecc_strength;
@@ -141,30 +172,14 @@ struct mtd_info {
int numeraseregions;
struct mtd_erase_region_info *eraseregions;
- /*
- * Erase is an asynchronous operation. Device drivers are supposed
- * to call instr->callback() whenever the operation completes, even
- * if it completes with a failure.
- * Callers are supposed to pass a callback function and wait for it
- * to be called before writing to the block.
- */
- int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
-
- int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
- int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
-
- /* In blackbox flight recorder like scenarios we want to make successful
- writes in interrupt context. panic_write() is only intended to be
- called when its known the kernel is about to panic and we need the
- write to succeed. Since the kernel is not going to be running for much
- longer, this function can break locks and delay to ensure the write
- succeeds (but not sleep). */
+ int (*_erase) (struct mtd_info *mtd, struct erase_info *instr);
- int (*panic_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+ int (*_read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
- int (*read_oob) (struct mtd_info *mtd, loff_t from,
+ int (*_read_oob) (struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops);
- int (*write_oob) (struct mtd_info *mtd, loff_t to,
+ int (*_write_oob) (struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops);
/*
@@ -172,24 +187,26 @@ struct mtd_info {
* flash devices. The user data is one time programmable but the
* factory data is read only.
*/
- int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
- int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
- int (*get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
- int (*read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
- int (*write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
- int (*lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
+ int (*_get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
+ int (*_read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*_get_user_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len);
+ int (*_read_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*_write_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+ int (*_lock_user_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len);
/* Sync */
- void (*sync) (struct mtd_info *mtd);
+ void (*_sync) (struct mtd_info *mtd);
/* Chip-supported device locking */
- int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
- int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+ int (*_lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
+ int (*_unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
/* Bad block management functions */
- int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
- int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
- int (*block_markgood) (struct mtd_info *mtd, loff_t ofs);
+ int (*_block_isbad) (struct mtd_info *mtd, loff_t ofs);
+ int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
+ int (*_block_markgood) (struct mtd_info *mtd, loff_t ofs);
+
+ int (*of_fixup)(struct mtd_info *mtd, struct device_node *root);
/* ECC status information */
struct mtd_ecc_stats ecc_stats;
@@ -205,11 +222,10 @@ struct mtd_info {
* its own reference counting. The below functions are only for driver.
* The driver may register its callbacks. These callbacks are not
* supposed to be called by MTD users */
- int (*get_device) (struct mtd_info *mtd);
- void (*put_device) (struct mtd_info *mtd);
+ int (*_get_device) (struct mtd_info *mtd);
+ void (*_put_device) (struct mtd_info *mtd);
- struct device_d class_dev;
- struct device_d *parent;
+ struct device dev;
struct cdev cdev;
struct cdev *cdev_bb;
@@ -221,17 +237,46 @@ struct mtd_info {
bool allow_erasebad;
int p_allow_erasebad;
- struct mtd_info *master;
+ /*
+ * Parent device from the MTD partition point of view.
+ *
+ * MTD masters do not have any parent, MTD partitions do. The parent
+ * MTD device can itself be a partition.
+ */
+ struct mtd_info *parent;
loff_t master_offset;
struct list_head partitions;
struct list_head partitions_entry;
char *partition_string;
- char *of_path;
unsigned int of_binding;
};
+int mtd_ooblayout_ecc(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobecc);
+int mtd_ooblayout_find_eccregion(struct mtd_info *mtd, int eccbyte,
+ int *section,
+ struct mtd_oob_region *oobregion);
+int mtd_ooblayout_get_eccbytes(struct mtd_info *mtd, u8 *eccbuf,
+ const u8 *oobbuf, int start, int nbytes);
+int mtd_ooblayout_set_eccbytes(struct mtd_info *mtd, const u8 *eccbuf,
+ u8 *oobbuf, int start, int nbytes);
+int mtd_ooblayout_free(struct mtd_info *mtd, int section,
+ struct mtd_oob_region *oobfree);
+int mtd_ooblayout_get_databytes(struct mtd_info *mtd, u8 *databuf,
+ const u8 *oobbuf, int start, int nbytes);
+int mtd_ooblayout_set_databytes(struct mtd_info *mtd, const u8 *databuf,
+ u8 *oobbuf, int start, int nbytes);
+int mtd_ooblayout_count_freebytes(struct mtd_info *mtd);
+int mtd_ooblayout_count_eccbytes(struct mtd_info *mtd);
+
+static inline void mtd_set_ooblayout(struct mtd_info *mtd,
+ const struct mtd_ooblayout_ops *ooblayout)
+{
+ mtd->ooblayout = ooblayout;
+}
+
int mtd_erase(struct mtd_info *mtd, struct erase_info *instr);
int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
u_char *buf);
@@ -240,20 +285,33 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
int mtd_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops);
-static inline int mtd_write_oob(struct mtd_info *mtd, loff_t to,
- struct mtd_oob_ops *ops)
+static inline void mtd_set_of_node(struct mtd_info *mtd,
+ struct device_node *np)
+{
+ mtd->dev.of_node = np;
+}
+
+static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
+{
+ 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->of_node;
+ return NULL;
+}
+
+static inline u32 mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
{
- ops->retlen = ops->oobretlen = 0;
- if (!mtd->write_oob)
- return -EOPNOTSUPP;
- if (!(mtd->flags & MTD_WRITEABLE))
- return -EROFS;
- return mtd->write_oob(mtd, to, ops);
+ return ops->mode == MTD_OPS_AUTO_OOB ? mtd->oobavail : mtd->oobsize;
}
+int mtd_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops);
+
static inline int mtd_can_have_bb(const struct mtd_info *mtd)
{
- return !!mtd->block_isbad;
+ return !!mtd->_block_isbad;
}
static inline uint32_t mtd_div_by_eb(uint64_t sz, struct mtd_info *mtd)
@@ -298,16 +356,6 @@ int mtd_del_partition(struct mtd_info *mtd);
extern void register_mtd_user (struct mtd_notifier *new);
extern int unregister_mtd_user (struct mtd_notifier *old);
-#ifdef CONFIG_MTD_PARTITIONS
-void mtd_erase_callback(struct erase_info *instr);
-#else
-static inline void mtd_erase_callback(struct erase_info *instr)
-{
- if (instr->callback)
- instr->callback(instr);
-}
-#endif
-
int mtd_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
int mtd_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
int mtd_block_isbad(struct mtd_info *mtd, loff_t ofs);
@@ -329,4 +377,8 @@ static inline int mtd_is_bitflip_or_eccerr(int err) {
return mtd_is_bitflip(err) || mtd_is_eccerr(err);
}
+void mtd_set_ecclayout(struct mtd_info *mtd, struct nand_ecclayout *ecclayout);
+
+void mtd_print_oob_info(struct mtd_info *mtd);
+
#endif /* __MTD_MTD_H__ */
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 401f630570..6ce5c1d041 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -1,809 +1,737 @@
+/* SPDX-License-Identifier: GPL-2.0 */
/*
- * linux/include/linux/mtd/nand.h
+ * Copyright 2017 - Free Electrons
*
- * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
- * Steven J. Hill <sjhill@realitydiluted.com>
- * Thomas Gleixner <tglx@linutronix.de>
- *
- * 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.
- *
- * Info:
- * Contains standard defines and IDs for NAND flash devices
- *
- * Changelog:
- * See git changelog.
+ * Authors:
+ * Boris Brezillon <boris.brezillon@free-electrons.com>
+ * Peter Pan <peterpandong@micron.com>
*/
+
#ifndef __LINUX_MTD_NAND_H
#define __LINUX_MTD_NAND_H
#include <linux/mtd/mtd.h>
-#include <linux/mtd/flashchip.h>
-#include <linux/mtd/bbm.h>
-struct mtd_info;
-struct nand_flash_dev;
-/* Scan and identify a NAND device */
-extern int nand_scan(struct mtd_info *mtd, int max_chips);
+struct nand_device;
+
/*
- * Separate phases of nand_scan(), allowing board driver to intervene
- * and override command or ECC setup according to flash type.
+ * This constant declares the max. oobsize / page, which
+ * is supported now. If you add a chip with bigger oobsize/page
+ * adjust this accordingly.
*/
-extern int nand_scan_ident(struct mtd_info *mtd, int max_chips,
- struct nand_flash_dev *table);
-extern int nand_scan_tail(struct mtd_info *mtd);
+#define NAND_MAX_OOBSIZE 640
+#define NAND_MAX_PAGESIZE 8192
-/* Free resources held by the NAND device */
-extern void nand_release(struct mtd_info *mtd);
+/**
+ * struct nand_memory_organization - Memory organization structure
+ * @bits_per_cell: number of bits per NAND cell
+ * @pagesize: page size
+ * @oobsize: OOB area size
+ * @pages_per_eraseblock: number of pages per eraseblock
+ * @eraseblocks_per_lun: number of eraseblocks per LUN (Logical Unit Number)
+ * @max_bad_eraseblocks_per_lun: maximum number of eraseblocks per LUN
+ * @planes_per_lun: number of planes per LUN
+ * @luns_per_target: number of LUN per target (target is a synonym for die)
+ * @ntargets: total number of targets exposed by the NAND device
+ */
+struct nand_memory_organization {
+ unsigned int bits_per_cell;
+ unsigned int pagesize;
+ unsigned int oobsize;
+ unsigned int pages_per_eraseblock;
+ unsigned int eraseblocks_per_lun;
+ unsigned int max_bad_eraseblocks_per_lun;
+ unsigned int planes_per_lun;
+ unsigned int luns_per_target;
+ unsigned int ntargets;
+};
-/* Internal helper for board drivers which need to override command function */
-extern void nand_wait_ready(struct mtd_info *mtd);
+#define NAND_MEMORG(bpc, ps, os, ppe, epl, mbb, ppl, lpt, nt) \
+ { \
+ .bits_per_cell = (bpc), \
+ .pagesize = (ps), \
+ .oobsize = (os), \
+ .pages_per_eraseblock = (ppe), \
+ .eraseblocks_per_lun = (epl), \
+ .max_bad_eraseblocks_per_lun = (mbb), \
+ .planes_per_lun = (ppl), \
+ .luns_per_target = (lpt), \
+ .ntargets = (nt), \
+ }
-/* locks all blocks present in the device */
-extern int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+/**
+ * struct nand_row_converter - Information needed to convert an absolute offset
+ * into a row address
+ * @lun_addr_shift: position of the LUN identifier in the row address
+ * @eraseblock_addr_shift: position of the eraseblock identifier in the row
+ * address
+ */
+struct nand_row_converter {
+ unsigned int lun_addr_shift;
+ unsigned int eraseblock_addr_shift;
+};
-/* unlocks specified locked blocks */
-extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
+/**
+ * struct nand_pos - NAND position object
+ * @target: the NAND target/die
+ * @lun: the LUN identifier
+ * @plane: the plane within the LUN
+ * @eraseblock: the eraseblock within the LUN
+ * @page: the page within the LUN
+ *
+ * These information are usually used by specific sub-layers to select the
+ * appropriate target/die and generate a row address to pass to the device.
+ */
+struct nand_pos {
+ unsigned int target;
+ unsigned int lun;
+ unsigned int plane;
+ unsigned int eraseblock;
+ unsigned int page;
+};
-extern int nand_check_erased_ecc_chunk(void *data, int datalen,
- void *ecc, int ecclen,
- void *extraoob, int extraooblen,
- int bitflips_threshold);
-int nand_check_erased_buf(void *buf, int len, int bitflips_threshold);
+/**
+ * struct nand_page_io_req - NAND I/O request object
+ * @pos: the position this I/O request is targeting
+ * @dataoffs: the offset within the page
+ * @datalen: number of data bytes to read from/write to this page
+ * @databuf: buffer to store data in or get data from
+ * @ooboffs: the OOB offset within the page
+ * @ooblen: the number of OOB bytes to read from/write to this page
+ * @oobbuf: buffer to store OOB data in or get OOB data from
+ * @mode: one of the %MTD_OPS_XXX mode
+ *
+ * This object is used to pass per-page I/O requests to NAND sub-layers. This
+ * way all useful information are already formatted in a useful way and
+ * specific NAND layers can focus on translating these information into
+ * specific commands/operations.
+ */
+struct nand_page_io_req {
+ struct nand_pos pos;
+ unsigned int dataoffs;
+ unsigned int datalen;
+ union {
+ const void *out;
+ void *in;
+ } databuf;
+ unsigned int ooboffs;
+ unsigned int ooblen;
+ union {
+ const void *out;
+ void *in;
+ } oobbuf;
+ int mode;
+};
-void nand_of_parse_node(struct mtd_info *mtd, struct device_node *np);
+/**
+ * struct nand_ecc_props - NAND ECC properties
+ * @strength: ECC strength
+ * @step_size: Number of bytes per step
+ */
+struct nand_ecc_props {
+ unsigned int strength;
+ unsigned int step_size;
+};
-/* The maximum number of NAND chips in an array */
-#define NAND_MAX_CHIPS 8
+#define NAND_ECCREQ(str, stp) { .strength = (str), .step_size = (stp) }
-/*
- * This constant declares the max. oobsize / page, which
- * is supported now. If you add a chip with bigger oobsize/page
- * adjust this accordingly.
+/**
+ * struct nand_bbt - bad block table object
+ * @cache: in memory BBT cache
*/
-#define NAND_MAX_OOBSIZE 640
-#define NAND_MAX_PAGESIZE 8192
+struct nand_bbt {
+ unsigned long *cache;
+};
-/*
- * Constants for hardware specific CLE/ALE/NCE function
+/**
+ * struct nand_ops - NAND operations
+ * @erase: erase a specific block. No need to check if the block is bad before
+ * erasing, this has been taken care of by the generic NAND layer
+ * @markbad: mark a specific block bad. No need to check if the block is
+ * already marked bad, this has been taken care of by the generic
+ * NAND layer. This method should just write the BBM (Bad Block
+ * Marker) so that future call to struct_nand_ops->isbad() return
+ * true
+ * @isbad: check whether a block is bad or not. This method should just read
+ * the BBM and return whether the block is bad or not based on what it
+ * reads
*
- * These are bits which can be or'ed to set/clear multiple
- * bits in one go.
+ * These are all low level operations that should be implemented by specialized
+ * NAND layers (SPI NAND, raw NAND, ...).
*/
-/* Select the chip by setting nCE to low */
-#define NAND_NCE 0x01
-/* Select the command latch by setting CLE to high */
-#define NAND_CLE 0x02
-/* Select the address latch by setting ALE to high */
-#define NAND_ALE 0x04
+struct nand_ops {
+ int (*erase)(struct nand_device *nand, const struct nand_pos *pos);
+ int (*markbad)(struct nand_device *nand, const struct nand_pos *pos);
+ bool (*isbad)(struct nand_device *nand, const struct nand_pos *pos);
+};
-#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE)
-#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE)
-#define NAND_CTRL_CHANGE 0x80
+/**
+ * struct nand_ecc - Information relative to the ECC
+ * @requirements: ECC requirements from the NAND chip perspective
+ */
+struct nand_ecc {
+ struct nand_ecc_props requirements;
+};
-/*
- * Standard NAND flash commands
- */
-#define NAND_CMD_READ0 0
-#define NAND_CMD_READ1 1
-#define NAND_CMD_RNDOUT 5
-#define NAND_CMD_PAGEPROG 0x10
-#define NAND_CMD_READOOB 0x50
-#define NAND_CMD_ERASE1 0x60
-#define NAND_CMD_STATUS 0x70
-#define NAND_CMD_SEQIN 0x80
-#define NAND_CMD_RNDIN 0x85
-#define NAND_CMD_READID 0x90
-#define NAND_CMD_ERASE2 0xd0
-#define NAND_CMD_PARAM 0xec
-#define NAND_CMD_GET_FEATURES 0xee
-#define NAND_CMD_SET_FEATURES 0xef
-#define NAND_CMD_RESET 0xff
-
-#define NAND_CMD_LOCK 0x2a
-#define NAND_CMD_UNLOCK1 0x23
-#define NAND_CMD_UNLOCK2 0x24
-
-/* Extended commands for large page devices */
-#define NAND_CMD_READSTART 0x30
-#define NAND_CMD_RNDOUTSTART 0xE0
-#define NAND_CMD_CACHEDPROG 0x15
-
-#define NAND_CMD_NONE -1
-
-/* Status bits */
-#define NAND_STATUS_FAIL 0x01
-#define NAND_STATUS_FAIL_N1 0x02
-#define NAND_STATUS_TRUE_READY 0x20
-#define NAND_STATUS_READY 0x40
-#define NAND_STATUS_WP 0x80
+/**
+ * struct nand_device - NAND device
+ * @mtd: MTD instance attached to the NAND device
+ * @memorg: memory layout
+ * @ecc: ECC information
+ * @rowconv: position to row address converter
+ * @bbt: bad block table info
+ * @ops: NAND operations attached to the NAND device
+ *
+ * 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->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
+ * struct_nand_device->mtd except for the ->_read/write() hooks.
+ */
+struct nand_device {
+ struct mtd_info mtd;
+ struct nand_memory_organization memorg;
+ struct nand_ecc ecc;
+ struct nand_row_converter rowconv;
+ struct nand_bbt bbt;
+ const struct nand_ops *ops;
+};
-/*
- * Constants for ECC_MODES
+/**
+ * struct nand_io_iter - NAND I/O iterator
+ * @req: current I/O request
+ * @oobbytes_per_page: maximum number of OOB bytes per page
+ * @dataleft: remaining number of data bytes to read/write
+ * @oobleft: remaining number of OOB bytes to read/write
+ *
+ * Can be used by specialized NAND layers to iterate over all pages covered
+ * by an MTD I/O request, which should greatly simplifies the boiler-plate
+ * code needed to read/write data from/to a NAND device.
+ */
+struct nand_io_iter {
+ struct nand_page_io_req req;
+ unsigned int oobbytes_per_page;
+ unsigned int dataleft;
+ unsigned int oobleft;
+};
+
+/**
+ * mtd_to_nanddev() - Get the NAND device attached to the MTD instance
+ * @mtd: MTD instance
+ *
+ * Return: the NAND device embedding @mtd.
+ */
+static inline struct nand_device *mtd_to_nanddev(struct mtd_info *mtd)
+{
+ return container_of(mtd, struct nand_device, mtd);
+}
+
+/**
+ * nanddev_to_mtd() - Get the MTD device attached to a NAND device
+ * @nand: NAND device
+ *
+ * Return: the MTD device embedded in @nand.
*/
-typedef enum {
- NAND_ECC_NONE,
- NAND_ECC_SOFT,
- NAND_ECC_HW,
- NAND_ECC_HW_SYNDROME,
- NAND_ECC_HW_OOB_FIRST,
- NAND_ECC_SOFT_BCH,
-} nand_ecc_modes_t;
+static inline struct mtd_info *nanddev_to_mtd(struct nand_device *nand)
+{
+ return &nand->mtd;
+}
/*
- * Constants for Hardware ECC
+ * nanddev_bits_per_cell() - Get the number of bits per cell
+ * @nand: NAND device
+ *
+ * Return: the number of bits per cell.
*/
-/* Reset Hardware ECC for read */
-#define NAND_ECC_READ 0
-/* Reset Hardware ECC for write */
-#define NAND_ECC_WRITE 1
-/* Enable Hardware ECC before syndrome is read back from flash */
-#define NAND_ECC_READSYN 2
+static inline unsigned int nanddev_bits_per_cell(const struct nand_device *nand)
+{
+ return nand->memorg.bits_per_cell;
+}
-/* Bit mask for flags passed to do_nand_read_ecc */
-#define NAND_GET_DEVICE 0x80
+/**
+ * nanddev_page_size() - Get NAND page size
+ * @nand: NAND device
+ *
+ * Return: the page size.
+ */
+static inline size_t nanddev_page_size(const struct nand_device *nand)
+{
+ return nand->memorg.pagesize;
+}
+/**
+ * nanddev_per_page_oobsize() - Get NAND OOB size
+ * @nand: NAND device
+ *
+ * Return: the OOB size.
+ */
+static inline unsigned int
+nanddev_per_page_oobsize(const struct nand_device *nand)
+{
+ return nand->memorg.oobsize;
+}
-/*
- * Option constants for bizarre disfunctionality and real
- * features.
+/**
+ * nanddev_pages_per_eraseblock() - Get the number of pages per eraseblock
+ * @nand: NAND device
+ *
+ * Return: the number of pages per eraseblock.
*/
-/* Buswidth is 16 bit */
-#define NAND_BUSWIDTH_16 0x00000002
-/* Chip has cache program function */
-#define NAND_CACHEPRG 0x00000008
-/*
- * Chip requires ready check on read (for auto-incremented sequential read).
- * True only for small page devices; large page devices do not support
- * autoincrement.
+static inline unsigned int
+nanddev_pages_per_eraseblock(const struct nand_device *nand)
+{
+ return nand->memorg.pages_per_eraseblock;
+}
+
+/**
+ * nanddev_pages_per_target() - Get the number of pages per target
+ * @nand: NAND device
+ *
+ * Return: the number of pages per target.
*/
-#define NAND_NEED_READRDY 0x00000100
+static inline unsigned int
+nanddev_pages_per_target(const struct nand_device *nand)
+{
+ return nand->memorg.pages_per_eraseblock *
+ nand->memorg.eraseblocks_per_lun *
+ nand->memorg.luns_per_target;
+}
-/* Chip does not allow subpage writes */
-#define NAND_NO_SUBPAGE_WRITE 0x00000200
+/**
+ * nanddev_per_page_oobsize() - Get NAND erase block size
+ * @nand: NAND device
+ *
+ * Return: the eraseblock size.
+ */
+static inline size_t nanddev_eraseblock_size(const struct nand_device *nand)
+{
+ return nand->memorg.pagesize * nand->memorg.pages_per_eraseblock;
+}
-/* Device is one of 'new' xD cards that expose fake nand command set */
-#define NAND_BROKEN_XD 0x00000400
+/**
+ * nanddev_eraseblocks_per_lun() - Get the number of eraseblocks per LUN
+ * @nand: NAND device
+ *
+ * Return: the number of eraseblocks per LUN.
+ */
+static inline unsigned int
+nanddev_eraseblocks_per_lun(const struct nand_device *nand)
+{
+ return nand->memorg.eraseblocks_per_lun;
+}
-/* Device behaves just like nand, but is readonly */
-#define NAND_ROM 0x00000800
+/**
+ * nanddev_eraseblocks_per_target() - Get the number of eraseblocks per target
+ * @nand: NAND device
+ *
+ * Return: the number of eraseblocks per target.
+ */
+static inline unsigned int
+nanddev_eraseblocks_per_target(const struct nand_device *nand)
+{
+ return nand->memorg.eraseblocks_per_lun * nand->memorg.luns_per_target;
+}
-/* Device supports subpage reads */
-/* Disabled in barebox for smaller binary sizes */
-#define NAND_SUBPAGE_READ (0x00001000)
+/**
+ * nanddev_target_size() - Get the total size provided by a single target/die
+ * @nand: NAND device
+ *
+ * Return: the total size exposed by a single target/die in bytes.
+ */
+static inline u64 nanddev_target_size(const struct nand_device *nand)
+{
+ return (u64)nand->memorg.luns_per_target *
+ nand->memorg.eraseblocks_per_lun *
+ nand->memorg.pages_per_eraseblock *
+ nand->memorg.pagesize;
+}
-/* Options valid for Samsung large page devices */
-#define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG
+/**
+ * nanddev_ntarget() - Get the total of targets
+ * @nand: NAND device
+ *
+ * Return: the number of targets/dies exposed by @nand.
+ */
+static inline unsigned int nanddev_ntargets(const struct nand_device *nand)
+{
+ return nand->memorg.ntargets;
+}
-/* Macros to identify the above */
-#define NAND_HAS_CACHEPROG(chip) ((chip->options & NAND_CACHEPRG))
-#define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
+/**
+ * nanddev_neraseblocks() - Get the total number of eraseblocks
+ * @nand: NAND device
+ *
+ * Return: the total number of eraseblocks exposed by @nand.
+ */
+static inline unsigned int nanddev_neraseblocks(const struct nand_device *nand)
+{
+ return nand->memorg.ntargets * nand->memorg.luns_per_target *
+ nand->memorg.eraseblocks_per_lun;
+}
-/* Non chip related options */
-/* This option skips the bbt scan during initialization. */
-#define NAND_SKIP_BBTSCAN 0x00010000
-/*
- * This option is defined if the board driver allocates its own buffers
- * (e.g. because it needs them DMA-coherent).
+/**
+ * nanddev_size() - Get NAND size
+ * @nand: NAND device
+ *
+ * Return: the total size (in bytes) exposed by @nand.
*/
-#define NAND_OWN_BUFFERS 0x00020000
-/* Chip may not exist, so silence any errors in scan */
-#define NAND_SCAN_SILENT_NODEV 0x00040000
-/*
- * Autodetect nand buswidth with readid/onfi.
- * This suppose the driver will configure the hardware in 8 bits mode
- * when calling nand_scan_ident, and update its configuration
- * before calling nand_scan_tail.
- */
-#define NAND_BUSWIDTH_AUTO 0x00080000
-
-/* Options set by nand scan */
-/* Nand scan has allocated controller struct */
-#define NAND_CONTROLLER_ALLOC 0x80000000
-
-/* Cell info constants */
-#define NAND_CI_CHIPNR_MSK 0x03
-#define NAND_CI_CELLTYPE_MSK 0x0C
-#define NAND_CI_CELLTYPE_SHIFT 2
-
-/* Keep gcc happy */
-struct nand_chip;
-
-/* ONFI timing mode, used in both asynchronous and synchronous mode */
-#define ONFI_TIMING_MODE_0 (1 << 0)
-#define ONFI_TIMING_MODE_1 (1 << 1)
-#define ONFI_TIMING_MODE_2 (1 << 2)
-#define ONFI_TIMING_MODE_3 (1 << 3)
-#define ONFI_TIMING_MODE_4 (1 << 4)
-#define ONFI_TIMING_MODE_5 (1 << 5)
-#define ONFI_TIMING_MODE_UNKNOWN (1 << 6)
-
-/* ONFI feature address */
-#define ONFI_FEATURE_ADDR_TIMING_MODE 0x1
-
-/* ONFI subfeature parameters length */
-#define ONFI_SUBFEATURE_PARAM_LEN 4
-
-/* ONFI optional commands SET/GET FEATURES supported? */
-#define ONFI_OPT_CMD_SET_GET_FEATURES (1 << 2)
-
-struct nand_onfi_params {
- /* rev info and features block */
- /* 'O' 'N' 'F' 'I' */
- u8 sig[4];
- __le16 revision;
- __le16 features;
- __le16 opt_cmd;
- u8 reserved[22];
-
- /* manufacturer information block */
- char manufacturer[12];
- char model[20];
- u8 jedec_id;
- __le16 date_code;
- u8 reserved2[13];
-
- /* memory organization block */
- __le32 byte_per_page;
- __le16 spare_bytes_per_page;
- __le32 data_bytes_per_ppage;
- __le16 spare_bytes_per_ppage;
- __le32 pages_per_block;
- __le32 blocks_per_lun;
- u8 lun_count;
- u8 addr_cycles;
- u8 bits_per_cell;
- __le16 bb_per_lun;
- __le16 block_endurance;
- u8 guaranteed_good_blocks;
- __le16 guaranteed_block_endurance;
- u8 programs_per_page;
- u8 ppage_attr;
- u8 ecc_bits;
- u8 interleaved_bits;
- u8 interleaved_ops;
- u8 reserved3[13];
-
- /* electrical parameter block */
- u8 io_pin_capacitance_max;
- __le16 async_timing_mode;
- __le16 program_cache_timing_mode;
- __le16 t_prog;
- __le16 t_bers;
- __le16 t_r;
- __le16 t_ccs;
- __le16 src_sync_timing_mode;
- __le16 src_ssync_features;
- __le16 clk_pin_capacitance_typ;
- __le16 io_pin_capacitance_typ;
- __le16 input_pin_capacitance_typ;
- u8 input_pin_capacitance_max;
- u8 driver_strenght_support;
- __le16 t_int_r;
- __le16 t_ald;
- u8 reserved4[7];
-
- /* vendor */
- u8 reserved5[90];
-
- __le16 crc;
-} __attribute__((packed));
-
-#define ONFI_CRC_BASE 0x4F4E
-
-/**
- * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
- * @lock: protection lock
- * @active: the mtd device which holds the controller currently
- * @wq: wait queue to sleep on if a NAND operation is in
- * progress used instead of the per chip wait queue
- * when a hw controller is available.
- */
-struct nand_hw_control {
- struct nand_chip *active;
-};
+static inline u64 nanddev_size(const struct nand_device *nand)
+{
+ return nanddev_target_size(nand) * nanddev_ntargets(nand);
+}
/**
- * struct nand_ecc_ctrl - Control structure for ECC
- * @mode: ECC mode
- * @steps: number of ECC steps per page
- * @size: data bytes per ECC step
- * @bytes: ECC bytes per step
- * @strength: max number of correctible bits per ECC step
- * @total: total number of ECC bytes per page
- * @prepad: padding information for syndrome based ECC generators
- * @postpad: padding information for syndrome based ECC generators
- * @layout: ECC layout control struct pointer
- * @priv: pointer to private ECC control data
- * @hwctl: function to control hardware ECC generator. Must only
- * be provided if an hardware ECC is available
- * @calculate: function for ECC calculation or readback from ECC hardware
- * @correct: function for ECC correction, matching to ECC generator (sw/hw)
- * @read_page_raw: function to read a raw page without ECC
- * @write_page_raw: function to write a raw page without ECC
- * @read_page: function to read a page according to the ECC generator
- * requirements; returns maximum number of bitflips corrected in
- * any single ECC step, 0 if bitflips uncorrectable, -EIO hw error
- * @read_subpage: function to read parts of the page covered by ECC;
- * returns same as read_page()
- * @write_subpage: function to write parts of the page covered by ECC.
- * @write_page: function to write a page according to the ECC generator
- * requirements.
- * @write_oob_raw: function to write chip OOB data without ECC
- * @read_oob_raw: function to read chip OOB data without ECC
- * @read_oob: function to read chip OOB data
- * @write_oob: function to write chip OOB data
- */
-struct nand_ecc_ctrl {
- nand_ecc_modes_t mode;
- int steps;
- int size;
- int bytes;
- int total;
- int strength;
- int prepad;
- int postpad;
- struct nand_ecclayout *layout;
- void *priv;
- void (*hwctl)(struct mtd_info *mtd, int mode);
- int (*calculate)(struct mtd_info *mtd, const uint8_t *dat,
- uint8_t *ecc_code);
- int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
- uint8_t *calc_ecc);
- int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page);
- int (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required);
- int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
- uint8_t *buf, int oob_required, int page);
- int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t offs, uint32_t len, uint8_t *buf, int page);
- int (*write_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t offset, uint32_t data_len,
- const uint8_t *data_buf, int oob_required);
- int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- const uint8_t *buf, int oob_required);
- int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- int page);
- int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip,
- int page);
- int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page);
- int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,
- int page);
-};
+ * nanddev_get_memorg() - Extract memory organization info from a NAND device
+ * @nand: NAND device
+ *
+ * This can be used by the upper layer to fill the memorg info before calling
+ * nanddev_init().
+ *
+ * Return: the memorg object embedded in the NAND device.
+ */
+static inline struct nand_memory_organization *
+nanddev_get_memorg(struct nand_device *nand)
+{
+ return &nand->memorg;
+}
+
+int nanddev_init(struct nand_device *nand, const struct nand_ops *ops,
+ struct module *owner);
+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;
+}
/**
- * struct nand_buffers - buffer structure for read/write
- * @ecccalc: buffer for calculated ECC
- * @ecccode: buffer for ECC read from flash
- * @databuf: buffer for data - dynamically sized
+ * 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)
+ * @pos: a NAND position object to fill in
+ *
+ * Converts @offs into a nand_pos representation.
*
- * Do not change the order of buffers. databuf and oobrbuf must be in
- * consecutive order.
+ * Return: the offset within the NAND page pointed by @pos.
*/
-struct nand_buffers {
- uint8_t ecccalc[NAND_MAX_OOBSIZE];
- uint8_t ecccode[NAND_MAX_OOBSIZE];
- uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
-};
+static inline unsigned int nanddev_offs_to_pos(struct nand_device *nand,
+ loff_t offs,
+ struct nand_pos *pos)
+{
+ unsigned int pageoffs;
+ u64 tmp = offs;
+
+ pageoffs = do_div(tmp, nand->memorg.pagesize);
+ pos->page = do_div(tmp, nand->memorg.pages_per_eraseblock);
+ pos->eraseblock = do_div(tmp, nand->memorg.eraseblocks_per_lun);
+ pos->plane = pos->eraseblock % nand->memorg.planes_per_lun;
+ pos->lun = do_div(tmp, nand->memorg.luns_per_target);
+ pos->target = tmp;
+
+ return pageoffs;
+}
/**
- * struct nand_chip - NAND Private Flash Chip Data
- * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the
- * flash device
- * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the
- * flash device.
- * @read_byte: [REPLACEABLE] read one byte from the chip
- * @read_word: [REPLACEABLE] read one word from the chip
- * @write_buf: [REPLACEABLE] write data from the buffer to the chip
- * @read_buf: [REPLACEABLE] read data from the chip into the buffer
- * @select_chip: [REPLACEABLE] select chip nr
- * @block_bad: [REPLACEABLE] check, if the block is bad
- * @block_markbad: [REPLACEABLE] mark the block bad
- * @cmd_ctrl: [BOARDSPECIFIC] hardwarespecific function for controlling
- * ALE/CLE/nCE. Also used to write command and address
- * @init_size: [BOARDSPECIFIC] hardwarespecific function for setting
- * mtd->oobsize, mtd->writesize and so on.
- * @id_data contains the 8 bytes values of NAND_CMD_READID.
- * Return with the bus width.
- * @dev_ready: [BOARDSPECIFIC] hardwarespecific function for accessing
- * device ready/busy line. If set to NULL no access to
- * ready/busy is available and the ready/busy information
- * is read from the chip status register.
- * @cmdfunc: [REPLACEABLE] hardwarespecific function for writing
- * commands to the chip.
- * @waitfunc: [REPLACEABLE] hardwarespecific function for wait on
- * ready.
- * @ecc: [BOARDSPECIFIC] ECC control structure
- * @buffers: buffer structure for read/write
- * @hwcontrol: platform-specific hardware control structure
- * @erase_cmd: [INTERN] erase command write function, selectable due
- * to AND support.
- * @scan_bbt: [REPLACEABLE] function to scan bad block table
- * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transferring
- * data from array to read regs (tR).
- * @state: [INTERN] the current state of the NAND device
- * @oob_poi: "poison value buffer," used for laying out OOB data
- * before writing
- * @page_shift: [INTERN] number of address bits in a page (column
- * address bits).
- * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock
- * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry
- * @chip_shift: [INTERN] number of address bits in one chip
- * @options: [BOARDSPECIFIC] various chip options. They can partly
- * be set to inform nand_scan about special functionality.
- * See the defines for further explanation.
- * @bbt_options: [INTERN] bad block specific options. All options used
- * here must come from bbm.h. By default, these options
- * will be copied to the appropriate nand_bbt_descr's.
- * @badblockpos: [INTERN] position of the bad block marker in the oob
- * area.
- * @badblockbits: [INTERN] minimum number of set bits in a good block's
- * bad block marker position; i.e., BBM == 11110111b is
- * not bad when badblockbits == 7
- * @bits_per_cell: [INTERN] number of bits per cell. i.e., 1 means SLC.
- * @numchips: [INTERN] number of physical chips
- * @chipsize: [INTERN] the size of one chip for multichip arrays
- * @pagemask: [INTERN] page number mask = number of (pages / chip) - 1
- * @pagebuf: [INTERN] holds the pagenumber which is currently in
- * data_buf.
- * @pagebuf_bitflips: [INTERN] holds the bitflip count for the page which is
- * currently in data_buf.
- * @subpagesize: [INTERN] holds the subpagesize
- * @onfi_version: [INTERN] holds the chip ONFI version (BCD encoded),
- * non 0 if ONFI supported.
- * @onfi_params: [INTERN] holds the ONFI page parameter when ONFI is
- * supported, 0 otherwise.
- * @onfi_set_features: [REPLACEABLE] set the features for ONFI nand
- * @onfi_get_features: [REPLACEABLE] get the features for ONFI nand
- * @ecclayout: [REPLACEABLE] the default ECC placement scheme
- * @bbt: [INTERN] bad block table pointer
- * @bbt_td: [REPLACEABLE] bad block table descriptor for flash
- * lookup.
- * @bbt_md: [REPLACEABLE] bad block table mirror descriptor
- * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial
- * bad block scan.
- * @controller: [REPLACEABLE] a pointer to a hardware controller
- * structure which is shared among multiple independent
- * devices.
- * @priv: [OPTIONAL] pointer to private chip data
- * @errstat: [OPTIONAL] hardware specific function to perform
- * additional error status checks (determine if errors are
- * correctable).
- * @write_page: [REPLACEABLE] High-level page write function
- */
-
-struct nand_chip {
- void __iomem *IO_ADDR_R;
- void __iomem *IO_ADDR_W;
-
- uint8_t (*read_byte)(struct mtd_info *mtd);
- u16 (*read_word)(struct mtd_info *mtd);
- void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
- void (*select_chip)(struct mtd_info *mtd, int chip);
- int (*block_bad)(struct mtd_info *mtd, loff_t ofs, int getchip);
- int (*block_markbad)(struct mtd_info *mtd, loff_t ofs);
- void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
- int (*init_size)(struct mtd_info *mtd, struct nand_chip *this,
- u8 *id_data);
- int (*dev_ready)(struct mtd_info *mtd);
- void (*cmdfunc)(struct mtd_info *mtd, unsigned command, int column,
- int page_addr);
- int(*waitfunc)(struct mtd_info *mtd, struct nand_chip *this);
- void (*erase_cmd)(struct mtd_info *mtd, int page);
- int (*scan_bbt)(struct mtd_info *mtd);
- int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
- int status, int page);
- int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
- uint32_t offset, int data_len, const uint8_t *buf,
- int oob_required, int page, int cached, int raw);
- int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
- int feature_addr, uint8_t *subfeature_para);
- int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
- int feature_addr, uint8_t *subfeature_para);
-
- int chip_delay;
- unsigned int options;
- unsigned int bbt_options;
-
- int page_shift;
- int phys_erase_shift;
- int bbt_erase_shift;
- int chip_shift;
- int numchips;
- uint64_t chipsize;
- int pagemask;
- int pagebuf;
- unsigned int pagebuf_bitflips;
- int subpagesize;
- uint8_t bits_per_cell;
- int badblockpos;
- int badblockbits;
-
- int onfi_version;
- struct nand_onfi_params onfi_params;
-
- flstate_t state;
-
- uint8_t *oob_poi;
- struct nand_hw_control *controller;
- struct nand_ecclayout *ecclayout;
-
- struct nand_ecc_ctrl ecc;
- struct nand_buffers *buffers;
- struct nand_hw_control hwcontrol;
-
- uint8_t *bbt;
- struct nand_bbt_descr *bbt_td;
- struct nand_bbt_descr *bbt_md;
-
- struct nand_bbt_descr *badblock_pattern;
-
- void *priv;
- unsigned int bbt_type;
+ * nanddev_pos_cmp() - Compare two NAND positions
+ * @a: First NAND position
+ * @b: Second NAND position
+ *
+ * Compares two NAND positions.
+ *
+ * Return: -1 if @a < @b, 0 if @a == @b and 1 if @a > @b.
+ */
+static inline int nanddev_pos_cmp(const struct nand_pos *a,
+ const struct nand_pos *b)
+{
+ if (a->target != b->target)
+ return a->target < b->target ? -1 : 1;
- struct mtd_info mtd;
-};
+ if (a->lun != b->lun)
+ return a->lun < b->lun ? -1 : 1;
-/*
- * NAND Flash Manufacturer ID Codes
- */
-#define NAND_MFR_TOSHIBA 0x98
-#define NAND_MFR_SAMSUNG 0xec
-#define NAND_MFR_FUJITSU 0x04
-#define NAND_MFR_NATIONAL 0x8f
-#define NAND_MFR_RENESAS 0x07
-#define NAND_MFR_STMICRO 0x20
-#define NAND_MFR_HYNIX 0xad
-#define NAND_MFR_MICRON 0x2c
-#define NAND_MFR_AMD 0x01
-#define NAND_MFR_MACRONIX 0xc2
-#define NAND_MFR_EON 0x92
-#define NAND_MFR_WINBOND 0xef
-
-/* The maximum expected count of bytes in the NAND ID sequence */
-#define NAND_MAX_ID_LEN 8
+ if (a->eraseblock != b->eraseblock)
+ return a->eraseblock < b->eraseblock ? -1 : 1;
-/*
- * A helper for defining older NAND chips where the second ID byte fully
- * defined the chip, including the geometry (chip size, eraseblock size, page
- * size). All these chips have 512 bytes NAND page size.
+ if (a->page != b->page)
+ return a->page < b->page ? -1 : 1;
+
+ return 0;
+}
+
+/**
+ * nanddev_pos_to_offs() - Convert a NAND position into an absolute offset
+ * @nand: NAND device
+ * @pos: the NAND position to convert
+ *
+ * Converts @pos NAND position into an absolute offset.
+ *
+ * Return: the absolute offset. Note that @pos points to the beginning of a
+ * page, if one wants to point to a specific offset within this page
+ * the returned offset has to be adjusted manually.
*/
-#define LEGACY_ID_NAND(nm, devid, chipsz, erasesz, opts) \
- { .name = (nm), {{ .dev_id = (devid) }}, .pagesize = 512, \
- .chipsize = (chipsz), .erasesize = (erasesz), .options = (opts) }
+static inline loff_t nanddev_pos_to_offs(struct nand_device *nand,
+ const struct nand_pos *pos)
+{
+ unsigned int npages;
-/*
- * A helper for defining newer chips which report their page size and
- * eraseblock size via the extended ID bytes.
- *
- * The real difference between LEGACY_ID_NAND and EXTENDED_ID_NAND is that with
- * EXTENDED_ID_NAND, manufacturers overloaded the same device ID so that the
- * device ID now only represented a particular total chip size (and voltage,
- * buswidth), and the page size, eraseblock size, and OOB size could vary while
- * using the same device ID.
- */
-#define EXTENDED_ID_NAND(nm, devid, chipsz, opts) \
- { .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \
- .options = (opts) }
-
-/**
- * struct nand_flash_dev - NAND Flash Device ID Structure
- * @name: a human-readable name of the NAND chip
- * @dev_id: the device ID (the second byte of the full chip ID array)
- * @mfr_id: manufecturer ID part of the full chip ID array (refers the same
- * memory address as @id[0])
- * @dev_id: device ID part of the full chip ID array (refers the same memory
- * address as @id[1])
- * @id: full device ID array
- * @pagesize: size of the NAND page in bytes; if 0, then the real page size (as
- * well as the eraseblock size) is determined from the extended NAND
- * chip ID array)
- * @chipsize: total chip size in MiB
- * @erasesize: eraseblock size in bytes (determined from the extended ID if 0)
- * @options: stores various chip bit options
- * @id_len: The valid length of the @id.
- * @oobsize: OOB size
- */
-struct nand_flash_dev {
- char *name;
- union {
- struct {
- uint8_t mfr_id;
- uint8_t dev_id;
- };
- uint8_t id[NAND_MAX_ID_LEN];
- };
- unsigned int pagesize;
- unsigned int chipsize;
- unsigned int erasesize;
- unsigned int options;
- uint16_t id_len;
- uint16_t oobsize;
-};
+ npages = pos->page +
+ ((pos->eraseblock +
+ (pos->lun +
+ (pos->target * nand->memorg.luns_per_target)) *
+ nand->memorg.eraseblocks_per_lun) *
+ nand->memorg.pages_per_eraseblock);
+
+ return (loff_t)npages * nand->memorg.pagesize;
+}
/**
- * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
- * @name: Manufacturer name
- * @id: manufacturer ID code of device.
-*/
-struct nand_manufacturers {
- int id;
- char *name;
-};
+ * nanddev_pos_to_row() - Extract a row address from a NAND position
+ * @nand: NAND device
+ * @pos: the position to convert
+ *
+ * Converts a NAND position into a row address that can then be passed to the
+ * device.
+ *
+ * Return: the row address extracted from @pos.
+ */
+static inline unsigned int nanddev_pos_to_row(struct nand_device *nand,
+ const struct nand_pos *pos)
+{
+ return (pos->lun << nand->rowconv.lun_addr_shift) |
+ (pos->eraseblock << nand->rowconv.eraseblock_addr_shift) |
+ pos->page;
+}
-extern struct nand_flash_dev nand_flash_ids[];
-extern struct nand_manufacturers nand_manuf_ids[];
-
-extern int nand_update_bbt(struct mtd_info *mtd, loff_t offs);
-extern int nand_default_bbt(struct mtd_info *mtd);
-extern int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
-extern int nand_markgood_bbt(struct mtd_info *mtd, loff_t offs);
-extern int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt);
-extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
- int allowbbt);
-extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, uint8_t *buf);
-extern int add_mtd_nand_device(struct mtd_info *mtd, char *devname);
-
-/**
- * struct platform_nand_chip - chip level device structure
- * @nr_chips: max. number of chips to scan for
- * @chip_offset: chip number offset
- * @nr_partitions: number of partitions pointed to by partitions (or zero)
- * @partitions: mtd partition list
- * @chip_delay: R/B delay value in us
- * @options: Option flags, e.g. 16bit buswidth
- * @bbt_options: BBT option flags, e.g. NAND_BBT_USE_FLASH
- * @ecclayout: ECC layout info structure
- * @part_probe_types: NULL-terminated array of probe types
- */
-struct platform_nand_chip {
- int nr_chips;
- int chip_offset;
- int nr_partitions;
- struct mtd_partition *partitions;
- struct nand_ecclayout *ecclayout;
- int chip_delay;
- unsigned int options;
- unsigned int bbt_options;
- const char **part_probe_types;
-};
+/**
+ * nanddev_pos_next_target() - Move a position to the next target/die
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next target/die. Useful when you
+ * want to iterate over all targets/dies of a NAND device.
+ */
+static inline void nanddev_pos_next_target(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ pos->page = 0;
+ pos->plane = 0;
+ pos->eraseblock = 0;
+ pos->lun = 0;
+ pos->target++;
+}
-/* Keep gcc happy */
-struct platform_device;
-
-/**
- * struct platform_nand_ctrl - controller level device structure
- * @probe: platform specific function to probe/setup hardware
- * @remove: platform specific function to remove/teardown hardware
- * @hwcontrol: platform specific hardware control structure
- * @dev_ready: platform specific function to read ready/busy pin
- * @select_chip: platform specific chip select function
- * @cmd_ctrl: platform specific function for controlling
- * ALE/CLE/nCE. Also used to write command and address
- * @write_buf: platform specific function for write buffer
- * @read_buf: platform specific function for read buffer
- * @read_byte: platform specific function to read one byte from chip
- * @priv: private data to transport driver specific settings
- *
- * All fields are optional and depend on the hardware driver requirements
- */
-struct platform_nand_ctrl {
- int (*probe)(struct platform_device *pdev);
- void (*remove)(struct platform_device *pdev);
- void (*hwcontrol)(struct mtd_info *mtd, int cmd);
- int (*dev_ready)(struct mtd_info *mtd);
- void (*select_chip)(struct mtd_info *mtd, int chip);
- void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
- void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
- void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
- unsigned char (*read_byte)(struct mtd_info *mtd);
- void *priv;
-};
+/**
+ * nanddev_pos_next_lun() - Move a position to the next LUN
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next LUN. Useful when you want to
+ * iterate over all LUNs of a NAND device.
+ */
+static inline void nanddev_pos_next_lun(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ if (pos->lun >= nand->memorg.luns_per_target - 1)
+ return nanddev_pos_next_target(nand, pos);
+
+ pos->lun++;
+ pos->page = 0;
+ pos->plane = 0;
+ pos->eraseblock = 0;
+}
/**
- * struct platform_nand_data - container structure for platform-specific data
- * @chip: chip level chip structure
- * @ctrl: controller level device structure
+ * nanddev_pos_next_eraseblock() - Move a position to the next eraseblock
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next eraseblock. Useful when you
+ * want to iterate over all eraseblocks of a NAND device.
*/
-struct platform_nand_data {
- struct platform_nand_chip chip;
- struct platform_nand_ctrl ctrl;
-};
+static inline void nanddev_pos_next_eraseblock(struct nand_device *nand,
+ struct nand_pos *pos)
+{
+ if (pos->eraseblock >= nand->memorg.eraseblocks_per_lun - 1)
+ return nanddev_pos_next_lun(nand, pos);
+
+ pos->eraseblock++;
+ pos->page = 0;
+ pos->plane = pos->eraseblock % nand->memorg.planes_per_lun;
+}
-/* Some helpers to access the data structures */
-static inline
-struct platform_nand_chip *get_platform_nandchip(struct mtd_info *mtd)
+/**
+ * nanddev_pos_next_page() - Move a position to the next page
+ * @nand: NAND device
+ * @pos: the position to update
+ *
+ * Updates @pos to point to the start of the next page. Useful when you want to
+ * iterate over all pages of a NAND device.
+ */
+static inline void nanddev_pos_next_page(struct nand_device *nand,
+ struct nand_pos *pos)
{
- struct nand_chip *chip = mtd->priv;
+ if (pos->page >= nand->memorg.pages_per_eraseblock - 1)
+ return nanddev_pos_next_eraseblock(nand, pos);
- return chip->priv;
+ pos->page++;
}
-/* return the supported asynchronous timing mode. */
-static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
+/**
+ * nand_io_iter_init - Initialize a NAND I/O iterator
+ * @nand: NAND device
+ * @offs: absolute offset
+ * @req: MTD request
+ * @iter: NAND I/O iterator
+ *
+ * Initializes a NAND iterator based on the information passed by the MTD
+ * layer.
+ */
+static inline void nanddev_io_iter_init(struct nand_device *nand,
+ loff_t offs, struct mtd_oob_ops *req,
+ struct nand_io_iter *iter)
{
- if (!chip->onfi_version)
- return ONFI_TIMING_MODE_UNKNOWN;
- return le16_to_cpu(chip->onfi_params.async_timing_mode);
+ struct mtd_info *mtd = nanddev_to_mtd(nand);
+
+ iter->req.mode = req->mode;
+ iter->req.dataoffs = nanddev_offs_to_pos(nand, offs, &iter->req.pos);
+ iter->req.ooboffs = req->ooboffs;
+ iter->oobbytes_per_page = mtd_oobavail(mtd, req);
+ iter->dataleft = req->len;
+ iter->oobleft = req->ooblen;
+ iter->req.databuf.in = req->datbuf;
+ iter->req.datalen = min_t(unsigned int,
+ nand->memorg.pagesize - iter->req.dataoffs,
+ iter->dataleft);
+ iter->req.oobbuf.in = req->oobbuf;
+ iter->req.ooblen = min_t(unsigned int,
+ iter->oobbytes_per_page - iter->req.ooboffs,
+ iter->oobleft);
}
-/* return the supported synchronous timing mode. */
-static inline int onfi_get_sync_timing_mode(struct nand_chip *chip)
+/**
+ * nand_io_iter_next_page - Move to the next page
+ * @nand: NAND device
+ * @iter: NAND I/O iterator
+ *
+ * Updates the @iter to point to the next page.
+ */
+static inline void nanddev_io_iter_next_page(struct nand_device *nand,
+ struct nand_io_iter *iter)
{
- if (!chip->onfi_version)
- return ONFI_TIMING_MODE_UNKNOWN;
- return le16_to_cpu(chip->onfi_params.src_sync_timing_mode);
+ nanddev_pos_next_page(nand, &iter->req.pos);
+ iter->dataleft -= iter->req.datalen;
+ iter->req.databuf.in += iter->req.datalen;
+ iter->oobleft -= iter->req.ooblen;
+ iter->req.oobbuf.in += iter->req.ooblen;
+ iter->req.dataoffs = 0;
+ iter->req.ooboffs = 0;
+ iter->req.datalen = min_t(unsigned int, nand->memorg.pagesize,
+ iter->dataleft);
+ iter->req.ooblen = min_t(unsigned int, iter->oobbytes_per_page,
+ iter->oobleft);
}
-/*
- * Check if it is a SLC nand.
- * The !nand_is_slc() can be used to check the MLC/TLC nand chips.
- * We do not distinguish the MLC and TLC now.
+/**
+ * nand_io_iter_end - Should end iteration or not
+ * @nand: NAND device
+ * @iter: NAND I/O iterator
+ *
+ * Check whether @iter has reached the end of the NAND portion it was asked to
+ * iterate on or not.
+ *
+ * Return: true if @iter has reached the end of the iteration request, false
+ * otherwise.
*/
-static inline bool nand_is_slc(struct nand_chip *chip)
+static inline bool nanddev_io_iter_end(struct nand_device *nand,
+ const struct nand_io_iter *iter)
{
- return chip->bits_per_cell == 1;
+ if (iter->dataleft || iter->oobleft)
+ return false;
+
+ return true;
}
/**
- * struct nand_sdr_timings - SDR NAND chip timings
- *
- * This struct defines the timing requirements of a SDR NAND chip.
- * These informations can be found in every NAND datasheets and the timings
- * meaning are described in the ONFI specifications:
- * www.onfi.org/~/media/ONFI/specs/onfi_3_1_spec.pdf (chapter 4.15 Timing
- * Parameters)
- *
- * All these timings are expressed in picoseconds.
- */
-
-struct nand_sdr_timings {
- u32 tALH_min;
- u32 tADL_min;
- u32 tALS_min;
- u32 tAR_min;
- u32 tCEA_max;
- u32 tCEH_min;
- u32 tCH_min;
- u32 tCHZ_max;
- u32 tCLH_min;
- u32 tCLR_min;
- u32 tCLS_min;
- u32 tCOH_min;
- u32 tCS_min;
- u32 tDH_min;
- u32 tDS_min;
- u32 tFEAT_max;
- u32 tIR_min;
- u32 tITC_max;
- u32 tRC_min;
- u32 tREA_max;
- u32 tREH_min;
- u32 tRHOH_min;
- u32 tRHW_min;
- u32 tRHZ_max;
- u32 tRLOH_min;
- u32 tRP_min;
- u32 tRR_min;
- u64 tRST_max;
- u32 tWB_max;
- u32 tWC_min;
- u32 tWH_min;
- u32 tWHR_min;
- u32 tWP_min;
- u32 tWW_min;
+ * nand_io_for_each_page - Iterate over all NAND pages contained in an MTD I/O
+ * request
+ * @nand: NAND device
+ * @start: start address to read/write from
+ * @req: MTD I/O request
+ * @iter: NAND I/O iterator
+ *
+ * Should be used for iterate over pages that are contained in an MTD request.
+ */
+#define nanddev_io_for_each_page(nand, start, req, iter) \
+ for (nanddev_io_iter_init(nand, start, req, iter); \
+ !nanddev_io_iter_end(nand, iter); \
+ nanddev_io_iter_next_page(nand, iter))
+
+bool nanddev_isbad(struct nand_device *nand, const struct nand_pos *pos);
+bool nanddev_isreserved(struct nand_device *nand, const struct nand_pos *pos);
+int nanddev_erase(struct nand_device *nand, const struct nand_pos *pos);
+int nanddev_markbad(struct nand_device *nand, const struct nand_pos *pos);
+
+/* BBT related functions */
+enum nand_bbt_block_status {
+ NAND_BBT_BLOCK_STATUS_UNKNOWN,
+ NAND_BBT_BLOCK_GOOD,
+ NAND_BBT_BLOCK_WORN,
+ NAND_BBT_BLOCK_RESERVED,
+ NAND_BBT_BLOCK_FACTORY_BAD,
+ NAND_BBT_BLOCK_NUM_STATUS,
};
-/* get timing characteristics from ONFI timing mode. */
-const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
+int nanddev_bbt_init(struct nand_device *nand);
+void nanddev_bbt_cleanup(struct nand_device *nand);
+int nanddev_bbt_update(struct nand_device *nand);
+int nanddev_bbt_get_block_status(const struct nand_device *nand,
+ unsigned int entry);
+int nanddev_bbt_set_block_status(struct nand_device *nand, unsigned int entry,
+ enum nand_bbt_block_status status);
+int nanddev_bbt_markbad(struct nand_device *nand, unsigned int block);
-static inline struct nand_chip *mtd_to_nand(struct mtd_info *mtd)
+/**
+ * nanddev_bbt_pos_to_entry() - Convert a NAND position into a BBT entry
+ * @nand: NAND device
+ * @pos: the NAND position we want to get BBT entry for
+ *
+ * Return the BBT entry used to store information about the eraseblock pointed
+ * by @pos.
+ *
+ * Return: the BBT entry storing information about eraseblock pointed by @pos.
+ */
+static inline unsigned int nanddev_bbt_pos_to_entry(struct nand_device *nand,
+ const struct nand_pos *pos)
{
- return container_of(mtd, struct nand_chip, mtd);
+ return pos->eraseblock +
+ ((pos->lun + (pos->target * nand->memorg.luns_per_target)) *
+ nand->memorg.eraseblocks_per_lun);
}
+/**
+ * nanddev_bbt_is_initialized() - Check if the BBT has been initialized
+ * @nand: NAND device
+ *
+ * Return: true if the BBT has been initialized, false otherwise.
+ */
+static inline bool nanddev_bbt_is_initialized(struct nand_device *nand)
+{
+ return !!nand->bbt.cache;
+}
+
+/* MTD -> NAND helper functions. */
+int nanddev_mtd_erase(struct mtd_info *mtd, struct erase_info *einfo);
+int nanddev_mtd_max_bad_blocks(struct mtd_info *mtd, loff_t offs, size_t len);
+int nand_check_erased_buf(void *buf, int len, int bitflips_threshold);
+
#endif /* __LINUX_MTD_NAND_H */
diff --git a/include/linux/mtd/nand_bch.h b/include/linux/mtd/nand_bch.h
index 5465ddd132..d5956cc48b 100644
--- a/include/linux/mtd/nand_bch.h
+++ b/include/linux/mtd/nand_bch.h
@@ -1,10 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright © 2011 Ivan Djelic <ivan.djelic@parrot.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 file is the header for the NAND BCH ECC implementation.
*/
@@ -12,23 +9,24 @@
#define __MTD_NAND_BCH_H__
struct mtd_info;
+struct nand_chip;
struct nand_bch_control;
-#if defined(CONFIG_NAND_ECC_BCH)
+#if IS_ENABLED(CONFIG_MTD_NAND_ECC_SW_BCH)
static inline int mtd_nand_has_bch(void) { return 1; }
/*
* Calculate BCH ecc code
*/
-int nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+int nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat,
u_char *ecc_code);
/*
* Detect and correct bit errors
*/
-int nand_bch_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc,
- u_char *calc_ecc);
+int nand_bch_correct_data(struct nand_chip *chip, u_char *dat,
+ u_char *read_ecc, u_char *calc_ecc);
/*
* Initialize BCH encoder/decoder
*/
@@ -38,22 +36,22 @@ struct nand_bch_control *nand_bch_init(struct mtd_info *mtd);
*/
void nand_bch_free(struct nand_bch_control *nbc);
-#else /* !CONFIG_MTD_NAND_ECC_BCH */
+#else /* !CONFIG_MTD_NAND_ECC_SW_BCH */
static inline int mtd_nand_has_bch(void) { return 0; }
static inline int
-nand_bch_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
+nand_bch_calculate_ecc(struct nand_chip *chip, const u_char *dat,
u_char *ecc_code)
{
return -1;
}
static inline int
-nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
+nand_bch_correct_data(struct nand_chip *chip, unsigned char *buf,
unsigned char *read_ecc, unsigned char *calc_ecc)
{
- return -1;
+ return -ENOTSUPP;
}
static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
@@ -63,6 +61,6 @@ static inline struct nand_bch_control *nand_bch_init(struct mtd_info *mtd)
static inline void nand_bch_free(struct nand_bch_control *nbc) {}
-#endif /* CONFIG_MTD_NAND_ECC_BCH */
+#endif /* CONFIG_MTD_NAND_ECC_SW_BCH */
#endif /* __MTD_NAND_BCH_H__ */
diff --git a/include/linux/mtd/nand_ecc.h b/include/linux/mtd/nand_ecc.h
index 12c5bc342e..d423916b94 100644
--- a/include/linux/mtd/nand_ecc.h
+++ b/include/linux/mtd/nand_ecc.h
@@ -1,13 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * drivers/mtd/nand_ecc.h
- *
- * Copyright (C) 2000 Steven J. Hill (sjhill@realitydiluted.com)
- *
- * $Id: nand_ecc.h,v 1.4 2004/06/17 02:35:02 dbrown Exp $
- *
- * 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.
+ * Copyright (C) 2000-2010 Steven J. Hill <sjhill@realitydiluted.com>
+ * David Woodhouse <dwmw2@infradead.org>
+ * Thomas Gleixner <tglx@linutronix.de>
*
* This file is the header for the ECC algorithm.
*/
@@ -15,16 +10,30 @@
#ifndef __MTD_NAND_ECC_H__
#define __MTD_NAND_ECC_H__
-struct mtd_info;
+struct nand_chip;
+
+/*
+ * Calculate 3 byte ECC code for eccsize byte block
+ */
+void __nand_calculate_ecc(const u_char *dat, unsigned int eccsize,
+ u_char *ecc_code, bool sm_order);
+
+/*
+ * Calculate 3 byte ECC code for 256/512 byte block
+ */
+int nand_calculate_ecc(struct nand_chip *chip, const u_char *dat,
+ u_char *ecc_code);
/*
- * Calculate 3 byte ECC code for 256 byte block
+ * Detect and correct a 1 bit error for eccsize byte block
*/
-int nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code);
+int __nand_correct_data(u_char *dat, u_char *read_ecc, u_char *calc_ecc,
+ unsigned int eccsize, bool sm_order);
/*
- * Detect and correct a 1 bit error for 256 byte block
+ * Detect and correct a 1 bit error for 256/512 byte block
*/
-int nand_correct_data(struct mtd_info *mtd, u_char *dat, u_char *read_ecc, u_char *calc_ecc);
+int nand_correct_data(struct nand_chip *chip, u_char *dat, u_char *read_ecc,
+ u_char *calc_ecc);
#endif /* __MTD_NAND_ECC_H__ */
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/onfi.h b/include/linux/mtd/onfi.h
new file mode 100644
index 0000000000..339ac79856
--- /dev/null
+++ b/include/linux/mtd/onfi.h
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ * Steven J. Hill <sjhill@realitydiluted.com>
+ * Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Contains all ONFI related definitions
+ */
+
+#ifndef __LINUX_MTD_ONFI_H
+#define __LINUX_MTD_ONFI_H
+
+#include <linux/types.h>
+
+/* ONFI version bits */
+#define ONFI_VERSION_1_0 BIT(1)
+#define ONFI_VERSION_2_0 BIT(2)
+#define ONFI_VERSION_2_1 BIT(3)
+#define ONFI_VERSION_2_2 BIT(4)
+#define ONFI_VERSION_2_3 BIT(5)
+#define ONFI_VERSION_3_0 BIT(6)
+#define ONFI_VERSION_3_1 BIT(7)
+#define ONFI_VERSION_3_2 BIT(8)
+#define ONFI_VERSION_4_0 BIT(9)
+
+/* ONFI features */
+#define ONFI_FEATURE_16_BIT_BUS (1 << 0)
+#define ONFI_FEATURE_EXT_PARAM_PAGE (1 << 7)
+
+/* ONFI timing mode, used in both asynchronous and synchronous mode */
+#define ONFI_TIMING_MODE_0 (1 << 0)
+#define ONFI_TIMING_MODE_1 (1 << 1)
+#define ONFI_TIMING_MODE_2 (1 << 2)
+#define ONFI_TIMING_MODE_3 (1 << 3)
+#define ONFI_TIMING_MODE_4 (1 << 4)
+#define ONFI_TIMING_MODE_5 (1 << 5)
+#define ONFI_TIMING_MODE_UNKNOWN (1 << 6)
+
+/* ONFI feature number/address */
+#define ONFI_FEATURE_NUMBER 256
+#define ONFI_FEATURE_ADDR_TIMING_MODE 0x1
+
+/* Vendor-specific feature address (Micron) */
+#define ONFI_FEATURE_ADDR_READ_RETRY 0x89
+#define ONFI_FEATURE_ON_DIE_ECC 0x90
+#define ONFI_FEATURE_ON_DIE_ECC_EN BIT(3)
+
+/* ONFI subfeature parameters length */
+#define ONFI_SUBFEATURE_PARAM_LEN 4
+
+/* ONFI optional commands SET/GET FEATURES supported? */
+#define ONFI_OPT_CMD_SET_GET_FEATURES (1 << 2)
+
+struct nand_onfi_params {
+ /* rev info and features block */
+ /* 'O' 'N' 'F' 'I' */
+ u8 sig[4];
+ __le16 revision;
+ __le16 features;
+ __le16 opt_cmd;
+ u8 reserved0[2];
+ __le16 ext_param_page_length; /* since ONFI 2.1 */
+ u8 num_of_param_pages; /* since ONFI 2.1 */
+ u8 reserved1[17];
+
+ /* manufacturer information block */
+ char manufacturer[12];
+ char model[20];
+ u8 jedec_id;
+ __le16 date_code;
+ u8 reserved2[13];
+
+ /* memory organization block */
+ __le32 byte_per_page;
+ __le16 spare_bytes_per_page;
+ __le32 data_bytes_per_ppage;
+ __le16 spare_bytes_per_ppage;
+ __le32 pages_per_block;
+ __le32 blocks_per_lun;
+ u8 lun_count;
+ u8 addr_cycles;
+ u8 bits_per_cell;
+ __le16 bb_per_lun;
+ __le16 block_endurance;
+ u8 guaranteed_good_blocks;
+ __le16 guaranteed_block_endurance;
+ u8 programs_per_page;
+ u8 ppage_attr;
+ u8 ecc_bits;
+ u8 interleaved_bits;
+ u8 interleaved_ops;
+ u8 reserved3[13];
+
+ /* electrical parameter block */
+ u8 io_pin_capacitance_max;
+ __le16 async_timing_mode;
+ __le16 program_cache_timing_mode;
+ __le16 t_prog;
+ __le16 t_bers;
+ __le16 t_r;
+ __le16 t_ccs;
+ __le16 src_sync_timing_mode;
+ u8 src_ssync_features;
+ __le16 clk_pin_capacitance_typ;
+ __le16 io_pin_capacitance_typ;
+ __le16 input_pin_capacitance_typ;
+ u8 input_pin_capacitance_max;
+ u8 driver_strength_support;
+ __le16 t_int_r;
+ __le16 t_adl;
+ u8 reserved4[8];
+
+ /* vendor */
+ __le16 vendor_revision;
+ u8 vendor[88];
+
+ __le16 crc;
+} __packed;
+
+#define ONFI_CRC_BASE 0x4F4E
+
+/* Extended ECC information Block Definition (since ONFI 2.1) */
+struct onfi_ext_ecc_info {
+ u8 ecc_bits;
+ u8 codeword_size;
+ __le16 bb_per_lun;
+ __le16 block_endurance;
+ u8 reserved[2];
+} __packed;
+
+#define ONFI_SECTION_TYPE_0 0 /* Unused section. */
+#define ONFI_SECTION_TYPE_1 1 /* for additional sections. */
+#define ONFI_SECTION_TYPE_2 2 /* for ECC information. */
+struct onfi_ext_section {
+ u8 type;
+ u8 length;
+} __packed;
+
+#define ONFI_EXT_SECTION_MAX 8
+
+/* Extended Parameter Page Definition (since ONFI 2.1) */
+struct onfi_ext_param_page {
+ __le16 crc;
+ u8 sig[4]; /* 'E' 'P' 'P' 'S' */
+ u8 reserved0[10];
+ struct onfi_ext_section sections[ONFI_EXT_SECTION_MAX];
+
+ /*
+ * The actual size of the Extended Parameter Page is in
+ * @ext_param_page_length of nand_onfi_params{}.
+ * The following are the variable length sections.
+ * So we do not add any fields below. Please see the ONFI spec.
+ */
+} __packed;
+
+/**
+ * struct onfi_params - ONFI specific parameters that will be reused
+ * @version: ONFI version (BCD encoded), 0 if ONFI is not supported
+ * @tPROG: Page program time
+ * @tBERS: Block erase time
+ * @tR: Page read time
+ * @tCCS: Change column setup time
+ * @async_timing_mode: Supported asynchronous timing mode
+ * @vendor_revision: Vendor specific revision number
+ * @vendor: Vendor specific data
+ */
+struct onfi_params {
+ int version;
+ u16 tPROG;
+ u16 tBERS;
+ u16 tR;
+ u16 tCCS;
+ u16 async_timing_mode;
+ u16 vendor_revision;
+ u8 vendor[88];
+};
+
+#endif /* __LINUX_MTD_ONFI_H */
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
new file mode 100644
index 0000000000..9ea2310bd9
--- /dev/null
+++ b/include/linux/mtd/partitions.h
@@ -0,0 +1,115 @@
+/*
+ * MTD partitioning layer definitions
+ *
+ * (C) 2000 Nicolas Pitre <nico@fluxnic.net>
+ *
+ * This code is GPL
+ */
+
+#ifndef MTD_PARTITIONS_H
+#define MTD_PARTITIONS_H
+
+#include <linux/types.h>
+
+
+/*
+ * Partition definition structure:
+ *
+ * An array of struct partition is passed along with a MTD object to
+ * mtd_device_register() to create them.
+ *
+ * For each partition, these fields are available:
+ * name: string that will be used to label the partition's MTD device.
+ * types: some partitions can be containers using specific format to describe
+ * embedded subpartitions / volumes. E.g. many home routers use "firmware"
+ * partition that contains at least kernel and rootfs. In such case an
+ * extra parser is needed that will detect these dynamic partitions and
+ * report them to the MTD subsystem. If set this property stores an array
+ * of parser names to use when looking for subpartitions.
+ * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition
+ * will extend to the end of the master MTD device.
+ * offset: absolute starting position within the master MTD device; if
+ * defined as MTDPART_OFS_APPEND, the partition will start where the
+ * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block;
+ * if MTDPART_OFS_RETAIN, consume as much as possible, leaving size
+ * after the end of partition.
+ * mask_flags: contains flags that have to be masked (removed) from the
+ * master MTD flag set for the corresponding MTD partition.
+ * For example, to force a read-only partition, simply adding
+ * MTD_WRITEABLE to the mask_flags will do the trick.
+ * add_flags: contains flags to add to the parent flags
+ *
+ * Note: writeable partitions require their size and offset be
+ * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK).
+ */
+
+struct mtd_partition {
+ const char *name; /* identifier string */
+ const char *const *types; /* names of parsers to use if any */
+ uint64_t size; /* partition size */
+ uint64_t offset; /* offset within the master MTD space */
+ uint32_t mask_flags; /* master MTD flags to mask out for this partition */
+ uint32_t add_flags; /* flags to add to the partition */
+ struct device_node *of_node;
+};
+
+#define MTDPART_OFS_RETAIN (-3)
+#define MTDPART_OFS_NXTBLK (-2)
+#define MTDPART_OFS_APPEND (-1)
+#define MTDPART_SIZ_FULL (0)
+
+
+struct mtd_info;
+struct device_node;
+
+/**
+ * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
+ * @origin: for RedBoot, start address of MTD device
+ */
+struct mtd_part_parser_data {
+ unsigned long origin;
+};
+
+
+/*
+ * Functions dealing with the various ways of partitioning the space
+ */
+
+struct mtd_part_parser {
+ struct list_head list;
+ struct module *owner;
+ const char *name;
+ const struct of_device_id *of_match_table;
+ int (*parse_fn)(struct mtd_info *, const struct mtd_partition **,
+ struct mtd_part_parser_data *);
+ void (*cleanup)(const struct mtd_partition *pparts, int nr_parts);
+};
+
+/* Container for passing around a set of parsed partitions */
+struct mtd_partitions {
+ const struct mtd_partition *parts;
+ int nr_parts;
+ const struct mtd_part_parser *parser;
+};
+
+extern int __register_mtd_parser(struct mtd_part_parser *parser,
+ struct module *owner);
+#define register_mtd_parser(parser) __register_mtd_parser(parser, THIS_MODULE)
+
+extern void deregister_mtd_parser(struct mtd_part_parser *parser);
+
+/*
+ * module_mtd_part_parser() - Helper macro for MTD partition parsers that don't
+ * do anything special in module init/exit. Each driver may only use this macro
+ * once, and calling it replaces module_init() and module_exit().
+ */
+#define module_mtd_part_parser(__mtd_part_parser) \
+ module_driver(__mtd_part_parser, register_mtd_parser, \
+ deregister_mtd_parser)
+
+struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset,
+ uint64_t size, unsigned long flags, const char *name);
+int mtd_del_partition(struct mtd_info *part);
+uint64_t mtd_get_device_size(const struct mtd_info *mtd);
+
+#endif
diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
new file mode 100644
index 0000000000..54a788cc18
--- /dev/null
+++ b/include/linux/mtd/rawnand.h
@@ -0,0 +1,1495 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
+ * Steven J. Hill <sjhill@realitydiluted.com>
+ * Thomas Gleixner <tglx@linutronix.de>
+ *
+ * Info:
+ * Contains standard defines and IDs for NAND flash devices
+ *
+ * Changelog:
+ * See git changelog.
+ */
+#ifndef __LINUX_MTD_RAWNAND_H
+#define __LINUX_MTD_RAWNAND_H
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/flashchip.h>
+#include <linux/mtd/bbm.h>
+#include <linux/mtd/jedec.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/onfi.h>
+#include <linux/bitmap.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+#include <common.h>
+
+struct nand_chip;
+
+/* The maximum number of NAND chips in an array */
+#define NAND_MAX_CHIPS 8
+
+/*
+ * Constants for hardware specific CLE/ALE/NCE function
+ *
+ * These are bits which can be or'ed to set/clear multiple
+ * bits in one go.
+ */
+/* Select the chip by setting nCE to low */
+#define NAND_NCE 0x01
+/* Select the command latch by setting CLE to high */
+#define NAND_CLE 0x02
+/* Select the address latch by setting ALE to high */
+#define NAND_ALE 0x04
+
+#define NAND_CTRL_CLE (NAND_NCE | NAND_CLE)
+#define NAND_CTRL_ALE (NAND_NCE | NAND_ALE)
+#define NAND_CTRL_CHANGE 0x80
+
+/*
+ * Standard NAND flash commands
+ */
+#define NAND_CMD_READ0 0
+#define NAND_CMD_READ1 1
+#define NAND_CMD_RNDOUT 5
+#define NAND_CMD_PAGEPROG 0x10
+#define NAND_CMD_READOOB 0x50
+#define NAND_CMD_ERASE1 0x60
+#define NAND_CMD_STATUS 0x70
+#define NAND_CMD_SEQIN 0x80
+#define NAND_CMD_RNDIN 0x85
+#define NAND_CMD_READID 0x90
+#define NAND_CMD_ERASE2 0xd0
+#define NAND_CMD_PARAM 0xec
+#define NAND_CMD_GET_FEATURES 0xee
+#define NAND_CMD_SET_FEATURES 0xef
+#define NAND_CMD_RESET 0xff
+
+/* Extended commands for large page devices */
+#define NAND_CMD_READSTART 0x30
+#define NAND_CMD_RNDOUTSTART 0xE0
+#define NAND_CMD_CACHEDPROG 0x15
+
+#define NAND_CMD_NONE -1
+
+/* Status bits */
+#define NAND_STATUS_FAIL 0x01
+#define NAND_STATUS_FAIL_N1 0x02
+#define NAND_STATUS_TRUE_READY 0x20
+#define NAND_STATUS_READY 0x40
+#define NAND_STATUS_WP 0x80
+
+#define NAND_DATA_IFACE_CHECK_ONLY -1
+
+/*
+ * Constants for ECC_MODES
+ */
+enum nand_ecc_mode {
+ NAND_ECC_INVALID,
+ NAND_ECC_NONE,
+ NAND_ECC_SOFT,
+ NAND_ECC_HW,
+ NAND_ECC_HW_SYNDROME,
+ NAND_ECC_ON_DIE,
+ NAND_ECC_HW_OOB_FIRST,
+ 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_ALGO_UNKNOWN,
+ NAND_ECC_ALGO_HAMMING,
+ NAND_ECC_ALGO_BCH,
+ NAND_ECC_ALGO_RS,
+};
+
+/*
+ * Constants for Hardware ECC
+ */
+/* Reset Hardware ECC for read */
+#define NAND_ECC_READ 0
+/* Reset Hardware ECC for write */
+#define NAND_ECC_WRITE 1
+/* Enable Hardware ECC before syndrome is read back from flash */
+#define NAND_ECC_READSYN 2
+
+/*
+ * Enable generic NAND 'page erased' check. This check is only done when
+ * ecc.correct() returns -EBADMSG.
+ * Set this flag if your implementation does not fix bitflips in erased
+ * pages and you want to rely on the default implementation.
+ */
+#define NAND_ECC_GENERIC_ERASED_CHECK BIT(0)
+#define NAND_ECC_MAXIMIZE BIT(1)
+
+/*
+ * Option constants for bizarre disfunctionality and real
+ * features.
+ */
+
+/* Buswidth is 16 bit */
+#define NAND_BUSWIDTH_16 BIT(1)
+
+/*
+ * When using software implementation of Hamming, we can specify which byte
+ * ordering should be used.
+ */
+#define NAND_ECC_SOFT_HAMMING_SM_ORDER BIT(2)
+
+/* Chip has cache program function */
+#define NAND_CACHEPRG BIT(3)
+/* Options valid for Samsung large page devices */
+#define NAND_SAMSUNG_LP_OPTIONS NAND_CACHEPRG
+
+/*
+ * Chip requires ready check on read (for auto-incremented sequential read).
+ * True only for small page devices; large page devices do not support
+ * autoincrement.
+ */
+#define NAND_NEED_READRDY BIT(8)
+
+/* Chip does not allow subpage writes */
+#define NAND_NO_SUBPAGE_WRITE BIT(9)
+
+/* Device is one of 'new' xD cards that expose fake nand command set */
+#define NAND_BROKEN_XD BIT(10)
+
+/* Device behaves just like nand, but is readonly */
+#define NAND_ROM BIT(11)
+
+/* Device supports subpage reads */
+#define NAND_SUBPAGE_READ BIT(12)
+/* Macros to identify the above */
+#define NAND_HAS_SUBPAGE_READ(chip) ((chip->options & NAND_SUBPAGE_READ))
+
+/*
+ * Some MLC NANDs need data scrambling to limit bitflips caused by repeated
+ * patterns.
+ */
+#define NAND_NEED_SCRAMBLING BIT(13)
+
+/* Device needs 3rd row address cycle */
+#define NAND_ROW_ADDR_3 BIT(14)
+
+/* Non chip related options */
+/* This option skips the bbt scan during initialization. */
+#define NAND_SKIP_BBTSCAN BIT(16)
+/* Chip may not exist, so silence any errors in scan */
+#define NAND_SCAN_SILENT_NODEV BIT(18)
+
+/*
+ * Autodetect nand buswidth with readid/onfi.
+ * This suppose the driver will configure the hardware in 8 bits mode
+ * when calling nand_scan_ident, and update its configuration
+ * before calling nand_scan_tail.
+ */
+#define NAND_BUSWIDTH_AUTO BIT(19)
+
+/*
+ * This option could be defined by controller drivers to protect against
+ * kmap'ed, vmalloc'ed highmem buffers being passed from upper layers
+ */
+#define NAND_USES_DMA BIT(20)
+
+/*
+ * In case your controller is implementing ->legacy.cmd_ctrl() and is relying
+ * on the default ->cmdfunc() implementation, you may want to let the core
+ * handle the tCCS delay which is required when a column change (RNDIN or
+ * RNDOUT) is requested.
+ * If your controller already takes care of this delay, you don't need to set
+ * this flag.
+ */
+#define NAND_WAIT_TCCS BIT(21)
+
+/*
+ * Whether the NAND chip is a boot medium. Drivers might use this information
+ * to select ECC algorithms supported by the boot ROM or similar restrictions.
+ */
+#define NAND_IS_BOOT_MEDIUM BIT(22)
+
+/*
+ * Do not try to tweak the timings at runtime. This is needed when the
+ * controller initializes the timings on itself or when it relies on
+ * configuration done by the bootloader.
+ */
+#define NAND_KEEP_TIMINGS BIT(23)
+
+/*
+ * There are different places where the manufacturer stores the factory bad
+ * block markers.
+ *
+ * Position within the block: Each of these pages needs to be checked for a
+ * bad block marking pattern.
+ */
+#define NAND_BBM_FIRSTPAGE BIT(24)
+#define NAND_BBM_SECONDPAGE BIT(25)
+#define NAND_BBM_LASTPAGE BIT(26)
+
+/*
+ * Some controllers with pipelined ECC engines override the BBM marker with
+ * data or ECC bytes, thus making bad block detection through bad block marker
+ * impossible. Let's flag those chips so the core knows it shouldn't check the
+ * BBM and consider all blocks good.
+ */
+#define NAND_NO_BBM_QUIRK BIT(27)
+
+/* Cell info constants */
+#define NAND_CI_CHIPNR_MSK 0x03
+#define NAND_CI_CELLTYPE_MSK 0x0C
+#define NAND_CI_CELLTYPE_SHIFT 2
+
+/* Position within the OOB data of the page */
+#define NAND_BBM_POS_SMALL 5
+#define NAND_BBM_POS_LARGE 0
+
+/**
+ * struct nand_parameters - NAND generic parameters from the parameter page
+ * @model: Model name
+ * @supports_set_get_features: The NAND chip supports setting/getting features
+ * @set_feature_list: Bitmap of features that can be set
+ * @get_feature_list: Bitmap of features that can be get
+ * @onfi: ONFI specific parameters
+ */
+struct nand_parameters {
+ /* Generic parameters */
+ const char *model;
+ bool supports_set_get_features;
+ DECLARE_BITMAP(set_feature_list, ONFI_FEATURE_NUMBER);
+ DECLARE_BITMAP(get_feature_list, ONFI_FEATURE_NUMBER);
+
+ /* ONFI parameters */
+ struct onfi_params *onfi;
+};
+
+/* The maximum expected count of bytes in the NAND ID sequence */
+#define NAND_MAX_ID_LEN 8
+
+/**
+ * struct nand_id - NAND id structure
+ * @data: buffer containing the id bytes.
+ * @len: ID length.
+ */
+struct nand_id {
+ u8 data[NAND_MAX_ID_LEN];
+ int len;
+};
+
+/**
+ * struct nand_ecc_step_info - ECC step information of ECC engine
+ * @stepsize: data bytes per ECC step
+ * @strengths: array of supported strengths
+ * @nstrengths: number of supported strengths
+ */
+struct nand_ecc_step_info {
+ int stepsize;
+ const int *strengths;
+ int nstrengths;
+};
+
+/**
+ * struct nand_ecc_caps - capability of ECC engine
+ * @stepinfos: array of ECC step information
+ * @nstepinfos: number of ECC step information
+ * @calc_ecc_bytes: driver's hook to calculate ECC bytes per step
+ */
+struct nand_ecc_caps {
+ const struct nand_ecc_step_info *stepinfos;
+ int nstepinfos;
+ int (*calc_ecc_bytes)(int step_size, int strength);
+};
+
+/* a shorthand to generate struct nand_ecc_caps with only one ECC stepsize */
+#define NAND_ECC_CAPS_SINGLE(__name, __calc, __step, ...) \
+static const int __name##_strengths[] = { __VA_ARGS__ }; \
+static const struct nand_ecc_step_info __name##_stepinfo = { \
+ .stepsize = __step, \
+ .strengths = __name##_strengths, \
+ .nstrengths = ARRAY_SIZE(__name##_strengths), \
+}; \
+static const struct nand_ecc_caps __name = { \
+ .stepinfos = &__name##_stepinfo, \
+ .nstepinfos = 1, \
+ .calc_ecc_bytes = __calc, \
+}
+
+/**
+ * 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
+ * @size: data bytes per ECC step
+ * @bytes: ECC bytes per step
+ * @strength: max number of correctible bits per ECC step
+ * @total: total number of ECC bytes per page
+ * @prepad: padding information for syndrome based ECC generators
+ * @postpad: padding information for syndrome based ECC generators
+ * @options: ECC specific options (see NAND_ECC_XXX flags defined above)
+ * @priv: pointer to private ECC control data
+ * @calc_buf: buffer for calculated ECC, size is oobsize.
+ * @code_buf: buffer for ECC read from flash, size is oobsize.
+ * @hwctl: function to control hardware ECC generator. Must only
+ * be provided if an hardware ECC is available
+ * @calculate: function for ECC calculation or readback from ECC hardware
+ * @correct: function for ECC correction, matching to ECC generator (sw/hw).
+ * Should return a positive number representing the number of
+ * corrected bitflips, -EBADMSG if the number of bitflips exceed
+ * ECC strength, or any other error code if the error is not
+ * directly related to correction.
+ * If -EBADMSG is returned the input buffers should be left
+ * untouched.
+ * @read_page_raw: function to read a raw page without ECC. This function
+ * should hide the specific layout used by the ECC
+ * controller and always return contiguous in-band and
+ * out-of-band data even if they're not stored
+ * contiguously on the NAND chip (e.g.
+ * NAND_ECC_HW_SYNDROME interleaves in-band and
+ * out-of-band data).
+ * @write_page_raw: function to write a raw page without ECC. This function
+ * should hide the specific layout used by the ECC
+ * controller and consider the passed data as contiguous
+ * in-band and out-of-band data. ECC controller is
+ * responsible for doing the appropriate transformations
+ * to adapt to its specific layout (e.g.
+ * NAND_ECC_HW_SYNDROME interleaves in-band and
+ * out-of-band data).
+ * @read_page: function to read a page according to the ECC generator
+ * requirements; returns maximum number of bitflips corrected in
+ * any single ECC step, -EIO hw error
+ * @read_subpage: function to read parts of the page covered by ECC;
+ * returns same as read_page()
+ * @write_subpage: function to write parts of the page covered by ECC.
+ * @write_page: function to write a page according to the ECC generator
+ * requirements.
+ * @write_oob_raw: function to write chip OOB data without ECC
+ * @read_oob_raw: function to read chip OOB data without ECC
+ * @read_oob: function to read chip OOB data
+ * @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;
+ int size;
+ int bytes;
+ int total;
+ int strength;
+ int prepad;
+ int postpad;
+ unsigned int options;
+ void *priv;
+ u8 *calc_buf;
+ u8 *code_buf;
+ void (*hwctl)(struct nand_chip *chip, int mode);
+ int (*calculate)(struct nand_chip *chip, const uint8_t *dat,
+ uint8_t *ecc_code);
+ int (*correct)(struct nand_chip *chip, uint8_t *dat, uint8_t *read_ecc,
+ uint8_t *calc_ecc);
+ int (*read_page_raw)(struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page);
+ int (*write_page_raw)(struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page);
+ int (*read_page)(struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page);
+ int (*read_subpage)(struct nand_chip *chip, uint32_t offs,
+ uint32_t len, uint8_t *buf, int page);
+ int (*write_subpage)(struct nand_chip *chip, uint32_t offset,
+ uint32_t data_len, const uint8_t *data_buf,
+ int oob_required, int page);
+ int (*write_page)(struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page);
+ int (*write_oob_raw)(struct nand_chip *chip, int page);
+ int (*read_oob_raw)(struct nand_chip *chip, int page);
+ int (*read_oob)(struct nand_chip *chip, int page);
+ int (*write_oob)(struct nand_chip *chip, int page);
+};
+
+/**
+ * struct nand_sdr_timings - SDR NAND chip timings
+ *
+ * This struct defines the timing requirements of a SDR NAND chip.
+ * These information can be found in every NAND datasheets and the timings
+ * meaning are described in the ONFI specifications:
+ * www.onfi.org/~/media/ONFI/specs/onfi_3_1_spec.pdf (chapter 4.15 Timing
+ * Parameters)
+ *
+ * All these timings are expressed in picoseconds.
+ *
+ * @tBERS_max: Block erase time
+ * @tCCS_min: Change column setup time
+ * @tPROG_max: Page program time
+ * @tR_max: Page read time
+ * @tALH_min: ALE hold time
+ * @tADL_min: ALE to data loading time
+ * @tALS_min: ALE setup time
+ * @tAR_min: ALE to RE# delay
+ * @tCEA_max: CE# access time
+ * @tCEH_min: CE# high hold time
+ * @tCH_min: CE# hold time
+ * @tCHZ_max: CE# high to output hi-Z
+ * @tCLH_min: CLE hold time
+ * @tCLR_min: CLE to RE# delay
+ * @tCLS_min: CLE setup time
+ * @tCOH_min: CE# high to output hold
+ * @tCS_min: CE# setup time
+ * @tDH_min: Data hold time
+ * @tDS_min: Data setup time
+ * @tFEAT_max: Busy time for Set Features and Get Features
+ * @tIR_min: Output hi-Z to RE# low
+ * @tITC_max: Interface and Timing Mode Change time
+ * @tRC_min: RE# cycle time
+ * @tREA_max: RE# access time
+ * @tREH_min: RE# high hold time
+ * @tRHOH_min: RE# high to output hold
+ * @tRHW_min: RE# high to WE# low
+ * @tRHZ_max: RE# high to output hi-Z
+ * @tRLOH_min: RE# low to output hold
+ * @tRP_min: RE# pulse width
+ * @tRR_min: Ready to RE# low (data only)
+ * @tRST_max: Device reset time, measured from the falling edge of R/B# to the
+ * rising edge of R/B#.
+ * @tWB_max: WE# high to SR[6] low
+ * @tWC_min: WE# cycle time
+ * @tWH_min: WE# high hold time
+ * @tWHR_min: WE# high to RE# low
+ * @tWP_min: WE# pulse width
+ * @tWW_min: WP# transition to WE# low
+ */
+struct nand_sdr_timings {
+ u64 tBERS_max;
+ u32 tCCS_min;
+ u64 tPROG_max;
+ u64 tR_max;
+ u32 tALH_min;
+ u32 tADL_min;
+ u32 tALS_min;
+ u32 tAR_min;
+ u32 tCEA_max;
+ u32 tCEH_min;
+ u32 tCH_min;
+ u32 tCHZ_max;
+ u32 tCLH_min;
+ u32 tCLR_min;
+ u32 tCLS_min;
+ u32 tCOH_min;
+ u32 tCS_min;
+ u32 tDH_min;
+ u32 tDS_min;
+ u32 tFEAT_max;
+ u32 tIR_min;
+ u32 tITC_max;
+ u32 tRC_min;
+ u32 tREA_max;
+ u32 tREH_min;
+ u32 tRHOH_min;
+ u32 tRHW_min;
+ u32 tRHZ_max;
+ u32 tRLOH_min;
+ u32 tRP_min;
+ u32 tRR_min;
+ u64 tRST_max;
+ u32 tWB_max;
+ u32 tWC_min;
+ u32 tWH_min;
+ u32 tWHR_min;
+ u32 tWP_min;
+ u32 tWW_min;
+};
+
+/**
+ * enum nand_interface_type - NAND interface type
+ * @NAND_SDR_IFACE: Single Data Rate interface
+ */
+enum nand_interface_type {
+ NAND_SDR_IFACE,
+};
+
+/**
+ * struct nand_interface_config - NAND interface timing
+ * @type: type of the timing
+ * @timings: The timing information
+ * @timings.mode: Timing mode as defined in the specification
+ * @timings.sdr: Use it when @type is %NAND_SDR_IFACE.
+ */
+struct nand_interface_config {
+ enum nand_interface_type type;
+ struct nand_timings {
+ unsigned int mode;
+ union {
+ struct nand_sdr_timings sdr;
+ };
+ } timings;
+};
+
+/**
+ * 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 (!nand_interface_is_sdr(conf))
+ return ERR_PTR(-EINVAL);
+
+ return &conf->timings.sdr;
+}
+
+/**
+ * struct nand_op_cmd_instr - Definition of a command instruction
+ * @opcode: the command to issue in one cycle
+ */
+struct nand_op_cmd_instr {
+ u8 opcode;
+};
+
+/**
+ * struct nand_op_addr_instr - Definition of an address instruction
+ * @naddrs: length of the @addrs array
+ * @addrs: array containing the address cycles to issue
+ */
+struct nand_op_addr_instr {
+ unsigned int naddrs;
+ const u8 *addrs;
+};
+
+/**
+ * struct nand_op_data_instr - Definition of a data instruction
+ * @len: number of data bytes to move
+ * @buf: buffer to fill
+ * @buf.in: buffer to fill when reading from the NAND chip
+ * @buf.out: buffer to read from when writing to the NAND chip
+ * @force_8bit: force 8-bit access
+ *
+ * Please note that "in" and "out" are inverted from the ONFI specification
+ * and are from the controller perspective, so a "in" is a read from the NAND
+ * chip while a "out" is a write to the NAND chip.
+ */
+struct nand_op_data_instr {
+ unsigned int len;
+ union {
+ void *in;
+ const void *out;
+ } buf;
+ bool force_8bit;
+};
+
+/**
+ * struct nand_op_waitrdy_instr - Definition of a wait ready instruction
+ * @timeout_ms: maximum delay while waiting for the ready/busy pin in ms
+ */
+struct nand_op_waitrdy_instr {
+ unsigned int timeout_ms;
+};
+
+/**
+ * enum nand_op_instr_type - Definition of all instruction types
+ * @NAND_OP_CMD_INSTR: command instruction
+ * @NAND_OP_ADDR_INSTR: address instruction
+ * @NAND_OP_DATA_IN_INSTR: data in instruction
+ * @NAND_OP_DATA_OUT_INSTR: data out instruction
+ * @NAND_OP_WAITRDY_INSTR: wait ready instruction
+ */
+enum nand_op_instr_type {
+ NAND_OP_CMD_INSTR,
+ NAND_OP_ADDR_INSTR,
+ NAND_OP_DATA_IN_INSTR,
+ NAND_OP_DATA_OUT_INSTR,
+ NAND_OP_WAITRDY_INSTR,
+};
+
+/**
+ * struct nand_op_instr - Instruction object
+ * @type: the instruction type
+ * @ctx: extra data associated to the instruction. You'll have to use the
+ * appropriate element depending on @type
+ * @ctx.cmd: use it if @type is %NAND_OP_CMD_INSTR
+ * @ctx.addr: use it if @type is %NAND_OP_ADDR_INSTR
+ * @ctx.data: use it if @type is %NAND_OP_DATA_IN_INSTR
+ * or %NAND_OP_DATA_OUT_INSTR
+ * @ctx.waitrdy: use it if @type is %NAND_OP_WAITRDY_INSTR
+ * @delay_ns: delay the controller should apply after the instruction has been
+ * issued on the bus. Most modern controllers have internal timings
+ * control logic, and in this case, the controller driver can ignore
+ * this field.
+ */
+struct nand_op_instr {
+ enum nand_op_instr_type type;
+ union {
+ struct nand_op_cmd_instr cmd;
+ struct nand_op_addr_instr addr;
+ struct nand_op_data_instr data;
+ struct nand_op_waitrdy_instr waitrdy;
+ } ctx;
+ unsigned int delay_ns;
+};
+
+/*
+ * Special handling must be done for the WAITRDY timeout parameter as it usually
+ * is either tPROG (after a prog), tR (before a read), tRST (during a reset) or
+ * tBERS (during an erase) which all of them are u64 values that cannot be
+ * divided by usual kernel macros and must be handled with the special
+ * DIV_ROUND_UP_ULL() macro.
+ *
+ * Cast to type of dividend is needed here to guarantee that the result won't
+ * be an unsigned long long when the dividend is an unsigned long (or smaller),
+ * which is what the compiler does when it sees ternary operator with 2
+ * different return types (picks the largest type to make sure there's no
+ * loss).
+ */
+#define __DIVIDE(dividend, divisor) ({ \
+ (__typeof__(dividend))(sizeof(dividend) <= sizeof(unsigned long) ? \
+ DIV_ROUND_UP(dividend, divisor) : \
+ DIV_ROUND_UP_ULL(dividend, divisor)); \
+ })
+#define PSEC_TO_NSEC(x) __DIVIDE(x, 1000)
+#define PSEC_TO_MSEC(x) __DIVIDE(x, 1000000000)
+
+#define NAND_OP_CMD(id, ns) \
+ { \
+ .type = NAND_OP_CMD_INSTR, \
+ .ctx.cmd.opcode = id, \
+ .delay_ns = ns, \
+ }
+
+#define NAND_OP_ADDR(ncycles, cycles, ns) \
+ { \
+ .type = NAND_OP_ADDR_INSTR, \
+ .ctx.addr = { \
+ .naddrs = ncycles, \
+ .addrs = cycles, \
+ }, \
+ .delay_ns = ns, \
+ }
+
+#define NAND_OP_DATA_IN(l, b, ns) \
+ { \
+ .type = NAND_OP_DATA_IN_INSTR, \
+ .ctx.data = { \
+ .len = l, \
+ .buf.in = b, \
+ .force_8bit = false, \
+ }, \
+ .delay_ns = ns, \
+ }
+
+#define NAND_OP_DATA_OUT(l, b, ns) \
+ { \
+ .type = NAND_OP_DATA_OUT_INSTR, \
+ .ctx.data = { \
+ .len = l, \
+ .buf.out = b, \
+ .force_8bit = false, \
+ }, \
+ .delay_ns = ns, \
+ }
+
+#define NAND_OP_8BIT_DATA_IN(l, b, ns) \
+ { \
+ .type = NAND_OP_DATA_IN_INSTR, \
+ .ctx.data = { \
+ .len = l, \
+ .buf.in = b, \
+ .force_8bit = true, \
+ }, \
+ .delay_ns = ns, \
+ }
+
+#define NAND_OP_8BIT_DATA_OUT(l, b, ns) \
+ { \
+ .type = NAND_OP_DATA_OUT_INSTR, \
+ .ctx.data = { \
+ .len = l, \
+ .buf.out = b, \
+ .force_8bit = true, \
+ }, \
+ .delay_ns = ns, \
+ }
+
+#define NAND_OP_WAIT_RDY(tout_ms, ns) \
+ { \
+ .type = NAND_OP_WAITRDY_INSTR, \
+ .ctx.waitrdy.timeout_ms = tout_ms, \
+ .delay_ns = ns, \
+ }
+
+/**
+ * struct nand_subop - a sub operation
+ * @cs: the CS line to select for this NAND sub-operation
+ * @instrs: array of instructions
+ * @ninstrs: length of the @instrs array
+ * @first_instr_start_off: offset to start from for the first instruction
+ * of the sub-operation
+ * @last_instr_end_off: offset to end at (excluded) for the last instruction
+ * of the sub-operation
+ *
+ * Both @first_instr_start_off and @last_instr_end_off only apply to data or
+ * address instructions.
+ *
+ * When an operation cannot be handled as is by the NAND controller, it will
+ * be split by the parser into sub-operations which will be passed to the
+ * controller driver.
+ */
+struct nand_subop {
+ unsigned int cs;
+ const struct nand_op_instr *instrs;
+ unsigned int ninstrs;
+ unsigned int first_instr_start_off;
+ unsigned int last_instr_end_off;
+};
+
+unsigned int nand_subop_get_addr_start_off(const struct nand_subop *subop,
+ unsigned int op_id);
+unsigned int nand_subop_get_num_addr_cyc(const struct nand_subop *subop,
+ unsigned int op_id);
+unsigned int nand_subop_get_data_start_off(const struct nand_subop *subop,
+ unsigned int op_id);
+unsigned int nand_subop_get_data_len(const struct nand_subop *subop,
+ unsigned int op_id);
+
+/**
+ * struct nand_op_parser_addr_constraints - Constraints for address instructions
+ * @maxcycles: maximum number of address cycles the controller can issue in a
+ * single step
+ */
+struct nand_op_parser_addr_constraints {
+ unsigned int maxcycles;
+};
+
+/**
+ * struct nand_op_parser_data_constraints - Constraints for data instructions
+ * @maxlen: maximum data length that the controller can handle in a single step
+ */
+struct nand_op_parser_data_constraints {
+ unsigned int maxlen;
+};
+
+/**
+ * struct nand_op_parser_pattern_elem - One element of a pattern
+ * @type: the instructuction type
+ * @optional: whether this element of the pattern is optional or mandatory
+ * @ctx: address or data constraint
+ * @ctx.addr: address constraint (number of cycles)
+ * @ctx.data: data constraint (data length)
+ */
+struct nand_op_parser_pattern_elem {
+ enum nand_op_instr_type type;
+ bool optional;
+ union {
+ struct nand_op_parser_addr_constraints addr;
+ struct nand_op_parser_data_constraints data;
+ } ctx;
+};
+
+#define NAND_OP_PARSER_PAT_CMD_ELEM(_opt) \
+ { \
+ .type = NAND_OP_CMD_INSTR, \
+ .optional = _opt, \
+ }
+
+#define NAND_OP_PARSER_PAT_ADDR_ELEM(_opt, _maxcycles) \
+ { \
+ .type = NAND_OP_ADDR_INSTR, \
+ .optional = _opt, \
+ .ctx.addr.maxcycles = _maxcycles, \
+ }
+
+#define NAND_OP_PARSER_PAT_DATA_IN_ELEM(_opt, _maxlen) \
+ { \
+ .type = NAND_OP_DATA_IN_INSTR, \
+ .optional = _opt, \
+ .ctx.data.maxlen = _maxlen, \
+ }
+
+#define NAND_OP_PARSER_PAT_DATA_OUT_ELEM(_opt, _maxlen) \
+ { \
+ .type = NAND_OP_DATA_OUT_INSTR, \
+ .optional = _opt, \
+ .ctx.data.maxlen = _maxlen, \
+ }
+
+#define NAND_OP_PARSER_PAT_WAITRDY_ELEM(_opt) \
+ { \
+ .type = NAND_OP_WAITRDY_INSTR, \
+ .optional = _opt, \
+ }
+
+/**
+ * struct nand_op_parser_pattern - NAND sub-operation pattern descriptor
+ * @elems: array of pattern elements
+ * @nelems: number of pattern elements in @elems array
+ * @exec: the function that will issue a sub-operation
+ *
+ * A pattern is a list of elements, each element reprensenting one instruction
+ * with its constraints. The pattern itself is used by the core to match NAND
+ * chip operation with NAND controller operations.
+ * Once a match between a NAND controller operation pattern and a NAND chip
+ * operation (or a sub-set of a NAND operation) is found, the pattern ->exec()
+ * hook is called so that the controller driver can issue the operation on the
+ * bus.
+ *
+ * Controller drivers should declare as many patterns as they support and pass
+ * this list of patterns (created with the help of the following macro) to
+ * the nand_op_parser_exec_op() helper.
+ */
+struct nand_op_parser_pattern {
+ const struct nand_op_parser_pattern_elem *elems;
+ unsigned int nelems;
+ int (*exec)(struct nand_chip *chip, const struct nand_subop *subop);
+};
+
+#define NAND_OP_PARSER_PATTERN(_exec, ...) \
+ { \
+ .exec = _exec, \
+ .elems = (const struct nand_op_parser_pattern_elem[]) { __VA_ARGS__ }, \
+ .nelems = sizeof((struct nand_op_parser_pattern_elem[]) { __VA_ARGS__ }) / \
+ sizeof(struct nand_op_parser_pattern_elem), \
+ }
+
+/**
+ * struct nand_op_parser - NAND controller operation parser descriptor
+ * @patterns: array of supported patterns
+ * @npatterns: length of the @patterns array
+ *
+ * The parser descriptor is just an array of supported patterns which will be
+ * iterated by nand_op_parser_exec_op() everytime it tries to execute an
+ * NAND operation (or tries to determine if a specific operation is supported).
+ *
+ * It is worth mentioning that patterns will be tested in their declaration
+ * order, and the first match will be taken, so it's important to order patterns
+ * appropriately so that simple/inefficient patterns are placed at the end of
+ * the list. Usually, this is where you put single instruction patterns.
+ */
+struct nand_op_parser {
+ const struct nand_op_parser_pattern *patterns;
+ unsigned int npatterns;
+};
+
+#define NAND_OP_PARSER(...) \
+ { \
+ .patterns = (const struct nand_op_parser_pattern[]) { __VA_ARGS__ }, \
+ .npatterns = sizeof((struct nand_op_parser_pattern[]) { __VA_ARGS__ }) / \
+ sizeof(struct nand_op_parser_pattern), \
+ }
+
+/**
+ * struct nand_operation - NAND operation descriptor
+ * @cs: the CS line to select for this NAND operation
+ * @instrs: array of instructions to execute
+ * @ninstrs: length of the @instrs array
+ *
+ * The actual operation structure that will be passed to chip->exec_op().
+ */
+struct nand_operation {
+ unsigned int cs;
+ const struct nand_op_instr *instrs;
+ unsigned int ninstrs;
+};
+
+#define NAND_OPERATION(_cs, _instrs) \
+ { \
+ .cs = _cs, \
+ .instrs = _instrs, \
+ .ninstrs = ARRAY_SIZE(_instrs), \
+ }
+
+int nand_op_parser_exec_op(struct nand_chip *chip,
+ const struct nand_op_parser *parser,
+ const struct nand_operation *op, bool check_only);
+
+static inline void nand_op_trace(const char *prefix,
+ const struct nand_op_instr *instr)
+{
+#if IS_ENABLED(CONFIG_DYNAMIC_DEBUG) || defined(DEBUG)
+ switch (instr->type) {
+ case NAND_OP_CMD_INSTR:
+ pr_debug("%sCMD [0x%02x]\n", prefix,
+ instr->ctx.cmd.opcode);
+ break;
+ case NAND_OP_ADDR_INSTR:
+ pr_debug("%sADDR [%d cyc: %*ph]\n", prefix,
+ instr->ctx.addr.naddrs,
+ instr->ctx.addr.naddrs < 64 ?
+ instr->ctx.addr.naddrs : 64,
+ instr->ctx.addr.addrs);
+ break;
+ case NAND_OP_DATA_IN_INSTR:
+ pr_debug("%sDATA_IN [%d B%s]\n", prefix,
+ instr->ctx.data.len,
+ instr->ctx.data.force_8bit ?
+ ", force 8-bit" : "");
+ break;
+ case NAND_OP_DATA_OUT_INSTR:
+ pr_debug("%sDATA_OUT [%d B%s]\n", prefix,
+ instr->ctx.data.len,
+ instr->ctx.data.force_8bit ?
+ ", force 8-bit" : "");
+ break;
+ case NAND_OP_WAITRDY_INSTR:
+ pr_debug("%sWAITRDY [max %d ms]\n", prefix,
+ instr->ctx.waitrdy.timeout_ms);
+ break;
+ }
+#endif
+}
+
+/**
+ * struct nand_controller_ops - Controller operations
+ *
+ * @attach_chip: this method is called after the NAND detection phase after
+ * flash ID and MTD fields such as erase size, page size and OOB
+ * size have been set up. ECC requirements are available if
+ * provided by the NAND chip or device tree. Typically used to
+ * choose the appropriate ECC configuration and allocate
+ * associated resources.
+ * This hook is optional.
+ * @detach_chip: free all resources allocated/claimed in
+ * nand_controller_ops->attach_chip().
+ * This hook is optional.
+ * @exec_op: controller specific method to execute NAND operations.
+ * This method replaces chip->legacy.cmdfunc(),
+ * chip->legacy.{read,write}_{buf,byte,word}(),
+ * chip->legacy.dev_ready() and chip->legacy.waifunc().
+ * @setup_interface: setup the data interface and timing. If chipnr is set to
+ * %NAND_DATA_IFACE_CHECK_ONLY this means the configuration
+ * should not be applied but only checked.
+ * This hook is optional.
+ */
+struct nand_controller_ops {
+ int (*attach_chip)(struct nand_chip *chip);
+ void (*detach_chip)(struct nand_chip *chip);
+ int (*exec_op)(struct nand_chip *chip,
+ const struct nand_operation *op,
+ bool check_only);
+ int (*setup_interface)(struct nand_chip *chip, int chipnr,
+ const struct nand_interface_config *conf);
+};
+
+/**
+ * struct nand_controller - Structure used to describe a NAND controller
+ *
+ * @lock: lock used to serialize accesses to the NAND controller
+ * @ops: NAND controller operations.
+ */
+struct nand_controller {
+ struct mutex lock;
+ const struct nand_controller_ops *ops;
+};
+
+static inline void nand_controller_init(struct nand_controller *nfc)
+{
+ mutex_init(&nfc->lock);
+}
+
+/**
+ * struct nand_legacy - NAND chip legacy fields/hooks
+ * @IO_ADDR_R: address to read the 8 I/O lines of the flash device
+ * @IO_ADDR_W: address to write the 8 I/O lines of the flash device
+ * @select_chip: select/deselect a specific target/die
+ * @read_byte: read one byte from the chip
+ * @write_byte: write a single byte to the chip on the low 8 I/O lines
+ * @write_buf: write data from the buffer to the chip
+ * @read_buf: read data from the chip into the buffer
+ * @cmd_ctrl: hardware specific function for controlling ALE/CLE/nCE. Also used
+ * to write command and address
+ * @cmdfunc: hardware specific function for writing commands to the chip.
+ * @dev_ready: hardware specific function for accessing device ready/busy line.
+ * If set to NULL no access to ready/busy is available and the
+ * ready/busy information is read from the chip status register.
+ * @waitfunc: hardware specific function for wait on ready.
+ * @block_bad: check if a block is bad, using OOB markers
+ * @block_markbad: mark a block bad
+ * @set_features: set the NAND chip features
+ * @get_features: get the NAND chip features
+ * @chip_delay: chip dependent delay for transferring data from array to read
+ * regs (tR).
+ * @dummy_controller: dummy controller implementation for drivers that can
+ * only control a single chip
+ *
+ * If you look at this structure you're already wrong. These fields/hooks are
+ * all deprecated.
+ */
+struct nand_legacy {
+ void __iomem *IO_ADDR_R;
+ void __iomem *IO_ADDR_W;
+ void (*select_chip)(struct nand_chip *chip, int cs);
+ u8 (*read_byte)(struct nand_chip *chip);
+ u16 (*read_word)(struct nand_chip *chip);
+ void (*write_byte)(struct nand_chip *chip, u8 byte);
+ void (*write_buf)(struct nand_chip *chip, const u8 *buf, int len);
+ void (*read_buf)(struct nand_chip *chip, u8 *buf, int len);
+ void (*cmd_ctrl)(struct nand_chip *chip, int dat, unsigned int ctrl);
+ void (*cmdfunc)(struct nand_chip *chip, unsigned command, int column,
+ int page_addr);
+ int (*dev_ready)(struct nand_chip *chip);
+ int (*waitfunc)(struct nand_chip *chip);
+ int (*block_bad)(struct nand_chip *chip, loff_t ofs);
+ int (*block_markbad)(struct nand_chip *chip, loff_t ofs);
+ int (*set_features)(struct nand_chip *chip, int feature_addr,
+ u8 *subfeature_para);
+ int (*get_features)(struct nand_chip *chip, int feature_addr,
+ u8 *subfeature_para);
+ int chip_delay;
+ struct nand_controller dummy_controller;
+};
+
+/**
+ * struct nand_chip_ops - NAND chip operations
+ * @suspend: Suspend operation
+ * @resume: Resume operation
+ * @lock_area: Lock operation
+ * @unlock_area: Unlock operation
+ * @setup_read_retry: Set the read-retry mode (mostly needed for MLC NANDs)
+ * @choose_interface_config: Choose the best interface configuration
+ */
+struct nand_chip_ops {
+ int (*suspend)(struct nand_chip *chip);
+ void (*resume)(struct nand_chip *chip);
+ int (*lock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
+ int (*unlock_area)(struct nand_chip *chip, loff_t ofs, uint64_t len);
+ int (*setup_read_retry)(struct nand_chip *chip, int retry_mode);
+ int (*choose_interface_config)(struct nand_chip *chip,
+ struct nand_interface_config *iface);
+};
+
+/**
+ * struct nand_manufacturer - NAND manufacturer structure
+ * @desc: The manufacturer description
+ * @priv: Private information for the manufacturer driver
+ */
+struct nand_manufacturer {
+ const struct nand_manufacturer_desc *desc;
+ void *priv;
+};
+
+/**
+ * struct nand_chip - NAND Private Flash Chip Data
+ * @base: Inherit from the generic NAND device
+ * @id: Holds NAND ID
+ * @parameters: Holds generic parameters under an easily readable form
+ * @manufacturer: Manufacturer information
+ * @ops: NAND chip operations
+ * @legacy: All legacy fields/hooks. If you develop a new driver, don't even try
+ * to use any of these fields/hooks, and if you're modifying an
+ * existing driver that is using those fields/hooks, you should
+ * consider reworking the driver and avoid using them.
+ * @options: Various chip options. They can partly be set to inform nand_scan
+ * about special functionality. See the defines for further
+ * explanation.
+ * @current_interface_config: The currently used NAND interface configuration
+ * @best_interface_config: The best NAND interface configuration which fits both
+ * the NAND chip and NAND controller constraints. If
+ * unset, the default reset interface configuration must
+ * be used.
+ * @bbt_erase_shift: Number of address bits in a bbt entry
+ * @bbt_options: Bad block table specific options. All options used here must
+ * come from bbm.h. By default, these options will be copied to
+ * the appropriate nand_bbt_descr's.
+ * @badblockpos: Bad block marker position in the oob area
+ * @badblockbits: Minimum number of set bits in a good block's bad block marker
+ * position; i.e., BBM = 11110111b is good when badblockbits = 7
+ * @bbt_td: Bad block table descriptor for flash lookup
+ * @bbt_md: Bad block table mirror descriptor
+ * @badblock_pattern: Bad block scan pattern used for initial bad block scan
+ * @bbt: Bad block table pointer
+ * @page_shift: Number of address bits in a page (column address bits)
+ * @phys_erase_shift: Number of address bits in a physical eraseblock
+ * @chip_shift: Number of address bits in one chip
+ * @pagemask: Page number mask = number of (pages / chip) - 1
+ * @subpagesize: Holds the subpagesize
+ * @data_buf: Buffer for data, size is (page size + oobsize)
+ * @oob_poi: pointer on the OOB area covered by data_buf
+ * @pagecache: Structure containing page cache related fields
+ * @pagecache.bitflips: Number of bitflips of the cached page
+ * @pagecache.page: Page number currently in the cache. -1 means no page is
+ * currently cached
+ * @buf_align: Minimum buffer alignment required by a platform
+ * @lock: Lock protecting the suspended field. Also used to serialize accesses
+ * to the NAND device
+ * @suspended: Set to 1 when the device is suspended, 0 when it's not
+ * @cur_cs: Currently selected target. -1 means no target selected, otherwise we
+ * should always have cur_cs >= 0 && cur_cs < nanddev_ntargets().
+ * NAND Controller drivers should not modify this value, but they're
+ * allowed to read it.
+ * @read_retries: The number of read retry modes supported
+ * @controller: The hardware controller structure which is shared among multiple
+ * independent devices
+ * @ecc: The ECC controller structure
+ * @priv: Chip private data
+ */
+struct nand_chip {
+ struct nand_device base;
+ struct nand_id id;
+ struct nand_parameters parameters;
+ struct nand_manufacturer manufacturer;
+ struct nand_chip_ops ops;
+ struct nand_legacy legacy;
+ unsigned int options;
+
+ /* Data interface */
+ const struct nand_interface_config *current_interface_config;
+ struct nand_interface_config *best_interface_config;
+
+ /* Bad block information */
+ unsigned int bbt_erase_shift;
+ unsigned int bbt_options;
+ unsigned int badblockpos;
+ unsigned int badblockbits;
+ struct nand_bbt_descr *bbt_td;
+ struct nand_bbt_descr *bbt_md;
+ struct nand_bbt_descr *badblock_pattern;
+ u8 *bbt;
+
+ /* Device internal layout */
+ unsigned int page_shift;
+ unsigned int phys_erase_shift;
+ unsigned int chip_shift;
+ unsigned int pagemask;
+ unsigned int subpagesize;
+
+ /* Buffers */
+ u8 *data_buf;
+ u8 *oob_poi;
+ struct {
+ unsigned int bitflips;
+ int page;
+ } pagecache;
+ unsigned long buf_align;
+
+ /* Internals */
+ struct mutex lock;
+ unsigned int suspended : 1;
+ int cur_cs;
+ int read_retries;
+
+ /* Externals */
+ struct nand_controller *controller;
+ struct nand_ecc_ctrl ecc;
+ void *priv;
+
+ /* barebox specific */
+ unsigned int bbt_type;
+};
+
+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)
+{
+ return container_of(mtd, struct nand_chip, base.mtd);
+}
+
+static inline struct mtd_info *nand_to_mtd(struct nand_chip *chip)
+{
+ return &chip->base.mtd;
+}
+
+static inline void *nand_get_controller_data(struct nand_chip *chip)
+{
+ return chip->priv;
+}
+
+static inline void nand_set_controller_data(struct nand_chip *chip, void *priv)
+{
+ chip->priv = priv;
+}
+
+static inline void nand_set_manufacturer_data(struct nand_chip *chip,
+ void *priv)
+{
+ chip->manufacturer.priv = priv;
+}
+
+static inline void *nand_get_manufacturer_data(struct nand_chip *chip)
+{
+ return chip->manufacturer.priv;
+}
+
+static inline void nand_set_flash_node(struct nand_chip *chip,
+ struct device_node *np)
+{
+ mtd_set_of_node(nand_to_mtd(chip), np);
+}
+
+static inline struct device_node *nand_get_flash_node(struct nand_chip *chip)
+{
+ return mtd_get_of_node(nand_to_mtd(chip));
+}
+
+/**
+ * nand_get_interface_config - Retrieve the current interface configuration
+ * of a NAND chip
+ * @chip: The NAND chip
+ */
+static inline const struct nand_interface_config *
+nand_get_interface_config(struct nand_chip *chip)
+{
+ return chip->current_interface_config;
+}
+
+/*
+ * A helper for defining older NAND chips where the second ID byte fully
+ * defined the chip, including the geometry (chip size, eraseblock size, page
+ * size). All these chips have 512 bytes NAND page size.
+ */
+#define LEGACY_ID_NAND(nm, devid, chipsz, erasesz, opts) \
+ { .name = (nm), {{ .dev_id = (devid) }}, .pagesize = 512, \
+ .chipsize = (chipsz), .erasesize = (erasesz), .options = (opts) }
+
+/*
+ * A helper for defining newer chips which report their page size and
+ * eraseblock size via the extended ID bytes.
+ *
+ * The real difference between LEGACY_ID_NAND and EXTENDED_ID_NAND is that with
+ * EXTENDED_ID_NAND, manufacturers overloaded the same device ID so that the
+ * device ID now only represented a particular total chip size (and voltage,
+ * buswidth), and the page size, eraseblock size, and OOB size could vary while
+ * using the same device ID.
+ */
+#define EXTENDED_ID_NAND(nm, devid, chipsz, opts) \
+ { .name = (nm), {{ .dev_id = (devid) }}, .chipsize = (chipsz), \
+ .options = (opts) }
+
+#define NAND_ECC_INFO(_strength, _step) \
+ { .strength_ds = (_strength), .step_ds = (_step) }
+#define NAND_ECC_STRENGTH(type) ((type)->ecc.strength_ds)
+#define NAND_ECC_STEP(type) ((type)->ecc.step_ds)
+
+/**
+ * struct nand_flash_dev - NAND Flash Device ID Structure
+ * @name: a human-readable name of the NAND chip
+ * @dev_id: the device ID (the second byte of the full chip ID array)
+ * @mfr_id: manufacturer ID part of the full chip ID array (refers the same
+ * memory address as ``id[0]``)
+ * @dev_id: device ID part of the full chip ID array (refers the same memory
+ * address as ``id[1]``)
+ * @id: full device ID array
+ * @pagesize: size of the NAND page in bytes; if 0, then the real page size (as
+ * well as the eraseblock size) is determined from the extended NAND
+ * chip ID array)
+ * @chipsize: total chip size in MiB
+ * @erasesize: eraseblock size in bytes (determined from the extended ID if 0)
+ * @options: stores various chip bit options
+ * @id_len: The valid length of the @id.
+ * @oobsize: OOB size
+ * @ecc: ECC correctability and step information from the datasheet.
+ * @ecc.strength_ds: The ECC correctability from the datasheet, same as the
+ * @ecc_strength_ds in nand_chip{}.
+ * @ecc.step_ds: The ECC step required by the @ecc.strength_ds, same as the
+ * @ecc_step_ds in nand_chip{}, also from the datasheet.
+ * For example, the "4bit ECC for each 512Byte" can be set with
+ * NAND_ECC_INFO(4, 512).
+ */
+struct nand_flash_dev {
+ char *name;
+ union {
+ struct {
+ uint8_t mfr_id;
+ uint8_t dev_id;
+ };
+ uint8_t id[NAND_MAX_ID_LEN];
+ };
+ unsigned int pagesize;
+ unsigned int chipsize;
+ unsigned int erasesize;
+ unsigned int options;
+ uint16_t id_len;
+ uint16_t oobsize;
+ struct {
+ uint16_t strength_ds;
+ uint16_t step_ds;
+ } ecc;
+};
+
+int nand_create_bbt(struct nand_chip *chip);
+
+/*
+ * Check if it is a SLC nand.
+ * The !nand_is_slc() can be used to check the MLC/TLC nand chips.
+ * We do not distinguish the MLC and TLC now.
+ */
+static inline bool nand_is_slc(struct nand_chip *chip)
+{
+ WARN(nanddev_bits_per_cell(&chip->base) == 0,
+ "chip->bits_per_cell is used uninitialized\n");
+ return nanddev_bits_per_cell(&chip->base) == 1;
+}
+
+/**
+ * Check if the opcode's address should be sent only on the lower 8 bits
+ * @command: opcode to check
+ */
+static inline int nand_opcode_8bits(unsigned int command)
+{
+ switch (command) {
+ case NAND_CMD_READID:
+ case NAND_CMD_PARAM:
+ case NAND_CMD_GET_FEATURES:
+ case NAND_CMD_SET_FEATURES:
+ return 1;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int nand_check_erased_ecc_chunk(void *data, int datalen,
+ void *ecc, int ecclen,
+ void *extraoob, int extraooblen,
+ int threshold);
+
+int nand_ecc_choose_conf(struct nand_chip *chip,
+ const struct nand_ecc_caps *caps, int oobavail);
+
+/* Default write_oob implementation */
+int nand_write_oob_std(struct nand_chip *chip, int page);
+
+/* Default read_oob implementation */
+int nand_read_oob_std(struct nand_chip *chip, int page);
+
+/* Stub used by drivers that do not support GET/SET FEATURES operations */
+int nand_get_set_features_notsupp(struct nand_chip *chip, int addr,
+ u8 *subfeature_param);
+
+/* read_page_raw implementations */
+int nand_read_page_raw(struct nand_chip *chip, uint8_t *buf, int oob_required,
+ int page);
+int nand_monolithic_read_page_raw(struct nand_chip *chip, uint8_t *buf,
+ int oob_required, int page);
+
+/* write_page_raw implementations */
+int nand_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page);
+int nand_monolithic_write_page_raw(struct nand_chip *chip, const uint8_t *buf,
+ int oob_required, int page);
+
+/* Reset and initialize a NAND device */
+int nand_reset(struct nand_chip *chip, int chipnr);
+
+/* NAND operation helpers */
+int nand_reset_op(struct nand_chip *chip);
+int nand_readid_op(struct nand_chip *chip, u8 addr, void *buf,
+ unsigned int len);
+int nand_status_op(struct nand_chip *chip, u8 *status);
+int nand_erase_op(struct nand_chip *chip, unsigned int eraseblock);
+int nand_read_page_op(struct nand_chip *chip, unsigned int page,
+ unsigned int offset_in_page, void *buf, unsigned int len);
+int nand_change_read_column_op(struct nand_chip *chip,
+ unsigned int offset_in_page, void *buf,
+ unsigned int len, bool force_8bit);
+int nand_read_oob_op(struct nand_chip *chip, unsigned int page,
+ unsigned int offset_in_page, void *buf, unsigned int len);
+int nand_prog_page_begin_op(struct nand_chip *chip, unsigned int page,
+ unsigned int offset_in_page, const void *buf,
+ unsigned int len);
+int nand_prog_page_end_op(struct nand_chip *chip);
+int nand_prog_page_op(struct nand_chip *chip, unsigned int page,
+ unsigned int offset_in_page, const void *buf,
+ unsigned int len);
+int nand_change_write_column_op(struct nand_chip *chip,
+ unsigned int offset_in_page, const void *buf,
+ unsigned int len, bool force_8bit);
+int nand_read_data_op(struct nand_chip *chip, void *buf, unsigned int len,
+ bool force_8bit, bool check_only);
+int nand_write_data_op(struct nand_chip *chip, const void *buf,
+ unsigned int len, bool force_8bit);
+
+/* Scan and identify a NAND device */
+int nand_scan_with_ids(struct nand_chip *chip, unsigned int max_chips,
+ struct nand_flash_dev *ids);
+
+static inline int nand_scan(struct nand_chip *chip, unsigned int max_chips)
+{
+ return nand_scan_with_ids(chip, max_chips, NULL);
+}
+
+/* Internal helper for board drivers which need to override command function */
+void nand_wait_ready(struct nand_chip *chip);
+
+/*
+ * Free resources held by the NAND device, must be called on error after a
+ * sucessful nand_scan().
+ */
+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);
+void nand_deselect_target(struct nand_chip *chip);
+
+/* Bitops */
+void nand_extract_bits(u8 *dst, unsigned int dst_off, const u8 *src,
+ unsigned int src_off, unsigned int nbits);
+
+/**
+ * nand_get_data_buf() - Get the internal page buffer
+ * @chip: NAND chip object
+ *
+ * Returns the pre-allocated page buffer after invalidating the cache. This
+ * function should be used by drivers that do not want to allocate their own
+ * bounce buffer and still need such a buffer for specific operations (most
+ * commonly when reading OOB data only).
+ *
+ * Be careful to never call this function in the write/write_oob path, because
+ * the core may have placed the data to be written out in this buffer.
+ *
+ * Return: pointer to the page cache buffer
+ */
+static inline void *nand_get_data_buf(struct nand_chip *chip)
+{
+ chip->pagecache.page = -1;
+
+ return chip->data_buf;
+}
+
+int nand_scan_ident(struct nand_chip *chip, unsigned int max_chips,
+ struct nand_flash_dev *table);
+int nand_scan_tail(struct nand_chip *chip);
+int nand_update_bbt(struct nand_chip *this, loff_t offs);
+int add_mtd_nand_device(struct mtd_info *mtd, char *devname);
+
+/* return the supported asynchronous timing mode. */
+static inline int onfi_get_async_timing_mode(struct nand_chip *chip)
+{
+ if (!chip->parameters.onfi)
+ return ONFI_TIMING_MODE_UNKNOWN;
+ return chip->parameters.onfi->async_timing_mode;
+}
+
+const struct nand_sdr_timings *onfi_async_timing_mode_to_sdr_timings(int mode);
+bool nand_supports_set_features(struct nand_chip *chip, int addr);
+
+#endif /* __LINUX_MTD_RAWNAND_H */
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 8ed7f8a1cd..29c3460ace 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -19,34 +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
-
-#define AT_FDCWD -100 /* Special value used to indicate
- openat should use the current
- working directory. */
#endif /* _LINUX_NAMEI_H */
diff --git a/include/linux/nls.h b/include/linux/nls.h
index 62fb7b5a97..ee0e1ffd58 100644
--- a/include/linux/nls.h
+++ b/include/linux/nls.h
@@ -2,6 +2,8 @@
#ifndef _LINUX_NLS_H
#define _LINUX_NLS_H
+#include <linux/stddef.h>
+
/* Unicode has changed over the years. Unicode code points no longer
* fit into 16 bits; as of Unicode 5 valid code points range from 0
* to 0x10ffff (17 planes, where each plane holds 65536 code points).
@@ -14,7 +16,6 @@
*/
/* Plane-0 Unicode character */
-typedef u16 wchar_t;
#define MAX_WCHAR_T 0xffff
/* Arbitrary Unicode character */
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 9e0fd4265e..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,28 +29,36 @@ 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);
+int nvmem_device_write(struct nvmem_device *nvmem, unsigned int offset,
+ size_t bytes, const void *buf);
ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
struct nvmem_cell_info *info, void *buf);
int nvmem_device_cell_write(struct nvmem_device *nvmem,
struct nvmem_cell_info *info, void *buf);
+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(-ENOSYS);
+ return ERR_PTR(-EOPNOTSUPP);
}
static inline void nvmem_cell_put(struct nvmem_cell *cell)
@@ -59,31 +67,67 @@ static inline void nvmem_cell_put(struct nvmem_cell *cell)
static inline char *nvmem_cell_read(struct nvmem_cell *cell, size_t *len)
{
- return ERR_PTR(-ENOSYS);
+ return ERR_PTR(-EOPNOTSUPP);
}
static inline void *nvmem_cell_get_and_read(struct device_node *np,
const char *cell_name,
size_t bytes)
{
- return ERR_PTR(-ENOSYS);
+ 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,
- const char *buf, size_t len)
+ void *buf, size_t len)
{
- return -ENOSYS;
+ 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(-ENOSYS);
+ return ERR_PTR(-EOPNOTSUPP);
}
static inline void nvmem_device_put(struct nvmem_device *nvmem)
{
}
+
+static inline ssize_t nvmem_device_cell_read(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info,
+ void *buf)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int nvmem_device_cell_write(struct nvmem_device *nvmem,
+ struct nvmem_cell_info *info,
+ void *buf)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int nvmem_device_read(struct nvmem_device *nvmem,
+ unsigned int offset, size_t bytes,
+ void *buf)
+{
+ return -EOPNOTSUPP;
+}
+
+static inline int nvmem_device_write(struct nvmem_device *nvmem,
+ unsigned int offset, size_t bytes,
+ const void *buf)
+{
+ return -EOPNOTSUPP;
+}
+
#endif /* CONFIG_NVMEM */
#if IS_ENABLED(CONFIG_NVMEM) && IS_ENABLED(CONFIG_OFTREE)
diff --git a/include/linux/nvmem-provider.h b/include/linux/nvmem-provider.h
index 6ef5ea6854..41c636b3a4 100644
--- a/include/linux/nvmem-provider.h
+++ b/include/linux/nvmem-provider.h
@@ -17,26 +17,38 @@
struct nvmem_device;
-struct nvmem_bus {
- int (*write)(struct device_d *dev, const int reg, const void *val,
- int val_size);
- int (*read)(struct device_d *dev, const int reg, void *val,
- int 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;
+struct cdev;
+
#if IS_ENABLED(CONFIG_NVMEM)
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
@@ -45,5 +57,26 @@ static inline struct nvmem_device *nvmem_register(const struct nvmem_config *c)
return ERR_PTR(-ENOSYS);
}
+static inline struct nvmem_device *nvmem_regmap_register(struct regmap *regmap, const char *name)
+{
+ 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
new file mode 100644
index 0000000000..f9b60313ea
--- /dev/null
+++ b/include/linux/overflow.h
@@ -0,0 +1,312 @@
+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
+#ifndef __LINUX_OVERFLOW_H
+#define __LINUX_OVERFLOW_H
+
+#include <linux/compiler.h>
+#include <linux/limits.h>
+#include <linux/const.h>
+
+/*
+ * 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)
+ *
+ * Unfortunately, the middle expressions, strictly speaking, have
+ * undefined behaviour, and at least some versions of gcc warn about
+ * the type_max expression (but not if -fsanitize=undefined is in
+ * effect; in that case, the warning is deferred to runtime...).
+ *
+ * The slightly excessive casting in type_min is to make sure the
+ * macros also produce sensible values for the exotic type _Bool. [The
+ * overflow checkers only almost work for _Bool, but that's
+ * a-feature-not-a-bug, since people shouldn't be doing arithmetic on
+ * _Bools. Besides, the gcc builtins don't allow _Bool* as third
+ * argument.]
+ *
+ * Idea stolen from
+ * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
+ * credit to Christian Biere.
+ */
+#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))
+
+/*
+ * Avoids triggering -Wtype-limits compilation warning,
+ * while using unsigned data types to check a < 0.
+ */
+#define is_non_negative(a) ((a) > 0 || (a) == 0)
+#define is_negative(a) (!(is_non_negative(a)))
+
+/*
+ * 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);
+}
+
+/**
+ * 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 check_add_overflow(a, b, d) \
+ __must_check_overflow(__builtin_add_overflow(a, b, d))
+
+/**
+ * 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 check_sub_overflow(a, b, d) \
+ __must_check_overflow(__builtin_sub_overflow(a, b, d))
+
+/**
+ * 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))
+
+/**
+ * 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
+ * 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 true is returned.
+ */
+#define check_shl_overflow(a, s, d) __must_check_overflow(({ \
+ typeof(a) _a = a; \
+ typeof(s) _s = s; \
+ typeof(d) _d = d; \
+ u64 _a_full = _a; \
+ unsigned int _to_shift = \
+ is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \
+ *_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); \
+})
+
+/**
+ * overflows_type - helper for checking the overflows between value, variables,
+ * or data type
+ *
+ * @n: source constant value or variable to be checked
+ * @T: destination variable or data type proposed to store @x
+ *
+ * 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: 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().
+ */
+#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(factor1, factor2, &bytes))
+ return SIZE_MAX;
+
+ return bytes;
+}
+
+/**
+ * size_add() - Calculate size_t addition with saturation at SIZE_MAX
+ * @addend1: first addend
+ * @addend2: second addend
+ *
+ * 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 size_t __must_check size_add(size_t addend1, size_t addend2)
+{
+ size_t bytes;
+
+ if (check_add_overflow(addend1, addend2, &bytes))
+ return SIZE_MAX;
+
+ return bytes;
+}
+
+/**
+ * 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 size_t __must_check size_sub(size_t minuend, size_t subtrahend)
+{
+ size_t bytes;
+
+ if (minuend == SIZE_MAX || subtrahend == SIZE_MAX ||
+ check_sub_overflow(minuend, subtrahend, &bytes))
+ return SIZE_MAX;
+
+ return bytes;
+}
+
+/**
+ * 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.
+ * @count: Number of elements in the array.
+ *
+ * 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_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 c742570e36..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
*
@@ -29,8 +31,13 @@
#include <linux/pci_ids.h>
+/* Include architecture-dependent settings and functions */
+
+#include <asm/pci.h>
#define PCI_ANY_ID (~0)
+#define PCI_FIND_CAP_TTL 48
+
/*
* The PCI interface treats multi-function devices as independent
* devices. The slot/function address of each device is encoded
@@ -95,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;
@@ -134,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 */
@@ -166,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;
@@ -189,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
@@ -319,9 +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
@@ -346,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 a9fdf44f1a..7da4f94e0e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1,21 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (c) 2009-2012 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
*
* Author: Andy Fleming
*
* Copyright (c) 2004 Freescale Semiconductor, Inc.
- *
- * 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 __PHY_H
#define __PHY_H
#include <driver.h>
+#include <slice.h>
#include <linux/list.h>
#include <linux/ethtool.h>
#include <linux/mii.h>
@@ -40,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,
@@ -50,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,
@@ -57,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;
@@ -103,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];
@@ -116,16 +160,23 @@ struct mii_bus {
struct list_head list;
bool is_multiplexed;
+
+ struct slice slice;
};
#define to_mii_bus(d) container_of(d, struct mii_bus, dev)
+static inline struct slice *mdiobus_slice(struct mii_bus *bus)
+{
+ return &bus->slice;
+}
+
int mdiobus_register(struct mii_bus *bus);
void mdiobus_unregister(struct mii_bus *bus);
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)
@@ -134,37 +185,18 @@ struct mii_bus *mdiobus_get_bus(int busnum);
struct mii_bus *of_mdio_find_bus(struct device_node *mdio_bus_np);
-/**
- * mdiobus_read - Convenience function for reading a given MII mgmt register
- * @bus: the mii_bus struct
- * @addr: the phy address
- * @regnum: register number to read
- */
-static inline int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum)
-{
- return bus->read(bus, addr, regnum);
-}
-
-/**
- * mdiobus_write - Convenience function for writing a given MII mgmt register
- * @bus: the mii_bus struct
- * @addr: the phy address
- * @regnum: register number to write
- * @val: value to write to @regnum
- */
-static inline int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val)
-{
- return bus->write(bus, addr, regnum, val);
-}
+int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
+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
@@ -172,10 +204,12 @@ static inline int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 v
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;
@@ -218,12 +252,13 @@ 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
*
* The drivers must implement config_aneg and read_status. All
* other functions are optional. Note that none of these
@@ -237,6 +272,8 @@ struct phy_driver {
u32 phy_id;
unsigned int phy_id_mask;
u32 features;
+ const void *driver_data;
+ bool is_phy;
/*
* Called to initialize the PHY,
@@ -270,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)
@@ -295,6 +332,28 @@ 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) \
+ { \
+ return phy_drivers_register(drvs, ARRAY_SIZE(drvs)); \
+ } \
+ level##_initcall(drvs##_register)
+
+#define device_phy_drivers(drvs) \
+ phy_register_drivers_macro(device, drvs)
+
+#define phy_register_driver_macro(level, drv) \
+ static int __init drv##_register(void) \
+ { \
+ return phy_driver_register(&drv); \
+ } \
+ level##_initcall(drv##_register)
+
+#define device_phy_driver(drv) \
+ phy_register_driver_macro(device, drv)
int phy_save_page(struct phy_device *phydev);
int phy_select_page(struct phy_device *phydev, int page);
@@ -353,6 +412,27 @@ static inline int phy_clear_bits(struct phy_device *phydev, u32 regnum, u16 val)
return phy_modify(phydev, regnum, val, 0);
}
+/**
+ * phy_interface_mode_is_rgmii - Convenience function for testing if a
+ * PHY interface mode is RGMII (all variants)
+ * @mode: the phy_interface_t enum
+ */
+static inline bool phy_interface_mode_is_rgmii(phy_interface_t mode)
+{
+ return mode >= PHY_INTERFACE_MODE_RGMII &&
+ mode <= PHY_INTERFACE_MODE_RGMII_TXID;
+};
+
+/**
+ * phy_interface_is_rgmii - Convenience function for testing if a PHY interface
+ * is RGMII (all variants)
+ * @phydev: the phy_device struct
+ */
+static inline bool phy_interface_is_rgmii(struct phy_device *phydev)
+{
+ return phy_interface_mode_is_rgmii(phydev->interface);
+};
+
int phy_device_connect(struct eth_device *dev, struct mii_bus *bus, int addr,
void (*adjust_link) (struct eth_device *edev),
u32 flags, phy_interface_t interface);
@@ -376,10 +456,66 @@ int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask,
int phy_register_fixup_for_id(const char *bus_id,
int (*run)(struct phy_device *));
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,
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index 8a28b8e068..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,23 +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 *of_phy_simple_xlate(struct device_d *dev,
- struct of_phandle_args *args);
-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)
{
@@ -179,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;
@@ -189,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);
@@ -215,13 +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 *of_phy_simple_xlate(struct device_d *dev,
- struct of_phandle_args *args)
-{
- 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)
{
@@ -232,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);
}
@@ -248,7 +280,7 @@ static inline struct usb_phy *phy_to_usbphy(struct phy *phy)
return NULL;
}
-static 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/platform_data/simplefb.h b/include/linux/platform_data/simplefb.h
new file mode 100644
index 0000000000..a4f07eccd8
--- /dev/null
+++ b/include/linux/platform_data/simplefb.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * simplefb.h - Simple Framebuffer Device
+ *
+ * Copyright (C) 2013 David Herrmann <dh.herrmann@gmail.com>
+ */
+
+#ifndef __PLATFORM_DATA_SIMPLEFB_H__
+#define __PLATFORM_DATA_SIMPLEFB_H__
+
+#include <video/fourcc.h>
+#include <fb.h>
+#include <linux/types.h>
+
+/* format array, use it to initialize a "struct simplefb_format" array */
+#define SIMPLEFB_FORMATS \
+{ \
+ { "r5g6b5", 16, {11, 5}, {5, 6}, {0, 5}, {0, 0}, DRM_FORMAT_RGB565 }, \
+ { "x1r5g5b5", 16, {10, 5}, {5, 5}, {0, 5}, {0, 0}, DRM_FORMAT_XRGB1555 }, \
+ { "a1r5g5b5", 16, {10, 5}, {5, 5}, {0, 5}, {15, 1}, DRM_FORMAT_ARGB1555 }, \
+ { "r8g8b8", 24, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_RGB888 }, \
+ { "x8r8g8b8", 32, {16, 8}, {8, 8}, {0, 8}, {0, 0}, DRM_FORMAT_XRGB8888 }, \
+ { "a8r8g8b8", 32, {16, 8}, {8, 8}, {0, 8}, {24, 8}, DRM_FORMAT_ARGB8888 }, \
+ { "a8b8g8r8", 32, {0, 8}, {8, 8}, {16, 8}, {24, 8}, DRM_FORMAT_ABGR8888 }, \
+ { "x2r10g10b10", 32, {20, 10}, {10, 10}, {0, 10}, {0, 0}, DRM_FORMAT_XRGB2101010 }, \
+ { "a2r10g10b10", 32, {20, 10}, {10, 10}, {0, 10}, {30, 2}, DRM_FORMAT_ARGB2101010 }, \
+}
+
+/*
+ * Data-Format for Simple-Framebuffers
+ * @name: unique 0-terminated name that can be used to identify the mode
+ * @red,green,blue: Offsets and sizes of the single RGB parts
+ * @transp: Offset and size of the alpha bits. length=0 means no alpha
+ * @fourcc: 32bit DRM four-CC code (see drm_fourcc.h)
+ */
+struct simplefb_format {
+ const char *name;
+ u32 bits_per_pixel;
+ struct fb_bitfield red;
+ struct fb_bitfield green;
+ struct fb_bitfield blue;
+ struct fb_bitfield transp;
+ u32 fourcc;
+};
+
+#endif /* __PLATFORM_DATA_SIMPLEFB_H__ */
diff --git a/include/linux/poison.h b/include/linux/poison.h
new file mode 100644
index 0000000000..b92eb2f95b
--- /dev/null
+++ b/include/linux/poison.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_POISON_H
+#define _LINUX_POISON_H
+
+/********** include/linux/list.h **********/
+
+/*
+ * Architectures might want to move the poison pointer offset
+ * into some well-recognized area such as 0xdead000000000000,
+ * that is also not mappable by user-space exploits:
+ */
+#ifdef CONFIG_ILLEGAL_POINTER_VALUE
+# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
+#else
+# define POISON_POINTER_DELTA 0
+#endif
+
+/*
+ * These are non-NULL pointers that will result in page faults
+ * under normal circumstances, used to verify that nobody uses
+ * non-initialized list entries.
+ */
+#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
+#define LIST_POISON2 ((void *) 0x122 + POISON_POINTER_DELTA)
+
+#endif
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
new file mode 100644
index 0000000000..07403ea60c
--- /dev/null
+++ b/include/linux/printk.h
@@ -0,0 +1,240 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __LINUX_PRINTK_H
+#define __LINUX_PRINTK_H
+
+#include <linux/list.h>
+#include <linux/err.h>
+#include <printk.h>
+#include <stdarg.h>
+
+#define MSG_EMERG 0 /* system is unusable */
+#define MSG_ALERT 1 /* action must be taken immediately */
+#define MSG_CRIT 2 /* critical conditions */
+#define MSG_ERR 3 /* error conditions */
+#define MSG_WARNING 4 /* warning conditions */
+#define MSG_NOTICE 5 /* normal but significant condition */
+#define MSG_INFO 6 /* informational */
+#define MSG_DEBUG 7 /* debug-level messages */
+#define MSG_VDEBUG 8 /* verbose debug messages */
+
+#ifdef VERBOSE_DEBUG
+#define LOGLEVEL MSG_VDEBUG
+#elif defined DEBUG
+#define LOGLEVEL MSG_DEBUG
+#else
+#define LOGLEVEL CONFIG_COMPILE_LOGLEVEL
+#endif
+
+/* debugging and troubleshooting/diagnostic helpers. */
+struct device;
+
+#ifndef CONFIG_CONSOLE_NONE
+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 *dev,
+ const char *format, ...)
+{
+ return 0;
+}
+#endif
+
+#if (!defined(__PBL__) && !defined(CONFIG_CONSOLE_NONE)) || \
+ (defined(__PBL__) && defined(CONFIG_PBL_CONSOLE))
+int pr_print(int level, const char *format, ...)
+ __attribute__ ((format(__printf__, 2, 3)));
+#else
+static int pr_print(int level, const char *format, ...)
+ __attribute__ ((format(__printf__, 2, 3)));
+static inline int pr_print(int level, const char *format, ...)
+{
+ return 0;
+}
+#endif
+
+#define __dev_printf(level, dev, format, args...) \
+ ({ \
+ (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...) \
+ __dev_printf(1, (dev) , format , ## arg)
+#define dev_crit(dev, format, arg...) \
+ __dev_printf(2, (dev) , format , ## arg)
+#define dev_err(dev, format, arg...) \
+ __dev_printf(3, (dev) , format , ## arg)
+#define dev_warn(dev, format, arg...) \
+ __dev_printf(4, (dev) , format , ## arg)
+#define dev_notice(dev, format, arg...) \
+ __dev_printf(5, (dev) , format , ## arg)
+#define dev_info(dev, format, arg...) \
+ __dev_printf(6, (dev) , format , ## arg)
+#define dev_dbg(dev, format, arg...) \
+ __dev_printf(7, (dev) , format , ## arg)
+#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(struct device *dev, int err, const char *fmt, ...)
+ __attribute__ ((format(__printf__, 3, 4)));
+#elif !defined(dev_err_probe)
+static int dev_err_probe(struct device *dev, int err, const char *fmt, ...)
+ __attribute__ ((format(__printf__, 3, 4)));
+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
+
+#define pr_emerg(fmt, arg...) __pr_printk(0, pr_fmt(fmt), ##arg)
+#define pr_alert(fmt, arg...) __pr_printk(1, pr_fmt(fmt), ##arg)
+#define pr_crit(fmt, arg...) __pr_printk(2, pr_fmt(fmt), ##arg)
+#define pr_err(fmt, arg...) __pr_printk(3, pr_fmt(fmt), ##arg)
+#define pr_warning(fmt, arg...) __pr_printk(4, pr_fmt(fmt), ##arg)
+#define pr_notice(fmt, arg...) __pr_printk(5, pr_fmt(fmt), ##arg)
+#define pr_info(fmt, arg...) __pr_printk(6, pr_fmt(fmt), ##arg)
+#define pr_debug(fmt, arg...) __pr_printk(7, pr_fmt(fmt), ##arg)
+#define debug(fmt, arg...) __pr_printk(7, pr_fmt(fmt), ##arg)
+#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);
+int __pr_memory_display(int level, const void *addr, loff_t offs, unsigned nbytes,
+ int size, int swab, const char *format, ...);
+
+#define pr_memory_display(level, addr, offs, nbytes, size, swab) \
+ ({ \
+ (level) <= LOGLEVEL ? __pr_memory_display((level), (addr), \
+ (offs), (nbytes), (size), (swab), pr_fmt("")) : 0; \
+ })
+
+struct log_entry {
+ struct list_head list;
+ uint64_t timestamp;
+ int level;
+ char msg[];
+};
+
+extern struct list_head barebox_logbuf;
+
+extern void log_clean(unsigned int limit);
+
+#define BAREBOX_LOG_PRINT_RAW BIT(2)
+#define BAREBOX_LOG_DIFF_TIME BIT(1)
+#define BAREBOX_LOG_PRINT_TIME BIT(0)
+
+int log_writefile(const char *filepath);
+int log_print(unsigned flags, unsigned levels);
+
+struct va_format {
+ const char *fmt;
+ va_list *va;
+};
+
+#if LOGLEVEL >= MSG_DEBUG
+#define print_hex_dump_debug(prefix_str, prefix_type, rowsize, \
+ groupsize, buf, len, ascii) \
+ print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \
+ groupsize, buf, len, ascii)
+#else
+static inline void print_hex_dump_debug(const char *prefix_str, int prefix_type,
+ int rowsize, int groupsize,
+ const void *buf, size_t len, bool ascii)
+{
+}
+#endif
+
+/**
+ * print_hex_dump_bytes - shorthand form of print_hex_dump() with default params
+ * @prefix_str: string to prefix each line with;
+ * caller supplies trailing spaces for alignment if desired
+ * @prefix_type: controls whether prefix of an offset, address, or none
+ * is printed (%DUMP_PREFIX_OFFSET, %DUMP_PREFIX_ADDRESS, %DUMP_PREFIX_NONE)
+ * @buf: data blob to dump
+ * @len: number of bytes in the @buf
+ *
+ * Calls print_hex_dump(), with log level of KERN_DEBUG,
+ * rowsize of 16, groupsize of 1, and ASCII output included.
+ */
+#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \
+ print_hex_dump_debug(prefix_str, prefix_type, 16, 1, buf, len, true)
+
+#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/rational.h b/include/linux/rational.h
new file mode 100644
index 0000000000..33f5f5fc3e
--- /dev/null
+++ b/include/linux/rational.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * rational fractions
+ *
+ * Copyright (C) 2009 emlix GmbH, Oskar Schirmer <oskar@scara.com>
+ *
+ * helper functions when coping with rational numbers,
+ * e.g. when calculating optimum numerator/denominator pairs for
+ * pll configuration taking into account restricted register size
+ */
+
+#ifndef _LINUX_RATIONAL_H
+#define _LINUX_RATIONAL_H
+
+void rational_best_approximation(
+ unsigned long given_numerator, unsigned long given_denominator,
+ unsigned long max_numerator, unsigned long max_denominator,
+ unsigned long *best_numerator, unsigned long *best_denominator);
+
+#endif /* _LINUX_RATIONAL_H */
diff --git a/include/linux/reboot-mode.h b/include/linux/reboot-mode.h
new file mode 100644
index 0000000000..66e7768fdf
--- /dev/null
+++ b/include/linux/reboot-mode.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __REBOOT_MODE_H__
+#define __REBOOT_MODE_H__
+
+#include <linux/types.h>
+
+struct device;
+
+#ifdef CONFIG_REBOOT_MODE
+struct reboot_mode_driver {
+ struct device *dev;
+ int (*write)(struct reboot_mode_driver *reboot, const u32 *magic);
+ int priority;
+ bool no_fixup;
+
+ /* filled by reboot_mode_register */
+ int reboot_mode_prev, reboot_mode_next;
+ unsigned nmodes, nelems;
+ const char **modes;
+ u32 *magics;
+};
+
+int reboot_mode_register(struct reboot_mode_driver *reboot,
+ const u32 *magic, size_t num);
+const char *reboot_mode_get(void);
+
+#define REBOOT_MODE_DEFAULT_PRIORITY 100
+
+#else
+
+static inline const char *reboot_mode_get(void)
+{
+ return NULL;
+}
+
+#endif
+
+#endif
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/machine.h b/include/linux/regulator/machine.h
deleted file mode 100644
index bb8bc7c4e0..0000000000
--- a/include/linux/regulator/machine.h
+++ /dev/null
@@ -1,207 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * machine.h -- SoC Regulator support, machine/board driver API.
- *
- * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC.
- *
- * Author: Liam Girdwood <lrg@slimlogic.co.uk>
- *
- * Regulator Machine/Board Interface.
- */
-
-#ifndef __LINUX_REGULATOR_MACHINE_H_
-#define __LINUX_REGULATOR_MACHINE_H_
-
-#include <regulator.h>
-
-struct regulator;
-
-/*
- * Regulator operation constraint flags. These flags are used to enable
- * certain regulator operations and can be OR'ed together.
- *
- * VOLTAGE: Regulator output voltage can be changed by software on this
- * board/machine.
- * CURRENT: Regulator output current can be changed by software on this
- * board/machine.
- * MODE: Regulator operating mode can be changed by software on this
- * board/machine.
- * STATUS: Regulator can be enabled and disabled.
- * DRMS: Dynamic Regulator Mode Switching is enabled for this regulator.
- * BYPASS: Regulator can be put into bypass mode
- */
-
-#define REGULATOR_CHANGE_VOLTAGE 0x1
-#define REGULATOR_CHANGE_CURRENT 0x2
-#define REGULATOR_CHANGE_MODE 0x4
-#define REGULATOR_CHANGE_STATUS 0x8
-#define REGULATOR_CHANGE_DRMS 0x10
-#define REGULATOR_CHANGE_BYPASS 0x20
-
-/* Regulator active discharge flags */
-enum regulator_active_discharge {
- REGULATOR_ACTIVE_DISCHARGE_DEFAULT,
- REGULATOR_ACTIVE_DISCHARGE_DISABLE,
- REGULATOR_ACTIVE_DISCHARGE_ENABLE,
-};
-
-/**
- * struct regulation_constraints - regulator operating constraints.
- *
- * This struct describes regulator and board/machine specific constraints.
- *
- * @name: Descriptive name for the constraints, used for display purposes.
- *
- * @min_uV: Smallest voltage consumers may set.
- * @max_uV: Largest voltage consumers may set.
- * @uV_offset: Offset applied to voltages from consumer to compensate for
- * voltage drops.
- *
- * @min_uA: Smallest current consumers may set.
- * @max_uA: Largest current consumers may set.
- * @ilim_uA: Maximum input current.
- * @system_load: Load that isn't captured by any consumer requests.
- *
- * @max_spread: Max possible spread between coupled regulators
- * @valid_modes_mask: Mask of modes which may be configured by consumers.
- * @valid_ops_mask: Operations which may be performed by consumers.
- *
- * @always_on: Set if the regulator should never be disabled.
- * @boot_on: Set if the regulator is enabled when the system is initially
- * started. If the regulator is not enabled by the hardware or
- * bootloader then it will be enabled when the constraints are
- * applied.
- * @apply_uV: Apply the voltage constraint when initialising.
- * @ramp_disable: Disable ramp delay when initialising or when setting voltage.
- * @soft_start: Enable soft start so that voltage ramps slowly.
- * @pull_down: Enable pull down when regulator is disabled.
- * @over_current_protection: Auto disable on over current event.
- *
- * @input_uV: Input voltage for regulator when supplied by another regulator.
- *
- * @initial_mode: Mode to set at startup.
- * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
- * @settling_time: Time to settle down after voltage change when voltage
- * change is non-linear (unit: microseconds).
- * @settling_time_up: Time to settle down after voltage increase when voltage
- * change is non-linear (unit: microseconds).
- * @settling_time_down : Time to settle down after voltage decrease when
- * voltage change is non-linear (unit: microseconds).
- * @active_discharge: Enable/disable active discharge. The enum
- * regulator_active_discharge values are used for
- * initialisation.
- * @enable_time: Turn-on time of the rails (unit: microseconds)
- */
-struct regulation_constraints {
-
- const char *name;
-
- /* voltage output range (inclusive) - for voltage control */
- int min_uV;
- int max_uV;
-
- int uV_offset;
-
- /* current output range (inclusive) - for current control */
- int min_uA;
- int max_uA;
- int ilim_uA;
-
- int system_load;
-
- /* used for coupled regulators */
- u32 *max_spread;
-
- /* used for changing voltage in steps */
- int max_uV_step;
-
- /* valid regulator operating modes for this machine */
- unsigned int valid_modes_mask;
-
- /* valid operations for regulator on this machine */
- unsigned int valid_ops_mask;
-
- /* regulator input voltage - only if supply is another regulator */
- int input_uV;
-
- /* mode to set on startup */
- unsigned int initial_mode;
-
- unsigned int ramp_delay;
- unsigned int settling_time;
- unsigned int settling_time_up;
- unsigned int settling_time_down;
- unsigned int enable_time;
-
- unsigned int active_discharge;
-
- /* constraint flags */
- unsigned always_on:1; /* regulator never off when system is on */
- unsigned boot_on:1; /* bootloader/firmware enabled regulator */
- unsigned apply_uV:1; /* apply uV constraint if min == max */
- unsigned ramp_disable:1; /* disable ramp delay */
- unsigned soft_start:1; /* ramp voltage slowly */
- unsigned pull_down:1; /* pull down resistor when regulator off */
- unsigned over_current_protection:1; /* auto disable on over current */
-};
-
-/**
- * struct regulator_consumer_supply - supply -> device mapping
- *
- * This maps a supply name to a device. Use of dev_name allows support for
- * buses which make struct device available late such as I2C.
- *
- * @dev_name: Result of dev_name() for the consumer.
- * @supply: Name for the supply.
- */
-struct regulator_consumer_supply {
- const char *dev_name; /* dev_name() for consumer */
- const char *supply; /* consumer supply - e.g. "vcc" */
-};
-
-/* Initialize struct regulator_consumer_supply */
-#define REGULATOR_SUPPLY(_name, _dev_name) \
-{ \
- .supply = _name, \
- .dev_name = _dev_name, \
-}
-
-/**
- * struct regulator_init_data - regulator platform initialisation data.
- *
- * Initialisation constraints, our supply and consumers supplies.
- *
- * @supply_regulator: Parent regulator. Specified using the regulator name
- * as it appears in the name field in sysfs, which can
- * be explicitly set using the constraints field 'name'.
- *
- * @constraints: Constraints. These must be specified for the regulator to
- * be usable.
- * @num_consumer_supplies: Number of consumer device supplies.
- * @consumer_supplies: Consumer device supply configuration.
- *
- * @regulator_init: Callback invoked when the regulator has been registered.
- * @driver_data: Data passed to regulator_init.
- */
-struct regulator_init_data {
- const char *supply_regulator; /* or NULL for system supply */
-
- struct regulation_constraints constraints;
-
- int num_consumer_supplies;
- struct regulator_consumer_supply *consumer_supplies;
-
- /* optional regulator machine specific init */
- int (*regulator_init)(void *driver_data);
- void *driver_data; /* core does not touch this */
-};
-
-#ifdef CONFIG_REGULATOR
-void regulator_has_full_constraints(void);
-#else
-static inline void regulator_has_full_constraints(void)
-{
-}
-#endif
-
-#endif
diff --git a/include/linux/regulator/of_regulator.h b/include/linux/regulator/of_regulator.h
index 265b98d1ee..649e11db9f 100644
--- a/include/linux/regulator/of_regulator.h
+++ b/include/linux/regulator/of_regulator.h
@@ -8,35 +8,22 @@
#include <linux/types.h>
-struct device_d;
+struct device;
struct regulator_desc;
struct of_regulator_match {
const char *name;
void *driver_data;
- struct regulator_init_data *init_data;
struct device_node *of_node;
const struct regulator_desc *desc;
};
#if defined(CONFIG_OFDEVICE)
-extern struct regulator_init_data
- *of_get_regulator_init_data(struct device_d *dev,
- struct device_node *node,
- const struct regulator_desc *desc);
-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 struct regulator_init_data
- *of_get_regulator_init_data(struct device_d *dev,
- struct device_node *node,
- const struct regulator_desc *desc)
-{
- return NULL;
-}
-
-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 4a92a177bc..7db3d3162a 100644
--- a/include/linux/reset.h
+++ b/include/linux/reset.h
@@ -1,66 +1,103 @@
+/* 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 reset_control_get_count(struct device *dev);
-int __must_check device_reset_us(struct device_d *dev, int us);
+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)
{
- WARN_ON(1);
return 0;
}
static inline int reset_control_assert(struct reset_control *rstc)
{
- WARN_ON(1);
return 0;
}
static inline int reset_control_deassert(struct reset_control *rstc)
{
- WARN_ON(1);
return 0;
}
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)
{
- WARN_ON(1);
return NULL;
}
static inline void reset_control_put(struct reset_control *rstc)
{
- WARN_ON(1);
}
-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 *dev)
+{
+ return 0;
+}
+
+static inline int device_reset_all(struct device *dev)
{
- WARN_ON(1);
return 0;
}
-static inline int device_reset(struct device_d *dev)
+static inline int reset_control_get_count(struct device *dev)
{
- WARN_ON(1);
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 87fe068396..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
@@ -45,26 +47,11 @@ extern "C" {
#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
struct stat {
- unsigned short st_dev;
- unsigned short __pad1;
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;
- unsigned long st_blksize;
- unsigned long st_blocks;
- unsigned long st_atime;
- unsigned long __unused1;
- unsigned long st_mtime;
- unsigned long __unused2;
- unsigned long st_ctime;
- unsigned long __unused3;
- unsigned long __unused4;
- unsigned long __unused5;
};
#ifdef __cplusplus
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 fd42f5020a..0d046f7832 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -1,16 +1,17 @@
+/* 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" {
#endif
-extern char * ___strtok;
extern char * strpbrk(const char *,const char *);
-extern char * strtok(char *,const char *);
extern char * strsep(char **,const char *);
extern __kernel_size_t strspn(const char *,const char *);
@@ -27,6 +28,10 @@ extern __kernel_size_t strspn(const char *,const char *);
(typeof(&(s1)[0]))(_strstr((s1), (s2))); \
})
+#ifndef __HAVE_ARCH_STRCHRNUL
+extern char * strchrnul(const char *,int);
+#endif
+
/*
* Include machine specific inline routines
*/
@@ -41,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
@@ -53,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
@@ -110,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.
@@ -129,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);
@@ -136,4 +164,37 @@ static inline void *kmemdup(const void *src, size_t len, gfp_t gfp)
extern int kstrtobool(const char *s, bool *res);
+int match_string(const char * const *array, size_t n, const char *string);
+
+/**
+ * strstarts - does @str start with @prefix?
+ * @str: string to examine
+ * @prefix: prefix to look for.
+ */
+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/typecheck.h b/include/linux/typecheck.h
new file mode 100644
index 0000000000..20d310331e
--- /dev/null
+++ b/include/linux/typecheck.h
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef TYPECHECK_H_INCLUDED
+#define TYPECHECK_H_INCLUDED
+
+/*
+ * 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; \
+})
+
+/*
+ * Check at compile time that 'function' is a certain type, or is a pointer
+ * to that type (needs to use typedef for the function type.)
+ */
+#define typecheck_fn(type,function) \
+({ typeof(type) __tmp = function; \
+ (void)__tmp; \
+})
+
+#endif /* TYPECHECK_H_INCLUDED */
diff --git a/include/linux/types.h b/include/linux/types.h
index c19d1dc053..aee9dfa87e 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -1,5 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
#ifndef _LINUX_TYPES_H
#define _LINUX_TYPES_H
+#ifndef __ASSEMBLY__
#include <linux/posix_types.h>
#include <asm/types.h>
@@ -166,13 +169,8 @@ typedef __u32 __bitwise __wsum;
*
* blkcnt_t is the type of the inode's block count.
*/
-#ifdef CONFIG_LBDAF
typedef u64 sector_t;
typedef u64 blkcnt_t;
-#else
-typedef unsigned long sector_t;
-typedef unsigned long blkcnt_t;
-#endif
/*
* The type of an index into the pagecache.
@@ -206,4 +204,19 @@ struct ustat {
char f_fpack[6];
};
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+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
new file mode 100644
index 0000000000..a4a54531ca
--- /dev/null
+++ b/include/linux/virtio.h
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_VIRTIO_H
+#define _LINUX_VIRTIO_H
+/* Everything a virtio driver needs to work with any particular virtio
+ * implementation. */
+#include <linux/types.h>
+#include <driver.h>
+#include <linux/slab.h>
+
+struct virtio_device_id {
+ __u32 device;
+ __u32 vendor;
+};
+#define VIRTIO_DEV_ANY_ID 0xffffffff
+
+/**
+ * virtio scatter-gather struct
+ *
+ * @addr: sg buffer address
+ * @lengh: sg buffer length
+ */
+struct virtio_sg {
+ void *addr;
+ size_t length;
+};
+
+static inline void virtio_sg_init_one(struct virtio_sg *sg,
+ void *addr, size_t length)
+{
+ sg[0].addr = addr;
+ sg[0].length = length;
+}
+
+struct virtio_config_ops;
+
+/**
+ * virtio_device - representation of a device using virtio
+ * @index: unique position on the virtio bus
+ * @failed: saved value for VIRTIO_CONFIG_S_FAILED bit (for restore)
+ * @config_enabled: configuration change reporting enabled
+ * @config_change_pending: configuration change reported while disabled
+ * @dev: underlying device.
+ * @id: the device type identification (used to match it with a driver).
+ * @config: the configuration ops for this device.
+ * @vringh_config: configuration ops for host vrings.
+ * @vqs: the list of virtqueues for this device.
+ * @features: the features supported by both driver and device.
+ * @priv: private pointer for the driver's use.
+ */
+struct virtio_device {
+ int index;
+ bool failed;
+ bool config_enabled;
+ bool config_change_pending;
+ struct device dev;
+ struct virtio_device_id id;
+ const struct virtio_config_ops *config;
+ struct list_head vqs;
+ u64 features;
+ void *priv;
+ u32 status_param;
+};
+
+static inline struct virtio_device *dev_to_virtio(struct device *_dev)
+{
+ return container_of(_dev, struct virtio_device, 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 *dev);
+
+void virtio_break_device(struct virtio_device *dev);
+
+void virtio_config_changed(struct virtio_device *dev);
+void virtio_config_disable(struct virtio_device *dev);
+void virtio_config_enable(struct virtio_device *dev);
+int virtio_finalize_features(struct virtio_device *dev);
+
+size_t virtio_max_dma_size(struct virtio_device *vdev);
+
+#define virtio_device_for_each_vq(vdev, vq) \
+ list_for_each_entry(vq, &vdev->vqs, list)
+
+/**
+ * virtio_driver - operations for a virtio I/O driver
+ * @driver: underlying device driver (populate name and owner).
+ * @id_table: the ids serviced by this driver.
+ * @feature_table: an array of feature numbers supported by this driver.
+ * @feature_table_size: number of entries in the feature table array.
+ * @feature_table_legacy: same as feature_table but when working in legacy mode.
+ * @feature_table_size_legacy: number of entries in feature table legacy array.
+ * @probe: the function to call when a device is found. Returns 0 or -errno.
+ * @scan: optional function to call after successful probe; intended
+ * for virtio-scsi to invoke a scan.
+ * @remove: the function to call when a device is removed.
+ * @config_changed: optional function to call when the device configuration
+ * changes; may be called in interrupt context.
+ * @freeze: optional function to call during suspend/hibernation.
+ * @restore: optional function to call on resume.
+ */
+struct virtio_driver {
+ struct driver driver;
+ const struct virtio_device_id *id_table;
+ const unsigned int *feature_table;
+ unsigned int feature_table_size;
+ const unsigned int *feature_table_legacy;
+ unsigned int feature_table_size_legacy;
+ int (*validate)(struct virtio_device *dev);
+ int (*probe)(struct virtio_device *dev);
+ void (*scan)(struct virtio_device *dev);
+ void (*remove)(struct virtio_device *dev);
+ void (*config_changed)(struct virtio_device *dev);
+};
+
+static inline struct virtio_driver *drv_to_virtio(struct driver *drv)
+{
+ return container_of(drv, struct virtio_driver, driver);
+}
+
+int virtio_driver_register(struct virtio_driver *drv);
+
+/* module_virtio_driver() - Helper macro for drivers that don't do
+ * anything special in module init/exit. This eliminates a lot of
+ * boilerplate. Each module may only use this macro once, and
+ * calling it replaces module_init() and module_exit()
+ */
+#define module_virtio_driver(drv) \
+ device_virtio_driver(drv)
+
+#define device_virtio_driver(drv) \
+ register_driver_macro(device,virtio,drv)
+
+#endif /* _LINUX_VIRTIO_H */
diff --git a/include/linux/virtio_byteorder.h b/include/linux/virtio_byteorder.h
new file mode 100644
index 0000000000..825aaefac9
--- /dev/null
+++ b/include/linux/virtio_byteorder.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_VIRTIO_BYTEORDER_H
+#define _LINUX_VIRTIO_BYTEORDER_H
+#include <linux/types.h>
+#include <uapi/linux/virtio_types.h>
+
+static inline bool virtio_legacy_is_little_endian(void)
+{
+#ifdef __LITTLE_ENDIAN
+ return true;
+#else
+ return false;
+#endif
+}
+
+static inline u16 __virtio16_to_cpu(bool little_endian, __virtio16 val)
+{
+ if (little_endian)
+ return le16_to_cpu((__force __le16)val);
+ else
+ return be16_to_cpu((__force __be16)val);
+}
+
+static inline __virtio16 __cpu_to_virtio16(bool little_endian, u16 val)
+{
+ if (little_endian)
+ return (__force __virtio16)cpu_to_le16(val);
+ else
+ return (__force __virtio16)cpu_to_be16(val);
+}
+
+static inline u32 __virtio32_to_cpu(bool little_endian, __virtio32 val)
+{
+ if (little_endian)
+ return le32_to_cpu((__force __le32)val);
+ else
+ return be32_to_cpu((__force __be32)val);
+}
+
+static inline __virtio32 __cpu_to_virtio32(bool little_endian, u32 val)
+{
+ if (little_endian)
+ return (__force __virtio32)cpu_to_le32(val);
+ else
+ return (__force __virtio32)cpu_to_be32(val);
+}
+
+static inline u64 __virtio64_to_cpu(bool little_endian, __virtio64 val)
+{
+ if (little_endian)
+ return le64_to_cpu((__force __le64)val);
+ else
+ return be64_to_cpu((__force __be64)val);
+}
+
+static inline __virtio64 __cpu_to_virtio64(bool little_endian, u64 val)
+{
+ if (little_endian)
+ return (__force __virtio64)cpu_to_le64(val);
+ else
+ return (__force __virtio64)cpu_to_be64(val);
+}
+
+#endif /* _LINUX_VIRTIO_BYTEORDER */
diff --git a/include/linux/virtio_config.h b/include/linux/virtio_config.h
new file mode 100644
index 0000000000..6bb1f768b6
--- /dev/null
+++ b/include/linux/virtio_config.h
@@ -0,0 +1,538 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_VIRTIO_CONFIG_H
+#define _LINUX_VIRTIO_CONFIG_H
+
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/virtio.h>
+#include <linux/virtio_byteorder.h>
+#include <linux/compiler_types.h>
+#include <linux/typecheck.h>
+#include <uapi/linux/virtio_config.h>
+
+#ifndef might_sleep
+#define might_sleep() do { } while (0)
+#endif
+
+struct virtio_shm_region {
+ u64 addr;
+ u64 len;
+};
+
+struct virtqueue;
+
+/* virtio bus operations */
+struct virtio_config_ops {
+ /**
+ * get_config() - read the value of a configuration field
+ *
+ * @vdev: the real virtio device
+ * @offset: the offset of the configuration field
+ * @buf: the buffer to write the field value into
+ * @len: the length of the buffer
+ * @return 0 if OK, -ve on error
+ */
+ int (*get_config)(struct virtio_device *vdev, unsigned int offset,
+ void *buf, unsigned int len);
+ /**
+ * set_config() - write the value of a configuration field
+ *
+ * @vdev: the real virtio device
+ * @offset: the offset of the configuration field
+ * @buf: the buffer to read the field value from
+ * @len: the length of the buffer
+ * @return 0 if OK, -ve on error
+ */
+ int (*set_config)(struct virtio_device *vdev, unsigned int offset,
+ const void *buf, unsigned int len);
+ /**
+ * generation() - config generation counter
+ *
+ * @vdev: the real virtio device
+ * @return the config generation counter
+ */
+ u32 (*generation)(struct virtio_device *vdev);
+ /**
+ * get_status() - read the status byte
+ *
+ * @vdev: the real virtio device
+ * @status: the returned status byte
+ * @return 0 if OK, -ve on error
+ */
+ int (*get_status)(struct virtio_device *vdev);
+ /**
+ * set_status() - write the status byte
+ *
+ * @vdev: the real virtio device
+ * @status: the new status byte
+ * @return 0 if OK, -ve on error
+ */
+ int (*set_status)(struct virtio_device *vdev, u8 status);
+ /**
+ * reset() - reset the device
+ *
+ * @vdev: the real virtio device
+ * @return 0 if OK, -ve on error
+ */
+ int (*reset)(struct virtio_device *vdev);
+ /**
+ * get_features() - get the array of feature bits for this device
+ *
+ * @vdev: the real virtio device
+ * @return features
+ */
+ u64 (*get_features)(struct virtio_device *vdev);
+ /**
+ * find_vqs() - find virtqueues and instantiate them
+ *
+ * @vdev: the real virtio device
+ * @nvqs: the number of virtqueues to find
+ * @vqs: on success, includes new virtqueues
+ * @return 0 if OK, -ve on error
+ */
+ int (*find_vqs)(struct virtio_device *vdev, unsigned int nvqs,
+ struct virtqueue *vqs[]);
+ /**
+ * del_vqs() - free virtqueues found by find_vqs()
+ *
+ * @vdev: the real virtio device
+ * @return 0 if OK, -ve on error
+ */
+ int (*del_vqs)(struct virtio_device *vdev);
+ /**
+ * notify() - notify the device to process the queue
+ *
+ * @vdev: the real virtio device
+ * @vq: virtqueue to process
+ * @return 0 if OK, -ve on error
+ */
+ int (*notify)(struct virtio_device *vdev, struct virtqueue *vq);
+ /**
+ * finalize_features() - confirm what device features we'll be using.
+ * @vdev: the virtio_device
+ * This gives the final feature bits for the device: it can change
+ * the dev->feature bits if it wants.
+ * @returns 0 if OK, -ve on error
+ */
+ int (*finalize_features)(struct virtio_device *vdev);
+};
+
+/* If driver didn't advertise the feature, it will never appear. */
+void virtio_check_driver_offered_feature(const struct virtio_device *vdev,
+ unsigned int fbit);
+
+/**
+ * __virtio_test_bit - helper to test feature bits. For use by transports.
+ * Devices should normally use virtio_has_feature,
+ * which includes more checks.
+ * @vdev: the device
+ * @fbit: the feature bit
+ */
+static inline bool __virtio_test_bit(const struct virtio_device *vdev,
+ unsigned int fbit)
+{
+ /* Did you forget to fix assumptions on max features? */
+ if (__builtin_constant_p(fbit))
+ BUILD_BUG_ON(fbit >= 64);
+ else
+ BUG_ON(fbit >= 64);
+
+ return vdev->features & BIT_ULL(fbit);
+}
+
+/**
+ * __virtio_set_bit - helper to set feature bits. For use by transports.
+ * @vdev: the device
+ * @fbit: the feature bit
+ */
+static inline void __virtio_set_bit(struct virtio_device *vdev,
+ unsigned int fbit)
+{
+ /* Did you forget to fix assumptions on max features? */
+ if (__builtin_constant_p(fbit))
+ BUILD_BUG_ON(fbit >= 64);
+ else
+ BUG_ON(fbit >= 64);
+
+ vdev->features |= BIT_ULL(fbit);
+}
+
+/**
+ * __virtio_clear_bit - helper to clear feature bits. For use by transports.
+ * @vdev: the device
+ * @fbit: the feature bit
+ */
+static inline void __virtio_clear_bit(struct virtio_device *vdev,
+ unsigned int fbit)
+{
+ /* Did you forget to fix assumptions on max features? */
+ if (__builtin_constant_p(fbit))
+ BUILD_BUG_ON(fbit >= 64);
+ else
+ BUG_ON(fbit >= 64);
+
+ vdev->features &= ~BIT_ULL(fbit);
+}
+
+/**
+ * virtio_has_feature - helper to determine if this device has this feature.
+ * @vdev: the device
+ * @fbit: the feature bit
+ */
+static inline bool virtio_has_feature(const struct virtio_device *vdev,
+ unsigned int fbit)
+{
+ if (fbit < VIRTIO_TRANSPORT_F_START)
+ virtio_check_driver_offered_feature(vdev, fbit);
+
+ return __virtio_test_bit(vdev, fbit);
+}
+
+/**
+ * virtio_has_dma_quirk - determine whether this device has the DMA quirk
+ * @vdev: the device
+ */
+static inline bool virtio_has_dma_quirk(const struct virtio_device *vdev)
+{
+ /*
+ * Note the reverse polarity of the quirk feature (compared to most
+ * other features), this is for compatibility with legacy systems.
+ */
+ return !virtio_has_feature(vdev, VIRTIO_F_ACCESS_PLATFORM);
+}
+
+static inline bool virtio_is_little_endian(struct virtio_device *vdev)
+{
+ return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
+ virtio_legacy_is_little_endian();
+}
+
+
+/**
+ * virtio_get_config() - read the value of a configuration field
+ *
+ * @vdev: the real virtio device
+ * @offset: the offset of the configuration field
+ * @buf: the buffer to write the field value into
+ * @len: the length of the buffer
+ * @return 0 if OK, -ve on error
+ */
+static inline int virtio_get_config(struct virtio_device *vdev, unsigned int offset,
+ void *buf, unsigned int len)
+{
+ return vdev->config->get_config(vdev, offset, buf, len);
+}
+
+/**
+ * virtio_set_config() - write the value of a configuration field
+ *
+ * @vdev: the real virtio device
+ * @offset: the offset of the configuration field
+ * @buf: the buffer to read the field value from
+ * @len: the length of the buffer
+ * @return 0 if OK, -ve on error
+ */
+static inline int virtio_set_config(struct virtio_device *vdev, unsigned int offset,
+ void *buf, unsigned int len)
+{
+ return vdev->config->set_config(vdev, offset, buf, len);
+}
+
+/**
+ * virtio_find_vqs() - find virtqueues and instantiate them
+ *
+ * @vdev: the real virtio device
+ * @nvqs: the number of virtqueues to find
+ * @vqs: on success, includes new virtqueues
+ * @return 0 if OK, -ve on error
+ */
+int virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
+ struct virtqueue *vqs[]);
+
+/**
+ * virtio_device_ready - enable vq use in probe function
+ * @vdev: the device
+ *
+ * Driver must call this to use vqs in the probe function.
+ *
+ * Note: vqs are enabled automatically after probe returns.
+ */
+static inline
+void virtio_device_ready(struct virtio_device *dev)
+{
+ unsigned status = dev->config->get_status(dev);
+
+ BUG_ON(status & VIRTIO_CONFIG_S_DRIVER_OK);
+ dev->config->set_status(dev, status | VIRTIO_CONFIG_S_DRIVER_OK);
+}
+
+
+/* Memory accessors */
+static inline u16 virtio16_to_cpu(struct virtio_device *vdev, __virtio16 val)
+{
+ return __virtio16_to_cpu(virtio_is_little_endian(vdev), val);
+}
+
+static inline __virtio16 cpu_to_virtio16(struct virtio_device *vdev, u16 val)
+{
+ return __cpu_to_virtio16(virtio_is_little_endian(vdev), val);
+}
+
+static inline u32 virtio32_to_cpu(struct virtio_device *vdev, __virtio32 val)
+{
+ return __virtio32_to_cpu(virtio_is_little_endian(vdev), val);
+}
+
+static inline __virtio32 cpu_to_virtio32(struct virtio_device *vdev, u32 val)
+{
+ return __cpu_to_virtio32(virtio_is_little_endian(vdev), val);
+}
+
+static inline u64 virtio64_to_cpu(struct virtio_device *vdev, __virtio64 val)
+{
+ return __virtio64_to_cpu(virtio_is_little_endian(vdev), val);
+}
+
+static inline __virtio64 cpu_to_virtio64(struct virtio_device *vdev, u64 val)
+{
+ return __cpu_to_virtio64(virtio_is_little_endian(vdev), val);
+}
+
+/* Read @count fields, @bytes each */
+static inline void __virtio_cread_many(struct virtio_device *vdev,
+ unsigned int offset,
+ void *buf, size_t count, size_t bytes)
+{
+ u32 old, gen;
+ int i;
+
+ /* no need to check return value as generation can be optional */
+ gen = vdev->config->generation(vdev);
+ do {
+ old = gen;
+
+ for (i = 0; i < count; i++)
+ virtio_get_config(vdev, offset + bytes * i,
+ buf + i * bytes, bytes);
+
+ gen = vdev->config->generation(vdev);
+ } while (gen != old);
+}
+
+static inline void virtio_cread_bytes(struct virtio_device *vdev,
+ unsigned int offset,
+ void *buf, size_t len)
+{
+ __virtio_cread_many(vdev, offset, buf, len, 1);
+}
+
+static inline u8 virtio_cread8(struct virtio_device *vdev, unsigned int offset)
+{
+ u8 ret;
+
+ virtio_get_config(vdev, offset, &ret, sizeof(ret));
+ return ret;
+}
+
+static inline void virtio_cwrite8(struct virtio_device *vdev,
+ unsigned int offset, u8 val)
+{
+ virtio_set_config(vdev, offset, &val, sizeof(val));
+}
+
+static inline u16 virtio_cread16(struct virtio_device *vdev,
+ unsigned int offset)
+{
+ u16 ret;
+
+ virtio_get_config(vdev, offset, &ret, sizeof(ret));
+ return virtio16_to_cpu(vdev, (__force __virtio16)ret);
+}
+
+static inline void virtio_cwrite16(struct virtio_device *vdev,
+ unsigned int offset, u16 val)
+{
+ val = (__force u16)cpu_to_virtio16(vdev, val);
+ virtio_set_config(vdev, offset, &val, sizeof(val));
+}
+
+static inline u32 virtio_cread32(struct virtio_device *vdev,
+ unsigned int offset)
+{
+ u32 ret;
+
+ virtio_get_config(vdev, offset, &ret, sizeof(ret));
+ return virtio32_to_cpu(vdev, (__force __virtio32)ret);
+}
+
+static inline void virtio_cwrite32(struct virtio_device *vdev,
+ unsigned int offset, u32 val)
+{
+ val = (__force u32)cpu_to_virtio32(vdev, val);
+ virtio_set_config(vdev, offset, &val, sizeof(val));
+}
+
+static inline u64 virtio_cread64(struct virtio_device *vdev,
+ unsigned int offset)
+{
+ u64 ret;
+
+ __virtio_cread_many(vdev, offset, &ret, 1, sizeof(ret));
+ return virtio64_to_cpu(vdev, (__force __virtio64)ret);
+}
+
+static inline void virtio_cwrite64(struct virtio_device *vdev,
+ unsigned int offset, u64 val)
+{
+ val = (__force u64)cpu_to_virtio64(vdev, val);
+ virtio_set_config(vdev, offset, &val, sizeof(val));
+}
+
+/* Config space read accessor */
+#define virtio_cread(vdev, structname, member, ptr) \
+ do { \
+ /* Must match the member's type, and be integer */ \
+ if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
+ (*ptr) = 1; \
+ \
+ switch (sizeof(*ptr)) { \
+ case 1: \
+ *(ptr) = virtio_cread8(vdev, \
+ offsetof(structname, member)); \
+ break; \
+ case 2: \
+ *(ptr) = virtio_cread16(vdev, \
+ offsetof(structname, member)); \
+ break; \
+ case 4: \
+ *(ptr) = virtio_cread32(vdev, \
+ offsetof(structname, member)); \
+ break; \
+ case 8: \
+ *(ptr) = virtio_cread64(vdev, \
+ offsetof(structname, member)); \
+ break; \
+ default: \
+ WARN_ON(true); \
+ } \
+ } while (0)
+
+/* Config space write accessor */
+#define virtio_cwrite(vdev, structname, member, ptr) \
+ do { \
+ /* Must match the member's type, and be integer */ \
+ if (!typecheck(typeof((((structname *)0)->member)), *(ptr))) \
+ WARN_ON((*ptr) == 1); \
+ \
+ switch (sizeof(*ptr)) { \
+ case 1: \
+ virtio_cwrite8(vdev, \
+ offsetof(structname, member), \
+ *(ptr)); \
+ break; \
+ case 2: \
+ virtio_cwrite16(vdev, \
+ offsetof(structname, member), \
+ *(ptr)); \
+ break; \
+ case 4: \
+ virtio_cwrite32(vdev, \
+ offsetof(structname, member), \
+ *(ptr)); \
+ break; \
+ case 8: \
+ virtio_cwrite64(vdev, \
+ offsetof(structname, member), \
+ *(ptr)); \
+ break; \
+ default: \
+ WARN_ON(true); \
+ } \
+ } while (0)
+
+/* Conditional config space accessors */
+#define virtio_cread_feature(vdev, fbit, structname, member, ptr) \
+ ({ \
+ int _r = 0; \
+ if (!virtio_has_feature(vdev, fbit)) \
+ _r = -ENOENT; \
+ else \
+ virtio_cread(vdev, structname, member, ptr); \
+ _r; \
+ })
+
+/*
+ * Nothing virtio-specific about these, but let's worry about generalizing
+ * these later.
+ */
+#define virtio_le_to_cpu(x) \
+ _Generic((x), \
+ __u8: (u8)(x), \
+ __le16: (u16)le16_to_cpu(x), \
+ __le32: (u32)le32_to_cpu(x), \
+ __le64: (u64)le64_to_cpu(x) \
+ )
+
+#define virtio_cpu_to_le(x, m) \
+ _Generic((m), \
+ __u8: (x), \
+ __le16: cpu_to_le16(x), \
+ __le32: cpu_to_le32(x), \
+ __le64: cpu_to_le64(x) \
+ )
+
+/* LE (e.g. modern) Config space accessors. */
+#define virtio_cread_le(vdev, structname, member, ptr) \
+ do { \
+ typeof(((structname*)0)->member) virtio_cread_v; \
+ \
+ /* Sanity check: must match the member's type */ \
+ typecheck(typeof(virtio_le_to_cpu(virtio_cread_v)), *(ptr)); \
+ \
+ switch (sizeof(virtio_cread_v)) { \
+ case 1: \
+ case 2: \
+ case 4: \
+ vdev->config->get_config((vdev), \
+ offsetof(structname, member), \
+ &virtio_cread_v, \
+ sizeof(virtio_cread_v)); \
+ break; \
+ default: \
+ __virtio_cread_many((vdev), \
+ offsetof(structname, member), \
+ &virtio_cread_v, \
+ 1, \
+ sizeof(virtio_cread_v)); \
+ break; \
+ } \
+ *(ptr) = virtio_le_to_cpu(virtio_cread_v); \
+ } while(0)
+
+#define virtio_cwrite_le(vdev, structname, member, ptr) \
+ do { \
+ typeof(((structname*)0)->member) virtio_cwrite_v = \
+ virtio_cpu_to_le(*(ptr), ((structname*)0)->member); \
+ \
+ /* Sanity check: must match the member's type */ \
+ typecheck(typeof(virtio_le_to_cpu(virtio_cwrite_v)), *(ptr)); \
+ \
+ vdev->config->set_config((vdev), offsetof(structname, member), \
+ &virtio_cwrite_v, \
+ sizeof(virtio_cwrite_v)); \
+ } while(0)
+
+
+#ifdef CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS
+int arch_has_restricted_virtio_memory_access(void);
+#else
+static inline int arch_has_restricted_virtio_memory_access(void)
+{
+ return 0;
+}
+#endif /* CONFIG_ARCH_HAS_RESTRICTED_VIRTIO_MEMORY_ACCESS */
+
+
+#undef might_sleep
+
+#endif /* _LINUX_VIRTIO_CONFIG_H */
diff --git a/include/linux/virtio_ring.h b/include/linux/virtio_ring.h
new file mode 100644
index 0000000000..bdef47b0fa
--- /dev/null
+++ b/include/linux/virtio_ring.h
@@ -0,0 +1,366 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Copyright (C) 2018, Tuomas Tynkkynen <tuomas.tynkkynen@iki.fi>
+ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com>
+ *
+ * From Linux kernel include/uapi/linux/virtio_ring.h
+ */
+
+#ifndef _LINUX_VIRTIO_RING_H
+#define _LINUX_VIRTIO_RING_H
+
+#include <linux/virtio_types.h>
+
+/* This marks a buffer as continuing via the next field */
+#define VRING_DESC_F_NEXT 1
+/* This marks a buffer as write-only (otherwise read-only) */
+#define VRING_DESC_F_WRITE 2
+/* This means the buffer contains a list of buffer descriptors */
+#define VRING_DESC_F_INDIRECT 4
+
+/*
+ * The Host uses this in used->flags to advise the Guest: don't kick me when
+ * you add a buffer. It's unreliable, so it's simply an optimization. Guest
+ * will still kick if it's out of buffers.
+ */
+#define VRING_USED_F_NO_NOTIFY 1
+
+/*
+ * The Guest uses this in avail->flags to advise the Host: don't interrupt me
+ * when you consume a buffer. It's unreliable, so it's simply an optimization.
+ */
+#define VRING_AVAIL_F_NO_INTERRUPT 1
+
+/* We support indirect buffer descriptors */
+#define VIRTIO_RING_F_INDIRECT_DESC 28
+
+/*
+ * The Guest publishes the used index for which it expects an interrupt
+ * at the end of the avail ring. Host should ignore the avail->flags field.
+ *
+ * The Host publishes the avail index for which it expects a kick
+ * at the end of the used ring. Guest should ignore the used->flags field.
+ */
+#define VIRTIO_RING_F_EVENT_IDX 29
+
+/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */
+struct vring_desc {
+ /* Address (guest-physical) */
+ __virtio64 addr;
+ /* Length */
+ __virtio32 len;
+ /* The flags as indicated above */
+ __virtio16 flags;
+ /* We chain unused descriptors via this, too */
+ __virtio16 next;
+};
+
+struct vring_avail {
+ __virtio16 flags;
+ __virtio16 idx;
+ __virtio16 ring[];
+};
+
+struct vring_used_elem {
+ /* Index of start of used descriptor chain */
+ __virtio32 id;
+ /* Total length of the descriptor chain which was used (written to) */
+ __virtio32 len;
+};
+
+struct vring_used {
+ __virtio16 flags;
+ __virtio16 idx;
+ struct vring_used_elem ring[];
+};
+
+struct vring {
+ unsigned int num;
+ struct vring_desc *desc;
+ struct vring_avail *avail;
+ struct vring_used *used;
+};
+
+/**
+ * virtqueue - a queue to register buffers for sending or receiving.
+ *
+ * @list: the chain of virtqueues for this device
+ * @vdev: the virtio device this queue was created for
+ * @index: the zero-based ordinal number for this queue
+ * @num_free: number of elements we expect to be able to fit
+ * @vring: actual memory layout for this queue
+ * @event: host publishes avail event idx
+ * @free_head: head of free buffer list
+ * @num_added: number we've added since last sync
+ * @last_used_idx: last used index we've seen
+ * @avail_flags_shadow: last written value to avail->flags
+ * @avail_idx_shadow: last written value to avail->idx in guest byte order
+ */
+struct virtqueue {
+ struct list_head list;
+ struct virtio_device *vdev;
+ unsigned int index;
+ unsigned int num_free;
+ struct vring vring;
+ bool event;
+ unsigned int free_head;
+ unsigned int num_added;
+ u16 last_used_idx;
+ u16 avail_flags_shadow;
+ u16 avail_idx_shadow;
+ dma_addr_t queue_dma_addr;
+ size_t queue_size_in_bytes;
+};
+
+/*
+ * Alignment requirements for vring elements.
+ * When using pre-virtio 1.0 layout, these fall out naturally.
+ */
+#define VRING_AVAIL_ALIGN_SIZE 2
+#define VRING_USED_ALIGN_SIZE 4
+#define VRING_DESC_ALIGN_SIZE 16
+
+/*
+ * We publish the used event index at the end of the available ring,
+ * and vice versa. They are at the end for backwards compatibility.
+ */
+#define vring_used_event(vr) ((vr)->avail->ring[(vr)->num])
+#define vring_avail_event(vr) (*(__virtio16 *)&(vr)->used->ring[(vr)->num])
+
+static inline void vring_init(struct vring *vr, unsigned int num, void *p,
+ unsigned long align)
+{
+ vr->num = num;
+ vr->desc = p;
+ vr->avail = p + num * sizeof(struct vring_desc);
+ vr->used = (void *)(((uintptr_t)&vr->avail->ring[num] +
+ sizeof(__virtio16) + align - 1) & ~(align - 1));
+}
+
+static inline unsigned int vring_size(unsigned int num, unsigned long align)
+{
+ return ((sizeof(struct vring_desc) * num +
+ sizeof(__virtio16) * (3 + num) + align - 1) & ~(align - 1)) +
+ sizeof(__virtio16) * 3 + sizeof(struct vring_used_elem) * num;
+}
+
+/*
+ * The following is used with USED_EVENT_IDX and AVAIL_EVENT_IDX.
+ * Assuming a given event_idx value from the other side, if we have just
+ * incremented index from old to new_idx, should we trigger an event?
+ */
+static inline int vring_need_event(__u16 event_idx, __u16 new_idx, __u16 old)
+{
+ /*
+ * Note: Xen has similar logic for notification hold-off
+ * in include/xen/interface/io/ring.h with req_event and req_prod
+ * corresponding to event_idx + 1 and new_idx respectively.
+ * Note also that req_event and req_prod in Xen start at 1,
+ * event indexes in virtio start at 0.
+ */
+ return (__u16)(new_idx - event_idx - 1) < (__u16)(new_idx - old);
+}
+
+struct virtio_sg;
+
+/**
+ * virtqueue_add - expose buffers to other end
+ *
+ * @vq: the struct virtqueue we're talking about
+ * @sgs: array of terminated scatterlists
+ * @out_sgs: the number of scatterlists readable by other side
+ * @in_sgs: the number of scatterlists which are writable
+ * (after readable ones)
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).
+ */
+int virtqueue_add(struct virtqueue *vq, struct virtio_sg *sgs[],
+ unsigned int out_sgs, unsigned int in_sgs);
+
+/**
+ * virtqueue_add_outbuf - expose output buffers to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sg: scatterlist (must be well-formed and terminated!)
+ * @num: the number of entries in @sg readable by other side
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).
+ */
+static inline int virtqueue_add_outbuf(struct virtqueue *vq,
+ struct virtio_sg *sg, unsigned int num)
+{
+ return virtqueue_add(vq, &sg, num, 0);
+}
+
+/**
+ * virtqueue_add_inbuf - expose input buffers to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sg: scatterlist (must be well-formed and terminated!)
+ * @num: the number of entries in @sg writable by other side
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).
+ */
+static inline int virtqueue_add_inbuf(struct virtqueue *vq,
+ struct virtio_sg *sg, unsigned int num)
+{
+ return virtqueue_add(vq, &sg, 0, num);
+}
+
+/**
+ * virtqueue_kick - update after add_buf
+ *
+ * @vq: the struct virtqueue
+ *
+ * After one or more virtqueue_add() calls, invoke this to kick
+ * the other side.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ */
+void virtqueue_kick(struct virtqueue *vq);
+
+/**
+ * virtqueue_get_buf - get the next used buffer
+ *
+ * @vq: the struct virtqueue we're talking about
+ * @len: the length written into the buffer
+ *
+ * If the device wrote data into the buffer, @len will be set to the
+ * amount written. This means you don't need to clear the buffer
+ * beforehand to ensure there's no data leakage in the case of short
+ * writes.
+ *
+ * Caller must ensure we don't call this with other virtqueue
+ * operations at the same time (except where noted).
+ *
+ * Returns NULL if there are no used buffers, or the memory buffer
+ * handed to virtqueue_add_*().
+ */
+void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
+
+/**
+ * vring_create_virtqueue - create a virtqueue for a virtio device
+ *
+ * @index: the index of the queue
+ * @num: number of elements of the queue
+ * @vring_align:the alignment requirement of the descriptor ring
+ * @udev: the virtio transport device
+ * @return: the virtqueue pointer or NULL if failed
+ *
+ * This creates a virtqueue and allocates the descriptor ring for a virtio
+ * device. The caller should query virtqueue_get_ring_size() to learn the
+ * actual size of the ring.
+ *
+ * This API is supposed to be called by the virtio transport driver in the
+ * virtio find_vqs() uclass method.
+ */
+struct virtqueue *vring_create_virtqueue(unsigned int index, unsigned int num,
+ unsigned int vring_align,
+ struct virtio_device *vdev);
+
+/**
+ * vring_del_virtqueue - destroy a virtqueue
+ *
+ * @vq: the struct virtqueue we're talking about
+ *
+ * This destroys a virtqueue. If created with vring_create_virtqueue(),
+ * this also frees the descriptor ring.
+ *
+ * This API is supposed to be called by the virtio transport driver in the
+ * virtio del_vqs() uclass method.
+ */
+void vring_del_virtqueue(struct virtqueue *vq);
+
+/**
+ * virtqueue_get_vring_size - get the size of the virtqueue's vring
+ *
+ * @vq: the struct virtqueue containing the vring of interest
+ * @return: the size of the vring in a virtqueue.
+ */
+unsigned int virtqueue_get_vring_size(struct virtqueue *vq);
+
+/**
+ * virtqueue_get_desc_addr - get the vring descriptor table address
+ *
+ * @vq: the struct virtqueue containing the vring of interest
+ * @return: the descriptor table address of the vring in a virtqueue.
+ */
+dma_addr_t virtqueue_get_desc_addr(struct virtqueue *vq);
+
+/**
+ * virtqueue_get_avail_addr - get the vring available ring address
+ *
+ * @vq: the struct virtqueue containing the vring of interest
+ * @return: the available ring address of the vring in a virtqueue.
+ */
+dma_addr_t virtqueue_get_avail_addr(struct virtqueue *vq);
+
+/**
+ * virtqueue_get_used_addr - get the vring used ring address
+ *
+ * @vq: the struct virtqueue containing the vring of interest
+ * @return: the used ring address of the vring in a virtqueue.
+ */
+dma_addr_t virtqueue_get_used_addr(struct virtqueue *vq);
+
+/**
+ * virtqueue_poll - query pending used buffers
+ *
+ * @vq: the struct virtqueue we're talking about
+ * @last_used_idx: virtqueue last used index
+ *
+ * Returns "true" if there are pending used buffers in the queue.
+ */
+bool virtqueue_poll(const struct virtqueue *vq, u16 last_used_idx);
+
+/**
+ * virtio_notify() - notify the device to process the queue
+ *
+ * @vdev: the real virtio device
+ * @vq: virtqueue to process
+ * @return 0 if OK, -ve on error
+ */
+int virtio_notify(struct virtio_device *vdev, struct virtqueue *vq);
+
+
+/**
+ * virtqueue_dump - dump the virtqueue for debugging
+ *
+ * @vq: the struct virtqueue we're talking about
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ */
+void virtqueue_dump(struct virtqueue *vq);
+
+/*
+ * Barriers in virtio are tricky. Since we are not in a hyperviosr/guest
+ * scenario, having these as nops is enough to work as expected.
+ */
+
+static inline void virtio_mb(void)
+{
+}
+
+static inline void virtio_rmb(void)
+{
+}
+
+static inline void virtio_wmb(void)
+{
+}
+
+static inline void virtio_store_mb(__virtio16 *p, __virtio16 v)
+{
+ WRITE_ONCE(*p, v);
+}
+
+#endif /* _LINUX_VIRTIO_RING_H */
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