diff options
-rw-r--r-- | drivers/clocksource/em_sti.c | 13 | ||||
-rw-r--r-- | drivers/clocksource/sh_cmt.c | 189 | ||||
-rw-r--r-- | drivers/clocksource/sh_mtu2.c | 2 | ||||
-rw-r--r-- | drivers/clocksource/sh_tmu.c | 2 |
4 files changed, 132 insertions, 74 deletions
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index e6a553cb73e8..4329a29a5310 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c | |||
@@ -399,7 +399,18 @@ static struct platform_driver em_sti_device_driver = { | |||
399 | } | 399 | } |
400 | }; | 400 | }; |
401 | 401 | ||
402 | module_platform_driver(em_sti_device_driver); | 402 | static int __init em_sti_init(void) |
403 | { | ||
404 | return platform_driver_register(&em_sti_device_driver); | ||
405 | } | ||
406 | |||
407 | static void __exit em_sti_exit(void) | ||
408 | { | ||
409 | platform_driver_unregister(&em_sti_device_driver); | ||
410 | } | ||
411 | |||
412 | subsys_initcall(em_sti_init); | ||
413 | module_exit(em_sti_exit); | ||
403 | 414 | ||
404 | MODULE_AUTHOR("Magnus Damm"); | 415 | MODULE_AUTHOR("Magnus Damm"); |
405 | MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); | 416 | MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); |
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 488c14cc8dbf..08d0c418c94a 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
@@ -54,62 +54,100 @@ struct sh_cmt_priv { | |||
54 | struct clocksource cs; | 54 | struct clocksource cs; |
55 | unsigned long total_cycles; | 55 | unsigned long total_cycles; |
56 | bool cs_enabled; | 56 | bool cs_enabled; |
57 | |||
58 | /* callbacks for CMSTR and CMCSR access */ | ||
59 | unsigned long (*read_control)(void __iomem *base, unsigned long offs); | ||
60 | void (*write_control)(void __iomem *base, unsigned long offs, | ||
61 | unsigned long value); | ||
62 | |||
63 | /* callbacks for CMCNT and CMCOR access */ | ||
64 | unsigned long (*read_count)(void __iomem *base, unsigned long offs); | ||
65 | void (*write_count)(void __iomem *base, unsigned long offs, | ||
66 | unsigned long value); | ||
57 | }; | 67 | }; |
58 | 68 | ||
59 | static DEFINE_RAW_SPINLOCK(sh_cmt_lock); | 69 | /* Examples of supported CMT timer register layouts and I/O access widths: |
70 | * | ||
71 | * "16-bit counter and 16-bit control" as found on sh7263: | ||
72 | * CMSTR 0xfffec000 16-bit | ||
73 | * CMCSR 0xfffec002 16-bit | ||
74 | * CMCNT 0xfffec004 16-bit | ||
75 | * CMCOR 0xfffec006 16-bit | ||
76 | * | ||
77 | * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740: | ||
78 | * CMSTR 0xffca0000 16-bit | ||
79 | * CMCSR 0xffca0060 16-bit | ||
80 | * CMCNT 0xffca0064 32-bit | ||
81 | * CMCOR 0xffca0068 32-bit | ||
82 | */ | ||
83 | |||
84 | static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs) | ||
85 | { | ||
86 | return ioread16(base + (offs << 1)); | ||
87 | } | ||
88 | |||
89 | static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs) | ||
90 | { | ||
91 | return ioread32(base + (offs << 2)); | ||
92 | } | ||
93 | |||
94 | static void sh_cmt_write16(void __iomem *base, unsigned long offs, | ||
95 | unsigned long value) | ||
96 | { | ||
97 | iowrite16(value, base + (offs << 1)); | ||
98 | } | ||
99 | |||
100 | static void sh_cmt_write32(void __iomem *base, unsigned long offs, | ||
101 | unsigned long value) | ||
102 | { | ||
103 | iowrite32(value, base + (offs << 2)); | ||
104 | } | ||
60 | 105 | ||
61 | #define CMSTR -1 /* shared register */ | ||
62 | #define CMCSR 0 /* channel register */ | 106 | #define CMCSR 0 /* channel register */ |
63 | #define CMCNT 1 /* channel register */ | 107 | #define CMCNT 1 /* channel register */ |
64 | #define CMCOR 2 /* channel register */ | 108 | #define CMCOR 2 /* channel register */ |
65 | 109 | ||
66 | static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) | 110 | static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p) |
67 | { | 111 | { |
68 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | 112 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
69 | void __iomem *base = p->mapbase; | ||
70 | unsigned long offs; | ||
71 | |||
72 | if (reg_nr == CMSTR) { | ||
73 | offs = 0; | ||
74 | base -= cfg->channel_offset; | ||
75 | } else | ||
76 | offs = reg_nr; | ||
77 | |||
78 | if (p->width == 16) | ||
79 | offs <<= 1; | ||
80 | else { | ||
81 | offs <<= 2; | ||
82 | if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) | ||
83 | return ioread32(base + offs); | ||
84 | } | ||
85 | 113 | ||
86 | return ioread16(base + offs); | 114 | return p->read_control(p->mapbase - cfg->channel_offset, 0); |
87 | } | 115 | } |
88 | 116 | ||
89 | static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr, | 117 | static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p) |
90 | unsigned long value) | 118 | { |
119 | return p->read_control(p->mapbase, CMCSR); | ||
120 | } | ||
121 | |||
122 | static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p) | ||
123 | { | ||
124 | return p->read_count(p->mapbase, CMCNT); | ||
125 | } | ||
126 | |||
127 | static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p, | ||
128 | unsigned long value) | ||
91 | { | 129 | { |
92 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | 130 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
93 | void __iomem *base = p->mapbase; | ||
94 | unsigned long offs; | ||
95 | |||
96 | if (reg_nr == CMSTR) { | ||
97 | offs = 0; | ||
98 | base -= cfg->channel_offset; | ||
99 | } else | ||
100 | offs = reg_nr; | ||
101 | |||
102 | if (p->width == 16) | ||
103 | offs <<= 1; | ||
104 | else { | ||
105 | offs <<= 2; | ||
106 | if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) { | ||
107 | iowrite32(value, base + offs); | ||
108 | return; | ||
109 | } | ||
110 | } | ||
111 | 131 | ||
112 | iowrite16(value, base + offs); | 132 | p->write_control(p->mapbase - cfg->channel_offset, 0, value); |
133 | } | ||
134 | |||
135 | static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p, | ||
136 | unsigned long value) | ||
137 | { | ||
138 | p->write_control(p->mapbase, CMCSR, value); | ||
139 | } | ||
140 | |||
141 | static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p, | ||
142 | unsigned long value) | ||
143 | { | ||
144 | p->write_count(p->mapbase, CMCNT, value); | ||
145 | } | ||
146 | |||
147 | static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p, | ||
148 | unsigned long value) | ||
149 | { | ||
150 | p->write_count(p->mapbase, CMCOR, value); | ||
113 | } | 151 | } |
114 | 152 | ||
115 | static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | 153 | static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, |
@@ -118,15 +156,15 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | |||
118 | unsigned long v1, v2, v3; | 156 | unsigned long v1, v2, v3; |
119 | int o1, o2; | 157 | int o1, o2; |
120 | 158 | ||
121 | o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit; | 159 | o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit; |
122 | 160 | ||
123 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ | 161 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ |
124 | do { | 162 | do { |
125 | o2 = o1; | 163 | o2 = o1; |
126 | v1 = sh_cmt_read(p, CMCNT); | 164 | v1 = sh_cmt_read_cmcnt(p); |
127 | v2 = sh_cmt_read(p, CMCNT); | 165 | v2 = sh_cmt_read_cmcnt(p); |
128 | v3 = sh_cmt_read(p, CMCNT); | 166 | v3 = sh_cmt_read_cmcnt(p); |
129 | o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit; | 167 | o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit; |
130 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) | 168 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) |
131 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); | 169 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); |
132 | 170 | ||
@@ -134,6 +172,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | |||
134 | return v2; | 172 | return v2; |
135 | } | 173 | } |
136 | 174 | ||
175 | static DEFINE_RAW_SPINLOCK(sh_cmt_lock); | ||
137 | 176 | ||
138 | static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | 177 | static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) |
139 | { | 178 | { |
@@ -142,14 +181,14 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | |||
142 | 181 | ||
143 | /* start stop register shared by multiple timer channels */ | 182 | /* start stop register shared by multiple timer channels */ |
144 | raw_spin_lock_irqsave(&sh_cmt_lock, flags); | 183 | raw_spin_lock_irqsave(&sh_cmt_lock, flags); |
145 | value = sh_cmt_read(p, CMSTR); | 184 | value = sh_cmt_read_cmstr(p); |
146 | 185 | ||
147 | if (start) | 186 | if (start) |
148 | value |= 1 << cfg->timer_bit; | 187 | value |= 1 << cfg->timer_bit; |
149 | else | 188 | else |
150 | value &= ~(1 << cfg->timer_bit); | 189 | value &= ~(1 << cfg->timer_bit); |
151 | 190 | ||
152 | sh_cmt_write(p, CMSTR, value); | 191 | sh_cmt_write_cmstr(p, value); |
153 | raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); | 192 | raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); |
154 | } | 193 | } |
155 | 194 | ||
@@ -173,14 +212,14 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | |||
173 | /* configure channel, periodic mode and maximum timeout */ | 212 | /* configure channel, periodic mode and maximum timeout */ |
174 | if (p->width == 16) { | 213 | if (p->width == 16) { |
175 | *rate = clk_get_rate(p->clk) / 512; | 214 | *rate = clk_get_rate(p->clk) / 512; |
176 | sh_cmt_write(p, CMCSR, 0x43); | 215 | sh_cmt_write_cmcsr(p, 0x43); |
177 | } else { | 216 | } else { |
178 | *rate = clk_get_rate(p->clk) / 8; | 217 | *rate = clk_get_rate(p->clk) / 8; |
179 | sh_cmt_write(p, CMCSR, 0x01a4); | 218 | sh_cmt_write_cmcsr(p, 0x01a4); |
180 | } | 219 | } |
181 | 220 | ||
182 | sh_cmt_write(p, CMCOR, 0xffffffff); | 221 | sh_cmt_write_cmcor(p, 0xffffffff); |
183 | sh_cmt_write(p, CMCNT, 0); | 222 | sh_cmt_write_cmcnt(p, 0); |
184 | 223 | ||
185 | /* | 224 | /* |
186 | * According to the sh73a0 user's manual, as CMCNT can be operated | 225 | * According to the sh73a0 user's manual, as CMCNT can be operated |
@@ -194,12 +233,12 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | |||
194 | * take RCLKx2 at maximum. | 233 | * take RCLKx2 at maximum. |
195 | */ | 234 | */ |
196 | for (k = 0; k < 100; k++) { | 235 | for (k = 0; k < 100; k++) { |
197 | if (!sh_cmt_read(p, CMCNT)) | 236 | if (!sh_cmt_read_cmcnt(p)) |
198 | break; | 237 | break; |
199 | udelay(1); | 238 | udelay(1); |
200 | } | 239 | } |
201 | 240 | ||
202 | if (sh_cmt_read(p, CMCNT)) { | 241 | if (sh_cmt_read_cmcnt(p)) { |
203 | dev_err(&p->pdev->dev, "cannot clear CMCNT\n"); | 242 | dev_err(&p->pdev->dev, "cannot clear CMCNT\n"); |
204 | ret = -ETIMEDOUT; | 243 | ret = -ETIMEDOUT; |
205 | goto err1; | 244 | goto err1; |
@@ -222,7 +261,7 @@ static void sh_cmt_disable(struct sh_cmt_priv *p) | |||
222 | sh_cmt_start_stop_ch(p, 0); | 261 | sh_cmt_start_stop_ch(p, 0); |
223 | 262 | ||
224 | /* disable interrupts in CMT block */ | 263 | /* disable interrupts in CMT block */ |
225 | sh_cmt_write(p, CMCSR, 0); | 264 | sh_cmt_write_cmcsr(p, 0); |
226 | 265 | ||
227 | /* stop clock */ | 266 | /* stop clock */ |
228 | clk_disable(p->clk); | 267 | clk_disable(p->clk); |
@@ -270,7 +309,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, | |||
270 | if (new_match > p->max_match_value) | 309 | if (new_match > p->max_match_value) |
271 | new_match = p->max_match_value; | 310 | new_match = p->max_match_value; |
272 | 311 | ||
273 | sh_cmt_write(p, CMCOR, new_match); | 312 | sh_cmt_write_cmcor(p, new_match); |
274 | 313 | ||
275 | now = sh_cmt_get_counter(p, &has_wrapped); | 314 | now = sh_cmt_get_counter(p, &has_wrapped); |
276 | if (has_wrapped && (new_match > p->match_value)) { | 315 | if (has_wrapped && (new_match > p->match_value)) { |
@@ -346,7 +385,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) | |||
346 | struct sh_cmt_priv *p = dev_id; | 385 | struct sh_cmt_priv *p = dev_id; |
347 | 386 | ||
348 | /* clear flags */ | 387 | /* clear flags */ |
349 | sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits); | 388 | sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits); |
350 | 389 | ||
351 | /* update clock source counter to begin with if enabled | 390 | /* update clock source counter to begin with if enabled |
352 | * the wrap flag should be cleared by the timer specific | 391 | * the wrap flag should be cleared by the timer specific |
@@ -625,14 +664,6 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name, | |||
625 | unsigned long clockevent_rating, | 664 | unsigned long clockevent_rating, |
626 | unsigned long clocksource_rating) | 665 | unsigned long clocksource_rating) |
627 | { | 666 | { |
628 | if (p->width == (sizeof(p->max_match_value) * 8)) | ||
629 | p->max_match_value = ~0; | ||
630 | else | ||
631 | p->max_match_value = (1 << p->width) - 1; | ||
632 | |||
633 | p->match_value = p->max_match_value; | ||
634 | raw_spin_lock_init(&p->lock); | ||
635 | |||
636 | if (clockevent_rating) | 667 | if (clockevent_rating) |
637 | sh_cmt_register_clockevent(p, name, clockevent_rating); | 668 | sh_cmt_register_clockevent(p, name, clockevent_rating); |
638 | 669 | ||
@@ -657,8 +688,6 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
657 | goto err0; | 688 | goto err0; |
658 | } | 689 | } |
659 | 690 | ||
660 | platform_set_drvdata(pdev, p); | ||
661 | |||
662 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); | 691 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); |
663 | if (!res) { | 692 | if (!res) { |
664 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | 693 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); |
@@ -693,32 +722,51 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
693 | goto err1; | 722 | goto err1; |
694 | } | 723 | } |
695 | 724 | ||
725 | p->read_control = sh_cmt_read16; | ||
726 | p->write_control = sh_cmt_write16; | ||
727 | |||
696 | if (resource_size(res) == 6) { | 728 | if (resource_size(res) == 6) { |
697 | p->width = 16; | 729 | p->width = 16; |
730 | p->read_count = sh_cmt_read16; | ||
731 | p->write_count = sh_cmt_write16; | ||
698 | p->overflow_bit = 0x80; | 732 | p->overflow_bit = 0x80; |
699 | p->clear_bits = ~0x80; | 733 | p->clear_bits = ~0x80; |
700 | } else { | 734 | } else { |
701 | p->width = 32; | 735 | p->width = 32; |
736 | p->read_count = sh_cmt_read32; | ||
737 | p->write_count = sh_cmt_write32; | ||
702 | p->overflow_bit = 0x8000; | 738 | p->overflow_bit = 0x8000; |
703 | p->clear_bits = ~0xc000; | 739 | p->clear_bits = ~0xc000; |
704 | } | 740 | } |
705 | 741 | ||
742 | if (p->width == (sizeof(p->max_match_value) * 8)) | ||
743 | p->max_match_value = ~0; | ||
744 | else | ||
745 | p->max_match_value = (1 << p->width) - 1; | ||
746 | |||
747 | p->match_value = p->max_match_value; | ||
748 | raw_spin_lock_init(&p->lock); | ||
749 | |||
706 | ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), | 750 | ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), |
707 | cfg->clockevent_rating, | 751 | cfg->clockevent_rating, |
708 | cfg->clocksource_rating); | 752 | cfg->clocksource_rating); |
709 | if (ret) { | 753 | if (ret) { |
710 | dev_err(&p->pdev->dev, "registration failed\n"); | 754 | dev_err(&p->pdev->dev, "registration failed\n"); |
711 | goto err1; | 755 | goto err2; |
712 | } | 756 | } |
713 | p->cs_enabled = false; | 757 | p->cs_enabled = false; |
714 | 758 | ||
715 | ret = setup_irq(irq, &p->irqaction); | 759 | ret = setup_irq(irq, &p->irqaction); |
716 | if (ret) { | 760 | if (ret) { |
717 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); | 761 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); |
718 | goto err1; | 762 | goto err2; |
719 | } | 763 | } |
720 | 764 | ||
765 | platform_set_drvdata(pdev, p); | ||
766 | |||
721 | return 0; | 767 | return 0; |
768 | err2: | ||
769 | clk_put(p->clk); | ||
722 | 770 | ||
723 | err1: | 771 | err1: |
724 | iounmap(p->mapbase); | 772 | iounmap(p->mapbase); |
@@ -751,7 +799,6 @@ static int sh_cmt_probe(struct platform_device *pdev) | |||
751 | ret = sh_cmt_setup(p, pdev); | 799 | ret = sh_cmt_setup(p, pdev); |
752 | if (ret) { | 800 | if (ret) { |
753 | kfree(p); | 801 | kfree(p); |
754 | platform_set_drvdata(pdev, NULL); | ||
755 | pm_runtime_idle(&pdev->dev); | 802 | pm_runtime_idle(&pdev->dev); |
756 | return ret; | 803 | return ret; |
757 | } | 804 | } |
@@ -791,7 +838,7 @@ static void __exit sh_cmt_exit(void) | |||
791 | } | 838 | } |
792 | 839 | ||
793 | early_platform_init("earlytimer", &sh_cmt_device_driver); | 840 | early_platform_init("earlytimer", &sh_cmt_device_driver); |
794 | module_init(sh_cmt_init); | 841 | subsys_initcall(sh_cmt_init); |
795 | module_exit(sh_cmt_exit); | 842 | module_exit(sh_cmt_exit); |
796 | 843 | ||
797 | MODULE_AUTHOR("Magnus Damm"); | 844 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 83943e27cfac..4aac9ee0d0c0 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
@@ -386,7 +386,7 @@ static void __exit sh_mtu2_exit(void) | |||
386 | } | 386 | } |
387 | 387 | ||
388 | early_platform_init("earlytimer", &sh_mtu2_device_driver); | 388 | early_platform_init("earlytimer", &sh_mtu2_device_driver); |
389 | module_init(sh_mtu2_init); | 389 | subsys_initcall(sh_mtu2_init); |
390 | module_exit(sh_mtu2_exit); | 390 | module_exit(sh_mtu2_exit); |
391 | 391 | ||
392 | MODULE_AUTHOR("Magnus Damm"); | 392 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index b4502edce2a1..78b8dae49628 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
@@ -549,7 +549,7 @@ static void __exit sh_tmu_exit(void) | |||
549 | } | 549 | } |
550 | 550 | ||
551 | early_platform_init("earlytimer", &sh_tmu_device_driver); | 551 | early_platform_init("earlytimer", &sh_tmu_device_driver); |
552 | module_init(sh_tmu_init); | 552 | subsys_initcall(sh_tmu_init); |
553 | module_exit(sh_tmu_exit); | 553 | module_exit(sh_tmu_exit); |
554 | 554 | ||
555 | MODULE_AUTHOR("Magnus Damm"); | 555 | MODULE_AUTHOR("Magnus Damm"); |