0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/kernel.h>
0010 #include <linux/errno.h>
0011 #include <linux/export.h>
0012 #include <linux/spinlock.h>
0013 #include <linux/log2.h>
0014 #include <bcm63xx_cpu.h>
0015 #include <bcm63xx_io.h>
0016 #include <bcm63xx_regs.h>
0017 #include <bcm63xx_cs.h>
0018
0019 static DEFINE_SPINLOCK(bcm63xx_cs_lock);
0020
0021
0022
0023
0024 static int is_valid_cs(unsigned int cs)
0025 {
0026 if (cs > 6)
0027 return 0;
0028 return 1;
0029 }
0030
0031
0032
0033
0034
0035 int bcm63xx_set_cs_base(unsigned int cs, u32 base, unsigned int size)
0036 {
0037 unsigned long flags;
0038 u32 val;
0039
0040 if (!is_valid_cs(cs))
0041 return -EINVAL;
0042
0043
0044 if (size != roundup_pow_of_two(size))
0045 return -EINVAL;
0046
0047 if (size < 8 * 1024 || size > 256 * 1024 * 1024)
0048 return -EINVAL;
0049
0050 val = (base & MPI_CSBASE_BASE_MASK);
0051
0052 val |= (ilog2(size) - ilog2(8 * 1024)) << MPI_CSBASE_SIZE_SHIFT;
0053
0054 spin_lock_irqsave(&bcm63xx_cs_lock, flags);
0055 bcm_mpi_writel(val, MPI_CSBASE_REG(cs));
0056 spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
0057
0058 return 0;
0059 }
0060
0061 EXPORT_SYMBOL(bcm63xx_set_cs_base);
0062
0063
0064
0065
0066 int bcm63xx_set_cs_timing(unsigned int cs, unsigned int wait,
0067 unsigned int setup, unsigned int hold)
0068 {
0069 unsigned long flags;
0070 u32 val;
0071
0072 if (!is_valid_cs(cs))
0073 return -EINVAL;
0074
0075 spin_lock_irqsave(&bcm63xx_cs_lock, flags);
0076 val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
0077 val &= ~(MPI_CSCTL_WAIT_MASK);
0078 val &= ~(MPI_CSCTL_SETUP_MASK);
0079 val &= ~(MPI_CSCTL_HOLD_MASK);
0080 val |= wait << MPI_CSCTL_WAIT_SHIFT;
0081 val |= setup << MPI_CSCTL_SETUP_SHIFT;
0082 val |= hold << MPI_CSCTL_HOLD_SHIFT;
0083 bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
0084 spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
0085
0086 return 0;
0087 }
0088
0089 EXPORT_SYMBOL(bcm63xx_set_cs_timing);
0090
0091
0092
0093
0094 int bcm63xx_set_cs_param(unsigned int cs, u32 params)
0095 {
0096 unsigned long flags;
0097 u32 val;
0098
0099 if (!is_valid_cs(cs))
0100 return -EINVAL;
0101
0102
0103 if (cs == MPI_CS_PCMCIA_COMMON ||
0104 cs == MPI_CS_PCMCIA_ATTR ||
0105 cs == MPI_CS_PCMCIA_IO)
0106 return -EINVAL;
0107
0108 spin_lock_irqsave(&bcm63xx_cs_lock, flags);
0109 val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
0110 val &= ~(MPI_CSCTL_DATA16_MASK);
0111 val &= ~(MPI_CSCTL_SYNCMODE_MASK);
0112 val &= ~(MPI_CSCTL_TSIZE_MASK);
0113 val &= ~(MPI_CSCTL_ENDIANSWAP_MASK);
0114 val |= params;
0115 bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
0116 spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
0117
0118 return 0;
0119 }
0120
0121 EXPORT_SYMBOL(bcm63xx_set_cs_param);
0122
0123
0124
0125
0126 int bcm63xx_set_cs_status(unsigned int cs, int enable)
0127 {
0128 unsigned long flags;
0129 u32 val;
0130
0131 if (!is_valid_cs(cs))
0132 return -EINVAL;
0133
0134 spin_lock_irqsave(&bcm63xx_cs_lock, flags);
0135 val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
0136 if (enable)
0137 val |= MPI_CSCTL_ENABLE_MASK;
0138 else
0139 val &= ~MPI_CSCTL_ENABLE_MASK;
0140 bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
0141 spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
0142 return 0;
0143 }
0144
0145 EXPORT_SYMBOL(bcm63xx_set_cs_status);