0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <linux/errno.h>
0029 #include <linux/sched.h>
0030 #include <linux/kernel.h>
0031 #include <linux/param.h>
0032 #include <linux/string.h>
0033 #include <linux/mm.h>
0034 #include <linux/interrupt.h>
0035 #include <linux/module.h>
0036 #include <linux/of.h>
0037
0038 #include <asm/io.h>
0039 #include <asm/irq.h>
0040 #include <asm/mpc8260.h>
0041 #include <asm/page.h>
0042 #include <asm/cpm2.h>
0043 #include <asm/rheap.h>
0044 #include <asm/fs_pd.h>
0045
0046 #include <sysdev/fsl_soc.h>
0047
0048 cpm_cpm2_t __iomem *cpmp;
0049
0050
0051
0052
0053 cpm2_map_t __iomem *cpm2_immr;
0054 EXPORT_SYMBOL(cpm2_immr);
0055
0056 #define CPM_MAP_SIZE (0x40000)
0057
0058
0059
0060 void __init cpm2_reset(void)
0061 {
0062 #ifdef CONFIG_PPC_85xx
0063 cpm2_immr = ioremap(get_immrbase() + 0x80000, CPM_MAP_SIZE);
0064 #else
0065 cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
0066 #endif
0067
0068
0069
0070 cpmp = &cpm2_immr->im_cpm;
0071
0072 #ifndef CONFIG_PPC_EARLY_DEBUG_CPM
0073
0074
0075 cpm_command(CPM_CR_RST, 0);
0076 #endif
0077 }
0078
0079 static DEFINE_SPINLOCK(cmd_lock);
0080
0081 #define MAX_CR_CMD_LOOPS 10000
0082
0083 int cpm_command(u32 command, u8 opcode)
0084 {
0085 int i, ret;
0086 unsigned long flags;
0087
0088 spin_lock_irqsave(&cmd_lock, flags);
0089
0090 ret = 0;
0091 out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
0092 for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
0093 if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
0094 goto out;
0095
0096 printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
0097 ret = -EIO;
0098 out:
0099 spin_unlock_irqrestore(&cmd_lock, flags);
0100 return ret;
0101 }
0102 EXPORT_SYMBOL(cpm_command);
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114 void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)
0115 {
0116 u32 __iomem *bp;
0117 u32 val;
0118
0119
0120
0121 if (brg < 4) {
0122 bp = cpm2_map_size(im_brgc1, 16);
0123 } else {
0124 bp = cpm2_map_size(im_brgc5, 16);
0125 brg -= 4;
0126 }
0127 bp += brg;
0128
0129 val = (((clk * 2 / rate) - 1) & ~1) | CPM_BRG_EN | src;
0130 if (div16)
0131 val |= CPM_BRG_DIV16;
0132
0133 out_be32(bp, val);
0134 cpm2_unmap(bp);
0135 }
0136 EXPORT_SYMBOL(__cpm2_setbrg);
0137
0138 int __init cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
0139 {
0140 int ret = 0;
0141 int shift;
0142 int i, bits = 0;
0143 cpmux_t __iomem *im_cpmux;
0144 u32 __iomem *reg;
0145 u32 mask = 7;
0146
0147 u8 clk_map[][3] = {
0148 {CPM_CLK_FCC1, CPM_BRG5, 0},
0149 {CPM_CLK_FCC1, CPM_BRG6, 1},
0150 {CPM_CLK_FCC1, CPM_BRG7, 2},
0151 {CPM_CLK_FCC1, CPM_BRG8, 3},
0152 {CPM_CLK_FCC1, CPM_CLK9, 4},
0153 {CPM_CLK_FCC1, CPM_CLK10, 5},
0154 {CPM_CLK_FCC1, CPM_CLK11, 6},
0155 {CPM_CLK_FCC1, CPM_CLK12, 7},
0156 {CPM_CLK_FCC2, CPM_BRG5, 0},
0157 {CPM_CLK_FCC2, CPM_BRG6, 1},
0158 {CPM_CLK_FCC2, CPM_BRG7, 2},
0159 {CPM_CLK_FCC2, CPM_BRG8, 3},
0160 {CPM_CLK_FCC2, CPM_CLK13, 4},
0161 {CPM_CLK_FCC2, CPM_CLK14, 5},
0162 {CPM_CLK_FCC2, CPM_CLK15, 6},
0163 {CPM_CLK_FCC2, CPM_CLK16, 7},
0164 {CPM_CLK_FCC3, CPM_BRG5, 0},
0165 {CPM_CLK_FCC3, CPM_BRG6, 1},
0166 {CPM_CLK_FCC3, CPM_BRG7, 2},
0167 {CPM_CLK_FCC3, CPM_BRG8, 3},
0168 {CPM_CLK_FCC3, CPM_CLK13, 4},
0169 {CPM_CLK_FCC3, CPM_CLK14, 5},
0170 {CPM_CLK_FCC3, CPM_CLK15, 6},
0171 {CPM_CLK_FCC3, CPM_CLK16, 7},
0172 {CPM_CLK_SCC1, CPM_BRG1, 0},
0173 {CPM_CLK_SCC1, CPM_BRG2, 1},
0174 {CPM_CLK_SCC1, CPM_BRG3, 2},
0175 {CPM_CLK_SCC1, CPM_BRG4, 3},
0176 {CPM_CLK_SCC1, CPM_CLK11, 4},
0177 {CPM_CLK_SCC1, CPM_CLK12, 5},
0178 {CPM_CLK_SCC1, CPM_CLK3, 6},
0179 {CPM_CLK_SCC1, CPM_CLK4, 7},
0180 {CPM_CLK_SCC2, CPM_BRG1, 0},
0181 {CPM_CLK_SCC2, CPM_BRG2, 1},
0182 {CPM_CLK_SCC2, CPM_BRG3, 2},
0183 {CPM_CLK_SCC2, CPM_BRG4, 3},
0184 {CPM_CLK_SCC2, CPM_CLK11, 4},
0185 {CPM_CLK_SCC2, CPM_CLK12, 5},
0186 {CPM_CLK_SCC2, CPM_CLK3, 6},
0187 {CPM_CLK_SCC2, CPM_CLK4, 7},
0188 {CPM_CLK_SCC3, CPM_BRG1, 0},
0189 {CPM_CLK_SCC3, CPM_BRG2, 1},
0190 {CPM_CLK_SCC3, CPM_BRG3, 2},
0191 {CPM_CLK_SCC3, CPM_BRG4, 3},
0192 {CPM_CLK_SCC3, CPM_CLK5, 4},
0193 {CPM_CLK_SCC3, CPM_CLK6, 5},
0194 {CPM_CLK_SCC3, CPM_CLK7, 6},
0195 {CPM_CLK_SCC3, CPM_CLK8, 7},
0196 {CPM_CLK_SCC4, CPM_BRG1, 0},
0197 {CPM_CLK_SCC4, CPM_BRG2, 1},
0198 {CPM_CLK_SCC4, CPM_BRG3, 2},
0199 {CPM_CLK_SCC4, CPM_BRG4, 3},
0200 {CPM_CLK_SCC4, CPM_CLK5, 4},
0201 {CPM_CLK_SCC4, CPM_CLK6, 5},
0202 {CPM_CLK_SCC4, CPM_CLK7, 6},
0203 {CPM_CLK_SCC4, CPM_CLK8, 7},
0204 };
0205
0206 im_cpmux = cpm2_map(im_cpmux);
0207
0208 switch (target) {
0209 case CPM_CLK_SCC1:
0210 reg = &im_cpmux->cmx_scr;
0211 shift = 24;
0212 break;
0213 case CPM_CLK_SCC2:
0214 reg = &im_cpmux->cmx_scr;
0215 shift = 16;
0216 break;
0217 case CPM_CLK_SCC3:
0218 reg = &im_cpmux->cmx_scr;
0219 shift = 8;
0220 break;
0221 case CPM_CLK_SCC4:
0222 reg = &im_cpmux->cmx_scr;
0223 shift = 0;
0224 break;
0225 case CPM_CLK_FCC1:
0226 reg = &im_cpmux->cmx_fcr;
0227 shift = 24;
0228 break;
0229 case CPM_CLK_FCC2:
0230 reg = &im_cpmux->cmx_fcr;
0231 shift = 16;
0232 break;
0233 case CPM_CLK_FCC3:
0234 reg = &im_cpmux->cmx_fcr;
0235 shift = 8;
0236 break;
0237 default:
0238 printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
0239 return -EINVAL;
0240 }
0241
0242 for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
0243 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
0244 bits = clk_map[i][2];
0245 break;
0246 }
0247 }
0248 if (i == ARRAY_SIZE(clk_map))
0249 ret = -EINVAL;
0250
0251 bits <<= shift;
0252 mask <<= shift;
0253
0254 if (mode == CPM_CLK_RTX) {
0255 bits |= bits << 3;
0256 mask |= mask << 3;
0257 } else if (mode == CPM_CLK_RX) {
0258 bits <<= 3;
0259 mask <<= 3;
0260 }
0261
0262 out_be32(reg, (in_be32(reg) & ~mask) | bits);
0263
0264 cpm2_unmap(im_cpmux);
0265 return ret;
0266 }
0267
0268 int __init cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
0269 {
0270 int ret = 0;
0271 int shift;
0272 int i, bits = 0;
0273 cpmux_t __iomem *im_cpmux;
0274 u8 __iomem *reg;
0275 u8 mask = 3;
0276
0277 u8 clk_map[][3] = {
0278 {CPM_CLK_SMC1, CPM_BRG1, 0},
0279 {CPM_CLK_SMC1, CPM_BRG7, 1},
0280 {CPM_CLK_SMC1, CPM_CLK7, 2},
0281 {CPM_CLK_SMC1, CPM_CLK9, 3},
0282 {CPM_CLK_SMC2, CPM_BRG2, 0},
0283 {CPM_CLK_SMC2, CPM_BRG8, 1},
0284 {CPM_CLK_SMC2, CPM_CLK4, 2},
0285 {CPM_CLK_SMC2, CPM_CLK15, 3},
0286 };
0287
0288 im_cpmux = cpm2_map(im_cpmux);
0289
0290 switch (target) {
0291 case CPM_CLK_SMC1:
0292 reg = &im_cpmux->cmx_smr;
0293 mask = 3;
0294 shift = 4;
0295 break;
0296 case CPM_CLK_SMC2:
0297 reg = &im_cpmux->cmx_smr;
0298 mask = 3;
0299 shift = 0;
0300 break;
0301 default:
0302 printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
0303 return -EINVAL;
0304 }
0305
0306 for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
0307 if (clk_map[i][0] == target && clk_map[i][1] == clock) {
0308 bits = clk_map[i][2];
0309 break;
0310 }
0311 }
0312 if (i == ARRAY_SIZE(clk_map))
0313 ret = -EINVAL;
0314
0315 bits <<= shift;
0316 mask <<= shift;
0317
0318 out_8(reg, (in_8(reg) & ~mask) | bits);
0319
0320 cpm2_unmap(im_cpmux);
0321 return ret;
0322 }
0323
0324 struct cpm2_ioports {
0325 u32 dir, par, sor, odr, dat;
0326 u32 res[3];
0327 };
0328
0329 void __init cpm2_set_pin(int port, int pin, int flags)
0330 {
0331 struct cpm2_ioports __iomem *iop =
0332 (struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
0333
0334 pin = 1 << (31 - pin);
0335
0336 if (flags & CPM_PIN_OUTPUT)
0337 setbits32(&iop[port].dir, pin);
0338 else
0339 clrbits32(&iop[port].dir, pin);
0340
0341 if (!(flags & CPM_PIN_GPIO))
0342 setbits32(&iop[port].par, pin);
0343 else
0344 clrbits32(&iop[port].par, pin);
0345
0346 if (flags & CPM_PIN_SECONDARY)
0347 setbits32(&iop[port].sor, pin);
0348 else
0349 clrbits32(&iop[port].sor, pin);
0350
0351 if (flags & CPM_PIN_OPENDRAIN)
0352 setbits32(&iop[port].odr, pin);
0353 else
0354 clrbits32(&iop[port].odr, pin);
0355 }