aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-davinci')
-rw-r--r--arch/arm/mach-davinci/Makefile3
-rw-r--r--arch/arm/mach-davinci/board-evm.c2
-rw-r--r--arch/arm/mach-davinci/clock.c323
-rw-r--r--arch/arm/mach-davinci/clock.h33
-rw-r--r--arch/arm/mach-davinci/gpio.c286
-rw-r--r--arch/arm/mach-davinci/io.c6
-rw-r--r--arch/arm/mach-davinci/mux.c41
-rw-r--r--arch/arm/mach-davinci/psc.c87
8 files changed, 750 insertions, 31 deletions
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index a8f88cd29905..99ac2e55774d 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -4,7 +4,8 @@
4# 4#
5 5
6# Common objects 6# Common objects
7obj-y := time.o irq.o serial.o io.o id.o psc.o 7obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
8 gpio.o mux.o
8 9
9# Board specific 10# Board specific
10obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o 11obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index 633c12e43044..9e4024c4965f 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -32,6 +32,7 @@
32void __init davinci_psc_init(void); 32void __init davinci_psc_init(void);
33void __init davinci_irq_init(void); 33void __init davinci_irq_init(void);
34void __init davinci_map_common_io(void); 34void __init davinci_map_common_io(void);
35void __init davinci_init_common_hw(void);
35 36
36/* NOR Flash base address set to CS0 by default */ 37/* NOR Flash base address set to CS0 by default */
37#define NOR_FLASH_PHYS 0x02000000 38#define NOR_FLASH_PHYS 0x02000000
@@ -116,6 +117,7 @@ static __init void davinci_evm_init(void)
116 117
117static __init void davinci_evm_irq_init(void) 118static __init void davinci_evm_irq_init(void)
118{ 119{
120 davinci_init_common_hw();
119 davinci_irq_init(); 121 davinci_irq_init();
120} 122}
121 123
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
new file mode 100644
index 000000000000..139ceaa35e24
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.c
@@ -0,0 +1,323 @@
1/*
2 * TI DaVinci clock config file
3 *
4 * Copyright (C) 2006 Texas Instruments.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/errno.h>
16#include <linux/err.h>
17#include <linux/mutex.h>
18#include <linux/platform_device.h>
19
20#include <asm/hardware.h>
21#include <asm/io.h>
22
23#include <asm/arch/psc.h>
24#include "clock.h"
25
26/* PLL/Reset register offsets */
27#define PLLM 0x110
28
29static LIST_HEAD(clocks);
30static DEFINE_MUTEX(clocks_mutex);
31static DEFINE_SPINLOCK(clockfw_lock);
32
33static unsigned int commonrate;
34static unsigned int armrate;
35static unsigned int fixedrate = 27000000; /* 27 MHZ */
36
37extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
38
39/*
40 * Returns a clock. Note that we first try to use device id on the bus
41 * and clock name. If this fails, we try to use clock name only.
42 */
43struct clk *clk_get(struct device *dev, const char *id)
44{
45 struct clk *p, *clk = ERR_PTR(-ENOENT);
46 int idno;
47
48 if (dev == NULL || dev->bus != &platform_bus_type)
49 idno = -1;
50 else
51 idno = to_platform_device(dev)->id;
52
53 mutex_lock(&clocks_mutex);
54
55 list_for_each_entry(p, &clocks, node) {
56 if (p->id == idno &&
57 strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
58 clk = p;
59 goto found;
60 }
61 }
62
63 list_for_each_entry(p, &clocks, node) {
64 if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
65 clk = p;
66 break;
67 }
68 }
69
70found:
71 mutex_unlock(&clocks_mutex);
72
73 return clk;
74}
75EXPORT_SYMBOL(clk_get);
76
77void clk_put(struct clk *clk)
78{
79 if (clk && !IS_ERR(clk))
80 module_put(clk->owner);
81}
82EXPORT_SYMBOL(clk_put);
83
84static int __clk_enable(struct clk *clk)
85{
86 if (clk->flags & ALWAYS_ENABLED)
87 return 0;
88
89 davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
90 return 0;
91}
92
93static void __clk_disable(struct clk *clk)
94{
95 if (clk->usecount)
96 return;
97
98 davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
99}
100
101int clk_enable(struct clk *clk)
102{
103 unsigned long flags;
104 int ret = 0;
105
106 if (clk == NULL || IS_ERR(clk))
107 return -EINVAL;
108
109 if (clk->usecount++ == 0) {
110 spin_lock_irqsave(&clockfw_lock, flags);
111 ret = __clk_enable(clk);
112 spin_unlock_irqrestore(&clockfw_lock, flags);
113 }
114
115 return ret;
116}
117EXPORT_SYMBOL(clk_enable);
118
119void clk_disable(struct clk *clk)
120{
121 unsigned long flags;
122
123 if (clk == NULL || IS_ERR(clk))
124 return;
125
126 if (clk->usecount > 0 && !(--clk->usecount)) {
127 spin_lock_irqsave(&clockfw_lock, flags);
128 __clk_disable(clk);
129 spin_unlock_irqrestore(&clockfw_lock, flags);
130 }
131}
132EXPORT_SYMBOL(clk_disable);
133
134unsigned long clk_get_rate(struct clk *clk)
135{
136 if (clk == NULL || IS_ERR(clk))
137 return -EINVAL;
138
139 return *(clk->rate);
140}
141EXPORT_SYMBOL(clk_get_rate);
142
143long clk_round_rate(struct clk *clk, unsigned long rate)
144{
145 if (clk == NULL || IS_ERR(clk))
146 return -EINVAL;
147
148 return *(clk->rate);
149}
150EXPORT_SYMBOL(clk_round_rate);
151
152int clk_set_rate(struct clk *clk, unsigned long rate)
153{
154 if (clk == NULL || IS_ERR(clk))
155 return -EINVAL;
156
157 /* changing the clk rate is not supported */
158 return -EINVAL;
159}
160EXPORT_SYMBOL(clk_set_rate);
161
162int clk_register(struct clk *clk)
163{
164 if (clk == NULL || IS_ERR(clk))
165 return -EINVAL;
166
167 mutex_lock(&clocks_mutex);
168 list_add(&clk->node, &clocks);
169 mutex_unlock(&clocks_mutex);
170
171 return 0;
172}
173EXPORT_SYMBOL(clk_register);
174
175void clk_unregister(struct clk *clk)
176{
177 if (clk == NULL || IS_ERR(clk))
178 return;
179
180 mutex_lock(&clocks_mutex);
181 list_del(&clk->node);
182 mutex_unlock(&clocks_mutex);
183}
184EXPORT_SYMBOL(clk_unregister);
185
186static struct clk davinci_clks[] = {
187 {
188 .name = "ARMCLK",
189 .rate = &armrate,
190 .lpsc = -1,
191 .flags = ALWAYS_ENABLED,
192 },
193 {
194 .name = "UART",
195 .rate = &fixedrate,
196 .lpsc = DAVINCI_LPSC_UART0,
197 },
198 {
199 .name = "EMACCLK",
200 .rate = &commonrate,
201 .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
202 },
203 {
204 .name = "I2CCLK",
205 .rate = &fixedrate,
206 .lpsc = DAVINCI_LPSC_I2C,
207 },
208 {
209 .name = "IDECLK",
210 .rate = &commonrate,
211 .lpsc = DAVINCI_LPSC_ATA,
212 },
213 {
214 .name = "McBSPCLK",
215 .rate = &commonrate,
216 .lpsc = DAVINCI_LPSC_McBSP,
217 },
218 {
219 .name = "MMCSDCLK",
220 .rate = &commonrate,
221 .lpsc = DAVINCI_LPSC_MMC_SD,
222 },
223 {
224 .name = "SPICLK",
225 .rate = &commonrate,
226 .lpsc = DAVINCI_LPSC_SPI,
227 },
228 {
229 .name = "gpio",
230 .rate = &commonrate,
231 .lpsc = DAVINCI_LPSC_GPIO,
232 },
233 {
234 .name = "AEMIFCLK",
235 .rate = &commonrate,
236 .lpsc = DAVINCI_LPSC_AEMIF,
237 .usecount = 1,
238 }
239};
240
241int __init davinci_clk_init(void)
242{
243 struct clk *clkp;
244 int count = 0;
245 u32 pll_mult;
246
247 pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
248 commonrate = ((pll_mult + 1) * 27000000) / 6;
249 armrate = ((pll_mult + 1) * 27000000) / 2;
250
251 for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
252 count++, clkp++) {
253 clk_register(clkp);
254
255 /* Turn on clocks that have been enabled in the
256 * table above */
257 if (clkp->usecount)
258 clk_enable(clkp);
259 }
260
261 return 0;
262}
263
264#ifdef CONFIG_PROC_FS
265#include <linux/proc_fs.h>
266#include <linux/seq_file.h>
267
268static void *davinci_ck_start(struct seq_file *m, loff_t *pos)
269{
270 return *pos < 1 ? (void *)1 : NULL;
271}
272
273static void *davinci_ck_next(struct seq_file *m, void *v, loff_t *pos)
274{
275 ++*pos;
276 return NULL;
277}
278
279static void davinci_ck_stop(struct seq_file *m, void *v)
280{
281}
282
283static int davinci_ck_show(struct seq_file *m, void *v)
284{
285 struct clk *cp;
286
287 list_for_each_entry(cp, &clocks, node)
288 seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
289
290 return 0;
291}
292
293static struct seq_operations davinci_ck_op = {
294 .start = davinci_ck_start,
295 .next = davinci_ck_next,
296 .stop = davinci_ck_stop,
297 .show = davinci_ck_show
298};
299
300static int davinci_ck_open(struct inode *inode, struct file *file)
301{
302 return seq_open(file, &davinci_ck_op);
303}
304
305static struct file_operations proc_davinci_ck_operations = {
306 .open = davinci_ck_open,
307 .read = seq_read,
308 .llseek = seq_lseek,
309 .release = seq_release,
310};
311
312static int __init davinci_ck_proc_init(void)
313{
314 struct proc_dir_entry *entry;
315
316 entry = create_proc_entry("davinci_clocks", 0, NULL);
317 if (entry)
318 entry->proc_fops = &proc_davinci_ck_operations;
319 return 0;
320
321}
322__initcall(davinci_ck_proc_init);
323#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
new file mode 100644
index 000000000000..ed47079a52e4
--- /dev/null
+++ b/arch/arm/mach-davinci/clock.h
@@ -0,0 +1,33 @@
1/*
2 * TI DaVinci clock definitions
3 *
4 * Copyright (C) 2006 Texas Instruments.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
12#define __ARCH_ARM_DAVINCI_CLOCK_H
13
14struct clk {
15 struct list_head node;
16 struct module *owner;
17 const char *name;
18 unsigned int *rate;
19 int id;
20 __s8 usecount;
21 __u8 flags;
22 __u8 lpsc;
23};
24
25/* Clock flags */
26#define RATE_CKCTL 1
27#define RATE_FIXED 2
28#define RATE_PROPAGATES 4
29#define VIRTUAL_CLOCK 8
30#define ALWAYS_ENABLED 16
31#define ENABLE_REG_32BIT 32
32
33#endif
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
new file mode 100644
index 000000000000..9c67886e7189
--- /dev/null
+++ b/arch/arm/mach-davinci/gpio.c
@@ -0,0 +1,286 @@
1/*
2 * TI DaVinci GPIO Support
3 *
4 * Copyright (c) 2006 David Brownell
5 * Copyright (c) 2007, MontaVista Software, Inc. <source@mvista.com>
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 as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13#include <linux/errno.h>
14#include <linux/kernel.h>
15#include <linux/list.h>
16#include <linux/module.h>
17#include <linux/clk.h>
18#include <linux/err.h>
19#include <linux/io.h>
20#include <linux/irq.h>
21#include <linux/bitops.h>
22
23#include <asm/arch/irqs.h>
24#include <asm/arch/hardware.h>
25#include <asm/arch/gpio.h>
26
27#include <asm/mach/irq.h>
28
29static DEFINE_SPINLOCK(gpio_lock);
30static DECLARE_BITMAP(gpio_in_use, DAVINCI_N_GPIO);
31
32int gpio_request(unsigned gpio, const char *tag)
33{
34 if (gpio >= DAVINCI_N_GPIO)
35 return -EINVAL;
36
37 if (test_and_set_bit(gpio, gpio_in_use))
38 return -EBUSY;
39
40 return 0;
41}
42EXPORT_SYMBOL(gpio_request);
43
44void gpio_free(unsigned gpio)
45{
46 if (gpio >= DAVINCI_N_GPIO)
47 return;
48
49 clear_bit(gpio, gpio_in_use);
50}
51EXPORT_SYMBOL(gpio_free);
52
53/* create a non-inlined version */
54static struct gpio_controller *__iomem gpio2controller(unsigned gpio)
55{
56 return __gpio_to_controller(gpio);
57}
58
59/*
60 * Assuming the pin is muxed as a gpio output, set its output value.
61 */
62void __gpio_set(unsigned gpio, int value)
63{
64 struct gpio_controller *__iomem g = gpio2controller(gpio);
65
66 __raw_writel(__gpio_mask(gpio), value ? &g->set_data : &g->clr_data);
67}
68EXPORT_SYMBOL(__gpio_set);
69
70
71/*
72 * Read the pin's value (works even if it's set up as output);
73 * returns zero/nonzero.
74 *
75 * Note that changes are synched to the GPIO clock, so reading values back
76 * right after you've set them may give old values.
77 */
78int __gpio_get(unsigned gpio)
79{
80 struct gpio_controller *__iomem g = gpio2controller(gpio);
81
82 return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
83}
84EXPORT_SYMBOL(__gpio_get);
85
86
87/*--------------------------------------------------------------------------*/
88
89/*
90 * board setup code *MUST* set PINMUX0 and PINMUX1 as
91 * needed, and enable the GPIO clock.
92 */
93
94int gpio_direction_input(unsigned gpio)
95{
96 struct gpio_controller *__iomem g = gpio2controller(gpio);
97 u32 temp;
98 u32 mask;
99
100 if (!g)
101 return -EINVAL;
102
103 spin_lock(&gpio_lock);
104 mask = __gpio_mask(gpio);
105 temp = __raw_readl(&g->dir);
106 temp |= mask;
107 __raw_writel(temp, &g->dir);
108 spin_unlock(&gpio_lock);
109 return 0;
110}
111EXPORT_SYMBOL(gpio_direction_input);
112
113int gpio_direction_output(unsigned gpio, int value)
114{
115 struct gpio_controller *__iomem g = gpio2controller(gpio);
116 u32 temp;
117 u32 mask;
118
119 if (!g)
120 return -EINVAL;
121
122 spin_lock(&gpio_lock);
123 mask = __gpio_mask(gpio);
124 temp = __raw_readl(&g->dir);
125 temp &= ~mask;
126 __raw_writel(mask, value ? &g->set_data : &g->clr_data);
127 __raw_writel(temp, &g->dir);
128 spin_unlock(&gpio_lock);
129 return 0;
130}
131EXPORT_SYMBOL(gpio_direction_output);
132
133/*
134 * We expect irqs will normally be set up as input pins, but they can also be
135 * used as output pins ... which is convenient for testing.
136 *
137 * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition
138 * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have
139 * a good way to hook those up ...
140 *
141 * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
142 * serve as EDMA event triggers.
143 */
144
145static void gpio_irq_disable(unsigned irq)
146{
147 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
148 u32 mask = __gpio_mask(irq_to_gpio(irq));
149
150 __raw_writel(mask, &g->clr_falling);
151 __raw_writel(mask, &g->clr_rising);
152}
153
154static void gpio_irq_enable(unsigned irq)
155{
156 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
157 u32 mask = __gpio_mask(irq_to_gpio(irq));
158
159 if (irq_desc[irq].status & IRQ_TYPE_EDGE_FALLING)
160 __raw_writel(mask, &g->set_falling);
161 if (irq_desc[irq].status & IRQ_TYPE_EDGE_RISING)
162 __raw_writel(mask, &g->set_rising);
163}
164
165static int gpio_irq_type(unsigned irq, unsigned trigger)
166{
167 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
168 u32 mask = __gpio_mask(irq_to_gpio(irq));
169
170 if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
171 return -EINVAL;
172
173 irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK;
174 irq_desc[irq].status |= trigger;
175
176 __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_FALLING)
177 ? &g->set_falling : &g->clr_falling);
178 __raw_writel(mask, (trigger & IRQ_TYPE_EDGE_RISING)
179 ? &g->set_rising : &g->clr_rising);
180 return 0;
181}
182
183static struct irq_chip gpio_irqchip = {
184 .name = "GPIO",
185 .enable = gpio_irq_enable,
186 .disable = gpio_irq_disable,
187 .set_type = gpio_irq_type,
188};
189
190static void
191gpio_irq_handler(unsigned irq, struct irq_desc *desc)
192{
193 struct gpio_controller *__iomem g = get_irq_chip_data(irq);
194 u32 mask = 0xffff;
195
196 /* we only care about one bank */
197 if (irq & 1)
198 mask <<= 16;
199
200 /* temporarily mask (level sensitive) parent IRQ */
201 desc->chip->ack(irq);
202 while (1) {
203 u32 status;
204 struct irq_desc *gpio;
205 int n;
206 int res;
207
208 /* ack any irqs */
209 status = __raw_readl(&g->intstat) & mask;
210 if (!status)
211 break;
212 __raw_writel(status, &g->intstat);
213 if (irq & 1)
214 status >>= 16;
215
216 /* now demux them to the right lowlevel handler */
217 n = (int)get_irq_data(irq);
218 gpio = &irq_desc[n];
219 while (status) {
220 res = ffs(status);
221 n += res;
222 gpio += res;
223 desc_handle_irq(n - 1, gpio - 1);
224 status >>= res;
225 }
226 }
227 desc->chip->unmask(irq);
228 /* now it may re-trigger */
229}
230
231/*
232 * NOTE: for suspend/resume, probably best to make a sysdev (and class)
233 * with its suspend/resume calls hooking into the results of the set_wake()
234 * calls ... so if no gpios are wakeup events the clock can be disabled,
235 * with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
236 * can be set appropriately for GPIOV33 pins.
237 */
238
239static int __init davinci_gpio_irq_setup(void)
240{
241 unsigned gpio, irq, bank;
242 struct clk *clk;
243
244 clk = clk_get(NULL, "gpio");
245 if (IS_ERR(clk)) {
246 printk(KERN_ERR "Error %ld getting gpio clock?\n",
247 PTR_ERR(clk));
248 return 0;
249 }
250
251 clk_enable(clk);
252
253 for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
254 gpio < DAVINCI_N_GPIO; bank++) {
255 struct gpio_controller *__iomem g = gpio2controller(gpio);
256 unsigned i;
257
258 __raw_writel(~0, &g->clr_falling);
259 __raw_writel(~0, &g->clr_rising);
260
261 /* set up all irqs in this bank */
262 set_irq_chained_handler(bank, gpio_irq_handler);
263 set_irq_chip_data(bank, g);
264 set_irq_data(bank, (void *)irq);
265
266 for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
267 i++, irq++, gpio++) {
268 set_irq_chip(irq, &gpio_irqchip);
269 set_irq_chip_data(irq, g);
270 set_irq_handler(irq, handle_simple_irq);
271 set_irq_flags(irq, IRQF_VALID);
272 }
273 }
274
275 /* BINTEN -- per-bank interrupt enable. genirq would also let these
276 * bits be set/cleared dynamically.
277 */
278 __raw_writel(0x1f, (void *__iomem)
279 IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
280
281 printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
282
283 return 0;
284}
285
286arch_initcall(davinci_gpio_irq_setup);
diff --git a/arch/arm/mach-davinci/io.c b/arch/arm/mach-davinci/io.c
index 87fae6fb6ecf..47787ff84a6a 100644
--- a/arch/arm/mach-davinci/io.c
+++ b/arch/arm/mach-davinci/io.c
@@ -17,6 +17,7 @@
17#include <asm/memory.h> 17#include <asm/memory.h>
18 18
19#include <asm/mach/map.h> 19#include <asm/mach/map.h>
20#include <asm/arch/clock.h>
20 21
21extern void davinci_check_revision(void); 22extern void davinci_check_revision(void);
22 23
@@ -49,3 +50,8 @@ void __init davinci_map_common_io(void)
49 */ 50 */
50 davinci_check_revision(); 51 davinci_check_revision();
51} 52}
53
54void __init davinci_init_common_hw(void)
55{
56 davinci_clk_init();
57}
diff --git a/arch/arm/mach-davinci/mux.c b/arch/arm/mach-davinci/mux.c
new file mode 100644
index 000000000000..92d26bd305b7
--- /dev/null
+++ b/arch/arm/mach-davinci/mux.c
@@ -0,0 +1,41 @@
1/*
2 * DaVinci pin multiplexing configurations
3 *
4 * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
5 *
6 * 2007 (c) MontaVista Software, Inc. This file is licensed under
7 * the terms of the GNU General Public License version 2. This program
8 * is licensed "as is" without any warranty of any kind, whether express
9 * or implied.
10 */
11#include <linux/io.h>
12#include <linux/spinlock.h>
13
14#include <asm/hardware.h>
15
16#include <asm/arch/mux.h>
17
18/* System control register offsets */
19#define PINMUX0 0x00
20#define PINMUX1 0x04
21
22static DEFINE_SPINLOCK(mux_lock);
23
24void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
25{
26 u32 pinmux, muxreg = PINMUX0;
27
28 if (mux >= DAVINCI_MUX_LEVEL2) {
29 muxreg = PINMUX1;
30 mux -= DAVINCI_MUX_LEVEL2;
31 }
32
33 spin_lock(&mux_lock);
34 pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
35 if (enable)
36 pinmux |= (1 << mux);
37 else
38 pinmux &= ~(1 << mux);
39 davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
40 spin_unlock(&mux_lock);
41}
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index e1b0050283a6..1334416559ad 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -25,39 +25,40 @@
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/hardware.h> 26#include <asm/hardware.h>
27#include <asm/arch/psc.h> 27#include <asm/arch/psc.h>
28#include <asm/arch/mux.h>
28 29
29#define PTCMD __REG(0x01C41120) 30/* PSC register offsets */
30#define PDSTAT __REG(0x01C41200) 31#define EPCPR 0x070
31#define PDCTL1 __REG(0x01C41304) 32#define PTCMD 0x120
32#define EPCPR __REG(0x01C41070) 33#define PTSTAT 0x128
33#define PTSTAT __REG(0x01C41128) 34#define PDSTAT 0x200
35#define PDCTL1 0x304
36#define MDSTAT 0x800
37#define MDCTL 0xA00
34 38
35#define MDSTAT IO_ADDRESS(0x01C41800) 39/* System control register offsets */
36#define MDCTL IO_ADDRESS(0x01C41A00) 40#define VDD3P3V_PWDN 0x48
37
38#define PINMUX0 __REG(0x01c40000)
39#define PINMUX1 __REG(0x01c40004)
40#define VDD3P3V_PWDN __REG(0x01C40048)
41 41
42static void davinci_psc_mux(unsigned int id) 42static void davinci_psc_mux(unsigned int id)
43{ 43{
44 switch (id) { 44 switch (id) {
45 case DAVINCI_LPSC_ATA: 45 case DAVINCI_LPSC_ATA:
46 PINMUX0 |= (1 << 17) | (1 << 16); 46 davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
47 davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
47 break; 48 break;
48 case DAVINCI_LPSC_MMC_SD: 49 case DAVINCI_LPSC_MMC_SD:
49 /* VDD power manupulations are done in U-Boot for CPMAC 50 /* VDD power manupulations are done in U-Boot for CPMAC
50 * so applies to MMC as well 51 * so applies to MMC as well
51 */ 52 */
52 /*Set up the pull regiter for MMC */ 53 /*Set up the pull regiter for MMC */
53 VDD3P3V_PWDN = 0x0; 54 davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
54 PINMUX1 &= (~(1 << 9)); 55 davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
55 break; 56 break;
56 case DAVINCI_LPSC_I2C: 57 case DAVINCI_LPSC_I2C:
57 PINMUX1 |= (1 << 7); 58 davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
58 break; 59 break;
59 case DAVINCI_LPSC_McBSP: 60 case DAVINCI_LPSC_McBSP:
60 PINMUX1 |= (1 << 10); 61 davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
61 break; 62 break;
62 default: 63 default:
63 break; 64 break;
@@ -67,33 +68,59 @@ static void davinci_psc_mux(unsigned int id)
67/* Enable or disable a PSC domain */ 68/* Enable or disable a PSC domain */
68void davinci_psc_config(unsigned int domain, unsigned int id, char enable) 69void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
69{ 70{
70 volatile unsigned int *mdstat = (unsigned int *)((int)MDSTAT + 4 * id); 71 u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
71 volatile unsigned int *mdctl = (unsigned int *)((int)MDCTL + 4 * id);
72 72
73 if (id < 0) 73 if (id < 0)
74 return; 74 return;
75 75
76 mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
76 if (enable) 77 if (enable)
77 *mdctl |= 0x00000003; /* Enable Module */ 78 mdctl |= 0x00000003; /* Enable Module */
78 else 79 else
79 *mdctl &= 0xFFFFFFF2; /* Disable Module */ 80 mdctl &= 0xFFFFFFF2; /* Disable Module */
81 davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
82
83 pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
84 if ((pdstat & 0x00000001) == 0) {
85 pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
86 pdctl1 |= 0x1;
87 davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
88
89 ptcmd = 1 << domain;
90 davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
80 91
81 if ((PDSTAT & 0x00000001) == 0) { 92 do {
82 PDCTL1 |= 0x1; 93 epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
83 PTCMD = (1 << domain); 94 EPCPR);
84 while ((((EPCPR >> domain) & 1) == 0)); 95 } while ((((epcpr >> domain) & 1) == 0));
85 96
86 PDCTL1 |= 0x100; 97 pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
87 while (!(((PTSTAT >> domain) & 1) == 0)); 98 pdctl1 |= 0x100;
99 davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
100
101 do {
102 ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
103 PTSTAT);
104 } while (!(((ptstat >> domain) & 1) == 0));
88 } else { 105 } else {
89 PTCMD = (1 << domain); 106 ptcmd = 1 << domain;
90 while (!(((PTSTAT >> domain) & 1) == 0)); 107 davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
108
109 do {
110 ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
111 PTSTAT);
112 } while (!(((ptstat >> domain) & 1) == 0));
91 } 113 }
92 114
93 if (enable) 115 if (enable)
94 while (!((*mdstat & 0x0000001F) == 0x3)); 116 mdstat_mask = 0x3;
95 else 117 else
96 while (!((*mdstat & 0x0000001F) == 0x2)); 118 mdstat_mask = 0x2;
119
120 do {
121 mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
122 MDSTAT + 4 * id);
123 } while (!((mdstat & 0x0000001F) == mdstat_mask));
97 124
98 if (enable) 125 if (enable)
99 davinci_psc_mux(id); 126 davinci_psc_mux(id);