linux/drivers/remoteproc/pru_rproc.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * PRU-ICSS remoteproc driver for various TI SoCs
 *
 * Copyright (C) 2014-2022 Texas Instruments Incorporated - https://www.ti.com/
 *
 * Author(s):
 *	Suman Anna <[email protected]>
 *	Andrew F. Davis <[email protected]>
 *	Grzegorz Jaszczyk <[email protected]> for Texas Instruments
 *	Puranjay Mohan <[email protected]>
 *	Md Danish Anwar <[email protected]>
 */

#include <linux/bitops.h>
#include <linux/debugfs.h>
#include <linux/irqdomain.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>
#include <linux/remoteproc/pruss.h>
#include <linux/pruss_driver.h>
#include <linux/remoteproc.h>

#include "remoteproc_internal.h"
#include "remoteproc_elf_helpers.h"
#include "pru_rproc.h"

/* PRU_ICSS_PRU_CTRL registers */
#define PRU_CTRL_CTRL
#define PRU_CTRL_STS
#define PRU_CTRL_WAKEUP_EN
#define PRU_CTRL_CYCLE
#define PRU_CTRL_STALL
#define PRU_CTRL_CTBIR0
#define PRU_CTRL_CTBIR1
#define PRU_CTRL_CTPPR0
#define PRU_CTRL_CTPPR1

/* CTRL register bit-fields */
#define CTRL_CTRL_SOFT_RST_N
#define CTRL_CTRL_EN
#define CTRL_CTRL_SLEEPING
#define CTRL_CTRL_CTR_EN
#define CTRL_CTRL_SINGLE_STEP
#define CTRL_CTRL_RUNSTATE

/* PRU_ICSS_PRU_DEBUG registers */
#define PRU_DEBUG_GPREG(x)
#define PRU_DEBUG_CT_REG(x)

/* PRU/RTU/Tx_PRU Core IRAM address masks */
#define PRU_IRAM_ADDR_MASK
#define PRU0_IRAM_ADDR_MASK
#define PRU1_IRAM_ADDR_MASK
#define RTU0_IRAM_ADDR_MASK
#define RTU1_IRAM_ADDR_MASK
#define TX_PRU0_IRAM_ADDR_MASK
#define TX_PRU1_IRAM_ADDR_MASK

/* PRU device addresses for various type of PRU RAMs */
#define PRU_IRAM_DA
#define PRU_PDRAM_DA
#define PRU_SDRAM_DA
#define PRU_SHRDRAM_DA

#define MAX_PRU_SYS_EVENTS

/**
 * enum pru_iomem - PRU core memory/register range identifiers
 *
 * @PRU_IOMEM_IRAM: PRU Instruction RAM range
 * @PRU_IOMEM_CTRL: PRU Control register range
 * @PRU_IOMEM_DEBUG: PRU Debug register range
 * @PRU_IOMEM_MAX: just keep this one at the end
 */
enum pru_iomem {};

/**
 * struct pru_private_data - device data for a PRU core
 * @type: type of the PRU core (PRU, RTU, Tx_PRU)
 * @is_k3: flag used to identify the need for special load handling
 */
struct pru_private_data {};

/**
 * struct pru_rproc - PRU remoteproc structure
 * @id: id of the PRU core within the PRUSS
 * @dev: PRU core device pointer
 * @pruss: back-reference to parent PRUSS structure
 * @rproc: remoteproc pointer for this PRU core
 * @data: PRU core specific data
 * @mem_regions: data for each of the PRU memory regions
 * @client_np: client device node
 * @lock: mutex to protect client usage
 * @fw_name: name of firmware image used during loading
 * @mapped_irq: virtual interrupt numbers of created fw specific mapping
 * @pru_interrupt_map: pointer to interrupt mapping description (firmware)
 * @pru_interrupt_map_sz: pru_interrupt_map size
 * @rmw_lock: lock for read, modify, write operations on registers
 * @dbg_single_step: debug state variable to set PRU into single step mode
 * @dbg_continuous: debug state variable to restore PRU execution mode
 * @evt_count: number of mapped events
 * @gpmux_save: saved value for gpmux config
 */
struct pru_rproc {};

static inline u32 pru_control_read_reg(struct pru_rproc *pru, unsigned int reg)
{}

static inline
void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
{}

static inline
void pru_control_set_reg(struct pru_rproc *pru, unsigned int reg,
			 u32 mask, u32 set)
{}

/**
 * pru_rproc_set_firmware() - set firmware for a PRU core
 * @rproc: the rproc instance of the PRU
 * @fw_name: the new firmware name, or NULL if default is desired
 *
 * Return: 0 on success, or errno in error case.
 */
static int pru_rproc_set_firmware(struct rproc *rproc, const char *fw_name)
{}

static struct rproc *__pru_rproc_get(struct device_node *np, int index)
{}

/**
 * pru_rproc_get() - get the PRU rproc instance from a device node
 * @np: the user/client device node
 * @index: index to use for the ti,prus property
 * @pru_id: optional pointer to return the PRU remoteproc processor id
 *
 * This function looks through a client device node's "ti,prus" property at
 * index @index and returns the rproc handle for a valid PRU remote processor if
 * found. The function allows only one user to own the PRU rproc resource at a
 * time. Caller must call pru_rproc_put() when done with using the rproc, not
 * required if the function returns a failure.
 *
 * When optional @pru_id pointer is passed the PRU remoteproc processor id is
 * returned.
 *
 * Return: rproc handle on success, and an ERR_PTR on failure using one
 * of the following error values
 *    -ENODEV if device is not found
 *    -EBUSY if PRU is already acquired by anyone
 *    -EPROBE_DEFER is PRU device is not probed yet
 */
