1fa74a025SManivannan Sadhasivam // SPDX-License-Identifier: GPL-2.0-only 2fa74a025SManivannan Sadhasivam /* 3fa74a025SManivannan Sadhasivam * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. 4fa74a025SManivannan Sadhasivam */ 5fa74a025SManivannan Sadhasivam 6fa74a025SManivannan Sadhasivam #include <linux/bitfield.h> 7fa74a025SManivannan Sadhasivam #include <linux/interrupt.h> 8fa74a025SManivannan Sadhasivam #include <linux/irq.h> 9fa74a025SManivannan Sadhasivam #include <linux/irqdomain.h> 10fa74a025SManivannan Sadhasivam #include <linux/mailbox_controller.h> 11fa74a025SManivannan Sadhasivam #include <linux/module.h> 12fa74a025SManivannan Sadhasivam #include <linux/platform_device.h> 13fa74a025SManivannan Sadhasivam 14fa74a025SManivannan Sadhasivam #include <dt-bindings/mailbox/qcom-ipcc.h> 15fa74a025SManivannan Sadhasivam 16fa74a025SManivannan Sadhasivam /* IPCC Register offsets */ 17fa74a025SManivannan Sadhasivam #define IPCC_REG_SEND_ID 0x0c 18fa74a025SManivannan Sadhasivam #define IPCC_REG_RECV_ID 0x10 19fa74a025SManivannan Sadhasivam #define IPCC_REG_RECV_SIGNAL_ENABLE 0x14 20fa74a025SManivannan Sadhasivam #define IPCC_REG_RECV_SIGNAL_DISABLE 0x18 21fa74a025SManivannan Sadhasivam #define IPCC_REG_RECV_SIGNAL_CLEAR 0x1c 22fa74a025SManivannan Sadhasivam #define IPCC_REG_CLIENT_CLEAR 0x38 23fa74a025SManivannan Sadhasivam 24fa74a025SManivannan Sadhasivam #define IPCC_SIGNAL_ID_MASK GENMASK(15, 0) 25fa74a025SManivannan Sadhasivam #define IPCC_CLIENT_ID_MASK GENMASK(31, 16) 26fa74a025SManivannan Sadhasivam 27fa74a025SManivannan Sadhasivam #define IPCC_NO_PENDING_IRQ GENMASK(31, 0) 28fa74a025SManivannan Sadhasivam 29fa74a025SManivannan Sadhasivam /** 30fa74a025SManivannan Sadhasivam * struct qcom_ipcc_chan_info - Per-mailbox-channel info 31fa74a025SManivannan Sadhasivam * @client_id: The client-id to which the interrupt has to be triggered 32fa74a025SManivannan Sadhasivam * @signal_id: The signal-id to which the interrupt has to be triggered 33fa74a025SManivannan Sadhasivam */ 34fa74a025SManivannan Sadhasivam struct qcom_ipcc_chan_info { 35fa74a025SManivannan Sadhasivam u16 client_id; 36fa74a025SManivannan Sadhasivam u16 signal_id; 37fa74a025SManivannan Sadhasivam }; 38fa74a025SManivannan Sadhasivam 39fa74a025SManivannan Sadhasivam /** 40fa74a025SManivannan Sadhasivam * struct qcom_ipcc - Holder for the mailbox driver 41fa74a025SManivannan Sadhasivam * @dev: Device associated with this instance 42fa74a025SManivannan Sadhasivam * @base: Base address of the IPCC frame associated to APSS 43fa74a025SManivannan Sadhasivam * @irq_domain: The irq_domain associated with this instance 44fa74a025SManivannan Sadhasivam * @chan: The mailbox channels array 45fa74a025SManivannan Sadhasivam * @mchan: The per-mailbox channel info array 46fa74a025SManivannan Sadhasivam * @mbox: The mailbox controller 47fa74a025SManivannan Sadhasivam * @irq: Summary irq 48fa74a025SManivannan Sadhasivam */ 49fa74a025SManivannan Sadhasivam struct qcom_ipcc { 50fa74a025SManivannan Sadhasivam struct device *dev; 51fa74a025SManivannan Sadhasivam void __iomem *base; 52fa74a025SManivannan Sadhasivam struct irq_domain *irq_domain; 53e9d50e4bSHuang Yiwei struct mbox_chan *chans; 54e9d50e4bSHuang Yiwei struct qcom_ipcc_chan_info *mchan; 55fa74a025SManivannan Sadhasivam struct mbox_controller mbox; 56e9d50e4bSHuang Yiwei int num_chans; 57fa74a025SManivannan Sadhasivam int irq; 58fa74a025SManivannan Sadhasivam }; 59fa74a025SManivannan Sadhasivam 60fa74a025SManivannan Sadhasivam static inline struct qcom_ipcc *to_qcom_ipcc(struct mbox_controller *mbox) 61fa74a025SManivannan Sadhasivam { 62fa74a025SManivannan Sadhasivam return container_of(mbox, struct qcom_ipcc, mbox); 63fa74a025SManivannan Sadhasivam } 64fa74a025SManivannan Sadhasivam 65fa74a025SManivannan Sadhasivam static inline u32 qcom_ipcc_get_hwirq(u16 client_id, u16 signal_id) 66fa74a025SManivannan Sadhasivam { 67fa74a025SManivannan Sadhasivam return FIELD_PREP(IPCC_CLIENT_ID_MASK, client_id) | 68fa74a025SManivannan Sadhasivam FIELD_PREP(IPCC_SIGNAL_ID_MASK, signal_id); 69fa74a025SManivannan Sadhasivam } 70fa74a025SManivannan Sadhasivam 71fa74a025SManivannan Sadhasivam static irqreturn_t qcom_ipcc_irq_fn(int irq, void *data) 72fa74a025SManivannan Sadhasivam { 73fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = data; 74fa74a025SManivannan Sadhasivam u32 hwirq; 75fa74a025SManivannan Sadhasivam int virq; 76fa74a025SManivannan Sadhasivam 77fa74a025SManivannan Sadhasivam for (;;) { 78fa74a025SManivannan Sadhasivam hwirq = readl(ipcc->base + IPCC_REG_RECV_ID); 79fa74a025SManivannan Sadhasivam if (hwirq == IPCC_NO_PENDING_IRQ) 80fa74a025SManivannan Sadhasivam break; 81fa74a025SManivannan Sadhasivam 82fa74a025SManivannan Sadhasivam virq = irq_find_mapping(ipcc->irq_domain, hwirq); 83fa74a025SManivannan Sadhasivam writel(hwirq, ipcc->base + IPCC_REG_RECV_SIGNAL_CLEAR); 84fa74a025SManivannan Sadhasivam generic_handle_irq(virq); 85fa74a025SManivannan Sadhasivam } 86fa74a025SManivannan Sadhasivam 87fa74a025SManivannan Sadhasivam return IRQ_HANDLED; 88fa74a025SManivannan Sadhasivam } 89fa74a025SManivannan Sadhasivam 90fa74a025SManivannan Sadhasivam static void qcom_ipcc_mask_irq(struct irq_data *irqd) 91fa74a025SManivannan Sadhasivam { 92fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = irq_data_get_irq_chip_data(irqd); 93fa74a025SManivannan Sadhasivam irq_hw_number_t hwirq = irqd_to_hwirq(irqd); 94fa74a025SManivannan Sadhasivam 95fa74a025SManivannan Sadhasivam writel(hwirq, ipcc->base + IPCC_REG_RECV_SIGNAL_DISABLE); 96fa74a025SManivannan Sadhasivam } 97fa74a025SManivannan Sadhasivam 98fa74a025SManivannan Sadhasivam static void qcom_ipcc_unmask_irq(struct irq_data *irqd) 99fa74a025SManivannan Sadhasivam { 100fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = irq_data_get_irq_chip_data(irqd); 101fa74a025SManivannan Sadhasivam irq_hw_number_t hwirq = irqd_to_hwirq(irqd); 102fa74a025SManivannan Sadhasivam 103fa74a025SManivannan Sadhasivam writel(hwirq, ipcc->base + IPCC_REG_RECV_SIGNAL_ENABLE); 104fa74a025SManivannan Sadhasivam } 105fa74a025SManivannan Sadhasivam 106fa74a025SManivannan Sadhasivam static struct irq_chip qcom_ipcc_irq_chip = { 107fa74a025SManivannan Sadhasivam .name = "ipcc", 108fa74a025SManivannan Sadhasivam .irq_mask = qcom_ipcc_mask_irq, 109fa74a025SManivannan Sadhasivam .irq_unmask = qcom_ipcc_unmask_irq, 110fa74a025SManivannan Sadhasivam .flags = IRQCHIP_SKIP_SET_WAKE, 111fa74a025SManivannan Sadhasivam }; 112fa74a025SManivannan Sadhasivam 113fa74a025SManivannan Sadhasivam static int qcom_ipcc_domain_map(struct irq_domain *d, unsigned int irq, 114fa74a025SManivannan Sadhasivam irq_hw_number_t hw) 115fa74a025SManivannan Sadhasivam { 116fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = d->host_data; 117fa74a025SManivannan Sadhasivam 118fa74a025SManivannan Sadhasivam irq_set_chip_and_handler(irq, &qcom_ipcc_irq_chip, handle_level_irq); 119fa74a025SManivannan Sadhasivam irq_set_chip_data(irq, ipcc); 120fa74a025SManivannan Sadhasivam irq_set_noprobe(irq); 121fa74a025SManivannan Sadhasivam 122fa74a025SManivannan Sadhasivam return 0; 123fa74a025SManivannan Sadhasivam } 124fa74a025SManivannan Sadhasivam 125fa74a025SManivannan Sadhasivam static int qcom_ipcc_domain_xlate(struct irq_domain *d, 126fa74a025SManivannan Sadhasivam struct device_node *node, const u32 *intspec, 127fa74a025SManivannan Sadhasivam unsigned int intsize, 128fa74a025SManivannan Sadhasivam unsigned long *out_hwirq, 129fa74a025SManivannan Sadhasivam unsigned int *out_type) 130fa74a025SManivannan Sadhasivam { 131fa74a025SManivannan Sadhasivam if (intsize != 3) 132fa74a025SManivannan Sadhasivam return -EINVAL; 133fa74a025SManivannan Sadhasivam 134fa74a025SManivannan Sadhasivam *out_hwirq = qcom_ipcc_get_hwirq(intspec[0], intspec[1]); 135fa74a025SManivannan Sadhasivam *out_type = intspec[2] & IRQ_TYPE_SENSE_MASK; 136fa74a025SManivannan Sadhasivam 137fa74a025SManivannan Sadhasivam return 0; 138fa74a025SManivannan Sadhasivam } 139fa74a025SManivannan Sadhasivam 140fa74a025SManivannan Sadhasivam static const struct irq_domain_ops qcom_ipcc_irq_ops = { 141fa74a025SManivannan Sadhasivam .map = qcom_ipcc_domain_map, 142fa74a025SManivannan Sadhasivam .xlate = qcom_ipcc_domain_xlate, 143fa74a025SManivannan Sadhasivam }; 144fa74a025SManivannan Sadhasivam 145fa74a025SManivannan Sadhasivam static int qcom_ipcc_mbox_send_data(struct mbox_chan *chan, void *data) 146fa74a025SManivannan Sadhasivam { 147fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = to_qcom_ipcc(chan->mbox); 148fa74a025SManivannan Sadhasivam struct qcom_ipcc_chan_info *mchan = chan->con_priv; 149fa74a025SManivannan Sadhasivam u32 hwirq; 150fa74a025SManivannan Sadhasivam 151fa74a025SManivannan Sadhasivam hwirq = qcom_ipcc_get_hwirq(mchan->client_id, mchan->signal_id); 152fa74a025SManivannan Sadhasivam writel(hwirq, ipcc->base + IPCC_REG_SEND_ID); 153fa74a025SManivannan Sadhasivam 154fa74a025SManivannan Sadhasivam return 0; 155fa74a025SManivannan Sadhasivam } 156fa74a025SManivannan Sadhasivam 157d6fbfdbcSSibi Sankar static void qcom_ipcc_mbox_shutdown(struct mbox_chan *chan) 158d6fbfdbcSSibi Sankar { 159d6fbfdbcSSibi Sankar chan->con_priv = NULL; 160d6fbfdbcSSibi Sankar } 161d6fbfdbcSSibi Sankar 162fa74a025SManivannan Sadhasivam static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox, 163fa74a025SManivannan Sadhasivam const struct of_phandle_args *ph) 164fa74a025SManivannan Sadhasivam { 165fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = to_qcom_ipcc(mbox); 166fa74a025SManivannan Sadhasivam struct qcom_ipcc_chan_info *mchan; 167fa74a025SManivannan Sadhasivam struct mbox_chan *chan; 168e9d50e4bSHuang Yiwei struct device *dev; 169e9d50e4bSHuang Yiwei int chan_id; 170e9d50e4bSHuang Yiwei 171e9d50e4bSHuang Yiwei dev = ipcc->dev; 172fa74a025SManivannan Sadhasivam 173fa74a025SManivannan Sadhasivam if (ph->args_count != 2) 174fa74a025SManivannan Sadhasivam return ERR_PTR(-EINVAL); 175fa74a025SManivannan Sadhasivam 176e9d50e4bSHuang Yiwei for (chan_id = 0; chan_id < mbox->num_chans; chan_id++) { 177e9d50e4bSHuang Yiwei chan = &ipcc->chans[chan_id]; 178e9d50e4bSHuang Yiwei mchan = chan->con_priv; 179e9d50e4bSHuang Yiwei 180e9d50e4bSHuang Yiwei if (!mchan) 181e9d50e4bSHuang Yiwei break; 182e9d50e4bSHuang Yiwei else if (mchan->client_id == ph->args[0] && 183e9d50e4bSHuang Yiwei mchan->signal_id == ph->args[1]) 184e9d50e4bSHuang Yiwei return ERR_PTR(-EBUSY); 185e9d50e4bSHuang Yiwei } 186e9d50e4bSHuang Yiwei 187e9d50e4bSHuang Yiwei if (chan_id >= mbox->num_chans) 188e9d50e4bSHuang Yiwei return ERR_PTR(-EBUSY); 189e9d50e4bSHuang Yiwei 190e9d50e4bSHuang Yiwei mchan = devm_kzalloc(dev, sizeof(*mchan), GFP_KERNEL); 191e9d50e4bSHuang Yiwei if (!mchan) 192e9d50e4bSHuang Yiwei return ERR_PTR(-ENOMEM); 193e9d50e4bSHuang Yiwei 194fa74a025SManivannan Sadhasivam mchan->client_id = ph->args[0]; 195fa74a025SManivannan Sadhasivam mchan->signal_id = ph->args[1]; 196fa74a025SManivannan Sadhasivam chan->con_priv = mchan; 197fa74a025SManivannan Sadhasivam 198e9d50e4bSHuang Yiwei return chan; 199fa74a025SManivannan Sadhasivam } 200fa74a025SManivannan Sadhasivam 201fa74a025SManivannan Sadhasivam static const struct mbox_chan_ops ipcc_mbox_chan_ops = { 202fa74a025SManivannan Sadhasivam .send_data = qcom_ipcc_mbox_send_data, 203d6fbfdbcSSibi Sankar .shutdown = qcom_ipcc_mbox_shutdown, 204fa74a025SManivannan Sadhasivam }; 205fa74a025SManivannan Sadhasivam 206e9d50e4bSHuang Yiwei static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc, 207e9d50e4bSHuang Yiwei struct device_node *controller_dn) 208fa74a025SManivannan Sadhasivam { 209e9d50e4bSHuang Yiwei struct of_phandle_args curr_ph; 210e9d50e4bSHuang Yiwei struct device_node *client_dn; 211fa74a025SManivannan Sadhasivam struct mbox_controller *mbox; 212fa74a025SManivannan Sadhasivam struct device *dev = ipcc->dev; 213e9d50e4bSHuang Yiwei int i, j, ret; 214e9d50e4bSHuang Yiwei 215e9d50e4bSHuang Yiwei /* 216e9d50e4bSHuang Yiwei * Find out the number of clients interested in this mailbox 217e9d50e4bSHuang Yiwei * and create channels accordingly. 218e9d50e4bSHuang Yiwei */ 219e9d50e4bSHuang Yiwei ipcc->num_chans = 0; 220e9d50e4bSHuang Yiwei for_each_node_with_property(client_dn, "mboxes") { 221e9d50e4bSHuang Yiwei if (!of_device_is_available(client_dn)) 222e9d50e4bSHuang Yiwei continue; 223e9d50e4bSHuang Yiwei i = of_count_phandle_with_args(client_dn, 224e9d50e4bSHuang Yiwei "mboxes", "#mbox-cells"); 225e9d50e4bSHuang Yiwei for (j = 0; j < i; j++) { 226e9d50e4bSHuang Yiwei ret = of_parse_phandle_with_args(client_dn, "mboxes", 227e9d50e4bSHuang Yiwei "#mbox-cells", j, &curr_ph); 228e9d50e4bSHuang Yiwei of_node_put(curr_ph.np); 229e9d50e4bSHuang Yiwei if (!ret && curr_ph.np == controller_dn) { 230e9d50e4bSHuang Yiwei ipcc->num_chans++; 231e9d50e4bSHuang Yiwei break; 232e9d50e4bSHuang Yiwei } 233e9d50e4bSHuang Yiwei } 234e9d50e4bSHuang Yiwei } 235e9d50e4bSHuang Yiwei 236e9d50e4bSHuang Yiwei /* If no clients are found, skip registering as a mbox controller */ 237e9d50e4bSHuang Yiwei if (!ipcc->num_chans) 238e9d50e4bSHuang Yiwei return 0; 239e9d50e4bSHuang Yiwei 240e9d50e4bSHuang Yiwei ipcc->chans = devm_kcalloc(dev, ipcc->num_chans, 241e9d50e4bSHuang Yiwei sizeof(struct mbox_chan), GFP_KERNEL); 242e9d50e4bSHuang Yiwei if (!ipcc->chans) 243e9d50e4bSHuang Yiwei return -ENOMEM; 244fa74a025SManivannan Sadhasivam 245fa74a025SManivannan Sadhasivam mbox = &ipcc->mbox; 246fa74a025SManivannan Sadhasivam mbox->dev = dev; 247e9d50e4bSHuang Yiwei mbox->num_chans = ipcc->num_chans; 248e9d50e4bSHuang Yiwei mbox->chans = ipcc->chans; 249fa74a025SManivannan Sadhasivam mbox->ops = &ipcc_mbox_chan_ops; 250fa74a025SManivannan Sadhasivam mbox->of_xlate = qcom_ipcc_mbox_xlate; 251fa74a025SManivannan Sadhasivam mbox->txdone_irq = false; 252fa74a025SManivannan Sadhasivam mbox->txdone_poll = false; 253fa74a025SManivannan Sadhasivam 254fa74a025SManivannan Sadhasivam return devm_mbox_controller_register(dev, mbox); 255fa74a025SManivannan Sadhasivam } 256fa74a025SManivannan Sadhasivam 257fa74a025SManivannan Sadhasivam static int qcom_ipcc_probe(struct platform_device *pdev) 258fa74a025SManivannan Sadhasivam { 259fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc; 260*1f43e523SHuang Yiwei static int id; 261*1f43e523SHuang Yiwei char *name; 262fa74a025SManivannan Sadhasivam int ret; 263fa74a025SManivannan Sadhasivam 264fa74a025SManivannan Sadhasivam ipcc = devm_kzalloc(&pdev->dev, sizeof(*ipcc), GFP_KERNEL); 265fa74a025SManivannan Sadhasivam if (!ipcc) 266fa74a025SManivannan Sadhasivam return -ENOMEM; 267fa74a025SManivannan Sadhasivam 268fa74a025SManivannan Sadhasivam ipcc->dev = &pdev->dev; 269fa74a025SManivannan Sadhasivam 270fa74a025SManivannan Sadhasivam ipcc->base = devm_platform_ioremap_resource(pdev, 0); 271fa74a025SManivannan Sadhasivam if (IS_ERR(ipcc->base)) 272fa74a025SManivannan Sadhasivam return PTR_ERR(ipcc->base); 273fa74a025SManivannan Sadhasivam 274fa74a025SManivannan Sadhasivam ipcc->irq = platform_get_irq(pdev, 0); 275fa74a025SManivannan Sadhasivam if (ipcc->irq < 0) 276fa74a025SManivannan Sadhasivam return ipcc->irq; 277fa74a025SManivannan Sadhasivam 278*1f43e523SHuang Yiwei name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ipcc_%d", id++); 279*1f43e523SHuang Yiwei if (!name) 280*1f43e523SHuang Yiwei return -ENOMEM; 281*1f43e523SHuang Yiwei 282fa74a025SManivannan Sadhasivam ipcc->irq_domain = irq_domain_add_tree(pdev->dev.of_node, 283fa74a025SManivannan Sadhasivam &qcom_ipcc_irq_ops, ipcc); 284fa74a025SManivannan Sadhasivam if (!ipcc->irq_domain) 285fa74a025SManivannan Sadhasivam return -ENOMEM; 286fa74a025SManivannan Sadhasivam 287e9d50e4bSHuang Yiwei ret = qcom_ipcc_setup_mbox(ipcc, pdev->dev.of_node); 288fa74a025SManivannan Sadhasivam if (ret) 289fa74a025SManivannan Sadhasivam goto err_mbox; 290fa74a025SManivannan Sadhasivam 291fa74a025SManivannan Sadhasivam ret = devm_request_irq(&pdev->dev, ipcc->irq, qcom_ipcc_irq_fn, 292*1f43e523SHuang Yiwei IRQF_TRIGGER_HIGH, name, ipcc); 293fa74a025SManivannan Sadhasivam if (ret < 0) { 294fa74a025SManivannan Sadhasivam dev_err(&pdev->dev, "Failed to register the irq: %d\n", ret); 295e9d50e4bSHuang Yiwei goto err_req_irq; 296fa74a025SManivannan Sadhasivam } 297fa74a025SManivannan Sadhasivam 298fa74a025SManivannan Sadhasivam enable_irq_wake(ipcc->irq); 299fa74a025SManivannan Sadhasivam platform_set_drvdata(pdev, ipcc); 300fa74a025SManivannan Sadhasivam 301fa74a025SManivannan Sadhasivam return 0; 302fa74a025SManivannan Sadhasivam 303e9d50e4bSHuang Yiwei err_req_irq: 304e9d50e4bSHuang Yiwei if (ipcc->num_chans) 305e9d50e4bSHuang Yiwei mbox_controller_unregister(&ipcc->mbox); 306fa74a025SManivannan Sadhasivam err_mbox: 307fa74a025SManivannan Sadhasivam irq_domain_remove(ipcc->irq_domain); 308fa74a025SManivannan Sadhasivam 309fa74a025SManivannan Sadhasivam return ret; 310fa74a025SManivannan Sadhasivam } 311fa74a025SManivannan Sadhasivam 312fa74a025SManivannan Sadhasivam static int qcom_ipcc_remove(struct platform_device *pdev) 313fa74a025SManivannan Sadhasivam { 314fa74a025SManivannan Sadhasivam struct qcom_ipcc *ipcc = platform_get_drvdata(pdev); 315fa74a025SManivannan Sadhasivam 316fa74a025SManivannan Sadhasivam disable_irq_wake(ipcc->irq); 317fa74a025SManivannan Sadhasivam irq_domain_remove(ipcc->irq_domain); 318fa74a025SManivannan Sadhasivam 319fa74a025SManivannan Sadhasivam return 0; 320fa74a025SManivannan Sadhasivam } 321fa74a025SManivannan Sadhasivam 322fa74a025SManivannan Sadhasivam static const struct of_device_id qcom_ipcc_of_match[] = { 323fa74a025SManivannan Sadhasivam { .compatible = "qcom,ipcc"}, 324fa74a025SManivannan Sadhasivam {} 325fa74a025SManivannan Sadhasivam }; 326fa74a025SManivannan Sadhasivam MODULE_DEVICE_TABLE(of, qcom_ipcc_of_match); 327fa74a025SManivannan Sadhasivam 328fa74a025SManivannan Sadhasivam static struct platform_driver qcom_ipcc_driver = { 329fa74a025SManivannan Sadhasivam .probe = qcom_ipcc_probe, 330fa74a025SManivannan Sadhasivam .remove = qcom_ipcc_remove, 331fa74a025SManivannan Sadhasivam .driver = { 332fa74a025SManivannan Sadhasivam .name = "qcom-ipcc", 333fa74a025SManivannan Sadhasivam .of_match_table = qcom_ipcc_of_match, 3348d7e5908SAmit Pundir .suppress_bind_attrs = true, 335fa74a025SManivannan Sadhasivam }, 336fa74a025SManivannan Sadhasivam }; 337fa74a025SManivannan Sadhasivam 338fa74a025SManivannan Sadhasivam static int __init qcom_ipcc_init(void) 339fa74a025SManivannan Sadhasivam { 340fa74a025SManivannan Sadhasivam return platform_driver_register(&qcom_ipcc_driver); 341fa74a025SManivannan Sadhasivam } 342fa74a025SManivannan Sadhasivam arch_initcall(qcom_ipcc_init); 343fa74a025SManivannan Sadhasivam 344fa74a025SManivannan Sadhasivam MODULE_AUTHOR("Venkata Narendra Kumar Gutta <vnkgutta@codeaurora.org>"); 345fa74a025SManivannan Sadhasivam MODULE_AUTHOR("Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>"); 346fa74a025SManivannan Sadhasivam MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPCC driver"); 347fa74a025SManivannan Sadhasivam MODULE_LICENSE("GPL v2"); 348