brintos

brintos / linux-shallow public Read only

0
0
Text · 27.5 KiB · 521d08b Raw
1040 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Xilinx Inter Processor Interrupt(IPI) Mailbox Driver4 *5 * Copyright (C) 2018 Xilinx, Inc.6 */7 8#include <linux/arm-smccc.h>9#include <linux/cpuhotplug.h>10#include <linux/delay.h>11#include <linux/device.h>12#include <linux/interrupt.h>13#include <linux/irqdomain.h>14#include <linux/io.h>15#include <linux/kernel.h>16#include <linux/mailbox_controller.h>17#include <linux/mailbox/zynqmp-ipi-message.h>18#include <linux/module.h>19#include <linux/of.h>20#include <linux/of_address.h>21#include <linux/of_irq.h>22#include <linux/platform_device.h>23 24/* IPI agent ID any */25#define IPI_ID_ANY 0xFFUL26 27/* indicate if ZynqMP IPI mailbox driver uses SMC calls or HVC calls */28#define USE_SMC 029#define USE_HVC 130 31/* Default IPI SMC function IDs */32#define SMC_IPI_MAILBOX_OPEN		0x82001000U33#define SMC_IPI_MAILBOX_RELEASE		0x82001001U34#define SMC_IPI_MAILBOX_STATUS_ENQUIRY	0x82001002U35#define SMC_IPI_MAILBOX_NOTIFY		0x82001003U36#define SMC_IPI_MAILBOX_ACK		0x82001004U37#define SMC_IPI_MAILBOX_ENABLE_IRQ	0x82001005U38#define SMC_IPI_MAILBOX_DISABLE_IRQ	0x82001006U39 40/* IPI SMC Macros */41#define IPI_SMC_ENQUIRY_DIRQ_MASK	0x00000001UL /* Flag to indicate if42						      * notification interrupt43						      * to be disabled.44						      */45#define IPI_SMC_ACK_EIRQ_MASK		0x00000001UL /* Flag to indicate if46						      * notification interrupt47						      * to be enabled.48						      */49 50/* IPI mailbox status */51#define IPI_MB_STATUS_IDLE		052#define IPI_MB_STATUS_SEND_PENDING	153#define IPI_MB_STATUS_RECV_PENDING	254 55#define IPI_MB_CHNL_TX	0 /* IPI mailbox TX channel */56#define IPI_MB_CHNL_RX	1 /* IPI mailbox RX channel */57 58/* IPI Message Buffer Information */59#define RESP_OFFSET	0x20U60#define DEST_OFFSET	0x40U61#define IPI_BUF_SIZE	0x20U62#define DST_BIT_POS	9U63#define SRC_BITMASK	GENMASK(11, 8)64 65#define MAX_SGI 1666 67/*68 * Module parameters69 */70static int tx_poll_period = 5;71module_param_named(tx_poll_period, tx_poll_period, int, 0644);72MODULE_PARM_DESC(tx_poll_period, "Poll period waiting for ack after send.");73 74/**75 * struct zynqmp_ipi_mchan - Description of a Xilinx ZynqMP IPI mailbox channel76 * @is_opened: indicate if the IPI channel is opened77 * @req_buf: local to remote request buffer start address78 * @resp_buf: local to remote response buffer start address79 * @req_buf_size: request buffer size80 * @resp_buf_size: response buffer size81 * @rx_buf: receive buffer to pass received message to client82 * @chan_type: channel type83 */84struct zynqmp_ipi_mchan {85	int is_opened;86	void __iomem *req_buf;87	void __iomem *resp_buf;88	void *rx_buf;89	size_t req_buf_size;90	size_t resp_buf_size;91	unsigned int chan_type;92};93 94struct zynqmp_ipi_mbox;95 96typedef int (*setup_ipi_fn)(struct zynqmp_ipi_mbox *ipi_mbox, struct device_node *node);97 98/**99 * struct zynqmp_ipi_mbox - Description of a ZynqMP IPI mailbox100 *                          platform data.101 * @pdata:		  pointer to the IPI private data102 * @dev:                  device pointer corresponding to the Xilinx ZynqMP103 *                        IPI mailbox104 * @remote_id:            remote IPI agent ID105 * @mbox:                 mailbox Controller106 * @mchans:               array for channels, tx channel and rx channel.107 * @setup_ipi_fn:         Function Pointer to set up IPI Channels108 */109struct zynqmp_ipi_mbox {110	struct zynqmp_ipi_pdata *pdata;111	struct device dev;112	u32 remote_id;113	struct mbox_controller mbox;114	struct zynqmp_ipi_mchan mchans[2];115	setup_ipi_fn setup_ipi_fn;116};117 118/**119 * struct zynqmp_ipi_pdata - Description of z ZynqMP IPI agent platform data.120 *121 * @dev:                  device pointer corresponding to the Xilinx ZynqMP122 *                        IPI agent123 * @irq:                  IPI agent interrupt ID124 * @method:               IPI SMC or HVC is going to be used125 * @local_id:             local IPI agent ID126 * @virq_sgi:             IRQ number mapped to SGI127 * @num_mboxes:           number of mailboxes of this IPI agent128 * @ipi_mboxes:           IPI mailboxes of this IPI agent129 */130struct zynqmp_ipi_pdata {131	struct device *dev;132	int irq;133	unsigned int method;134	u32 local_id;135	int virq_sgi;136	int num_mboxes;137	struct zynqmp_ipi_mbox ipi_mboxes[] __counted_by(num_mboxes);138};139 140static DEFINE_PER_CPU(struct zynqmp_ipi_pdata *, per_cpu_pdata);141 142static struct device_driver zynqmp_ipi_mbox_driver = {143	.owner = THIS_MODULE,144	.name = "zynqmp-ipi-mbox",145};146 147static void zynqmp_ipi_fw_call(struct zynqmp_ipi_mbox *ipi_mbox,148			       unsigned long a0, unsigned long a3,149			       struct arm_smccc_res *res)150{151	struct zynqmp_ipi_pdata *pdata = ipi_mbox->pdata;152	unsigned long a1, a2;153 154	a1 = pdata->local_id;155	a2 = ipi_mbox->remote_id;156	if (pdata->method == USE_SMC)157		arm_smccc_smc(a0, a1, a2, a3, 0, 0, 0, 0, res);158	else159		arm_smccc_hvc(a0, a1, a2, a3, 0, 0, 0, 0, res);160}161 162/**163 * zynqmp_ipi_interrupt - Interrupt handler for IPI notification164 *165 * @irq:  Interrupt number166 * @data: ZynqMP IPI mailbox platform data.167 *168 * Return: -EINVAL if there is no instance169 * IRQ_NONE if the interrupt is not ours.170 * IRQ_HANDLED if the rx interrupt was successfully handled.171 */172static irqreturn_t zynqmp_ipi_interrupt(int irq, void *data)173{174	struct zynqmp_ipi_pdata *pdata = data;175	struct mbox_chan *chan;176	struct zynqmp_ipi_mbox *ipi_mbox;177	struct zynqmp_ipi_mchan *mchan;178	struct zynqmp_ipi_message *msg;179	u64 arg0, arg3;180	struct arm_smccc_res res;181	int ret, i, status = IRQ_NONE;182 183	(void)irq;184	arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;185	arg3 = IPI_SMC_ENQUIRY_DIRQ_MASK;186	for (i = 0; i < pdata->num_mboxes; i++) {187		ipi_mbox = &pdata->ipi_mboxes[i];188		mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];189		chan = &ipi_mbox->mbox.chans[IPI_MB_CHNL_RX];190		zynqmp_ipi_fw_call(ipi_mbox, arg0, arg3, &res);191		ret = (int)(res.a0 & 0xFFFFFFFF);192		if (ret > 0 && ret & IPI_MB_STATUS_RECV_PENDING) {193			if (mchan->is_opened) {194				msg = mchan->rx_buf;195				if (msg) {196					msg->len = mchan->req_buf_size;197					memcpy_fromio(msg->data, mchan->req_buf,198						      msg->len);199				}200				mbox_chan_received_data(chan, (void *)msg);201				status = IRQ_HANDLED;202			}203		}204	}205	return status;206}207 208static irqreturn_t zynqmp_sgi_interrupt(int irq, void *data)209{210	struct zynqmp_ipi_pdata **pdata_ptr = data;211	struct zynqmp_ipi_pdata *pdata = *pdata_ptr;212 213	return zynqmp_ipi_interrupt(irq, pdata);214}215 216/**217 * zynqmp_ipi_peek_data - Peek to see if there are any rx messages.218 *219 * @chan: Channel Pointer220 *221 * Return: 'true' if there is pending rx data, 'false' if there is none.222 */223static bool zynqmp_ipi_peek_data(struct mbox_chan *chan)224{225	struct device *dev = chan->mbox->dev;226	struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);227	struct zynqmp_ipi_mchan *mchan = chan->con_priv;228	int ret;229	u64 arg0;230	struct arm_smccc_res res;231 232	if (WARN_ON(!ipi_mbox)) {233		dev_err(dev, "no platform drv data??\n");234		return false;235	}236 237	arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;238	zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);239	ret = (int)(res.a0 & 0xFFFFFFFF);240 241	if (mchan->chan_type == IPI_MB_CHNL_TX) {242		/* TX channel, check if the message has been acked243		 * by the remote, if yes, response is available.244		 */245		if (ret < 0 || ret & IPI_MB_STATUS_SEND_PENDING)246			return false;247		else248			return true;249	} else if (ret > 0 && ret & IPI_MB_STATUS_RECV_PENDING) {250		/* RX channel, check if there is message arrived. */251		return true;252	}253	return false;254}255 256/**257 * zynqmp_ipi_last_tx_done - See if the last tx message is sent258 *259 * @chan: Channel pointer260 *261 * Return: 'true' is no pending tx data, 'false' if there are any.262 */263static bool zynqmp_ipi_last_tx_done(struct mbox_chan *chan)264{265	struct device *dev = chan->mbox->dev;266	struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);267	struct zynqmp_ipi_mchan *mchan = chan->con_priv;268	int ret;269	u64 arg0;270	struct arm_smccc_res res;271 272	if (WARN_ON(!ipi_mbox)) {273		dev_err(dev, "no platform drv data??\n");274		return false;275	}276 277	if (mchan->chan_type == IPI_MB_CHNL_TX) {278		/* We only need to check if the message been taken279		 * by the remote in the TX channel280		 */281		arg0 = SMC_IPI_MAILBOX_STATUS_ENQUIRY;282		zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);283		/* Check the SMC call status, a0 of the result */284		ret = (int)(res.a0 & 0xFFFFFFFF);285		if (ret < 0 || ret & IPI_MB_STATUS_SEND_PENDING)286			return false;287		return true;288	}289	/* Always true for the response message in RX channel */290	return true;291}292 293/**294 * zynqmp_ipi_send_data - Send data295 *296 * @chan: Channel Pointer297 * @data: Message Pointer298 *299 * Return: 0 if all goes good, else appropriate error messages.300 */301static int zynqmp_ipi_send_data(struct mbox_chan *chan, void *data)302{303	struct device *dev = chan->mbox->dev;304	struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);305	struct zynqmp_ipi_mchan *mchan = chan->con_priv;306	struct zynqmp_ipi_message *msg = data;307	u64 arg0;308	struct arm_smccc_res res;309 310	if (WARN_ON(!ipi_mbox)) {311		dev_err(dev, "no platform drv data??\n");312		return -EINVAL;313	}314 315	if (mchan->chan_type == IPI_MB_CHNL_TX) {316		/* Send request message */317		if (msg && msg->len > mchan->req_buf_size && mchan->req_buf) {318			dev_err(dev, "channel %d message length %u > max %lu\n",319				mchan->chan_type, (unsigned int)msg->len,320				mchan->req_buf_size);321			return -EINVAL;322		}323		if (msg && msg->len && mchan->req_buf)324			memcpy_toio(mchan->req_buf, msg->data, msg->len);325		/* Kick IPI mailbox to send message */326		arg0 = SMC_IPI_MAILBOX_NOTIFY;327		zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);328	} else {329		/* Send response message */330		if (msg && msg->len > mchan->resp_buf_size && mchan->resp_buf) {331			dev_err(dev, "channel %d message length %u > max %lu\n",332				mchan->chan_type, (unsigned int)msg->len,333				mchan->resp_buf_size);334			return -EINVAL;335		}336		if (msg && msg->len && mchan->resp_buf)337			memcpy_toio(mchan->resp_buf, msg->data, msg->len);338		arg0 = SMC_IPI_MAILBOX_ACK;339		zynqmp_ipi_fw_call(ipi_mbox, arg0, IPI_SMC_ACK_EIRQ_MASK,340				   &res);341	}342	return 0;343}344 345/**346 * zynqmp_ipi_startup - Startup the IPI channel347 *348 * @chan: Channel pointer349 *350 * Return: 0 if all goes good, else return corresponding error message351 */352static int zynqmp_ipi_startup(struct mbox_chan *chan)353{354	struct device *dev = chan->mbox->dev;355	struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);356	struct zynqmp_ipi_mchan *mchan = chan->con_priv;357	u64 arg0;358	struct arm_smccc_res res;359	int ret = 0;360	unsigned int nchan_type;361 362	if (mchan->is_opened)363		return 0;364 365	/* If no channel has been opened, open the IPI mailbox */366	nchan_type = (mchan->chan_type + 1) % 2;367	if (!ipi_mbox->mchans[nchan_type].is_opened) {368		arg0 = SMC_IPI_MAILBOX_OPEN;369		zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);370		/* Check the SMC call status, a0 of the result */371		ret = (int)(res.a0 & 0xFFFFFFFF);372		if (ret < 0) {373			dev_err(dev, "SMC to open the IPI channel failed.\n");374			return ret;375		}376		ret = 0;377	}378 379	/* If it is RX channel, enable the IPI notification interrupt */380	if (mchan->chan_type == IPI_MB_CHNL_RX) {381		arg0 = SMC_IPI_MAILBOX_ENABLE_IRQ;382		zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);383	}384	mchan->is_opened = 1;385 386	return ret;387}388 389/**390 * zynqmp_ipi_shutdown - Shutdown the IPI channel391 *392 * @chan: Channel pointer393 */394static void zynqmp_ipi_shutdown(struct mbox_chan *chan)395{396	struct device *dev = chan->mbox->dev;397	struct zynqmp_ipi_mbox *ipi_mbox = dev_get_drvdata(dev);398	struct zynqmp_ipi_mchan *mchan = chan->con_priv;399	u64 arg0;400	struct arm_smccc_res res;401	unsigned int chan_type;402 403	if (!mchan->is_opened)404		return;405 406	/* If it is RX channel, disable notification interrupt */407	chan_type = mchan->chan_type;408	if (chan_type == IPI_MB_CHNL_RX) {409		arg0 = SMC_IPI_MAILBOX_DISABLE_IRQ;410		zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);411	}412	/* Release IPI mailbox if no other channel is opened */413	chan_type = (chan_type + 1) % 2;414	if (!ipi_mbox->mchans[chan_type].is_opened) {415		arg0 = SMC_IPI_MAILBOX_RELEASE;416		zynqmp_ipi_fw_call(ipi_mbox, arg0, 0, &res);417	}418 419	mchan->is_opened = 0;420}421 422/* ZynqMP IPI mailbox operations */423static const struct mbox_chan_ops zynqmp_ipi_chan_ops = {424	.startup = zynqmp_ipi_startup,425	.shutdown = zynqmp_ipi_shutdown,426	.peek_data = zynqmp_ipi_peek_data,427	.last_tx_done = zynqmp_ipi_last_tx_done,428	.send_data = zynqmp_ipi_send_data,429};430 431/**432 * zynqmp_ipi_of_xlate - Translate of phandle to IPI mailbox channel433 *434 * @mbox: mailbox controller pointer435 * @p:    phandle pointer436 *437 * Return: Mailbox channel, else return error pointer.438 */439static struct mbox_chan *zynqmp_ipi_of_xlate(struct mbox_controller *mbox,440					     const struct of_phandle_args *p)441{442	struct mbox_chan *chan;443	struct device *dev = mbox->dev;444	unsigned int chan_type;445 446	/* Only supports TX and RX channels */447	chan_type = p->args[0];448	if (chan_type != IPI_MB_CHNL_TX && chan_type != IPI_MB_CHNL_RX) {449		dev_err(dev, "req chnl failure: invalid chnl type %u.\n",450			chan_type);451		return ERR_PTR(-EINVAL);452	}453	chan = &mbox->chans[chan_type];454	return chan;455}456 457/**458 * zynqmp_ipi_mbox_get_buf_res - Get buffer resource from the IPI dev node459 *460 * @node: IPI mbox device child node461 * @name: name of the IPI buffer462 * @res: pointer to where the resource information will be stored.463 *464 * Return: 0 for success, negative value for failure465 */466static int zynqmp_ipi_mbox_get_buf_res(struct device_node *node,467				       const char *name,468				       struct resource *res)469{470	int ret, index;471 472	index = of_property_match_string(node, "reg-names", name);473	if (index >= 0) {474		ret = of_address_to_resource(node, index, res);475		if (ret < 0)476			return -EINVAL;477		return 0;478	}479	return -ENODEV;480}481 482/**483 * zynqmp_ipi_mbox_dev_release() - release the existence of a ipi mbox dev484 *485 * @dev: the ipi mailbox device486 *487 * This is to avoid the no device release() function kernel warning.488 *489 */490static void zynqmp_ipi_mbox_dev_release(struct device *dev)491{492	(void)dev;493}494 495/**496 * zynqmp_ipi_mbox_probe - probe IPI mailbox resource from device node497 *498 * @ipi_mbox: pointer to IPI mailbox private data structure499 * @node: IPI mailbox device node500 *501 * Return: 0 for success, negative value for failure502 */503static int zynqmp_ipi_mbox_probe(struct zynqmp_ipi_mbox *ipi_mbox,504				 struct device_node *node)505{506	struct mbox_chan *chans;507	struct mbox_controller *mbox;508	struct device *dev, *mdev;509	int ret;510 511	dev = ipi_mbox->pdata->dev;512	/* Initialize dev for IPI mailbox */513	ipi_mbox->dev.parent = dev;514	ipi_mbox->dev.release = NULL;515	ipi_mbox->dev.of_node = node;516	dev_set_name(&ipi_mbox->dev, "%s", of_node_full_name(node));517	dev_set_drvdata(&ipi_mbox->dev, ipi_mbox);518	ipi_mbox->dev.release = zynqmp_ipi_mbox_dev_release;519	ipi_mbox->dev.driver = &zynqmp_ipi_mbox_driver;520	ret = device_register(&ipi_mbox->dev);521	if (ret) {522		dev_err(dev, "Failed to register ipi mbox dev.\n");523		put_device(&ipi_mbox->dev);524		return ret;525	}526	mdev = &ipi_mbox->dev;527 528	/* Get the IPI remote agent ID */529	ret = of_property_read_u32(node, "xlnx,ipi-id", &ipi_mbox->remote_id);530	if (ret < 0) {531		dev_err(dev, "No IPI remote ID is specified.\n");532		return ret;533	}534 535	ret = ipi_mbox->setup_ipi_fn(ipi_mbox, node);536	if (ret) {537		dev_err(dev, "Failed to set up IPI Buffers.\n");538		return ret;539	}540 541	mbox = &ipi_mbox->mbox;542	mbox->dev = mdev;543	mbox->ops = &zynqmp_ipi_chan_ops;544	mbox->num_chans = 2;545	mbox->txdone_irq = false;546	mbox->txdone_poll = true;547	mbox->txpoll_period = tx_poll_period;548	mbox->of_xlate = zynqmp_ipi_of_xlate;549	chans = devm_kzalloc(mdev, 2 * sizeof(*chans), GFP_KERNEL);550	if (!chans)551		return -ENOMEM;552	mbox->chans = chans;553	chans[IPI_MB_CHNL_TX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_TX];554	chans[IPI_MB_CHNL_RX].con_priv = &ipi_mbox->mchans[IPI_MB_CHNL_RX];555	ipi_mbox->mchans[IPI_MB_CHNL_TX].chan_type = IPI_MB_CHNL_TX;556	ipi_mbox->mchans[IPI_MB_CHNL_RX].chan_type = IPI_MB_CHNL_RX;557	ret = devm_mbox_controller_register(mdev, mbox);558	if (ret)559		dev_err(mdev,560			"Failed to register mbox_controller(%d)\n", ret);561	else562		dev_info(mdev,563			 "Registered ZynqMP IPI mbox with TX/RX channels.\n");564	return ret;565}566 567/**568 * zynqmp_ipi_setup - set up IPI Buffers for classic flow569 *570 * @ipi_mbox: pointer to IPI mailbox private data structure571 * @node: IPI mailbox device node572 *573 * This will be used to set up IPI Buffers for ZynqMP SOC if user574 * wishes to use classic driver usage model on new SOC's with only575 * buffered IPIs.576 *577 * Note that bufferless IPIs and mixed usage of buffered and bufferless578 * IPIs are not supported with this flow.579 *580 * This will be invoked with compatible string "xlnx,zynqmp-ipi-mailbox".581 *582 * Return: 0 for success, negative value for failure583 */584static int zynqmp_ipi_setup(struct zynqmp_ipi_mbox *ipi_mbox,585			    struct device_node *node)586{587	struct zynqmp_ipi_mchan *mchan;588	struct device *mdev;589	struct resource res;590	const char *name;591	int ret;592 593	mdev = &ipi_mbox->dev;594 595	mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];596	name = "local_request_region";597	ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);598	if (!ret) {599		mchan->req_buf_size = resource_size(&res);600		mchan->req_buf = devm_ioremap(mdev, res.start,601					      mchan->req_buf_size);602		if (!mchan->req_buf) {603			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");604			return -ENOMEM;605		}606	} else if (ret != -ENODEV) {607		dev_err(mdev, "Unmatched resource %s, %d.\n", name, ret);608		return ret;609	}610 611	name = "remote_response_region";612	ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);613	if (!ret) {614		mchan->resp_buf_size = resource_size(&res);615		mchan->resp_buf = devm_ioremap(mdev, res.start,616					       mchan->resp_buf_size);617		if (!mchan->resp_buf) {618			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");619			return -ENOMEM;620		}621	} else if (ret != -ENODEV) {622		dev_err(mdev, "Unmatched resource %s.\n", name);623		return ret;624	}625	mchan->rx_buf = devm_kzalloc(mdev,626				     mchan->resp_buf_size +627				     sizeof(struct zynqmp_ipi_message),628				     GFP_KERNEL);629	if (!mchan->rx_buf)630		return -ENOMEM;631 632	mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];633	name = "remote_request_region";634	ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);635	if (!ret) {636		mchan->req_buf_size = resource_size(&res);637		mchan->req_buf = devm_ioremap(mdev, res.start,638					      mchan->req_buf_size);639		if (!mchan->req_buf) {640			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");641			return -ENOMEM;642		}643	} else if (ret != -ENODEV) {644		dev_err(mdev, "Unmatched resource %s.\n", name);645		return ret;646	}647 648	name = "local_response_region";649	ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);650	if (!ret) {651		mchan->resp_buf_size = resource_size(&res);652		mchan->resp_buf = devm_ioremap(mdev, res.start,653					       mchan->resp_buf_size);654		if (!mchan->resp_buf) {655			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");656			return -ENOMEM;657		}658	} else if (ret != -ENODEV) {659		dev_err(mdev, "Unmatched resource %s.\n", name);660		return ret;661	}662	mchan->rx_buf = devm_kzalloc(mdev,663				     mchan->resp_buf_size +664				     sizeof(struct zynqmp_ipi_message),665				     GFP_KERNEL);666	if (!mchan->rx_buf)667		return -ENOMEM;668 669	return 0;670}671 672/**673 * versal_ipi_setup - Set up IPIs to support mixed usage of674 *				 Buffered and Bufferless IPIs.675 *676 * @ipi_mbox: pointer to IPI mailbox private data structure677 * @node: IPI mailbox device node678 *679 * Return: 0 for success, negative value for failure680 */681static int versal_ipi_setup(struct zynqmp_ipi_mbox *ipi_mbox,682			    struct device_node *node)683{684	struct zynqmp_ipi_mchan *tx_mchan, *rx_mchan;685	struct resource host_res, remote_res;686	struct device_node *parent_node;687	int host_idx, remote_idx;688	struct device *mdev;689 690	tx_mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];691	rx_mchan = &ipi_mbox->mchans[IPI_MB_CHNL_RX];692	parent_node = of_get_parent(node);693	mdev = &ipi_mbox->dev;694 695	host_idx = zynqmp_ipi_mbox_get_buf_res(parent_node, "msg", &host_res);696	remote_idx = zynqmp_ipi_mbox_get_buf_res(node, "msg", &remote_res);697 698	/*699	 * Only set up buffers if both sides claim to have msg buffers.700	 * This is because each buffered IPI's corresponding msg buffers701	 * are reserved for use by other buffered IPI's.702	 */703	if (!host_idx && !remote_idx) {704		u32 host_src, host_dst, remote_src, remote_dst;705		u32 buff_sz;706 707		buff_sz = resource_size(&host_res);708 709		host_src = host_res.start & SRC_BITMASK;710		remote_src = remote_res.start & SRC_BITMASK;711 712		host_dst = (host_src >> DST_BIT_POS) * DEST_OFFSET;713		remote_dst = (remote_src >> DST_BIT_POS) * DEST_OFFSET;714 715		/* Validate that IPI IDs is within IPI Message buffer space. */716		if (host_dst >= buff_sz || remote_dst >= buff_sz) {717			dev_err(mdev,718				"Invalid IPI Message buffer values: %x %x\n",719				host_dst, remote_dst);720			return -EINVAL;721		}722 723		tx_mchan->req_buf = devm_ioremap(mdev,724						 host_res.start | remote_dst,725						 IPI_BUF_SIZE);726		if (!tx_mchan->req_buf) {727			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");728			return -ENOMEM;729		}730 731		tx_mchan->resp_buf = devm_ioremap(mdev,732						  (remote_res.start | host_dst) +733						  RESP_OFFSET, IPI_BUF_SIZE);734		if (!tx_mchan->resp_buf) {735			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");736			return -ENOMEM;737		}738 739		rx_mchan->req_buf = devm_ioremap(mdev,740						 remote_res.start | host_dst,741						 IPI_BUF_SIZE);742		if (!rx_mchan->req_buf) {743			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");744			return -ENOMEM;745		}746 747		rx_mchan->resp_buf = devm_ioremap(mdev,748						  (host_res.start | remote_dst) +749						  RESP_OFFSET, IPI_BUF_SIZE);750		if (!rx_mchan->resp_buf) {751			dev_err(mdev, "Unable to map IPI buffer I/O memory\n");752			return -ENOMEM;753		}754 755		tx_mchan->resp_buf_size = IPI_BUF_SIZE;756		tx_mchan->req_buf_size = IPI_BUF_SIZE;757		tx_mchan->rx_buf = devm_kzalloc(mdev, IPI_BUF_SIZE +758						sizeof(struct zynqmp_ipi_message),759						GFP_KERNEL);760		if (!tx_mchan->rx_buf)761			return -ENOMEM;762 763		rx_mchan->resp_buf_size = IPI_BUF_SIZE;764		rx_mchan->req_buf_size = IPI_BUF_SIZE;765		rx_mchan->rx_buf = devm_kzalloc(mdev, IPI_BUF_SIZE +766						sizeof(struct zynqmp_ipi_message),767						GFP_KERNEL);768		if (!rx_mchan->rx_buf)769			return -ENOMEM;770	}771 772	return 0;773}774 775static int xlnx_mbox_cpuhp_start(unsigned int cpu)776{777	struct zynqmp_ipi_pdata *pdata;778 779	pdata = get_cpu_var(per_cpu_pdata);780	put_cpu_var(per_cpu_pdata);781	enable_percpu_irq(pdata->virq_sgi, IRQ_TYPE_NONE);782 783	return 0;784}785 786static int xlnx_mbox_cpuhp_down(unsigned int cpu)787{788	struct zynqmp_ipi_pdata *pdata;789 790	pdata = get_cpu_var(per_cpu_pdata);791	put_cpu_var(per_cpu_pdata);792	disable_percpu_irq(pdata->virq_sgi);793 794	return 0;795}796 797static void xlnx_disable_percpu_irq(void *data)798{799	struct zynqmp_ipi_pdata *pdata;800 801	pdata = *this_cpu_ptr(&per_cpu_pdata);802 803	disable_percpu_irq(pdata->virq_sgi);804}805 806static int xlnx_mbox_init_sgi(struct platform_device *pdev,807			      int sgi_num,808			      struct zynqmp_ipi_pdata *pdata)809{810	int ret = 0;811	int cpu;812 813	/*814	 * IRQ related structures are used for the following:815	 * for each SGI interrupt ensure its mapped by GIC IRQ domain816	 * and that each corresponding linux IRQ for the HW IRQ has817	 * a handler for when receiving an interrupt from the remote818	 * processor.819	 */820	struct irq_domain *domain;821	struct irq_fwspec sgi_fwspec;822	struct device_node *interrupt_parent = NULL;823	struct device *dev = &pdev->dev;824 825	/* Find GIC controller to map SGIs. */826	interrupt_parent = of_irq_find_parent(dev->of_node);827	if (!interrupt_parent) {828		dev_err(&pdev->dev, "Failed to find property for Interrupt parent\n");829		return -EINVAL;830	}831 832	/* Each SGI needs to be associated with GIC's IRQ domain. */833	domain = irq_find_host(interrupt_parent);834	of_node_put(interrupt_parent);835 836	/* Each mapping needs GIC domain when finding IRQ mapping. */837	sgi_fwspec.fwnode = domain->fwnode;838 839	/*840	 * When irq domain looks at mapping each arg is as follows:841	 * 3 args for: interrupt type (SGI), interrupt # (set later), type842	 */843	sgi_fwspec.param_count = 1;844 845	/* Set SGI's hwirq */846	sgi_fwspec.param[0] = sgi_num;847	pdata->virq_sgi = irq_create_fwspec_mapping(&sgi_fwspec);848 849	for_each_possible_cpu(cpu)850		per_cpu(per_cpu_pdata, cpu) = pdata;851 852	ret = request_percpu_irq(pdata->virq_sgi, zynqmp_sgi_interrupt, pdev->name,853				 &per_cpu_pdata);854	WARN_ON(ret);855	if (ret) {856		irq_dispose_mapping(pdata->virq_sgi);857		return ret;858	}859 860	irq_set_status_flags(pdata->virq_sgi, IRQ_PER_CPU);861 862	/* Setup function for the CPU hot-plug cases */863	cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mailbox/sgi:starting",864			  xlnx_mbox_cpuhp_start, xlnx_mbox_cpuhp_down);865 866	return ret;867}868 869static void xlnx_mbox_cleanup_sgi(struct zynqmp_ipi_pdata *pdata)870{871	cpuhp_remove_state(CPUHP_AP_ONLINE_DYN);872 873	on_each_cpu(xlnx_disable_percpu_irq, NULL, 1);874 875	irq_clear_status_flags(pdata->virq_sgi, IRQ_PER_CPU);876	free_percpu_irq(pdata->virq_sgi, &per_cpu_pdata);877	irq_dispose_mapping(pdata->virq_sgi);878}879 880/**881 * zynqmp_ipi_free_mboxes - Free IPI mailboxes devices882 *883 * @pdata: IPI private data884 */885static void zynqmp_ipi_free_mboxes(struct zynqmp_ipi_pdata *pdata)886{887	struct zynqmp_ipi_mbox *ipi_mbox;888	int i;889 890	if (pdata->irq < MAX_SGI)891		xlnx_mbox_cleanup_sgi(pdata);892 893	i = pdata->num_mboxes;894	for (; i >= 0; i--) {895		ipi_mbox = &pdata->ipi_mboxes[i];896		if (ipi_mbox->dev.parent) {897			mbox_controller_unregister(&ipi_mbox->mbox);898			if (device_is_registered(&ipi_mbox->dev))899				device_unregister(&ipi_mbox->dev);900		}901	}902}903 904static int zynqmp_ipi_probe(struct platform_device *pdev)905{906	struct device *dev = &pdev->dev;907	struct device_node *nc, *np = pdev->dev.of_node;908	struct zynqmp_ipi_pdata __percpu *pdata;909	struct of_phandle_args out_irq;910	struct zynqmp_ipi_mbox *mbox;911	int num_mboxes, ret = -EINVAL;912	setup_ipi_fn ipi_fn;913 914	num_mboxes = of_get_available_child_count(np);915	if (num_mboxes == 0) {916		dev_err(dev, "mailbox nodes not available\n");917		return -EINVAL;918	}919 920	pdata = devm_kzalloc(dev, struct_size(pdata, ipi_mboxes, num_mboxes),921			     GFP_KERNEL);922	if (!pdata)923		return -ENOMEM;924	pdata->dev = dev;925 926	/* Get the IPI local agents ID */927	ret = of_property_read_u32(np, "xlnx,ipi-id", &pdata->local_id);928	if (ret < 0) {929		dev_err(dev, "No IPI local ID is specified.\n");930		return ret;931	}932 933	ipi_fn = (setup_ipi_fn)device_get_match_data(&pdev->dev);934	if (!ipi_fn) {935		dev_err(dev,936			"Mbox Compatible String is missing IPI Setup fn.\n");937		return -ENODEV;938	}939 940	pdata->num_mboxes = num_mboxes;941 942	mbox = pdata->ipi_mboxes;943	mbox->setup_ipi_fn = ipi_fn;944 945	for_each_available_child_of_node(np, nc) {946		mbox->pdata = pdata;947		ret = zynqmp_ipi_mbox_probe(mbox, nc);948		if (ret) {949			of_node_put(nc);950			dev_err(dev, "failed to probe subdev.\n");951			ret = -EINVAL;952			goto free_mbox_dev;953		}954		mbox++;955	}956 957	ret = of_irq_parse_one(dev_of_node(dev), 0, &out_irq);958	if (ret < 0) {959		dev_err(dev, "failed to parse interrupts\n");960		goto free_mbox_dev;961	}962	ret = out_irq.args[1];963 964	/*965	 * If Interrupt number is in SGI range, then request SGI else request966	 * IPI system IRQ.967	 */968	if (ret < MAX_SGI) {969		pdata->irq = ret;970		ret = xlnx_mbox_init_sgi(pdev, pdata->irq, pdata);971		if (ret)972			goto free_mbox_dev;973	} else {974		ret = platform_get_irq(pdev, 0);975		if (ret < 0)976			goto free_mbox_dev;977 978		pdata->irq = ret;979		ret = devm_request_irq(dev, pdata->irq, zynqmp_ipi_interrupt,980				       IRQF_SHARED, dev_name(dev), pdata);981	}982 983	if (ret) {984		dev_err(dev, "IRQ %d is not requested successfully.\n",985			pdata->irq);986		goto free_mbox_dev;987	}988 989	platform_set_drvdata(pdev, pdata);990	return ret;991 992free_mbox_dev:993	zynqmp_ipi_free_mboxes(pdata);994	return ret;995}996 997static void zynqmp_ipi_remove(struct platform_device *pdev)998{999	struct zynqmp_ipi_pdata *pdata;1000 1001	pdata = platform_get_drvdata(pdev);1002	zynqmp_ipi_free_mboxes(pdata);1003}1004 1005static const struct of_device_id zynqmp_ipi_of_match[] = {1006	{ .compatible = "xlnx,zynqmp-ipi-mailbox",1007	  .data = &zynqmp_ipi_setup,1008	},1009	{ .compatible = "xlnx,versal-ipi-mailbox",1010	  .data = &versal_ipi_setup,1011	},1012	{},1013};1014MODULE_DEVICE_TABLE(of, zynqmp_ipi_of_match);1015 1016static struct platform_driver zynqmp_ipi_driver = {1017	.probe = zynqmp_ipi_probe,1018	.remove_new = zynqmp_ipi_remove,1019	.driver = {1020		   .name = "zynqmp-ipi",1021		   .of_match_table = of_match_ptr(zynqmp_ipi_of_match),1022	},1023};1024 1025static int __init zynqmp_ipi_init(void)1026{1027	return platform_driver_register(&zynqmp_ipi_driver);1028}1029subsys_initcall(zynqmp_ipi_init);1030 1031static void __exit zynqmp_ipi_exit(void)1032{1033	platform_driver_unregister(&zynqmp_ipi_driver);1034}1035module_exit(zynqmp_ipi_exit);1036 1037MODULE_LICENSE("GPL v2");1038MODULE_DESCRIPTION("Xilinx ZynqMP IPI Mailbox driver");1039MODULE_AUTHOR("Xilinx Inc.");1040