blob: 32b5faa87bb8dbcef676f744adf0f4f4ece4ba61 [file] [log] [blame]
Yangbo Lu9bdf43b2018-04-23 11:55:00 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright 2013-2016 Freescale Semiconductor Inc.
4 * Copyright 2016-2018 NXP
Yangbo Lud21c7842020-09-18 17:07:59 +08005 * Copyright 2020 NXP
Yangbo Lu9bdf43b2018-04-23 11:55:00 +08006 */
7
8#include <linux/module.h>
Yangbo Lud346c9e2019-06-14 18:40:51 +08009#include <linux/of.h>
10#include <linux/of_address.h>
Yangbo Lu8893a842019-06-14 18:40:54 +080011#include <linux/msi.h>
Yangbo Lu9bdf43b2018-04-23 11:55:00 +080012#include <linux/fsl/mc.h>
13
Yangbo Lu0a006a22018-10-08 15:44:25 +080014#include "dpaa2-ptp.h"
Yangbo Lu9bdf43b2018-04-23 11:55:00 +080015
Yangbo Lu8893a842019-06-14 18:40:54 +080016static int dpaa2_ptp_enable(struct ptp_clock_info *ptp,
17 struct ptp_clock_request *rq, int on)
18{
19 struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
20 struct fsl_mc_device *mc_dev;
21 struct device *dev;
22 u32 mask = 0;
23 u32 bit;
24 int err;
25
26 dev = ptp_qoriq->dev;
27 mc_dev = to_fsl_mc_device(dev);
28
29 switch (rq->type) {
Yangbo Lu17568c62019-12-12 18:08:06 +080030 case PTP_CLK_REQ_EXTTS:
31 switch (rq->extts.index) {
32 case 0:
33 bit = DPRTC_EVENT_ETS1;
34 break;
35 case 1:
36 bit = DPRTC_EVENT_ETS2;
37 break;
38 default:
39 return -EINVAL;
40 }
41 if (on)
42 extts_clean_up(ptp_qoriq, rq->extts.index, false);
43 break;
Yangbo Lu8893a842019-06-14 18:40:54 +080044 case PTP_CLK_REQ_PPS:
45 bit = DPRTC_EVENT_PPS;
46 break;
47 default:
48 return -EOPNOTSUPP;
49 }
50
51 err = dprtc_get_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
52 DPRTC_IRQ_INDEX, &mask);
53 if (err < 0) {
54 dev_err(dev, "dprtc_get_irq_mask(): %d\n", err);
55 return err;
56 }
57
58 if (on)
59 mask |= bit;
60 else
61 mask &= ~bit;
62
63 err = dprtc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
64 DPRTC_IRQ_INDEX, mask);
65 if (err < 0) {
66 dev_err(dev, "dprtc_set_irq_mask(): %d\n", err);
67 return err;
68 }
69
70 return 0;
71}
72
Yangbo Lud346c9e2019-06-14 18:40:51 +080073static const struct ptp_clock_info dpaa2_ptp_caps = {
Yangbo Lu9bdf43b2018-04-23 11:55:00 +080074 .owner = THIS_MODULE,
75 .name = "DPAA2 PTP Clock",
76 .max_adj = 512000,
77 .n_alarm = 2,
78 .n_ext_ts = 2,
79 .n_per_out = 3,
80 .n_pins = 0,
81 .pps = 1,
Yangbo Lud346c9e2019-06-14 18:40:51 +080082 .adjfine = ptp_qoriq_adjfine,
83 .adjtime = ptp_qoriq_adjtime,
84 .gettime64 = ptp_qoriq_gettime,
85 .settime64 = ptp_qoriq_settime,
Yangbo Lu8893a842019-06-14 18:40:54 +080086 .enable = dpaa2_ptp_enable,
Yangbo Lu9bdf43b2018-04-23 11:55:00 +080087};
88
Yangbo Lu8893a842019-06-14 18:40:54 +080089static irqreturn_t dpaa2_ptp_irq_handler_thread(int irq, void *priv)
90{
91 struct ptp_qoriq *ptp_qoriq = priv;
92 struct ptp_clock_event event;
93 struct fsl_mc_device *mc_dev;
94 struct device *dev;
95 u32 status = 0;
96 int err;
97
98 dev = ptp_qoriq->dev;
99 mc_dev = to_fsl_mc_device(dev);
100
101 err = dprtc_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
102 DPRTC_IRQ_INDEX, &status);
103 if (unlikely(err)) {
104 dev_err(dev, "dprtc_get_irq_status err %d\n", err);
105 return IRQ_NONE;
106 }
107
108 if (status & DPRTC_EVENT_PPS) {
109 event.type = PTP_CLOCK_PPS;
110 ptp_clock_event(ptp_qoriq->clock, &event);
111 }
112
Yangbo Lu17568c62019-12-12 18:08:06 +0800113 if (status & DPRTC_EVENT_ETS1)
114 extts_clean_up(ptp_qoriq, 0, true);
115
116 if (status & DPRTC_EVENT_ETS2)
117 extts_clean_up(ptp_qoriq, 1, true);
118
Yangbo Lu8893a842019-06-14 18:40:54 +0800119 err = dprtc_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
120 DPRTC_IRQ_INDEX, status);
121 if (unlikely(err)) {
122 dev_err(dev, "dprtc_clear_irq_status err %d\n", err);
123 return IRQ_NONE;
124 }
125
126 return IRQ_HANDLED;
127}
128
Yangbo Lu180f5392018-10-08 15:44:28 +0800129static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800130{
131 struct device *dev = &mc_dev->dev;
Yangbo Lu8893a842019-06-14 18:40:54 +0800132 struct fsl_mc_device_irq *irq;
Yangbo Lud346c9e2019-06-14 18:40:51 +0800133 struct ptp_qoriq *ptp_qoriq;
134 struct device_node *node;
135 void __iomem *base;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800136 int err;
137
Yangbo Lud346c9e2019-06-14 18:40:51 +0800138 ptp_qoriq = devm_kzalloc(dev, sizeof(*ptp_qoriq), GFP_KERNEL);
139 if (!ptp_qoriq)
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800140 return -ENOMEM;
141
142 err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
143 if (err) {
Ioana Ciornei55005982018-11-09 15:26:46 +0000144 if (err == -ENXIO)
145 err = -EPROBE_DEFER;
146 else
147 dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800148 goto err_exit;
149 }
150
151 err = dprtc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
152 &mc_dev->mc_handle);
153 if (err) {
154 dev_err(dev, "dprtc_open err %d\n", err);
155 goto err_free_mcp;
156 }
157
Yangbo Lud346c9e2019-06-14 18:40:51 +0800158 ptp_qoriq->dev = dev;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800159
Yangbo Lud346c9e2019-06-14 18:40:51 +0800160 node = of_find_compatible_node(NULL, NULL, "fsl,dpaa2-ptp");
161 if (!node) {
162 err = -ENODEV;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800163 goto err_close;
164 }
165
Yangbo Lud346c9e2019-06-14 18:40:51 +0800166 dev->of_node = node;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800167
Yangbo Lud346c9e2019-06-14 18:40:51 +0800168 base = of_iomap(node, 0);
169 if (!base) {
170 err = -ENOMEM;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800171 goto err_close;
172 }
173
Yangbo Lu8893a842019-06-14 18:40:54 +0800174 err = fsl_mc_allocate_irqs(mc_dev);
175 if (err) {
176 dev_err(dev, "MC irqs allocation failed\n");
177 goto err_unmap;
178 }
179
180 irq = mc_dev->irqs[0];
181 ptp_qoriq->irq = irq->msi_desc->irq;
182
Ioana Ciorneidaa6eb52019-12-16 17:32:30 +0200183 err = request_threaded_irq(ptp_qoriq->irq, NULL,
184 dpaa2_ptp_irq_handler_thread,
185 IRQF_NO_SUSPEND | IRQF_ONESHOT,
186 dev_name(dev), ptp_qoriq);
Yangbo Lu8893a842019-06-14 18:40:54 +0800187 if (err < 0) {
188 dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
189 goto err_free_mc_irq;
190 }
191
192 err = dprtc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
193 DPRTC_IRQ_INDEX, 1);
194 if (err < 0) {
195 dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
Ioana Ciorneidaa6eb52019-12-16 17:32:30 +0200196 goto err_free_threaded_irq;
Yangbo Lu8893a842019-06-14 18:40:54 +0800197 }
198
Yangbo Lud346c9e2019-06-14 18:40:51 +0800199 err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
200 if (err)
Ioana Ciorneidaa6eb52019-12-16 17:32:30 +0200201 goto err_free_threaded_irq;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800202
Yangbo Lud346c9e2019-06-14 18:40:51 +0800203 dpaa2_phc_index = ptp_qoriq->phc_index;
Yangbo Lud21c7842020-09-18 17:07:59 +0800204 dpaa2_ptp = ptp_qoriq;
Yangbo Lud346c9e2019-06-14 18:40:51 +0800205 dev_set_drvdata(dev, ptp_qoriq);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800206
207 return 0;
208
Ioana Ciorneidaa6eb52019-12-16 17:32:30 +0200209err_free_threaded_irq:
210 free_irq(ptp_qoriq->irq, ptp_qoriq);
Yangbo Lu8893a842019-06-14 18:40:54 +0800211err_free_mc_irq:
212 fsl_mc_free_irqs(mc_dev);
Yangbo Lud346c9e2019-06-14 18:40:51 +0800213err_unmap:
214 iounmap(base);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800215err_close:
216 dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
217err_free_mcp:
218 fsl_mc_portal_free(mc_dev->mc_io);
219err_exit:
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800220 return err;
221}
222
Yangbo Lu180f5392018-10-08 15:44:28 +0800223static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800224{
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800225 struct device *dev = &mc_dev->dev;
Yangbo Lud346c9e2019-06-14 18:40:51 +0800226 struct ptp_qoriq *ptp_qoriq;
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800227
Yangbo Lud346c9e2019-06-14 18:40:51 +0800228 ptp_qoriq = dev_get_drvdata(dev);
229
230 dpaa2_phc_index = -1;
231 ptp_qoriq_free(ptp_qoriq);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800232
Yangbo Lu8893a842019-06-14 18:40:54 +0800233 fsl_mc_free_irqs(mc_dev);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800234 dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
235 fsl_mc_portal_free(mc_dev->mc_io);
236
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800237 return 0;
238}
239
Yangbo Lu180f5392018-10-08 15:44:28 +0800240static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800241 {
242 .vendor = FSL_MC_VENDOR_FREESCALE,
243 .obj_type = "dprtc",
244 },
245 {}
246};
Yangbo Lu180f5392018-10-08 15:44:28 +0800247MODULE_DEVICE_TABLE(fslmc, dpaa2_ptp_match_id_table);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800248
Yangbo Lu180f5392018-10-08 15:44:28 +0800249static struct fsl_mc_driver dpaa2_ptp_drv = {
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800250 .driver = {
251 .name = KBUILD_MODNAME,
252 .owner = THIS_MODULE,
253 },
Yangbo Lu180f5392018-10-08 15:44:28 +0800254 .probe = dpaa2_ptp_probe,
255 .remove = dpaa2_ptp_remove,
256 .match_id_table = dpaa2_ptp_match_id_table,
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800257};
258
Yangbo Lu180f5392018-10-08 15:44:28 +0800259module_fsl_mc_driver(dpaa2_ptp_drv);
Yangbo Lu9bdf43b2018-04-23 11:55:00 +0800260
261MODULE_LICENSE("GPL v2");
262MODULE_DESCRIPTION("DPAA2 PTP Clock Driver");