| Fabio Estevam | c53bb60 | 2018-05-22 20:05:04 -0300 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0+ | 
 | 2 | // | 
 | 3 | //  Copyright (C) 2000-2001 Deep Blue Solutions | 
 | 4 | //  Copyright (C) 2002 Shane Nay (shane@minirl.com) | 
 | 5 | //  Copyright (C) 2006-2007 Pavel Pisa (ppisa@pikron.com) | 
 | 6 | //  Copyright (C) 2008 Juergen Beisert (kernel@pengutronix.de) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 7 |  | 
 | 8 | #include <linux/interrupt.h> | 
 | 9 | #include <linux/irq.h> | 
 | 10 | #include <linux/clockchips.h> | 
 | 11 | #include <linux/clk.h> | 
| Sebastian Andrzej Siewior | 1119c84 | 2014-01-22 12:35:44 +0100 | [diff] [blame] | 12 | #include <linux/delay.h> | 
| Sascha Hauer | 821dc4d | 2012-03-09 09:29:27 +0100 | [diff] [blame] | 13 | #include <linux/err.h> | 
| Stephen Boyd | 38ff87f | 2013-06-01 23:39:40 -0700 | [diff] [blame] | 14 | #include <linux/sched_clock.h> | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 15 | #include <linux/slab.h> | 
| Gilles Chanteperdrix | 876292d | 2014-04-05 17:57:45 +0200 | [diff] [blame] | 16 | #include <linux/of.h> | 
 | 17 | #include <linux/of_address.h> | 
 | 18 | #include <linux/of_irq.h> | 
| Shawn Guo | 0931aff | 2015-05-15 11:41:39 +0800 | [diff] [blame] | 19 | #include <soc/imx/timer.h> | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 20 |  | 
| Sascha Hauer | 0f3332c | 2009-12-04 09:34:51 +0100 | [diff] [blame] | 21 | /* | 
| Shenwei Wang | 65d0a16 | 2015-04-29 16:40:27 -0500 | [diff] [blame] | 22 |  * There are 4 versions of the timer hardware on Freescale MXC hardware. | 
 | 23 |  *  - MX1/MXL | 
 | 24 |  *  - MX21, MX27. | 
 | 25 |  *  - MX25, MX31, MX35, MX37, MX51, MX6Q(rev1.0) | 
 | 26 |  *  - MX6DL, MX6SX, MX6Q(rev1.1+) | 
| Sascha Hauer | 0f3332c | 2009-12-04 09:34:51 +0100 | [diff] [blame] | 27 |  */ | 
 | 28 |  | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 29 | /* defines common for all i.MX */ | 
 | 30 | #define MXC_TCTL		0x00 | 
| Sascha Hauer | 0f3332c | 2009-12-04 09:34:51 +0100 | [diff] [blame] | 31 | #define MXC_TCTL_TEN		(1 << 0) /* Enable module */ | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 32 | #define MXC_TPRER		0x04 | 
 | 33 |  | 
 | 34 | /* MX1, MX21, MX27 */ | 
 | 35 | #define MX1_2_TCTL_CLK_PCLK1	(1 << 1) | 
 | 36 | #define MX1_2_TCTL_IRQEN	(1 << 4) | 
 | 37 | #define MX1_2_TCTL_FRR		(1 << 8) | 
 | 38 | #define MX1_2_TCMP		0x08 | 
 | 39 | #define MX1_2_TCN		0x10 | 
 | 40 | #define MX1_2_TSTAT		0x14 | 
 | 41 |  | 
 | 42 | /* MX21, MX27 */ | 
 | 43 | #define MX2_TSTAT_CAPT		(1 << 1) | 
 | 44 | #define MX2_TSTAT_COMP		(1 << 0) | 
 | 45 |  | 
| Anson Huang | bad3db1 | 2014-09-11 11:29:42 +0800 | [diff] [blame] | 46 | /* MX31, MX35, MX25, MX5, MX6 */ | 
| Amit Kucheria | 38a66f5 | 2010-04-21 21:34:36 +0300 | [diff] [blame] | 47 | #define V2_TCTL_WAITEN		(1 << 3) /* Wait enable mode */ | 
 | 48 | #define V2_TCTL_CLK_IPG		(1 << 6) | 
| Richard Zhao | 1f152b4 | 2012-05-15 15:34:40 +0800 | [diff] [blame] | 49 | #define V2_TCTL_CLK_PER		(2 << 6) | 
| Anson Huang | bad3db1 | 2014-09-11 11:29:42 +0800 | [diff] [blame] | 50 | #define V2_TCTL_CLK_OSC_DIV8	(5 << 6) | 
| Amit Kucheria | 38a66f5 | 2010-04-21 21:34:36 +0300 | [diff] [blame] | 51 | #define V2_TCTL_FRR		(1 << 9) | 
| Anson Huang | bad3db1 | 2014-09-11 11:29:42 +0800 | [diff] [blame] | 52 | #define V2_TCTL_24MEN		(1 << 10) | 
 | 53 | #define V2_TPRER_PRE24M		12 | 
