Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.17.
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * ZynqMP R5 Remote Processor driver
   4 *
   5 */
   6
   7#include <dt-bindings/power/xlnx-zynqmp-power.h>
   8#include <linux/dma-mapping.h>
   9#include <linux/firmware/xlnx-zynqmp.h>
  10#include <linux/kernel.h>
  11#include <linux/mailbox_client.h>
  12#include <linux/mailbox/zynqmp-ipi-message.h>
  13#include <linux/module.h>
  14#include <linux/of_address.h>
  15#include <linux/of_platform.h>
  16#include <linux/of_reserved_mem.h>
  17#include <linux/platform_device.h>
  18#include <linux/remoteproc.h>
  19
  20#include "remoteproc_internal.h"
  21
  22/* IPI buffer MAX length */
  23#define IPI_BUF_LEN_MAX	32U
  24
  25/* RX mailbox client buffer max length */
  26#define MBOX_CLIENT_BUF_MAX	(IPI_BUF_LEN_MAX + \
  27				 sizeof(struct zynqmp_ipi_message))
  28/*
  29 * settings for RPU cluster mode which
  30 * reflects possible values of xlnx,cluster-mode dt-property
  31 */
  32enum zynqmp_r5_cluster_mode {
  33	SPLIT_MODE = 0, /* When cores run as separate processor */
  34	LOCKSTEP_MODE = 1, /* cores execute same code in lockstep,clk-for-clk */
  35	SINGLE_CPU_MODE = 2, /* core0 is held in reset and only core1 runs */
  36};
  37
  38/**
  39 * struct mem_bank_data - Memory Bank description
  40 *
  41 * @addr: Start address of memory bank
  42 * @da: device address
  43 * @size: Size of Memory bank
  44 * @pm_domain_id: Power-domains id of memory bank for firmware to turn on/off
  45 * @bank_name: name of the bank for remoteproc framework
  46 */
  47struct mem_bank_data {
  48	phys_addr_t addr;
  49	u32 da;
  50	size_t size;
  51	u32 pm_domain_id;
  52	char *bank_name;
  53};
  54
  55/**
  56 * struct mbox_info
  57 *
  58 * @rx_mc_buf: to copy data from mailbox rx channel
  59 * @tx_mc_buf: to copy data to mailbox tx channel
  60 * @r5_core: this mailbox's corresponding r5_core pointer
  61 * @mbox_work: schedule work after receiving data from mailbox
  62 * @mbox_cl: mailbox client
  63 * @tx_chan: mailbox tx channel
  64 * @rx_chan: mailbox rx channel
  65 */
  66struct mbox_info {
  67	unsigned char rx_mc_buf[MBOX_CLIENT_BUF_MAX];
  68	unsigned char tx_mc_buf[MBOX_CLIENT_BUF_MAX];
  69	struct zynqmp_r5_core *r5_core;
  70	struct work_struct mbox_work;
  71	struct mbox_client mbox_cl;
  72	struct mbox_chan *tx_chan;
  73	struct mbox_chan *rx_chan;
  74};
  75
  76/*
  77 * Hardcoded TCM bank values. This will be removed once TCM bindings are
  78 * accepted for system-dt specifications and upstreamed in linux kernel
  79 */
  80static const struct mem_bank_data zynqmp_tcm_banks_split[] = {
  81	{0xffe00000UL, 0x0, 0x10000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 64KB each */
  82	{0xffe20000UL, 0x20000, 0x10000UL, PD_R5_0_BTCM, "btcm0"},
  83	{0xffe90000UL, 0x0, 0x10000UL, PD_R5_1_ATCM, "atcm1"},
  84	{0xffeb0000UL, 0x20000, 0x10000UL, PD_R5_1_BTCM, "btcm1"},
  85};
  86
  87/* In lockstep mode cluster combines each 64KB TCM and makes 128KB TCM */
  88static const struct mem_bank_data zynqmp_tcm_banks_lockstep[] = {
  89	{0xffe00000UL, 0x0, 0x20000UL, PD_R5_0_ATCM, "atcm0"}, /* TCM 128KB each */
  90	{0xffe20000UL, 0x20000, 0x20000UL, PD_R5_0_BTCM, "btcm0"},
  91	{0, 0, 0, PD_R5_1_ATCM, ""},
  92	{0, 0, 0, PD_R5_1_BTCM, ""},
  93};
  94
  95/**
  96 * struct zynqmp_r5_core
  97 *
  98 * @dev: device of RPU instance
  99 * @np: device node of RPU instance
 100 * @tcm_bank_count: number TCM banks accessible to this RPU
 101 * @tcm_banks: array of each TCM bank data
 102 * @rproc: rproc handle
 103 * @pm_domain_id: RPU CPU power domain id
 104 * @ipi: pointer to mailbox information
 105 */
 106struct zynqmp_r5_core {
 107	struct device *dev;
 108	struct device_node *np;
 109	int tcm_bank_count;
 110	struct mem_bank_data **tcm_banks;
 111	struct rproc *rproc;
 112	u32 pm_domain_id;
 113	struct mbox_info *ipi;
 114};
 115
 116/**
 117 * struct zynqmp_r5_cluster
 118 *
 119 * @dev: r5f subsystem cluster device node
 120 * @mode: cluster mode of type zynqmp_r5_cluster_mode
 121 * @core_count: number of r5 cores used for this cluster mode
 122 * @r5_cores: Array of pointers pointing to r5 core
 123 */
 124struct zynqmp_r5_cluster {
 125	struct device *dev;
 126	enum  zynqmp_r5_cluster_mode mode;
 127	int core_count;
 128	struct zynqmp_r5_core **r5_cores;
 129};
 130
 131/**
 132 * event_notified_idr_cb() - callback for vq_interrupt per notifyid
 133 * @id: rproc->notify id
 134 * @ptr: pointer to idr private data
 135 * @data: data passed to idr_for_each callback
 136 *
 137 * Pass notification to remoteproc virtio
 138 *
 139 * Return: 0. having return is to satisfy the idr_for_each() function
 140 *          pointer input argument requirement.
 141 **/
 142static int event_notified_idr_cb(int id, void *ptr, void *data)
 143{
 144	struct rproc *rproc = data;
 145
 146	if (rproc_vq_interrupt(rproc, id) == IRQ_NONE)
 147		dev_dbg(&rproc->dev, "data not found for vqid=%d\n", id);
 148
 149	return 0;
 150}
 151
 152/**
 153 * handle_event_notified() - remoteproc notification work function
 154 * @work: pointer to the work structure
 155 *
 156 * It checks each registered remoteproc notify IDs.
 157 */
 158static void handle_event_notified(struct work_struct *work)
 159{
 160	struct mbox_info *ipi;
 161	struct rproc *rproc;
 162
 163	ipi = container_of(work, struct mbox_info, mbox_work);
 164	rproc = ipi->r5_core->rproc;
 165
 166	/*
 167	 * We only use IPI for interrupt. The RPU firmware side may or may
 168	 * not write the notifyid when it trigger IPI.
 169	 * And thus, we scan through all the registered notifyids and
 170	 * find which one is valid to get the message.
 171	 * Even if message from firmware is NULL, we attempt to get vqid
 172	 */
 173	idr_for_each(&rproc->notifyids, event_notified_idr_cb, rproc);
 174}
 175
 176/**
 177 * zynqmp_r5_mb_rx_cb() - receive channel mailbox callback
 178 * @cl: mailbox client
 179 * @msg: message pointer
 180 *
 181 * Receive data from ipi buffer, ack interrupt and then
 182 * it will schedule the R5 notification work.
 183 */
 184static void zynqmp_r5_mb_rx_cb(struct mbox_client *cl, void *msg)
 185{
 186	struct zynqmp_ipi_message *ipi_msg, *buf_msg;
 187	struct mbox_info *ipi;
 188	size_t len;
 189
 190	ipi = container_of(cl, struct mbox_info, mbox_cl);
 191
 192	/* copy data from ipi buffer to r5_core */
 193	ipi_msg = (struct zynqmp_ipi_message *)msg;
 194	buf_msg = (struct zynqmp_ipi_message *)ipi->rx_mc_buf;
 195	len = ipi_msg->len;
 196	if (len > IPI_BUF_LEN_MAX) {
 197		dev_warn(cl->dev, "msg size exceeded than %d\n",
 198			 IPI_BUF_LEN_MAX);
 199		len = IPI_BUF_LEN_MAX;
 200	}
 201	buf_msg->len = len;
 202	memcpy(buf_msg->data, ipi_msg->data, len);
 203
 204	/* received and processed interrupt ack */
 205	if (mbox_send_message(ipi->rx_chan, NULL) < 0)
 206		dev_err(cl->dev, "ack failed to mbox rx_chan\n");
 207
 208	schedule_work(&ipi->mbox_work);
 209}
 210
 211/**
 212 * zynqmp_r5_setup_mbox() - Setup mailboxes related properties
 213 *			    this is used for each individual R5 core
 214 *
 215 * @cdev: child node device
 216 *
 217 * Function to setup mailboxes related properties
 218 * return : NULL if failed else pointer to mbox_info
 219 */
 220static struct mbox_info *zynqmp_r5_setup_mbox(struct device *cdev)
 221{
 222	struct mbox_client *mbox_cl;
 223	struct mbox_info *ipi;
 224
 225	ipi = kzalloc(sizeof(*ipi), GFP_KERNEL);
 226	if (!ipi)
 227		return NULL;
 228
 229	mbox_cl = &ipi->mbox_cl;
 230	mbox_cl->rx_callback = zynqmp_r5_mb_rx_cb;
 231	mbox_cl->tx_block = false;
 232	mbox_cl->knows_txdone = false;
 233	mbox_cl->tx_done = NULL;
 234	mbox_cl->dev = cdev;
 235
 236	/* Request TX and RX channels */
 237	ipi->tx_chan = mbox_request_channel_byname(mbox_cl, "tx");
 238	if (IS_ERR(ipi->tx_chan)) {
 239		ipi->tx_chan = NULL;
 240		kfree(ipi);
 241		dev_warn(cdev, "mbox tx channel request failed\n");
 242		return NULL;
 243	}
 244
 245	ipi->rx_chan = mbox_request_channel_byname(mbox_cl, "rx");
 246	if (IS_ERR(ipi->rx_chan)) {
 247		mbox_free_channel(ipi->tx_chan);
 248		ipi->rx_chan = NULL;
 249		ipi->tx_chan = NULL;
 250		kfree(ipi);
 251		dev_warn(cdev, "mbox rx channel request failed\n");
 252		return NULL;
 253	}
 254
 255	INIT_WORK(&ipi->mbox_work, handle_event_notified);
 256
 257	return ipi;
 258}
 259
 260static void zynqmp_r5_free_mbox(struct mbox_info *ipi)
 261{
 262	if (!ipi)
 263		return;
 264
 265	if (ipi->tx_chan) {
 266		mbox_free_channel(ipi->tx_chan);
 267		ipi->tx_chan = NULL;
 268	}
 269
 270	if (ipi->rx_chan) {
 271		mbox_free_channel(ipi->rx_chan);
 272		ipi->rx_chan = NULL;
 273	}
 274
 275	kfree(ipi);
 276}
 277
 278/*
 279 * zynqmp_r5_core_kick() - kick a firmware if mbox is provided
 280 * @rproc: r5 core's corresponding rproc structure
 281 * @vqid: virtqueue ID
 282 */
 283static void zynqmp_r5_rproc_kick(struct rproc *rproc, int vqid)
 284{
 285	struct zynqmp_r5_core *r5_core = rproc->priv;
 286	struct device *dev = r5_core->dev;
 287	struct zynqmp_ipi_message *mb_msg;
 288	struct mbox_info *ipi;
 289	int ret;
 290
 291	ipi = r5_core->ipi;
 292	if (!ipi)
 293		return;
 294
 295	mb_msg = (struct zynqmp_ipi_message *)ipi->tx_mc_buf;
 296	memcpy(mb_msg->data, &vqid, sizeof(vqid));
 297	mb_msg->len = sizeof(vqid);
 298	ret = mbox_send_message(ipi->tx_chan, mb_msg);
 299	if (ret < 0)
 300		dev_warn(dev, "failed to send message\n");
 301}
 302
 303/*
 304 * zynqmp_r5_set_mode()
 305 *
 306 * set RPU cluster and TCM operation mode
 307 *
 308 * @r5_core: pointer to zynqmp_r5_core type object
 309 * @fw_reg_val: value expected by firmware to configure RPU cluster mode
 310 * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
 311 *
 312 * Return: 0 for success and < 0 for failure
 313 */
 314static int zynqmp_r5_set_mode(struct zynqmp_r5_core *r5_core,
 315			      enum rpu_oper_mode fw_reg_val,
 316			      enum rpu_tcm_comb tcm_mode)
 317{
 318	int ret;
 319
 320	ret = zynqmp_pm_set_rpu_mode(r5_core->pm_domain_id, fw_reg_val);
 321	if (ret < 0) {
 322		dev_err(r5_core->dev, "failed to set RPU mode\n");
 323		return ret;
 324	}
 325
 326	ret = zynqmp_pm_set_tcm_config(r5_core->pm_domain_id, tcm_mode);
 327	if (ret < 0)
 328		dev_err(r5_core->dev, "failed to configure TCM\n");
 329
 330	return ret;
 331}
 332
 333/*
 334 * zynqmp_r5_rproc_start()
 335 * @rproc: single R5 core's corresponding rproc instance
 336 *
 337 * Start R5 Core from designated boot address.
 338 *
 339 * return 0 on success, otherwise non-zero value on failure
 340 */
 341static int zynqmp_r5_rproc_start(struct rproc *rproc)
 342{
 343	struct zynqmp_r5_core *r5_core = rproc->priv;
 344	enum rpu_boot_mem bootmem;
 345	int ret;
 346
 347	/*
 348	 * The exception vector pointers (EVP) refer to the base-address of
 349	 * exception vectors (for reset, IRQ, FIQ, etc). The reset-vector
 350	 * starts at the base-address and subsequent vectors are on 4-byte
 351	 * boundaries.
 352	 *
 353	 * Exception vectors can start either from 0x0000_0000 (LOVEC) or
 354	 * from 0xFFFF_0000 (HIVEC) which is mapped in the OCM (On-Chip Memory)
 355	 *
 356	 * Usually firmware will put Exception vectors at LOVEC.
 357	 *
 358	 * It is not recommend that you change the exception vector.
 359	 * Changing the EVP to HIVEC will result in increased interrupt latency
 360	 * and jitter. Also, if the OCM is secured and the Cortex-R5F processor
 361	 * is non-secured, then the Cortex-R5F processor cannot access the
 362	 * HIVEC exception vectors in the OCM.
 363	 */
 364	bootmem = (rproc->bootaddr >= 0xFFFC0000) ?
 365		   PM_RPU_BOOTMEM_HIVEC : PM_RPU_BOOTMEM_LOVEC;
 366
 367	dev_dbg(r5_core->dev, "RPU boot addr 0x%llx from %s.", rproc->bootaddr,
 368		bootmem == PM_RPU_BOOTMEM_HIVEC ? "OCM" : "TCM");
 369
 370	ret = zynqmp_pm_request_wake(r5_core->pm_domain_id, 1,
 371				     bootmem, ZYNQMP_PM_REQUEST_ACK_NO);
 372	if (ret)
 373		dev_err(r5_core->dev,
 374			"failed to start RPU = 0x%x\n", r5_core->pm_domain_id);
 375	return ret;
 376}
 377
 378/*
 379 * zynqmp_r5_rproc_stop()
 380 * @rproc: single R5 core's corresponding rproc instance
 381 *
 382 * Power down  R5 Core.
 383 *
 384 * return 0 on success, otherwise non-zero value on failure
 385 */
 386static int zynqmp_r5_rproc_stop(struct rproc *rproc)
 387{
 388	struct zynqmp_r5_core *r5_core = rproc->priv;
 389	int ret;
 390
 391	ret = zynqmp_pm_force_pwrdwn(r5_core->pm_domain_id,
 392				     ZYNQMP_PM_REQUEST_ACK_BLOCKING);
 393	if (ret)
 394		dev_err(r5_core->dev, "failed to stop remoteproc RPU %d\n", ret);
 395
 396	return ret;
 397}
 398
 399/*
 400 * zynqmp_r5_mem_region_map()
 401 * @rproc: single R5 core's corresponding rproc instance
 402 * @mem: mem descriptor to map reserved memory-regions
 403 *
 404 * Callback to map va for memory-region's carveout.
 405 *
 406 * return 0 on success, otherwise non-zero value on failure
 407 */
 408static int zynqmp_r5_mem_region_map(struct rproc *rproc,
 409				    struct rproc_mem_entry *mem)
 410{
 411	void __iomem *va;
 412
 413	va = ioremap_wc(mem->dma, mem->len);
 414	if (IS_ERR_OR_NULL(va))
 415		return -ENOMEM;
 416
 417	mem->va = (void *)va;
 418
 419	return 0;
 420}
 421
 422/*
 423 * zynqmp_r5_rproc_mem_unmap
 424 * @rproc: single R5 core's corresponding rproc instance
 425 * @mem: mem entry to unmap
 426 *
 427 * Unmap memory-region carveout
 428 *
 429 * return: always returns 0
 430 */
 431static int zynqmp_r5_mem_region_unmap(struct rproc *rproc,
 432				      struct rproc_mem_entry *mem)
 433{
 434	iounmap((void __iomem *)mem->va);
 435	return 0;
 436}
 437
 438/*
 439 * add_mem_regions_carveout()
 440 * @rproc: single R5 core's corresponding rproc instance
 441 *
 442 * Construct rproc mem carveouts from memory-region property nodes
 443 *
 444 * return 0 on success, otherwise non-zero value on failure
 445 */
 446static int add_mem_regions_carveout(struct rproc *rproc)
 447{
 448	struct rproc_mem_entry *rproc_mem;
 449	struct zynqmp_r5_core *r5_core;
 450	struct of_phandle_iterator it;
 451	struct reserved_mem *rmem;
 452	int i = 0;
 453
 454	r5_core = rproc->priv;
 455
 456	/* Register associated reserved memory regions */
 457	of_phandle_iterator_init(&it, r5_core->np, "memory-region", NULL, 0);
 458
 459	while (of_phandle_iterator_next(&it) == 0) {
 460		rmem = of_reserved_mem_lookup(it.node);
 461		if (!rmem) {
 462			of_node_put(it.node);
 463			dev_err(&rproc->dev, "unable to acquire memory-region\n");
 464			return -EINVAL;
 465		}
 466
 467		if (!strcmp(it.node->name, "vdev0buffer")) {
 468			/* Init reserved memory for vdev buffer */
 469			rproc_mem = rproc_of_resm_mem_entry_init(&rproc->dev, i,
 470								 rmem->size,
 471								 rmem->base,
 472								 it.node->name);
 473		} else {
 474			/* Register associated reserved memory regions */
 475			rproc_mem = rproc_mem_entry_init(&rproc->dev, NULL,
 476							 (dma_addr_t)rmem->base,
 477							 rmem->size, rmem->base,
 478							 zynqmp_r5_mem_region_map,
 479							 zynqmp_r5_mem_region_unmap,
 480							 it.node->name);
 481		}
 482
 483		if (!rproc_mem) {
 484			of_node_put(it.node);
 485			return -ENOMEM;
 486		}
 487
 488		rproc_add_carveout(rproc, rproc_mem);
 489
 490		dev_dbg(&rproc->dev, "reserved mem carveout %s addr=%llx, size=0x%llx",
 491			it.node->name, rmem->base, rmem->size);
 492		i++;
 493	}
 494
 495	return 0;
 496}
 497
 498/*
 499 * tcm_mem_unmap()
 500 * @rproc: single R5 core's corresponding rproc instance
 501 * @mem: tcm mem entry to unmap
 502 *
 503 * Unmap TCM banks when powering down R5 core.
 504 *
 505 * return always 0
 506 */
 507static int tcm_mem_unmap(struct rproc *rproc, struct rproc_mem_entry *mem)
 508{
 509	iounmap((void __iomem *)mem->va);
 510
 511	return 0;
 512}
 513
 514/*
 515 * tcm_mem_map()
 516 * @rproc: single R5 core's corresponding rproc instance
 517 * @mem: tcm memory entry descriptor
 518 *
 519 * Given TCM bank entry, this func setup virtual address for TCM bank
 520 * remoteproc carveout. It also takes care of va to da address translation
 521 *
 522 * return 0 on success, otherwise non-zero value on failure
 523 */
 524static int tcm_mem_map(struct rproc *rproc,
 525		       struct rproc_mem_entry *mem)
 526{
 527	void __iomem *va;
 528
 529	va = ioremap_wc(mem->dma, mem->len);
 530	if (IS_ERR_OR_NULL(va))
 531		return -ENOMEM;
 532
 533	/* Update memory entry va */
 534	mem->va = (void *)va;
 535
 536	/* clear TCMs */
 537	memset_io(va, 0, mem->len);
 538
 539	return 0;
 540}
 541
 542/*
 543 * add_tcm_carveout_split_mode()
 544 * @rproc: single R5 core's corresponding rproc instance
 545 *
 546 * allocate and add remoteproc carveout for TCM memory in split mode
 547 *
 548 * return 0 on success, otherwise non-zero value on failure
 549 */
 550static int add_tcm_carveout_split_mode(struct rproc *rproc)
 551{
 552	struct rproc_mem_entry *rproc_mem;
 553	struct zynqmp_r5_core *r5_core;
 554	int i, num_banks, ret;
 555	phys_addr_t bank_addr;
 556	struct device *dev;
 557	u32 pm_domain_id;
 558	size_t bank_size;
 559	char *bank_name;
 560	u32 da;
 561
 562	r5_core = rproc->priv;
 563	dev = r5_core->dev;
 564	num_banks = r5_core->tcm_bank_count;
 565
 566	/*
 567	 * Power-on Each 64KB TCM,
 568	 * register its address space, map and unmap functions
 569	 * and add carveouts accordingly
 570	 */
 571	for (i = 0; i < num_banks; i++) {
 572		bank_addr = r5_core->tcm_banks[i]->addr;
 573		da = r5_core->tcm_banks[i]->da;
 574		bank_name = r5_core->tcm_banks[i]->bank_name;
 575		bank_size = r5_core->tcm_banks[i]->size;
 576		pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
 577
 578		ret = zynqmp_pm_request_node(pm_domain_id,
 579					     ZYNQMP_PM_CAPABILITY_ACCESS, 0,
 580					     ZYNQMP_PM_REQUEST_ACK_BLOCKING);
 581		if (ret < 0) {
 582			dev_err(dev, "failed to turn on TCM 0x%x", pm_domain_id);
 583			goto release_tcm_split;
 584		}
 585
 586		dev_dbg(dev, "TCM carveout split mode %s addr=%llx, da=0x%x, size=0x%lx",
 587			bank_name, bank_addr, da, bank_size);
 588
 589		rproc_mem = rproc_mem_entry_init(dev, NULL, bank_addr,
 590						 bank_size, da,
 591						 tcm_mem_map, tcm_mem_unmap,
 592						 bank_name);
 593		if (!rproc_mem) {
 594			ret = -ENOMEM;
 595			zynqmp_pm_release_node(pm_domain_id);
 596			goto release_tcm_split;
 597		}
 598
 599		rproc_add_carveout(rproc, rproc_mem);
 600	}
 601
 602	return 0;
 603
 604release_tcm_split:
 605	/* If failed, Turn off all TCM banks turned on before */
 606	for (i--; i >= 0; i--) {
 607		pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
 608		zynqmp_pm_release_node(pm_domain_id);
 609	}
 610	return ret;
 611}
 612
 613/*
 614 * add_tcm_carveout_lockstep_mode()
 615 * @rproc: single R5 core's corresponding rproc instance
 616 *
 617 * allocate and add remoteproc carveout for TCM memory in lockstep mode
 618 *
 619 * return 0 on success, otherwise non-zero value on failure
 620 */
 621static int add_tcm_carveout_lockstep_mode(struct rproc *rproc)
 622{
 623	struct rproc_mem_entry *rproc_mem;
 624	struct zynqmp_r5_core *r5_core;
 625	int i, num_banks, ret;
 626	phys_addr_t bank_addr;
 627	size_t bank_size = 0;
 628	struct device *dev;
 629	u32 pm_domain_id;
 630	char *bank_name;
 631	u32 da;
 632
 633	r5_core = rproc->priv;
 634	dev = r5_core->dev;
 635
 636	/* Go through zynqmp banks for r5 node */
 637	num_banks = r5_core->tcm_bank_count;
 638
 639	/*
 640	 * In lockstep mode, TCM is contiguous memory block
 641	 * However, each TCM block still needs to be enabled individually.
 642	 * So, Enable each TCM block individually.
 643	 * Although ATCM and BTCM is contiguous memory block, add two separate
 644	 * carveouts for both.
 645	 */
 646	for (i = 0; i < num_banks; i++) {
 647		pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
 648
 649		/* Turn on each TCM bank individually */
 650		ret = zynqmp_pm_request_node(pm_domain_id,
 651					     ZYNQMP_PM_CAPABILITY_ACCESS, 0,
 652					     ZYNQMP_PM_REQUEST_ACK_BLOCKING);
 653		if (ret < 0) {
 654			dev_err(dev, "failed to turn on TCM 0x%x", pm_domain_id);
 655			goto release_tcm_lockstep;
 656		}
 657
 658		bank_size = r5_core->tcm_banks[i]->size;
 659		if (bank_size == 0)
 660			continue;
 661
 662		bank_addr = r5_core->tcm_banks[i]->addr;
 663		da = r5_core->tcm_banks[i]->da;
 664		bank_name = r5_core->tcm_banks[i]->bank_name;
 665
 666		/* Register TCM address range, TCM map and unmap functions */
 667		rproc_mem = rproc_mem_entry_init(dev, NULL, bank_addr,
 668						 bank_size, da,
 669						 tcm_mem_map, tcm_mem_unmap,
 670						 bank_name);
 671		if (!rproc_mem) {
 672			ret = -ENOMEM;
 673			zynqmp_pm_release_node(pm_domain_id);
 674			goto release_tcm_lockstep;
 675		}
 676
 677		/* If registration is success, add carveouts */
 678		rproc_add_carveout(rproc, rproc_mem);
 679
 680		dev_dbg(dev, "TCM carveout lockstep mode %s addr=0x%llx, da=0x%x, size=0x%lx",
 681			bank_name, bank_addr, da, bank_size);
 682	}
 683
 684	return 0;
 685
 686release_tcm_lockstep:
 687	/* If failed, Turn off all TCM banks turned on before */
 688	for (i--; i >= 0; i--) {
 689		pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
 690		zynqmp_pm_release_node(pm_domain_id);
 691	}
 692	return ret;
 693}
 694
 695/*
 696 * add_tcm_banks()
 697 * @rproc: single R5 core's corresponding rproc instance
 698 *
 699 * allocate and add remoteproc carveouts for TCM memory based on cluster mode
 700 *
 701 * return 0 on success, otherwise non-zero value on failure
 702 */
 703static int add_tcm_banks(struct rproc *rproc)
 704{
 705	struct zynqmp_r5_cluster *cluster;
 706	struct zynqmp_r5_core *r5_core;
 707	struct device *dev;
 708
 709	r5_core = rproc->priv;
 710	if (!r5_core)
 711		return -EINVAL;
 712
 713	dev = r5_core->dev;
 714
 715	cluster = dev_get_drvdata(dev->parent);
 716	if (!cluster) {
 717		dev_err(dev->parent, "Invalid driver data\n");
 718		return -EINVAL;
 719	}
 720
 721	/*
 722	 * In lockstep mode TCM banks are one contiguous memory region of 256Kb
 723	 * In split mode, each TCM bank is 64Kb and not contiguous.
 724	 * We add memory carveouts accordingly.
 725	 */
 726	if (cluster->mode == SPLIT_MODE)
 727		return add_tcm_carveout_split_mode(rproc);
 728	else if (cluster->mode == LOCKSTEP_MODE)
 729		return add_tcm_carveout_lockstep_mode(rproc);
 730
 731	return -EINVAL;
 732}
 733
 734/*
 735 * zynqmp_r5_parse_fw()
 736 * @rproc: single R5 core's corresponding rproc instance
 737 * @fw: ptr to firmware to be loaded onto r5 core
 738 *
 739 * get resource table if available
 740 *
 741 * return 0 on success, otherwise non-zero value on failure
 742 */
 743static int zynqmp_r5_parse_fw(struct rproc *rproc, const struct firmware *fw)
 744{
 745	int ret;
 746
 747	ret = rproc_elf_load_rsc_table(rproc, fw);
 748	if (ret == -EINVAL) {
 749		/*
 750		 * resource table only required for IPC.
 751		 * if not present, this is not necessarily an error;
 752		 * for example, loading r5 hello world application
 753		 * so simply inform user and keep going.
 754		 */
 755		dev_info(&rproc->dev, "no resource table found.\n");
 756		ret = 0;
 757	}
 758	return ret;
 759}
 760
 761/**
 762 * zynqmp_r5_rproc_prepare()
 763 * adds carveouts for TCM bank and reserved memory regions
 764 *
 765 * @rproc: Device node of each rproc
 766 *
 767 * Return: 0 for success else < 0 error code
 768 */
 769static int zynqmp_r5_rproc_prepare(struct rproc *rproc)
 770{
 771	int ret;
 772
 773	ret = add_tcm_banks(rproc);
 774	if (ret) {
 775		dev_err(&rproc->dev, "failed to get TCM banks, err %d\n", ret);
 776		return ret;
 777	}
 778
 779	ret = add_mem_regions_carveout(rproc);
 780	if (ret) {
 781		dev_err(&rproc->dev, "failed to get reserve mem regions %d\n", ret);
 782		return ret;
 783	}
 784
 785	return 0;
 786}
 787
 788/**
 789 * zynqmp_r5_rproc_unprepare()
 790 * Turns off TCM banks using power-domain id
 791 *
 792 * @rproc: Device node of each rproc
 793 *
 794 * Return: always 0
 795 */
 796static int zynqmp_r5_rproc_unprepare(struct rproc *rproc)
 797{
 798	struct zynqmp_r5_core *r5_core;
 799	u32 pm_domain_id;
 800	int i;
 801
 802	r5_core = rproc->priv;
 803
 804	for (i = 0; i < r5_core->tcm_bank_count; i++) {
 805		pm_domain_id = r5_core->tcm_banks[i]->pm_domain_id;
 806		if (zynqmp_pm_release_node(pm_domain_id))
 807			dev_warn(r5_core->dev,
 808				 "can't turn off TCM bank 0x%x", pm_domain_id);
 809	}
 810
 811	return 0;
 812}
 813
 814static const struct rproc_ops zynqmp_r5_rproc_ops = {
 815	.prepare	= zynqmp_r5_rproc_prepare,
 816	.unprepare	= zynqmp_r5_rproc_unprepare,
 817	.start		= zynqmp_r5_rproc_start,
 818	.stop		= zynqmp_r5_rproc_stop,
 819	.load		= rproc_elf_load_segments,
 820	.parse_fw	= zynqmp_r5_parse_fw,
 821	.find_loaded_rsc_table = rproc_elf_find_loaded_rsc_table,
 822	.sanity_check	= rproc_elf_sanity_check,
 823	.get_boot_addr	= rproc_elf_get_boot_addr,
 824	.kick		= zynqmp_r5_rproc_kick,
 825};
 826
 827/**
 828 * zynqmp_r5_add_rproc_core()
 829 * Allocate and add struct rproc object for each r5f core
 830 * This is called for each individual r5f core
 831 *
 832 * @cdev: Device node of each r5 core
 833 *
 834 * Return: zynqmp_r5_core object for success else error code pointer
 835 */
 836static struct zynqmp_r5_core *zynqmp_r5_add_rproc_core(struct device *cdev)
 837{
 838	struct zynqmp_r5_core *r5_core;
 839	struct rproc *r5_rproc;
 840	int ret;
 841
 842	/* Set up DMA mask */
 843	ret = dma_set_coherent_mask(cdev, DMA_BIT_MASK(32));
 844	if (ret)
 845		return ERR_PTR(ret);
 846
 847	/* Allocate remoteproc instance */
 848	r5_rproc = rproc_alloc(cdev, dev_name(cdev),
 849			       &zynqmp_r5_rproc_ops,
 850			       NULL, sizeof(struct zynqmp_r5_core));
 851	if (!r5_rproc) {
 852		dev_err(cdev, "failed to allocate memory for rproc instance\n");
 853		return ERR_PTR(-ENOMEM);
 854	}
 855
 856	r5_rproc->auto_boot = false;
 857	r5_core = r5_rproc->priv;
 858	r5_core->dev = cdev;
 859	r5_core->np = dev_of_node(cdev);
 860	if (!r5_core->np) {
 861		dev_err(cdev, "can't get device node for r5 core\n");
 862		ret = -EINVAL;
 863		goto free_rproc;
 864	}
 865
 866	/* Add R5 remoteproc core */
 867	ret = rproc_add(r5_rproc);
 868	if (ret) {
 869		dev_err(cdev, "failed to add r5 remoteproc\n");
 870		goto free_rproc;
 871	}
 872
 873	r5_core->rproc = r5_rproc;
 874	return r5_core;
 875
 876free_rproc:
 877	rproc_free(r5_rproc);
 878	return ERR_PTR(ret);
 879}
 880
 881/**
 882 * zynqmp_r5_get_tcm_node()
 883 * Ideally this function should parse tcm node and store information
 884 * in r5_core instance. For now, Hardcoded TCM information is used.
 885 * This approach is used as TCM bindings for system-dt is being developed
 886 *
 887 * @cluster: pointer to zynqmp_r5_cluster type object
 888 *
 889 * Return: 0 for success and < 0 error code for failure.
 890 */
 891static int zynqmp_r5_get_tcm_node(struct zynqmp_r5_cluster *cluster)
 892{
 893	const struct mem_bank_data *zynqmp_tcm_banks;
 894	struct device *dev = cluster->dev;
 895	struct zynqmp_r5_core *r5_core;
 896	int tcm_bank_count, tcm_node;
 897	int i, j;
 898
 899	if (cluster->mode == SPLIT_MODE) {
 900		zynqmp_tcm_banks = zynqmp_tcm_banks_split;
 901		tcm_bank_count = ARRAY_SIZE(zynqmp_tcm_banks_split);
 902	} else {
 903		zynqmp_tcm_banks = zynqmp_tcm_banks_lockstep;
 904		tcm_bank_count = ARRAY_SIZE(zynqmp_tcm_banks_lockstep);
 905	}
 906
 907	/* count per core tcm banks */
 908	tcm_bank_count = tcm_bank_count / cluster->core_count;
 909
 910	/*
 911	 * r5 core 0 will use all of TCM banks in lockstep mode.
 912	 * In split mode, r5 core0 will use 128k and r5 core1 will use another
 913	 * 128k. Assign TCM banks to each core accordingly
 914	 */
 915	tcm_node = 0;
 916	for (i = 0; i < cluster->core_count; i++) {
 917		r5_core = cluster->r5_cores[i];
 918		r5_core->tcm_banks = devm_kcalloc(dev, tcm_bank_count,
 919						  sizeof(struct mem_bank_data *),
 920						  GFP_KERNEL);
 921		if (!r5_core->tcm_banks)
 922			return -ENOMEM;
 923
 924		for (j = 0; j < tcm_bank_count; j++) {
 925			/*
 926			 * Use pre-defined TCM reg values.
 927			 * Eventually this should be replaced by values
 928			 * parsed from dts.
 929			 */
 930			r5_core->tcm_banks[j] =
 931				(struct mem_bank_data *)&zynqmp_tcm_banks[tcm_node];
 932			tcm_node++;
 933		}
 934
 935		r5_core->tcm_bank_count = tcm_bank_count;
 936	}
 937
 938	return 0;
 939}
 940
 941/*
 942 * zynqmp_r5_core_init()
 943 * Create and initialize zynqmp_r5_core type object
 944 *
 945 * @cluster: pointer to zynqmp_r5_cluster type object
 946 * @fw_reg_val: value expected by firmware to configure RPU cluster mode
 947 * @tcm_mode: value expected by fw to configure TCM mode (lockstep or split)
 948 *
 949 * Return: 0 for success and error code for failure.
 950 */
 951static int zynqmp_r5_core_init(struct zynqmp_r5_cluster *cluster,
 952			       enum rpu_oper_mode fw_reg_val,
 953			       enum rpu_tcm_comb tcm_mode)
 954{
 955	struct device *dev = cluster->dev;
 956	struct zynqmp_r5_core *r5_core;
 957	int ret, i;
 958
 959	ret = zynqmp_r5_get_tcm_node(cluster);
 960	if (ret < 0) {
 961		dev_err(dev, "can't get tcm node, err %d\n", ret);
 962		return ret;
 963	}
 964
 965	for (i = 0; i < cluster->core_count; i++) {
 966		r5_core = cluster->r5_cores[i];
 967
 968		/* Initialize r5 cores with power-domains parsed from dts */
 969		ret = of_property_read_u32_index(r5_core->np, "power-domains",
 970						 1, &r5_core->pm_domain_id);
 971		if (ret) {
 972			dev_err(dev, "failed to get power-domains property\n");
 973			return ret;
 974		}
 975
 976		ret = zynqmp_r5_set_mode(r5_core, fw_reg_val, tcm_mode);
 977		if (ret) {
 978			dev_err(dev, "failed to set r5 cluster mode %d, err %d\n",
 979				cluster->mode, ret);
 980			return ret;
 981		}
 982	}
 983
 984	return 0;
 985}
 986
 987/*
 988 * zynqmp_r5_cluster_init()
 989 * Create and initialize zynqmp_r5_cluster type object
 990 *
 991 * @cluster: pointer to zynqmp_r5_cluster type object
 992 *
 993 * Return: 0 for success and error code for failure.
 994 */
 995static int zynqmp_r5_cluster_init(struct zynqmp_r5_cluster *cluster)
 996{
 997	enum zynqmp_r5_cluster_mode cluster_mode = LOCKSTEP_MODE;
 998	struct device *dev = cluster->dev;
 999	struct device_node *dev_node = dev_of_node(dev);
1000	struct platform_device *child_pdev;
1001	struct zynqmp_r5_core **r5_cores;
1002	enum rpu_oper_mode fw_reg_val;
1003	struct device **child_devs;
1004	struct device_node *child;
1005	enum rpu_tcm_comb tcm_mode;
1006	int core_count, ret, i;
1007	struct mbox_info *ipi;
1008
1009	ret = of_property_read_u32(dev_node, "xlnx,cluster-mode", &cluster_mode);
1010
1011	/*
1012	 * on success returns 0, if not defined then returns -EINVAL,
1013	 * In that case, default is LOCKSTEP mode. Other than that
1014	 * returns relative error code < 0.
1015	 */
1016	if (ret != -EINVAL && ret != 0) {
1017		dev_err(dev, "Invalid xlnx,cluster-mode property\n");
1018		return ret;
1019	}
1020
1021	/*
1022	 * For now driver only supports split mode and lockstep mode.
1023	 * fail driver probe if either of that is not set in dts.
1024	 */
1025	if (cluster_mode == LOCKSTEP_MODE) {
1026		tcm_mode = PM_RPU_TCM_COMB;
1027		fw_reg_val = PM_RPU_MODE_LOCKSTEP;
1028	} else if (cluster_mode == SPLIT_MODE) {
1029		tcm_mode = PM_RPU_TCM_SPLIT;
1030		fw_reg_val = PM_RPU_MODE_SPLIT;
1031	} else {
1032		dev_err(dev, "driver does not support cluster mode %d\n", cluster_mode);
1033		return -EINVAL;
1034	}
1035
1036	/*
1037	 * Number of cores is decided by number of child nodes of
1038	 * r5f subsystem node in dts. If Split mode is used in dts
1039	 * 2 child nodes are expected.
1040	 * In lockstep mode if two child nodes are available,
1041	 * only use first child node and consider it as core0
1042	 * and ignore core1 dt node.
1043	 */
1044	core_count = of_get_available_child_count(dev_node);
1045	if (core_count == 0) {
1046		dev_err(dev, "Invalid number of r5 cores %d", core_count);
1047		return -EINVAL;
1048	} else if (cluster_mode == SPLIT_MODE && core_count != 2) {
1049		dev_err(dev, "Invalid number of r5 cores for split mode\n");
1050		return -EINVAL;
1051	} else if (cluster_mode == LOCKSTEP_MODE && core_count == 2) {
1052		dev_warn(dev, "Only r5 core0 will be used\n");
1053		core_count = 1;
1054	}
1055
1056	child_devs = kcalloc(core_count, sizeof(struct device *), GFP_KERNEL);
1057	if (!child_devs)
1058		return -ENOMEM;
1059
1060	r5_cores = kcalloc(core_count,
1061			   sizeof(struct zynqmp_r5_core *), GFP_KERNEL);
1062	if (!r5_cores) {
1063		kfree(child_devs);
1064		return -ENOMEM;
1065	}
1066
1067	i = 0;
1068	for_each_available_child_of_node(dev_node, child) {
1069		child_pdev = of_find_device_by_node(child);
1070		if (!child_pdev) {
1071			of_node_put(child);
1072			ret = -ENODEV;
1073			goto release_r5_cores;
1074		}
1075
1076		child_devs[i] = &child_pdev->dev;
1077
1078		/* create and add remoteproc instance of type struct rproc */
1079		r5_cores[i] = zynqmp_r5_add_rproc_core(&child_pdev->dev);
1080		if (IS_ERR(r5_cores[i])) {
1081			of_node_put(child);
1082			ret = PTR_ERR(r5_cores[i]);
1083			r5_cores[i] = NULL;
1084			goto release_r5_cores;
1085		}
1086
1087		/*
1088		 * If mailbox nodes are disabled using "status" property then
1089		 * setting up mailbox channels will fail.
1090		 */
1091		ipi = zynqmp_r5_setup_mbox(&child_pdev->dev);
1092		if (ipi) {
1093			r5_cores[i]->ipi = ipi;
1094			ipi->r5_core = r5_cores[i];
1095		}
1096
1097		/*
1098		 * If two child nodes are available in dts in lockstep mode,
1099		 * then ignore second child node.
1100		 */
1101		if (cluster_mode == LOCKSTEP_MODE) {
1102			of_node_put(child);
1103			break;
1104		}
1105
1106		i++;
1107	}
1108
1109	cluster->mode = cluster_mode;
1110	cluster->core_count = core_count;
1111	cluster->r5_cores = r5_cores;
1112
1113	ret = zynqmp_r5_core_init(cluster, fw_reg_val, tcm_mode);
1114	if (ret < 0) {
1115		dev_err(dev, "failed to init r5 core err %d\n", ret);
1116		cluster->core_count = 0;
1117		cluster->r5_cores = NULL;
1118
1119		/*
1120		 * at this point rproc resources for each core are allocated.
1121		 * adjust index to free resources in reverse order
1122		 */
1123		i = core_count - 1;
1124		goto release_r5_cores;
1125	}
1126
1127	kfree(child_devs);
1128	return 0;
1129
1130release_r5_cores:
1131	while (i >= 0) {
1132		put_device(child_devs[i]);
1133		if (r5_cores[i]) {
1134			zynqmp_r5_free_mbox(r5_cores[i]->ipi);
1135			of_reserved_mem_device_release(r5_cores[i]->dev);
1136			rproc_del(r5_cores[i]->rproc);
1137			rproc_free(r5_cores[i]->rproc);
1138		}
1139		i--;
1140	}
1141	kfree(r5_cores);
1142	kfree(child_devs);
1143	return ret;
1144}
1145
1146static void zynqmp_r5_cluster_exit(void *data)
1147{
1148	struct platform_device *pdev = data;
1149	struct zynqmp_r5_cluster *cluster;
1150	struct zynqmp_r5_core *r5_core;
1151	int i;
1152
1153	cluster = platform_get_drvdata(pdev);
1154	if (!cluster)
1155		return;
1156
1157	for (i = 0; i < cluster->core_count; i++) {
1158		r5_core = cluster->r5_cores[i];
1159		zynqmp_r5_free_mbox(r5_core->ipi);
1160		of_reserved_mem_device_release(r5_core->dev);
1161		put_device(r5_core->dev);
1162		rproc_del(r5_core->rproc);
1163		rproc_free(r5_core->rproc);
1164	}
1165
1166	kfree(cluster->r5_cores);
1167	kfree(cluster);
1168	platform_set_drvdata(pdev, NULL);
1169}
1170
1171/*
1172 * zynqmp_r5_remoteproc_probe()
1173 * parse device-tree, initialize hardware and allocate required resources
1174 * and remoteproc ops
1175 *
1176 * @pdev: domain platform device for R5 cluster
1177 *
1178 * Return: 0 for success and < 0 for failure.
1179 */
1180static int zynqmp_r5_remoteproc_probe(struct platform_device *pdev)
1181{
1182	struct zynqmp_r5_cluster *cluster;
1183	struct device *dev = &pdev->dev;
1184	int ret;
1185
1186	cluster = kzalloc(sizeof(*cluster), GFP_KERNEL);
1187	if (!cluster)
1188		return -ENOMEM;
1189
1190	cluster->dev = dev;
1191
1192	ret = devm_of_platform_populate(dev);
1193	if (ret) {
1194		dev_err_probe(dev, ret, "failed to populate platform dev\n");
1195		kfree(cluster);
1196		return ret;
1197	}
1198
1199	/* wire in so each core can be cleaned up at driver remove */
1200	platform_set_drvdata(pdev, cluster);
1201
1202	ret = zynqmp_r5_cluster_init(cluster);
1203	if (ret) {
1204		kfree(cluster);
1205		platform_set_drvdata(pdev, NULL);
1206		dev_err_probe(dev, ret, "Invalid r5f subsystem device tree\n");
1207		return ret;
1208	}
1209
1210	ret = devm_add_action_or_reset(dev, zynqmp_r5_cluster_exit, pdev);
1211	if (ret)
1212		return ret;
1213
1214	return 0;
1215}
1216
1217/* Match table for OF platform binding */
1218static const struct of_device_id zynqmp_r5_remoteproc_match[] = {
1219	{ .compatible = "xlnx,zynqmp-r5fss", },
1220	{ /* end of list */ },
1221};
1222MODULE_DEVICE_TABLE(of, zynqmp_r5_remoteproc_match);
1223
1224static struct platform_driver zynqmp_r5_remoteproc_driver = {
1225	.probe = zynqmp_r5_remoteproc_probe,
1226	.driver = {
1227		.name = "zynqmp_r5_remoteproc",
1228		.of_match_table = zynqmp_r5_remoteproc_match,
1229	},
1230};
1231module_platform_driver(zynqmp_r5_remoteproc_driver);
1232
1233MODULE_DESCRIPTION("Xilinx R5F remote processor driver");
1234MODULE_AUTHOR("Xilinx Inc.");
1235MODULE_LICENSE("GPL");