aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/mpc85xx/image/spi-loader/include
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2022-03-27 20:57:01 +0200
committerDavid Bauer <mail@david-bauer.net>2022-10-14 23:13:02 +0200
commita296055b82fbb20457273492069ce9d62009e2a1 (patch)
tree83db19e52b93c16e832ba33f9f11f20514d6a159 /target/linux/mpc85xx/image/spi-loader/include
parent63e5ba8e69f03a584b707520db0a0821eda3024f (diff)
downloadupstream-a296055b82fbb20457273492069ce9d62009e2a1.tar.gz
upstream-a296055b82fbb20457273492069ce9d62009e2a1.tar.bz2
upstream-a296055b82fbb20457273492069ce9d62009e2a1.zip
mpc85xx: add SPI kernel loader for TP-Link TL-WDR4900 v1
Similar to the lzma-loader on our MIPS targets, the spi-loader acts as a second-stage loader that will then load and start the actual kernel. As the TL-WDR4900 uses SPI-NOR and the P1010 family does not have support for memory mapping of this type of flash, this loader needs to contain a basic driver for the FSL ESPI controller. Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Diffstat (limited to 'target/linux/mpc85xx/image/spi-loader/include')
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/image.h61
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/init.h8
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/io.h101
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/ppc_asm.h55
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/serial.h9
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/spi-nor.h11
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/spi.h43
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/stdio.h43
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/string.h23
-rw-r--r--target/linux/mpc85xx/image/spi-loader/include/types.h72
10 files changed, 426 insertions, 0 deletions
diff --git a/target/linux/mpc85xx/image/spi-loader/include/image.h b/target/linux/mpc85xx/image/spi-loader/include/image.h
new file mode 100644
index 0000000000..0377c2959e
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/image.h
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Derived from U-Boot include/image.h:
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2005
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#pragma once
+
+#include <types.h>
+
+/*
+ * Compression Types
+ *
+ * The following are exposed to uImage header.
+ * New IDs *MUST* be appended at the end of the list and *NEVER*
+ * inserted for backward compatibility.
+ */
+enum {
+ IH_COMP_NONE = 0, /* No Compression Used */
+ IH_COMP_GZIP, /* gzip Compression Used */
+ IH_COMP_BZIP2, /* bzip2 Compression Used */
+ IH_COMP_LZMA, /* lzma Compression Used */
+ IH_COMP_LZO, /* lzo Compression Used */
+ IH_COMP_LZ4, /* lz4 Compression Used */
+ IH_COMP_ZSTD, /* zstd Compression Used */
+
+ IH_COMP_COUNT,
+};
+
+#define IH_MAGIC 0x27051956 /* Image Magic Number */
+#define IH_MAGIC_OKLI 0x4f4b4c49 /* 'OKLI' Magic Number */
+#define IH_NMLEN 32 /* Image Name Length */
+
+/*
+ * Legacy format image header,
+ * all data in network byte order (aka natural aka bigendian).
+ */
+typedef struct image_header {
+ uint32_t ih_magic; /* Image Header Magic Number */
+ uint32_t ih_hcrc; /* Image Header CRC Checksum */
+ uint32_t ih_time; /* Image Creation Timestamp */
+ uint32_t ih_size; /* Image Data Size */
+ uint32_t ih_load; /* Data Load Address */
+ uint32_t ih_ep; /* Entry Point Address */
+ uint32_t ih_dcrc; /* Image Data CRC Checksum */
+ uint8_t ih_os; /* Operating System */
+ uint8_t ih_arch; /* CPU architecture */
+ uint8_t ih_type; /* Image Type */
+ uint8_t ih_comp; /* Compression Type */
+ uint8_t ih_name[IH_NMLEN]; /* Image Name */
+} image_header_t;
diff --git a/target/linux/mpc85xx/image/spi-loader/include/init.h b/target/linux/mpc85xx/image/spi-loader/include/init.h
new file mode 100644
index 0000000000..f3a15f5d43
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/init.h
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022 Matthias Schiffer <mschiffer@universe-factory.net>
+ */
+
+#pragma once
+
+void start(void);
diff --git a/target/linux/mpc85xx/image/spi-loader/include/io.h b/target/linux/mpc85xx/image/spi-loader/include/io.h
new file mode 100644
index 0000000000..d6eed5eee0
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/io.h
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#pragma once
+
+#include <stdint.h>
+
+/*
+ * Low-level I/O routines.
+ *
+ * Copied from <file:arch/powerpc/include/asm/io.h> (which has no copyright)
+ */
+static inline uint8_t in_8(const volatile uint8_t *addr)
+{
+ int ret;
+
+ __asm__ __volatile__("lbz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_8(volatile uint8_t *addr, uint8_t val)
+{
+ __asm__ __volatile__("stb%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline uint16_t in_le16(const volatile uint16_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__("lhbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+
+ return ret;
+}
+
+static inline uint16_t in_be16(const volatile uint16_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__("lhz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le16(volatile uint16_t *addr, uint16_t val)
+{
+ __asm__ __volatile__("sthbrx %1,0,%2; sync" : "=m" (*addr)
+ : "r" (val), "r" (addr));
+}
+
+static inline void out_be16(volatile uint16_t *addr, uint16_t val)
+{
+ __asm__ __volatile__("sth%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline uint32_t in_le32(const volatile uint32_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__("lwbrx %0,0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "r" (addr), "m" (*addr));
+ return ret;
+}
+
+static inline uint32_t in_be32(const volatile uint32_t *addr)
+{
+ uint32_t ret;
+
+ __asm__ __volatile__("lwz%U1%X1 %0,%1; twi 0,%0,0; isync"
+ : "=r" (ret) : "m" (*addr));
+ return ret;
+}
+
+static inline void out_le32(volatile uint32_t *addr, uint32_t val)
+{
+ __asm__ __volatile__("stwbrx %1,0,%2; sync" : "=m" (*addr)
+ : "r" (val), "r" (addr));
+}
+
+static inline void out_be32(volatile uint32_t *addr, uint32_t val)
+{
+ __asm__ __volatile__("stw%U0%X0 %1,%0; sync"
+ : "=m" (*addr) : "r" (val));
+}
+
+static inline void sync(void)
+{
+ asm volatile("sync" : : : "memory");
+}
+
+static inline void eieio(void)
+{
+ asm volatile("eieio" : : : "memory");
+}
+
+static inline void barrier(void)
+{
+ asm volatile("" : : : "memory");
+}
diff --git a/target/linux/mpc85xx/image/spi-loader/include/ppc_asm.h b/target/linux/mpc85xx/image/spi-loader/include/ppc_asm.h
new file mode 100644
index 0000000000..5dae34eb70
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/ppc_asm.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#pragma once
+/*
+ *
+ * Definitions used by various bits of low-level assembly code on PowerPC.
+ *
+ * Copyright (C) 1995-1999 Gary Thomas, Paul Mackerras, Cort Dougan.
+ */
+
+/* Condition Register Bit Fields */
+
+#define cr0 0
+#define cr1 1
+#define cr2 2
+#define cr3 3
+#define cr4 4
+#define cr5 5
+#define cr6 6
+#define cr7 7
+
+/* General Purpose Registers (GPRs) */
+
+#define r0 0
+#define r1 1
+#define r2 2
+#define r3 3
+#define r4 4
+#define r5 5
+#define r6 6
+#define r7 7
+#define r8 8
+#define r9 9
+#define r10 10
+#define r11 11
+#define r12 12
+#define r13 13
+#define r14 14
+#define r15 15
+#define r16 16
+#define r17 17
+#define r18 18
+#define r19 19
+#define r20 20
+#define r21 21
+#define r22 22
+#define r23 23
+#define r24 24
+#define r25 25
+#define r26 26
+#define r27 27
+#define r28 28
+#define r29 29
+#define r30 30
+#define r31 31
diff --git a/target/linux/mpc85xx/image/spi-loader/include/serial.h b/target/linux/mpc85xx/image/spi-loader/include/serial.h
new file mode 100644
index 0000000000..1d80ede335
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/serial.h
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: BSD-2-Clause
+
+#pragma once
+
+int serial_console_getchar(void);
+int serial_console_tstc(void);
+void serial_console_putchar(char c);
+void serial_console_init(void);
+
diff --git a/target/linux/mpc85xx/image/spi-loader/include/spi-nor.h b/target/linux/mpc85xx/image/spi-loader/include/spi-nor.h
new file mode 100644
index 0000000000..efbf386601
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/spi-nor.h
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022 Matthias Schiffer <mschiffer@universe-factory.net>
+ */
+
+#pragma once
+
+#include <types.h>
+
+int spi_nor_read_id(void);
+int spi_nor_read_data(void *dest, size_t pos, size_t len);
diff --git a/target/linux/mpc85xx/image/spi-loader/include/spi.h b/target/linux/mpc85xx/image/spi-loader/include/spi.h
new file mode 100644
index 0000000000..98e799ccaf
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/spi.h
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Common SPI Interface: Controller-specific definitions
+ *
+ * Copyright (c) 2022 Matthias Schiffer <mschiffer@universe-factory.net>
+ *
+ * Based on U-boot's spi.h:
+ *
+ * (C) Copyright 2001
+ * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.com.
+ */
+
+#pragma once
+
+#include <types.h>
+
+/* SPI mode flags */
+#define SPI_CPHA BIT(0) /* clock phase (1 = SPI_CLOCK_PHASE_SECOND) */
+#define SPI_CPOL BIT(1) /* clock polarity (1 = SPI_POLARITY_HIGH) */
+#define SPI_MODE_0 (0|0) /* (original MicroWire) */
+#define SPI_MODE_1 (0|SPI_CPHA)
+#define SPI_MODE_2 (SPI_CPOL|0)
+#define SPI_MODE_3 (SPI_CPOL|SPI_CPHA)
+
+struct spi_transfer {
+ const void *tx_buf;
+ void *rx_buf;
+ size_t len;
+};
+
+static inline size_t spi_message_len(const struct spi_transfer *msg, int n) {
+ size_t total = 0;
+ for (int i = 0; i < n; i++) {
+ total += msg[i].len;
+ }
+ return total;
+}
+
+int spi_init(unsigned int cs, unsigned int max_hz, unsigned int mode);
+int spi_claim_bus(void);
+void spi_release_bus(void);
+int spi_xfer(const struct spi_transfer *msg, int n);
+size_t spi_max_xfer(void);
diff --git a/target/linux/mpc85xx/image/spi-loader/include/stdio.h b/target/linux/mpc85xx/image/spi-loader/include/stdio.h
new file mode 100644
index 0000000000..60494300b2
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/stdio.h
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (c) 2022 Matthias Schiffer <mschiffer@universe-factory.net>
+ */
+
+#pragma once
+
+#include <serial.h>
+#include <types.h>
+
+static inline int getchar(void)
+{
+ return serial_console_getchar();
+}
+
+static inline int tstc(void)
+{
+ return serial_console_tstc();
+}
+
+static inline int putchar(char c)
+{
+ if (c == '\n')
+ serial_console_putchar('\r');
+ serial_console_putchar(c);
+ return 0;
+}
+
+int puts(const char *s);
+
+/* Utility functions */
+void put_u4(uint8_t v);
+void put_u8(uint8_t v);
+void put_u16(uint16_t v);
+void put_u32(uint32_t v);
+void put_ptr(const void *p);
+void put_array(const void *p, size_t l);
+
+#define put_with_label(label, put, value) do { \
+ puts(label); \
+ put(value); \
+ puts("\n"); \
+ } while (0)
diff --git a/target/linux/mpc85xx/image/spi-loader/include/string.h b/target/linux/mpc85xx/image/spi-loader/include/string.h
new file mode 100644
index 0000000000..f9e6fed38d
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/string.h
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#pragma once
+
+#include <stddef.h>
+
+extern char *strcpy(char *dest, const char *src);
+extern char *strncpy(char *dest, const char *src, size_t n);
+extern char *strcat(char *dest, const char *src);
+extern char *strchr(const char *s, int c);
+extern char *strrchr(const char *s, int c);
+extern int strcmp(const char *s1, const char *s2);
+extern int strncmp(const char *s1, const char *s2, size_t n);
+extern size_t strlen(const char *s);
+extern size_t strnlen(const char *s, size_t count);
+
+extern void *memset(void *s, int c, size_t n);
+extern void *memmove(void *dest, const void *src, unsigned long n);
+extern void *memcpy(void *dest, const void *src, unsigned long n);
+extern void *memchr(const void *s, int c, size_t n);
+extern int memcmp(const void *s1, const void *s2, size_t n);
+
+extern void flush_cache(void *, unsigned long);
diff --git a/target/linux/mpc85xx/image/spi-loader/include/types.h b/target/linux/mpc85xx/image/spi-loader/include/types.h
new file mode 100644
index 0000000000..b80f9e625c
--- /dev/null
+++ b/target/linux/mpc85xx/image/spi-loader/include/types.h
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Code originates from Linux kernel arch/powerpc/boot
+ * (types.h, swab.h, of.h)
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define BIT(nr) (1UL << (nr))
+
+#define min(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x < _y ? _x : _y; })
+
+#define max(x,y) ({ \
+ typeof(x) _x = (x); \
+ typeof(y) _y = (y); \
+ (void) (&_x == &_y); \
+ _x > _y ? _x : _y; })
+
+#define min_t(type, a, b) min(((type) a), ((type) b))
+#define max_t(type, a, b) max(((type) a), ((type) b))
+
+static inline uint16_t swab16(uint16_t x)
+{
+ return ((x & (uint16_t)0x00ffU) << 8) |
+ ((x & (uint16_t)0xff00U) >> 8);
+}
+
+static inline uint32_t swab32(uint32_t x)
+{
+ return ((x & (uint32_t)0x000000ffUL) << 24) |
+ ((x & (uint32_t)0x0000ff00UL) << 8) |
+ ((x & (uint32_t)0x00ff0000UL) >> 8) |
+ ((x & (uint32_t)0xff000000UL) >> 24);
+}
+
+static inline uint64_t swab64(uint64_t x)
+{
+ return (uint64_t)((x & (uint64_t)0x00000000000000ffULL) << 56) |
+ (uint64_t)((x & (uint64_t)0x000000000000ff00ULL) << 40) |
+ (uint64_t)((x & (uint64_t)0x0000000000ff0000ULL) << 24) |
+ (uint64_t)((x & (uint64_t)0x00000000ff000000ULL) << 8) |
+ (uint64_t)((x & (uint64_t)0x000000ff00000000ULL) >> 8) |
+ (uint64_t)((x & (uint64_t)0x0000ff0000000000ULL) >> 24) |
+ (uint64_t)((x & (uint64_t)0x00ff000000000000ULL) >> 40) |
+ (uint64_t)((x & (uint64_t)0xff00000000000000ULL) >> 56);
+}
+
+#ifdef __LITTLE_ENDIAN__
+#define cpu_to_be16(x) swab16(x)
+#define be16_to_cpu(x) swab16(x)
+#define cpu_to_be32(x) swab32(x)
+#define be32_to_cpu(x) swab32(x)
+#define cpu_to_be64(x) swab64(x)
+#define be64_to_cpu(x) swab64(x)
+#else
+#define cpu_to_be16(x) (x)
+#define be16_to_cpu(x) (x)
+#define cpu_to_be32(x) (x)
+#define be32_to_cpu(x) (x)
+#define cpu_to_be64(x) (x)
+#define be64_to_cpu(x) (x)
+#endif