diff options
Diffstat (limited to 'yocto')
25 files changed, 1412 insertions, 38 deletions
diff --git a/yocto/README b/yocto/README index ef99121..6c92a6e 100644 --- a/yocto/README +++ b/yocto/README @@ -7,6 +7,8 @@ https://developer.toradex.com/linux-bsp/os-development/build-yocto/build-a-refer https://developer.toradex.com/linux-bsp/os-development/build-u-boot-and-linux-kernel-from-source-code/build-u-boot/ https://developer.toradex.com/linux-bsp/os-development/build-u-boot-and-linux-kernel-from-source-code/build-linux-kernel-from-source-code/ https://developer.toradex.com/linux-bsp/os-development/build-u-boot-and-linux-kernel-from-source-code/build-device-tree-overlays-from-source-code/ +https://developer.toradex.com/linux-bsp/os-development/build-yocto/custom-meta-layers-recipes-and-images-in-yocto-project-hello-world-examples/ +https://developer.toradex.com/linux-bsp/os-development/build-yocto/device-tree-overlays-linux - install dependencies: # dependencies for yocto: @@ -18,7 +20,7 @@ apt-get install bc build-essential git libncurses5-dev lzop perl libssl-dev biso apt-get install u-boot-tools # dependencies for kernel: - apt-get install bc build-essential git libncurses5-dev lzop perl libssl-dev bison flex +apt-get install bc build-essential git libncurses5-dev lzop perl libssl-dev bison flex apt-get install u-boot-tools locale-gen en_US.UTF-8 @@ -43,12 +45,9 @@ curl https://commondatastorage.googleapis.com/git-repo-downloads/repo > bin/repo chmod 755 bin/repo - install the ARM GCC toolchain: -mkdir arm -cd arm wget https://developer.arm.com/-/media/Files/downloads/gnu/14.2.rel1/binrel/arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz tar xvf arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz ln -s arm-gnu-toolchain-14.2.rel1-x86_64-aarch64-none-linux-gnu gcc-linaro-aarch64 -cd .. - install device tree compiler tool: git clone https://git.kernel.org/pub/scm/utils/dtc/dtc.git -b v1.7.2 @@ -76,11 +75,12 @@ yocto image - clone meta-information mkdir oe-core cd oe-core -# branch: repo init -u git://git.toradex.com/toradex-manifest.git -b scarthgap-7.x.y -m tdxref/default.xml +# branch: +repo init -u git://git.toradex.com/toradex-manifest.git -b scarthgap-7.x.y -m tdxref/default.xml # specific tag: -repo init -u git://git.toradex.com/toradex-manifest.git -b refs/tags/7.1.0 -m tdxref/default.xml +# repo init -u git://git.toradex.com/toradex-manifest.git -b refs/tags/7.1.0 -m tdxref/default.xml repo sync -# repeat sync until successful +# repeat repo sync until successful - setup environment: . export @@ -90,17 +90,59 @@ vi conf/local.conf ... # set MACHINE: MACHINE ?= "verdin-imx8mp" -# append: +... +# set debian packages +PACKAGE_CLASSES ?= "package_deb" +... +# append ACCEPT_FSL_EULA = "1" -TOOLCHAIN_TARGET_TASK:append = " kernel-devsrc" + +- append mikrophone layer: +vi conf/bblayers.conf +# append to BBLAYERS variable: ... + ${TOPDIR}/../layers/meta-mikrophone \ +" -- build: -bitbake -k tdx-reference-minimal-image -c populate_sdk +# copy yocto/meta-mikrophone to ../layers/ dir from mikroPhone repo + +- build image: +bitbake -k mikrophone-image +bitbake -k mikrophone-image -c populate_sdk + +- install sdk: +deploy/sdk/tdx-xwayland-glibc-x86_64-mikroPhone-Image-armv8a-verdin-imx8mp-toolchain-7.x.y.sh +# install into: /build/tdx-xwayland/7.x.y - machine.conf in: layers/meta-toradex-nxp/conf/machine/verdin-imx8mp.conf -- distro.conf in: layers/meta-toradex-distro/conf/distro/*.conf -- demo images in: layers/meta-toradex-demos/recipes-images/images/*.bb + layers/meta-mikrophone/conf/machine/include/verdin-imx8mp.inc +- mikrophone distro.conf in: layers/meta-mikrophone/conf/distro/mikrophone.conf +- mikrophone images in: layers/meta-mikrophone/recipes-images/images/mikrophone-image.bb + +- deployable tarballs in: build/deploy/images/verdin-imx8mp/ +- deployable sdk in: build/deploy/sdk/ + +- toradex distro.conf in: layers/meta-toradex-distro/conf/distro/*.conf +- toradex demo images in: layers/meta-toradex-demos/recipes-images/images/*.bb + + +upgrade yocto image +------------------- + +- upgrade yocto: +. /build/tools/start.sh +cd /build/oe-core +repo sync + +- build image: +. export +bitbake -k mikrophone-image +bitbake -k mikrophone-image -c populate_sdk + +- to launch TEZI installer: insert sdcard, reboot linux then stop u-boot auto boot and type: +setenv fdtfile imx8mp-verdin-wifi-dev.dtb +boot + u-boot ------ @@ -177,3 +219,46 @@ overlay cd overlays STAGING_KERNEL_DIR=../linux-toradex make mikroPhone-panel_overlay.dtbo cd .. + + +esp32d +------ + +- setup environment: +. /build/tdx-xwayland/7.x.y/environment-setup-armv8a-tdx-linux + +- build: +# copy yocto/esp32d from mikroPhone repo +cd esp32d +make +cd .. + + +debian repository +----------------- + +- install aptly and configure aptly: +apt-get install aptly gnupg1 gpgv1 +aptly # creates config file +vi ~/.aptly.conf +... + "gpgProvider": "internal", +... + "FileSystemPublishEndpoints": { + "mikrophone": { + "rootDir": "/build/repo", + "linkMethod": "copy", + "verifyMethod": "md5" + } + }, +... + +- generate gpg signing key: +gpg1 --gen-key +gpg1 --export --armor # signing key for apt-key add + +- create and publish repository: +aptly repo create -distribution=koshuta -component=main mikrophone +aptly repo add mikrophone /build/oe-core/build/deploy/deb +aptly publish repo mikrophone filesystem:mikrophone: +aptly publish update koshuta filesystem:mikrophone: diff --git a/yocto/esp32d/Makefile b/yocto/esp32d/Makefile new file mode 100644 index 0000000..677d09d --- /dev/null +++ b/yocto/esp32d/Makefile @@ -0,0 +1,15 @@ +#CFLAGS = +LDFLAGS = -pthread -lgpiod +TARGET = esp32d +obj = msgq.o spi.o tun.o + +all: $(TARGET) + +%.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +$(TARGET): $(obj) + $(CC) $(obj) $(LDFLAGS) -o $@ + +clean: + rm -f $(TARGET) *.o diff --git a/yocto/esp32d/msgq.c b/yocto/esp32d/msgq.c new file mode 100644 index 0000000..3039f13 --- /dev/null +++ b/yocto/esp32d/msgq.c @@ -0,0 +1,43 @@ +#include <stdlib.h> +#include <pthread.h> + +#include "msgq.h" + +#define IDX_MASK(IDX, SIZE) ((IDX) & ((SIZE) - 1)) + +int msgq_init(MSGQueue *msgq, unsigned char **array, uint16_t size) { + int rv; + + msgq->idx_r = 0; + msgq->idx_w = 0; + msgq->size = size; + msgq->array = array; + rv = pthread_mutex_init(&msgq->mutex, NULL); + if (rv) { + return MSGQ_ERR; + } + + rv = pthread_cond_init(&msgq->cond, NULL); + if (rv) { + pthread_mutex_destroy(&msgq->mutex); + return MSGQ_ERR; + } + return MSGQ_OK; +} + +int msgq_push(MSGQueue *msgq, unsigned char *buffer) { + if ((uint16_t)(msgq->idx_w - msgq->idx_r) == msgq->size) return MSGQ_ERR_FULL; + + msgq->array[IDX_MASK(msgq->idx_w++, msgq->size)] = buffer; + return MSGQ_OK; +} + +unsigned char *msgq_pop(MSGQueue *msgq) { + if (msgq->idx_r == msgq->idx_w) return NULL; + + return msgq->array[IDX_MASK(msgq->idx_r++, msgq->size)]; +} + +uint16_t msgq_len(MSGQueue *msgq) { + return (uint16_t)(msgq->idx_w - msgq->idx_r); +} diff --git a/yocto/esp32d/msgq.h b/yocto/esp32d/msgq.h new file mode 100644 index 0000000..32b20d0 --- /dev/null +++ b/yocto/esp32d/msgq.h @@ -0,0 +1,22 @@ +#include <stdint.h> + +#define MSGQ_OK 0 +#define MSGQ_ERR -1 + +#define MSGQ_ERR_SIZE -10 +#define MSGQ_ERR_FULL -11 +#define MSGQ_ERR_EMPTY -12 + +typedef struct MSGQueue { + uint16_t idx_r; + uint16_t idx_w; + uint16_t size; + unsigned char **array; + pthread_mutex_t mutex; + pthread_cond_t cond; +} MSGQueue; + +int msgq_init(MSGQueue *msgq, unsigned char **array, uint16_t size); +int msgq_push(MSGQueue *msgq, unsigned char *buffer); +unsigned char *msgq_pop(MSGQueue *msgq); +uint16_t msgq_len(MSGQueue *msgq); diff --git a/yocto/esp32d/spi.c b/yocto/esp32d/spi.c new file mode 100644 index 0000000..db46a63 --- /dev/null +++ b/yocto/esp32d/spi.c @@ -0,0 +1,411 @@ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <assert.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +#include <linux/spi/spidev.h> + +#include <gpiod.h> +#include <pthread.h> + +#include "msgq.h" +#include "tun.h" +#include "spi.h" + +static pthread_t worker_thd; +static pthread_t rtscts_thd; +static pthread_t msg_handler_thd; +static pthread_t tun_handler_thd; +static pthread_mutex_t mutex; +static pthread_cond_t cond; + +static MSGQueue spi_bufq; +static unsigned char *spi_bufq_array[SPI_SIZE_BUFQ]; + +static MSGQueue spi_msgq_in; +static unsigned char *spi_msgq_in_array[SPI_SIZE_MSGQ_IN]; + +static MSGQueue spi_msgq_out; +static unsigned char *spi_msgq_out_array[SPI_SIZE_MSGQ_OUT]; + +static uint32_t spi_speed = SPI_SPEED; +static int spi_fd; +static volatile int spi_cts; + +struct gpiod_line_request *request = NULL; + +static void _spi_wait4cts(void) { + pthread_mutex_lock(&mutex); + while (!spi_cts) { + pthread_cond_wait(&cond, &mutex); + } + spi_cts = 0; + pthread_mutex_unlock(&mutex); +} + +static int _spi_xchg(unsigned char *buffer) { + int rv; + uint16_t len_tx; + uint16_t len_rx; + struct spi_ioc_transfer tr; + + memset(&tr, 0, sizeof(tr)); + tr.tx_buf = (unsigned long)buffer; + tr.rx_buf = (unsigned long)buffer; + tr.speed_hz = spi_speed; + + len_tx = (uint16_t)buffer[1] << 8; + len_tx |= (uint16_t)buffer[2] & 0xFF; + if (len_tx > SPI_MTU) return SPI_ERR; + + if (buffer[0]) { + len_tx += SPI_SIZE_HDR; + // esp32 dma workaraund + if (len_tx < 8) { + len_tx = 8; + } else if (len_tx % 4 != 0) { + len_tx = (len_tx / 4 + 1) * 4; + } + + tr.len = len_tx; + } else { + /* nothing to send, reset esp32 spi transaction */ + tr.len = 1; + + _spi_wait4cts(); + rv = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr); + if (rv < 0) return SPI_ERR_MSG; + + /* receive SPI_SIZE_RECEIVE bytes in first transaction (estimate) */ + len_tx = SPI_SIZE_RECEIVE + SPI_SIZE_HDR; + tr.len = len_tx; + buffer[1] = 0; + buffer[2] = 0; + } + + _spi_wait4cts(); + rv = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr); + if (rv < 0) return SPI_ERR_MSG; + + len_rx = (uint16_t)buffer[1] << 8; + len_rx |= (uint16_t)buffer[2] & 0xFF; + if (len_rx > SPI_MTU) return SPI_ERR; + + len_rx += SPI_SIZE_HDR; + if (len_rx > len_tx) { + tr.tx_buf = (unsigned long)NULL; + tr.rx_buf = (unsigned long)(buffer + len_tx); + + len_tx = len_rx - len_tx; + // esp32 dma workaraund + if (len_tx < 8) { + len_tx = 8; + } else if (len_tx % 4 != 0) { + len_tx = (len_tx / 4 + 1) * 4; + } + + tr.len = len_tx; + + _spi_wait4cts(); + rv = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr); + if (rv < 0) return SPI_ERR_MSG; + } + + return SPI_OK; +} + +static void *worker(void *arg) { + MSGQueue *bufq = &spi_bufq; + MSGQueue *msgq_in = &spi_msgq_in; + MSGQueue *msgq_out = &spi_msgq_out; + int rv; + unsigned char *buffer; + + while (1) { + pthread_mutex_lock(&msgq_out->mutex); + buffer = msgq_pop(msgq_out); + if ((buffer == NULL) && (gpiod_line_request_get_value(request, SPI_GPIO_RTS) == GPIOD_LINE_VALUE_INACTIVE)) { + pthread_mutex_lock(&bufq->mutex); + buffer = msgq_pop(bufq); + pthread_mutex_unlock(&bufq->mutex); + } + if (buffer == NULL) { + pthread_cond_wait(&msgq_out->cond, &msgq_out->mutex); + buffer = msgq_pop(msgq_out); + } + pthread_mutex_unlock(&msgq_out->mutex); + if (buffer) { + rv = _spi_xchg(buffer); + if (rv || (buffer[0] == 0)) { + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 0; + pthread_mutex_lock(&bufq->mutex); + msgq_push(bufq, buffer); + pthread_mutex_unlock(&bufq->mutex); + } else { + pthread_mutex_lock(&msgq_in->mutex); + rv = msgq_push(msgq_in, buffer); + if (rv == MSGQ_OK) pthread_cond_signal(&msgq_in->cond); + pthread_mutex_unlock(&msgq_in->mutex); + + if (rv) { + pthread_mutex_lock(&bufq->mutex); + msgq_push(bufq, buffer); + pthread_mutex_unlock(&bufq->mutex); + } + } + } + } + + return NULL; +} + +static void *rtscts_handler(void *arg) { + MSGQueue *msgq_out = &spi_msgq_out; + struct gpiod_edge_event_buffer *event_buffer; + struct gpiod_edge_event *event; + int rv; + + event_buffer = gpiod_edge_event_buffer_new(1); + + while (1) { + rv = gpiod_line_request_read_edge_events(request, event_buffer, 1); + if (rv != 1) continue; + + event = gpiod_edge_event_buffer_get_event(event_buffer, 0); + switch (gpiod_edge_event_get_line_offset(event)) { + case SPI_GPIO_RTS: { + pthread_mutex_lock(&msgq_out->mutex); + pthread_cond_signal(&msgq_out->cond); + pthread_mutex_unlock(&msgq_out->mutex); + break; + } + + case SPI_GPIO_CTS: { + pthread_mutex_lock(&mutex); + spi_cts = 1; + pthread_cond_signal(&cond); + pthread_mutex_unlock(&mutex); + break; + } + } + } + + gpiod_edge_event_buffer_free(event_buffer); + return NULL; +} + +static void *msg_handler(void *arg) { + MSGQueue *bufq = &spi_bufq; + MSGQueue *msgq_in = &spi_msgq_in; + unsigned char *buffer; + unsigned char mtype; + uint16_t len; + int rv; + + while (1) { + pthread_mutex_lock(&msgq_in->mutex); + buffer = msgq_pop(msgq_in); + if (buffer == NULL) { + pthread_cond_wait(&msgq_in->cond, &msgq_in->mutex); + buffer = msgq_pop(msgq_in); + } + pthread_mutex_unlock(&msgq_in->mutex); + if (buffer) { + mtype = buffer[0]; + len = (uint16_t)buffer[1] << 8; + len |= (uint16_t)buffer[2] & 0xFF; + + switch (mtype) { + case SPI_MTYPE_TUN: + tun_write(buffer + SPI_SIZE_HDR, len); + break; + } + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 0; + pthread_mutex_lock(&bufq->mutex); + msgq_push(bufq, buffer); + pthread_mutex_unlock(&bufq->mutex); + } + } + + return NULL; +} + +static void *tun_handler(void *arg) { + unsigned char *buffer; + ssize_t len; + + while (1) { + buffer = spi_alloc(); + if (buffer == NULL) continue; + + len = tun_read(buffer + SPI_SIZE_HDR, SPI_SIZE_BUF - SPI_SIZE_HDR); + if (len < 0) { + perror("tun read"); + continue; + } + spi_xchg(SPI_MTYPE_TUN, buffer, len); + } + + return NULL; +} + +unsigned char *spi_alloc(void) { + MSGQueue *bufq = &spi_bufq; + unsigned char *buffer; + + pthread_mutex_lock(&bufq->mutex); + buffer = msgq_pop(bufq); + pthread_mutex_unlock(&bufq->mutex); + + return buffer; +} + +void spi_free(unsigned char *buffer) { + MSGQueue *bufq = &spi_bufq; + + buffer[0] = 0; + buffer[1] = 0; + buffer[2] = 0; + pthread_mutex_lock(&bufq->mutex); + msgq_push(bufq, buffer); + pthread_mutex_unlock(&bufq->mutex); +} + +int spi_xchg(unsigned char mtype, unsigned char *buffer, uint16_t len) { + MSGQueue *bufq = &spi_bufq; + MSGQueue *msgq_out = &spi_msgq_out; + int rv; + + buffer[0] = mtype; + buffer[1] = len >> 8; + buffer[2] = len & 0xFF; + + pthread_mutex_lock(&msgq_out->mutex); + rv = msgq_push(msgq_out, buffer); + if (rv == MSGQ_OK) pthread_cond_signal(&msgq_out->cond); + pthread_mutex_unlock(&msgq_out->mutex); + + if (rv) { + pthread_mutex_lock(&bufq->mutex); + msgq_push(bufq, buffer); + pthread_mutex_unlock(&bufq->mutex); + } + + return rv; +} + +int gpio_init(void) { + struct gpiod_chip *chip = NULL; + struct gpiod_line_settings *line_settings = NULL; + struct gpiod_line_config *line_cfg = NULL; + struct gpiod_request_config *req_cfg = NULL; + int rv; + + unsigned int line_offsets[2] = { SPI_GPIO_RTS, SPI_GPIO_CTS }; + + chip = gpiod_chip_open(SPI_GPIO_DEV); + if (chip == NULL) goto gpio_init_fin; + + line_settings = gpiod_line_settings_new(); + if (line_settings == NULL) goto gpio_init_fin; + + gpiod_line_settings_set_direction(line_settings, GPIOD_LINE_DIRECTION_INPUT); + gpiod_line_settings_set_edge_detection(line_settings, GPIOD_LINE_EDGE_FALLING); + gpiod_line_settings_set_bias(line_settings, GPIOD_LINE_BIAS_PULL_UP); + + line_cfg = gpiod_line_config_new(); + if (line_cfg == NULL) goto gpio_init_fin; + + rv = gpiod_line_config_add_line_settings(line_cfg, line_offsets, 2, line_settings); + if (rv) goto gpio_init_fin; + + req_cfg = gpiod_request_config_new(); + if (req_cfg == NULL) goto gpio_init_fin; + + gpiod_request_config_set_consumer(req_cfg, "rts-cts"); + + request = gpiod_chip_request_lines(chip, req_cfg, line_cfg); + +gpio_init_fin: + rv = (request ? SPI_OK : (chip ? SPI_ERR : SPI_ERR_OPEN)); + + if (req_cfg) gpiod_request_config_free(req_cfg); + if (line_cfg) gpiod_line_config_free(line_cfg); + if (line_settings) gpiod_line_settings_free(line_settings); + if (chip) gpiod_chip_close(chip); + + return rv; +} + +int spi_init(void) { + unsigned char *buffer; + int rv, i; + + spi_fd = open(SPI_DEV, O_RDWR); + if (spi_fd < 0) return SPI_ERR_OPEN; + + rv = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed); + if (rv == -1) return SPI_ERR; + + rv = msgq_init(&spi_bufq, spi_bufq_array, SPI_SIZE_BUFQ); + assert(rv == MSGQ_OK); + + rv = msgq_init(&spi_msgq_in, spi_msgq_in_array, SPI_SIZE_MSGQ_IN); + assert(rv == MSGQ_OK); + + rv = msgq_init(&spi_msgq_out, spi_msgq_out_array, SPI_SIZE_MSGQ_OUT); + assert(rv == MSGQ_OK); + + for (i=0; i<SPI_SIZE_BUFQ; i++) { + buffer = malloc(SPI_SIZE_BUF); + assert(buffer); + msgq_push(&spi_bufq, buffer); + } + + rv = pthread_mutex_init(&mutex, NULL); + assert(rv == 0); + + rv = pthread_cond_init(&cond, NULL); + assert(rv == 0); + + /* assret initial contitions */ + pthread_mutex_lock(&mutex); + spi_cts = (gpiod_line_request_get_value(request, SPI_GPIO_CTS) == GPIOD_LINE_VALUE_INACTIVE); + pthread_mutex_unlock(&mutex); + + rv = pthread_create(&worker_thd, NULL, worker, NULL); + assert(rv == 0); + + rv = pthread_create(&rtscts_thd, NULL, rtscts_handler, NULL); + assert(rv == 0); + + rv = pthread_create(&msg_handler_thd, NULL, msg_handler, NULL); + assert(rv == 0); + + rv = pthread_create(&tun_handler_thd, NULL, tun_handler, NULL); + assert(rv == 0); + + return SPI_OK; +} + +int main(int argc, char *argv[]) { + int rv; + + rv = tun_init(SPI_TUN_NAME); + if (rv) printf("TUN INIT ERR\n"); + + rv = gpio_init(); + if (rv) printf("GPIO INIT ERR\n"); + + rv = spi_init(); + if (rv) printf("SPI INIT ERR\n"); + + while (1); +} diff --git a/yocto/esp32d/spi.h b/yocto/esp32d/spi.h new file mode 100644 index 0000000..4d9ff86 --- /dev/null +++ b/yocto/esp32d/spi.h @@ -0,0 +1,31 @@ +#include <stdint.h> + +#define SPI_DEV "/dev/spidev0" +#define SPI_SPEED 10000000 + +#define SPI_TUN_NAME "tun0" + +#define SPI_GPIO_DEV "/dev/gpiochip3" +#define SPI_GPIO_CTS 28 +#define SPI_GPIO_RTS 25 + +#define SPI_MTU 1500 +#define SPI_SIZE_HDR 3 +#define SPI_SIZE_BUF (SPI_MTU + SPI_SIZE_HDR) +#define SPI_SIZE_RECEIVE 16 /* guestimate on number of bytes for transaction initiated by falling RTS */ + +#define SPI_SIZE_BUFQ 64 +#define SPI_SIZE_MSGQ_IN 32 +#define SPI_SIZE_MSGQ_OUT 32 + +#define SPI_MTYPE_TUN 1 + +#define SPI_OK 0 +#define SPI_ERR -1 +#define SPI_ERR_OPEN -10 +#define SPI_ERR_MSG -11 + +unsigned char *spi_alloc(void); +void spi_free(unsigned char *buffer); +int spi_xchg(unsigned char mtype, unsigned char *buffer, uint16_t len); +int spi_init(void);
\ No newline at end of file diff --git a/yocto/esp32d/tun.c b/yocto/esp32d/tun.c new file mode 100644 index 0000000..75043a3 --- /dev/null +++ b/yocto/esp32d/tun.c @@ -0,0 +1,84 @@ +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +#include <linux/if.h> +#include <linux/if_tun.h> + +#include <pthread.h> + +#include "spi.h" +#include "tun.h" + +static pthread_t read_thd; + +static int tun_fd; +static char tun_name[IFNAMSIZ]; + +static int tun_alloc(char *dev, int flags) { + struct ifreq ifr; + int fd, err; + char *clonedev = "/dev/net/tun"; + + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + + fd = open(clonedev, O_RDWR); + if (fd < 0) { + return fd; + } + + memset(&ifr, 0, sizeof(ifr)); + ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ + + if (*dev) { + /* if a device name was specified, put it in the structure; otherwise, + * the kernel will try to allocate the "next" device of the + * specified type */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + /* try to create the device */ + err = ioctl(fd, TUNSETIFF, (void *) &ifr); + if (err < 0) { + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * interface to the variable "dev", so the caller can know + * it. Note that the caller MUST reserve space in *dev (see calling + * code below) */ + strcpy(dev, ifr.ifr_name); + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} + +ssize_t tun_read(unsigned char *buffer, size_t buf_size) { + return read(tun_fd, buffer, buf_size); +} + +ssize_t tun_write(unsigned char *buffer, size_t buf_len) { + return write(tun_fd, buffer, buf_len); +} + +int tun_init(char *name) { + int rv; + + if (strlen(name) >= sizeof(tun_name) - 1) return -1; + strcpy(tun_name, name); + + tun_fd = tun_alloc(tun_name, IFF_TUN | IFF_NO_PI); + if (tun_fd < 0) return -1; + + return 0; +} diff --git a/yocto/esp32d/tun.h b/yocto/esp32d/tun.h new file mode 100644 index 0000000..793a4c9 --- /dev/null +++ b/yocto/esp32d/tun.h @@ -0,0 +1,5 @@ +#include <sys/types.h> + +ssize_t tun_read(unsigned char *buffer, size_t buf_size); +ssize_t tun_write(unsigned char *buffer, size_t buf_len); +int tun_init(char *name);
\ No newline at end of file diff --git a/yocto/meta-mikrophone/conf/distro/mikrophone.conf b/yocto/meta-mikrophone/conf/distro/mikrophone.conf new file mode 100644 index 0000000..efeba6e --- /dev/null +++ b/yocto/meta-mikrophone/conf/distro/mikrophone.conf @@ -0,0 +1,20 @@ +# Toradex Distro for Wayland with XWayland. +# Using the downstream kernel flavour. + +require conf/distro/include/tdx-base.inc + +DISTRO = "mikrophone" +DISTRO_NAME = "mikroPhone distribution" +DISTRO_FLAVOUR = "" + +IMX_DEFAULT_BSP = "nxp" + +# we use graphics, so set opengl +DISTRO_FEATURES:append = " opengl" + +DISTRO_FEATURES:append = " wayland x11" + +# lxqt requires this +DISTRO_FEATURES:append = " polkit" +TASK_BASIC_SSHDAEMON = "openssh-sshd openssh-sftp openssh-sftp-server" +IMAGE_FEATURES:append = " ssh-server-openssh" diff --git a/yocto/meta-mikrophone/conf/layer.conf b/yocto/meta-mikrophone/conf/layer.conf new file mode 100644 index 0000000..8abd100 --- /dev/null +++ b/yocto/meta-mikrophone/conf/layer.conf @@ -0,0 +1,13 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH .= ":${LAYERDIR}" + +# We have recipes-* directories, add to BBFILES +BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +BBFILE_COLLECTIONS += "meta-mikrophone" +BBFILE_PATTERN_meta-mikrophone = "^${LAYERDIR}/" +BBFILE_PRIORITY_meta-mikrophone = "6" + +LAYERDEPENDS_meta-mikrophone = "core" +LAYERSERIES_COMPAT_meta-mikrophone = "scarthgap" diff --git a/yocto/meta-mikrophone/conf/machine/._verdin-imx8mp-mikrophone.conf b/yocto/meta-mikrophone/conf/machine/._verdin-imx8mp-mikrophone.conf Binary files differnew file mode 100644 index 0000000..fe7655c --- /dev/null +++ b/yocto/meta-mikrophone/conf/machine/._verdin-imx8mp-mikrophone.conf diff --git a/yocto/meta-mikrophone/conf/machine/include/verdin-imx8mp.inc b/yocto/meta-mikrophone/conf/machine/include/verdin-imx8mp.inc new file mode 100644 index 0000000..b64f4f1 --- /dev/null +++ b/yocto/meta-mikrophone/conf/machine/include/verdin-imx8mp.inc @@ -0,0 +1,14 @@ +# needed in recent builds for wifi and bt +MACHINE_FIRMWARE:append = " firmware-nxp-wifi-nxp8997-sdio" + +# our device tree +KERNEL_DEVICETREE:append = " \ + ${KERNEL_DTB_PREFIX}imx8mp-verdin-wifi-mikrophone.dtb \ + ${KERNEL_DTB_PREFIX}imx8mp-verdin-nonwifi-mikrophone.dtb \ +" +# DTB for u-boot only +UBOOT_DTB_NAME = "imx8mp-verdin-wifi-mikrophone.dtb" + +# for SDK only +TOOLCHAIN_TARGET_TASK:append = " kernel-devsrc" +TOOLCHAIN_TARGET_TASK:remove = "target-sdk-provides-dummy" diff --git a/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-mikrophone.dtsi b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-mikrophone.dtsi new file mode 100644 index 0000000..6ce6362 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-mikrophone.dtsi @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +/* Verdin SPI_1 */ +&ecspi1 { + status = "okay"; +}; + +&eqos { + status = "disable"; +}; + +&fec { + status = "disable"; +}; + +&flexcan1 { + status = "disable"; +}; + +&flexcan2 { + status = "disable"; +}; + +/* Verdin QSPI_1 */ +&flexspi { + status = "disable"; +}; + +/* Verdin I2C_2_DSI */ +&i2c2 { + status = "disabled"; +}; + +&i2c3 { + status = "disabled"; +}; + +/* Verdin I2C_1 */ +&i2c4 { + status = "okay"; +}; + +/* Verdin PCIE_1 */ +&pcie { + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +/* Verdin PWM_1 */ +&pwm1 { + status = "okay"; +}; + +/* Verdin PWM_2 */ +&pwm2 { + status = "disabled"; +}; + +/* Verdin PWM_3_DSI */ +&pwm3 { + status = "disabled"; +}; + +®_usdhc2_vmmc { + vin-supply = <®_3p3v>; +}; + +/* Verdin UART_1 */ +&uart1 { + status = "disabled"; +}; + +/* Verdin UART_2 */ +&uart2 { + status = "disabled"; +}; + +/* Verdin UART_3, used as the Linux Console */ +&uart3 { + status = "okay"; +}; + +/* Verdin USB_1 */ +&usb3_0 { + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +/* Verdin USB_2 */ +&usb3_1 { + fsl,permanently-attached; + status = "okay"; +}; + +&usb3_phy1 { + status = "okay"; +}; + +/* Verdin SDCard */ +&usdhc2 { + status = "okay"; +}; diff --git a/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-nonwifi-mikrophone.dts b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-nonwifi-mikrophone.dts new file mode 100644 index 0000000..e8ba274 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-nonwifi-mikrophone.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +/dts-v1/; + +#include "imx8mp-verdin.dtsi" +#include "imx8mp-verdin-nonwifi.dtsi" +#include "imx8mp-verdin-mikrophone.dtsi" + +/ { + model = "Toradex Verdin iMX8M Plus on mikroPhone"; + compatible = "toradex,verdin-imx8mp-nonwifi-mikrophone", + "toradex,verdin-imx8mp-nonwifi", + "toradex,verdin-imx8mp", + "fsl,imx8mp"; +}; diff --git a/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-wifi-mikrophone.dts b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-wifi-mikrophone.dts new file mode 100644 index 0000000..3b04ab5 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex/imx8mp-verdin-wifi-mikrophone.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +/dts-v1/; + +#include "imx8mp-verdin.dtsi" +#include "imx8mp-verdin-wifi.dtsi" +#include "imx8mp-verdin-mikrophone.dtsi" + +/ { + model = "Toradex Verdin iMX8M Plus WB on mikroPhone"; + compatible = "toradex,verdin-imx8mp-wifi-mikrophone", + "toradex,verdin-imx8mp-wifi", + "toradex,verdin-imx8mp", + "fsl,imx8mp"; +}; diff --git a/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex_%.bbappend b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex_%.bbappend new file mode 100644 index 0000000..0a6f719 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-bsp/u-boot/u-boot-toradex_%.bbappend @@ -0,0 +1,19 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/u-boot-toradex:" + +SRC_URI += "\ + file://imx8mp-verdin-mikrophone.dtsi \ + file://imx8mp-verdin-wifi-mikrophone.dts \ + file://imx8mp-verdin-nonwifi-mikrophone.dts \ + " + +DTS_SRCDIR = "dts/upstream/src/arm64/freescale" + +do_configure:append() { + cp ${WORKDIR}/imx8mp-verdin-mikrophone.dtsi ${S}/${DTS_SRCDIR} + cp ${WORKDIR}/imx8mp-verdin-wifi-mikrophone.dts ${S}/${DTS_SRCDIR} + cp ${WORKDIR}/imx8mp-verdin-nonwifi-mikrophone.dts ${S}/${DTS_SRCDIR} + # Remove exisiting fdtfile, if there is one + sed -i '/"fdtfile=.*\\0" \\/d' ${S}/include/configs/verdin-imx8mp.h + # Add new fdtfile + sed -i 's/\("fdt_board=.*\\0" \\\)/\0\n\t"fdtfile=imx8mp-verdin-wifi-mikrophone.dtb\\0" \\/' ${S}/include/configs/verdin-imx8mp.h +}
\ No newline at end of file diff --git a/yocto/meta-mikrophone/recipes-images/images/mikrophone-image.bb b/yocto/meta-mikrophone/recipes-images/images/mikrophone-image.bb new file mode 100644 index 0000000..4a88221 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-images/images/mikrophone-image.bb @@ -0,0 +1,74 @@ +inherit core-image + +SUMMARY = "mikroPhone image" +DESCRIPTION = "mikroPhone image" + +LICENSE = "MIT" + +#Prefix to the resulting deployable tarball name +export IMAGE_BASENAME = "mikroPhone-Image" +MACHINE_NAME ?= "${MACHINE}" +IMAGE_NAME = "${MACHINE_NAME}_${IMAGE_BASENAME}" + +IMAGE_FEATURES += " \ + ${@bb.utils.contains('DISTRO_FEATURES', 'wayland', 'weston', '', d)} \ +" + +# Copy Licenses to image /usr/share/common-license +COPY_LIC_MANIFEST ?= "1" +COPY_LIC_DIRS ?= "1" + +add_rootfs_version () { + printf "${DISTRO_NAME} ${DISTRO_VERSION} (${DISTRO_CODENAME}) \\\n \\\l\n" > ${IMAGE_ROOTFS}/etc/issue + printf "${DISTRO_NAME} ${DISTRO_VERSION} (${DISTRO_CODENAME}) %%h\n" > ${IMAGE_ROOTFS}/etc/issue.net + printf "${IMAGE_NAME}\n\n" >> ${IMAGE_ROOTFS}/etc/issue + printf "${IMAGE_NAME}\n\n" >> ${IMAGE_ROOTFS}/etc/issue.net +} + +add_home_root_symlink () { + ln -sf ${ROOT_HOME} ${IMAGE_ROOTFS}/home/root +} + +# add the rootfs version to the welcome banner +ROOTFS_POSTPROCESS_COMMAND += " add_rootfs_version; add_home_root_symlink;" + +IMAGE_LINGUAS = "en-us" +#IMAGE_LINGUAS = "de-de fr-fr en-gb en-us pt-br es-es kn-in ml-in ta-in" + +CONMANPKGS ?= "connman connman-plugin-loopback connman-plugin-ethernet connman-plugin-wifi connman-client" + +IMAGE_INSTALL += " \ + packagegroup-boot \ + packagegroup-basic \ + packagegroup-base-tdx-cli \ + packagegroup-machine-tdx-cli \ + packagegroup-wifi-tdx-cli \ + packagegroup-wifi-fw-tdx-cli \ + udev-extraconf \ + ${CONMANPKGS} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', \ + 'timestamp-service systemd-analyze', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'x11 wayland', \ + 'weston-xwayland xterm', '', d)} \ + ${@bb.utils.contains('MACHINE_FEATURES', 'tpm2', \ + 'packagegroup-tpm2-tdx-cli', '', d)} \ + \ + packagegroup-tdx-cli \ + packagegroup-tdx-graphical \ + packagegroup-fsl-isp \ + \ + bash \ + coreutils \ + less \ + makedevs \ + mime-support \ + net-tools \ + util-linux \ + v4l-utils \ + \ + gpicview \ + media-files \ + \ + gnupg \ + weston weston-init wayland-terminal-launch \ +" diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/device-tree-overlays/mikroPhone-panel_overlay.dts b/yocto/meta-mikrophone/recipes-kernel/linux/device-tree-overlays/mikroPhone-panel_overlay.dts new file mode 100644 index 0000000..bee2682 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/device-tree-overlays/mikroPhone-panel_overlay.dts @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +// adapted from: https://git.toradex.com/cgit/device-tree-overlays.git/tree/overlays/verdin-imx8mp_panel-cap-touch-10inch-lvds_overlay.dts?h=toradex_6.6-2.2.x-imx +// Verdin iMX8M Plus single-channel LVDS + +/dts-v1/; +/plugin/; + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/pwm/pwm.h> +#include "freescale/imx8mp-pinfunc.h" + +/ { + compatible = "toradex,verdin-imx8mp"; +}; + +&{/} { + backlight_lvds_native: backlight-lvds-native { + compatible = "pwm-backlight"; + pinctrl-names = "default"; + brightness-levels = <0 45 63 88 119 158 203 255>; + default-brightness-level = <4>; + /* Verdin PWM_1 (SODIMM 15) */ + pwms = <&pwm1 0 6666667>; + }; + + panel-lvds-native { + compatible = "panel-lvds"; + backlight = <&backlight_lvds_native>; + data-mapping = "vesa-24"; + height-mm = <110>; + width-mm = <62>; + + panel-timing { + clock-frequency = <36000000>; + hactive = <480>; + hfront-porch = <23 60 71>; + hsync-len = <15 40 47>; + hback-porch = <23 60 71>; + + vactive = <854>; + vfront-porch = <5 7 10>; + vsync-len = <6 9 12>; + vback-porch = <5 7 10>; + + hsync-active = <0>; + vsync-active = <0>; + de-active = <0>; + pixelclk-active = <1>; /* positive edge */ + }; + + port { + panel_lvds_native_in: endpoint { + remote-endpoint = <&lvds_out>; + }; + }; + }; +}; + +/* Verdin I2C_1 */ +&i2c4 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + gt911@5d { + compatible = "goodix,gt911"; + reg = <0x5d>; + pinctrl-names = "default"; + pinctrl-0 = <&gpio1>; + /* Verdin GPIO_3 (SODIMM 210) */ + interrupt-parent = <&gpio1>; + interrupts = <5 IRQ_TYPE_EDGE_FALLING>; + /* Verdin GPIO_4 (SODIMM 212) */ + reset-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; + status = "okay"; + }; +}; + +&lcdif2 { + status = "okay"; +}; + +&ldb { + status = "okay"; + + lvds-channel@0 { + #address-cells = <1>; + #size-cells = <0>; + fsl,data-mapping = "spwg"; + fsl,data-width = <24>; + status = "okay"; + + port@1 { + reg = <1>; + + lvds_out: endpoint { + remote-endpoint = <&panel_lvds_native_in>; + }; + }; + }; +}; + +&ldb_phy { + status = "okay"; +}; diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/device-tree-overlays_git.bbappend b/yocto/meta-mikrophone/recipes-kernel/linux/device-tree-overlays_git.bbappend new file mode 100644 index 0000000..cae7974 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/device-tree-overlays_git.bbappend @@ -0,0 +1,15 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/device-tree-overlays:" + +MIKROPHONE_OVERLAYS_BINARY = "verdin-imx8mp_hdmi_overlay.dtbo mikroPhone-panel_overlay.dtbo" + +SRC_URI += " \ + file://mikroPhone-panel_overlay.dts \ +" + +TEZI_EXTERNAL_KERNEL_DEVICETREE = "${MIKROPHONE_OVERLAYS_BINARY}" + +TEZI_EXTERNAL_KERNEL_DEVICETREE_BOOT = "${MIKROPHONE_OVERLAYS_BINARY}" + +do_collect_overlays:prepend() { + cp ${WORKDIR}/mikroPhone-panel_overlay.dts ${S} +}
\ No newline at end of file diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex%.bbappend b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex%.bbappend new file mode 100644 index 0000000..a706b06 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex%.bbappend @@ -0,0 +1,20 @@ +FILESEXTRAPATHS:prepend := "${THISDIR}/linux-toradex:" + +# Prevent the use of in-tree defconfig +# unset KBUILD_DEFCONFIG + +SRC_URI += "\ + file://imx8mp-verdin-mikrophone.dtsi \ + file://imx8mp-verdin-wifi-mikrophone.dts \ + file://imx8mp-verdin-nonwifi-mikrophone.dts \ + file://kernel_lvds_freq.patch \ + " + +# For arm64 bit freescale/NXP devices +DTS_SRCDIR = "arch/arm64/boot/dts/freescale" + +do_configure:append() { + cp ${WORKDIR}/imx8mp-verdin-mikrophone.dtsi ${S}/${DTS_SRCDIR} + cp ${WORKDIR}/imx8mp-verdin-wifi-mikrophone.dts ${S}/${DTS_SRCDIR} + cp ${WORKDIR}/imx8mp-verdin-nonwifi-mikrophone.dts ${S}/${DTS_SRCDIR} +}
\ No newline at end of file diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-mikrophone.dtsi b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-mikrophone.dtsi new file mode 100644 index 0000000..7c23309 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-mikrophone.dtsi @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +/* Verdin HDMI_1 Audio */ +&aud2htx { + status = "okay"; +}; + +/* Verdin SPI_1 */ +&ecspi1 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + spidev@0 { + /* Use compatible "rohm,dh2228fv" to bind spidev driver */ + compatible = "rohm,dh2228fv"; + reg = <0>; + spi-max-frequency = <50000000>; + }; +}; + +&eqos { + status = "disabled"; +}; + +&fec { + status = "disabled"; +}; + +&flexcan1 { + status = "disabled"; +}; + +&flexcan2 { + status = "disabled"; +}; + +/* Verdin QSPI_1 */ +&flexspi { + status = "disabled"; +}; + +&gpio4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ctrl_sleep_moci>; +}; + +/* Verdin I2C_2_DSI */ +&i2c2 { + status = "disabled"; +}; + +/* CAM I2C, disabled for now */ +&i2c3 { + status = "disabled"; +}; + +/* Verdin I2C_1 */ +&i2c4 { + status = "okay"; +}; + +/* Verdin PCIE_1 */ +&pcie { + status = "okay"; +}; + +&pcie_phy { + status = "okay"; +}; + +/* Verdin PWM_1 */ +&pwm1 { + status = "okay"; +}; + +/* Verdin PWM_2 */ +&pwm2 { + status = "disabled"; +}; + +/* Verdin PWM_3_DSI */ +&pwm3 { + status = "disabled"; +}; + +®_usdhc2_vmmc { + vin-supply = <®_3p3v>; +}; + +/* Verdin HDMI_1 Audio */ +&sound_hdmi { + status = "okay"; +}; + +/* Verdin UART_1 */ +&uart1 { + status = "disabled"; +}; + +/* Verdin UART_2 */ +&uart2 { + status = "disabled"; +}; + +/* Verdin UART_3, used as the Linux Console */ +&uart3 { + status = "okay"; +}; + +/* Verdin USB_1 */ +&usb3_0 { + status = "okay"; +}; + +&usb3_phy0 { + status = "okay"; +}; + +/* Verdin USB_2 */ +&usb3_1 { + // fsl,permanently-attached; + status = "okay"; +}; + +&usb3_phy1 { + status = "okay"; +}; + +/* Verdin SDCard */ +&usdhc2 { + status = "okay"; +}; + +/* Video and graphics */ +&vpu_g1 { + status = "okay"; +}; + +&vpu_g2 { + status = "okay"; +}; + +&vpu_vc8000e { + status = "okay"; +}; + +&vpu_v4l2 { + status = "okay"; +}; + +&gpu_2d { + status = "okay"; +}; + +&gpu_3d { + status = "okay"; +}; + +&ml_vipsi { + status = "okay"; +}; + +&mix_gpu_ml { + status = "okay"; +}; diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-nonwifi-mikrophone.dts b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-nonwifi-mikrophone.dts new file mode 100644 index 0000000..91c08a7 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-nonwifi-mikrophone.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +/dts-v1/; + +#include "imx8mp-verdin.dtsi" +#include "imx8mp-verdin-nonwifi.dtsi" +#include "imx8mp-verdin-mikrophone.dtsi" + +/ { + model = "Toradex Verdin iMX8M Plus on mikroPhone"; + compatible = "toradex,verdin-imx8mp-nonwifi-mikrophone", + "toradex,verdin-imx8mp-wifi", + "toradex,verdin-imx8mp", + "fsl,imx8mp"; +}; diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-wifi-mikrophone.dts b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-wifi-mikrophone.dts new file mode 100644 index 0000000..35792e1 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/imx8mp-verdin-wifi-mikrophone.dts @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT +/* + * Copyright 2025 Uros Majstorovic + */ + +/dts-v1/; + +#include "imx8mp-verdin.dtsi" +#include "imx8mp-verdin-wifi.dtsi" +#include "imx8mp-verdin-mikrophone.dtsi" + +/ { + model = "Toradex Verdin iMX8M Plus WB on mikroPhone"; + compatible = "toradex,verdin-imx8mp-wifi-mikrophone", + "toradex,verdin-imx8mp-wifi", + "toradex,verdin-imx8mp", + "fsl,imx8mp"; +}; diff --git a/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/kernel_lvds_freq.patch b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/kernel_lvds_freq.patch new file mode 100644 index 0000000..9955bc4 --- /dev/null +++ b/yocto/meta-mikrophone/recipes-kernel/linux/linux-toradex/kernel_lvds_freq.patch @@ -0,0 +1,62 @@ +diff --git a/arch/arm64/boot/dts/freescale/imx8mp.dtsi b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +index 55adf1bf45d9..c875474e6c45 100644 +--- a/arch/arm64/boot/dts/freescale/imx8mp.dtsi ++++ b/arch/arm64/boot/dts/freescale/imx8mp.dtsi +@@ -752,7 +752,7 @@ clk: clock-controller@30380000 { + <800000000>, + <393216000>, + <361267200>, +- <1039500000>; ++ <252000000>; + }; + + src: reset-controller@30390000 { +diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c +index 6c17786ecb9f..8c9840f08c0e 100644 +--- a/drivers/clk/imx/clk-pll14xx.c ++++ b/drivers/clk/imx/clk-pll14xx.c +@@ -75,6 +75,7 @@ static const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = { + PLL_1443X_RATE(49152000U, 393, 3, 6, 0x374c), + PLL_1443X_RATE(45158400U, 241, 2, 6, 0xd845), + PLL_1443X_RATE(40960000U, 109, 1, 6, 0x3a07), ++ PLL_1443X_RATE(252000000U, 84, 2, 2, 0), + }; + + struct imx_pll14xx_clk imx_1443x_pll = { +diff --git a/drivers/gpu/drm/imx/imx8mp-ldb.c b/drivers/gpu/drm/imx/imx8mp-ldb.c +index e3f5c5e6e842..55dbafa863cf 100644 +--- a/drivers/gpu/drm/imx/imx8mp-ldb.c ++++ b/drivers/gpu/drm/imx/imx8mp-ldb.c +@@ -186,15 +186,6 @@ imx8mp_ldb_encoder_atomic_check(struct drm_encoder *encoder, + return -EINVAL; + } + +- /* +- * Due to limited video PLL frequency points on i.MX8mp, +- * we do mode fixup here in case any mode is unsupported. +- */ +- if (ldb->dual) +- mode->clock = mode->clock > 100000 ? 148500 : 74250; +- else +- mode->clock = 74250; +- + return 0; + } + +@@ -212,16 +203,6 @@ imx8mp_ldb_encoder_mode_valid(struct drm_encoder *encoder, + if (ldb_ch->panel) + return MODE_OK; + +- /* +- * Due to limited video PLL frequency points on i.MX8mp, +- * we do mode valid check here. +- */ +- if (ldb->dual && mode->clock != 74250 && mode->clock != 148500) +- return MODE_NOCLOCK; +- +- if (!ldb->dual && mode->clock != 74250) +- return MODE_NOCLOCK; +- + return MODE_OK; + } + diff --git a/yocto/overlays/mikroPhone-panel_overlay.dts b/yocto/overlays/mikroPhone-panel_overlay.dts index 0bc14b3..bee2682 100644 --- a/yocto/overlays/mikroPhone-panel_overlay.dts +++ b/yocto/overlays/mikroPhone-panel_overlay.dts @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later OR MIT /* - * Copyright 2023 Toradex + * Copyright 2025 Uros Majstorovic */ // adapted from: https://git.toradex.com/cgit/device-tree-overlays.git/tree/overlays/verdin-imx8mp_panel-cap-touch-10inch-lvds_overlay.dts?h=toradex_6.6-2.2.x-imx @@ -32,8 +32,8 @@ compatible = "panel-lvds"; backlight = <&backlight_lvds_native>; data-mapping = "vesa-24"; - height-mm = <136>; - width-mm = <217>; + height-mm = <110>; + width-mm = <62>; panel-timing { clock-frequency = <36000000>; @@ -61,16 +61,8 @@ }; }; -&gpu_2d { - status = "okay"; -}; - -&gpu_3d { - status = "okay"; -}; - /* Verdin I2C_1 */ -&i2c1 { +&i2c4 { #address-cells = <1>; #size-cells = <0>; status = "okay"; @@ -116,16 +108,3 @@ &ldb_phy { status = "okay"; }; - -&mix_gpu_ml { - status = "okay"; -}; - -&ml_vipsi { - status = "okay"; -}; - -/* Verdin PWM_2 */ -&pwm1 { - status = "okay"; -}; |