Skip to content

Commit b01457f

Browse files
naushirpelwell
authored andcommitted
drivers: media: pci: Add Hailo accelerator device drivers
Add version 4.17.1 of the Hailo PCIe device drivers. Sourced from https://github.com/hailo-ai/hailort-drivers/ Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
1 parent 573f8fd commit b01457f

39 files changed

+6849
-1
lines changed

arch/arm/configs/bcm2711_defconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,8 @@ CONFIG_VIDEO_EM28XX=m
923923
CONFIG_VIDEO_EM28XX_V4L2=m
924924
CONFIG_VIDEO_EM28XX_ALSA=m
925925
CONFIG_VIDEO_EM28XX_DVB=m
926+
CONFIG_MEDIA_PCI_SUPPORT=y
927+
CONFIG_MEDIA_PCI_HAILO=m
926928
CONFIG_RADIO_SAA7706H=m
927929
CONFIG_RADIO_SHARK=m
928930
CONFIG_RADIO_SHARK2=m

arch/arm64/configs/bcm2711_defconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,8 @@ CONFIG_VIDEO_EM28XX=m
951951
CONFIG_VIDEO_EM28XX_V4L2=m
952952
CONFIG_VIDEO_EM28XX_ALSA=m
953953
CONFIG_VIDEO_EM28XX_DVB=m
954+
CONFIG_MEDIA_PCI_SUPPORT=y
955+
CONFIG_MEDIA_PCI_HAILO=m
954956
CONFIG_RADIO_SAA7706H=m
955957
CONFIG_RADIO_SHARK=m
956958
CONFIG_RADIO_SHARK2=m

arch/arm64/configs/bcm2712_defconfig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,8 @@ CONFIG_VIDEO_EM28XX=m
954954
CONFIG_VIDEO_EM28XX_V4L2=m
955955
CONFIG_VIDEO_EM28XX_ALSA=m
956956
CONFIG_VIDEO_EM28XX_DVB=m
957+
CONFIG_MEDIA_PCI_SUPPORT=y
958+
CONFIG_MEDIA_PCI_HAILO=m
957959
CONFIG_RADIO_SAA7706H=m
958960
CONFIG_RADIO_SHARK=m
959961
CONFIG_RADIO_SHARK2=m

drivers/media/pci/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ config VIDEO_PCI_SKELETON
7474
when developing new drivers.
7575

7676
source "drivers/media/pci/intel/Kconfig"
77+
source "drivers/media/pci/hailo/Kconfig"
7778

7879
endif #MEDIA_PCI_SUPPORT
7980
endif #PCI

drivers/media/pci/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ obj-y += ttpci/ \
1717
saa7146/ \
1818
smipcie/ \
1919
netup_unidvb/ \
20-
intel/
20+
intel/ \
21+
hailo/
2122

2223
# Please keep it alphabetically sorted by Kconfig name
2324
# (e. g. LC_ALL=C sort Makefile)

drivers/media/pci/hailo/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
config MEDIA_PCI_HAILO
3+
tristate "Hailo AI accelerator PCIe driver"
4+
depends on PCI
5+
help
6+
Enable build of Hailo AI accelerator PCIe driver.