| Amit Kucheria | 38a66f5 | 2010-04-21 21:34:36 +0300 | [diff] [blame] | 54 | #define V2_IR			0x0c | 
 | 55 | #define V2_TSTAT		0x08 | 
 | 56 | #define V2_TSTAT_OF1		(1 << 0) | 
 | 57 | #define V2_TCN			0x24 | 
 | 58 | #define V2_TCMP			0x10 | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 59 |  | 
| Anson Huang | bad3db1 | 2014-09-11 11:29:42 +0800 | [diff] [blame] | 60 | #define V2_TIMER_RATE_OSC_DIV8	3000000 | 
 | 61 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 62 | struct imx_timer { | 
| Shawn Guo | 0931aff | 2015-05-15 11:41:39 +0800 | [diff] [blame] | 63 | 	enum imx_gpt_type type; | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 64 | 	void __iomem *base; | 
 | 65 | 	int irq; | 
 | 66 | 	struct clk *clk_per; | 
 | 67 | 	struct clk *clk_ipg; | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 68 | 	const struct imx_gpt_data *gpt; | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 69 | 	struct clock_event_device ced; | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 70 | 	struct irqaction act; | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 71 | }; | 
 | 72 |  | 
 | 73 | struct imx_gpt_data { | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 74 | 	int reg_tstat; | 
 | 75 | 	int reg_tcn; | 
 | 76 | 	int reg_tcmp; | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 77 | 	void (*gpt_setup_tctl)(struct imx_timer *imxtm); | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 78 | 	void (*gpt_irq_enable)(struct imx_timer *imxtm); | 
 | 79 | 	void (*gpt_irq_disable)(struct imx_timer *imxtm); | 
 | 80 | 	void (*gpt_irq_acknowledge)(struct imx_timer *imxtm); | 
| Shawn Guo | 5ab0475 | 2015-05-22 15:51:41 +0800 | [diff] [blame] | 81 | 	int (*set_next_event)(unsigned long evt, | 
 | 82 | 			      struct clock_event_device *ced); | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 83 | }; | 
 | 84 |  | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 85 | static inline struct imx_timer *to_imx_timer(struct clock_event_device *ced) | 
 | 86 | { | 
 | 87 | 	return container_of(ced, struct imx_timer, ced); | 
 | 88 | } | 
 | 89 |  | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 90 | static void imx1_gpt_irq_disable(struct imx_timer *imxtm) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 91 | { | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 92 | 	unsigned int tmp; | 
 | 93 |  | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 94 | 	tmp = readl_relaxed(imxtm->base + MXC_TCTL); | 
 | 95 | 	writel_relaxed(tmp & ~MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL); | 
 | 96 | } | 
 | 97 | #define imx21_gpt_irq_disable imx1_gpt_irq_disable | 
 | 98 |  | 
 | 99 | static void imx31_gpt_irq_disable(struct imx_timer *imxtm) | 
 | 100 | { | 
 | 101 | 	writel_relaxed(0, imxtm->base + V2_IR); | 
 | 102 | } | 
 | 103 | #define imx6dl_gpt_irq_disable imx31_gpt_irq_disable | 
 | 104 |  | 
 | 105 | static void imx1_gpt_irq_enable(struct imx_timer *imxtm) | 
 | 106 | { | 
 | 107 | 	unsigned int tmp; | 
 | 108 |  | 
 | 109 | 	tmp = readl_relaxed(imxtm->base + MXC_TCTL); | 
 | 110 | 	writel_relaxed(tmp | MX1_2_TCTL_IRQEN, imxtm->base + MXC_TCTL); | 
 | 111 | } | 
 | 112 | #define imx21_gpt_irq_enable imx1_gpt_irq_enable | 
 | 113 |  | 
 | 114 | static void imx31_gpt_irq_enable(struct imx_timer *imxtm) | 
 | 115 | { | 
 | 116 | 	writel_relaxed(1<<0, imxtm->base + V2_IR); | 
 | 117 | } | 
 | 118 | #define imx6dl_gpt_irq_enable imx31_gpt_irq_enable | 
 | 119 |  | 
 | 120 | static void imx1_gpt_irq_acknowledge(struct imx_timer *imxtm) | 
 | 121 | { | 
 | 122 | 	writel_relaxed(0, imxtm->base + MX1_2_TSTAT); | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 123 | } | 
 | 124 |  | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 125 | static void imx21_gpt_irq_acknowledge(struct imx_timer *imxtm) | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 126 | { | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 127 | 	writel_relaxed(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 128 | 				imxtm->base + MX1_2_TSTAT); | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 129 | } | 
 | 130 |  | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 131 | static void imx31_gpt_irq_acknowledge(struct imx_timer *imxtm) | 
 | 132 | { | 
 | 133 | 	writel_relaxed(V2_TSTAT_OF1, imxtm->base + V2_TSTAT); | 
 | 134 | } | 
 | 135 | #define imx6dl_gpt_irq_acknowledge imx31_gpt_irq_acknowledge | 
 | 136 |  | 
