diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-03 19:55:55 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-03 19:55:55 -0400 |
commit | 807249d3ada1ff28a47c4054ca4edd479421b671 (patch) | |
tree | a9051ff7b4c31670ac89bb037c90d5baf90d449d /drivers/clocksource/mips-gic-timer.c | |
parent | ff474e8ca8547d09cb82ebab56d4c96f9eea01ce (diff) | |
parent | 2db97045aa40da4312f7321845bc52b136c8603a (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"This is the main pull request for 4.3 for MIPS. Here's the summary:
Three fixes that didn't make 4.2-stable:
- a -Os build might compile the kernel using the MIPS16 instruction
set but the R2 optimized inline functions in <uapi/asm/swab.h> are
implemented using 32-bit wide instructions which is invalid.
- a build error in pgtable-bits.h for a particular kernel
configuration.
- accessing registers of the CM GCR might have been compiled to use
64 bit accesses but these registers are onl 32 bit wide.
And also a few new bits:
- move the ATH79 GPIO driver to drivers/gpio
- the definition of IRQCHIP_DECLARE has moved to linux/irqchip.h,
change ATH79 accordingly.
- fix definition of pgprot_writecombine
- add an implementation of dma_map_ops.mmap
- fix alignment of quiet build output for vmlinuz link
- BCM47xx: Use kmemdup rather than duplicating its implementation
- Netlogic: Fix 0x0x prefixes of constants.
- merge Bjorn Helgaas' series to remove most of the weak keywords
from function declarations.
- CP0 and CP1 registers are best considered treated as unsigned
values to avoid large values from becoming negative values.
- improve support for the MIPS GIC timer.
- enable common clock framework for Malta and SEAD3.
- a number of improvments and fixes to dump_tlb().
- document the MIPS TLB dump functionality in Magic SysRq.
- Cavium Octeon CN68XX improvments.
- NetLogic improvments.
- irq: Use access helper irq_data_get_affinity_mask.
- handle MSA unaligned accesses.
- a number of R6-related math-emu fixes.
- support for I6400.
- improvments to MSA support.
- add uprobes support.
- move from deprecated __initcall to arch_initcall.
- remove finish_arch_switch().
- IRQ cleanups by Thomas Gleixner.
- migrate to new 'set-state' interface.
- random small cleanups"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (148 commits)
MIPS: UAPI: Fix unrecognized opcode WSBH/DSBH/DSHD when using MIPS16.
MIPS: Fix alignment of quiet build output for vmlinuz link
MIPS: math-emu: Remove unused handle_dsemul function declaration
MIPS: math-emu: Add support for the MIPS R6 MAX{, A} FPU instruction
MIPS: math-emu: Add support for the MIPS R6 MIN{, A} FPU instruction
MIPS: math-emu: Add support for the MIPS R6 CLASS FPU instruction
MIPS: math-emu: Add support for the MIPS R6 RINT FPU instruction
MIPS: math-emu: Add support for the MIPS R6 MSUBF FPU instruction
MIPS: math-emu: Add support for the MIPS R6 MADDF FPU instruction
MIPS: math-emu: Add support for the MIPS R6 SELNEZ FPU instruction
MIPS: math-emu: Add support for the MIPS R6 SELEQZ FPU instruction
MIPS: math-emu: Add support for the CMP.condn.fmt R6 instruction
MIPS: inst.h: Add new MIPS R6 FPU opcodes
MIPS: Octeon: Fix management port MII address on Kontron S1901
MIPS: BCM47xx: Use kmemdup rather than duplicating its implementation
STAGING: Octeon: Use common helpers for determining interface and port
MIPS: Octeon: Support interfaces 4 and 5
MIPS: Octeon: Set up 1:1 mapping between CN68XX PKO queues and ports
MIPS: Octeon: Initialize CN68XX PKO
STAGING: Octeon: Support CN68XX style WQE
...
Diffstat (limited to 'drivers/clocksource/mips-gic-timer.c')
-rw-r--r-- | drivers/clocksource/mips-gic-timer.c | 65 |
1 files changed, 56 insertions, 9 deletions
diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index c3810b61c815..02a1945e5093 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c | |||
@@ -72,6 +72,13 @@ static void gic_clockevent_cpu_exit(struct clock_event_device *cd) | |||
72 | disable_percpu_irq(gic_timer_irq); | 72 | disable_percpu_irq(gic_timer_irq); |
73 | } | 73 | } |
74 | 74 | ||
75 | static void gic_update_frequency(void *data) | ||
76 | { | ||
77 | unsigned long rate = (unsigned long)data; | ||
78 | |||
79 | clockevents_update_freq(this_cpu_ptr(&gic_clockevent_device), rate); | ||
80 | } | ||
81 | |||
75 | static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action, | 82 | static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action, |
76 | void *data) | 83 | void *data) |
77 | { | 84 | { |
@@ -87,18 +94,40 @@ static int gic_cpu_notifier(struct notifier_block *nb, unsigned long action, | |||
87 | return NOTIFY_OK; | 94 | return NOTIFY_OK; |
88 | } | 95 | } |
89 | 96 | ||
97 | static int gic_clk_notifier(struct notifier_block *nb, unsigned long action, | ||
98 | void *data) | ||
99 | { | ||
100 | struct clk_notifier_data *cnd = data; | ||
101 | |||
102 | if (action == POST_RATE_CHANGE) | ||
103 | on_each_cpu(gic_update_frequency, (void *)cnd->new_rate, 1); | ||
104 | |||
105 | return NOTIFY_OK; | ||
106 | } | ||
107 | |||
108 | |||
90 | static struct notifier_block gic_cpu_nb = { | 109 | static struct notifier_block gic_cpu_nb = { |
91 | .notifier_call = gic_cpu_notifier, | 110 | .notifier_call = gic_cpu_notifier, |
92 | }; | 111 | }; |
93 | 112 | ||
113 | static struct notifier_block gic_clk_nb = { | ||
114 | .notifier_call = gic_clk_notifier, | ||
115 | }; | ||
116 | |||
94 | static int gic_clockevent_init(void) | 117 | static int gic_clockevent_init(void) |
95 | { | 118 | { |
119 | int ret; | ||
120 | |||
96 | if (!cpu_has_counter || !gic_frequency) | 121 | if (!cpu_has_counter || !gic_frequency) |
97 | return -ENXIO; | 122 | return -ENXIO; |
98 | 123 | ||
99 | setup_percpu_irq(gic_timer_irq, &gic_compare_irqaction); | 124 | ret = setup_percpu_irq(gic_timer_irq, &gic_compare_irqaction); |
125 | if (ret < 0) | ||
126 | return ret; | ||
100 | 127 | ||
101 | register_cpu_notifier(&gic_cpu_nb); | 128 | ret = register_cpu_notifier(&gic_cpu_nb); |
129 | if (ret < 0) | ||
130 | pr_warn("GIC: Unable to register CPU notifier\n"); | ||
102 | 131 | ||
103 | gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device)); | 132 | gic_clockevent_cpu_init(this_cpu_ptr(&gic_clockevent_device)); |
104 | 133 | ||
@@ -118,18 +147,17 @@ static struct clocksource gic_clocksource = { | |||
118 | 147 | ||
119 | static void __init __gic_clocksource_init(void) | 148 | static void __init __gic_clocksource_init(void) |
120 | { | 149 | { |
150 | int ret; | ||
151 | |||
121 | /* Set clocksource mask. */ | 152 | /* Set clocksource mask. */ |
122 | gic_clocksource.mask = CLOCKSOURCE_MASK(gic_get_count_width()); | 153 | gic_clocksource.mask = CLOCKSOURCE_MASK(gic_get_count_width()); |
123 | 154 | ||
124 | /* Calculate a somewhat reasonable rating value. */ | 155 | /* Calculate a somewhat reasonable rating value. */ |
125 | gic_clocksource.rating = 200 + gic_frequency / 10000000; | 156 | gic_clocksource.rating = 200 + gic_frequency / 10000000; |
126 | 157 | ||
127 | clocksource_register_hz(&gic_clocksource, gic_frequency); | 158 | ret = clocksource_register_hz(&gic_clocksource, gic_frequency); |
128 | 159 | if (ret < 0) | |
129 | gic_clockevent_init(); | 160 | pr_warn("GIC: Unable to register clocksource\n"); |
130 | |||
131 | /* And finally start the counter */ | ||
132 | gic_start_count(); | ||
133 | } | 161 | } |
134 | 162 | ||
135 | void __init gic_clocksource_init(unsigned int frequency) | 163 | void __init gic_clocksource_init(unsigned int frequency) |
@@ -139,11 +167,16 @@ void __init gic_clocksource_init(unsigned int frequency) | |||
139 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); | 167 | GIC_LOCAL_TO_HWIRQ(GIC_LOCAL_INT_COMPARE); |
140 | 168 | ||
141 | __gic_clocksource_init(); | 169 | __gic_clocksource_init(); |
170 | gic_clockevent_init(); | ||
171 | |||
172 | /* And finally start the counter */ | ||
173 | gic_start_count(); | ||
142 | } | 174 | } |
143 | 175 | ||
144 | static void __init gic_clocksource_of_init(struct device_node *node) | 176 | static void __init gic_clocksource_of_init(struct device_node *node) |
145 | { | 177 | { |
146 | struct clk *clk; | 178 | struct clk *clk; |
179 | int ret; | ||
147 | 180 | ||
148 | if (WARN_ON(!gic_present || !node->parent || | 181 | if (WARN_ON(!gic_present || !node->parent || |
149 | !of_device_is_compatible(node->parent, "mti,gic"))) | 182 | !of_device_is_compatible(node->parent, "mti,gic"))) |
@@ -151,8 +184,13 @@ static void __init gic_clocksource_of_init(struct device_node *node) | |||
151 | 184 | ||
152 | clk = of_clk_get(node, 0); | 185 | clk = of_clk_get(node, 0); |
153 | if (!IS_ERR(clk)) { | 186 | if (!IS_ERR(clk)) { |
187 | if (clk_prepare_enable(clk) < 0) { | ||
188 | pr_err("GIC failed to enable clock\n"); | ||
189 | clk_put(clk); | ||
190 | return; | ||
191 | } | ||
192 | |||
154 | gic_frequency = clk_get_rate(clk); | 193 | gic_frequency = clk_get_rate(clk); |
155 | clk_put(clk); | ||
156 | } else if (of_property_read_u32(node, "clock-frequency", | 194 | } else if (of_property_read_u32(node, "clock-frequency", |
157 | &gic_frequency)) { | 195 | &gic_frequency)) { |
158 | pr_err("GIC frequency not specified.\n"); | 196 | pr_err("GIC frequency not specified.\n"); |
@@ -165,6 +203,15 @@ static void __init gic_clocksource_of_init(struct device_node *node) | |||
165 | } | 203 | } |
166 | 204 | ||
167 | __gic_clocksource_init(); | 205 | __gic_clocksource_init(); |
206 | |||
207 | ret = gic_clockevent_init(); | ||
208 | if (!ret && !IS_ERR(clk)) { | ||
209 | if (clk_notifier_register(clk, &gic_clk_nb) < 0) | ||
210 | pr_warn("GIC: Unable to register clock notifier\n"); | ||
211 | } | ||
212 | |||
213 | /* And finally start the counter */ | ||
214 | gic_start_count(); | ||
168 | } | 215 | } |
169 | CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer", | 216 | CLOCKSOURCE_OF_DECLARE(mips_gic_timer, "mti,gic-timer", |
170 | gic_clocksource_of_init); | 217 | gic_clocksource_of_init); |