1*ffbded7dSFabien Dessenne // SPDX-License-Identifier: GPL-2.0 2*ffbded7dSFabien Dessenne /* 3*ffbded7dSFabien Dessenne * Copyright (C) STMicroelectronics 2018 - All Rights Reserved 4*ffbded7dSFabien Dessenne * Authors: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics. 5*ffbded7dSFabien Dessenne * Fabien Dessenne <fabien.dessenne@st.com> for STMicroelectronics. 6*ffbded7dSFabien Dessenne */ 7*ffbded7dSFabien Dessenne 8*ffbded7dSFabien Dessenne #include <linux/bitfield.h> 9*ffbded7dSFabien Dessenne #include <linux/clk.h> 10*ffbded7dSFabien Dessenne #include <linux/interrupt.h> 11*ffbded7dSFabien Dessenne #include <linux/mailbox_controller.h> 12*ffbded7dSFabien Dessenne #include <linux/module.h> 13*ffbded7dSFabien Dessenne #include <linux/of_irq.h> 14*ffbded7dSFabien Dessenne #include <linux/platform_device.h> 15*ffbded7dSFabien Dessenne #include <linux/pm_wakeirq.h> 16*ffbded7dSFabien Dessenne 17*ffbded7dSFabien Dessenne #define IPCC_XCR 0x000 18*ffbded7dSFabien Dessenne #define XCR_RXOIE BIT(0) 19*ffbded7dSFabien Dessenne #define XCR_TXOIE BIT(16) 20*ffbded7dSFabien Dessenne 21*ffbded7dSFabien Dessenne #define IPCC_XMR 0x004 22*ffbded7dSFabien Dessenne #define IPCC_XSCR 0x008 23*ffbded7dSFabien Dessenne #define IPCC_XTOYSR 0x00c 24*ffbded7dSFabien Dessenne 25*ffbded7dSFabien Dessenne #define IPCC_PROC_OFFST 0x010 26*ffbded7dSFabien Dessenne 27*ffbded7dSFabien Dessenne #define IPCC_HWCFGR 0x3f0 28*ffbded7dSFabien Dessenne #define IPCFGR_CHAN_MASK GENMASK(7, 0) 29*ffbded7dSFabien Dessenne 30*ffbded7dSFabien Dessenne #define IPCC_VER 0x3f4 31*ffbded7dSFabien Dessenne #define VER_MINREV_MASK GENMASK(3, 0) 32*ffbded7dSFabien Dessenne #define VER_MAJREV_MASK GENMASK(7, 4) 33*ffbded7dSFabien Dessenne 34*ffbded7dSFabien Dessenne #define RX_BIT_MASK GENMASK(15, 0) 35*ffbded7dSFabien Dessenne #define RX_BIT_CHAN(chan) BIT(chan) 36*ffbded7dSFabien Dessenne #define TX_BIT_SHIFT 16 37*ffbded7dSFabien Dessenne #define TX_BIT_MASK GENMASK(31, 16) 38*ffbded7dSFabien Dessenne #define TX_BIT_CHAN(chan) BIT(TX_BIT_SHIFT + (chan)) 39*ffbded7dSFabien Dessenne 40*ffbded7dSFabien Dessenne #define STM32_MAX_PROCS 2 41*ffbded7dSFabien Dessenne 42*ffbded7dSFabien Dessenne enum { 43*ffbded7dSFabien Dessenne IPCC_IRQ_RX, 44*ffbded7dSFabien Dessenne IPCC_IRQ_TX, 45*ffbded7dSFabien Dessenne IPCC_IRQ_NUM, 46*ffbded7dSFabien Dessenne }; 47*ffbded7dSFabien Dessenne 48*ffbded7dSFabien Dessenne struct stm32_ipcc { 49*ffbded7dSFabien Dessenne struct mbox_controller controller; 50*ffbded7dSFabien Dessenne void __iomem *reg_base; 51*ffbded7dSFabien Dessenne void __iomem *reg_proc; 52*ffbded7dSFabien Dessenne struct clk *clk; 53*ffbded7dSFabien Dessenne int irqs[IPCC_IRQ_NUM]; 54*ffbded7dSFabien Dessenne int wkp; 55*ffbded7dSFabien Dessenne u32 proc_id; 56*ffbded7dSFabien Dessenne u32 n_chans; 57*ffbded7dSFabien Dessenne u32 xcr; 58*ffbded7dSFabien Dessenne u32 xmr; 59*ffbded7dSFabien Dessenne }; 60*ffbded7dSFabien Dessenne 61*ffbded7dSFabien Dessenne static inline void stm32_ipcc_set_bits(void __iomem *reg, u32 mask) 62*ffbded7dSFabien Dessenne { 63*ffbded7dSFabien Dessenne writel_relaxed(readl_relaxed(reg) | mask, reg); 64*ffbded7dSFabien Dessenne } 65*ffbded7dSFabien Dessenne 66*ffbded7dSFabien Dessenne static inline void stm32_ipcc_clr_bits(void __iomem *reg, u32 mask) 67*ffbded7dSFabien Dessenne { 68*ffbded7dSFabien Dessenne writel_relaxed(readl_relaxed(reg) & ~mask, reg); 69*ffbded7dSFabien Dessenne } 70*ffbded7dSFabien Dessenne 71*ffbded7dSFabien Dessenne static irqreturn_t stm32_ipcc_rx_irq(int irq, void *data) 72*ffbded7dSFabien Dessenne { 73*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = data; 74*ffbded7dSFabien Dessenne struct device *dev = ipcc->controller.dev; 75*ffbded7dSFabien Dessenne u32 status, mr, tosr, chan; 76*ffbded7dSFabien Dessenne irqreturn_t ret = IRQ_NONE; 77*ffbded7dSFabien Dessenne int proc_offset; 78*ffbded7dSFabien Dessenne 79*ffbded7dSFabien Dessenne /* read 'channel occupied' status from other proc */ 80*ffbded7dSFabien Dessenne proc_offset = ipcc->proc_id ? -IPCC_PROC_OFFST : IPCC_PROC_OFFST; 81*ffbded7dSFabien Dessenne tosr = readl_relaxed(ipcc->reg_proc + proc_offset + IPCC_XTOYSR); 82*ffbded7dSFabien Dessenne mr = readl_relaxed(ipcc->reg_proc + IPCC_XMR); 83*ffbded7dSFabien Dessenne 84*ffbded7dSFabien Dessenne /* search for unmasked 'channel occupied' */ 85*ffbded7dSFabien Dessenne status = tosr & FIELD_GET(RX_BIT_MASK, ~mr); 86*ffbded7dSFabien Dessenne 87*ffbded7dSFabien Dessenne for (chan = 0; chan < ipcc->n_chans; chan++) { 88*ffbded7dSFabien Dessenne if (!(status & (1 << chan))) 89*ffbded7dSFabien Dessenne continue; 90*ffbded7dSFabien Dessenne 91*ffbded7dSFabien Dessenne dev_dbg(dev, "%s: chan:%d rx\n", __func__, chan); 92*ffbded7dSFabien Dessenne 93*ffbded7dSFabien Dessenne mbox_chan_received_data(&ipcc->controller.chans[chan], NULL); 94*ffbded7dSFabien Dessenne 95*ffbded7dSFabien Dessenne stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, 96*ffbded7dSFabien Dessenne RX_BIT_CHAN(chan)); 97*ffbded7dSFabien Dessenne 98*ffbded7dSFabien Dessenne ret = IRQ_HANDLED; 99*ffbded7dSFabien Dessenne } 100*ffbded7dSFabien Dessenne 101*ffbded7dSFabien Dessenne return ret; 102*ffbded7dSFabien Dessenne } 103*ffbded7dSFabien Dessenne 104*ffbded7dSFabien Dessenne static irqreturn_t stm32_ipcc_tx_irq(int irq, void *data) 105*ffbded7dSFabien Dessenne { 106*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = data; 107*ffbded7dSFabien Dessenne struct device *dev = ipcc->controller.dev; 108*ffbded7dSFabien Dessenne u32 status, mr, tosr, chan; 109*ffbded7dSFabien Dessenne irqreturn_t ret = IRQ_NONE; 110*ffbded7dSFabien Dessenne 111*ffbded7dSFabien Dessenne tosr = readl_relaxed(ipcc->reg_proc + IPCC_XTOYSR); 112*ffbded7dSFabien Dessenne mr = readl_relaxed(ipcc->reg_proc + IPCC_XMR); 113*ffbded7dSFabien Dessenne 114*ffbded7dSFabien Dessenne /* search for unmasked 'channel free' */ 115*ffbded7dSFabien Dessenne status = ~tosr & FIELD_GET(TX_BIT_MASK, ~mr); 116*ffbded7dSFabien Dessenne 117*ffbded7dSFabien Dessenne for (chan = 0; chan < ipcc->n_chans ; chan++) { 118*ffbded7dSFabien Dessenne if (!(status & (1 << chan))) 119*ffbded7dSFabien Dessenne continue; 120*ffbded7dSFabien Dessenne 121*ffbded7dSFabien Dessenne dev_dbg(dev, "%s: chan:%d tx\n", __func__, chan); 122*ffbded7dSFabien Dessenne 123*ffbded7dSFabien Dessenne /* mask 'tx channel free' interrupt */ 124*ffbded7dSFabien Dessenne stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, 125*ffbded7dSFabien Dessenne TX_BIT_CHAN(chan)); 126*ffbded7dSFabien Dessenne 127*ffbded7dSFabien Dessenne mbox_chan_txdone(&ipcc->controller.chans[chan], 0); 128*ffbded7dSFabien Dessenne 129*ffbded7dSFabien Dessenne ret = IRQ_HANDLED; 130*ffbded7dSFabien Dessenne } 131*ffbded7dSFabien Dessenne 132*ffbded7dSFabien Dessenne return ret; 133*ffbded7dSFabien Dessenne } 134*ffbded7dSFabien Dessenne 135*ffbded7dSFabien Dessenne static int stm32_ipcc_send_data(struct mbox_chan *link, void *data) 136*ffbded7dSFabien Dessenne { 137*ffbded7dSFabien Dessenne unsigned int chan = (unsigned int)link->con_priv; 138*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = container_of(link->mbox, struct stm32_ipcc, 139*ffbded7dSFabien Dessenne controller); 140*ffbded7dSFabien Dessenne 141*ffbded7dSFabien Dessenne dev_dbg(ipcc->controller.dev, "%s: chan:%d\n", __func__, chan); 142*ffbded7dSFabien Dessenne 143*ffbded7dSFabien Dessenne /* set channel n occupied */ 144*ffbded7dSFabien Dessenne stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XSCR, TX_BIT_CHAN(chan)); 145*ffbded7dSFabien Dessenne 146*ffbded7dSFabien Dessenne /* unmask 'tx channel free' interrupt */ 147*ffbded7dSFabien Dessenne stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, TX_BIT_CHAN(chan)); 148*ffbded7dSFabien Dessenne 149*ffbded7dSFabien Dessenne return 0; 150*ffbded7dSFabien Dessenne } 151*ffbded7dSFabien Dessenne 152*ffbded7dSFabien Dessenne static int stm32_ipcc_startup(struct mbox_chan *link) 153*ffbded7dSFabien Dessenne { 154*ffbded7dSFabien Dessenne unsigned int chan = (unsigned int)link->con_priv; 155*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = container_of(link->mbox, struct stm32_ipcc, 156*ffbded7dSFabien Dessenne controller); 157*ffbded7dSFabien Dessenne int ret; 158*ffbded7dSFabien Dessenne 159*ffbded7dSFabien Dessenne ret = clk_prepare_enable(ipcc->clk); 160*ffbded7dSFabien Dessenne if (ret) { 161*ffbded7dSFabien Dessenne dev_err(ipcc->controller.dev, "can not enable the clock\n"); 162*ffbded7dSFabien Dessenne return ret; 163*ffbded7dSFabien Dessenne } 164*ffbded7dSFabien Dessenne 165*ffbded7dSFabien Dessenne /* unmask 'rx channel occupied' interrupt */ 166*ffbded7dSFabien Dessenne stm32_ipcc_clr_bits(ipcc->reg_proc + IPCC_XMR, RX_BIT_CHAN(chan)); 167*ffbded7dSFabien Dessenne 168*ffbded7dSFabien Dessenne return 0; 169*ffbded7dSFabien Dessenne } 170*ffbded7dSFabien Dessenne 171*ffbded7dSFabien Dessenne static void stm32_ipcc_shutdown(struct mbox_chan *link) 172*ffbded7dSFabien Dessenne { 173*ffbded7dSFabien Dessenne unsigned int chan = (unsigned int)link->con_priv; 174*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = container_of(link->mbox, struct stm32_ipcc, 175*ffbded7dSFabien Dessenne controller); 176*ffbded7dSFabien Dessenne 177*ffbded7dSFabien Dessenne /* mask rx/tx interrupt */ 178*ffbded7dSFabien Dessenne stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, 179*ffbded7dSFabien Dessenne RX_BIT_CHAN(chan) | TX_BIT_CHAN(chan)); 180*ffbded7dSFabien Dessenne 181*ffbded7dSFabien Dessenne clk_disable_unprepare(ipcc->clk); 182*ffbded7dSFabien Dessenne } 183*ffbded7dSFabien Dessenne 184*ffbded7dSFabien Dessenne static const struct mbox_chan_ops stm32_ipcc_ops = { 185*ffbded7dSFabien Dessenne .send_data = stm32_ipcc_send_data, 186*ffbded7dSFabien Dessenne .startup = stm32_ipcc_startup, 187*ffbded7dSFabien Dessenne .shutdown = stm32_ipcc_shutdown, 188*ffbded7dSFabien Dessenne }; 189*ffbded7dSFabien Dessenne 190*ffbded7dSFabien Dessenne static int stm32_ipcc_probe(struct platform_device *pdev) 191*ffbded7dSFabien Dessenne { 192*ffbded7dSFabien Dessenne struct device *dev = &pdev->dev; 193*ffbded7dSFabien Dessenne struct device_node *np = dev->of_node; 194*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc; 195*ffbded7dSFabien Dessenne struct resource *res; 196*ffbded7dSFabien Dessenne unsigned int i; 197*ffbded7dSFabien Dessenne int ret; 198*ffbded7dSFabien Dessenne u32 ip_ver; 199*ffbded7dSFabien Dessenne static const char * const irq_name[] = {"rx", "tx"}; 200*ffbded7dSFabien Dessenne irq_handler_t irq_thread[] = {stm32_ipcc_rx_irq, stm32_ipcc_tx_irq}; 201*ffbded7dSFabien Dessenne 202*ffbded7dSFabien Dessenne if (!np) { 203*ffbded7dSFabien Dessenne dev_err(dev, "No DT found\n"); 204*ffbded7dSFabien Dessenne return -ENODEV; 205*ffbded7dSFabien Dessenne } 206*ffbded7dSFabien Dessenne 207*ffbded7dSFabien Dessenne ipcc = devm_kzalloc(dev, sizeof(*ipcc), GFP_KERNEL); 208*ffbded7dSFabien Dessenne if (!ipcc) 209*ffbded7dSFabien Dessenne return -ENOMEM; 210*ffbded7dSFabien Dessenne 211*ffbded7dSFabien Dessenne /* proc_id */ 212*ffbded7dSFabien Dessenne if (of_property_read_u32(np, "st,proc-id", &ipcc->proc_id)) { 213*ffbded7dSFabien Dessenne dev_err(dev, "Missing st,proc-id\n"); 214*ffbded7dSFabien Dessenne return -ENODEV; 215*ffbded7dSFabien Dessenne } 216*ffbded7dSFabien Dessenne 217*ffbded7dSFabien Dessenne if (ipcc->proc_id >= STM32_MAX_PROCS) { 218*ffbded7dSFabien Dessenne dev_err(dev, "Invalid proc_id (%d)\n", ipcc->proc_id); 219*ffbded7dSFabien Dessenne return -EINVAL; 220*ffbded7dSFabien Dessenne } 221*ffbded7dSFabien Dessenne 222*ffbded7dSFabien Dessenne /* regs */ 223*ffbded7dSFabien Dessenne res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 224*ffbded7dSFabien Dessenne ipcc->reg_base = devm_ioremap_resource(dev, res); 225*ffbded7dSFabien Dessenne if (IS_ERR(ipcc->reg_base)) 226*ffbded7dSFabien Dessenne return PTR_ERR(ipcc->reg_base); 227*ffbded7dSFabien Dessenne 228*ffbded7dSFabien Dessenne ipcc->reg_proc = ipcc->reg_base + ipcc->proc_id * IPCC_PROC_OFFST; 229*ffbded7dSFabien Dessenne 230*ffbded7dSFabien Dessenne /* clock */ 231*ffbded7dSFabien Dessenne ipcc->clk = devm_clk_get(dev, NULL); 232*ffbded7dSFabien Dessenne if (IS_ERR(ipcc->clk)) 233*ffbded7dSFabien Dessenne return PTR_ERR(ipcc->clk); 234*ffbded7dSFabien Dessenne 235*ffbded7dSFabien Dessenne ret = clk_prepare_enable(ipcc->clk); 236*ffbded7dSFabien Dessenne if (ret) { 237*ffbded7dSFabien Dessenne dev_err(dev, "can not enable the clock\n"); 238*ffbded7dSFabien Dessenne return ret; 239*ffbded7dSFabien Dessenne } 240*ffbded7dSFabien Dessenne 241*ffbded7dSFabien Dessenne /* irq */ 242*ffbded7dSFabien Dessenne for (i = 0; i < IPCC_IRQ_NUM; i++) { 243*ffbded7dSFabien Dessenne ipcc->irqs[i] = of_irq_get_byname(dev->of_node, irq_name[i]); 244*ffbded7dSFabien Dessenne if (ipcc->irqs[i] < 0) { 245*ffbded7dSFabien Dessenne dev_err(dev, "no IRQ specified %s\n", irq_name[i]); 246*ffbded7dSFabien Dessenne ret = ipcc->irqs[i]; 247*ffbded7dSFabien Dessenne goto err_clk; 248*ffbded7dSFabien Dessenne } 249*ffbded7dSFabien Dessenne 250*ffbded7dSFabien Dessenne ret = devm_request_threaded_irq(dev, ipcc->irqs[i], NULL, 251*ffbded7dSFabien Dessenne irq_thread[i], IRQF_ONESHOT, 252*ffbded7dSFabien Dessenne dev_name(dev), ipcc); 253*ffbded7dSFabien Dessenne if (ret) { 254*ffbded7dSFabien Dessenne dev_err(dev, "failed to request irq %d (%d)\n", i, ret); 255*ffbded7dSFabien Dessenne goto err_clk; 256*ffbded7dSFabien Dessenne } 257*ffbded7dSFabien Dessenne } 258*ffbded7dSFabien Dessenne 259*ffbded7dSFabien Dessenne /* mask and enable rx/tx irq */ 260*ffbded7dSFabien Dessenne stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XMR, 261*ffbded7dSFabien Dessenne RX_BIT_MASK | TX_BIT_MASK); 262*ffbded7dSFabien Dessenne stm32_ipcc_set_bits(ipcc->reg_proc + IPCC_XCR, XCR_RXOIE | XCR_TXOIE); 263*ffbded7dSFabien Dessenne 264*ffbded7dSFabien Dessenne /* wakeup */ 265*ffbded7dSFabien Dessenne if (of_property_read_bool(np, "wakeup-source")) { 266*ffbded7dSFabien Dessenne ipcc->wkp = of_irq_get_byname(dev->of_node, "wakeup"); 267*ffbded7dSFabien Dessenne if (ipcc->wkp < 0) { 268*ffbded7dSFabien Dessenne dev_err(dev, "could not get wakeup IRQ\n"); 269*ffbded7dSFabien Dessenne ret = ipcc->wkp; 270*ffbded7dSFabien Dessenne goto err_clk; 271*ffbded7dSFabien Dessenne } 272*ffbded7dSFabien Dessenne 273*ffbded7dSFabien Dessenne device_init_wakeup(dev, true); 274*ffbded7dSFabien Dessenne ret = dev_pm_set_dedicated_wake_irq(dev, ipcc->wkp); 275*ffbded7dSFabien Dessenne if (ret) { 276*ffbded7dSFabien Dessenne dev_err(dev, "Failed to set wake up irq\n"); 277*ffbded7dSFabien Dessenne goto err_init_wkp; 278*ffbded7dSFabien Dessenne } 279*ffbded7dSFabien Dessenne } else { 280*ffbded7dSFabien Dessenne device_init_wakeup(dev, false); 281*ffbded7dSFabien Dessenne } 282*ffbded7dSFabien Dessenne 283*ffbded7dSFabien Dessenne /* mailbox controller */ 284*ffbded7dSFabien Dessenne ipcc->n_chans = readl_relaxed(ipcc->reg_base + IPCC_HWCFGR); 285*ffbded7dSFabien Dessenne ipcc->n_chans &= IPCFGR_CHAN_MASK; 286*ffbded7dSFabien Dessenne 287*ffbded7dSFabien Dessenne ipcc->controller.dev = dev; 288*ffbded7dSFabien Dessenne ipcc->controller.txdone_irq = true; 289*ffbded7dSFabien Dessenne ipcc->controller.ops = &stm32_ipcc_ops; 290*ffbded7dSFabien Dessenne ipcc->controller.num_chans = ipcc->n_chans; 291*ffbded7dSFabien Dessenne ipcc->controller.chans = devm_kcalloc(dev, ipcc->controller.num_chans, 292*ffbded7dSFabien Dessenne sizeof(*ipcc->controller.chans), 293*ffbded7dSFabien Dessenne GFP_KERNEL); 294*ffbded7dSFabien Dessenne if (!ipcc->controller.chans) { 295*ffbded7dSFabien Dessenne ret = -ENOMEM; 296*ffbded7dSFabien Dessenne goto err_irq_wkp; 297*ffbded7dSFabien Dessenne } 298*ffbded7dSFabien Dessenne 299*ffbded7dSFabien Dessenne for (i = 0; i < ipcc->controller.num_chans; i++) 300*ffbded7dSFabien Dessenne ipcc->controller.chans[i].con_priv = (void *)i; 301*ffbded7dSFabien Dessenne 302*ffbded7dSFabien Dessenne ret = mbox_controller_register(&ipcc->controller); 303*ffbded7dSFabien Dessenne if (ret) 304*ffbded7dSFabien Dessenne goto err_irq_wkp; 305*ffbded7dSFabien Dessenne 306*ffbded7dSFabien Dessenne platform_set_drvdata(pdev, ipcc); 307*ffbded7dSFabien Dessenne 308*ffbded7dSFabien Dessenne ip_ver = readl_relaxed(ipcc->reg_base + IPCC_VER); 309*ffbded7dSFabien Dessenne 310*ffbded7dSFabien Dessenne dev_info(dev, "ipcc rev:%ld.%ld enabled, %d chans, proc %d\n", 311*ffbded7dSFabien Dessenne FIELD_GET(VER_MAJREV_MASK, ip_ver), 312*ffbded7dSFabien Dessenne FIELD_GET(VER_MINREV_MASK, ip_ver), 313*ffbded7dSFabien Dessenne ipcc->controller.num_chans, ipcc->proc_id); 314*ffbded7dSFabien Dessenne 315*ffbded7dSFabien Dessenne clk_disable_unprepare(ipcc->clk); 316*ffbded7dSFabien Dessenne return 0; 317*ffbded7dSFabien Dessenne 318*ffbded7dSFabien Dessenne err_irq_wkp: 319*ffbded7dSFabien Dessenne if (ipcc->wkp) 320*ffbded7dSFabien Dessenne dev_pm_clear_wake_irq(dev); 321*ffbded7dSFabien Dessenne err_init_wkp: 322*ffbded7dSFabien Dessenne device_init_wakeup(dev, false); 323*ffbded7dSFabien Dessenne err_clk: 324*ffbded7dSFabien Dessenne clk_disable_unprepare(ipcc->clk); 325*ffbded7dSFabien Dessenne return ret; 326*ffbded7dSFabien Dessenne } 327*ffbded7dSFabien Dessenne 328*ffbded7dSFabien Dessenne static int stm32_ipcc_remove(struct platform_device *pdev) 329*ffbded7dSFabien Dessenne { 330*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = platform_get_drvdata(pdev); 331*ffbded7dSFabien Dessenne 332*ffbded7dSFabien Dessenne mbox_controller_unregister(&ipcc->controller); 333*ffbded7dSFabien Dessenne 334*ffbded7dSFabien Dessenne if (ipcc->wkp) 335*ffbded7dSFabien Dessenne dev_pm_clear_wake_irq(&pdev->dev); 336*ffbded7dSFabien Dessenne 337*ffbded7dSFabien Dessenne device_init_wakeup(&pdev->dev, false); 338*ffbded7dSFabien Dessenne 339*ffbded7dSFabien Dessenne return 0; 340*ffbded7dSFabien Dessenne } 341*ffbded7dSFabien Dessenne 342*ffbded7dSFabien Dessenne #ifdef CONFIG_PM_SLEEP 343*ffbded7dSFabien Dessenne static void stm32_ipcc_set_irq_wake(struct device *dev, bool enable) 344*ffbded7dSFabien Dessenne { 345*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = dev_get_drvdata(dev); 346*ffbded7dSFabien Dessenne unsigned int i; 347*ffbded7dSFabien Dessenne 348*ffbded7dSFabien Dessenne if (device_may_wakeup(dev)) 349*ffbded7dSFabien Dessenne for (i = 0; i < IPCC_IRQ_NUM; i++) 350*ffbded7dSFabien Dessenne irq_set_irq_wake(ipcc->irqs[i], enable); 351*ffbded7dSFabien Dessenne } 352*ffbded7dSFabien Dessenne 353*ffbded7dSFabien Dessenne static int stm32_ipcc_suspend(struct device *dev) 354*ffbded7dSFabien Dessenne { 355*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = dev_get_drvdata(dev); 356*ffbded7dSFabien Dessenne 357*ffbded7dSFabien Dessenne ipcc->xmr = readl_relaxed(ipcc->reg_proc + IPCC_XMR); 358*ffbded7dSFabien Dessenne ipcc->xcr = readl_relaxed(ipcc->reg_proc + IPCC_XCR); 359*ffbded7dSFabien Dessenne 360*ffbded7dSFabien Dessenne stm32_ipcc_set_irq_wake(dev, true); 361*ffbded7dSFabien Dessenne 362*ffbded7dSFabien Dessenne return 0; 363*ffbded7dSFabien Dessenne } 364*ffbded7dSFabien Dessenne 365*ffbded7dSFabien Dessenne static int stm32_ipcc_resume(struct device *dev) 366*ffbded7dSFabien Dessenne { 367*ffbded7dSFabien Dessenne struct stm32_ipcc *ipcc = dev_get_drvdata(dev); 368*ffbded7dSFabien Dessenne 369*ffbded7dSFabien Dessenne stm32_ipcc_set_irq_wake(dev, false); 370*ffbded7dSFabien Dessenne 371*ffbded7dSFabien Dessenne writel_relaxed(ipcc->xmr, ipcc->reg_proc + IPCC_XMR); 372*ffbded7dSFabien Dessenne writel_relaxed(ipcc->xcr, ipcc->reg_proc + IPCC_XCR); 373*ffbded7dSFabien Dessenne 374*ffbded7dSFabien Dessenne return 0; 375*ffbded7dSFabien Dessenne } 376*ffbded7dSFabien Dessenne #endif 377*ffbded7dSFabien Dessenne 378*ffbded7dSFabien Dessenne static SIMPLE_DEV_PM_OPS(stm32_ipcc_pm_ops, 379*ffbded7dSFabien Dessenne stm32_ipcc_suspend, stm32_ipcc_resume); 380*ffbded7dSFabien Dessenne 381*ffbded7dSFabien Dessenne static const struct of_device_id stm32_ipcc_of_match[] = { 382*ffbded7dSFabien Dessenne { .compatible = "st,stm32mp1-ipcc" }, 383*ffbded7dSFabien Dessenne {}, 384*ffbded7dSFabien Dessenne }; 385*ffbded7dSFabien Dessenne MODULE_DEVICE_TABLE(of, stm32_ipcc_of_match); 386*ffbded7dSFabien Dessenne 387*ffbded7dSFabien Dessenne static struct platform_driver stm32_ipcc_driver = { 388*ffbded7dSFabien Dessenne .driver = { 389*ffbded7dSFabien Dessenne .name = "stm32-ipcc", 390*ffbded7dSFabien Dessenne .pm = &stm32_ipcc_pm_ops, 391*ffbded7dSFabien Dessenne .of_match_table = stm32_ipcc_of_match, 392*ffbded7dSFabien Dessenne }, 393*ffbded7dSFabien Dessenne .probe = stm32_ipcc_probe, 394*ffbded7dSFabien Dessenne .remove = stm32_ipcc_remove, 395*ffbded7dSFabien Dessenne }; 396*ffbded7dSFabien Dessenne 397*ffbded7dSFabien Dessenne module_platform_driver(stm32_ipcc_driver); 398*ffbded7dSFabien Dessenne 399*ffbded7dSFabien Dessenne MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>"); 400*ffbded7dSFabien Dessenne MODULE_AUTHOR("Fabien Dessenne <fabien.dessenne@st.com>"); 401*ffbded7dSFabien Dessenne MODULE_DESCRIPTION("STM32 IPCC driver"); 402*ffbded7dSFabien Dessenne MODULE_LICENSE("GPL v2"); 403