0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/apple-mailbox.h>
0020 #include <linux/device.h>
0021 #include <linux/gfp.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/io.h>
0024 #include <linux/mailbox_controller.h>
0025 #include <linux/module.h>
0026 #include <linux/of.h>
0027 #include <linux/platform_device.h>
0028 #include <linux/types.h>
0029
0030 #define APPLE_ASC_MBOX_CONTROL_FULL BIT(16)
0031 #define APPLE_ASC_MBOX_CONTROL_EMPTY BIT(17)
0032
0033 #define APPLE_ASC_MBOX_A2I_CONTROL 0x110
0034 #define APPLE_ASC_MBOX_A2I_SEND0 0x800
0035 #define APPLE_ASC_MBOX_A2I_SEND1 0x808
0036 #define APPLE_ASC_MBOX_A2I_RECV0 0x810
0037 #define APPLE_ASC_MBOX_A2I_RECV1 0x818
0038
0039 #define APPLE_ASC_MBOX_I2A_CONTROL 0x114
0040 #define APPLE_ASC_MBOX_I2A_SEND0 0x820
0041 #define APPLE_ASC_MBOX_I2A_SEND1 0x828
0042 #define APPLE_ASC_MBOX_I2A_RECV0 0x830
0043 #define APPLE_ASC_MBOX_I2A_RECV1 0x838
0044
0045 #define APPLE_M3_MBOX_CONTROL_FULL BIT(16)
0046 #define APPLE_M3_MBOX_CONTROL_EMPTY BIT(17)
0047
0048 #define APPLE_M3_MBOX_A2I_CONTROL 0x50
0049 #define APPLE_M3_MBOX_A2I_SEND0 0x60
0050 #define APPLE_M3_MBOX_A2I_SEND1 0x68
0051 #define APPLE_M3_MBOX_A2I_RECV0 0x70
0052 #define APPLE_M3_MBOX_A2I_RECV1 0x78
0053
0054 #define APPLE_M3_MBOX_I2A_CONTROL 0x80
0055 #define APPLE_M3_MBOX_I2A_SEND0 0x90
0056 #define APPLE_M3_MBOX_I2A_SEND1 0x98
0057 #define APPLE_M3_MBOX_I2A_RECV0 0xa0
0058 #define APPLE_M3_MBOX_I2A_RECV1 0xa8
0059
0060 #define APPLE_M3_MBOX_IRQ_ENABLE 0x48
0061 #define APPLE_M3_MBOX_IRQ_ACK 0x4c
0062 #define APPLE_M3_MBOX_IRQ_A2I_EMPTY BIT(0)
0063 #define APPLE_M3_MBOX_IRQ_A2I_NOT_EMPTY BIT(1)
0064 #define APPLE_M3_MBOX_IRQ_I2A_EMPTY BIT(2)
0065 #define APPLE_M3_MBOX_IRQ_I2A_NOT_EMPTY BIT(3)
0066
0067 #define APPLE_MBOX_MSG1_OUTCNT GENMASK(56, 52)
0068 #define APPLE_MBOX_MSG1_INCNT GENMASK(51, 48)
0069 #define APPLE_MBOX_MSG1_OUTPTR GENMASK(47, 44)
0070 #define APPLE_MBOX_MSG1_INPTR GENMASK(43, 40)
0071 #define APPLE_MBOX_MSG1_MSG GENMASK(31, 0)
0072
0073 struct apple_mbox_hw {
0074 unsigned int control_full;
0075 unsigned int control_empty;
0076
0077 unsigned int a2i_control;
0078 unsigned int a2i_send0;
0079 unsigned int a2i_send1;
0080
0081 unsigned int i2a_control;
0082 unsigned int i2a_recv0;
0083 unsigned int i2a_recv1;
0084
0085 bool has_irq_controls;
0086 unsigned int irq_enable;
0087 unsigned int irq_ack;
0088 unsigned int irq_bit_recv_not_empty;
0089 unsigned int irq_bit_send_empty;
0090 };
0091
0092 struct apple_mbox {
0093 void __iomem *regs;
0094 const struct apple_mbox_hw *hw;
0095
0096 int irq_recv_not_empty;
0097 int irq_send_empty;
0098
0099 struct mbox_chan chan;
0100
0101 struct device *dev;
0102 struct mbox_controller controller;
0103 };
0104
0105 static const struct of_device_id apple_mbox_of_match[];
0106
0107 static bool apple_mbox_hw_can_send(struct apple_mbox *apple_mbox)
0108 {
0109 u32 mbox_ctrl =
0110 readl_relaxed(apple_mbox->regs + apple_mbox->hw->a2i_control);
0111
0112 return !(mbox_ctrl & apple_mbox->hw->control_full);
0113 }
0114
0115 static int apple_mbox_hw_send(struct apple_mbox *apple_mbox,
0116 struct apple_mbox_msg *msg)
0117 {
0118 if (!apple_mbox_hw_can_send(apple_mbox))
0119 return -EBUSY;
0120
0121 dev_dbg(apple_mbox->dev, "> TX %016llx %08x\n", msg->msg0, msg->msg1);
0122
0123 writeq_relaxed(msg->msg0, apple_mbox->regs + apple_mbox->hw->a2i_send0);
0124 writeq_relaxed(FIELD_PREP(APPLE_MBOX_MSG1_MSG, msg->msg1),
0125 apple_mbox->regs + apple_mbox->hw->a2i_send1);
0126
0127 return 0;
0128 }
0129
0130 static bool apple_mbox_hw_can_recv(struct apple_mbox *apple_mbox)
0131 {
0132 u32 mbox_ctrl =
0133 readl_relaxed(apple_mbox->regs + apple_mbox->hw->i2a_control);
0134
0135 return !(mbox_ctrl & apple_mbox->hw->control_empty);
0136 }
0137
0138 static int apple_mbox_hw_recv(struct apple_mbox *apple_mbox,
0139 struct apple_mbox_msg *msg)
0140 {
0141 if (!apple_mbox_hw_can_recv(apple_mbox))
0142 return -ENOMSG;
0143
0144 msg->msg0 = readq_relaxed(apple_mbox->regs + apple_mbox->hw->i2a_recv0);
0145 msg->msg1 = FIELD_GET(
0146 APPLE_MBOX_MSG1_MSG,
0147 readq_relaxed(apple_mbox->regs + apple_mbox->hw->i2a_recv1));
0148
0149 dev_dbg(apple_mbox->dev, "< RX %016llx %08x\n", msg->msg0, msg->msg1);
0150
0151 return 0;
0152 }
0153
0154 static int apple_mbox_chan_send_data(struct mbox_chan *chan, void *data)
0155 {
0156 struct apple_mbox *apple_mbox = chan->con_priv;
0157 struct apple_mbox_msg *msg = data;
0158 int ret;
0159
0160 ret = apple_mbox_hw_send(apple_mbox, msg);
0161 if (ret)
0162 return ret;
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173 if (apple_mbox->hw->has_irq_controls) {
0174 writel_relaxed(apple_mbox->hw->irq_bit_send_empty,
0175 apple_mbox->regs + apple_mbox->hw->irq_ack);
0176 }
0177 enable_irq(apple_mbox->irq_send_empty);
0178
0179 return 0;
0180 }
0181
0182 static irqreturn_t apple_mbox_send_empty_irq(int irq, void *data)
0183 {
0184 struct apple_mbox *apple_mbox = data;
0185
0186
0187
0188
0189
0190
0191
0192
0193 disable_irq_nosync(apple_mbox->irq_send_empty);
0194 mbox_chan_txdone(&apple_mbox->chan, 0);
0195 return IRQ_HANDLED;
0196 }
0197
0198 static irqreturn_t apple_mbox_recv_irq(int irq, void *data)
0199 {
0200 struct apple_mbox *apple_mbox = data;
0201 struct apple_mbox_msg msg;
0202
0203 while (apple_mbox_hw_recv(apple_mbox, &msg) == 0)
0204 mbox_chan_received_data(&apple_mbox->chan, (void *)&msg);
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214 if (apple_mbox->hw->has_irq_controls) {
0215 writel_relaxed(apple_mbox->hw->irq_bit_recv_not_empty,
0216 apple_mbox->regs + apple_mbox->hw->irq_ack);
0217 }
0218
0219 return IRQ_HANDLED;
0220 }
0221
0222 static int apple_mbox_chan_startup(struct mbox_chan *chan)
0223 {
0224 struct apple_mbox *apple_mbox = chan->con_priv;
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 if (apple_mbox->hw->has_irq_controls) {
0235 writel_relaxed(apple_mbox->hw->irq_bit_recv_not_empty |
0236 apple_mbox->hw->irq_bit_send_empty,
0237 apple_mbox->regs + apple_mbox->hw->irq_enable);
0238 }
0239
0240 enable_irq(apple_mbox->irq_recv_not_empty);
0241 return 0;
0242 }
0243
0244 static void apple_mbox_chan_shutdown(struct mbox_chan *chan)
0245 {
0246 struct apple_mbox *apple_mbox = chan->con_priv;
0247
0248 disable_irq(apple_mbox->irq_recv_not_empty);
0249 }
0250
0251 static const struct mbox_chan_ops apple_mbox_ops = {
0252 .send_data = apple_mbox_chan_send_data,
0253 .startup = apple_mbox_chan_startup,
0254 .shutdown = apple_mbox_chan_shutdown,
0255 };
0256
0257 static struct mbox_chan *apple_mbox_of_xlate(struct mbox_controller *mbox,
0258 const struct of_phandle_args *args)
0259 {
0260 if (args->args_count != 0)
0261 return ERR_PTR(-EINVAL);
0262
0263 return &mbox->chans[0];
0264 }
0265
0266 static int apple_mbox_probe(struct platform_device *pdev)
0267 {
0268 int ret;
0269 const struct of_device_id *match;
0270 char *irqname;
0271 struct apple_mbox *mbox;
0272 struct device *dev = &pdev->dev;
0273
0274 match = of_match_node(apple_mbox_of_match, pdev->dev.of_node);
0275 if (!match)
0276 return -EINVAL;
0277 if (!match->data)
0278 return -EINVAL;
0279
0280 mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
0281 if (!mbox)
0282 return -ENOMEM;
0283 platform_set_drvdata(pdev, mbox);
0284
0285 mbox->dev = dev;
0286 mbox->regs = devm_platform_ioremap_resource(pdev, 0);
0287 if (IS_ERR(mbox->regs))
0288 return PTR_ERR(mbox->regs);
0289
0290 mbox->hw = match->data;
0291 mbox->irq_recv_not_empty =
0292 platform_get_irq_byname(pdev, "recv-not-empty");
0293 if (mbox->irq_recv_not_empty < 0)
0294 return -ENODEV;
0295
0296 mbox->irq_send_empty = platform_get_irq_byname(pdev, "send-empty");
0297 if (mbox->irq_send_empty < 0)
0298 return -ENODEV;
0299
0300 mbox->controller.dev = mbox->dev;
0301 mbox->controller.num_chans = 1;
0302 mbox->controller.chans = &mbox->chan;
0303 mbox->controller.ops = &apple_mbox_ops;
0304 mbox->controller.txdone_irq = true;
0305 mbox->controller.of_xlate = apple_mbox_of_xlate;
0306 mbox->chan.con_priv = mbox;
0307
0308 irqname = devm_kasprintf(dev, GFP_KERNEL, "%s-recv", dev_name(dev));
0309 if (!irqname)
0310 return -ENOMEM;
0311
0312 ret = devm_request_threaded_irq(dev, mbox->irq_recv_not_empty, NULL,
0313 apple_mbox_recv_irq,
0314 IRQF_NO_AUTOEN | IRQF_ONESHOT, irqname,
0315 mbox);
0316 if (ret)
0317 return ret;
0318
0319 irqname = devm_kasprintf(dev, GFP_KERNEL, "%s-send", dev_name(dev));
0320 if (!irqname)
0321 return -ENOMEM;
0322
0323 ret = devm_request_irq(dev, mbox->irq_send_empty,
0324 apple_mbox_send_empty_irq, IRQF_NO_AUTOEN,
0325 irqname, mbox);
0326 if (ret)
0327 return ret;
0328
0329 return devm_mbox_controller_register(dev, &mbox->controller);
0330 }
0331
0332 static const struct apple_mbox_hw apple_mbox_asc_hw = {
0333 .control_full = APPLE_ASC_MBOX_CONTROL_FULL,
0334 .control_empty = APPLE_ASC_MBOX_CONTROL_EMPTY,
0335
0336 .a2i_control = APPLE_ASC_MBOX_A2I_CONTROL,
0337 .a2i_send0 = APPLE_ASC_MBOX_A2I_SEND0,
0338 .a2i_send1 = APPLE_ASC_MBOX_A2I_SEND1,
0339
0340 .i2a_control = APPLE_ASC_MBOX_I2A_CONTROL,
0341 .i2a_recv0 = APPLE_ASC_MBOX_I2A_RECV0,
0342 .i2a_recv1 = APPLE_ASC_MBOX_I2A_RECV1,
0343
0344 .has_irq_controls = false,
0345 };
0346
0347 static const struct apple_mbox_hw apple_mbox_m3_hw = {
0348 .control_full = APPLE_M3_MBOX_CONTROL_FULL,
0349 .control_empty = APPLE_M3_MBOX_CONTROL_EMPTY,
0350
0351 .a2i_control = APPLE_M3_MBOX_A2I_CONTROL,
0352 .a2i_send0 = APPLE_M3_MBOX_A2I_SEND0,
0353 .a2i_send1 = APPLE_M3_MBOX_A2I_SEND1,
0354
0355 .i2a_control = APPLE_M3_MBOX_I2A_CONTROL,
0356 .i2a_recv0 = APPLE_M3_MBOX_I2A_RECV0,
0357 .i2a_recv1 = APPLE_M3_MBOX_I2A_RECV1,
0358
0359 .has_irq_controls = true,
0360 .irq_enable = APPLE_M3_MBOX_IRQ_ENABLE,
0361 .irq_ack = APPLE_M3_MBOX_IRQ_ACK,
0362 .irq_bit_recv_not_empty = APPLE_M3_MBOX_IRQ_I2A_NOT_EMPTY,
0363 .irq_bit_send_empty = APPLE_M3_MBOX_IRQ_A2I_EMPTY,
0364 };
0365
0366 static const struct of_device_id apple_mbox_of_match[] = {
0367 { .compatible = "apple,asc-mailbox-v4", .data = &apple_mbox_asc_hw },
0368 { .compatible = "apple,m3-mailbox-v2", .data = &apple_mbox_m3_hw },
0369 {}
0370 };
0371 MODULE_DEVICE_TABLE(of, apple_mbox_of_match);
0372
0373 static struct platform_driver apple_mbox_driver = {
0374 .driver = {
0375 .name = "apple-mailbox",
0376 .of_match_table = apple_mbox_of_match,
0377 },
0378 .probe = apple_mbox_probe,
0379 };
0380 module_platform_driver(apple_mbox_driver);
0381
0382 MODULE_LICENSE("Dual MIT/GPL");
0383 MODULE_AUTHOR("Sven Peter <sven@svenpeter.dev>");
0384 MODULE_DESCRIPTION("Apple Mailbox driver");