struct rproc *pru_rproc_get(struct device_node *np, int index,
			    enum pruss_pru_id *pru_id)
{}
EXPORT_SYMBOL_GPL();

/**
 * pru_rproc_put() - release the PRU rproc resource
 * @rproc: the rproc resource to release
 *
 * Releases the PRU rproc resource and makes it available to other
 * users.
 */
void pru_rproc_put(struct rproc *rproc)
{}
EXPORT_SYMBOL_GPL();

/**
 * pru_rproc_set_ctable() - set the constant table index for the PRU
 * @rproc: the rproc instance of the PRU
 * @c: constant table index to set
 * @addr: physical address to set it to
 *
 * Return: 0 on success, or errno in error case.
 */
int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr)
{}
EXPORT_SYMBOL_GPL();

static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg)
{}

static int regs_show(struct seq_file *s, void *data)
{}
DEFINE_SHOW_ATTRIBUTE();

/*
 * Control PRU single-step mode
 *
 * This is a debug helper function used for controlling the single-step
 * mode of the PRU. The PRU Debug registers are not accessible when the
 * PRU is in RUNNING state.
 *
 * Writing a non-zero value sets the PRU into single-step mode irrespective
 * of its previous state. The PRU mode is saved only on the first set into
 * a single-step mode. Writing a zero value will restore the PRU into its
 * original mode.
 */
static int pru_rproc_debug_ss_set(void *data, u64 val)
{}

static int pru_rproc_debug_ss_get(void *data, u64 *val)
{}
DEFINE_DEBUGFS_ATTRIBUTE();

/*
 * Create PRU-specific debugfs entries
 *
 * The entries are created only if the parent remoteproc debugfs directory
 * exists, and will be cleaned up by the remoteproc core.
 */
static void pru_rproc_create_debug_entries(struct rproc *rproc)
{}

static void pru_dispose_irq_mapping(struct pru_rproc *pru)
{}

/*
 * Parse the custom PRU interrupt map resource and configure the INTC
 * appropriately.
 */
static int pru_handle_intrmap(struct rproc *rproc)
{}

static int pru_rproc_start(struct rproc *rproc)
{}

static int pru_rproc_stop(struct rproc *rproc)
{}

/*
 * Convert PRU device address (data spaces only) to kernel virtual address.
 *
 * Each PRU has access to all data memories within the PRUSS, accessible at
 * different ranges. So, look through both its primary and secondary Data
 * RAMs as well as any shared Data RAM to convert a PRU device address to
 * kernel virtual address. Data RAM0 is primary Data RAM for PRU0 and Data
 * RAM1 is primary Data RAM for PRU1.
 */
static void *pru_d_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
{}

/*
 * Convert PRU device address (instruction space) to kernel virtual address.
 *
 * A PRU does not have an unified address space. Each PRU has its very own
 * private Instruction RAM, and its device address is identical to that of
 * its primary Data RAM device address.
 */
static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len)
{}

/*
 * Provide address translations for only PRU Data RAMs through the remoteproc
 * core for any PRU client drivers. The PRU Instruction RAM access is restricted
 * only to the PRU loader code.
 */
static void *pru_rproc_da_to_va(struct rproc *rproc, u64 da, size_t len, bool *is_iomem)
{}

/* PRU-specific address translator used by PRU loader. */
static void *pru_da_to_va(struct rproc *rproc, u64 da, size_t len, bool is_iram)
{}

static struct rproc_ops pru_rproc_ops =;

/*
 * Custom memory copy implementation for ICSSG PRU/RTU/Tx_PRU Cores
 *
 * The ICSSG PRU/RTU/Tx_PRU cores have a memory copying issue with IRAM
 * memories, that is not seen on previous generation SoCs. The data is reflected
 * properly in the IRAM memories only for integer (4-byte) copies. Any unaligned
 * copies result in all the other pre-existing bytes zeroed out within that
 * 4-byte boundary, thereby resulting in wrong text/code in the IRAMs. Also, the
 * IRAM memory port interface does not allow any 8-byte copies (as commonly used
 * by ARM64 memcpy implementation) and throws an exception. The DRAM memory
 * ports do not show this behavior.
 */
static int pru_rproc_memcpy(void *dest, const void *src, size_t count)
{}

static int
pru_rproc_load_elf_segments(struct rproc *rproc, const struct firmware *fw)
{}

static const void *
pru_rproc_find_interrupt_map(struct device *dev, const struct firmware *fw)
{}

/*
 * Use a custom parse_fw callback function for dealing with PRU firmware
 * specific sections.
 *
 * The firmware blob can contain optional ELF sections: .resource_table section
 * and .pru_irq_map one. The second one contains the PRUSS interrupt mapping
 * description, which needs to be setup before powering on the PRU core. To
 * avoid RAM wastage this ELF section is not mapped to any ELF segment (by the
 * firmware linker) and therefore is not loaded to PRU memory.
 */
static int pru_rproc_parse_fw(struct rproc *rproc, const struct firmware *fw)
{}

/*
 * Compute PRU id based on the IRAM addresses. The PRU IRAMs are
 * always at a particular offset within the PRUSS address space.
 */
static int pru_rproc_set_id(struct pru_rproc *pru)
{}

static int pru_rproc_probe(struct platform_device *pdev)
{}

static void pru_rproc_remove(struct platform_device *pdev)
{}

static const struct pru_private_data pru_data =;

static const struct pru_private_data k3_pru_data =;

static const struct pru_private_data k3_rtu_data =;

static const struct pru_private_data k3_tx_pru_data =;

static const struct of_device_id pru_rproc_match[] =;
MODULE_DEVICE_TABLE(of, pru_rproc_match);

static struct platform_driver pru_rproc_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();