diff options
Diffstat (limited to 'arch/arm/mach-s3c2410')
| -rw-r--r-- | arch/arm/mach-s3c2410/Kconfig | 7 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/Makefile | 1 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/clock.c | 178 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/clock.h | 8 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/mach-osiris.c | 294 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/s3c2440-clock.c | 89 | ||||
| -rw-r--r-- | arch/arm/mach-s3c2410/time.c | 8 |
7 files changed, 562 insertions, 23 deletions
diff --git a/arch/arm/mach-s3c2410/Kconfig b/arch/arm/mach-s3c2410/Kconfig index 0b9d7ca49ec1..ed07c4149d82 100644 --- a/arch/arm/mach-s3c2410/Kconfig +++ b/arch/arm/mach-s3c2410/Kconfig | |||
| @@ -9,6 +9,13 @@ config MACH_ANUBIS | |||
| 9 | Say Y gere if you are using the Simtec Electronics ANUBIS | 9 | Say Y gere if you are using the Simtec Electronics ANUBIS |
| 10 | development system | 10 | development system |
| 11 | 11 | ||
| 12 | config MACH_OSIRIS | ||
| 13 | bool "Simtec IM2440D20 (OSIRIS) module" | ||
| 14 | select CPU_S3C2440 | ||
| 15 | help | ||
| 16 | Say Y here if you are using the Simtec IM2440D20 module, also | ||
| 17 | known as the Osiris. | ||
| 18 | |||
| 12 | config ARCH_BAST | 19 | config ARCH_BAST |
| 13 | bool "Simtec Electronics BAST (EB2410ITX)" | 20 | bool "Simtec Electronics BAST (EB2410ITX)" |
| 14 | select CPU_S3C2410 | 21 | select CPU_S3C2410 |
diff --git a/arch/arm/mach-s3c2410/Makefile b/arch/arm/mach-s3c2410/Makefile index 1217bf00309c..1b3b476e5637 100644 --- a/arch/arm/mach-s3c2410/Makefile +++ b/arch/arm/mach-s3c2410/Makefile | |||
| @@ -38,6 +38,7 @@ obj-$(CONFIG_BAST_PC104_IRQ) += bast-irq.o | |||
| 38 | # machine specific support | 38 | # machine specific support |
| 39 | 39 | ||
| 40 | obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o | 40 | obj-$(CONFIG_MACH_ANUBIS) += mach-anubis.o |
| 41 | obj-$(CONFIG_MACH_OSIRIS) += mach-osiris.o | ||
| 41 | obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o | 42 | obj-$(CONFIG_ARCH_BAST) += mach-bast.o usb-simtec.o |
| 42 | obj-$(CONFIG_ARCH_H1940) += mach-h1940.o | 43 | obj-$(CONFIG_ARCH_H1940) += mach-h1940.o |
| 43 | obj-$(CONFIG_MACH_N30) += mach-n30.o | 44 | obj-$(CONFIG_MACH_N30) += mach-n30.o |
diff --git a/arch/arm/mach-s3c2410/clock.c b/arch/arm/mach-s3c2410/clock.c index 08489efdaf06..fec02c92f95f 100644 --- a/arch/arm/mach-s3c2410/clock.c +++ b/arch/arm/mach-s3c2410/clock.c | |||
| @@ -38,12 +38,14 @@ | |||
| 38 | #include <linux/ioport.h> | 38 | #include <linux/ioport.h> |
| 39 | #include <linux/clk.h> | 39 | #include <linux/clk.h> |
| 40 | #include <linux/mutex.h> | 40 | #include <linux/mutex.h> |
| 41 | #include <linux/delay.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/hardware.h> | 43 | #include <asm/hardware.h> |
| 43 | #include <asm/irq.h> | 44 | #include <asm/irq.h> |
| 44 | #include <asm/io.h> | 45 | #include <asm/io.h> |
| 45 | 46 | ||
| 46 | #include <asm/arch/regs-clock.h> | 47 | #include <asm/arch/regs-clock.h> |
| 48 | #include <asm/arch/regs-gpio.h> | ||
| 47 | 49 | ||
| 48 | #include "clock.h" | 50 | #include "clock.h" |
| 49 | #include "cpu.h" | 51 | #include "cpu.h" |
| @@ -51,7 +53,8 @@ | |||
| 51 | /* clock information */ | 53 | /* clock information */ |
| 52 | 54 | ||
| 53 | static LIST_HEAD(clocks); | 55 | static LIST_HEAD(clocks); |
| 54 | static DEFINE_MUTEX(clocks_mutex); | 56 | |
| 57 | DEFINE_MUTEX(clocks_mutex); | ||
| 55 | 58 | ||
| 56 | /* old functions */ | 59 | /* old functions */ |
| 57 | 60 | ||
| @@ -178,12 +181,24 @@ unsigned long clk_get_rate(struct clk *clk) | |||
| 178 | 181 | ||
| 179 | long clk_round_rate(struct clk *clk, unsigned long rate) | 182 | long clk_round_rate(struct clk *clk, unsigned long rate) |
| 180 | { | 183 | { |
| 184 | if (!IS_ERR(clk) && clk->round_rate) | ||
| 185 | return (clk->round_rate)(clk, rate); | ||
| 186 | |||
| 181 | return rate; | 187 | return rate; |
| 182 | } | 188 | } |
| 183 | 189 | ||
| 184 | int clk_set_rate(struct clk *clk, unsigned long rate) | 190 | int clk_set_rate(struct clk *clk, unsigned long rate) |
| 185 | { | 191 | { |
| 186 | return -EINVAL; | 192 | int ret; |
| 193 | |||
| 194 | if (IS_ERR(clk)) | ||
| 195 | return -EINVAL; | ||
| 196 | |||
| 197 | mutex_lock(&clocks_mutex); | ||
| 198 | ret = (clk->set_rate)(clk, rate); | ||
| 199 | mutex_unlock(&clocks_mutex); | ||
| 200 | |||
| 201 | return ret; | ||
| 187 | } | 202 | } |
| 188 | 203 | ||
| 189 | struct clk *clk_get_parent(struct clk *clk) | 204 | struct clk *clk_get_parent(struct clk *clk) |
| @@ -191,6 +206,23 @@ struct clk *clk_get_parent(struct clk *clk) | |||
| 191 | return clk->parent; | 206 | return clk->parent; |
| 192 | } | 207 | } |
| 193 | 208 | ||
| 209 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
| 210 | { | ||
| 211 | int ret = 0; | ||
| 212 | |||
| 213 | if (IS_ERR(clk)) | ||
| 214 | return -EINVAL; | ||
| 215 | |||
| 216 | mutex_lock(&clocks_mutex); | ||
| 217 | |||
| 218 | if (clk->set_parent) | ||
| 219 | ret = (clk->set_parent)(clk, parent); | ||
| 220 | |||
| 221 | mutex_unlock(&clocks_mutex); | ||
| 222 | |||
| 223 | return ret; | ||
| 224 | } | ||
| 225 | |||
| 194 | EXPORT_SYMBOL(clk_get); | 226 | EXPORT_SYMBOL(clk_get); |
| 195 | EXPORT_SYMBOL(clk_put); | 227 | EXPORT_SYMBOL(clk_put); |
| 196 | EXPORT_SYMBOL(clk_enable); | 228 | EXPORT_SYMBOL(clk_enable); |
| @@ -199,6 +231,29 @@ EXPORT_SYMBOL(clk_get_rate); | |||
| 199 | EXPORT_SYMBOL(clk_round_rate); | 231 | EXPORT_SYMBOL(clk_round_rate); |
| 200 | EXPORT_SYMBOL(clk_set_rate); | 232 | EXPORT_SYMBOL(clk_set_rate); |
| 201 | EXPORT_SYMBOL(clk_get_parent); | 233 | EXPORT_SYMBOL(clk_get_parent); |
| 234 | EXPORT_SYMBOL(clk_set_parent); | ||
| 235 | |||
| 236 | /* base clock enable */ | ||
| 237 | |||
| 238 | static int s3c24xx_upll_enable(struct clk *clk, int enable) | ||
| 239 | { | ||
| 240 | unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); | ||
| 241 | unsigned long orig = clkslow; | ||
| 242 | |||
| 243 | if (enable) | ||
| 244 | clkslow &= ~S3C2410_CLKSLOW_UCLK_OFF; | ||
| 245 | else | ||
| 246 | clkslow |= S3C2410_CLKSLOW_UCLK_OFF; | ||
| 247 | |||
| 248 | __raw_writel(clkslow, S3C2410_CLKSLOW); | ||
| 249 | |||
| 250 | /* if we started the UPLL, then allow to settle */ | ||
| 251 | |||
| 252 | if (enable && !(orig & S3C2410_CLKSLOW_UCLK_OFF)) | ||
| 253 | udelay(200); | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 202 | 257 | ||
| 203 | /* base clocks */ | 258 | /* base clocks */ |
| 204 | 259 | ||
| @@ -210,6 +265,14 @@ static struct clk clk_xtal = { | |||
| 210 | .ctrlbit = 0, | 265 | .ctrlbit = 0, |
| 211 | }; | 266 | }; |
| 212 | 267 | ||
| 268 | static struct clk clk_upll = { | ||
| 269 | .name = "upll", | ||
| 270 | .id = -1, | ||
| 271 | .parent = NULL, | ||
| 272 | .enable = s3c24xx_upll_enable, | ||
| 273 | .ctrlbit = 0, | ||
| 274 | }; | ||
| 275 | |||
| 213 | static struct clk clk_f = { | 276 | static struct clk clk_f = { |
| 214 | .name = "fclk", | 277 | .name = "fclk", |
| 215 | .id = -1, | 278 | .id = -1, |
| @@ -234,26 +297,124 @@ static struct clk clk_p = { | |||
| 234 | .ctrlbit = 0, | 297 | .ctrlbit = 0, |
| 235 | }; | 298 | }; |
| 236 | 299 | ||
| 300 | struct clk clk_usb_bus = { | ||
| 301 | .name = "usb-bus", | ||
| 302 | .id = -1, | ||
| 303 | .rate = 0, | ||
| 304 | .parent = &clk_upll, | ||
| 305 | }; | ||
| 306 | |||
| 237 | /* clocks that could be registered by external code */ | 307 | /* clocks that could be registered by external code */ |
| 238 | 308 | ||
| 309 | static int s3c24xx_dclk_enable(struct clk *clk, int enable) | ||
| 310 | { | ||
| 311 | unsigned long dclkcon = __raw_readl(S3C2410_DCLKCON); | ||
| 312 | |||
| 313 | if (enable) | ||
| 314 | dclkcon |= clk->ctrlbit; | ||
| 315 | else | ||
| 316 | dclkcon &= ~clk->ctrlbit; | ||
| 317 | |||
| 318 | __raw_writel(dclkcon, S3C2410_DCLKCON); | ||
| 319 | |||
| 320 | return 0; | ||
| 321 | } | ||
| 322 | |||
| 323 | static int s3c24xx_dclk_setparent(struct clk *clk, struct clk *parent) | ||
| 324 | { | ||
| 325 | unsigned long dclkcon; | ||
| 326 | unsigned int uclk; | ||
| 327 | |||
| 328 | if (parent == &clk_upll) | ||
| 329 | uclk = 1; | ||
| 330 | else if (parent == &clk_p) | ||
| 331 | uclk = 0; | ||
| 332 | else | ||
| 333 | return -EINVAL; | ||
| 334 | |||
| 335 | clk->parent = parent; | ||
| 336 | |||
| 337 | dclkcon = __raw_readl(S3C2410_DCLKCON); | ||
| 338 | |||
| 339 | if (clk->ctrlbit == S3C2410_DCLKCON_DCLK0EN) { | ||
| 340 | if (uclk) | ||
| 341 | dclkcon |= S3C2410_DCLKCON_DCLK0_UCLK; | ||
| 342 | else | ||
| 343 | dclkcon &= ~S3C2410_DCLKCON_DCLK0_UCLK; | ||
| 344 | } else { | ||
| 345 | if (uclk) | ||
| 346 | dclkcon |= S3C2410_DCLKCON_DCLK1_UCLK; | ||
| 347 | else | ||
| 348 | dclkcon &= ~S3C2410_DCLKCON_DCLK1_UCLK; | ||
| 349 | } | ||
| 350 | |||
| 351 | __raw_writel(dclkcon, S3C2410_DCLKCON); | ||
| 352 | |||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | |||
| 356 | |||
| 357 | static int s3c24xx_clkout_setparent(struct clk *clk, struct clk *parent) | ||
| 358 | { | ||
| 359 | unsigned long mask; | ||
| 360 | unsigned long source; | ||
| 361 | |||
| 362 | /* calculate the MISCCR setting for the clock */ | ||
| 363 | |||
| 364 | if (parent == &clk_xtal) | ||
| 365 | source = S3C2410_MISCCR_CLK0_MPLL; | ||
| 366 | else if (parent == &clk_upll) | ||
| 367 | source = S3C2410_MISCCR_CLK0_UPLL; | ||
| 368 | else if (parent == &clk_f) | ||
| 369 | source = S3C2410_MISCCR_CLK0_FCLK; | ||
| 370 | else if (parent == &clk_p) | ||
| 371 | source = S3C2410_MISCCR_CLK0_PCLK; | ||
| 372 | else if (clk == &s3c24xx_clkout0 && parent == &s3c24xx_dclk0) | ||
| 373 | source = S3C2410_MISCCR_CLK0_DCLK0; | ||
| 374 | else if (clk == &s3c24xx_clkout1 && parent == &s3c24xx_dclk1) | ||
| 375 | source = S3C2410_MISCCR_CLK0_DCLK0; | ||
| 376 | else | ||
| 377 | return -EINVAL; | ||
| 378 | |||
| 379 | if (clk == &s3c24xx_dclk0) | ||
| 380 | mask = S3C2410_MISCCR_CLK0_MASK; | ||
| 381 | else { | ||
| 382 | source <<= 4; | ||
| 383 | mask = S3C2410_MISCCR_CLK1_MASK; | ||
| 384 | } | ||
| 385 | |||
| 386 | s3c2410_modify_misccr(mask, source); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | /* external clock definitions */ | ||
| 391 | |||
| 239 | struct clk s3c24xx_dclk0 = { | 392 | struct clk s3c24xx_dclk0 = { |
| 240 | .name = "dclk0", | 393 | .name = "dclk0", |
| 241 | .id = -1, | 394 | .id = -1, |
| 395 | .ctrlbit = S3C2410_DCLKCON_DCLK0EN, | ||
| 396 | .enable = s3c24xx_dclk_enable, | ||
| 397 | .set_parent = s3c24xx_dclk_setparent, | ||
| 242 | }; | 398 | }; |
| 243 | 399 | ||
| 244 | struct clk s3c24xx_dclk1 = { | 400 | struct clk s3c24xx_dclk1 = { |
| 245 | .name = "dclk1", | 401 | .name = "dclk1", |
| 246 | .id = -1, | 402 | .id = -1, |
| 403 | .ctrlbit = S3C2410_DCLKCON_DCLK0EN, | ||
| 404 | .enable = s3c24xx_dclk_enable, | ||
| 405 | .set_parent = s3c24xx_dclk_setparent, | ||
| 247 | }; | 406 | }; |
| 248 | 407 | ||
| 249 | struct clk s3c24xx_clkout0 = { | 408 | struct clk s3c24xx_clkout0 = { |
| 250 | .name = "clkout0", | 409 | .name = "clkout0", |
| 251 | .id = -1, | 410 | .id = -1, |
| 411 | .set_parent = s3c24xx_clkout_setparent, | ||
| 252 | }; | 412 | }; |
| 253 | 413 | ||
| 254 | struct clk s3c24xx_clkout1 = { | 414 | struct clk s3c24xx_clkout1 = { |
| 255 | .name = "clkout1", | 415 | .name = "clkout1", |
| 256 | .id = -1, | 416 | .id = -1, |
| 417 | .set_parent = s3c24xx_clkout_setparent, | ||
| 257 | }; | 418 | }; |
| 258 | 419 | ||
| 259 | struct clk s3c24xx_uclk = { | 420 | struct clk s3c24xx_uclk = { |
| @@ -262,7 +423,7 @@ struct clk s3c24xx_uclk = { | |||
| 262 | }; | 423 | }; |
| 263 | 424 | ||
| 264 | 425 | ||
| 265 | /* clock definitions */ | 426 | /* standard clock definitions */ |
| 266 | 427 | ||
| 267 | static struct clk init_clocks[] = { | 428 | static struct clk init_clocks[] = { |
| 268 | { | 429 | { |
| @@ -374,7 +535,7 @@ int s3c24xx_register_clock(struct clk *clk) | |||
| 374 | 535 | ||
| 375 | /* if this is a standard clock, set the usage state */ | 536 | /* if this is a standard clock, set the usage state */ |
| 376 | 537 | ||
| 377 | if (clk->ctrlbit) { | 538 | if (clk->ctrlbit && clk->enable == s3c24xx_clkcon_enable) { |
| 378 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); | 539 | unsigned long clkcon = __raw_readl(S3C2410_CLKCON); |
| 379 | 540 | ||
| 380 | clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; | 541 | clk->usage = (clkcon & clk->ctrlbit) ? 1 : 0; |
| @@ -396,6 +557,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, | |||
| 396 | unsigned long hclk, | 557 | unsigned long hclk, |
| 397 | unsigned long pclk) | 558 | unsigned long pclk) |
| 398 | { | 559 | { |
| 560 | unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); | ||
| 399 | unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); | 561 | unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW); |
| 400 | struct clk *clkp = init_clocks; | 562 | struct clk *clkp = init_clocks; |
| 401 | int ptr; | 563 | int ptr; |
| @@ -406,6 +568,7 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, | |||
| 406 | /* initialise the main system clocks */ | 568 | /* initialise the main system clocks */ |
| 407 | 569 | ||
| 408 | clk_xtal.rate = xtal; | 570 | clk_xtal.rate = xtal; |
| 571 | clk_upll.rate = s3c2410_get_pll(upllcon, xtal); | ||
| 409 | 572 | ||
| 410 | clk_h.rate = hclk; | 573 | clk_h.rate = hclk; |
| 411 | clk_p.rate = pclk; | 574 | clk_p.rate = pclk; |
| @@ -439,6 +602,9 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, | |||
| 439 | if (s3c24xx_register_clock(&clk_xtal) < 0) | 602 | if (s3c24xx_register_clock(&clk_xtal) < 0) |
| 440 | printk(KERN_ERR "failed to register master xtal\n"); | 603 | printk(KERN_ERR "failed to register master xtal\n"); |
| 441 | 604 | ||
| 605 | if (s3c24xx_register_clock(&clk_upll) < 0) | ||
| 606 | printk(KERN_ERR "failed to register upll clock\n"); | ||
| 607 | |||
| 442 | if (s3c24xx_register_clock(&clk_f) < 0) | 608 | if (s3c24xx_register_clock(&clk_f) < 0) |
| 443 | printk(KERN_ERR "failed to register cpu fclk\n"); | 609 | printk(KERN_ERR "failed to register cpu fclk\n"); |
| 444 | 610 | ||
| @@ -448,6 +614,10 @@ int __init s3c24xx_setup_clocks(unsigned long xtal, | |||
| 448 | if (s3c24xx_register_clock(&clk_p) < 0) | 614 | if (s3c24xx_register_clock(&clk_p) < 0) |
| 449 | printk(KERN_ERR "failed to register cpu pclk\n"); | 615 | printk(KERN_ERR "failed to register cpu pclk\n"); |
| 450 | 616 | ||
| 617 | |||
| 618 | if (s3c24xx_register_clock(&clk_usb_bus) < 0) | ||
| 619 | printk(KERN_ERR "failed to register usb bus clock\n"); | ||
| 620 | |||
| 451 | /* register clocks from clock array */ | 621 | /* register clocks from clock array */ |
| 452 | 622 | ||
| 453 | for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { | 623 | for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) { |
diff --git a/arch/arm/mach-s3c2410/clock.h b/arch/arm/mach-s3c2410/clock.h index eb5c95d1e7f2..01bb458bf8eb 100644 --- a/arch/arm/mach-s3c2410/clock.h +++ b/arch/arm/mach-s3c2410/clock.h | |||
| @@ -19,7 +19,11 @@ struct clk { | |||
| 19 | int usage; | 19 | int usage; |
| 20 | unsigned long rate; | 20 | unsigned long rate; |
| 21 | unsigned long ctrlbit; | 21 | unsigned long ctrlbit; |
| 22 | |||
| 22 | int (*enable)(struct clk *, int enable); | 23 | int (*enable)(struct clk *, int enable); |
| 24 | int (*set_rate)(struct clk *c, unsigned long rate); | ||
| 25 | unsigned long (*round_rate)(struct clk *c, unsigned long rate); | ||
| 26 | int (*set_parent)(struct clk *c, struct clk *parent); | ||
| 23 | }; | 27 | }; |
| 24 | 28 | ||
| 25 | /* other clocks which may be registered by board support */ | 29 | /* other clocks which may be registered by board support */ |
| @@ -30,11 +34,15 @@ extern struct clk s3c24xx_clkout0; | |||
| 30 | extern struct clk s3c24xx_clkout1; | 34 | extern struct clk s3c24xx_clkout1; |
| 31 | extern struct clk s3c24xx_uclk; | 35 | extern struct clk s3c24xx_uclk; |
| 32 | 36 | ||
| 37 | extern struct clk clk_usb_bus; | ||
| 38 | |||
| 33 | /* exports for arch/arm/mach-s3c2410 | 39 | /* exports for arch/arm/mach-s3c2410 |
| 34 | * | 40 | * |
| 35 | * Please DO NOT use these outside of arch/arm/mach-s3c2410 | 41 | * Please DO NOT use these outside of arch/arm/mach-s3c2410 |
| 36 | */ | 42 | */ |
| 37 | 43 | ||
| 44 | extern struct mutex clocks_mutex; | ||
| 45 | |||
| 38 | extern int s3c24xx_clkcon_enable(struct clk *clk, int enable); | 46 | extern int s3c24xx_clkcon_enable(struct clk *clk, int enable); |
| 39 | extern int s3c24xx_register_clock(struct clk *clk); | 47 | extern int s3c24xx_register_clock(struct clk *clk); |
| 40 | 48 | ||
diff --git a/arch/arm/mach-s3c2410/mach-osiris.c b/arch/arm/mach-s3c2410/mach-osiris.c new file mode 100644 index 000000000000..ae0787557751 --- /dev/null +++ b/arch/arm/mach-s3c2410/mach-osiris.c | |||
| @@ -0,0 +1,294 @@ | |||
| 1 | /* linux/arch/arm/mach-s3c2410/mach-osiris.c | ||
| 2 | * | ||
| 3 | * Copyright (c) 2005 Simtec Electronics | ||
| 4 | * http://armlinux.simtec.co.uk/ | ||
| 5 | * Ben Dooks <ben@simtec.co.uk> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/kernel.h> | ||
| 13 | #include <linux/types.h> | ||
| 14 | #include <linux/interrupt.h> | ||
| 15 | #include <linux/list.h> | ||
| 16 | #include <linux/timer.h> | ||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/device.h> | ||
| 19 | |||
| 20 | #include <asm/mach/arch.h> | ||
| 21 | #include <asm/mach/map.h> | ||
| 22 | #include <asm/mach/irq.h> | ||
| 23 | |||
| 24 | #include <asm/arch/osiris-map.h> | ||
| 25 | #include <asm/arch/osiris-cpld.h> | ||
| 26 | |||
| 27 | #include <asm/hardware.h> | ||
| 28 | #include <asm/io.h> | ||
| 29 | #include <asm/irq.h> | ||
| 30 | #include <asm/mach-types.h> | ||
| 31 | |||
| 32 | #include <asm/arch/regs-serial.h> | ||
| 33 | #include <asm/arch/regs-gpio.h> | ||
| 34 | #include <asm/arch/regs-mem.h> | ||
| 35 | #include <asm/arch/regs-lcd.h> | ||
| 36 | #include <asm/arch/nand.h> | ||
| 37 | |||
| 38 | #include <linux/mtd/mtd.h> | ||
| 39 | #include <linux/mtd/nand.h> | ||
| 40 | #include <linux/mtd/nand_ecc.h> | ||
| 41 | #include <linux/mtd/partitions.h> | ||
| 42 | |||
| 43 | #include "clock.h" | ||
| 44 | #include "devs.h" | ||
| 45 | #include "cpu.h" | ||
| 46 | |||
| 47 | /* onboard perihpheral map */ | ||
| 48 | |||
| 49 | static struct map_desc osiris_iodesc[] __initdata = { | ||
| 50 | /* ISA IO areas (may be over-written later) */ | ||
| 51 | |||
| 52 | { | ||
| 53 | .virtual = (u32)S3C24XX_VA_ISA_BYTE, | ||
| 54 | .pfn = __phys_to_pfn(S3C2410_CS5), | ||
| 55 | .length = SZ_16M, | ||
| 56 | .type = MT_DEVICE, | ||
| 57 | }, { | ||
| 58 | .virtual = (u32)S3C24XX_VA_ISA_WORD, | ||
| 59 | .pfn = __phys_to_pfn(S3C2410_CS5), | ||
| 60 | .length = SZ_16M, | ||
| 61 | .type = MT_DEVICE, | ||
| 62 | }, | ||
| 63 | |||
| 64 | /* CPLD control registers */ | ||
| 65 | |||
| 66 | { | ||
| 67 | .virtual = (u32)OSIRIS_VA_CTRL1, | ||
| 68 | .pfn = __phys_to_pfn(OSIRIS_PA_CTRL1), | ||
| 69 | .length = SZ_16K, | ||
| 70 | .type = MT_DEVICE | ||
| 71 | }, { | ||
| 72 | .virtual = (u32)OSIRIS_VA_CTRL2, | ||
| 73 | .pfn = __phys_to_pfn(OSIRIS_PA_CTRL2), | ||
| 74 | .length = SZ_16K, | ||
| 75 | .type = MT_DEVICE | ||
| 76 | }, | ||
| 77 | }; | ||
| 78 | |||
| 79 | #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK | ||
| 80 | #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB | ||
| 81 | #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE | ||
| 82 | |||
| 83 | static struct s3c24xx_uart_clksrc osiris_serial_clocks[] = { | ||
| 84 | [0] = { | ||
| 85 | .name = "uclk", | ||
| 86 | .divisor = 1, | ||
| 87 | .min_baud = 0, | ||
| 88 | .max_baud = 0, | ||
| 89 | }, | ||
| 90 | [1] = { | ||
| 91 | .name = "pclk", | ||
| 92 | .divisor = 1, | ||
| 93 | .min_baud = 0, | ||
| 94 | .max_baud = 0. | ||
| 95 | } | ||
| 96 | }; | ||
| 97 | |||
| 98 | |||
| 99 | static struct s3c2410_uartcfg osiris_uartcfgs[] = { | ||
| 100 | [0] = { | ||
| 101 | .hwport = 0, | ||
| 102 | .flags = 0, | ||
| 103 | .ucon = UCON, | ||
| 104 | .ulcon = ULCON, | ||
| 105 | .ufcon = UFCON, | ||
| 106 | .clocks = osiris_serial_clocks, | ||
| 107 | .clocks_size = ARRAY_SIZE(osiris_serial_clocks) | ||
| 108 | }, | ||
| 109 | [1] = { | ||
| 110 | .hwport = 2, | ||
| 111 | .flags = 0, | ||
| 112 | .ucon = UCON, | ||
| 113 | .ulcon = ULCON, | ||
| 114 | .ufcon = UFCON, | ||
| 115 | .clocks = osiris_serial_clocks, | ||
| 116 | .clocks_size = ARRAY_SIZE(osiris_serial_clocks) | ||
| 117 | }, | ||
| 118 | }; | ||
| 119 | |||
| 120 | /* NAND Flash on Osiris board */ | ||
| 121 | |||
| 122 | static int external_map[] = { 2 }; | ||
| 123 | static int chip0_map[] = { 0 }; | ||
| 124 | static int chip1_map[] = { 1 }; | ||
| 125 | |||
| 126 | static struct mtd_partition osiris_default_nand_part[] = { | ||
| 127 | [0] = { | ||
| 128 | .name = "Boot Agent", | ||
| 129 | .size = SZ_16K, | ||
| 130 | .offset = 0 | ||
| 131 | }, | ||
| 132 | [1] = { | ||
| 133 | .name = "/boot", | ||
| 134 | .size = SZ_4M - SZ_16K, | ||
| 135 | .offset = SZ_16K, | ||
| 136 | }, | ||
| 137 | [2] = { | ||
| 138 | .name = "user1", | ||
| 139 | .offset = SZ_4M, | ||
| 140 | .size = SZ_32M - SZ_4M, | ||
| 141 | }, | ||
| 142 | [3] = { | ||
| 143 | .name = "user2", | ||
| 144 | .offset = SZ_32M, | ||
| 145 | .size = MTDPART_SIZ_FULL, | ||
| 146 | } | ||
| 147 | }; | ||
| 148 | |||
| 149 | /* the Osiris has 3 selectable slots for nand-flash, the two | ||
| 150 | * on-board chip areas, as well as the external slot. | ||
| 151 | * | ||
| 152 | * Note, there is no current hot-plug support for the External | ||
| 153 | * socket. | ||
| 154 | */ | ||
| 155 | |||
| 156 | static struct s3c2410_nand_set osiris_nand_sets[] = { | ||
| 157 | [1] = { | ||
| 158 | .name = "External", | ||
| 159 | .nr_chips = 1, | ||
| 160 | .nr_map = external_map, | ||
| 161 | .nr_partitions = ARRAY_SIZE(osiris_default_nand_part), | ||
| 162 | .partitions = osiris_default_nand_part | ||
| 163 | }, | ||
| 164 | [0] = { | ||
| 165 | .name = "chip0", | ||
| 166 | .nr_chips = 1, | ||
| 167 | .nr_map = chip0_map, | ||
| 168 | .nr_partitions = ARRAY_SIZE(osiris_default_nand_part), | ||
| 169 | .partitions = osiris_default_nand_part | ||
| 170 | }, | ||
| 171 | [2] = { | ||
| 172 | .name = "chip1", | ||
| 173 | .nr_chips = 1, | ||
| 174 | .nr_map = chip1_map, | ||
| 175 | .nr_partitions = ARRAY_SIZE(osiris_default_nand_part), | ||
| 176 | .partitions = osiris_default_nand_part | ||
| 177 | }, | ||
| 178 | }; | ||
| 179 | |||
| 180 | static void osiris_nand_select(struct s3c2410_nand_set *set, int slot) | ||
| 181 | { | ||
| 182 | unsigned int tmp; | ||
| 183 | |||
| 184 | slot = set->nr_map[slot] & 3; | ||
| 185 | |||
| 186 | pr_debug("osiris_nand: selecting slot %d (set %p,%p)\n", | ||
| 187 | slot, set, set->nr_map); | ||
| 188 | |||
| 189 | tmp = __raw_readb(OSIRIS_VA_CTRL1); | ||
| 190 | tmp &= ~OSIRIS_CTRL1_NANDSEL; | ||
| 191 | tmp |= slot; | ||
| 192 | |||
| 193 | pr_debug("osiris_nand: ctrl1 now %02x\n", tmp); | ||
| 194 | |||
| 195 | __raw_writeb(tmp, OSIRIS_VA_CTRL1); | ||
| 196 | } | ||
| 197 | |||
| 198 | static struct s3c2410_platform_nand osiris_nand_info = { | ||
| 199 | .tacls = 25, | ||
| 200 | .twrph0 = 60, | ||
| 201 | .twrph1 = 60, | ||
| 202 | .nr_sets = ARRAY_SIZE(osiris_nand_sets), | ||
| 203 | .sets = osiris_nand_sets, | ||
| 204 | .select_chip = osiris_nand_select, | ||
| 205 | }; | ||
| 206 | |||
| 207 | /* PCMCIA control and configuration */ | ||
| 208 | |||
| 209 | static struct resource osiris_pcmcia_resource[] = { | ||
| 210 | [0] = { | ||
| 211 | .start = 0x0f000000, | ||
| 212 | .end = 0x0f100000, | ||
| 213 | .flags = IORESOURCE_MEM, | ||
| 214 | }, | ||
| 215 | [1] = { | ||
| 216 | .start = 0x0c000000, | ||
| 217 | .end = 0x0c100000, | ||
| 218 | .flags = IORESOURCE_MEM, | ||
| 219 | } | ||
| 220 | }; | ||
| 221 | |||
| 222 | static struct platform_device osiris_pcmcia = { | ||
| 223 | .name = "osiris-pcmcia", | ||
| 224 | .id = -1, | ||
| 225 | .num_resources = ARRAY_SIZE(osiris_pcmcia_resource), | ||
| 226 | .resource = osiris_pcmcia_resource, | ||
| 227 | }; | ||
| 228 | |||
| 229 | /* Standard Osiris devices */ | ||
| 230 | |||
| 231 | static struct platform_device *osiris_devices[] __initdata = { | ||
| 232 | &s3c_device_i2c, | ||
| 233 | &s3c_device_nand, | ||
| 234 | &osiris_pcmcia, | ||
| 235 | }; | ||
| 236 | |||
| 237 | static struct clk *osiris_clocks[] = { | ||
| 238 | &s3c24xx_dclk0, | ||
| 239 | &s3c24xx_dclk1, | ||
| 240 | &s3c24xx_clkout0, | ||
| 241 | &s3c24xx_clkout1, | ||
| 242 | &s3c24xx_uclk, | ||
| 243 | }; | ||
| 244 | |||
| 245 | static struct s3c24xx_board osiris_board __initdata = { | ||
| 246 | .devices = osiris_devices, | ||
| 247 | .devices_count = ARRAY_SIZE(osiris_devices), | ||
| 248 | .clocks = osiris_clocks, | ||
| 249 | .clocks_count = ARRAY_SIZE(osiris_clocks) | ||
| 250 | }; | ||
| 251 | |||
| 252 | static void __init osiris_map_io(void) | ||
| 253 | { | ||
| 254 | unsigned long flags; | ||
| 255 | |||
| 256 | /* initialise the clocks */ | ||
| 257 | |||
| 258 | s3c24xx_dclk0.parent = NULL; | ||
| 259 | s3c24xx_dclk0.rate = 12*1000*1000; | ||
| 260 | |||
| 261 | s3c24xx_dclk1.parent = NULL; | ||
| 262 | s3c24xx_dclk1.rate = 24*1000*1000; | ||
| 263 | |||
| 264 | s3c24xx_clkout0.parent = &s3c24xx_dclk0; | ||
| 265 | s3c24xx_clkout1.parent = &s3c24xx_dclk1; | ||
| 266 | |||
| 267 | s3c24xx_uclk.parent = &s3c24xx_clkout1; | ||
| 268 | |||
| 269 | s3c_device_nand.dev.platform_data = &osiris_nand_info; | ||
| 270 | |||
| 271 | s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc)); | ||
| 272 | s3c24xx_init_clocks(0); | ||
| 273 | s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs)); | ||
| 274 | s3c24xx_set_board(&osiris_board); | ||
| 275 | |||
| 276 | /* fix bus configuration (nBE settings wrong on ABLE pre v2.20) */ | ||
| 277 | |||
| 278 | local_irq_save(flags); | ||
| 279 | __raw_writel(__raw_readl(S3C2410_BWSCON) | S3C2410_BWSCON_ST1 | S3C2410_BWSCON_ST2 | S3C2410_BWSCON_ST3 | S3C2410_BWSCON_ST4 | S3C2410_BWSCON_ST5, S3C2410_BWSCON); | ||
| 280 | local_irq_restore(flags); | ||
| 281 | |||
| 282 | /* write-protect line to the NAND */ | ||
| 283 | s3c2410_gpio_setpin(S3C2410_GPA0, 1); | ||
| 284 | } | ||
| 285 | |||
| 286 | MACHINE_START(OSIRIS, "Simtec-OSIRIS") | ||
| 287 | /* Maintainer: Ben Dooks <ben@simtec.co.uk> */ | ||
| 288 | .phys_io = S3C2410_PA_UART, | ||
| 289 | .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc, | ||
| 290 | .boot_params = S3C2410_SDRAM_PA + 0x100, | ||
| 291 | .map_io = osiris_map_io, | ||
| 292 | .init_irq = s3c24xx_init_irq, | ||
| 293 | .timer = &s3c24xx_timer, | ||
| 294 | MACHINE_END | ||
diff --git a/arch/arm/mach-s3c2410/s3c2440-clock.c b/arch/arm/mach-s3c2410/s3c2440-clock.c index b557a2be8a01..57a15974d4b5 100644 --- a/arch/arm/mach-s3c2410/s3c2440-clock.c +++ b/arch/arm/mach-s3c2410/s3c2440-clock.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/sysdev.h> | 31 | #include <linux/sysdev.h> |
| 32 | #include <linux/interrupt.h> | 32 | #include <linux/interrupt.h> |
| 33 | #include <linux/ioport.h> | 33 | #include <linux/ioport.h> |
| 34 | #include <linux/mutex.h> | ||
| 34 | #include <linux/clk.h> | 35 | #include <linux/clk.h> |
| 35 | 36 | ||
| 36 | #include <asm/hardware.h> | 37 | #include <asm/hardware.h> |
| @@ -45,10 +46,47 @@ | |||
| 45 | 46 | ||
| 46 | /* S3C2440 extended clock support */ | 47 | /* S3C2440 extended clock support */ |
| 47 | 48 | ||
| 48 | static struct clk s3c2440_clk_upll = { | 49 | static unsigned long s3c2440_camif_upll_round(struct clk *clk, |
| 49 | .name = "upll", | 50 | unsigned long rate) |
| 50 | .id = -1, | 51 | { |
| 51 | }; | 52 | unsigned long parent_rate = clk_get_rate(clk->parent); |
| 53 | int div; | ||
| 54 | |||
| 55 | if (rate > parent_rate) | ||
| 56 | return parent_rate; | ||
| 57 | |||
| 58 | /* note, we remove the +/- 1 calculations for the divisor */ | ||
| 59 | |||
| 60 | div = (parent_rate / rate) / 2; | ||
| 61 | |||
| 62 | if (div < 1) | ||
| 63 | div = 1; | ||
| 64 | else if (div > 16) | ||
| 65 | div = 16; | ||
| 66 | |||
| 67 | return parent_rate / (div * 2); | ||
| 68 | } | ||
| 69 | |||
| 70 | static int s3c2440_camif_upll_setrate(struct clk *clk, unsigned long rate) | ||
| 71 | { | ||
| 72 | unsigned long parent_rate = clk_get_rate(clk->parent); | ||
| 73 | unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); | ||
| 74 | |||
| 75 | rate = s3c2440_camif_upll_round(clk, rate); | ||
| 76 | |||
| 77 | camdivn &= ~(S3C2440_CAMDIVN_CAMCLK_SEL | S3C2440_CAMDIVN_CAMCLK_MASK); | ||
| 78 | |||
| 79 | if (rate != parent_rate) { | ||
| 80 | camdivn |= S3C2440_CAMDIVN_CAMCLK_SEL; | ||
| 81 | camdivn |= (((parent_rate / rate) / 2) - 1); | ||
| 82 | } | ||
| 83 | |||
| 84 | __raw_writel(camdivn, S3C2440_CAMDIVN); | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | |||
| 89 | /* Extra S3C2440 clocks */ | ||
| 52 | 90 | ||
| 53 | static struct clk s3c2440_clk_cam = { | 91 | static struct clk s3c2440_clk_cam = { |
| 54 | .name = "camif", | 92 | .name = "camif", |
| @@ -57,6 +95,13 @@ static struct clk s3c2440_clk_cam = { | |||
| 57 | .ctrlbit = S3C2440_CLKCON_CAMERA, | 95 | .ctrlbit = S3C2440_CLKCON_CAMERA, |
| 58 | }; | 96 | }; |
| 59 | 97 | ||
| 98 | static struct clk s3c2440_clk_cam_upll = { | ||
| 99 | .name = "camif-upll", | ||
| 100 | .id = -1, | ||
| 101 | .set_rate = s3c2440_camif_upll_setrate, | ||
| 102 | .round_rate = s3c2440_camif_upll_round, | ||
| 103 | }; | ||
| 104 | |||
| 60 | static struct clk s3c2440_clk_ac97 = { | 105 | static struct clk s3c2440_clk_ac97 = { |
| 61 | .name = "ac97", | 106 | .name = "ac97", |
| 62 | .id = -1, | 107 | .id = -1, |
| @@ -66,38 +111,46 @@ static struct clk s3c2440_clk_ac97 = { | |||
| 66 | 111 | ||
| 67 | static int s3c2440_clk_add(struct sys_device *sysdev) | 112 | static int s3c2440_clk_add(struct sys_device *sysdev) |
| 68 | { | 113 | { |
| 69 | unsigned long upllcon = __raw_readl(S3C2410_UPLLCON); | ||
| 70 | unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); | 114 | unsigned long camdivn = __raw_readl(S3C2440_CAMDIVN); |
| 115 | unsigned long clkdivn; | ||
| 71 | struct clk *clk_h; | 116 | struct clk *clk_h; |
| 72 | struct clk *clk_p; | 117 | struct clk *clk_p; |
| 73 | struct clk *clk_xtal; | 118 | struct clk *clk_upll; |
| 74 | |||
| 75 | clk_xtal = clk_get(NULL, "xtal"); | ||
| 76 | if (IS_ERR(clk_xtal)) { | ||
| 77 | printk(KERN_ERR "S3C2440: Failed to get clk_xtal\n"); | ||
| 78 | return -EINVAL; | ||
| 79 | } | ||
| 80 | |||
| 81 | s3c2440_clk_upll.rate = s3c2410_get_pll(upllcon, clk_xtal->rate); | ||
| 82 | 119 | ||
| 83 | printk("S3C2440: Clock Support, UPLL %ld.%03ld MHz, DVS %s\n", | 120 | printk("S3C2440: Clock Support, DVS %s\n", |
| 84 | print_mhz(s3c2440_clk_upll.rate), | ||
| 85 | (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); | 121 | (camdivn & S3C2440_CAMDIVN_DVSEN) ? "on" : "off"); |
| 86 | 122 | ||
| 87 | clk_p = clk_get(NULL, "pclk"); | 123 | clk_p = clk_get(NULL, "pclk"); |
| 88 | clk_h = clk_get(NULL, "hclk"); | 124 | clk_h = clk_get(NULL, "hclk"); |
| 125 | clk_upll = clk_get(NULL, "upll"); | ||
| 89 | 126 | ||
| 90 | if (IS_ERR(clk_p) || IS_ERR(clk_h)) { | 127 | if (IS_ERR(clk_p) || IS_ERR(clk_h) || IS_ERR(clk_upll)) { |
| 91 | printk(KERN_ERR "S3C2440: Failed to get parent clocks\n"); | 128 | printk(KERN_ERR "S3C2440: Failed to get parent clocks\n"); |
| 92 | return -EINVAL; | 129 | return -EINVAL; |
| 93 | } | 130 | } |
| 94 | 131 | ||
| 132 | /* check rate of UPLL, and if it is near 96MHz, then change | ||
| 133 | * to using half the UPLL rate for the system */ | ||
| 134 | |||
| 135 | if (clk_get_rate(clk_upll) > (94 * MHZ)) { | ||
| 136 | clk_usb_bus.rate = clk_get_rate(clk_upll) / 2; | ||
| 137 | |||
| 138 | mutex_lock(&clocks_mutex); | ||
| 139 | |||
| 140 | clkdivn = __raw_readl(S3C2410_CLKDIVN); | ||
| 141 | clkdivn |= S3C2440_CLKDIVN_UCLK; | ||
| 142 | __raw_writel(camdivn, S3C2410_CLKDIVN); | ||
| 143 | |||
| 144 | mutex_unlock(&clocks_mutex); | ||
| 145 | } | ||
| 146 | |||
| 95 | s3c2440_clk_cam.parent = clk_h; | 147 | s3c2440_clk_cam.parent = clk_h; |
| 96 | s3c2440_clk_ac97.parent = clk_p; | 148 | s3c2440_clk_ac97.parent = clk_p; |
| 149 | s3c2440_clk_cam_upll.parent = clk_upll; | ||
| 97 | 150 | ||
| 98 | s3c24xx_register_clock(&s3c2440_clk_ac97); | 151 | s3c24xx_register_clock(&s3c2440_clk_ac97); |
| 99 | s3c24xx_register_clock(&s3c2440_clk_cam); | 152 | s3c24xx_register_clock(&s3c2440_clk_cam); |
| 100 | s3c24xx_register_clock(&s3c2440_clk_upll); | 153 | s3c24xx_register_clock(&s3c2440_clk_cam_upll); |
| 101 | 154 | ||
| 102 | clk_disable(&s3c2440_clk_ac97); | 155 | clk_disable(&s3c2440_clk_ac97); |
| 103 | clk_disable(&s3c2440_clk_cam); | 156 | clk_disable(&s3c2440_clk_cam); |
diff --git a/arch/arm/mach-s3c2410/time.c b/arch/arm/mach-s3c2410/time.c index 10a2976aefdd..9d7b799ea4a4 100644 --- a/arch/arm/mach-s3c2410/time.c +++ b/arch/arm/mach-s3c2410/time.c | |||
| @@ -142,6 +142,12 @@ static struct irqaction s3c2410_timer_irq = { | |||
| 142 | .handler = s3c2410_timer_interrupt, | 142 | .handler = s3c2410_timer_interrupt, |
| 143 | }; | 143 | }; |
| 144 | 144 | ||
| 145 | #define use_tclk1_12() ( \ | ||
| 146 | machine_is_bast() || \ | ||
| 147 | machine_is_vr1000() || \ | ||
| 148 | machine_is_anubis() || \ | ||
| 149 | machine_is_osiris() ) | ||
| 150 | |||
| 145 | /* | 151 | /* |
| 146 | * Set up timer interrupt, and return the current time in seconds. | 152 | * Set up timer interrupt, and return the current time in seconds. |
| 147 | * | 153 | * |
| @@ -165,7 +171,7 @@ static void s3c2410_timer_setup (void) | |||
| 165 | 171 | ||
| 166 | /* configure the system for whichever machine is in use */ | 172 | /* configure the system for whichever machine is in use */ |
| 167 | 173 | ||
| 168 | if (machine_is_bast() || machine_is_vr1000() || machine_is_anubis()) { | 174 | if (use_tclk1_12()) { |
| 169 | /* timer is at 12MHz, scaler is 1 */ | 175 | /* timer is at 12MHz, scaler is 1 */ |
| 170 | timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); | 176 | timer_usec_ticks = timer_mask_usec_ticks(1, 12000000); |
| 171 | tcnt = 12000000 / HZ; | 177 | tcnt = 12000000 / HZ; |
