aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-omap1
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap1')
-rw-r--r--arch/arm/mach-omap1/Makefile3
-rw-r--r--arch/arm/mach-omap1/board-osk.c138
-rw-r--r--arch/arm/mach-omap1/leds-osk.c80
-rw-r--r--arch/arm/mach-omap1/mux.c146
-rw-r--r--arch/arm/mach-omap1/time.c49
-rw-r--r--arch/arm/mach-omap1/timer32k.c209
6 files changed, 432 insertions, 193 deletions
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
index 015a66b3ca8e..c06f5254c0f3 100644
--- a/arch/arm/mach-omap1/Makefile
+++ b/arch/arm/mach-omap1/Makefile
@@ -5,7 +5,8 @@
5# Common support 5# Common support
6obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o 6obj-y := io.o id.o clock.o irq.o mux.o serial.o devices.o
7 7
8obj-$(CONFIG_OMAP_MPU_TIMER) += time.o 8obj-$(CONFIG_OMAP_MPU_TIMER) += time.o
9obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
9 10
10# Power Management 11# Power Management
11obj-$(CONFIG_PM) += pm.o sleep.o 12obj-$(CONFIG_PM) += pm.o sleep.o
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 5279e35a8aec..4f9baba7d893 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -32,6 +32,7 @@
32#include <linux/interrupt.h> 32#include <linux/interrupt.h>
33#include <linux/irq.h> 33#include <linux/irq.h>
34#include <linux/i2c.h> 34#include <linux/i2c.h>
35#include <linux/leds.h>
35 36
36#include <linux/mtd/mtd.h> 37#include <linux/mtd/mtd.h>
37#include <linux/mtd/partitions.h> 38#include <linux/mtd/partitions.h>
@@ -183,11 +184,80 @@ static struct platform_device *osk5912_devices[] __initdata = {
183 &osk5912_mcbsp1_device, 184 &osk5912_mcbsp1_device,
184}; 185};
185 186
187static struct gpio_led tps_leds[] = {
188 /* NOTE: D9 and D2 have hardware blink support.
189 * Also, D9 requires non-battery power.
190 */
191 { .gpio = OSK_TPS_GPIO_LED_D9, .name = "d9", },
192 { .gpio = OSK_TPS_GPIO_LED_D2, .name = "d2", },
193 { .gpio = OSK_TPS_GPIO_LED_D3, .name = "d3", .active_low = 1,
194 .default_trigger = "heartbeat", },
195};
196
197static struct gpio_led_platform_data tps_leds_data = {
198 .num_leds = 3,
199 .leds = tps_leds,
200};
201
202static struct platform_device osk5912_tps_leds = {
203 .name = "leds-gpio",
204 .id = 0,
205 .dev.platform_data = &tps_leds_data,
206};
207
208static int osk_tps_setup(struct i2c_client *client, void *context)
209{
210 /* Set GPIO 1 HIGH to disable VBUS power supply;
211 * OHCI driver powers it up/down as needed.
212 */
213 gpio_request(OSK_TPS_GPIO_USB_PWR_EN, "n_vbus_en");
214 gpio_direction_output(OSK_TPS_GPIO_USB_PWR_EN, 1);
215
216 /* Set GPIO 2 high so LED D3 is off by default */
217 tps65010_set_gpio_out_value(GPIO2, HIGH);
218
219 /* Set GPIO 3 low to take ethernet out of reset */
220 gpio_request(OSK_TPS_GPIO_LAN_RESET, "smc_reset");
221 gpio_direction_output(OSK_TPS_GPIO_LAN_RESET, 0);
222
223 /* GPIO4 is VDD_DSP */
224 gpio_request(OSK_TPS_GPIO_DSP_PWR_EN, "dsp_power");
225 gpio_direction_output(OSK_TPS_GPIO_DSP_PWR_EN, 1);
226 /* REVISIT if DSP support isn't configured, power it off ... */
227
228 /* Let LED1 (D9) blink; leds-gpio may override it */
229 tps65010_set_led(LED1, BLINK);
230
231 /* Set LED2 off by default */
232 tps65010_set_led(LED2, OFF);
233
234 /* Enable LOW_PWR handshake */
235 tps65010_set_low_pwr(ON);
236
237 /* Switch VLDO2 to 3.0V for AIC23 */
238 tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
239 | TPS_LDO1_ENABLE);
240
241 /* register these three LEDs */
242 osk5912_tps_leds.dev.parent = &client->dev;
243 platform_device_register(&osk5912_tps_leds);
244
245 return 0;
246}
247
248static struct tps65010_board tps_board = {
249 .base = OSK_TPS_GPIO_BASE,
250 .outmask = 0x0f,
251 .setup = osk_tps_setup,
252};
253
186static struct i2c_board_info __initdata osk_i2c_board_info[] = { 254static struct i2c_board_info __initdata osk_i2c_board_info[] = {
187 { 255 {
188 I2C_BOARD_INFO("tps65010", 0x48), 256 I2C_BOARD_INFO("tps65010", 0x48),
189 .type = "tps65010", 257 .type = "tps65010",
190 .irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)), 258 .irq = OMAP_GPIO_IRQ(OMAP_MPUIO(1)),
259 .platform_data = &tps_board,
260
191 }, 261 },
192 /* TODO when driver support is ready: 262 /* TODO when driver support is ready:
193 * - aic23 audio chip at 0x1a 263 * - aic23 audio chip at 0x1a
@@ -198,7 +268,7 @@ static struct i2c_board_info __initdata osk_i2c_board_info[] = {
198 268
199static void __init osk_init_smc91x(void) 269static void __init osk_init_smc91x(void)
200{ 270{
201 if ((omap_request_gpio(0)) < 0) { 271 if ((gpio_request(0, "smc_irq")) < 0) {
202 printk("Error requesting gpio 0 for smc91x irq\n"); 272 printk("Error requesting gpio 0 for smc91x irq\n");
203 return; 273 return;
204 } 274 }
@@ -210,7 +280,7 @@ static void __init osk_init_smc91x(void)
210static void __init osk_init_cf(void) 280static void __init osk_init_cf(void)
211{ 281{
212 omap_cfg_reg(M7_1610_GPIO62); 282 omap_cfg_reg(M7_1610_GPIO62);
213 if ((omap_request_gpio(62)) < 0) { 283 if ((gpio_request(62, "cf_irq")) < 0) {
214 printk("Error requesting gpio 62 for CF irq\n"); 284 printk("Error requesting gpio 62 for CF irq\n");
215 return; 285 return;
216 } 286 }
@@ -334,7 +404,7 @@ static struct platform_device *mistral_devices[] __initdata = {
334 404
335static int mistral_get_pendown_state(void) 405static int mistral_get_pendown_state(void)
336{ 406{
337 return !omap_get_gpio_datain(4); 407 return !gpio_get_value(4);
338} 408}
339 409
340static const struct ads7846_platform_data mistral_ts_info = { 410static const struct ads7846_platform_data mistral_ts_info = {
@@ -396,25 +466,31 @@ static void __init osk_mistral_init(void)
396 omap_cfg_reg(W14_1610_CCP_DATAP); 466 omap_cfg_reg(W14_1610_CCP_DATAP);
397 467
398 /* CAM_PWDN */ 468 /* CAM_PWDN */
399 if (omap_request_gpio(11) == 0) { 469 if (gpio_request(11, "cam_pwdn") == 0) {
400 omap_cfg_reg(N20_1610_GPIO11); 470 omap_cfg_reg(N20_1610_GPIO11);
401 omap_set_gpio_direction(11, 0 /* out */); 471 gpio_direction_output(11, 0);
402 omap_set_gpio_dataout(11, 0 /* off */);
403 } else 472 } else
404 pr_debug("OSK+Mistral: CAM_PWDN is awol\n"); 473 pr_debug("OSK+Mistral: CAM_PWDN is awol\n");
405 474
406 475
407 /* omap_cfg_reg(P19_1610_GPIO6); */ /* BUSY */ 476 /* omap_cfg_reg(P19_1610_GPIO6); */ /* BUSY */
477 gpio_request(6, "ts_busy");
478 gpio_direction_input(6);
479
408 omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */ 480 omap_cfg_reg(P20_1610_GPIO4); /* PENIRQ */
481 gpio_request(4, "ts_int");
482 gpio_direction_input(4);
409 set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING); 483 set_irq_type(OMAP_GPIO_IRQ(4), IRQT_FALLING);
484
410 spi_register_board_info(mistral_boardinfo, 485 spi_register_board_info(mistral_boardinfo,
411 ARRAY_SIZE(mistral_boardinfo)); 486 ARRAY_SIZE(mistral_boardinfo));
412 487
413 /* the sideways button (SW1) is for use as a "wakeup" button */ 488 /* the sideways button (SW1) is for use as a "wakeup" button */
414 omap_cfg_reg(N15_1610_MPUIO2); 489 omap_cfg_reg(N15_1610_MPUIO2);
415 if (omap_request_gpio(OMAP_MPUIO(2)) == 0) { 490 if (gpio_request(OMAP_MPUIO(2), "wakeup") == 0) {
416 int ret = 0; 491 int ret = 0;
417 omap_set_gpio_direction(OMAP_MPUIO(2), 1); 492
493 gpio_direction_input(OMAP_MPUIO(2));
418 set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING); 494 set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING);
419#ifdef CONFIG_PM 495#ifdef CONFIG_PM
420 /* share the IRQ in case someone wants to use the 496 /* share the IRQ in case someone wants to use the
@@ -425,7 +501,7 @@ static void __init osk_mistral_init(void)
425 IRQF_SHARED, "mistral_wakeup", 501 IRQF_SHARED, "mistral_wakeup",
426 &osk_mistral_wake_interrupt); 502 &osk_mistral_wake_interrupt);
427 if (ret != 0) { 503 if (ret != 0) {
428 omap_free_gpio(OMAP_MPUIO(2)); 504 gpio_free(OMAP_MPUIO(2));
429 printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n", 505 printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n",
430 ret); 506 ret);
431 } else 507 } else
@@ -438,10 +514,8 @@ static void __init osk_mistral_init(void)
438 * board, like the touchscreen, EEPROM, and wakeup (!) switch. 514 * board, like the touchscreen, EEPROM, and wakeup (!) switch.
439 */ 515 */
440 omap_cfg_reg(PWL); 516 omap_cfg_reg(PWL);
441 if (omap_request_gpio(2) == 0) { 517 if (gpio_request(2, "lcd_pwr") == 0)
442 omap_set_gpio_direction(2, 0 /* out */); 518 gpio_direction_output(2, 1);
443 omap_set_gpio_dataout(2, 1 /* on */);
444 }
445 519
446 platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices)); 520 platform_add_devices(mistral_devices, ARRAY_SIZE(mistral_devices));
447} 521}
@@ -484,44 +558,6 @@ static void __init osk_map_io(void)
484 omap1_map_common_io(); 558 omap1_map_common_io();
485} 559}
486 560
487#ifdef CONFIG_TPS65010
488static int __init osk_tps_init(void)
489{
490 if (!machine_is_omap_osk())
491 return 0;
492
493 /* Let LED1 (D9) blink */
494 tps65010_set_led(LED1, BLINK);
495
496 /* Disable LED 2 (D2) */
497 tps65010_set_led(LED2, OFF);
498
499 /* Set GPIO 1 HIGH to disable VBUS power supply;
500 * OHCI driver powers it up/down as needed.
501 */
502 tps65010_set_gpio_out_value(GPIO1, HIGH);
503
504 /* Set GPIO 2 low to turn on LED D3 */
505 tps65010_set_gpio_out_value(GPIO2, HIGH);
506
507 /* Set GPIO 3 low to take ethernet out of reset */
508 tps65010_set_gpio_out_value(GPIO3, LOW);
509
510 /* gpio4 for VDD_DSP */
511 /* FIXME send power to DSP iff it's configured */
512
513 /* Enable LOW_PWR */
514 tps65010_set_low_pwr(ON);
515
516 /* Switch VLDO2 to 3.0V for AIC23 */
517 tps65010_config_vregs1(TPS_LDO2_ENABLE | TPS_VLDO2_3_0V
518 | TPS_LDO1_ENABLE);
519
520 return 0;
521}
522fs_initcall(osk_tps_init);
523#endif
524
525MACHINE_START(OMAP_OSK, "TI-OSK") 561MACHINE_START(OMAP_OSK, "TI-OSK")
526 /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */ 562 /* Maintainer: Dirk Behme <dirk.behme@de.bosch.com> */
527 .phys_io = 0xfff00000, 563 .phys_io = 0xfff00000,
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c
index 026685ed461a..754383dde807 100644
--- a/arch/arm/mach-omap1/leds-osk.c
+++ b/arch/arm/mach-omap1/leds-osk.c
@@ -1,11 +1,9 @@
1/* 1/*
2 * linux/arch/arm/mach-omap1/leds-osk.c 2 * linux/arch/arm/mach-omap1/leds-osk.c
3 * 3 *
4 * LED driver for OSK, and optionally Mistral QVGA, boards 4 * LED driver for OSK with optional Mistral QVGA board
5 */ 5 */
6#include <linux/init.h> 6#include <linux/init.h>
7#include <linux/workqueue.h>
8#include <linux/i2c/tps65010.h>
9 7
10#include <asm/hardware.h> 8#include <asm/hardware.h>
11#include <asm/leds.h> 9#include <asm/leds.h>
@@ -20,49 +18,11 @@
20#define LED_STATE_CLAIMED (1 << 1) 18#define LED_STATE_CLAIMED (1 << 1)
21static u8 led_state; 19static u8 led_state;
22 20
23#define GREEN_LED (1 << 0) /* TPS65010 LED1 */
24#define AMBER_LED (1 << 1) /* TPS65010 LED2 */
25#define RED_LED (1 << 2) /* TPS65010 GPIO2 */
26#define TIMER_LED (1 << 3) /* Mistral board */ 21#define TIMER_LED (1 << 3) /* Mistral board */
27#define IDLE_LED (1 << 4) /* Mistral board */ 22#define IDLE_LED (1 << 4) /* Mistral board */
28static u8 hw_led_state; 23static u8 hw_led_state;
29 24
30 25
31/* TPS65010 leds are changed using i2c -- from a task context.
32 * Using one of these for the "idle" LED would be impractical...
33 */
34#define TPS_LEDS (GREEN_LED | RED_LED | AMBER_LED)
35
36static u8 tps_leds_change;
37
38static void tps_work(struct work_struct *unused)
39{
40 for (;;) {
41 u8 leds;
42
43 local_irq_disable();
44 leds = tps_leds_change;
45 tps_leds_change = 0;
46 local_irq_enable();
47
48 if (!leds)
49 break;
50
51 /* careful: the set_led() value is on/off/blink */
52 if (leds & GREEN_LED)
53 tps65010_set_led(LED1, !!(hw_led_state & GREEN_LED));
54 if (leds & AMBER_LED)
55 tps65010_set_led(LED2, !!(hw_led_state & AMBER_LED));
56
57 /* the gpio led doesn't have that issue */
58 if (leds & RED_LED)
59 tps65010_set_gpio_out_value(GPIO2,
60 !(hw_led_state & RED_LED));
61 }
62}
63
64static DECLARE_WORK(work, tps_work);
65
66#ifdef CONFIG_OMAP_OSK_MISTRAL 26#ifdef CONFIG_OMAP_OSK_MISTRAL
67 27
68/* For now, all system indicators require the Mistral board, since that 28/* For now, all system indicators require the Mistral board, since that
@@ -112,7 +72,6 @@ void osk_leds_event(led_event_t evt)
112 case led_stop: 72 case led_stop:
113 led_state &= ~LED_STATE_ENABLED; 73 led_state &= ~LED_STATE_ENABLED;
114 hw_led_state = 0; 74 hw_led_state = 0;
115 /* NOTE: work may still be pending!! */
116 break; 75 break;
117 76
118 case led_claim: 77 case led_claim:
@@ -145,48 +104,11 @@ void osk_leds_event(led_event_t evt)
145 104
146#endif /* CONFIG_OMAP_OSK_MISTRAL */ 105#endif /* CONFIG_OMAP_OSK_MISTRAL */
147 106
148 /* "green" == tps LED1 (leftmost, normally power-good)
149 * works only with DC adapter, not on battery power!
150 */
151 case led_green_on:
152 if (led_state & LED_STATE_CLAIMED)
153 hw_led_state |= GREEN_LED;
154 break;
155 case led_green_off:
156 if (led_state & LED_STATE_CLAIMED)
157 hw_led_state &= ~GREEN_LED;
158 break;
159
160 /* "amber" == tps LED2 (middle) */
161 case led_amber_on:
162 if (led_state & LED_STATE_CLAIMED)
163 hw_led_state |= AMBER_LED;
164 break;
165 case led_amber_off:
166 if (led_state & LED_STATE_CLAIMED)
167 hw_led_state &= ~AMBER_LED;
168 break;
169
170 /* "red" == LED on tps gpio3 (rightmost) */
171 case led_red_on:
172 if (led_state & LED_STATE_CLAIMED)
173 hw_led_state |= RED_LED;
174 break;
175 case led_red_off:
176 if (led_state & LED_STATE_CLAIMED)
177 hw_led_state &= ~RED_LED;
178 break;
179
180 default: 107 default:
181 break; 108 break;
182 } 109 }
183 110
184 leds ^= hw_led_state; 111 leds ^= hw_led_state;
185 leds &= TPS_LEDS;
186 if (leds && (led_state & LED_STATE_CLAIMED)) {
187 tps_leds_change |= leds;
188 schedule_work(&work);
189 }
190 112
191done: 113done:
192 local_irq_restore(flags); 114 local_irq_restore(flags);
diff --git a/arch/arm/mach-omap1/mux.c b/arch/arm/mach-omap1/mux.c
index 52c70e5fcf65..e207bf7cb853 100644
--- a/arch/arm/mach-omap1/mux.c
+++ b/arch/arm/mach-omap1/mux.c
@@ -3,9 +3,9 @@
3 * 3 *
4 * OMAP1 pin multiplexing configurations 4 * OMAP1 pin multiplexing configurations
5 * 5 *
6 * Copyright (C) 2003 - 2005 Nokia Corporation 6 * Copyright (C) 2003 - 2008 Nokia Corporation
7 * 7 *
8 * Written by Tony Lindgren <tony.lindgren@nokia.com> 8 * Written by Tony Lindgren
9 * 9 *
10 * This program is free software; you can redistribute it and/or modify 10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 11 * it under the terms of the GNU General Public License as published by
@@ -32,8 +32,10 @@
32 32
33#ifdef CONFIG_OMAP_MUX 33#ifdef CONFIG_OMAP_MUX
34 34
35static struct omap_mux_cfg arch_mux_cfg;
36
35#ifdef CONFIG_ARCH_OMAP730 37#ifdef CONFIG_ARCH_OMAP730
36struct pin_config __initdata_or_module omap730_pins[] = { 38static struct pin_config __initdata_or_module omap730_pins[] = {
37MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0) 39MUX_CFG_730("E2_730_KBR0", 12, 21, 0, 20, 1, 0)
38MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0) 40MUX_CFG_730("J7_730_KBR1", 12, 25, 0, 24, 1, 0)
39MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0) 41MUX_CFG_730("E1_730_KBR2", 12, 29, 0, 28, 1, 0)
@@ -49,10 +51,14 @@ MUX_CFG_730("AA17_730_USB_DM", 2, 21, 0, 20, 0, 0)
49MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0) 51MUX_CFG_730("W16_730_USB_PU_EN", 2, 25, 0, 24, 0, 0)
50MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0) 52MUX_CFG_730("W17_730_USB_VBUSI", 2, 29, 0, 28, 0, 0)
51}; 53};
52#endif 54#define OMAP730_PINS_SZ ARRAY_SIZE(omap730_pins)
55#else
56#define omap730_pins NULL
57#define OMAP730_PINS_SZ 0
58#endif /* CONFIG_ARCH_OMAP730 */
53 59
54#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) 60#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX)
55struct pin_config __initdata_or_module omap1xxx_pins[] = { 61static struct pin_config __initdata_or_module omap1xxx_pins[] = {
56/* 62/*
57 * description mux mode mux pull pull pull pu_pd pu dbg 63 * description mux mode mux pull pull pull pu_pd pu dbg
58 * reg offset mode reg bit ena reg 64 * reg offset mode reg bit ena reg
@@ -306,22 +312,136 @@ MUX_CFG("Y12_1610_CCP_CLKP", 8, 18, 6, 1, 24, 1, 1, 0, 0)
306MUX_CFG("W13_1610_CCP_CLKM", 9, 0, 6, 1, 28, 1, 1, 0, 0) 312MUX_CFG("W13_1610_CCP_CLKM", 9, 0, 6, 1, 28, 1, 1, 0, 0)
307MUX_CFG("W14_1610_CCP_DATAP", 9, 24, 6, 2, 4, 1, 2, 0, 0) 313MUX_CFG("W14_1610_CCP_DATAP", 9, 24, 6, 2, 4, 1, 2, 0, 0)
308MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0) 314MUX_CFG("Y14_1610_CCP_DATAM", 9, 21, 6, 2, 3, 1, 2, 0, 0)
309
310}; 315};
316#define OMAP1XXX_PINS_SZ ARRAY_SIZE(omap1xxx_pins)
317#else
318#define omap1xxx_pins NULL
319#define OMAP1XXX_PINS_SZ 0
311#endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */ 320#endif /* CONFIG_ARCH_OMAP15XX || CONFIG_ARCH_OMAP16XX */
312 321
313int __init omap1_mux_init(void) 322int __init_or_module omap1_cfg_reg(const struct pin_config *cfg)
314{ 323{
315 324 static DEFINE_SPINLOCK(mux_spin_lock);
316#ifdef CONFIG_ARCH_OMAP730 325 unsigned long flags;
317 omap_mux_register(omap730_pins, ARRAY_SIZE(omap730_pins)); 326 unsigned int reg_orig = 0, reg = 0, pu_pd_orig = 0, pu_pd = 0,
327 pull_orig = 0, pull = 0;
328 unsigned int mask, warn = 0;
329
330 /* Check the mux register in question */
331 if (cfg->mux_reg) {
332 unsigned tmp1, tmp2;
333
334 spin_lock_irqsave(&mux_spin_lock, flags);
335 reg_orig = omap_readl(cfg->mux_reg);
336
337 /* The mux registers always seem to be 3 bits long */
338 mask = (0x7 << cfg->mask_offset);
339 tmp1 = reg_orig & mask;
340 reg = reg_orig & ~mask;
341
342 tmp2 = (cfg->mask << cfg->mask_offset);
343 reg |= tmp2;
344
345 if (tmp1 != tmp2)
346 warn = 1;
347
348 omap_writel(reg, cfg->mux_reg);
349 spin_unlock_irqrestore(&mux_spin_lock, flags);
350 }
351
352 /* Check for pull up or pull down selection on 1610 */
353 if (!cpu_is_omap15xx()) {
354 if (cfg->pu_pd_reg && cfg->pull_val) {
355 spin_lock_irqsave(&mux_spin_lock, flags);
356 pu_pd_orig = omap_readl(cfg->pu_pd_reg);
357 mask = 1 << cfg->pull_bit;
358
359 if (cfg->pu_pd_val) {
360 if (!(pu_pd_orig & mask))
361 warn = 1;
362 /* Use pull up */
363 pu_pd = pu_pd_orig | mask;
364 } else {
365 if (pu_pd_orig & mask)
366 warn = 1;
367 /* Use pull down */
368 pu_pd = pu_pd_orig & ~mask;
369 }
370 omap_writel(pu_pd, cfg->pu_pd_reg);
371 spin_unlock_irqrestore(&mux_spin_lock, flags);
372 }
373 }
374
375 /* Check for an associated pull down register */
376 if (cfg->pull_reg) {
377 spin_lock_irqsave(&mux_spin_lock, flags);
378 pull_orig = omap_readl(cfg->pull_reg);
379 mask = 1 << cfg->pull_bit;
380
381 if (cfg->pull_val) {
382 if (pull_orig & mask)
383 warn = 1;
384 /* Low bit = pull enabled */
385 pull = pull_orig & ~mask;
386 } else {
387 if (!(pull_orig & mask))
388 warn = 1;
389 /* High bit = pull disabled */
390 pull = pull_orig | mask;
391 }
392
393 omap_writel(pull, cfg->pull_reg);
394 spin_unlock_irqrestore(&mux_spin_lock, flags);
395 }
396
397 if (warn) {
398#ifdef CONFIG_OMAP_MUX_WARNINGS
399 printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
318#endif 400#endif
319 401 }
320#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) 402
321 omap_mux_register(omap1xxx_pins, ARRAY_SIZE(omap1xxx_pins)); 403#ifdef CONFIG_OMAP_MUX_DEBUG
404 if (cfg->debug || warn) {
405 printk("MUX: Setting register %s\n", cfg->name);
406 printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
407 cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
408
409 if (!cpu_is_omap15xx()) {
410 if (cfg->pu_pd_reg && cfg->pull_val) {
411 printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
412 cfg->pu_pd_name, cfg->pu_pd_reg,
413 pu_pd_orig, pu_pd);
414 }
415 }
416
417 if (cfg->pull_reg)
418 printk(" %s (0x%08x) = 0x%08x -> 0x%08x\n",
419 cfg->pull_name, cfg->pull_reg, pull_orig, pull);
420 }
322#endif 421#endif
323 422
423#ifdef CONFIG_OMAP_MUX_ERRORS
424 return warn ? -ETXTBSY : 0;
425#else
324 return 0; 426 return 0;
427#endif
428}
429
430int __init omap1_mux_init(void)
431{
432 if (cpu_is_omap730()) {
433 arch_mux_cfg.pins = omap730_pins;
434 arch_mux_cfg.size = OMAP730_PINS_SZ;
435 arch_mux_cfg.cfg_reg = omap1_cfg_reg;
436 }
437
438 if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
439 arch_mux_cfg.pins = omap1xxx_pins;
440 arch_mux_cfg.size = OMAP1XXX_PINS_SZ;
441 arch_mux_cfg.cfg_reg = omap1_cfg_reg;
442 }
443
444 return omap_mux_register(&arch_mux_cfg);
325} 445}
326 446
327#endif 447#endif
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index a4f8b2055437..5d2b270935a2 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -56,37 +56,6 @@
56#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE 56#define OMAP_MPU_TIMER_BASE OMAP_MPU_TIMER1_BASE
57#define OMAP_MPU_TIMER_OFFSET 0x100 57#define OMAP_MPU_TIMER_OFFSET 0x100
58 58
59/* cycles to nsec conversions taken from arch/i386/kernel/timers/timer_tsc.c,
60 * converted to use kHz by Kevin Hilman */
61/* convert from cycles(64bits) => nanoseconds (64bits)
62 * basic equation:
63 * ns = cycles / (freq / ns_per_sec)
64 * ns = cycles * (ns_per_sec / freq)
65 * ns = cycles * (10^9 / (cpu_khz * 10^3))
66 * ns = cycles * (10^6 / cpu_khz)
67 *
68 * Then we use scaling math (suggested by george at mvista.com) to get:
69 * ns = cycles * (10^6 * SC / cpu_khz / SC
70 * ns = cycles * cyc2ns_scale / SC
71 *
72 * And since SC is a constant power of two, we can convert the div
73 * into a shift.
74 * -johnstul at us.ibm.com "math is hard, lets go shopping!"
75 */
76static unsigned long cyc2ns_scale;
77#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
78
79static inline void set_cyc2ns_scale(unsigned long cpu_khz)
80{
81 cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR)/cpu_khz;
82}
83
84static inline unsigned long long cycles_2_ns(unsigned long long cyc)
85{
86 return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
87}
88
89
90typedef struct { 59typedef struct {
91 u32 cntl; /* CNTL_TIMER, R/W */ 60 u32 cntl; /* CNTL_TIMER, R/W */
92 u32 load_tim; /* LOAD_TIM, W */ 61 u32 load_tim; /* LOAD_TIM, W */
@@ -194,8 +163,6 @@ static struct irqaction omap_mpu_timer1_irq = {
194 163
195static __init void omap_init_mpu_timer(unsigned long rate) 164static __init void omap_init_mpu_timer(unsigned long rate)
196{ 165{
197 set_cyc2ns_scale(rate / 1000);
198
199 setup_irq(INT_TIMER1, &omap_mpu_timer1_irq); 166 setup_irq(INT_TIMER1, &omap_mpu_timer1_irq);
200 omap_mpu_timer_start(0, (rate / HZ) - 1, 1); 167 omap_mpu_timer_start(0, (rate / HZ) - 1, 1);
201 168
@@ -260,22 +227,6 @@ static void __init omap_init_clocksource(unsigned long rate)
260 printk(err, clocksource_mpu.name); 227 printk(err, clocksource_mpu.name);
261} 228}
262 229
263
264/*
265 * Scheduler clock - returns current time in nanosec units.
266 */
267unsigned long long sched_clock(void)
268{
269 unsigned long ticks = 0 - omap_mpu_timer_read(1);
270 unsigned long long ticks64;
271
272 ticks64 = omap_mpu_timer2_overflows;
273 ticks64 <<= 32;
274 ticks64 |= ticks;
275
276 return cycles_2_ns(ticks64);
277}
278
279/* 230/*
280 * --------------------------------------------------------------------------- 231 * ---------------------------------------------------------------------------
281 * Timer initialization 232 * Timer initialization
diff --git a/arch/arm/mach-omap1/timer32k.c b/arch/arm/mach-omap1/timer32k.c
new file mode 100644
index 000000000000..fbbdb806c95a
--- /dev/null
+++ b/arch/arm/mach-omap1/timer32k.c
@@ -0,0 +1,209 @@
1/*
2 * linux/arch/arm/mach-omap1/timer32k.c
3 *
4 * OMAP 32K Timer
5 *
6 * Copyright (C) 2004 - 2005 Nokia Corporation
7 * Partial timer rewrite and additional dynamic tick timer support by
8 * Tony Lindgen <tony@atomide.com> and
9 * Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com>
10 * OMAP Dual-mode timer framework support by Timo Teras
11 *
12 * MPU timer code based on the older MPU timer code for OMAP
13 * Copyright (C) 2000 RidgeRun, Inc.
14 * Author: Greg Lonnon <glonnon@ridgerun.com>
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the License, or (at your
19 * option) any later version.
20 *
21 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
24 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * You should have received a copy of the GNU General Public License along
33 * with this program; if not, write to the Free Software Foundation, Inc.,
34 * 675 Mass Ave, Cambridge, MA 02139, USA.
35 */
36
37#include <linux/kernel.h>
38#include <linux/init.h>
39#include <linux/delay.h>
40#include <linux/interrupt.h>
41#include <linux/sched.h>
42#include <linux/spinlock.h>
43#include <linux/err.h>
44#include <linux/clk.h>
45#include <linux/clocksource.h>
46#include <linux/clockchips.h>
47
48#include <asm/system.h>
49#include <asm/hardware.h>
50#include <asm/io.h>
51#include <asm/leds.h>
52#include <asm/irq.h>
53#include <asm/mach/irq.h>
54#include <asm/mach/time.h>
55#include <asm/arch/dmtimer.h>
56
57struct sys_timer omap_timer;
58
59/*
60 * ---------------------------------------------------------------------------
61 * 32KHz OS timer
62 *
63 * This currently works only on 16xx, as 1510 does not have the continuous
64 * 32KHz synchronous timer. The 32KHz synchronous timer is used to keep track
65 * of time in addition to the 32KHz OS timer. Using only the 32KHz OS timer
66 * on 1510 would be possible, but the timer would not be as accurate as
67 * with the 32KHz synchronized timer.
68 * ---------------------------------------------------------------------------
69 */
70
71#if defined(CONFIG_ARCH_OMAP16XX)
72#define TIMER_32K_SYNCHRONIZED 0xfffbc410
73#else
74#error OMAP 32KHz timer does not currently work on 15XX!
75#endif
76
77/* 16xx specific defines */
78#define OMAP1_32K_TIMER_BASE 0xfffb9000
79#define OMAP1_32K_TIMER_CR 0x08
80#define OMAP1_32K_TIMER_TVR 0x00
81#define OMAP1_32K_TIMER_TCR 0x04
82
83#define OMAP_32K_TICKS_PER_SEC (32768)
84
85/*
86 * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1
87 * so with HZ = 128, TVR = 255.
88 */
89#define OMAP_32K_TIMER_TICK_PERIOD ((OMAP_32K_TICKS_PER_SEC / HZ) - 1)
90
91#define JIFFIES_TO_HW_TICKS(nr_jiffies, clock_rate) \
92 (((nr_jiffies) * (clock_rate)) / HZ)
93
94static inline void omap_32k_timer_write(int val, int reg)
95{
96 omap_writew(val, OMAP1_32K_TIMER_BASE + reg);
97}
98
99static inline unsigned long omap_32k_timer_read(int reg)
100{
101 return omap_readl(OMAP1_32K_TIMER_BASE + reg) & 0xffffff;
102}
103
104static inline void omap_32k_timer_start(unsigned long load_val)
105{
106 if (!load_val)
107 load_val = 1;
108 omap_32k_timer_write(load_val, OMAP1_32K_TIMER_TVR);
109 omap_32k_timer_write(0x0f, OMAP1_32K_TIMER_CR);
110}
111
112static inline void omap_32k_timer_stop(void)
113{
114 omap_32k_timer_write(0x0, OMAP1_32K_TIMER_CR);
115}
116
117#define omap_32k_timer_ack_irq()
118
119static int omap_32k_timer_set_next_event(unsigned long delta,
120 struct clock_event_device *dev)
121{
122 omap_32k_timer_start(delta);
123
124 return 0;
125}
126
127static void omap_32k_timer_set_mode(enum clock_event_mode mode,
128 struct clock_event_device *evt)
129{
130 omap_32k_timer_stop();
131
132 switch (mode) {
133 case CLOCK_EVT_MODE_PERIODIC:
134 omap_32k_timer_start(OMAP_32K_TIMER_TICK_PERIOD);
135 break;
136 case CLOCK_EVT_MODE_ONESHOT:
137 case CLOCK_EVT_MODE_UNUSED:
138 case CLOCK_EVT_MODE_SHUTDOWN:
139 break;
140 case CLOCK_EVT_MODE_RESUME:
141 break;
142 }
143}
144
145static struct clock_event_device clockevent_32k_timer = {
146 .name = "32k-timer",
147 .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
148 .shift = 32,
149 .set_next_event = omap_32k_timer_set_next_event,
150 .set_mode = omap_32k_timer_set_mode,
151};
152
153/*
154 * The 32KHz synchronized timer is an additional timer on 16xx.
155 * It is always running.
156 */
157static inline unsigned long omap_32k_sync_timer_read(void)
158{
159 return omap_readl(TIMER_32K_SYNCHRONIZED);
160}
161
162static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id)
163{
164 struct clock_event_device *evt = &clockevent_32k_timer;
165 omap_32k_timer_ack_irq();
166
167 evt->event_handler(evt);
168
169 return IRQ_HANDLED;
170}
171
172static struct irqaction omap_32k_timer_irq = {
173 .name = "32KHz timer",
174 .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
175 .handler = omap_32k_timer_interrupt,
176};
177
178static __init void omap_init_32k_timer(void)
179{
180 setup_irq(INT_OS_TIMER, &omap_32k_timer_irq);
181
182 clockevent_32k_timer.mult = div_sc(OMAP_32K_TICKS_PER_SEC,
183 NSEC_PER_SEC,
184 clockevent_32k_timer.shift);
185 clockevent_32k_timer.max_delta_ns =
186 clockevent_delta2ns(0xfffffffe, &clockevent_32k_timer);
187 clockevent_32k_timer.min_delta_ns =
188 clockevent_delta2ns(1, &clockevent_32k_timer);
189
190 clockevent_32k_timer.cpumask = cpumask_of_cpu(0);
191 clockevents_register_device(&clockevent_32k_timer);
192}
193
194/*
195 * ---------------------------------------------------------------------------
196 * Timer initialization
197 * ---------------------------------------------------------------------------
198 */
199static void __init omap_timer_init(void)
200{
201#ifdef CONFIG_OMAP_DM_TIMER
202 omap_dm_timer_init();
203#endif
204 omap_init_32k_timer();
205}
206
207struct sys_timer omap_timer = {
208 .init = omap_timer_init,
209};