| Russell King | 234b6ced | 2011-05-08 14:09:47 +0100 | [diff] [blame] | 137 | static void __iomem *sched_clock_reg; | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 138 |  | 
| Stephen Boyd | b93767e | 2013-11-15 15:26:12 -0800 | [diff] [blame] | 139 | static u64 notrace mxc_read_sched_clock(void) | 
| Jan Weitzel | c124bef | 2011-03-17 13:44:30 +0100 | [diff] [blame] | 140 | { | 
| Shawn Guo | c7770bb | 2015-05-19 18:47:47 +0800 | [diff] [blame] | 141 | 	return sched_clock_reg ? readl_relaxed(sched_clock_reg) : 0; | 
| Jan Weitzel | c124bef | 2011-03-17 13:44:30 +0100 | [diff] [blame] | 142 | } | 
 | 143 |  | 
| Sebastian Andrzej Siewior | 1119c84 | 2014-01-22 12:35:44 +0100 | [diff] [blame] | 144 | static struct delay_timer imx_delay_timer; | 
 | 145 |  | 
 | 146 | static unsigned long imx_read_current_timer(void) | 
 | 147 | { | 
| Shawn Guo | c7770bb | 2015-05-19 18:47:47 +0800 | [diff] [blame] | 148 | 	return readl_relaxed(sched_clock_reg); | 
| Sebastian Andrzej Siewior | 1119c84 | 2014-01-22 12:35:44 +0100 | [diff] [blame] | 149 | } | 
 | 150 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 151 | static int __init mxc_clocksource_init(struct imx_timer *imxtm) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 152 | { | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 153 | 	unsigned int c = clk_get_rate(imxtm->clk_per); | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 154 | 	void __iomem *reg = imxtm->base + imxtm->gpt->reg_tcn; | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 155 |  | 
| Sebastian Andrzej Siewior | 1119c84 | 2014-01-22 12:35:44 +0100 | [diff] [blame] | 156 | 	imx_delay_timer.read_current_timer = &imx_read_current_timer; | 
 | 157 | 	imx_delay_timer.freq = c; | 
 | 158 | 	register_current_timer_delay(&imx_delay_timer); | 
 | 159 |  | 
| Russell King | 234b6ced | 2011-05-08 14:09:47 +0100 | [diff] [blame] | 160 | 	sched_clock_reg = reg; | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 161 |  | 
| Stephen Boyd | b93767e | 2013-11-15 15:26:12 -0800 | [diff] [blame] | 162 | 	sched_clock_register(mxc_read_sched_clock, 32, c); | 
| Russell King | 234b6ced | 2011-05-08 14:09:47 +0100 | [diff] [blame] | 163 | 	return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32, | 
 | 164 | 			clocksource_mmio_readl_up); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 165 | } | 
 | 166 |  | 
 | 167 | /* clock event */ | 
 | 168 |  | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 169 | static int mx1_2_set_next_event(unsigned long evt, | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 170 | 			      struct clock_event_device *ced) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 171 | { | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 172 | 	struct imx_timer *imxtm = to_imx_timer(ced); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 173 | 	unsigned long tcmp; | 
 | 174 |  | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 175 | 	tcmp = readl_relaxed(imxtm->base + MX1_2_TCN) + evt; | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 176 |  | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 177 | 	writel_relaxed(tcmp, imxtm->base + MX1_2_TCMP); | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 178 |  | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 179 | 	return (int)(tcmp - readl_relaxed(imxtm->base + MX1_2_TCN)) < 0 ? | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 180 | 				-ETIME : 0; | 
 | 181 | } | 
 | 182 |  | 
