@@ -65,6 +65,7 @@ enum pru_mem {
* @dram0: PRUSS DRAM0 region
* @dram1: PRUSS DRAM1 region
* @shrdram: PRUSS SHARED RAM region
+ * @rmw_lock: lock for read, modify, write operations on registers
* @iram_da: device address of Instruction RAM for this PRU
* @pdram_da: device address of primary Data RAM for this PRU
* @sdram_da: device address of secondary Data RAM for this PRU
@@ -85,6 +86,7 @@ struct pru_rproc {
struct pruss_mem_region dram0;
struct pruss_mem_region dram1;
struct pruss_mem_region shrdram;
+ spinlock_t rmw_lock; /* register access lock */
u32 iram_da;
u32 pdram_da;
u32 sdram_da;
@@ -107,6 +109,54 @@ void pru_control_write_reg(struct pru_rproc *pru, unsigned int reg, u32 val)
writel_relaxed(val, pru->mem_regions[PRU_MEM_CTRL].va + reg);
}
+static inline
+void pru_control_set_reg(struct pru_rproc *pru, unsigned int reg,
+ u32 mask, u32 set)
+{
+ u32 val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&pru->rmw_lock, flags);
+
+ val = pru_control_read_reg(pru, reg);
+ val &= ~mask;
+ val |= (set & mask);
+ pru_control_write_reg(pru, reg, val);
+
+ spin_unlock_irqrestore(&pru->rmw_lock, flags);
+}
+
+/**
+ * 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
+ */
+int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr)
+{
+ struct pru_rproc *pru = rproc->priv;
+ unsigned int reg;
+ u32 mask, set;
+ u16 idx;
+ u16 idx_mask;
+
+ /* pointer is 16 bit and index is 8-bit so mask out the rest */
+ idx_mask = (c >= PRU_C28) ? 0xFFFF : 0xFF;
+
+ /* ctable uses bit 8 and upwards only */
+ idx = (addr >> 8) & idx_mask;
+
+ /* configurable ctable (i.e. C24) starts at PRU_CTRL_CTBIR0 */
+ reg = PRU_CTRL_CTBIR0 + 4 * (c >> 1);
+ mask = idx_mask << (16 * (c & 1));
+ set = idx << (16 * (c & 1));
+
+ pru_control_set_reg(pru, reg, mask, set);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(pru_rproc_set_ctable);
+
static inline u32 pru_debug_read_reg(struct pru_rproc *pru, unsigned int reg)
{
return readl_relaxed(pru->mem_regions[PRU_MEM_DEBUG].va + reg);
@@ -537,6 +587,7 @@ static int pru_rproc_probe(struct platform_device *pdev)
pru->pruss = platform_get_drvdata(ppdev);
pru->rproc = rproc;
pru->fw_name = fw_name;
+ spin_lock_init(&pru->rmw_lock);
ret = pruss_request_mem_region(pru->pruss, PRUSS_MEM_DRAM0,
&pru->dram0);
@@ -134,7 +134,22 @@ struct pruss_intc_config {
s8 ch_to_host[MAX_PRU_CHANNELS];
};
+/**
+ * enum pru_ctable_idx - Configurable Constant table index identifiers
+ */
+enum pru_ctable_idx {
+ PRU_C24 = 0,
+ PRU_C25,
+ PRU_C26,
+ PRU_C27,
+ PRU_C28,
+ PRU_C29,
+ PRU_C30,
+ PRU_C31,
+};
+
struct pruss;
+struct rproc;
#if IS_ENABLED(CONFIG_TI_PRUSS)
@@ -232,4 +247,18 @@ int pruss_intc_unconfigure(struct pruss *pruss,
#endif /* CONFIG_TI_PRUSS */
+#if IS_ENABLED(CONFIG_PRUSS_REMOTEPROC)
+
+int pru_rproc_set_ctable(struct rproc *rproc, enum pru_ctable_idx c, u32 addr);
+
+#else
+
+static inline int pru_rproc_set_ctable(struct rproc *rproc,
+ enum pru_ctable_idx c, u32 addr)
+{
+ return -ENOTSUPP;
+}
+
+#endif /* CONFIG_PRUSS_REMOTEPROC */
+
#endif /* __LINUX_PRUSS_H */