Lines Matching +full:mpfs +full:- +full:can
1 // SPDX-License-Identifier: GPL-2.0
3 * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver
5 * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved.
22 #include <soc/microchip/mpfs.h>
46 #define SCB_CTRL_MASK GENMASK(SCB_CTRL_POS + SCB_MASK_WIDTH - 1, SCB_CTRL_POS)
63 #define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS)
82 if (mbox->control_scb) in mpfs_mbox_busy()
83 regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &status); in mpfs_mbox_busy()
85 status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); in mpfs_mbox_busy()
92 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; in mpfs_mbox_last_tx_done()
93 struct mpfs_mss_response *response = mbox->response; in mpfs_mbox_last_tx_done()
105 if (mbox->control_scb) in mpfs_mbox_last_tx_done()
106 regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &val); in mpfs_mbox_last_tx_done()
108 val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET); in mpfs_mbox_last_tx_done()
110 response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS; in mpfs_mbox_last_tx_done()
117 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; in mpfs_mbox_send_data()
123 mbox->response = msg->response; in mpfs_mbox_send_data()
124 mbox->resp_offset = msg->resp_offset; in mpfs_mbox_send_data()
127 return -EBUSY; in mpfs_mbox_send_data()
129 if (msg->cmd_data_size) { in mpfs_mbox_send_data()
131 u8 extra_bits = msg->cmd_data_size & 3; in mpfs_mbox_send_data()
132 u32 *word_buf = (u32 *)msg->cmd_data; in mpfs_mbox_send_data()
134 for (index = 0; index < (msg->cmd_data_size / 4); index++) in mpfs_mbox_send_data()
136 mbox->mbox_base + msg->mbox_offset + index * 0x4); in mpfs_mbox_send_data()
139 u8 byte_off = ALIGN_DOWN(msg->cmd_data_size, 4); in mpfs_mbox_send_data()
140 u8 *byte_buf = msg->cmd_data + byte_off; in mpfs_mbox_send_data()
142 val = readl_relaxed(mbox->mbox_base + msg->mbox_offset + index * 0x4); in mpfs_mbox_send_data()
149 writel_relaxed(val, mbox->mbox_base + msg->mbox_offset + index * 0x4); in mpfs_mbox_send_data()
153 opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu)); in mpfs_mbox_send_data()
158 if (mbox->control_scb) in mpfs_mbox_send_data()
159 regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, tx_trigger); in mpfs_mbox_send_data()
161 writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET); in mpfs_mbox_send_data()
169 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; in mpfs_mbox_rx_data()
170 struct mpfs_mss_response *response = mbox->response; in mpfs_mbox_rx_data()
171 u16 num_words = ALIGN((response->resp_size), (4)) / 4U; in mpfs_mbox_rx_data()
174 if (!response->resp_msg) { in mpfs_mbox_rx_data()
175 dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM); in mpfs_mbox_rx_data()
185 dev_err(mbox->dev, "got an interrupt but system controller is busy\n"); in mpfs_mbox_rx_data()
186 response->resp_status = 0xDEAD; in mpfs_mbox_rx_data()
191 response->resp_msg[i] = in mpfs_mbox_rx_data()
192 readl_relaxed(mbox->mbox_base in mpfs_mbox_rx_data()
193 + mbox->resp_offset + i * 0x4); in mpfs_mbox_rx_data()
202 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; in mpfs_mbox_inbox_isr()
204 if (mbox->control_scb) in mpfs_mbox_inbox_isr()
205 regmap_write(mbox->sysreg_scb, MESSAGE_INT_OFFSET, 0); in mpfs_mbox_inbox_isr()
207 writel_relaxed(0, mbox->int_reg); in mpfs_mbox_inbox_isr()
216 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; in mpfs_mbox_startup()
220 return -EINVAL; in mpfs_mbox_startup()
222 ret = devm_request_irq(mbox->dev, mbox->irq, mpfs_mbox_inbox_isr, 0, "mpfs-mailbox", chan); in mpfs_mbox_startup()
224 dev_err(mbox->dev, "failed to register mailbox interrupt:%d\n", ret); in mpfs_mbox_startup()
231 struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv; in mpfs_mbox_shutdown()
233 devm_free_irq(mbox->dev, mbox->irq, chan); in mpfs_mbox_shutdown()
245 mbox->control_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-control-scb"); in mpfs_mbox_syscon_probe()
246 if (IS_ERR(mbox->control_scb)) in mpfs_mbox_syscon_probe()
247 return PTR_ERR(mbox->control_scb); in mpfs_mbox_syscon_probe()
249 mbox->sysreg_scb = syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb"); in mpfs_mbox_syscon_probe()
250 if (IS_ERR(mbox->sysreg_scb)) in mpfs_mbox_syscon_probe()
251 return PTR_ERR(mbox->sysreg_scb); in mpfs_mbox_syscon_probe()
253 mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0); in mpfs_mbox_syscon_probe()
254 if (IS_ERR(mbox->ctrl_base)) in mpfs_mbox_syscon_probe()
255 return PTR_ERR(mbox->mbox_base); in mpfs_mbox_syscon_probe()
262 dev_warn(&pdev->dev, "falling back to old devicetree format"); in mpfs_mbox_old_format_probe()
264 mbox->ctrl_base = devm_platform_ioremap_resource(pdev, 0); in mpfs_mbox_old_format_probe()
265 if (IS_ERR(mbox->ctrl_base)) in mpfs_mbox_old_format_probe()
266 return PTR_ERR(mbox->ctrl_base); in mpfs_mbox_old_format_probe()
268 mbox->int_reg = devm_platform_ioremap_resource(pdev, 1); in mpfs_mbox_old_format_probe()
269 if (IS_ERR(mbox->int_reg)) in mpfs_mbox_old_format_probe()
270 return PTR_ERR(mbox->int_reg); in mpfs_mbox_old_format_probe()
272 mbox->mbox_base = devm_platform_ioremap_resource(pdev, 2); in mpfs_mbox_old_format_probe()
273 if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs in mpfs_mbox_old_format_probe()
274 mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET; in mpfs_mbox_old_format_probe()
284 mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); in mpfs_mbox_probe()
286 return -ENOMEM; in mpfs_mbox_probe()
291 * set this to null, so it can be used as the decision for to in mpfs_mbox_probe()
294 mbox->control_scb = NULL; in mpfs_mbox_probe()
299 mbox->irq = platform_get_irq(pdev, 0); in mpfs_mbox_probe()
300 if (mbox->irq < 0) in mpfs_mbox_probe()
301 return mbox->irq; in mpfs_mbox_probe()
303 mbox->dev = &pdev->dev; in mpfs_mbox_probe()
305 mbox->chans[0].con_priv = mbox; in mpfs_mbox_probe()
306 mbox->controller.dev = mbox->dev; in mpfs_mbox_probe()
307 mbox->controller.num_chans = 1; in mpfs_mbox_probe()
308 mbox->controller.chans = mbox->chans; in mpfs_mbox_probe()
309 mbox->controller.ops = &mpfs_mbox_ops; in mpfs_mbox_probe()
310 mbox->controller.txdone_poll = true; in mpfs_mbox_probe()
311 mbox->controller.txpoll_period = 10u; in mpfs_mbox_probe()
313 ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller); in mpfs_mbox_probe()
315 dev_err(&pdev->dev, "Registering MPFS mailbox controller failed\n"); in mpfs_mbox_probe()
318 dev_info(&pdev->dev, "Registered MPFS mailbox controller driver\n"); in mpfs_mbox_probe()
324 {.compatible = "microchip,mpfs-mailbox", },
331 .name = "mpfs-mailbox",
340 MODULE_DESCRIPTION("MPFS mailbox controller driver");