| Amit Kucheria | 38a66f5 | 2010-04-21 21:34:36 +0300 | [diff] [blame] | 183 | static int v2_set_next_event(unsigned long evt, | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 184 | 			      struct clock_event_device *ced) | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 185 | { | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 186 | 	struct imx_timer *imxtm = to_imx_timer(ced); | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 187 | 	unsigned long tcmp; | 
 | 188 |  | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 189 | 	tcmp = readl_relaxed(imxtm->base + V2_TCN) + evt; | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 190 |  | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 191 | 	writel_relaxed(tcmp, imxtm->base + V2_TCMP); | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 192 |  | 
| Shawn Guo | eea8e32 | 2012-12-06 22:54:41 +0800 | [diff] [blame] | 193 | 	return evt < 0x7fffffff && | 
| Shawn Guo | 8995552 | 2015-05-22 22:23:28 +0800 | [diff] [blame] | 194 | 		(int)(tcmp - readl_relaxed(imxtm->base + V2_TCN)) < 0 ? | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 195 | 				-ETIME : 0; | 
 | 196 | } | 
 | 197 |  | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 198 | static int mxc_shutdown(struct clock_event_device *ced) | 
 | 199 | { | 
 | 200 | 	struct imx_timer *imxtm = to_imx_timer(ced); | 
 | 201 | 	unsigned long flags; | 
 | 202 | 	u32 tcn; | 
 | 203 |  | 
 | 204 | 	/* | 
 | 205 | 	 * The timer interrupt generation is disabled at least | 
 | 206 | 	 * for enough time to call mxc_set_next_event() | 
 | 207 | 	 */ | 
 | 208 | 	local_irq_save(flags); | 
 | 209 |  | 
 | 210 | 	/* Disable interrupt in GPT module */ | 
 | 211 | 	imxtm->gpt->gpt_irq_disable(imxtm); | 
 | 212 |  | 
 | 213 | 	tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn); | 
 | 214 | 	/* Set event time into far-far future */ | 
 | 215 | 	writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp); | 
 | 216 |  | 
 | 217 | 	/* Clear pending interrupt */ | 
 | 218 | 	imxtm->gpt->gpt_irq_acknowledge(imxtm); | 
 | 219 |  | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 220 | #ifdef DEBUG | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 221 | 	printk(KERN_INFO "%s: changing mode\n", __func__); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 222 | #endif /* DEBUG */ | 
 | 223 |  | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 224 | 	local_irq_restore(flags); | 
 | 225 |  | 
 | 226 | 	return 0; | 
 | 227 | } | 
 | 228 |  | 
 | 229 | static int mxc_set_oneshot(struct clock_event_device *ced) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 230 | { | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 231 | 	struct imx_timer *imxtm = to_imx_timer(ced); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 232 | 	unsigned long flags; | 
 | 233 |  | 
 | 234 | 	/* | 
 | 235 | 	 * The timer interrupt generation is disabled at least | 
 | 236 | 	 * for enough time to call mxc_set_next_event() | 
 | 237 | 	 */ | 
 | 238 | 	local_irq_save(flags); | 
 | 239 |  | 
 | 240 | 	/* Disable interrupt in GPT module */ | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 241 | 	imxtm->gpt->gpt_irq_disable(imxtm); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 242 |  | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 243 | 	if (!clockevent_state_oneshot(ced)) { | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 244 | 		u32 tcn = readl_relaxed(imxtm->base + imxtm->gpt->reg_tcn); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 245 | 		/* Set event time into far-far future */ | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 246 | 		writel_relaxed(tcn - 3, imxtm->base + imxtm->gpt->reg_tcmp); | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 247 |  | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 248 | 		/* Clear pending interrupt */ | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 249 | 		imxtm->gpt->gpt_irq_acknowledge(imxtm); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 250 | 	} | 
 | 251 |  | 
 | 252 | #ifdef DEBUG | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 253 | 	printk(KERN_INFO "%s: changing mode\n", __func__); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 254 | #endif /* DEBUG */ | 
 | 255 |  | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 256 | 	/* | 
 | 257 | 	 * Do not put overhead of interrupt enable/disable into | 
 | 258 | 	 * mxc_set_next_event(), the core has about 4 minutes | 
 | 259 | 	 * to call mxc_set_next_event() or shutdown clock after | 
 | 260 | 	 * mode switching | 
 | 261 | 	 */ | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 262 | 	imxtm->gpt->gpt_irq_enable(imxtm); | 
 | 263 | 	local_irq_restore(flags); | 
 | 264 |  | 
 | 265 | 	return 0; | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 266 | } | 
 | 267 |  | 
 | 268 | /* | 
 | 269 |  * IRQ handler for the timer | 
 | 270 |  */ | 
 | 271 | static irqreturn_t mxc_timer_interrupt(int irq, void *dev_id) | 
 | 272 | { | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 273 | 	struct clock_event_device *ced = dev_id; | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 274 | 	struct imx_timer *imxtm = to_imx_timer(ced); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 275 | 	uint32_t tstat; | 
 | 276 |  | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 277 | 	tstat = readl_relaxed(imxtm->base + imxtm->gpt->reg_tstat); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 278 |  | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 279 | 	imxtm->gpt->gpt_irq_acknowledge(imxtm); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 280 |  | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 281 | 	ced->event_handler(ced); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 282 |  | 
 | 283 | 	return IRQ_HANDLED; | 
 | 284 | } | 
 | 285 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 286 | static int __init mxc_clockevent_init(struct imx_timer *imxtm) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 287 | { | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 288 | 	struct clock_event_device *ced = &imxtm->ced; | 
 | 289 | 	struct irqaction *act = &imxtm->act; | 
 | 290 |  | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 291 | 	ced->name = "mxc_timer1"; | 
| Lucas Stach | f1c08c9 | 2015-10-14 11:24:17 +0200 | [diff] [blame] | 292 | 	ced->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_DYNIRQ; | 
| Viresh Kumar | 26b91f0 | 2015-07-06 15:39:18 +0530 | [diff] [blame] | 293 | 	ced->set_state_shutdown = mxc_shutdown; | 
 | 294 | 	ced->set_state_oneshot = mxc_set_oneshot; | 
 | 295 | 	ced->tick_resume = mxc_shutdown; | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 296 | 	ced->set_next_event = imxtm->gpt->set_next_event; | 
 | 297 | 	ced->rating = 200; | 
 | 298 | 	ced->cpumask = cpumask_of(0); | 
| Lucas Stach | f1c08c9 | 2015-10-14 11:24:17 +0200 | [diff] [blame] | 299 | 	ced->irq = imxtm->irq; | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 300 | 	clockevents_config_and_register(ced, clk_get_rate(imxtm->clk_per), | 
| Shawn Guo | 838a2ae | 2013-01-12 11:50:05 +0000 | [diff] [blame] | 301 | 					0xff, 0xfffffffe); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 302 |  | 
| Shawn Guo | e510d20 | 2015-05-22 16:38:49 +0800 | [diff] [blame] | 303 | 	act->name = "i.MX Timer Tick"; | 
 | 304 | 	act->flags = IRQF_TIMER | IRQF_IRQPOLL; | 
 | 305 | 	act->handler = mxc_timer_interrupt; | 
 | 306 | 	act->dev_id = ced; | 
 | 307 |  | 
 | 308 | 	return setup_irq(imxtm->irq, act); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 309 | } | 
 | 310 |  | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 311 | static void imx1_gpt_setup_tctl(struct imx_timer *imxtm) | 
 | 312 | { | 
 | 313 | 	u32 tctl_val; | 
 | 314 |  | 
 | 315 | 	tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN; | 
 | 316 | 	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); | 
 | 317 | } | 
 | 318 | #define imx21_gpt_setup_tctl imx1_gpt_setup_tctl | 
 | 319 |  | 
 | 320 | static void imx31_gpt_setup_tctl(struct imx_timer *imxtm) | 
 | 321 | { | 
 | 322 | 	u32 tctl_val; | 
 | 323 |  | 
 | 324 | 	tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; | 
 | 325 | 	if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) | 
 | 326 | 		tctl_val |= V2_TCTL_CLK_OSC_DIV8; | 
 | 327 | 	else | 
 | 328 | 		tctl_val |= V2_TCTL_CLK_PER; | 
 | 329 |  | 
 | 330 | 	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); | 
 | 331 | } | 
 | 332 |  | 
 | 333 | static void imx6dl_gpt_setup_tctl(struct imx_timer *imxtm) | 
 | 334 | { | 
 | 335 | 	u32 tctl_val; | 
 | 336 |  | 
 | 337 | 	tctl_val = V2_TCTL_FRR | V2_TCTL_WAITEN | MXC_TCTL_TEN; | 
 | 338 | 	if (clk_get_rate(imxtm->clk_per) == V2_TIMER_RATE_OSC_DIV8) { | 
 | 339 | 		tctl_val |= V2_TCTL_CLK_OSC_DIV8; | 
 | 340 | 		/* 24 / 8 = 3 MHz */ | 
 | 341 | 		writel_relaxed(7 << V2_TPRER_PRE24M, imxtm->base + MXC_TPRER); | 
 | 342 | 		tctl_val |= V2_TCTL_24MEN; | 
 | 343 | 	} else { | 
 | 344 | 		tctl_val |= V2_TCTL_CLK_PER; | 
 | 345 | 	} | 
 | 346 |  | 
 | 347 | 	writel_relaxed(tctl_val, imxtm->base + MXC_TCTL); | 
 | 348 | } | 
 | 349 |  | 
 | 350 | static const struct imx_gpt_data imx1_gpt_data = { | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 351 | 	.reg_tstat = MX1_2_TSTAT, | 
 | 352 | 	.reg_tcn = MX1_2_TCN, | 
 | 353 | 	.reg_tcmp = MX1_2_TCMP, | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 354 | 	.gpt_irq_enable = imx1_gpt_irq_enable, | 
 | 355 | 	.gpt_irq_disable = imx1_gpt_irq_disable, | 
 | 356 | 	.gpt_irq_acknowledge = imx1_gpt_irq_acknowledge, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 357 | 	.gpt_setup_tctl = imx1_gpt_setup_tctl, | 
| Shawn Guo | 5ab0475 | 2015-05-22 15:51:41 +0800 | [diff] [blame] | 358 | 	.set_next_event = mx1_2_set_next_event, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 359 | }; | 
 | 360 |  | 
 | 361 | static const struct imx_gpt_data imx21_gpt_data = { | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 362 | 	.reg_tstat = MX1_2_TSTAT, | 
 | 363 | 	.reg_tcn = MX1_2_TCN, | 
 | 364 | 	.reg_tcmp = MX1_2_TCMP, | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 365 | 	.gpt_irq_enable = imx21_gpt_irq_enable, | 
 | 366 | 	.gpt_irq_disable = imx21_gpt_irq_disable, | 
 | 367 | 	.gpt_irq_acknowledge = imx21_gpt_irq_acknowledge, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 368 | 	.gpt_setup_tctl = imx21_gpt_setup_tctl, | 
| Shawn Guo | 5ab0475 | 2015-05-22 15:51:41 +0800 | [diff] [blame] | 369 | 	.set_next_event = mx1_2_set_next_event, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 370 | }; | 
 | 371 |  | 
 | 372 | static const struct imx_gpt_data imx31_gpt_data = { | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 373 | 	.reg_tstat = V2_TSTAT, | 
 | 374 | 	.reg_tcn = V2_TCN, | 
 | 375 | 	.reg_tcmp = V2_TCMP, | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 376 | 	.gpt_irq_enable = imx31_gpt_irq_enable, | 
 | 377 | 	.gpt_irq_disable = imx31_gpt_irq_disable, | 
 | 378 | 	.gpt_irq_acknowledge = imx31_gpt_irq_acknowledge, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 379 | 	.gpt_setup_tctl = imx31_gpt_setup_tctl, | 
| Shawn Guo | 5ab0475 | 2015-05-22 15:51:41 +0800 | [diff] [blame] | 380 | 	.set_next_event = v2_set_next_event, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 381 | }; | 
 | 382 |  | 
 | 383 | static const struct imx_gpt_data imx6dl_gpt_data = { | 
| Shawn Guo | 24f74ad | 2015-05-22 21:39:55 +0800 | [diff] [blame] | 384 | 	.reg_tstat = V2_TSTAT, | 
 | 385 | 	.reg_tcn = V2_TCN, | 
 | 386 | 	.reg_tcmp = V2_TCMP, | 
| Shawn Guo | db2ae4b | 2015-05-22 22:42:55 +0800 | [diff] [blame] | 387 | 	.gpt_irq_enable = imx6dl_gpt_irq_enable, | 
 | 388 | 	.gpt_irq_disable = imx6dl_gpt_irq_disable, | 
 | 389 | 	.gpt_irq_acknowledge = imx6dl_gpt_irq_acknowledge, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 390 | 	.gpt_setup_tctl = imx6dl_gpt_setup_tctl, | 
| Shawn Guo | 5ab0475 | 2015-05-22 15:51:41 +0800 | [diff] [blame] | 391 | 	.set_next_event = v2_set_next_event, | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 392 | }; | 
 | 393 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 394 | static int __init _mxc_timer_init(struct imx_timer *imxtm) | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 395 | { | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 396 | 	int ret; | 
 | 397 |  | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 398 | 	switch (imxtm->type) { | 
 | 399 | 	case GPT_TYPE_IMX1: | 
 | 400 | 		imxtm->gpt = &imx1_gpt_data; | 
 | 401 | 		break; | 
 | 402 | 	case GPT_TYPE_IMX21: | 
 | 403 | 		imxtm->gpt = &imx21_gpt_data; | 
 | 404 | 		break; | 
 | 405 | 	case GPT_TYPE_IMX31: | 
 | 406 | 		imxtm->gpt = &imx31_gpt_data; | 
 | 407 | 		break; | 
 | 408 | 	case GPT_TYPE_IMX6DL: | 
 | 409 | 		imxtm->gpt = &imx6dl_gpt_data; | 
 | 410 | 		break; | 
 | 411 | 	default: | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 412 | 		return -EINVAL; | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 413 | 	} | 
 | 414 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 415 | 	if (IS_ERR(imxtm->clk_per)) { | 
| Sascha Hauer | 2cfb451 | 2012-05-16 12:29:53 +0200 | [diff] [blame] | 416 | 		pr_err("i.MX timer: unable to get clk\n"); | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 417 | 		return PTR_ERR(imxtm->clk_per); | 
| Sascha Hauer | 821dc4d | 2012-03-09 09:29:27 +0100 | [diff] [blame] | 418 | 	} | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 419 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 420 | 	if (!IS_ERR(imxtm->clk_ipg)) | 
 | 421 | 		clk_prepare_enable(imxtm->clk_ipg); | 
| Sascha Hauer | 2cfb451 | 2012-05-16 12:29:53 +0200 | [diff] [blame] | 422 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 423 | 	clk_prepare_enable(imxtm->clk_per); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 424 |  | 
 | 425 | 	/* | 
 | 426 | 	 * Initialise to a known state (all timers off, and timing reset) | 
 | 427 | 	 */ | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 428 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 429 | 	writel_relaxed(0, imxtm->base + MXC_TCTL); | 
 | 430 | 	writel_relaxed(0, imxtm->base + MXC_TPRER); /* see datasheet note */ | 
| Sascha Hauer | ec996ba | 2009-02-18 20:58:40 +0100 | [diff] [blame] | 431 |  | 
| Shawn Guo | 9c8694b | 2015-05-15 14:24:41 +0800 | [diff] [blame] | 432 | 	imxtm->gpt->gpt_setup_tctl(imxtm); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 433 |  | 
 | 434 | 	/* init and register the timer to the framework */ | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 435 | 	ret = mxc_clocksource_init(imxtm); | 
 | 436 | 	if (ret) | 
 | 437 | 		return ret; | 
 | 438 |  | 
 | 439 | 	return mxc_clockevent_init(imxtm); | 
| Juergen Beisert | d0f349f | 2008-07-05 10:02:50 +0200 | [diff] [blame] | 440 | } | 
| Gilles Chanteperdrix | 876292d | 2014-04-05 17:57:45 +0200 | [diff] [blame] | 441 |  | 
| Shawn Guo | 0931aff | 2015-05-15 11:41:39 +0800 | [diff] [blame] | 442 | void __init mxc_timer_init(unsigned long pbase, int irq, enum imx_gpt_type type) | 
| Alexander Shiyan | f469675 | 2014-05-27 13:04:46 +0400 | [diff] [blame] | 443 | { | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 444 | 	struct imx_timer *imxtm; | 
| Alexander Shiyan | f469675 | 2014-05-27 13:04:46 +0400 | [diff] [blame] | 445 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 446 | 	imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL); | 
 | 447 | 	BUG_ON(!imxtm); | 
