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 18 spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); 19 20 struct fsl_lbc_regs __iomem *fsl_lbc_regs; 21 EXPORT_SYMBOL(fsl_lbc_regs); 22 23 static char __initdata *compat_lbc[] = { 24 "fsl,pq2-localbus", 25 "fsl,pq2pro-localbus", 26 "fsl,pq3-localbus", 27 "fsl,elbc", 28 }; 29 30 static 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 42 found: 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 } 49 arch_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 */ 60 int 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 } 77 EXPORT_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 */ 88 int 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 } 129 EXPORT_SYMBOL(fsl_upm_find); 130