162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_GENERIC_UNALIGNED_H
362306a36Sopenharmony_ci#define __ASM_GENERIC_UNALIGNED_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * This is the most generic implementation of unaligned accesses
762306a36Sopenharmony_ci * and should work almost anywhere.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci#include <linux/unaligned/packed_struct.h>
1062306a36Sopenharmony_ci#include <asm/byteorder.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#define __get_unaligned_t(type, ptr) ({						\
1362306a36Sopenharmony_ci	const struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr);	\
1462306a36Sopenharmony_ci	__pptr->x;								\
1562306a36Sopenharmony_ci})
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#define __put_unaligned_t(type, val, ptr) do {					\
1862306a36Sopenharmony_ci	struct { type x; } __packed *__pptr = (typeof(__pptr))(ptr);		\
1962306a36Sopenharmony_ci	__pptr->x = (val);							\
2062306a36Sopenharmony_ci} while (0)
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define get_unaligned(ptr)	__get_unaligned_t(typeof(*(ptr)), (ptr))
2362306a36Sopenharmony_ci#define put_unaligned(val, ptr) __put_unaligned_t(typeof(*(ptr)), (val), (ptr))
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic inline u16 get_unaligned_le16(const void *p)
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	return le16_to_cpu(__get_unaligned_t(__le16, p));
2862306a36Sopenharmony_ci}
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic inline u32 get_unaligned_le32(const void *p)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	return le32_to_cpu(__get_unaligned_t(__le32, p));
3362306a36Sopenharmony_ci}
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_cistatic inline u64 get_unaligned_le64(const void *p)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	return le64_to_cpu(__get_unaligned_t(__le64, p));
3862306a36Sopenharmony_ci}
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic inline void put_unaligned_le16(u16 val, void *p)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	__put_unaligned_t(__le16, cpu_to_le16(val), p);
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic inline void put_unaligned_le32(u32 val, void *p)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	__put_unaligned_t(__le32, cpu_to_le32(val), p);
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_cistatic inline void put_unaligned_le64(u64 val, void *p)
5162306a36Sopenharmony_ci{
5262306a36Sopenharmony_ci	__put_unaligned_t(__le64, cpu_to_le64(val), p);
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_cistatic inline u16 get_unaligned_be16(const void *p)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	return be16_to_cpu(__get_unaligned_t(__be16, p));
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic inline u32 get_unaligned_be32(const void *p)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	return be32_to_cpu(__get_unaligned_t(__be32, p));
6362306a36Sopenharmony_ci}
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic inline u64 get_unaligned_be64(const void *p)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	return be64_to_cpu(__get_unaligned_t(__be64, p));
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic inline void put_unaligned_be16(u16 val, void *p)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	__put_unaligned_t(__be16, cpu_to_be16(val), p);
7362306a36Sopenharmony_ci}
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_cistatic inline void put_unaligned_be32(u32 val, void *p)
7662306a36Sopenharmony_ci{
7762306a36Sopenharmony_ci	__put_unaligned_t(__be32, cpu_to_be32(val), p);
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistatic inline void put_unaligned_be64(u64 val, void *p)
8162306a36Sopenharmony_ci{
8262306a36Sopenharmony_ci	__put_unaligned_t(__be64, cpu_to_be64(val), p);
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic inline u32 __get_unaligned_be24(const u8 *p)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	return p[0] << 16 | p[1] << 8 | p[2];
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic inline u32 get_unaligned_be24(const void *p)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	return __get_unaligned_be24(p);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic inline u32 __get_unaligned_le24(const u8 *p)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	return p[0] | p[1] << 8 | p[2] << 16;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic inline u32 get_unaligned_le24(const void *p)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	return __get_unaligned_le24(p);
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic inline void __put_unaligned_be24(const u32 val, u8 *p)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	*p++ = (val >> 16) & 0xff;
10862306a36Sopenharmony_ci	*p++ = (val >> 8) & 0xff;
10962306a36Sopenharmony_ci	*p++ = val & 0xff;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_cistatic inline void put_unaligned_be24(const u32 val, void *p)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	__put_unaligned_be24(val, p);
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic inline void __put_unaligned_le24(const u32 val, u8 *p)
11862306a36Sopenharmony_ci{
11962306a36Sopenharmony_ci	*p++ = val & 0xff;
12062306a36Sopenharmony_ci	*p++ = (val >> 8) & 0xff;
12162306a36Sopenharmony_ci	*p++ = (val >> 16) & 0xff;
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic inline void put_unaligned_le24(const u32 val, void *p)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	__put_unaligned_le24(val, p);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic inline void __put_unaligned_be48(const u64 val, u8 *p)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	*p++ = (val >> 40) & 0xff;
13262306a36Sopenharmony_ci	*p++ = (val >> 32) & 0xff;
13362306a36Sopenharmony_ci	*p++ = (val >> 24) & 0xff;
13462306a36Sopenharmony_ci	*p++ = (val >> 16) & 0xff;
13562306a36Sopenharmony_ci	*p++ = (val >> 8) & 0xff;
13662306a36Sopenharmony_ci	*p++ = val & 0xff;
13762306a36Sopenharmony_ci}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline void put_unaligned_be48(const u64 val, void *p)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	__put_unaligned_be48(val, p);
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic inline u64 __get_unaligned_be48(const u8 *p)
14562306a36Sopenharmony_ci{
14662306a36Sopenharmony_ci	return (u64)p[0] << 40 | (u64)p[1] << 32 | (u64)p[2] << 24 |
14762306a36Sopenharmony_ci		p[3] << 16 | p[4] << 8 | p[5];
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic inline u64 get_unaligned_be48(const void *p)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	return __get_unaligned_be48(p);
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci#endif /* __ASM_GENERIC_UNALIGNED_H */
156