| Alexander Shiyan | d7f9891 | 2014-05-27 13:04:47 +0400 | [diff] [blame] | 448 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 449 | 	imxtm->clk_per = clk_get_sys("imx-gpt.0", "per"); | 
 | 450 | 	imxtm->clk_ipg = clk_get_sys("imx-gpt.0", "ipg"); | 
 | 451 |  | 
 | 452 | 	imxtm->base = ioremap(pbase, SZ_4K); | 
 | 453 | 	BUG_ON(!imxtm->base); | 
 | 454 |  | 
| Shawn Guo | 0931aff | 2015-05-15 11:41:39 +0800 | [diff] [blame] | 455 | 	imxtm->type = type; | 
| Guenter Roeck | be3b0f9 | 2015-08-20 03:27:21 -0700 | [diff] [blame] | 456 | 	imxtm->irq = irq; | 
| Shawn Guo | 0931aff | 2015-05-15 11:41:39 +0800 | [diff] [blame] | 457 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 458 | 	_mxc_timer_init(imxtm); | 
| Alexander Shiyan | f469675 | 2014-05-27 13:04:46 +0400 | [diff] [blame] | 459 | } | 
 | 460 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 461 | static int __init mxc_timer_init_dt(struct device_node *np,  enum imx_gpt_type type) | 
