| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2013-06-03 17:17:45 +01:00
										 |  |  |  * IMX GPT Timer | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * Copyright (c) 2008 OK Labs | 
					
						
							|  |  |  |  * Copyright (c) 2011 NICTA Pty Ltd | 
					
						
							| 
									
										
										
										
											2012-08-10 22:03:26 +02:00
										 |  |  |  * Originally written by Hans Jiang | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |  * Updated by Peter Chubb | 
					
						
							| 
									
										
										
										
											2015-08-13 11:26:20 +01:00
										 |  |  |  * Updated by Jean-Christophe Dubois <jcd@tribudubois.net> | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-08-10 22:03:26 +02:00
										 |  |  |  * This code is licensed under GPL version 2 or later.  See | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |  * the COPYING file in the top-level directory. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-01-26 18:17:05 +00:00
										 |  |  | #include "qemu/osdep.h"
 | 
					
						
							| 
									
										
										
										
											2015-08-13 11:26:20 +01:00
										 |  |  | #include "hw/timer/imx_gpt.h"
 | 
					
						
							| 
									
										
										
										
											2013-08-21 16:02:47 +01:00
										 |  |  | #include "qemu/main-loop.h"
 | 
					
						
							| 
									
										
										
										
											2015-12-15 13:16:16 +01:00
										 |  |  | #include "qemu/log.h"
 | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  | #ifndef DEBUG_IMX_GPT
 | 
					
						
							|  |  |  | #define DEBUG_IMX_GPT 0
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define DPRINTF(fmt, args...) \
 | 
					
						
							|  |  |  |     do { \ | 
					
						
							|  |  |  |         if (DEBUG_IMX_GPT) { \ | 
					
						
							|  |  |  |             fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_GPT, \ | 
					
						
							|  |  |  |                                              __func__, ##args); \ | 
					
						
							|  |  |  |         } \ | 
					
						
							|  |  |  |     } while (0) | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 18:13:09 +01:00
										 |  |  | static const char *imx_gpt_reg_name(uint32_t reg) | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     switch (reg) { | 
					
						
							|  |  |  |     case 0: | 
					
						
							|  |  |  |         return "CR"; | 
					
						
							|  |  |  |     case 1: | 
					
						
							|  |  |  |         return "PR"; | 
					
						
							|  |  |  |     case 2: | 
					
						
							|  |  |  |         return "SR"; | 
					
						
							|  |  |  |     case 3: | 
					
						
							|  |  |  |         return "IR"; | 
					
						
							|  |  |  |     case 4: | 
					
						
							|  |  |  |         return "OCR1"; | 
					
						
							|  |  |  |     case 5: | 
					
						
							|  |  |  |         return "OCR2"; | 
					
						
							|  |  |  |     case 6: | 
					
						
							|  |  |  |         return "OCR3"; | 
					
						
							|  |  |  |     case 7: | 
					
						
							|  |  |  |         return "ICR1"; | 
					
						
							|  |  |  |     case 8: | 
					
						
							|  |  |  |         return "ICR2"; | 
					
						
							|  |  |  |     case 9: | 
					
						
							|  |  |  |         return "CNT"; | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |         return "[?]"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static const VMStateDescription vmstate_imx_timer_gpt = { | 
					
						
							| 
									
										
										
										
											2015-08-13 11:26:21 +01:00
										 |  |  |     .name = TYPE_IMX_GPT, | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     .version_id = 3, | 
					
						
							|  |  |  |     .minimum_version_id = 3, | 
					
						
							| 
									
										
										
										
											2014-05-13 16:09:35 +01:00
										 |  |  |     .fields = (VMStateField[]) { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         VMSTATE_UINT32(cr, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(pr, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(sr, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(ir, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(ocr1, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(ocr2, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(ocr3, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(icr1, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(icr2, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(cnt, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(next_timeout, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(next_int, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_UINT32(freq, IMXGPTState), | 
					
						
							|  |  |  |         VMSTATE_PTIMER(timer, IMXGPTState), | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |         VMSTATE_END_OF_LIST() | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  | static const IMXClk imx25_gpt_clocks[] = { | 
					
						
							|  |  |  |     CLK_NONE,      /* 000 No clock source */ | 
					
						
							|  |  |  |     CLK_IPG,       /* 001 ipg_clk, 532MHz*/ | 
					
						
							|  |  |  |     CLK_IPG_HIGH,  /* 010 ipg_clk_highfreq */ | 
					
						
							|  |  |  |     CLK_NONE,      /* 011 not defined */ | 
					
						
							|  |  |  |     CLK_32k,       /* 100 ipg_clk_32k */ | 
					
						
							|  |  |  |     CLK_32k,       /* 101 ipg_clk_32k */ | 
					
						
							|  |  |  |     CLK_32k,       /* 110 ipg_clk_32k */ | 
					
						
							|  |  |  |     CLK_32k,       /* 111 ipg_clk_32k */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const IMXClk imx31_gpt_clocks[] = { | 
					
						
							| 
									
										
										
										
											2016-03-16 17:06:00 +00:00
										 |  |  |     CLK_NONE,      /* 000 No clock source */ | 
					
						
							|  |  |  |     CLK_IPG,       /* 001 ipg_clk, 532MHz*/ | 
					
						
							|  |  |  |     CLK_IPG_HIGH,  /* 010 ipg_clk_highfreq */ | 
					
						
							|  |  |  |     CLK_NONE,      /* 011 not defined */ | 
					
						
							|  |  |  |     CLK_32k,       /* 100 ipg_clk_32k */ | 
					
						
							|  |  |  |     CLK_NONE,      /* 101 not defined */ | 
					
						
							|  |  |  |     CLK_NONE,      /* 110 not defined */ | 
					
						
							|  |  |  |     CLK_NONE,      /* 111 not defined */ | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  | static const IMXClk imx6_gpt_clocks[] = { | 
					
						
							|  |  |  |     CLK_NONE,      /* 000 No clock source */ | 
					
						
							|  |  |  |     CLK_IPG,       /* 001 ipg_clk, 532MHz*/ | 
					
						
							|  |  |  |     CLK_IPG_HIGH,  /* 010 ipg_clk_highfreq */ | 
					
						
							|  |  |  |     CLK_EXT,       /* 011 External clock */ | 
					
						
							|  |  |  |     CLK_32k,       /* 100 ipg_clk_32k */ | 
					
						
							|  |  |  |     CLK_HIGH_DIV,  /* 101 reference clock / 8 */ | 
					
						
							|  |  |  |     CLK_NONE,      /* 110 not defined */ | 
					
						
							|  |  |  |     CLK_HIGH,      /* 111 reference clock */ | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_set_freq(IMXGPTState *s) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 13:37:15 +00:00
										 |  |  |     s->freq = imx_ccm_get_clock_frequency(s->ccm, | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  |                                           s->clocks[clksrc]) / (1 + s->pr); | 
					
						
							| 
									
										
										
										
											2013-06-03 17:17:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-17 13:37:15 +00:00
										 |  |  |     DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->freq) { | 
					
						
							|  |  |  |         ptimer_set_freq(s->timer, s->freq); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_update_int(IMXGPTState *s) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     if ((s->sr & s->ir) && (s->cr & GPT_CR_EN)) { | 
					
						
							|  |  |  |         qemu_irq_raise(s->irq); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         qemu_irq_lower(s->irq); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static uint32_t imx_gpt_update_count(IMXGPTState *s) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     s->cnt = s->next_timeout - (uint32_t)ptimer_get_count(s->timer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     return s->cnt; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg, | 
					
						
							| 
									
										
										
										
											2015-08-13 11:26:21 +01:00
										 |  |  |                                           uint32_t timeout) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     if ((count < reg) && (timeout > reg)) { | 
					
						
							|  |  |  |         timeout = reg; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return timeout; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event) | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |     uint32_t timeout = GPT_TIMER_MAX; | 
					
						
							| 
									
										
										
										
											2016-03-16 17:05:59 +00:00
										 |  |  |     uint32_t count; | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     long long limit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!(s->cr & GPT_CR_EN)) { | 
					
						
							|  |  |  |         /* if not enabled just return */ | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-16 17:05:59 +00:00
										 |  |  |     /* update the count */ | 
					
						
							|  |  |  |     count = imx_gpt_update_count(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-16 17:05:59 +00:00
										 |  |  |     if (event) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * This is an event (the ptimer reached 0 and stopped), and the | 
					
						
							|  |  |  |          * timer counter is now equal to s->next_timeout. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         if (!(s->cr & GPT_CR_FRR) && (count == s->ocr1)) { | 
					
						
							|  |  |  |             /* We are in restart mode and we crossed the compare channel 1
 | 
					
						
							|  |  |  |              * value. We need to reset the counter to 0. | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |              */ | 
					
						
							| 
									
										
										
										
											2016-03-16 17:05:59 +00:00
										 |  |  |             count = s->cnt = s->next_timeout = 0; | 
					
						
							|  |  |  |         } else if (count == GPT_TIMER_MAX) { | 
					
						
							|  |  |  |             /* We reached GPT_TIMER_MAX so we need to rollover */ | 
					
						
							|  |  |  |             count = s->cnt = s->next_timeout = 0; | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* now, find the next timeout related to count */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (s->ir & GPT_IR_OF1IE) { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         timeout = imx_gpt_find_limit(count, s->ocr1, timeout); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (s->ir & GPT_IR_OF2IE) { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         timeout = imx_gpt_find_limit(count, s->ocr2, timeout); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (s->ir & GPT_IR_OF3IE) { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         timeout = imx_gpt_find_limit(count, s->ocr3, timeout); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* find the next set of interrupts to raise for next timer event */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->next_int = 0; | 
					
						
							|  |  |  |     if ((s->ir & GPT_IR_OF1IE) && (timeout == s->ocr1)) { | 
					
						
							|  |  |  |         s->next_int |= GPT_SR_OF1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((s->ir & GPT_IR_OF2IE) && (timeout == s->ocr2)) { | 
					
						
							|  |  |  |         s->next_int |= GPT_SR_OF2; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if ((s->ir & GPT_IR_OF3IE) && (timeout == s->ocr3)) { | 
					
						
							|  |  |  |         s->next_int |= GPT_SR_OF3; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |     if ((s->ir & GPT_IR_ROVIE) && (timeout == GPT_TIMER_MAX)) { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         s->next_int |= GPT_SR_ROV; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* the new range to count down from */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     limit = timeout - imx_gpt_update_count(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (limit < 0) { | 
					
						
							|  |  |  |         /*
 | 
					
						
							|  |  |  |          * if we reach here, then QEMU is running too slow and we pass the | 
					
						
							|  |  |  |          * timeout limit while computing it. Let's deliver the interrupt | 
					
						
							|  |  |  |          * and compute a new limit. | 
					
						
							|  |  |  |          */ | 
					
						
							|  |  |  |         s->sr |= s->next_int; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_compute_next_timeout(s, event); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_update_int(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     } else { | 
					
						
							|  |  |  |         /* New timeout value */ | 
					
						
							|  |  |  |         s->next_timeout = timeout; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* reset the limit to the computed range */ | 
					
						
							|  |  |  |         ptimer_set_limit(s->timer, limit, 1); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     IMXGPTState *s = IMX_GPT(opaque); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     uint32_t reg_value = 0; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |     switch (offset >> 2) { | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     case 0: /* Control Register */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->cr; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 1: /* prescaler */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->pr; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 2: /* Status Register */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->sr; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 3: /* Interrupt Register */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->ir; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 4: /* Output Compare Register 1 */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->ocr1; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  |     case 5: /* Output Compare Register 2 */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->ocr2; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 6: /* Output Compare Register 3 */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->ocr3; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 7: /* input Capture Register 1 */ | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |         qemu_log_mask(LOG_UNIMP, "[%s]%s: icr1 feature is not implemented\n", | 
					
						
							|  |  |  |                       TYPE_IMX_GPT, __func__); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->icr1; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 8: /* input Capture Register 2 */ | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |         qemu_log_mask(LOG_UNIMP, "[%s]%s: icr2 feature is not implemented\n", | 
					
						
							|  |  |  |                       TYPE_IMX_GPT, __func__); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->icr2; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 9: /* cnt */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_update_count(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         reg_value = s->cnt; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     default: | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" | 
					
						
							|  |  |  |                       HWADDR_PRIx "\n", TYPE_IMX_GPT, __func__, offset); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |     DPRINTF("(%s) = 0x%08x\n", imx_gpt_reg_name(offset >> 2), reg_value); | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     return reg_value; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_reset(DeviceState *dev) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     IMXGPTState *s = IMX_GPT(dev); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     /* stop timer */ | 
					
						
							|  |  |  |     ptimer_stop(s->timer); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     /*
 | 
					
						
							|  |  |  |      * Soft reset doesn't touch some bits; hard reset clears them | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  |     s->cr &= ~(GPT_CR_EN|GPT_CR_ENMOD|GPT_CR_STOPEN|GPT_CR_DOZEN| | 
					
						
							|  |  |  |                GPT_CR_WAITEN|GPT_CR_DBGEN); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     s->sr = 0; | 
					
						
							|  |  |  |     s->pr = 0; | 
					
						
							|  |  |  |     s->ir = 0; | 
					
						
							|  |  |  |     s->cnt = 0; | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |     s->ocr1 = GPT_TIMER_MAX; | 
					
						
							|  |  |  |     s->ocr2 = GPT_TIMER_MAX; | 
					
						
							|  |  |  |     s->ocr3 = GPT_TIMER_MAX; | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  |     s->icr1 = 0; | 
					
						
							|  |  |  |     s->icr2 = 0; | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |     s->next_timeout = GPT_TIMER_MAX; | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     s->next_int = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* compute new freq */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     imx_gpt_set_freq(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |     /* reset the limit to GPT_TIMER_MAX */ | 
					
						
							|  |  |  |     ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /* if the timer is still enabled, restart it */ | 
					
						
							|  |  |  |     if (s->freq && (s->cr & GPT_CR_EN)) { | 
					
						
							|  |  |  |         ptimer_run(s->timer, 1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value, | 
					
						
							|  |  |  |                           unsigned size) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     IMXGPTState *s = IMX_GPT(opaque); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     uint32_t oldreg; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |     DPRINTF("(%s, value = 0x%08x)\n", imx_gpt_reg_name(offset >> 2), | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |             (uint32_t)value); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |     switch (offset >> 2) { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     case 0: | 
					
						
							|  |  |  |         oldreg = s->cr; | 
					
						
							|  |  |  |         s->cr = value & ~0x7c14; | 
					
						
							|  |  |  |         if (s->cr & GPT_CR_SWR) { /* force reset */ | 
					
						
							|  |  |  |             /* handle the reset */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |             imx_gpt_reset(DEVICE(s)); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             /* set our freq, as the source might have changed */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |             imx_gpt_set_freq(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if ((oldreg ^ s->cr) & GPT_CR_EN) { | 
					
						
							|  |  |  |                 if (s->cr & GPT_CR_EN) { | 
					
						
							|  |  |  |                     if (s->cr & GPT_CR_ENMOD) { | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |                         s->next_timeout = GPT_TIMER_MAX; | 
					
						
							|  |  |  |                         ptimer_set_count(s->timer, GPT_TIMER_MAX); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |                         imx_gpt_compute_next_timeout(s, false); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |                     } | 
					
						
							|  |  |  |                     ptimer_run(s->timer, 1); | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     /* stop timer */ | 
					
						
							|  |  |  |                     ptimer_stop(s->timer); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 1: /* Prescaler */ | 
					
						
							|  |  |  |         s->pr = value & 0xfff; | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_set_freq(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 2: /* SR */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         s->sr &= ~(value & 0x3f); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_update_int(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 3: /* IR -- interrupt register */ | 
					
						
							|  |  |  |         s->ir = value & 0x3f; | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_update_int(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_compute_next_timeout(s, false); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case 4: /* OCR1 -- output compare register */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         s->ocr1 = value; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |         /* In non-freerun mode, reset count when this register is written */ | 
					
						
							|  |  |  |         if (!(s->cr & GPT_CR_FRR)) { | 
					
						
							| 
									
										
										
										
											2014-08-02 00:14:48 +04:00
										 |  |  |             s->next_timeout = GPT_TIMER_MAX; | 
					
						
							|  |  |  |             ptimer_set_limit(s->timer, GPT_TIMER_MAX, 1); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         /* compute the new timeout */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_compute_next_timeout(s, false); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  |     case 5: /* OCR2 -- output compare register */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         s->ocr2 = value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* compute the new timeout */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_compute_next_timeout(s, false); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-05-03 18:21:02 +01:00
										 |  |  |     case 6: /* OCR3 -- output compare register */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         s->ocr3 = value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         /* compute the new timeout */ | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         imx_gpt_compute_next_timeout(s, false); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     default: | 
					
						
							| 
									
										
										
										
											2015-10-25 15:16:26 +01:00
										 |  |  |         qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" | 
					
						
							|  |  |  |                       HWADDR_PRIx "\n", TYPE_IMX_GPT, __func__, offset); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_timeout(void *opaque) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     IMXGPTState *s = IMX_GPT(opaque); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     DPRINTF("\n"); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     s->sr |= s->next_int; | 
					
						
							|  |  |  |     s->next_int = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     imx_gpt_compute_next_timeout(s, true); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     imx_gpt_update_int(s); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (s->freq && (s->cr & GPT_CR_EN)) { | 
					
						
							|  |  |  |         ptimer_run(s->timer, 1); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static const MemoryRegionOps imx_gpt_ops = { | 
					
						
							|  |  |  |     .read = imx_gpt_read, | 
					
						
							|  |  |  |     .write = imx_gpt_write, | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     .endianness = DEVICE_NATIVE_ENDIAN, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_realize(DeviceState *dev, Error **errp) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     IMXGPTState *s = IMX_GPT(dev); | 
					
						
							|  |  |  |     SysBusDevice *sbd = SYS_BUS_DEVICE(dev); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     QEMUBH *bh; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     sysbus_init_irq(sbd, &s->irq); | 
					
						
							| 
									
										
										
										
											2013-06-06 21:25:08 -04:00
										 |  |  |     memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT, | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |                           0x00001000); | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     sysbus_init_mmio(sbd, &s->iomem); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     bh = qemu_bh_new(imx_gpt_timeout, s); | 
					
						
							| 
									
										
										
										
											2016-09-22 18:13:06 +01:00
										 |  |  |     s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_class_init(ObjectClass *klass, void *data) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     DeviceClass *dc = DEVICE_CLASS(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     dc->realize = imx_gpt_realize; | 
					
						
							|  |  |  |     dc->reset = imx_gpt_reset; | 
					
						
							|  |  |  |     dc->vmsd = &vmstate_imx_timer_gpt; | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     dc->desc = "i.MX general timer"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  | static void imx25_gpt_init(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IMXGPTState *s = IMX_GPT(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->clocks = imx25_gpt_clocks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void imx31_gpt_init(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IMXGPTState *s = IMX_GPT(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->clocks = imx31_gpt_clocks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void imx6_gpt_init(Object *obj) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     IMXGPTState *s = IMX_GPT(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s->clocks = imx6_gpt_clocks; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TypeInfo imx25_gpt_info = { | 
					
						
							|  |  |  |     .name = TYPE_IMX25_GPT, | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  |     .parent = TYPE_SYS_BUS_DEVICE, | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     .instance_size = sizeof(IMXGPTState), | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  |     .instance_init = imx25_gpt_init, | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  |     .class_init = imx_gpt_class_init, | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  | static const TypeInfo imx31_gpt_info = { | 
					
						
							|  |  |  |     .name = TYPE_IMX31_GPT, | 
					
						
							|  |  |  |     .parent = TYPE_IMX25_GPT, | 
					
						
							|  |  |  |     .instance_init = imx31_gpt_init, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const TypeInfo imx6_gpt_info = { | 
					
						
							|  |  |  |     .name = TYPE_IMX6_GPT, | 
					
						
							|  |  |  |     .parent = TYPE_IMX25_GPT, | 
					
						
							|  |  |  |     .instance_init = imx6_gpt_init, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | static void imx_gpt_register_types(void) | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-07 13:47:01 +01:00
										 |  |  |     type_register_static(&imx25_gpt_info); | 
					
						
							|  |  |  |     type_register_static(&imx31_gpt_info); | 
					
						
							|  |  |  |     type_register_static(&imx6_gpt_info); | 
					
						
							| 
									
										
										
										
											2012-07-04 10:43:33 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-25 18:34:13 +01:00
										 |  |  | type_init(imx_gpt_register_types) |