0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/module.h>
0009 #include <linux/of.h>
0010 #include <linux/of_address.h>
0011 #include <linux/msi.h>
0012 #include <linux/fsl/mc.h>
0013
0014 #include "dpaa2-ptp.h"
0015
0016 static int dpaa2_ptp_enable(struct ptp_clock_info *ptp,
0017 struct ptp_clock_request *rq, int on)
0018 {
0019 struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
0020 struct fsl_mc_device *mc_dev;
0021 struct device *dev;
0022 u32 mask = 0;
0023 u32 bit;
0024 int err;
0025
0026 dev = ptp_qoriq->dev;
0027 mc_dev = to_fsl_mc_device(dev);
0028
0029 switch (rq->type) {
0030 case PTP_CLK_REQ_EXTTS:
0031 switch (rq->extts.index) {
0032 case 0:
0033 bit = DPRTC_EVENT_ETS1;
0034 break;
0035 case 1:
0036 bit = DPRTC_EVENT_ETS2;
0037 break;
0038 default:
0039 return -EINVAL;
0040 }
0041 if (on)
0042 extts_clean_up(ptp_qoriq, rq->extts.index, false);
0043 break;
0044 case PTP_CLK_REQ_PPS:
0045 bit = DPRTC_EVENT_PPS;
0046 break;
0047 default:
0048 return -EOPNOTSUPP;
0049 }
0050
0051 err = dprtc_get_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
0052 DPRTC_IRQ_INDEX, &mask);
0053 if (err < 0) {
0054 dev_err(dev, "dprtc_get_irq_mask(): %d\n", err);
0055 return err;
0056 }
0057
0058 if (on)
0059 mask |= bit;
0060 else
0061 mask &= ~bit;
0062
0063 err = dprtc_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
0064 DPRTC_IRQ_INDEX, mask);
0065 if (err < 0) {
0066 dev_err(dev, "dprtc_set_irq_mask(): %d\n", err);
0067 return err;
0068 }
0069
0070 return 0;
0071 }
0072
0073 static const struct ptp_clock_info dpaa2_ptp_caps = {
0074 .owner = THIS_MODULE,
0075 .name = "DPAA2 PTP Clock",
0076 .max_adj = 512000,
0077 .n_alarm = 2,
0078 .n_ext_ts = 2,
0079 .n_per_out = 3,
0080 .n_pins = 0,
0081 .pps = 1,
0082 .adjfine = ptp_qoriq_adjfine,
0083 .adjtime = ptp_qoriq_adjtime,
0084 .gettime64 = ptp_qoriq_gettime,
0085 .settime64 = ptp_qoriq_settime,
0086 .enable = dpaa2_ptp_enable,
0087 };
0088
0089 static irqreturn_t dpaa2_ptp_irq_handler_thread(int irq, void *priv)
0090 {
0091 struct ptp_qoriq *ptp_qoriq = priv;
0092 struct ptp_clock_event event;
0093 struct fsl_mc_device *mc_dev;
0094 struct device *dev;
0095 u32 status = 0;
0096 int err;
0097
0098 dev = ptp_qoriq->dev;
0099 mc_dev = to_fsl_mc_device(dev);
0100
0101 err = dprtc_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
0102 DPRTC_IRQ_INDEX, &status);
0103 if (unlikely(err)) {
0104 dev_err(dev, "dprtc_get_irq_status err %d\n", err);
0105 return IRQ_NONE;
0106 }
0107
0108 if (status & DPRTC_EVENT_PPS) {
0109 event.type = PTP_CLOCK_PPS;
0110 ptp_clock_event(ptp_qoriq->clock, &event);
0111 }
0112
0113 if (status & DPRTC_EVENT_ETS1)
0114 extts_clean_up(ptp_qoriq, 0, true);
0115
0116 if (status & DPRTC_EVENT_ETS2)
0117 extts_clean_up(ptp_qoriq, 1, true);
0118
0119 err = dprtc_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
0120 DPRTC_IRQ_INDEX, status);
0121 if (unlikely(err)) {
0122 dev_err(dev, "dprtc_clear_irq_status err %d\n", err);
0123 return IRQ_NONE;
0124 }
0125
0126 return IRQ_HANDLED;
0127 }
0128
0129 static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
0130 {
0131 struct device *dev = &mc_dev->dev;
0132 struct ptp_qoriq *ptp_qoriq;
0133 struct device_node *node;
0134 void __iomem *base;
0135 int err;
0136
0137 ptp_qoriq = devm_kzalloc(dev, sizeof(*ptp_qoriq), GFP_KERNEL);
0138 if (!ptp_qoriq)
0139 return -ENOMEM;
0140
0141 err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
0142 if (err) {
0143 if (err == -ENXIO)
0144 err = -EPROBE_DEFER;
0145 else
0146 dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
0147 goto err_exit;
0148 }
0149
0150 err = dprtc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
0151 &mc_dev->mc_handle);
0152 if (err) {
0153 dev_err(dev, "dprtc_open err %d\n", err);
0154 goto err_free_mcp;
0155 }
0156
0157 ptp_qoriq->dev = dev;
0158
0159 node = of_find_compatible_node(NULL, NULL, "fsl,dpaa2-ptp");
0160 if (!node) {
0161 err = -ENODEV;
0162 goto err_close;
0163 }
0164
0165 dev->of_node = node;
0166
0167 base = of_iomap(node, 0);
0168 if (!base) {
0169 err = -ENOMEM;
0170 goto err_put;
0171 }
0172
0173 err = fsl_mc_allocate_irqs(mc_dev);
0174 if (err) {
0175 dev_err(dev, "MC irqs allocation failed\n");
0176 goto err_unmap;
0177 }
0178
0179 ptp_qoriq->irq = mc_dev->irqs[0]->virq;
0180
0181 err = request_threaded_irq(ptp_qoriq->irq, NULL,
0182 dpaa2_ptp_irq_handler_thread,
0183 IRQF_NO_SUSPEND | IRQF_ONESHOT,
0184 dev_name(dev), ptp_qoriq);
0185 if (err < 0) {
0186 dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
0187 goto err_free_mc_irq;
0188 }
0189
0190 err = dprtc_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
0191 DPRTC_IRQ_INDEX, 1);
0192 if (err < 0) {
0193 dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
0194 goto err_free_threaded_irq;
0195 }
0196
0197 err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
0198 if (err)
0199 goto err_free_threaded_irq;
0200
0201 dpaa2_phc_index = ptp_qoriq->phc_index;
0202 dpaa2_ptp = ptp_qoriq;
0203 dev_set_drvdata(dev, ptp_qoriq);
0204
0205 return 0;
0206
0207 err_free_threaded_irq:
0208 free_irq(ptp_qoriq->irq, ptp_qoriq);
0209 err_free_mc_irq:
0210 fsl_mc_free_irqs(mc_dev);
0211 err_unmap:
0212 iounmap(base);
0213 err_put:
0214 of_node_put(node);
0215 err_close:
0216 dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
0217 err_free_mcp:
0218 fsl_mc_portal_free(mc_dev->mc_io);
0219 err_exit:
0220 return err;
0221 }
0222
0223 static int dpaa2_ptp_remove(struct fsl_mc_device *mc_dev)
0224 {
0225 struct device *dev = &mc_dev->dev;
0226 struct ptp_qoriq *ptp_qoriq;
0227
0228 ptp_qoriq = dev_get_drvdata(dev);
0229
0230 dpaa2_phc_index = -1;
0231 ptp_qoriq_free(ptp_qoriq);
0232
0233 fsl_mc_free_irqs(mc_dev);
0234 dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
0235 fsl_mc_portal_free(mc_dev->mc_io);
0236
0237 return 0;
0238 }
0239
0240 static const struct fsl_mc_device_id dpaa2_ptp_match_id_table[] = {
0241 {
0242 .vendor = FSL_MC_VENDOR_FREESCALE,
0243 .obj_type = "dprtc",
0244 },
0245 {}
0246 };
0247 MODULE_DEVICE_TABLE(fslmc, dpaa2_ptp_match_id_table);
0248
0249 static struct fsl_mc_driver dpaa2_ptp_drv = {
0250 .driver = {
0251 .name = KBUILD_MODNAME,
0252 .owner = THIS_MODULE,
0253 },
0254 .probe = dpaa2_ptp_probe,
0255 .remove = dpaa2_ptp_remove,
0256 .match_id_table = dpaa2_ptp_match_id_table,
0257 };
0258
0259 module_fsl_mc_driver(dpaa2_ptp_drv);
0260
0261 MODULE_LICENSE("GPL v2");
0262 MODULE_DESCRIPTION("DPAA2 PTP Clock Driver");