aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/fsl_lbc.c
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2008-04-11 13:03:40 -0400
committerKumar Gala <galak@kernel.crashing.org>2008-04-17 02:01:38 -0400
commitacaa7aa30a8cdf7276945629f56d6daf30beb157 (patch)
tree8fa70d5f1417f3d6f48dbb4ceb671e48ad0f752d /arch/powerpc/sysdev/fsl_lbc.c
parentd4a32fe40a57d1a47d6ec3ebbf3d3153b12baa2c (diff)
[POWERPC] fsl_lbc: implement few UPM routines
Freescale UPM can be used to adjust localbus timings or to generate orbitrary, pre-programmed "patterns" on the external Localbus signals. This patch implements few routines so drivers could work with UPMs in safe and generic manner. So far there is just one user of these routines: Freescale UPM NAND driver. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/fsl_lbc.c')
-rw-r--r--arch/powerpc/sysdev/fsl_lbc.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
new file mode 100644
index 000000000000..422c8faef593
--- /dev/null
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -0,0 +1,129 @@
1/*
2 * Freescale LBC and UPM routines.
3 *
4 * Copyright (c) 2007-2008 MontaVista Software, Inc.
5 *
6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 */
13
14#include <linux/kernel.h>
15#include <linux/of.h>
16#include <asm/fsl_lbc.h>
17
18spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
19
20struct fsl_lbc_regs __iomem *fsl_lbc_regs;
21EXPORT_SYMBOL(fsl_lbc_regs);
22
23static char __initdata *compat_lbc[] = {
24 "fsl,pq2-localbus",
25 "fsl,pq2pro-localbus",
26 "fsl,pq3-localbus",
27 "fsl,elbc",
28};
29
30static int __init fsl_lbc_init(void)
31{
32 struct device_node *lbus;
33 int i;
34
35 for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
36 lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
37 if (lbus)
38 goto found;
39 }
40 return -ENODEV;
41
42found:
43 fsl_lbc_regs = of_iomap(lbus, 0);
44 of_node_put(lbus);
45 if (!fsl_lbc_regs)
46 return -ENOMEM;
47 return 0;
48}
49arch_initcall(fsl_lbc_init);
50
51/**
52 * fsl_lbc_find - find Localbus bank
53 * @addr_base: base address of the memory bank
54 *
55 * This function walks LBC banks comparing "Base address" field of the BR
56 * registers with the supplied addr_base argument. When bases match this
57 * function returns bank number (starting with 0), otherwise it returns
58 * appropriate errno value.
59 */
60int fsl_lbc_find(phys_addr_t addr_base)
61{
62 int i;
63
64 if (!fsl_lbc_regs)
65 return -ENODEV;
66
67 for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
68 __be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
69 __be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
70
71 if (br & BR_V && (br & or & BR_BA) == addr_base)
72 return i;
73 }
74
75 return -ENOENT;
76}
77EXPORT_SYMBOL(fsl_lbc_find);
78
79/**
80 * fsl_upm_find - find pre-programmed UPM via base address
81 * @addr_base: base address of the memory bank controlled by the UPM
82 * @upm: pointer to the allocated fsl_upm structure
83 *
84 * This function fills fsl_upm structure so you can use it with the rest of
85 * UPM API. On success this function returns 0, otherwise it returns
86 * appropriate errno value.
87 */
88int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
89{
90 int bank;
91 __be32 br;
92
93 bank = fsl_lbc_find(addr_base);
94 if (bank < 0)
95 return bank;
96
97 br = in_be32(&fsl_lbc_regs->bank[bank].br);
98
99 switch (br & BR_MSEL) {
100 case BR_MS_UPMA:
101 upm->mxmr = &fsl_lbc_regs->mamr;
102 break;
103 case BR_MS_UPMB:
104 upm->mxmr = &fsl_lbc_regs->mbmr;
105 break;
106 case BR_MS_UPMC:
107 upm->mxmr = &fsl_lbc_regs->mcmr;
108 break;
109 default:
110 return -EINVAL;
111 }
112
113 switch (br & BR_PS) {
114 case BR_PS_8:
115 upm->width = 8;
116 break;
117 case BR_PS_16:
118 upm->width = 16;
119 break;
120 case BR_PS_32:
121 upm->width = 32;
122 break;
123 default:
124 return -EINVAL;
125 }
126
127 return 0;
128}
129EXPORT_SYMBOL(fsl_upm_find);