cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ptp_qoriq.c (15889B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * PTP 1588 clock for Freescale QorIQ 1588 timer
      4 *
      5 * Copyright (C) 2010 OMICRON electronics GmbH
      6 */
      7
      8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      9
     10#include <linux/device.h>
     11#include <linux/hrtimer.h>
     12#include <linux/kernel.h>
     13#include <linux/module.h>
     14#include <linux/of.h>
     15#include <linux/of_platform.h>
     16#include <linux/timex.h>
     17#include <linux/slab.h>
     18#include <linux/clk.h>
     19
     20#include <linux/fsl/ptp_qoriq.h>
     21
     22/*
     23 * Register access functions
     24 */
     25
     26/* Caller must hold ptp_qoriq->lock. */
     27static u64 tmr_cnt_read(struct ptp_qoriq *ptp_qoriq)
     28{
     29	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
     30	u64 ns;
     31	u32 lo, hi;
     32
     33	lo = ptp_qoriq->read(&regs->ctrl_regs->tmr_cnt_l);
     34	hi = ptp_qoriq->read(&regs->ctrl_regs->tmr_cnt_h);
     35	ns = ((u64) hi) << 32;
     36	ns |= lo;
     37	return ns;
     38}
     39
     40/* Caller must hold ptp_qoriq->lock. */
     41static void tmr_cnt_write(struct ptp_qoriq *ptp_qoriq, u64 ns)
     42{
     43	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
     44	u32 hi = ns >> 32;
     45	u32 lo = ns & 0xffffffff;
     46
     47	ptp_qoriq->write(&regs->ctrl_regs->tmr_cnt_l, lo);
     48	ptp_qoriq->write(&regs->ctrl_regs->tmr_cnt_h, hi);
     49}
     50
     51/* Caller must hold ptp_qoriq->lock. */
     52static void set_alarm(struct ptp_qoriq *ptp_qoriq)
     53{
     54	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
     55	u64 ns;
     56	u32 lo, hi;
     57
     58	ns = tmr_cnt_read(ptp_qoriq) + 1500000000ULL;
     59	ns = div_u64(ns, 1000000000UL) * 1000000000ULL;
     60	ns -= ptp_qoriq->tclk_period;
     61	hi = ns >> 32;
     62	lo = ns & 0xffffffff;
     63	ptp_qoriq->write(&regs->alarm_regs->tmr_alarm1_l, lo);
     64	ptp_qoriq->write(&regs->alarm_regs->tmr_alarm1_h, hi);
     65}
     66
     67/* Caller must hold ptp_qoriq->lock. */
     68static void set_fipers(struct ptp_qoriq *ptp_qoriq)
     69{
     70	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
     71
     72	set_alarm(ptp_qoriq);
     73	ptp_qoriq->write(&regs->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1);
     74	ptp_qoriq->write(&regs->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2);
     75
     76	if (ptp_qoriq->fiper3_support)
     77		ptp_qoriq->write(&regs->fiper_regs->tmr_fiper3,
     78				 ptp_qoriq->tmr_fiper3);
     79}
     80
     81int extts_clean_up(struct ptp_qoriq *ptp_qoriq, int index, bool update_event)
     82{
     83	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
     84	struct ptp_clock_event event;
     85	void __iomem *reg_etts_l;
     86	void __iomem *reg_etts_h;
     87	u32 valid, lo, hi;
     88
     89	switch (index) {
     90	case 0:
     91		valid = ETS1_VLD;
     92		reg_etts_l = &regs->etts_regs->tmr_etts1_l;
     93		reg_etts_h = &regs->etts_regs->tmr_etts1_h;
     94		break;
     95	case 1:
     96		valid = ETS2_VLD;
     97		reg_etts_l = &regs->etts_regs->tmr_etts2_l;
     98		reg_etts_h = &regs->etts_regs->tmr_etts2_h;
     99		break;
    100	default:
    101		return -EINVAL;
    102	}
    103
    104	event.type = PTP_CLOCK_EXTTS;
    105	event.index = index;
    106
    107	if (ptp_qoriq->extts_fifo_support)
    108		if (!(ptp_qoriq->read(&regs->ctrl_regs->tmr_stat) & valid))
    109			return 0;
    110
    111	do {
    112		lo = ptp_qoriq->read(reg_etts_l);
    113		hi = ptp_qoriq->read(reg_etts_h);
    114
    115		if (update_event) {
    116			event.timestamp = ((u64) hi) << 32;
    117			event.timestamp |= lo;
    118			ptp_clock_event(ptp_qoriq->clock, &event);
    119		}
    120
    121		if (!ptp_qoriq->extts_fifo_support)
    122			break;
    123	} while (ptp_qoriq->read(&regs->ctrl_regs->tmr_stat) & valid);
    124
    125	return 0;
    126}
    127EXPORT_SYMBOL_GPL(extts_clean_up);
    128
    129/*
    130 * Interrupt service routine
    131 */
    132
    133irqreturn_t ptp_qoriq_isr(int irq, void *priv)
    134{
    135	struct ptp_qoriq *ptp_qoriq = priv;
    136	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
    137	struct ptp_clock_event event;
    138	u32 ack = 0, mask, val, irqs;
    139
    140	spin_lock(&ptp_qoriq->lock);
    141
    142	val = ptp_qoriq->read(&regs->ctrl_regs->tmr_tevent);
    143	mask = ptp_qoriq->read(&regs->ctrl_regs->tmr_temask);
    144
    145	spin_unlock(&ptp_qoriq->lock);
    146
    147	irqs = val & mask;
    148
    149	if (irqs & ETS1) {
    150		ack |= ETS1;
    151		extts_clean_up(ptp_qoriq, 0, true);
    152	}
    153
    154	if (irqs & ETS2) {
    155		ack |= ETS2;
    156		extts_clean_up(ptp_qoriq, 1, true);
    157	}
    158
    159	if (irqs & PP1) {
    160		ack |= PP1;
    161		event.type = PTP_CLOCK_PPS;
    162		ptp_clock_event(ptp_qoriq->clock, &event);
    163	}
    164
    165	if (ack) {
    166		ptp_qoriq->write(&regs->ctrl_regs->tmr_tevent, ack);
    167		return IRQ_HANDLED;
    168	} else
    169		return IRQ_NONE;
    170}
    171EXPORT_SYMBOL_GPL(ptp_qoriq_isr);
    172
    173/*
    174 * PTP clock operations
    175 */
    176
    177int ptp_qoriq_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
    178{
    179	u64 adj, diff;
    180	u32 tmr_add;
    181	int neg_adj = 0;
    182	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
    183	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
    184
    185	if (scaled_ppm < 0) {
    186		neg_adj = 1;
    187		scaled_ppm = -scaled_ppm;
    188	}
    189	tmr_add = ptp_qoriq->tmr_add;
    190	adj = tmr_add;
    191
    192	/*
    193	 * Calculate diff and round() to the nearest integer
    194	 *
    195	 * diff = adj * (ppb / 1000000000)
    196	 *      = adj * scaled_ppm / 65536000000
    197	 */
    198	diff = mul_u64_u64_div_u64(adj, scaled_ppm, 32768000000);
    199	diff = DIV64_U64_ROUND_UP(diff, 2);
    200
    201	tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
    202	ptp_qoriq->write(&regs->ctrl_regs->tmr_add, tmr_add);
    203
    204	return 0;
    205}
    206EXPORT_SYMBOL_GPL(ptp_qoriq_adjfine);
    207
    208int ptp_qoriq_adjtime(struct ptp_clock_info *ptp, s64 delta)
    209{
    210	s64 now;
    211	unsigned long flags;
    212	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
    213
    214	spin_lock_irqsave(&ptp_qoriq->lock, flags);
    215
    216	now = tmr_cnt_read(ptp_qoriq);
    217	now += delta;
    218	tmr_cnt_write(ptp_qoriq, now);
    219	set_fipers(ptp_qoriq);
    220
    221	spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
    222
    223	return 0;
    224}
    225EXPORT_SYMBOL_GPL(ptp_qoriq_adjtime);
    226
    227int ptp_qoriq_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
    228{
    229	u64 ns;
    230	unsigned long flags;
    231	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
    232
    233	spin_lock_irqsave(&ptp_qoriq->lock, flags);
    234
    235	ns = tmr_cnt_read(ptp_qoriq);
    236
    237	spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
    238
    239	*ts = ns_to_timespec64(ns);
    240
    241	return 0;
    242}
    243EXPORT_SYMBOL_GPL(ptp_qoriq_gettime);
    244
    245int ptp_qoriq_settime(struct ptp_clock_info *ptp,
    246		      const struct timespec64 *ts)
    247{
    248	u64 ns;
    249	unsigned long flags;
    250	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
    251
    252	ns = timespec64_to_ns(ts);
    253
    254	spin_lock_irqsave(&ptp_qoriq->lock, flags);
    255
    256	tmr_cnt_write(ptp_qoriq, ns);
    257	set_fipers(ptp_qoriq);
    258
    259	spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
    260
    261	return 0;
    262}
    263EXPORT_SYMBOL_GPL(ptp_qoriq_settime);
    264
    265int ptp_qoriq_enable(struct ptp_clock_info *ptp,
    266		     struct ptp_clock_request *rq, int on)
    267{
    268	struct ptp_qoriq *ptp_qoriq = container_of(ptp, struct ptp_qoriq, caps);
    269	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
    270	unsigned long flags;
    271	u32 bit, mask = 0;
    272
    273	switch (rq->type) {
    274	case PTP_CLK_REQ_EXTTS:
    275		switch (rq->extts.index) {
    276		case 0:
    277			bit = ETS1EN;
    278			break;
    279		case 1:
    280			bit = ETS2EN;
    281			break;
    282		default:
    283			return -EINVAL;
    284		}
    285
    286		if (on)
    287			extts_clean_up(ptp_qoriq, rq->extts.index, false);
    288
    289		break;
    290	case PTP_CLK_REQ_PPS:
    291		bit = PP1EN;
    292		break;
    293	default:
    294		return -EOPNOTSUPP;
    295	}
    296
    297	spin_lock_irqsave(&ptp_qoriq->lock, flags);
    298
    299	mask = ptp_qoriq->read(&regs->ctrl_regs->tmr_temask);
    300	if (on) {
    301		mask |= bit;
    302		ptp_qoriq->write(&regs->ctrl_regs->tmr_tevent, bit);
    303	} else {
    304		mask &= ~bit;
    305	}
    306
    307	ptp_qoriq->write(&regs->ctrl_regs->tmr_temask, mask);
    308
    309	spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
    310	return 0;
    311}
    312EXPORT_SYMBOL_GPL(ptp_qoriq_enable);
    313
    314static const struct ptp_clock_info ptp_qoriq_caps = {
    315	.owner		= THIS_MODULE,
    316	.name		= "qoriq ptp clock",
    317	.max_adj	= 512000,
    318	.n_alarm	= 0,
    319	.n_ext_ts	= N_EXT_TS,
    320	.n_per_out	= 0,
    321	.n_pins		= 0,
    322	.pps		= 1,
    323	.adjfine	= ptp_qoriq_adjfine,
    324	.adjtime	= ptp_qoriq_adjtime,
    325	.gettime64	= ptp_qoriq_gettime,
    326	.settime64	= ptp_qoriq_settime,
    327	.enable		= ptp_qoriq_enable,
    328};
    329
    330/**
    331 * ptp_qoriq_nominal_freq - calculate nominal frequency according to
    332 *			    reference clock frequency
    333 *
    334 * @clk_src: reference clock frequency
    335 *
    336 * The nominal frequency is the desired clock frequency.
    337 * It should be less than the reference clock frequency.
    338 * It should be a factor of 1000MHz.
    339 *
    340 * Return the nominal frequency
    341 */
    342static u32 ptp_qoriq_nominal_freq(u32 clk_src)
    343{
    344	u32 remainder = 0;
    345
    346	clk_src /= 1000000;
    347	remainder = clk_src % 100;
    348	if (remainder) {
    349		clk_src -= remainder;
    350		clk_src += 100;
    351	}
    352
    353	do {
    354		clk_src -= 100;
    355
    356	} while (1000 % clk_src);
    357
    358	return clk_src * 1000000;
    359}
    360
    361/**
    362 * ptp_qoriq_auto_config - calculate a set of default configurations
    363 *
    364 * @ptp_qoriq: pointer to ptp_qoriq
    365 * @node: pointer to device_node
    366 *
    367 * If below dts properties are not provided, this function will be
    368 * called to calculate a set of default configurations for them.
    369 *   "fsl,tclk-period"
    370 *   "fsl,tmr-prsc"
    371 *   "fsl,tmr-add"
    372 *   "fsl,tmr-fiper1"
    373 *   "fsl,tmr-fiper2"
    374 *   "fsl,tmr-fiper3" (required only for DPAA2 and ENETC hardware)
    375 *   "fsl,max-adj"
    376 *
    377 * Return 0 if success
    378 */
    379static int ptp_qoriq_auto_config(struct ptp_qoriq *ptp_qoriq,
    380				 struct device_node *node)
    381{
    382	struct clk *clk;
    383	u64 freq_comp;
    384	u64 max_adj;
    385	u32 nominal_freq;
    386	u32 remainder = 0;
    387	u32 clk_src = 0;
    388
    389	ptp_qoriq->cksel = DEFAULT_CKSEL;
    390
    391	clk = of_clk_get(node, 0);
    392	if (!IS_ERR(clk)) {
    393		clk_src = clk_get_rate(clk);
    394		clk_put(clk);
    395	}
    396
    397	if (clk_src <= 100000000UL) {
    398		pr_err("error reference clock value, or lower than 100MHz\n");
    399		return -EINVAL;
    400	}
    401
    402	nominal_freq = ptp_qoriq_nominal_freq(clk_src);
    403	if (!nominal_freq)
    404		return -EINVAL;
    405
    406	ptp_qoriq->tclk_period = 1000000000UL / nominal_freq;
    407	ptp_qoriq->tmr_prsc = DEFAULT_TMR_PRSC;
    408
    409	/* Calculate initial frequency compensation value for TMR_ADD register.
    410	 * freq_comp = ceil(2^32 / freq_ratio)
    411	 * freq_ratio = reference_clock_freq / nominal_freq
    412	 */
    413	freq_comp = ((u64)1 << 32) * nominal_freq;
    414	freq_comp = div_u64_rem(freq_comp, clk_src, &remainder);
    415	if (remainder)
    416		freq_comp++;
    417
    418	ptp_qoriq->tmr_add = freq_comp;
    419	ptp_qoriq->tmr_fiper1 = DEFAULT_FIPER1_PERIOD - ptp_qoriq->tclk_period;
    420	ptp_qoriq->tmr_fiper2 = DEFAULT_FIPER2_PERIOD - ptp_qoriq->tclk_period;
    421	ptp_qoriq->tmr_fiper3 = DEFAULT_FIPER3_PERIOD - ptp_qoriq->tclk_period;
    422
    423	/* max_adj = 1000000000 * (freq_ratio - 1.0) - 1
    424	 * freq_ratio = reference_clock_freq / nominal_freq
    425	 */
    426	max_adj = 1000000000ULL * (clk_src - nominal_freq);
    427	max_adj = div_u64(max_adj, nominal_freq) - 1;
    428	ptp_qoriq->caps.max_adj = max_adj;
    429
    430	return 0;
    431}
    432
    433int ptp_qoriq_init(struct ptp_qoriq *ptp_qoriq, void __iomem *base,
    434		   const struct ptp_clock_info *caps)
    435{
    436	struct device_node *node = ptp_qoriq->dev->of_node;
    437	struct ptp_qoriq_registers *regs;
    438	struct timespec64 now;
    439	unsigned long flags;
    440	u32 tmr_ctrl;
    441
    442	if (!node)
    443		return -ENODEV;
    444
    445	ptp_qoriq->base = base;
    446	ptp_qoriq->caps = *caps;
    447
    448	if (of_property_read_u32(node, "fsl,cksel", &ptp_qoriq->cksel))
    449		ptp_qoriq->cksel = DEFAULT_CKSEL;
    450
    451	if (of_property_read_bool(node, "fsl,extts-fifo"))
    452		ptp_qoriq->extts_fifo_support = true;
    453	else
    454		ptp_qoriq->extts_fifo_support = false;
    455
    456	if (of_device_is_compatible(node, "fsl,dpaa2-ptp") ||
    457	    of_device_is_compatible(node, "fsl,enetc-ptp"))
    458		ptp_qoriq->fiper3_support = true;
    459
    460	if (of_property_read_u32(node,
    461				 "fsl,tclk-period", &ptp_qoriq->tclk_period) ||
    462	    of_property_read_u32(node,
    463				 "fsl,tmr-prsc", &ptp_qoriq->tmr_prsc) ||
    464	    of_property_read_u32(node,
    465				 "fsl,tmr-add", &ptp_qoriq->tmr_add) ||
    466	    of_property_read_u32(node,
    467				 "fsl,tmr-fiper1", &ptp_qoriq->tmr_fiper1) ||
    468	    of_property_read_u32(node,
    469				 "fsl,tmr-fiper2", &ptp_qoriq->tmr_fiper2) ||
    470	    of_property_read_u32(node,
    471				 "fsl,max-adj", &ptp_qoriq->caps.max_adj) ||
    472	    (ptp_qoriq->fiper3_support &&
    473	     of_property_read_u32(node, "fsl,tmr-fiper3",
    474				  &ptp_qoriq->tmr_fiper3))) {
    475		pr_warn("device tree node missing required elements, try automatic configuration\n");
    476
    477		if (ptp_qoriq_auto_config(ptp_qoriq, node))
    478			return -ENODEV;
    479	}
    480
    481	if (of_property_read_bool(node, "little-endian")) {
    482		ptp_qoriq->read = qoriq_read_le;
    483		ptp_qoriq->write = qoriq_write_le;
    484	} else {
    485		ptp_qoriq->read = qoriq_read_be;
    486		ptp_qoriq->write = qoriq_write_be;
    487	}
    488
    489	/* The eTSEC uses differnt memory map with DPAA/ENETC */
    490	if (of_device_is_compatible(node, "fsl,etsec-ptp")) {
    491		ptp_qoriq->regs.ctrl_regs = base + ETSEC_CTRL_REGS_OFFSET;
    492		ptp_qoriq->regs.alarm_regs = base + ETSEC_ALARM_REGS_OFFSET;
    493		ptp_qoriq->regs.fiper_regs = base + ETSEC_FIPER_REGS_OFFSET;
    494		ptp_qoriq->regs.etts_regs = base + ETSEC_ETTS_REGS_OFFSET;
    495	} else {
    496		ptp_qoriq->regs.ctrl_regs = base + CTRL_REGS_OFFSET;
    497		ptp_qoriq->regs.alarm_regs = base + ALARM_REGS_OFFSET;
    498		ptp_qoriq->regs.fiper_regs = base + FIPER_REGS_OFFSET;
    499		ptp_qoriq->regs.etts_regs = base + ETTS_REGS_OFFSET;
    500	}
    501
    502	spin_lock_init(&ptp_qoriq->lock);
    503
    504	ktime_get_real_ts64(&now);
    505	ptp_qoriq_settime(&ptp_qoriq->caps, &now);
    506
    507	tmr_ctrl =
    508	  (ptp_qoriq->tclk_period & TCLK_PERIOD_MASK) << TCLK_PERIOD_SHIFT |
    509	  (ptp_qoriq->cksel & CKSEL_MASK) << CKSEL_SHIFT;
    510
    511	spin_lock_irqsave(&ptp_qoriq->lock, flags);
    512
    513	regs = &ptp_qoriq->regs;
    514	ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl, tmr_ctrl);
    515	ptp_qoriq->write(&regs->ctrl_regs->tmr_add, ptp_qoriq->tmr_add);
    516	ptp_qoriq->write(&regs->ctrl_regs->tmr_prsc, ptp_qoriq->tmr_prsc);
    517	ptp_qoriq->write(&regs->fiper_regs->tmr_fiper1, ptp_qoriq->tmr_fiper1);
    518	ptp_qoriq->write(&regs->fiper_regs->tmr_fiper2, ptp_qoriq->tmr_fiper2);
    519
    520	if (ptp_qoriq->fiper3_support)
    521		ptp_qoriq->write(&regs->fiper_regs->tmr_fiper3,
    522				 ptp_qoriq->tmr_fiper3);
    523
    524	set_alarm(ptp_qoriq);
    525	ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl,
    526			 tmr_ctrl|FIPERST|RTPE|TE|FRD);
    527
    528	spin_unlock_irqrestore(&ptp_qoriq->lock, flags);
    529
    530	ptp_qoriq->clock = ptp_clock_register(&ptp_qoriq->caps, ptp_qoriq->dev);
    531	if (IS_ERR(ptp_qoriq->clock))
    532		return PTR_ERR(ptp_qoriq->clock);
    533
    534	ptp_qoriq->phc_index = ptp_clock_index(ptp_qoriq->clock);
    535	ptp_qoriq_create_debugfs(ptp_qoriq);
    536	return 0;
    537}
    538EXPORT_SYMBOL_GPL(ptp_qoriq_init);
    539
    540void ptp_qoriq_free(struct ptp_qoriq *ptp_qoriq)
    541{
    542	struct ptp_qoriq_registers *regs = &ptp_qoriq->regs;
    543
    544	ptp_qoriq->write(&regs->ctrl_regs->tmr_temask, 0);
    545	ptp_qoriq->write(&regs->ctrl_regs->tmr_ctrl,   0);
    546
    547	ptp_qoriq_remove_debugfs(ptp_qoriq);
    548	ptp_clock_unregister(ptp_qoriq->clock);
    549	iounmap(ptp_qoriq->base);
    550	free_irq(ptp_qoriq->irq, ptp_qoriq);
    551}
    552EXPORT_SYMBOL_GPL(ptp_qoriq_free);
    553
    554static int ptp_qoriq_probe(struct platform_device *dev)
    555{
    556	struct ptp_qoriq *ptp_qoriq;
    557	int err = -ENOMEM;
    558	void __iomem *base;
    559
    560	ptp_qoriq = kzalloc(sizeof(*ptp_qoriq), GFP_KERNEL);
    561	if (!ptp_qoriq)
    562		goto no_memory;
    563
    564	ptp_qoriq->dev = &dev->dev;
    565
    566	err = -ENODEV;
    567
    568	ptp_qoriq->irq = platform_get_irq(dev, 0);
    569	if (ptp_qoriq->irq < 0) {
    570		pr_err("irq not in device tree\n");
    571		goto no_node;
    572	}
    573	if (request_irq(ptp_qoriq->irq, ptp_qoriq_isr, IRQF_SHARED,
    574			DRIVER, ptp_qoriq)) {
    575		pr_err("request_irq failed\n");
    576		goto no_node;
    577	}
    578
    579	ptp_qoriq->rsrc = platform_get_resource(dev, IORESOURCE_MEM, 0);
    580	if (!ptp_qoriq->rsrc) {
    581		pr_err("no resource\n");
    582		goto no_resource;
    583	}
    584	if (request_resource(&iomem_resource, ptp_qoriq->rsrc)) {
    585		pr_err("resource busy\n");
    586		goto no_resource;
    587	}
    588
    589	base = ioremap(ptp_qoriq->rsrc->start,
    590		       resource_size(ptp_qoriq->rsrc));
    591	if (!base) {
    592		pr_err("ioremap ptp registers failed\n");
    593		goto no_ioremap;
    594	}
    595
    596	err = ptp_qoriq_init(ptp_qoriq, base, &ptp_qoriq_caps);
    597	if (err)
    598		goto no_clock;
    599
    600	platform_set_drvdata(dev, ptp_qoriq);
    601	return 0;
    602
    603no_clock:
    604	iounmap(ptp_qoriq->base);
    605no_ioremap:
    606	release_resource(ptp_qoriq->rsrc);
    607no_resource:
    608	free_irq(ptp_qoriq->irq, ptp_qoriq);
    609no_node:
    610	kfree(ptp_qoriq);
    611no_memory:
    612	return err;
    613}
    614
    615static int ptp_qoriq_remove(struct platform_device *dev)
    616{
    617	struct ptp_qoriq *ptp_qoriq = platform_get_drvdata(dev);
    618
    619	ptp_qoriq_free(ptp_qoriq);
    620	release_resource(ptp_qoriq->rsrc);
    621	kfree(ptp_qoriq);
    622	return 0;
    623}
    624
    625static const struct of_device_id match_table[] = {
    626	{ .compatible = "fsl,etsec-ptp" },
    627	{ .compatible = "fsl,fman-ptp-timer" },
    628	{},
    629};
    630MODULE_DEVICE_TABLE(of, match_table);
    631
    632static struct platform_driver ptp_qoriq_driver = {
    633	.driver = {
    634		.name		= "ptp_qoriq",
    635		.of_match_table	= match_table,
    636	},
    637	.probe       = ptp_qoriq_probe,
    638	.remove      = ptp_qoriq_remove,
    639};
    640
    641module_platform_driver(ptp_qoriq_driver);
    642
    643MODULE_AUTHOR("Richard Cochran <richardcochran@gmail.com>");
    644MODULE_DESCRIPTION("PTP clock for Freescale QorIQ 1588 timer");
    645MODULE_LICENSE("GPL");