| Gilles Chanteperdrix | 876292d | 2014-04-05 17:57:45 +0200 | [diff] [blame] | 462 | { | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 463 | 	struct imx_timer *imxtm; | 
 | 464 | 	static int initialized; | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 465 | 	int ret; | 
| Gilles Chanteperdrix | 876292d | 2014-04-05 17:57:45 +0200 | [diff] [blame] | 466 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 467 | 	/* Support one instance only */ | 
 | 468 | 	if (initialized) | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 469 | 		return 0; | 
| Alexander Shiyan | fd4959d | 2014-07-13 09:34:00 +0400 | [diff] [blame] | 470 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 471 | 	imxtm = kzalloc(sizeof(*imxtm), GFP_KERNEL); | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 472 | 	if (!imxtm) | 
 | 473 | 		return -ENOMEM; | 
| Gilles Chanteperdrix | 876292d | 2014-04-05 17:57:45 +0200 | [diff] [blame] | 474 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 475 | 	imxtm->base = of_iomap(np, 0); | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 476 | 	if (!imxtm->base) | 
 | 477 | 		return -ENXIO; | 
 | 478 |  | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 479 | 	imxtm->irq = irq_of_parse_and_map(np, 0); | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 480 | 	if (imxtm->irq <= 0) | 
 | 481 | 		return -EINVAL; | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 482 |  | 
 | 483 | 	imxtm->clk_ipg = of_clk_get_by_name(np, "ipg"); | 
| Alexander Shiyan | f469675 | 2014-05-27 13:04:46 +0400 | [diff] [blame] | 484 |  | 
| Anson Huang | bad3db1 | 2014-09-11 11:29:42 +0800 | [diff] [blame] | 485 | 	/* Try osc_per first, and fall back to per otherwise */ | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 486 | 	imxtm->clk_per = of_clk_get_by_name(np, "osc_per"); | 
 | 487 | 	if (IS_ERR(imxtm->clk_per)) | 
 | 488 | 		imxtm->clk_per = of_clk_get_by_name(np, "per"); | 
| Anson Huang | bad3db1 | 2014-09-11 11:29:42 +0800 | [diff] [blame] | 489 |  | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 490 | 	imxtm->type = type; | 
 | 491 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 492 | 	ret = _mxc_timer_init(imxtm); | 
 | 493 | 	if (ret) | 
 | 494 | 		return ret; | 
| Shawn Guo | 6dd7478 | 2015-05-22 13:53:45 +0800 | [diff] [blame] | 495 |  | 
 | 496 | 	initialized = 1; | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 497 |  | 
 | 498 | 	return 0; | 
| Gilles Chanteperdrix | 876292d | 2014-04-05 17:57:45 +0200 | [diff] [blame] | 499 | } | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 500 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 501 | static int __init imx1_timer_init_dt(struct device_node *np) | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 502 | { | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 503 | 	return mxc_timer_init_dt(np, GPT_TYPE_IMX1); | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 504 | } | 
 | 505 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 506 | static int __init imx21_timer_init_dt(struct device_node *np) | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 507 | { | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 508 | 	return mxc_timer_init_dt(np, GPT_TYPE_IMX21); | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 509 | } | 
 | 510 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 511 | static int __init imx31_timer_init_dt(struct device_node *np) | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 512 | { | 
 | 513 | 	enum imx_gpt_type type = GPT_TYPE_IMX31; | 
 | 514 |  | 
 | 515 | 	/* | 
 | 516 | 	 * We were using the same compatible string for i.MX6Q/D and i.MX6DL/S | 
 | 517 | 	 * GPT device, while they actually have different programming model. | 
 | 518 | 	 * This is a workaround to keep the existing i.MX6DL/S DTBs continue | 
 | 519 | 	 * working with the new kernel. | 
 | 520 | 	 */ | 
 | 521 | 	if (of_machine_is_compatible("fsl,imx6dl")) | 
 | 522 | 		type = GPT_TYPE_IMX6DL; | 
 | 523 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 524 | 	return mxc_timer_init_dt(np, type); | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 525 | } | 
 | 526 |  | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 527 | static int __init imx6dl_timer_init_dt(struct device_node *np) | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 528 | { | 
| Daniel Lezcano | c11cd41 | 2016-06-06 23:27:05 +0200 | [diff] [blame] | 529 | 	return mxc_timer_init_dt(np, GPT_TYPE_IMX6DL); | 
| Shawn Guo | bef11c8 | 2015-05-15 13:38:20 +0800 | [diff] [blame] | 530 | } | 
 | 531 |  | 
