aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/pru/Makefile4
-rw-r--r--src/pru/gpio.c2
-rw-r--r--src/pru/intc_map_0.h62
-rw-r--r--src/pru/internal.h6
-rw-r--r--src/pru/main.c31
-rw-r--r--src/pru/pru0.c135
-rw-r--r--src/pru/resource_table.h91
7 files changed, 191 insertions, 140 deletions
diff --git a/src/pru/Makefile b/src/pru/Makefile
index 5fea9e17..c304219e 100644
--- a/src/pru/Makefile
+++ b/src/pru/Makefile
@@ -27,7 +27,11 @@ target-y += $(OUT)pru0.elf $(OUT)pru1.elf
$(OUT)pru0.elf: $(patsubst %.c, $(OUT)src/%.o,$(pru0-y))
@echo " Linking $@"
$(Q)$(CC) $(CFLAGS_klipper.elf) $^ -o $(OUT)pru0.o
+ # dumping info about INTC
+ $(Q)$(OBJCOPY) --dump-section '.pru_irq_map'=$(OUT)pru0.pru_irq_map.bin $(OUT)src/pru/pru0.o $(OUT)pru0.o.discard
$(Q)$(CC) $(CFLAGS_pru0.elf) $(OUT)pru0.o -o $@
+ # in previous step linker did loose info about INTC during optimization, restoring it here (P.S. pru.lds is not helping)
+ $(Q)$(OBJCOPY) --add-section '.pru_irq_map'=$(OUT)pru0.pru_irq_map.bin $@
$(OUT)pru1.elf: $(OUT)klipper.elf
@echo " Linking $@"
diff --git a/src/pru/gpio.c b/src/pru/gpio.c
index 2f77a071..43effa28 100644
--- a/src/pru/gpio.c
+++ b/src/pru/gpio.c
@@ -20,7 +20,7 @@
#define GPIO2BIT(PIN) (1<<((PIN) % 32))
struct gpio_regs {
- uint32_t pad_0[77];
+ uint32_t pad_0[77]; // 77*4=308=134h
volatile uint32_t oe;
volatile uint32_t datain;
volatile uint32_t dataout;
diff --git a/src/pru/intc_map_0.h b/src/pru/intc_map_0.h
new file mode 100644
index 00000000..a8972992
--- /dev/null
+++ b/src/pru/intc_map_0.h
@@ -0,0 +1,62 @@
+#ifndef _INTC_MAP_0_H_
+#define _INTC_MAP_0_H_ __attribute__((used, section(".pru_irq_map")))
+
+/*
+ * ======== PRU INTC Map ========
+ *
+ * Define the INTC mapping for interrupts going to the ICSS / ICSSG:
+ * ICSS Host interrupts 0, 1
+ * ICSSG Host interrupts 0, 1, 10-19
+ *
+ * Note that INTC interrupts going to the ARM Linux host should not be defined
+ * in this file (ICSS/ICSSG Host interrupts 2-9).
+ *
+ * The INTC configuration for interrupts going to the ARM host should be defined
+ * in the device tree node of the client driver, "interrupts" property.
+ * See Documentation/devicetree/bindings/interrupt-controller/ti,pruss-intc.yaml
+ * entry #interrupt-cells for more.
+ *
+ * For example, on ICSSG:
+ *
+ * &client_driver0 {
+ * interrupt-parent = <&icssg0_intc>;
+ * interrupts = <21 2 2>, <22 3 3>;
+ * interrupt-names = "interrupt_name1", "interrupt_name2";
+ * };
+ *
+ */
+
+#include <stddef.h>
+
+/*
+ * .pru_irq_map is used by the RemoteProc driver during initialization. However,
+ * the map is NOT used by the PRU firmware. That means DATA_SECTION and RETAIN
+ * are required to prevent the PRU compiler from optimizing out .pru_irq_map.
+ */
+
+#if !defined(__GNUC__)
+ #pragma DATA_SECTION(my_irq_rsc, ".pru_irq_map")
+ #pragma RETAIN(my_irq_rsc)
+ #define __pru_irq_map
+#else
+ #define __pru_irq_map __attribute__((section(".pru_irq_map"), \
+ unavailable("pru_irq_map is for usage by the host only")))
+#endif
+
+struct pru_irq_rsc my_irq_rsc __pru_irq_map = {
+ 0, /* type = 0 */
+ 4, /* number of system events being mapped */
+ {
+// this item (sysevt=16) is obsolete in Linux 5.10
+// {16, 2, 2}, /* {sysevt, channel, host interrupt} */
+ {17, 0, 0}, /* {sysevt, channel, host interrupt} */
+ {18, 0, 0}, /* {sysevt, channel, host interrupt} */
+ {19, 1, 1}, /* {sysevt, channel, host interrupt} */
+// next item is responsible for timer to function,
+// it should be kept last in Linux 5.10
+// (if it will be first - gpios will not work)
+ {7, 1, 1}, /* {sysevt, channel, host interrupt} */
+ },
+};
+
+#endif /* _INTC_MAP_0_H_ */
diff --git a/src/pru/internal.h b/src/pru/internal.h
index 2aef0da3..f735f80a 100644
--- a/src/pru/internal.h
+++ b/src/pru/internal.h
@@ -15,6 +15,12 @@
#define WAKE_PRU1_IRQ 1
#define WAKE_ARM_IRQ 2
+/* Host-0 Interrupt sets bit 31 in register R31 */
+#define HOST_INT_0 ((uint32_t) 1 << 30)
+
+/* Host-1 Interrupt sets bit 31 in register R31 */
+#define HOST_INT_1 ((uint32_t) 1 << 31)
+
#define R31_IRQ_OFFSET 30
#define R31_WRITE_IRQ_SELECT (1<<5)
diff --git a/src/pru/main.c b/src/pru/main.c
index 27634a12..2127479f 100644
--- a/src/pru/main.c
+++ b/src/pru/main.c
@@ -7,7 +7,7 @@
#include <stdint.h> // uint32_t
#include <pru/io.h> // read_r31
#include <pru_iep.h> // CT_IEP
-#include <pru_intc.h> // CT_INTC
+
#include <rsc_types.h> // resource_table
#include "board/misc.h" // dynmem_start
#include "board/io.h" // readl
@@ -75,7 +75,7 @@ timer_kick(void)
timer_set(timer_read_time() + 50);
CT_IEP.TMR_CMP_STS = 0xff;
__delay_cycles(4);
- CT_INTC.SECR0 = 1 << IEP_EVENT;
+ PRU_INTC.SECR0 = 1 << IEP_EVENT;
}
static uint32_t in_timer_dispatch;
@@ -83,9 +83,9 @@ static uint32_t in_timer_dispatch;
static void
_irq_poll(void)
{
- uint32_t secr0 = CT_INTC.SECR0;
+ uint32_t secr0 = PRU_INTC.SECR0;
if (secr0 & (1 << KICK_PRU1_EVENT)) {
- CT_INTC.SECR0 = 1 << KICK_PRU1_EVENT;
+ PRU_INTC.SECR0 = 1 << KICK_PRU1_EVENT;
sched_wake_tasks();
}
if (secr0 & (1 << IEP_EVENT)) {
@@ -93,7 +93,7 @@ _irq_poll(void)
in_timer_dispatch = 1;
uint32_t next = timer_dispatch_many();
timer_set(next);
- CT_INTC.SECR0 = 1 << IEP_EVENT;
+ PRU_INTC.SECR0 = 1 << IEP_EVENT;
in_timer_dispatch = 0;
}
}
@@ -148,7 +148,7 @@ console_sendf(const struct command_encoder *ce, va_list args)
SHARED_MEM->next_encoder_args = args;
writel(&SHARED_MEM->next_encoder, (uint32_t)ce);
- // Signal PRU0 to transmit message
+ // Signal PRU0 to transmit message - 20 | (18-16) = 22 = 0010 0010
write_r31(R31_WRITE_IRQ_SELECT | (KICK_PRU0_EVENT - R31_WRITE_IRQ_OFFSET));
uint32_t itd = in_timer_dispatch;
while (readl(&SHARED_MEM->next_encoder))
@@ -197,25 +197,6 @@ dynmem_end(void)
return (void*)(8*1024 - STACK_SIZE);
}
-
-/****************************************************************
- * Resource table
- ****************************************************************/
-
-struct my_resource_table {
- struct resource_table base;
-
- uint32_t offset[1]; /* Should match 'num' in actual definition */
-} resourceTable __visible __section(".resource_table") = {
- {
- 1, /* Resource table version: only version 1 is
- * supported by the current driver */
- 0, /* number of entries in the table */
- { 0, 0 }, /* reserved, must be zero */
- },
-};
-
-
/****************************************************************
* Startup
****************************************************************/
diff --git a/src/pru/pru0.c b/src/pru/pru0.c
index efede044..57d55d27 100644
--- a/src/pru/pru0.c
+++ b/src/pru/pru0.c
@@ -8,17 +8,16 @@
#include <stdint.h> // uint32_t
#include <string.h> // memset
#include <pru/io.h> // write_r31
-#include <pru_cfg.h> // CT_CFG
-#include <pru_intc.h> // CT_INTC
#include <pru_rpmsg.h> // pru_rpmsg_send
#include <pru_virtio_ids.h> // VIRTIO_ID_RPMSG
-#include <rsc_types.h> // resource_table
#include "board/io.h" // readl
#include "board/misc.h" // console_sendf
#include "command.h" // command_encode_add_frame
#include "compiler.h" // __section
#include "internal.h" // SHARED_MEM
#include "sched.h" // sched_shutdown
+#include "intc_map_0.h"
+#include "resource_table.h"
struct pru_rpmsg_transport transport;
static uint16_t transport_dst;
@@ -32,8 +31,7 @@ static uint16_t transport_dst;
#define CHAN_DESC "Channel 30"
#define CHAN_PORT 30
-#define RPMSG_HDR_SIZE 16
-static uint8_t transmit_buf[RPMSG_BUF_SIZE - RPMSG_HDR_SIZE];
+static uint8_t transmit_buf[RPMSG_MESSAGE_SIZE];
static int transmit_pos;
// Transmit all pending message blocks
@@ -195,7 +193,7 @@ static void
process_io(void)
{
for (;;) {
- CT_INTC.SECR0 = ((1 << KICK_PRU0_FROM_ARM_EVENT)
+ PRU_INTC.SECR0 = ((1 << KICK_PRU0_FROM_ARM_EVENT)
| (1 << KICK_PRU0_EVENT));
check_can_send();
int can_sleep = check_can_read();
@@ -251,112 +249,6 @@ console_sendf(const struct command_encoder *ce, va_list args)
}
-/****************************************************************
- * Resource table
- ****************************************************************/
-
-/*
- * Sizes of the virtqueues (expressed in number of buffers supported,
- * and must be power of 2)
- */
-#define PRU_RPMSG_VQ0_SIZE 16
-#define PRU_RPMSG_VQ1_SIZE 16
-
-/*
- * The feature bitmap for virtio rpmsg
- */
-#define VIRTIO_RPMSG_F_NS 0 //name service notifications
-
-/* This firmware supports name service notifications as one of its features */
-#define RPMSG_PRU_C0_FEATURES (1 << VIRTIO_RPMSG_F_NS)
-
-/* Definition for unused interrupts */
-#define HOST_UNUSED 255
-
-/* Mapping sysevts to a channel. Each pair contains a sysevt, channel. */
-static struct ch_map pru_intc_map[] = {
- {IEP_EVENT, WAKE_PRU1_IRQ},
- {KICK_ARM_EVENT, WAKE_ARM_IRQ},
- {KICK_PRU0_FROM_ARM_EVENT, WAKE_PRU0_IRQ},
- {KICK_PRU0_EVENT, WAKE_PRU0_IRQ},
- {KICK_PRU1_EVENT, WAKE_PRU1_IRQ},
-};
-
-struct my_resource_table {
- struct resource_table base;
-
- uint32_t offset[2]; /* Should match 'num' in actual definition */
-
- /* rpmsg vdev entry */
- struct fw_rsc_vdev rpmsg_vdev;
- struct fw_rsc_vdev_vring rpmsg_vring0;
- struct fw_rsc_vdev_vring rpmsg_vring1;
-
- /* intc definition */
- struct fw_rsc_custom pru_ints;
-} resourceTable __section(".resource_table") = {
- {
- 1, /* Resource table version: only version 1 is
- * supported by the current driver */
- 2, /* number of entries in the table */
- { 0, 0 }, /* reserved, must be zero */
- },
- /* offsets to entries */
- {
- offsetof(struct my_resource_table, rpmsg_vdev),
- offsetof(struct my_resource_table, pru_ints),
- },
-
- /* rpmsg vdev entry */
- {
- (uint32_t)TYPE_VDEV, //type
- (uint32_t)VIRTIO_ID_RPMSG, //id
- (uint32_t)0, //notifyid
- (uint32_t)RPMSG_PRU_C0_FEATURES,//dfeatures
- (uint32_t)0, //gfeatures
- (uint32_t)0, //config_len
- (uint8_t)0, //status
- (uint8_t)2, //num_of_vrings, only two is supported
- {(uint8_t)0, (uint8_t)0 }, //reserved
- /* no config data */
- },
- /* the two vrings */
- {
- 0, //da, will be populated by host, can't pass it in
- 16, //align (bytes),
- PRU_RPMSG_VQ0_SIZE, //num of descriptors
- 0, //notifyid, will be populated, can't pass right now
- 0 //reserved
- },
- {
- 0, //da, will be populated by host, can't pass it in
- 16, //align (bytes),
- PRU_RPMSG_VQ1_SIZE, //num of descriptors
- 0, //notifyid, will be populated, can't pass right now
- 0 //reserved
- },
-
- {
- TYPE_CUSTOM, TYPE_PRU_INTS,
- sizeof(struct fw_rsc_custom_ints),
- { /* PRU_INTS version */
- {
- 0x0000,
- /* Channel-to-host mapping, 255 for unused */
- {
- WAKE_PRU0_IRQ, WAKE_PRU1_IRQ, WAKE_ARM_IRQ,
- HOST_UNUSED, HOST_UNUSED, HOST_UNUSED,
- HOST_UNUSED, HOST_UNUSED, HOST_UNUSED, HOST_UNUSED
- },
- /* Number of evts being mapped to channels */
- (sizeof(pru_intc_map) / sizeof(struct ch_map)),
- /* Pointer to the structure containing mapped events */
- pru_intc_map,
- },
- },
- },
-};
-
/****************************************************************
* Startup
@@ -368,11 +260,26 @@ int
main(void)
{
// allow access to external memory
+#if defined(__AM335X__)
+ /* AM335x must enable OCP master port access in order for the PRU to
+ * read external memories.*/
CT_CFG.SYSCFG_bit.STANDBY_INIT = 0;
+#endif
+
+ /* Clear the status of the PRU-ICSS system event that the ARM
+ will use to 'kick' us */
+#if defined(__AM335X__)
+ PRU_INTC.SICR_bit.STS_CLR_IDX = KICK_PRU0_FROM_ARM_EVENT;
+#elif defined(__TDA4VM__) || defined(__AM62X__)
+ PRU_INTC.STATUS_CLR_INDEX_REG_bit.STATUS_CLR_INDEX = \
+ KICK_PRU0_FROM_ARM_EVENT;
+#else
+ #error "Unsupported SoC."
+#endif
// clear all irqs
- CT_INTC.SECR0 = 0xffffffff;
- CT_INTC.SECR1 = 0xffffffff;
+ PRU_INTC.SECR0 = 0xffffffff;
+ PRU_INTC.SECR1 = 0xffffffff;
/* Make sure the Linux drivers are ready for RPMsg communication */
volatile uint8_t *status = &resourceTable.rpmsg_vdev.status;
diff --git a/src/pru/resource_table.h b/src/pru/resource_table.h
new file mode 100644
index 00000000..9dff2b9c
--- /dev/null
+++ b/src/pru/resource_table.h
@@ -0,0 +1,91 @@
+/****************************************************************
+ * Resource table
+ ****************************************************************/
+
+#ifndef _RESOURCE_TABLE_H_
+#define _RESOURCE_TABLE_H_
+
+#include <stddef.h>
+#include "pru_virtio_ids.h"
+
+/*
+ * Sizes of the virtqueues (expressed in number of buffers supported,
+ * and must be power of 2)
+ */
+#define PRU_RPMSG_VQ0_SIZE 16
+#define PRU_RPMSG_VQ1_SIZE 16
+
+/*
+ * The feature bitmap for virtio rpmsg
+ */
+#define VIRTIO_RPMSG_F_NS 0 //name service notifications
+
+/* This firmware supports name service notifications as one of its features */
+#define RPMSG_PRU_C0_FEATURES (1 << VIRTIO_RPMSG_F_NS)
+
+/* Definition for unused interrupts */
+#define HOST_UNUSED 255
+
+struct my_resource_table {
+ struct resource_table base;
+
+ uint32_t offset[1]; /* Should match 'num' in actual definition */
+
+ /* rpmsg vdev entry */
+ struct fw_rsc_vdev rpmsg_vdev;
+ struct fw_rsc_vdev_vring rpmsg_vring0;
+ struct fw_rsc_vdev_vring rpmsg_vring1;
+
+};
+
+#if !defined(__GNUC__)
+ #pragma DATA_SECTION(resourceTable, ".resource_table")
+ #pragma RETAIN(resourceTable)
+ #define __resource_table /* */
+#else
+ #define __resource_table __attribute__((section(".resource_table")))
+#endif
+
+struct my_resource_table resourceTable __resource_table = {
+ {
+ 1, /* Resource table version: only version 1 is
+ * supported by the current driver */
+ 1, /* number of entries in the table */
+ {0, 0}, /* reserved, must be zero */
+ },
+ /* offsets to entries */
+ {
+ offsetof(struct my_resource_table, rpmsg_vdev),
+ },
+
+ /* rpmsg vdev entry */
+ {
+ (uint32_t)TYPE_VDEV, //type
+ (uint32_t)VIRTIO_ID_RPMSG, //id
+ (uint32_t)0, //notifyid
+ (uint32_t)RPMSG_PRU_C0_FEATURES,//dfeatures
+ (uint32_t)0, //gfeatures
+ (uint32_t)0, //config_len
+ (uint8_t)0, //status
+ (uint8_t)2, //num_of_vrings, only two is supported
+ {(uint8_t)0, (uint8_t)0 }, //reserved
+ /* no config data */
+ },
+ /* the two vrings */
+ {
+ FW_RSC_ADDR_ANY, //da, will be populated by host, can't pass it in
+ 16, //align (bytes),
+ PRU_RPMSG_VQ0_SIZE, //num of descriptors
+ 0, //notifyid, will be populated, can't pass right now
+ 0 //reserved
+ },
+ {
+ FW_RSC_ADDR_ANY, //da, will be populated by host, can't pass it in
+ 16, //align (bytes),
+ PRU_RPMSG_VQ1_SIZE, //num of descriptors
+ 0, //notifyid, will be populated, can't pass right now
+ 0 //reserved
+ },
+};
+
+#endif /* _RESOURCE_TABLE_H_ */