diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/pru/Makefile | 4 | ||||
-rw-r--r-- | src/pru/gpio.c | 2 | ||||
-rw-r--r-- | src/pru/intc_map_0.h | 62 | ||||
-rw-r--r-- | src/pru/internal.h | 6 | ||||
-rw-r--r-- | src/pru/main.c | 31 | ||||
-rw-r--r-- | src/pru/pru0.c | 135 | ||||
-rw-r--r-- | src/pru/resource_table.h | 91 |
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_ */ |