Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/mips/bcm63xx/cs.c
26439 views
1
/*
2
* This file is subject to the terms and conditions of the GNU General Public
3
* License. See the file "COPYING" in the main directory of this archive
4
* for more details.
5
*
6
* Copyright (C) 2008 Maxime Bizon <[email protected]>
7
*/
8
9
#include <linux/kernel.h>
10
#include <linux/errno.h>
11
#include <linux/export.h>
12
#include <linux/spinlock.h>
13
#include <linux/log2.h>
14
#include <bcm63xx_cpu.h>
15
#include <bcm63xx_io.h>
16
#include <bcm63xx_regs.h>
17
#include <bcm63xx_cs.h>
18
19
static DEFINE_SPINLOCK(bcm63xx_cs_lock);
20
21
/*
22
* check if given chip select exists
23
*/
24
static int is_valid_cs(unsigned int cs)
25
{
26
if (cs > 6)
27
return 0;
28
return 1;
29
}
30
31
/*
32
* Configure chipselect base address and size (bytes).
33
* Size must be a power of two between 8k and 256M.
34
*/
35
int bcm63xx_set_cs_base(unsigned int cs, u32 base, unsigned int size)
36
{
37
unsigned long flags;
38
u32 val;
39
40
if (!is_valid_cs(cs))
41
return -EINVAL;
42
43
/* sanity check on size */
44
if (size != roundup_pow_of_two(size))
45
return -EINVAL;
46
47
if (size < 8 * 1024 || size > 256 * 1024 * 1024)
48
return -EINVAL;
49
50
val = (base & MPI_CSBASE_BASE_MASK);
51
/* 8k => 0 - 256M => 15 */
52
val |= (ilog2(size) - ilog2(8 * 1024)) << MPI_CSBASE_SIZE_SHIFT;
53
54
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
55
bcm_mpi_writel(val, MPI_CSBASE_REG(cs));
56
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
57
58
return 0;
59
}
60
61
EXPORT_SYMBOL(bcm63xx_set_cs_base);
62
63
/*
64
* configure chipselect timing (ns)
65
*/
66
int bcm63xx_set_cs_timing(unsigned int cs, unsigned int wait,
67
unsigned int setup, unsigned int hold)
68
{
69
unsigned long flags;
70
u32 val;
71
72
if (!is_valid_cs(cs))
73
return -EINVAL;
74
75
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
76
val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
77
val &= ~(MPI_CSCTL_WAIT_MASK);
78
val &= ~(MPI_CSCTL_SETUP_MASK);
79
val &= ~(MPI_CSCTL_HOLD_MASK);
80
val |= wait << MPI_CSCTL_WAIT_SHIFT;
81
val |= setup << MPI_CSCTL_SETUP_SHIFT;
82
val |= hold << MPI_CSCTL_HOLD_SHIFT;
83
bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
84
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
85
86
return 0;
87
}
88
89
EXPORT_SYMBOL(bcm63xx_set_cs_timing);
90
91
/*
92
* configure other chipselect parameter (data bus size, ...)
93
*/
94
int bcm63xx_set_cs_param(unsigned int cs, u32 params)
95
{
96
unsigned long flags;
97
u32 val;
98
99
if (!is_valid_cs(cs))
100
return -EINVAL;
101
102
/* none of this fields apply to pcmcia */
103
if (cs == MPI_CS_PCMCIA_COMMON ||
104
cs == MPI_CS_PCMCIA_ATTR ||
105
cs == MPI_CS_PCMCIA_IO)
106
return -EINVAL;
107
108
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
109
val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
110
val &= ~(MPI_CSCTL_DATA16_MASK);
111
val &= ~(MPI_CSCTL_SYNCMODE_MASK);
112
val &= ~(MPI_CSCTL_TSIZE_MASK);
113
val &= ~(MPI_CSCTL_ENDIANSWAP_MASK);
114
val |= params;
115
bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
116
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
117
118
return 0;
119
}
120
121
EXPORT_SYMBOL(bcm63xx_set_cs_param);
122
123
/*
124
* set cs status (enable/disable)
125
*/
126
int bcm63xx_set_cs_status(unsigned int cs, int enable)
127
{
128
unsigned long flags;
129
u32 val;
130
131
if (!is_valid_cs(cs))
132
return -EINVAL;
133
134
spin_lock_irqsave(&bcm63xx_cs_lock, flags);
135
val = bcm_mpi_readl(MPI_CSCTL_REG(cs));
136
if (enable)
137
val |= MPI_CSCTL_ENABLE_MASK;
138
else
139
val &= ~MPI_CSCTL_ENABLE_MASK;
140
bcm_mpi_writel(val, MPI_CSCTL_REG(cs));
141
spin_unlock_irqrestore(&bcm63xx_cs_lock, flags);
142
return 0;
143
}
144
145
EXPORT_SYMBOL(bcm63xx_set_cs_status);
146
147