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/init.h> 15 #include <linux/module.h> 16 #include <linux/kernel.h> 17 #include <linux/compiler.h> 18 #include <linux/spinlock.h> 19 #include <linux/types.h> 20 #include <linux/io.h> 21 #include <linux/of.h> 22 #include <asm/prom.h> 23 #include <asm/fsl_lbc.h> 24 25 static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); 26 static struct fsl_lbc_regs __iomem *fsl_lbc_regs; 27 28 static char __initdata *compat_lbc[] = { 29 "fsl,pq2-localbus", 30 "fsl,pq2pro-localbus", 31 "fsl,pq3-localbus", 32 "fsl,elbc", 33 }; 34 35 static int __init fsl_lbc_init(void) 36 { 37 struct device_node *lbus; 38 int i; 39 40 for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) { 41 lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]); 42 if (lbus) 43 goto found; 44 } 45 return -ENODEV; 46 47 found: 48 fsl_lbc_regs = of_iomap(lbus, 0); 49 of_node_put(lbus); 50 if (!fsl_lbc_regs) 51 return -ENOMEM; 52 return 0; 53 } 54 arch_initcall(fsl_lbc_init); 55 56 /** 57 * fsl_lbc_find - find Localbus bank 58 * @addr_base: base address of the memory bank 59 * 60 * This function walks LBC banks comparing "Base address" field of the BR 61 * registers with the supplied addr_base argument. When bases match this 62 * function returns bank number (starting with 0), otherwise it returns 63 * appropriate errno value. 64 */ 65 int fsl_lbc_find(phys_addr_t addr_base) 66 { 67 int i; 68 69 if (!fsl_lbc_regs) 70 return -ENODEV; 71 72 for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) { 73 __be32 br = in_be32(&fsl_lbc_regs->bank[i].br); 74 __be32 or = in_be32(&fsl_lbc_regs->bank[i].or); 75 76 if (br & BR_V && (br & or & BR_BA) == addr_base) 77 return i; 78 } 79 80 return -ENOENT; 81 } 82 EXPORT_SYMBOL(fsl_lbc_find); 83 84 /** 85 * fsl_upm_find - find pre-programmed UPM via base address 86 * @addr_base: base address of the memory bank controlled by the UPM 87 * @upm: pointer to the allocated fsl_upm structure 88 * 89 * This function fills fsl_upm structure so you can use it with the rest of 90 * UPM API. On success this function returns 0, otherwise it returns 91 * appropriate errno value. 92 */ 93 int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm) 94 { 95 int bank; 96 __be32 br; 97 98 bank = fsl_lbc_find(addr_base); 99 if (bank < 0) 100 return bank; 101 102 br = in_be32(&fsl_lbc_regs->bank[bank].br); 103 104 switch (br & BR_MSEL) { 105 case BR_MS_UPMA: 106 upm->mxmr = &fsl_lbc_regs->mamr; 107 break; 108 case BR_MS_UPMB: 109 upm->mxmr = &fsl_lbc_regs->mbmr; 110 break; 111 case BR_MS_UPMC: 112 upm->mxmr = &fsl_lbc_regs->mcmr; 113 break; 114 default: 115 return -EINVAL; 116 } 117 118 switch (br & BR_PS) { 119 case BR_PS_8: 120 upm->width = 8; 121 break; 122 case BR_PS_16: 123 upm->width = 16; 124 break; 125 case BR_PS_32: 126 upm->width = 32; 127 break; 128 default: 129 return -EINVAL; 130 } 131 132 return 0; 133 } 134 EXPORT_SYMBOL(fsl_upm_find); 135 136 /** 137 * fsl_upm_run_pattern - actually run an UPM pattern 138 * @upm: pointer to the fsl_upm structure obtained via fsl_upm_find 139 * @io_base: remapped pointer to where memory access should happen 140 * @mar: MAR register content during pattern execution 141 * 142 * This function triggers dummy write to the memory specified by the io_base, 143 * thus UPM pattern actually executed. Note that mar usage depends on the 144 * pre-programmed AMX bits in the UPM RAM. 145 */ 146 int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar) 147 { 148 int ret = 0; 149 unsigned long flags; 150 151 spin_lock_irqsave(&fsl_lbc_lock, flags); 152 153 out_be32(&fsl_lbc_regs->mar, mar); 154 155 switch (upm->width) { 156 case 8: 157 out_8(io_base, 0x0); 158 break; 159 case 16: 160 out_be16(io_base, 0x0); 161 break; 162 case 32: 163 out_be32(io_base, 0x0); 164 break; 165 default: 166 ret = -EINVAL; 167 break; 168 } 169 170 spin_unlock_irqrestore(&fsl_lbc_lock, flags); 171 172 return ret; 173 } 174 EXPORT_SYMBOL(fsl_upm_run_pattern); 175