drivers/media/pci/hailo/Makefile

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# SPDX-License-Identifier: GPL-2.0
2+
3+
COMMON_SRC_DIRECTORY=common
4+
VDMA_SRC_DIRECTORY=vdma
5+
UTILS_SRC_DIRECTORY=utils
6+
7+
obj-$(CONFIG_MEDIA_PCI_HAILO) := hailo_pci.o
8+
9+
hailo_pci-objs += src/pcie.o
10+
hailo_pci-objs += src/fops.o
11+
hailo_pci-objs += src/utils.o
12+
hailo_pci-objs += src/sysfs.o
13+
14+
hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/fw_validation.o
15+
hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/fw_operation.o
16+
hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/pcie_common.o
17+
hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/vdma_common.o
18+
hailo_pci-objs += $(COMMON_SRC_DIRECTORY)/hailo_resource.o
19+
20+
hailo_pci-objs += $(UTILS_SRC_DIRECTORY)/logs.o
21+
22+
hailo_pci-objs += $(VDMA_SRC_DIRECTORY)/vdma.o
23+
hailo_pci-objs += $(VDMA_SRC_DIRECTORY)/memory.o
24+
hailo_pci-objs += $(VDMA_SRC_DIRECTORY)/ioctl.o
25+
26+
ccflags-y += -Werror
27+
ccflags-y += -DHAILO_RASBERRY_PIE
28+
ccflags-y += -I$(srctree)/$(src)
29+
ccflags-y += -I$(srctree)/$(src)/include
30+
ccflags-y += -I$(srctree)/$(src)/common
31+
32+
clean-files := $(hailo_pci-objs)
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/**
3+
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
4+
**/
5+
6+
#include "fw_operation.h"
7+
8+
#include <linux/errno.h>
9+
#include <linux/types.h>
10+
#include <linux/kernel.h>
11+
#include <linux/bug.h>
12+
13+
typedef struct {
14+
u32 host_offset;
15+
u32 chip_offset;
16+
} FW_DEBUG_BUFFER_HEADER_t;
17+
18+
#define DEBUG_BUFFER_DATA_SIZE (DEBUG_BUFFER_TOTAL_SIZE - sizeof(FW_DEBUG_BUFFER_HEADER_t))
19+
20+
int hailo_read_firmware_notification(struct hailo_resource *resource, struct hailo_d2h_notification *notification)
21+
{
22+
hailo_d2h_buffer_details_t d2h_buffer_details = {0, 0};
23+
hailo_resource_read_buffer(resource, 0, sizeof(d2h_buffer_details),
24+
&d2h_buffer_details);
25+
26+
if ((sizeof(notification->buffer) < d2h_buffer_details.buffer_len) || (0 == d2h_buffer_details.is_buffer_in_use)) {
27+
return -EINVAL;
28+
}
29+
30+
notification->buffer_len = d2h_buffer_details.buffer_len;
31+
hailo_resource_read_buffer(resource, sizeof(d2h_buffer_details), notification->buffer_len, notification->buffer);
32+
33+
// Write is_buffer_in_use = false
34+
hailo_resource_write16(resource, 0, 0);
35+
return 0;
36+
}
37+
38+
static inline size_t calculate_log_ready_to_read(FW_DEBUG_BUFFER_HEADER_t *header)
39+
{
40+
size_t ready_to_read = 0;
41+
size_t host_offset = header->host_offset;
42+
size_t chip_offset = header->chip_offset;
43+
44+
if (chip_offset >= host_offset) {
45+
ready_to_read = chip_offset - host_offset;
46+
} else {
47+
ready_to_read = DEBUG_BUFFER_DATA_SIZE - (host_offset - chip_offset);
48+
}
49+
50+
return ready_to_read;
51+
}
52+
53+
long hailo_read_firmware_log(struct hailo_resource *fw_logger_resource, struct hailo_read_log_params *params)
54+
{
55+
FW_DEBUG_BUFFER_HEADER_t debug_buffer_header = {0};
56+
size_t read_offset = 0;
57+
size_t ready_to_read = 0;
58+
size_t size_to_read = 0;
59+
uintptr_t user_buffer = (uintptr_t)params->buffer;
60+
61+
if (params->buffer_size > ARRAY_SIZE(params->buffer)) {
62+
return -EINVAL;
63+
}
64+
65+
hailo_resource_read_buffer(fw_logger_resource, 0, sizeof(debug_buffer_header),
66+
&debug_buffer_header);
67+
68+
/* Point to the start of the data buffer. */
69+
ready_to_read = calculate_log_ready_to_read(&debug_buffer_header);
70+
if (0 == ready_to_read) {
71+
params->read_bytes = 0;
72+
return 0;
73+
}
74+
/* If ready to read is bigger than the buffer size, read only buffer size bytes. */
75+
ready_to_read = min(ready_to_read, params->buffer_size);
76+
77+
/* Point to the data that is read to be read by the host. */
78+
read_offset = sizeof(debug_buffer_header) + debug_buffer_header.host_offset;
79+
/* Check if the offset should cycle back to beginning. */
80+
if (DEBUG_BUFFER_DATA_SIZE <= debug_buffer_header.host_offset + ready_to_read) {
81+
size_to_read = DEBUG_BUFFER_DATA_SIZE - debug_buffer_header.host_offset;
82+
hailo_resource_read_buffer(fw_logger_resource, read_offset, size_to_read, (void*)user_buffer);
83+
84+
user_buffer += size_to_read;
85+
size_to_read = ready_to_read - size_to_read;
86+
/* Point back to the beginning of the data buffer. */
87+
read_offset -= debug_buffer_header.host_offset;
88+
}
89+
else {
90+
size_to_read = ready_to_read;
91+
}
92+
93+
/* size_to_read may become 0 if the read reached DEBUG_BUFFER_DATA_SIZE exactly */
94+
hailo_resource_read_buffer(fw_logger_resource, read_offset, size_to_read, (void*)user_buffer);
95+
96+
/* Change current_offset to represent the new host offset. */
97+
read_offset += size_to_read;
98+
hailo_resource_write32(fw_logger_resource, offsetof(FW_DEBUG_BUFFER_HEADER_t, host_offset),
99+
(u32)(read_offset - sizeof(debug_buffer_header)));
100+
101+
params->read_bytes = ready_to_read;
102+
return 0;
103+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/**
3+
* Copyright (c) 2022 Hailo Technologies Ltd. All rights reserved.
4+
**/
5+
6+
#ifndef _HAILO_COMMON_FIRMWARE_OPERATION_H_
7+
#define _HAILO_COMMON_FIRMWARE_OPERATION_H_
8+
9+
#include "hailo_resource.h"
10+
11+
#define DEBUG_BUFFER_TOTAL_SIZE (4*1024)
12+
13+
#ifdef __cplusplus
14+
extern "C" {
15+
#endif
16+
17+
int hailo_read_firmware_notification(struct hailo_resource *resource, struct hailo_d2h_notification *notification);
18+
19+
long hailo_read_firmware_log(struct hailo_resource *fw_logger_resource, struct hailo_read_log_params *params);
20+
21+
#ifdef __cplusplus
22+
}
23+
#endif
24+
25+
#endif /* _HAILO_COMMON_FIRMWARE_OPERATION_H_ */
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/**
3+
* Copyright (c) 2019-2022 Hailo Technologies Ltd. All rights reserved.
4+
**/
5+
6+
#include "fw_validation.h"
7+
#include <linux/errno.h>
8+
#include <linux/types.h>
9+
10+
11+
12+
/* when reading the firmware we don't want to read past the firmware_size,
13+
so we have a consumed_firmware_offset that is updated _before_ accessing data at that offset
14+
of firmware_base_address */
15+
#define CONSUME_FIRMWARE(__size, __err) do { \
16+
consumed_firmware_offset += (u32) (__size); \
17+
if ((firmware_size < (__size)) || (firmware_size < consumed_firmware_offset)) { \
18+
err = __err; \
19+
goto exit; \
20+
} \
21+
} while(0)
22+
23+
int FW_VALIDATION__validate_fw_header(uintptr_t firmware_base_address,
24+
size_t firmware_size, u32 max_code_size, u32 *outer_consumed_firmware_offset,
25+
firmware_header_t **out_firmware_header, enum hailo_board_type board_type)
26+
{
27+
int err = -EINVAL;
28+
firmware_header_t *firmware_header = NULL;
29+
u32 consumed_firmware_offset = *outer_consumed_firmware_offset;
30+
u32 expected_firmware_magic = 0;
31+
32+
firmware_header = (firmware_header_t *) (firmware_base_address + consumed_firmware_offset);
33+
CONSUME_FIRMWARE(sizeof(firmware_header_t), -EINVAL);
34+
35+
switch (board_type) {
36+
case HAILO_BOARD_TYPE_HAILO8:
37+
expected_firmware_magic = FIRMWARE_HEADER_MAGIC_HAILO8;
38+
break;
39+
case HAILO_BOARD_TYPE_HAILO15:
40+
expected_firmware_magic = FIRMWARE_HEADER_MAGIC_HAILO15;
41+
break;
42+
case HAILO_BOARD_TYPE_PLUTO:
43+
expected_firmware_magic = FIRMWARE_HEADER_MAGIC_PLUTO;
44+
break;
45+
default:
46+
err = -EINVAL;
47+
goto exit;
48+
}
49+
50+
if (expected_firmware_magic != firmware_header->magic) {
51+
err = -EINVAL;
52+
goto exit;
53+
}
54+
55+
/* Validate that the firmware header version is supported */
56+
switch(firmware_header->header_version) {
57+
case FIRMWARE_HEADER_VERSION_INITIAL:
58+
break;
59+
default:
60+
err = -EINVAL;
61+
goto exit;
62+
break;
63+
}
64+
65+
if (MINIMUM_FIRMWARE_CODE_SIZE > firmware_header->code_size) {
66+
err = -EINVAL;
67+
goto exit;
68+
}
69+
70+
if (max_code_size < firmware_header->code_size) {
71+
err = -EINVAL;
72+
goto exit;
73+
}
74+
75+
CONSUME_FIRMWARE(firmware_header->code_size, -EINVAL);
76+
77+
*outer_consumed_firmware_offset = consumed_firmware_offset;
78+
*out_firmware_header = firmware_header;
79+
err = 0;
80+
81+
exit:
82+
return err;
83+
}
84+
85+
int FW_VALIDATION__validate_cert_header(uintptr_t firmware_base_address,
86+
size_t firmware_size, u32 *outer_consumed_firmware_offset, secure_boot_certificate_t **out_firmware_cert)
87+
{
88+
89+
secure_boot_certificate_t *firmware_cert = NULL;
90+
int err = -EINVAL;
91+
u32 consumed_firmware_offset = *outer_consumed_firmware_offset;
92+
93+
firmware_cert = (secure_boot_certificate_t *) (firmware_base_address + consumed_firmware_offset);
94+
CONSUME_FIRMWARE(sizeof(secure_boot_certificate_t), -EINVAL);
95+
96+
if ((MAXIMUM_FIRMWARE_CERT_KEY_SIZE < firmware_cert->key_size) ||
97+
(MAXIMUM_FIRMWARE_CERT_CONTENT_SIZE < firmware_cert->content_size)) {
98+
err = -EINVAL;
99+
goto exit;
100+
}
101+
102+
CONSUME_FIRMWARE(firmware_cert->key_size, -EINVAL);
103+
CONSUME_FIRMWARE(firmware_cert->content_size, -EINVAL);
104+
105+
*outer_consumed_firmware_offset = consumed_firmware_offset;
106+
*out_firmware_cert = firmware_cert;
107+
err = 0;
108+
109+
exit:
110+
return err;
111+
}
112+

0 commit comments

Comments
 (0)