diff options
-rw-r--r-- | arch/mips/kernel/cevt-txx9.c | 67 |
1 files changed, 43 insertions, 24 deletions
diff --git a/arch/mips/kernel/cevt-txx9.c b/arch/mips/kernel/cevt-txx9.c index 2e911e3da8d3..0037f21baf0d 100644 --- a/arch/mips/kernel/cevt-txx9.c +++ b/arch/mips/kernel/cevt-txx9.c | |||
@@ -20,22 +20,29 @@ | |||
20 | #define TIMER_CCD 0 /* 1/2 */ | 20 | #define TIMER_CCD 0 /* 1/2 */ |
21 | #define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD)) | 21 | #define TIMER_CLK(imclk) ((imclk) / (2 << TIMER_CCD)) |
22 | 22 | ||
23 | static struct txx9_tmr_reg __iomem *txx9_cs_tmrptr; | 23 | struct txx9_clocksource { |
24 | struct clocksource cs; | ||
25 | struct txx9_tmr_reg __iomem *tmrptr; | ||
26 | }; | ||
24 | 27 | ||
25 | static cycle_t txx9_cs_read(struct clocksource *cs) | 28 | static cycle_t txx9_cs_read(struct clocksource *cs) |
26 | { | 29 | { |
27 | return __raw_readl(&txx9_cs_tmrptr->trr); | 30 | struct txx9_clocksource *txx9_cs = |
31 | container_of(cs, struct txx9_clocksource, cs); | ||
32 | return __raw_readl(&txx9_cs->tmrptr->trr); | ||
28 | } | 33 | } |
29 | 34 | ||
30 | /* Use 1 bit smaller width to use full bits in that width */ | 35 | /* Use 1 bit smaller width to use full bits in that width */ |
31 | #define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1) | 36 | #define TXX9_CLOCKSOURCE_BITS (TXX9_TIMER_BITS - 1) |
32 | 37 | ||
33 | static struct clocksource txx9_clocksource = { | 38 | static struct txx9_clocksource txx9_clocksource = { |
34 | .name = "TXx9", | 39 | .cs = { |
35 | .rating = 200, | 40 | .name = "TXx9", |
36 | .read = txx9_cs_read, | 41 | .rating = 200, |
37 | .mask = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS), | 42 | .read = txx9_cs_read, |
38 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | 43 | .mask = CLOCKSOURCE_MASK(TXX9_CLOCKSOURCE_BITS), |
44 | .flags = CLOCK_SOURCE_IS_CONTINUOUS, | ||
45 | }, | ||
39 | }; | 46 | }; |
40 | 47 | ||
41 | void __init txx9_clocksource_init(unsigned long baseaddr, | 48 | void __init txx9_clocksource_init(unsigned long baseaddr, |
@@ -43,8 +50,8 @@ void __init txx9_clocksource_init(unsigned long baseaddr, | |||
43 | { | 50 | { |
44 | struct txx9_tmr_reg __iomem *tmrptr; | 51 | struct txx9_tmr_reg __iomem *tmrptr; |
45 | 52 | ||
46 | clocksource_set_clock(&txx9_clocksource, TIMER_CLK(imbusclk)); | 53 | clocksource_set_clock(&txx9_clocksource.cs, TIMER_CLK(imbusclk)); |
47 | clocksource_register(&txx9_clocksource); | 54 | clocksource_register(&txx9_clocksource.cs); |
48 | 55 | ||
49 | tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); | 56 | tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); |
50 | __raw_writel(TCR_BASE, &tmrptr->tcr); | 57 | __raw_writel(TCR_BASE, &tmrptr->tcr); |
@@ -53,10 +60,13 @@ void __init txx9_clocksource_init(unsigned long baseaddr, | |||
53 | __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr); | 60 | __raw_writel(TXx9_TMITMR_TZCE, &tmrptr->itmr); |
54 | __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra); | 61 | __raw_writel(1 << TXX9_CLOCKSOURCE_BITS, &tmrptr->cpra); |
55 | __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); | 62 | __raw_writel(TCR_BASE | TXx9_TMTCR_TCE, &tmrptr->tcr); |
56 | txx9_cs_tmrptr = tmrptr; | 63 | txx9_clocksource.tmrptr = tmrptr; |
57 | } | 64 | } |
58 | 65 | ||
59 | static struct txx9_tmr_reg __iomem *txx9_tmrptr; | 66 | struct txx9_clock_event_device { |
67 | struct clock_event_device cd; | ||
68 | struct txx9_tmr_reg __iomem *tmrptr; | ||
69 | }; | ||
60 | 70 | ||
61 | static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr) | 71 | static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr) |
62 | { | 72 | { |
@@ -69,7 +79,9 @@ static void txx9tmr_stop_and_clear(struct txx9_tmr_reg __iomem *tmrptr) | |||
69 | static void txx9tmr_set_mode(enum clock_event_mode mode, | 79 | static void txx9tmr_set_mode(enum clock_event_mode mode, |
70 | struct clock_event_device *evt) | 80 | struct clock_event_device *evt) |
71 | { | 81 | { |
72 | struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; | 82 | struct txx9_clock_event_device *txx9_cd = |
83 | container_of(evt, struct txx9_clock_event_device, cd); | ||
84 | struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr; | ||
73 | 85 | ||
74 | txx9tmr_stop_and_clear(tmrptr); | 86 | txx9tmr_stop_and_clear(tmrptr); |
75 | switch (mode) { | 87 | switch (mode) { |
@@ -99,7 +111,9 @@ static void txx9tmr_set_mode(enum clock_event_mode mode, | |||
99 | static int txx9tmr_set_next_event(unsigned long delta, | 111 | static int txx9tmr_set_next_event(unsigned long delta, |
100 | struct clock_event_device *evt) | 112 | struct clock_event_device *evt) |
101 | { | 113 | { |
102 | struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; | 114 | struct txx9_clock_event_device *txx9_cd = |
115 | container_of(evt, struct txx9_clock_event_device, cd); | ||
116 | struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr; | ||
103 | 117 | ||
104 | txx9tmr_stop_and_clear(tmrptr); | 118 | txx9tmr_stop_and_clear(tmrptr); |
105 | /* start timer */ | 119 | /* start timer */ |
@@ -108,18 +122,22 @@ static int txx9tmr_set_next_event(unsigned long delta, | |||
108 | return 0; | 122 | return 0; |
109 | } | 123 | } |
110 | 124 | ||
111 | static struct clock_event_device txx9tmr_clock_event_device = { | 125 | static struct txx9_clock_event_device txx9_clock_event_device = { |
112 | .name = "TXx9", | 126 | .cd = { |
113 | .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, | 127 | .name = "TXx9", |
114 | .rating = 200, | 128 | .features = CLOCK_EVT_FEAT_PERIODIC | |
115 | .set_mode = txx9tmr_set_mode, | 129 | CLOCK_EVT_FEAT_ONESHOT, |
116 | .set_next_event = txx9tmr_set_next_event, | 130 | .rating = 200, |
131 | .set_mode = txx9tmr_set_mode, | ||
132 | .set_next_event = txx9tmr_set_next_event, | ||
133 | }, | ||
117 | }; | 134 | }; |
118 | 135 | ||
119 | static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id) | 136 | static irqreturn_t txx9tmr_interrupt(int irq, void *dev_id) |
120 | { | 137 | { |
121 | struct clock_event_device *cd = &txx9tmr_clock_event_device; | 138 | struct txx9_clock_event_device *txx9_cd = dev_id; |
122 | struct txx9_tmr_reg __iomem *tmrptr = txx9_tmrptr; | 139 | struct clock_event_device *cd = &txx9_cd->cd; |
140 | struct txx9_tmr_reg __iomem *tmrptr = txx9_cd->tmrptr; | ||
123 | 141 | ||
124 | __raw_writel(0, &tmrptr->tisr); /* ack interrupt */ | 142 | __raw_writel(0, &tmrptr->tisr); /* ack interrupt */ |
125 | cd->event_handler(cd); | 143 | cd->event_handler(cd); |
@@ -130,19 +148,20 @@ static struct irqaction txx9tmr_irq = { | |||
130 | .handler = txx9tmr_interrupt, | 148 | .handler = txx9tmr_interrupt, |
131 | .flags = IRQF_DISABLED | IRQF_PERCPU, | 149 | .flags = IRQF_DISABLED | IRQF_PERCPU, |
132 | .name = "txx9tmr", | 150 | .name = "txx9tmr", |
151 | .dev_id = &txx9_clock_event_device, | ||
133 | }; | 152 | }; |
134 | 153 | ||
135 | void __init txx9_clockevent_init(unsigned long baseaddr, int irq, | 154 | void __init txx9_clockevent_init(unsigned long baseaddr, int irq, |
136 | unsigned int imbusclk) | 155 | unsigned int imbusclk) |
137 | { | 156 | { |
138 | struct clock_event_device *cd = &txx9tmr_clock_event_device; | 157 | struct clock_event_device *cd = &txx9_clock_event_device.cd; |
139 | struct txx9_tmr_reg __iomem *tmrptr; | 158 | struct txx9_tmr_reg __iomem *tmrptr; |
140 | 159 | ||
141 | tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); | 160 | tmrptr = ioremap(baseaddr, sizeof(struct txx9_tmr_reg)); |
142 | txx9tmr_stop_and_clear(tmrptr); | 161 | txx9tmr_stop_and_clear(tmrptr); |
143 | __raw_writel(TIMER_CCD, &tmrptr->ccdr); | 162 | __raw_writel(TIMER_CCD, &tmrptr->ccdr); |
144 | __raw_writel(0, &tmrptr->itmr); | 163 | __raw_writel(0, &tmrptr->itmr); |
145 | txx9_tmrptr = tmrptr; | 164 | txx9_clock_event_device.tmrptr = tmrptr; |
146 | 165 | ||
147 | clockevent_set_clock(cd, TIMER_CLK(imbusclk)); | 166 | clockevent_set_clock(cd, TIMER_CLK(imbusclk)); |
148 | cd->max_delta_ns = | 167 | cd->max_delta_ns = |