| Daniel Lezcano | 1727339 | 2017-05-26 16:56:11 +0200 | [diff] [blame] | 532 | TIMER_OF_DECLARE(imx1_timer, "fsl,imx1-gpt", imx1_timer_init_dt); | 
 | 533 | TIMER_OF_DECLARE(imx21_timer, "fsl,imx21-gpt", imx21_timer_init_dt); | 
 | 534 | TIMER_OF_DECLARE(imx27_timer, "fsl,imx27-gpt", imx21_timer_init_dt); | 
 | 535 | TIMER_OF_DECLARE(imx31_timer, "fsl,imx31-gpt", imx31_timer_init_dt); | 
 | 536 | TIMER_OF_DECLARE(imx25_timer, "fsl,imx25-gpt", imx31_timer_init_dt); | 
 | 537 | TIMER_OF_DECLARE(imx50_timer, "fsl,imx50-gpt", imx31_timer_init_dt); | 
 | 538 | TIMER_OF_DECLARE(imx51_timer, "fsl,imx51-gpt", imx31_timer_init_dt); | 
 | 539 | TIMER_OF_DECLARE(imx53_timer, "fsl,imx53-gpt", imx31_timer_init_dt); | 
 | 540 | TIMER_OF_DECLARE(imx6q_timer, "fsl,imx6q-gpt", imx31_timer_init_dt); | 
 | 541 | TIMER_OF_DECLARE(imx6dl_timer, "fsl,imx6dl-gpt", imx6dl_timer_init_dt); | 
 | 542 | TIMER_OF_DECLARE(imx6sl_timer, "fsl,imx6sl-gpt", imx6dl_timer_init_dt); | 
 | 543 | TIMER_OF_DECLARE(imx6sx_timer, "fsl,imx6sx-gpt", imx6dl_timer_init_dt); |