1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright 2013-2016 Freescale Semiconductor Inc.
4 * Copyright 2016-2018 NXP
8 #include <linux/module.h>
10 #include <linux/of_address.h>
11 #include <linux/msi.h>
12 #include <linux/fsl/mc.h>
14 #include "dpaa2-ptp.h"
16 static int dpaa2_ptp_enable(struct ptp_clock_info
*ptp
,
17 struct ptp_clock_request
*rq
, int on
)
19 struct ptp_qoriq
*ptp_qoriq
= container_of(ptp
, struct ptp_qoriq
, caps
);
20 struct fsl_mc_device
*mc_dev
;
27 mc_dev
= to_fsl_mc_device(dev
);
30 case PTP_CLK_REQ_EXTTS
:
31 switch (rq
->extts
.index
) {
33 bit
= DPRTC_EVENT_ETS1
;
36 bit
= DPRTC_EVENT_ETS2
;
42 extts_clean_up(ptp_qoriq
, rq
->extts
.index
, false);
45 bit
= DPRTC_EVENT_PPS
;
51 err
= dprtc_get_irq_mask(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
,
52 DPRTC_IRQ_INDEX
, &mask
);
54 dev_err(dev
, "dprtc_get_irq_mask(): %d\n", err
);
63 err
= dprtc_set_irq_mask(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
,
64 DPRTC_IRQ_INDEX
, mask
);
66 dev_err(dev
, "dprtc_set_irq_mask(): %d\n", err
);
73 static const struct ptp_clock_info dpaa2_ptp_caps
= {
75 .name
= "DPAA2 PTP Clock",
82 .adjfine
= ptp_qoriq_adjfine
,
83 .adjtime
= ptp_qoriq_adjtime
,
84 .gettime64
= ptp_qoriq_gettime
,
85 .settime64
= ptp_qoriq_settime
,
86 .enable
= dpaa2_ptp_enable
,
89 static irqreturn_t
dpaa2_ptp_irq_handler_thread(int irq
, void *priv
)
91 struct ptp_qoriq
*ptp_qoriq
= priv
;
92 struct ptp_clock_event event
;
93 struct fsl_mc_device
*mc_dev
;
99 mc_dev
= to_fsl_mc_device(dev
);
101 err
= dprtc_get_irq_status(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
,
102 DPRTC_IRQ_INDEX
, &status
);
104 dev_err(dev
, "dprtc_get_irq_status err %d\n", err
);
108 if (status
& DPRTC_EVENT_PPS
) {
109 event
.type
= PTP_CLOCK_PPS
;
110 ptp_clock_event(ptp_qoriq
->clock
, &event
);
113 if (status
& DPRTC_EVENT_ETS1
)
114 extts_clean_up(ptp_qoriq
, 0, true);
116 if (status
& DPRTC_EVENT_ETS2
)
117 extts_clean_up(ptp_qoriq
, 1, true);
119 err
= dprtc_clear_irq_status(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
,
120 DPRTC_IRQ_INDEX
, status
);
122 dev_err(dev
, "dprtc_clear_irq_status err %d\n", err
);
129 static int dpaa2_ptp_probe(struct fsl_mc_device
*mc_dev
)
131 struct device
*dev
= &mc_dev
->dev
;
132 struct fsl_mc_device_irq
*irq
;
133 struct ptp_qoriq
*ptp_qoriq
;
134 struct device_node
*node
;
138 ptp_qoriq
= devm_kzalloc(dev
, sizeof(*ptp_qoriq
), GFP_KERNEL
);
142 err
= fsl_mc_portal_allocate(mc_dev
, 0, &mc_dev
->mc_io
);
147 dev_err(dev
, "fsl_mc_portal_allocate err %d\n", err
);
151 err
= dprtc_open(mc_dev
->mc_io
, 0, mc_dev
->obj_desc
.id
,
154 dev_err(dev
, "dprtc_open err %d\n", err
);
158 ptp_qoriq
->dev
= dev
;
160 node
= of_find_compatible_node(NULL
, NULL
, "fsl,dpaa2-ptp");
168 base
= of_iomap(node
, 0);
174 err
= fsl_mc_allocate_irqs(mc_dev
);
176 dev_err(dev
, "MC irqs allocation failed\n");
180 irq
= mc_dev
->irqs
[0];
181 ptp_qoriq
->irq
= irq
->msi_desc
->irq
;
183 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
);
188 dev_err(dev
, "devm_request_threaded_irq(): %d\n", err
);
189 goto err_free_mc_irq
;
192 err
= dprtc_set_irq_enable(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
,
195 dev_err(dev
, "dprtc_set_irq_enable(): %d\n", err
);
196 goto err_free_threaded_irq
;
199 err
= ptp_qoriq_init(ptp_qoriq
, base
, &dpaa2_ptp_caps
);
201 goto err_free_threaded_irq
;
203 dpaa2_phc_index
= ptp_qoriq
->phc_index
;
204 dpaa2_ptp
= ptp_qoriq
;
205 dev_set_drvdata(dev
, ptp_qoriq
);
209 err_free_threaded_irq
:
210 free_irq(ptp_qoriq
->irq
, ptp_qoriq
);
212 fsl_mc_free_irqs(mc_dev
);
216 dprtc_close(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
);
218 fsl_mc_portal_free(mc_dev
->mc_io
);
223 static int dpaa2_ptp_remove(struct fsl_mc_device
*mc_dev
)
225 struct device
*dev
= &mc_dev
->dev
;
226 struct ptp_qoriq
*ptp_qoriq
;
228 ptp_qoriq
= dev_get_drvdata(dev
);
230 dpaa2_phc_index
= -1;
231 ptp_qoriq_free(ptp_qoriq
);
233 fsl_mc_free_irqs(mc_dev
);
234 dprtc_close(mc_dev
->mc_io
, 0, mc_dev
->mc_handle
);
235 fsl_mc_portal_free(mc_dev
->mc_io
);
240 static const struct fsl_mc_device_id dpaa2_ptp_match_id_table
[] = {
242 .vendor
= FSL_MC_VENDOR_FREESCALE
,
247 MODULE_DEVICE_TABLE(fslmc
, dpaa2_ptp_match_id_table
);
249 static struct fsl_mc_driver dpaa2_ptp_drv
= {
251 .name
= KBUILD_MODNAME
,
252 .owner
= THIS_MODULE
,
254 .probe
= dpaa2_ptp_probe
,
255 .remove
= dpaa2_ptp_remove
,
256 .match_id_table
= dpaa2_ptp_match_id_table
,
259 module_fsl_mc_driver(dpaa2_ptp_drv
);
261 MODULE_LICENSE("GPL v2");
262 MODULE_DESCRIPTION("DPAA2 PTP Clock Driver");