197d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King/* 297d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King * linux/arch/arm/mach-sa1100/clock.c 397d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King */ 497d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/module.h> 597d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/kernel.h> 65e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King#include <linux/device.h> 797d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/list.h> 897d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/errno.h> 997d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/err.h> 1097d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/string.h> 1197d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/clk.h> 1297d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King#include <linux/spinlock.h> 13d0a9d75b9cd9cc8097c746611cc57cc8438b94beRussell King#include <linux/mutex.h> 144a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou#include <linux/io.h> 154a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou#include <linux/clkdev.h> 1697d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 17a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h> 1897d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 194a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustruct clkops { 204a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou void (*enable)(struct clk *); 214a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou void (*disable)(struct clk *); 224a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou}; 234a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 2497d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell Kingstruct clk { 254a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou const struct clkops *ops; 2697d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King unsigned int enabled; 2797d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King}; 2897d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 294a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou#define DEFINE_CLK(_name, _ops) \ 304a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustruct clk clk_##_name = { \ 314a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou .ops = _ops, \ 324a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou } 334a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 344a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustatic DEFINE_SPINLOCK(clocks_lock); 354a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 364a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustatic void clk_gpio27_enable(struct clk *clk) 375e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King{ 385e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King /* 395e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111: 405e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King * (SA-1110 Developer's Manual, section 9.1.2.1) 415e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King */ 425e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King GAFR |= GPIO_32_768kHz; 435e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King GPDR |= GPIO_32_768kHz; 445e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King TUCR = TUCR_3_6864MHz; 455e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King} 465e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King 474a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustatic void clk_gpio27_disable(struct clk *clk) 485e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King{ 495e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King TUCR = 0; 505e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King GPDR &= ~GPIO_32_768kHz; 515e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King GAFR &= ~GPIO_32_768kHz; 525e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King} 535e1dbdb458ada37f7e97265cb2ea87c55fd5d034Russell King 5497d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell Kingint clk_enable(struct clk *clk) 5597d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King{ 5697d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King unsigned long flags; 5797d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 584a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou if (clk) { 594a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou spin_lock_irqsave(&clocks_lock, flags); 604a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou if (clk->enabled++ == 0) 614a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou clk->ops->enable(clk); 624a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou spin_unlock_irqrestore(&clocks_lock, flags); 634a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou } 644a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 6597d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King return 0; 6697d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King} 6797d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell KingEXPORT_SYMBOL(clk_enable); 6897d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 6997d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell Kingvoid clk_disable(struct clk *clk) 7097d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King{ 7197d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King unsigned long flags; 7297d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 734a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou if (clk) { 744a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou WARN_ON(clk->enabled == 0); 754a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou spin_lock_irqsave(&clocks_lock, flags); 764a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou if (--clk->enabled == 0) 774a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou clk->ops->disable(clk); 784a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou spin_unlock_irqrestore(&clocks_lock, flags); 794a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou } 8097d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King} 8197d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell KingEXPORT_SYMBOL(clk_disable); 8297d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King 834a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhouconst struct clkops clk_gpio27_ops = { 844a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou .enable = clk_gpio27_enable, 854a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou .disable = clk_gpio27_disable, 864a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou}; 874a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 884a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustatic DEFINE_CLK(gpio27, &clk_gpio27_ops); 894a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 904a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustatic struct clk_lookup sa11xx_clkregs[] = { 914a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou CLKDEV_INIT("sa1111.0", NULL, &clk_gpio27), 924a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou CLKDEV_INIT("sa1100-rtc", NULL, NULL), 934a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou}; 944a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou 954a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoustatic int __init sa11xx_clk_init(void) 9697d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King{ 974a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou clkdev_add_table(sa11xx_clkregs, ARRAY_SIZE(sa11xx_clkregs)); 984a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhou return 0; 9997d654f8eb4b8fbb6e1afef076429a4235a3a3adRussell King} 1004a8f83409da6be1085b3c8f52538c1427ef2c0f1Jett.Zhoucore_initcall(sa11xx_clk_init); 101