diff options
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 791 |
1 files changed, 605 insertions, 186 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index e664b912d7bb..e1d0440fd4a8 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -23,68 +23,102 @@ | |||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | #include <linux/slab.h> | ||
26 | 27 | ||
27 | #include <mach/dma.h> | 28 | #include <plat/dma.h> |
28 | #include <mach/mcbsp.h> | 29 | #include <plat/mcbsp.h> |
30 | |||
31 | #include "../mach-omap2/cm-regbits-34xx.h" | ||
29 | 32 | ||
30 | struct omap_mcbsp **mcbsp_ptr; | 33 | struct omap_mcbsp **mcbsp_ptr; |
31 | int omap_mcbsp_count; | 34 | int omap_mcbsp_count, omap_mcbsp_cache_size; |
32 | 35 | ||
33 | void omap_mcbsp_write(void __iomem *io_base, u16 reg, u32 val) | 36 | void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) |
34 | { | 37 | { |
35 | if (cpu_class_is_omap1() || cpu_is_omap2420()) | 38 | if (cpu_class_is_omap1()) { |
36 | __raw_writew((u16)val, io_base + reg); | 39 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)] = (u16)val; |
37 | else | 40 | __raw_writew((u16)val, mcbsp->io_base + reg); |
38 | __raw_writel(val, io_base + reg); | 41 | } else if (cpu_is_omap2420()) { |
42 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)] = (u16)val; | ||
43 | __raw_writew((u16)val, mcbsp->io_base + reg); | ||
44 | } else { | ||
45 | ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)] = val; | ||
46 | __raw_writel(val, mcbsp->io_base + reg); | ||
47 | } | ||
39 | } | 48 | } |
40 | 49 | ||
41 | int omap_mcbsp_read(void __iomem *io_base, u16 reg) | 50 | int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache) |
42 | { | 51 | { |
43 | if (cpu_class_is_omap1() || cpu_is_omap2420()) | 52 | if (cpu_class_is_omap1()) { |
44 | return __raw_readw(io_base + reg); | 53 | return !from_cache ? __raw_readw(mcbsp->io_base + reg) : |
45 | else | 54 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u16)]; |
46 | return __raw_readl(io_base + reg); | 55 | } else if (cpu_is_omap2420()) { |
56 | return !from_cache ? __raw_readw(mcbsp->io_base + reg) : | ||
57 | ((u16 *)mcbsp->reg_cache)[reg / sizeof(u32)]; | ||
58 | } else { | ||
59 | return !from_cache ? __raw_readl(mcbsp->io_base + reg) : | ||
60 | ((u32 *)mcbsp->reg_cache)[reg / sizeof(u32)]; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | #ifdef CONFIG_ARCH_OMAP3 | ||
65 | void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val) | ||
66 | { | ||
67 | __raw_writel(val, mcbsp->st_data->io_base_st + reg); | ||
47 | } | 68 | } |
48 | 69 | ||
49 | #define OMAP_MCBSP_READ(base, reg) \ | 70 | int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg) |
50 | omap_mcbsp_read(base, OMAP_MCBSP_REG_##reg) | 71 | { |
51 | #define OMAP_MCBSP_WRITE(base, reg, val) \ | 72 | return __raw_readl(mcbsp->st_data->io_base_st + reg); |
52 | omap_mcbsp_write(base, OMAP_MCBSP_REG_##reg, val) | 73 | } |
74 | #endif | ||
75 | |||
76 | #define MCBSP_READ(mcbsp, reg) \ | ||
77 | omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0) | ||
78 | #define MCBSP_WRITE(mcbsp, reg, val) \ | ||
79 | omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val) | ||
80 | #define MCBSP_READ_CACHE(mcbsp, reg) \ | ||
81 | omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1) | ||
53 | 82 | ||
54 | #define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) | 83 | #define omap_mcbsp_check_valid_id(id) (id < omap_mcbsp_count) |
55 | #define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; | 84 | #define id_to_mcbsp_ptr(id) mcbsp_ptr[id]; |
56 | 85 | ||
86 | #define MCBSP_ST_READ(mcbsp, reg) \ | ||
87 | omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg) | ||
88 | #define MCBSP_ST_WRITE(mcbsp, reg, val) \ | ||
89 | omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val) | ||
90 | |||
57 | static void omap_mcbsp_dump_reg(u8 id) | 91 | static void omap_mcbsp_dump_reg(u8 id) |
58 | { | 92 | { |
59 | struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); | 93 | struct omap_mcbsp *mcbsp = id_to_mcbsp_ptr(id); |
60 | 94 | ||
61 | dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id); | 95 | dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id); |
62 | dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", | 96 | dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n", |
63 | OMAP_MCBSP_READ(mcbsp->io_base, DRR2)); | 97 | MCBSP_READ(mcbsp, DRR2)); |
64 | dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n", | 98 | dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n", |
65 | OMAP_MCBSP_READ(mcbsp->io_base, DRR1)); | 99 | MCBSP_READ(mcbsp, DRR1)); |
66 | dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n", | 100 | dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n", |
67 | OMAP_MCBSP_READ(mcbsp->io_base, DXR2)); | 101 | MCBSP_READ(mcbsp, DXR2)); |
68 | dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n", | 102 | dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n", |
69 | OMAP_MCBSP_READ(mcbsp->io_base, DXR1)); | 103 | MCBSP_READ(mcbsp, DXR1)); |
70 | dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n", | 104 | dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n", |
71 | OMAP_MCBSP_READ(mcbsp->io_base, SPCR2)); | 105 | MCBSP_READ(mcbsp, SPCR2)); |
72 | dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n", | 106 | dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n", |
73 | OMAP_MCBSP_READ(mcbsp->io_base, SPCR1)); | 107 | MCBSP_READ(mcbsp, SPCR1)); |
74 | dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n", | 108 | dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n", |
75 | OMAP_MCBSP_READ(mcbsp->io_base, RCR2)); | 109 | MCBSP_READ(mcbsp, RCR2)); |
76 | dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n", | 110 | dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n", |
77 | OMAP_MCBSP_READ(mcbsp->io_base, RCR1)); | 111 | MCBSP_READ(mcbsp, RCR1)); |
78 | dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n", | 112 | dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n", |
79 | OMAP_MCBSP_READ(mcbsp->io_base, XCR2)); | 113 | MCBSP_READ(mcbsp, XCR2)); |
80 | dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n", | 114 | dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n", |
81 | OMAP_MCBSP_READ(mcbsp->io_base, XCR1)); | 115 | MCBSP_READ(mcbsp, XCR1)); |
82 | dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n", | 116 | dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n", |
83 | OMAP_MCBSP_READ(mcbsp->io_base, SRGR2)); | 117 | MCBSP_READ(mcbsp, SRGR2)); |
84 | dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n", | 118 | dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n", |
85 | OMAP_MCBSP_READ(mcbsp->io_base, SRGR1)); | 119 | MCBSP_READ(mcbsp, SRGR1)); |
86 | dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n", | 120 | dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n", |
87 | OMAP_MCBSP_READ(mcbsp->io_base, PCR0)); | 121 | MCBSP_READ(mcbsp, PCR0)); |
88 | dev_dbg(mcbsp->dev, "***********************\n"); | 122 | dev_dbg(mcbsp->dev, "***********************\n"); |
89 | } | 123 | } |
90 | 124 | ||
@@ -93,15 +127,14 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) | |||
93 | struct omap_mcbsp *mcbsp_tx = dev_id; | 127 | struct omap_mcbsp *mcbsp_tx = dev_id; |
94 | u16 irqst_spcr2; | 128 | u16 irqst_spcr2; |
95 | 129 | ||
96 | irqst_spcr2 = OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2); | 130 | irqst_spcr2 = MCBSP_READ(mcbsp_tx, SPCR2); |
97 | dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2); | 131 | dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2); |
98 | 132 | ||
99 | if (irqst_spcr2 & XSYNC_ERR) { | 133 | if (irqst_spcr2 & XSYNC_ERR) { |
100 | dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n", | 134 | dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n", |
101 | irqst_spcr2); | 135 | irqst_spcr2); |
102 | /* Writing zero to XSYNC_ERR clears the IRQ */ | 136 | /* Writing zero to XSYNC_ERR clears the IRQ */ |
103 | OMAP_MCBSP_WRITE(mcbsp_tx->io_base, SPCR2, | 137 | MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2)); |
104 | irqst_spcr2 & ~(XSYNC_ERR)); | ||
105 | } else { | 138 | } else { |
106 | complete(&mcbsp_tx->tx_irq_completion); | 139 | complete(&mcbsp_tx->tx_irq_completion); |
107 | } | 140 | } |
@@ -114,15 +147,14 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) | |||
114 | struct omap_mcbsp *mcbsp_rx = dev_id; | 147 | struct omap_mcbsp *mcbsp_rx = dev_id; |
115 | u16 irqst_spcr1; | 148 | u16 irqst_spcr1; |
116 | 149 | ||
117 | irqst_spcr1 = OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR1); | 150 | irqst_spcr1 = MCBSP_READ(mcbsp_rx, SPCR1); |
118 | dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1); | 151 | dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1); |
119 | 152 | ||
120 | if (irqst_spcr1 & RSYNC_ERR) { | 153 | if (irqst_spcr1 & RSYNC_ERR) { |
121 | dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n", | 154 | dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n", |
122 | irqst_spcr1); | 155 | irqst_spcr1); |
123 | /* Writing zero to RSYNC_ERR clears the IRQ */ | 156 | /* Writing zero to RSYNC_ERR clears the IRQ */ |
124 | OMAP_MCBSP_WRITE(mcbsp_rx->io_base, SPCR1, | 157 | MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); |
125 | irqst_spcr1 & ~(RSYNC_ERR)); | ||
126 | } else { | 158 | } else { |
127 | complete(&mcbsp_rx->tx_irq_completion); | 159 | complete(&mcbsp_rx->tx_irq_completion); |
128 | } | 160 | } |
@@ -135,7 +167,7 @@ static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) | |||
135 | struct omap_mcbsp *mcbsp_dma_tx = data; | 167 | struct omap_mcbsp *mcbsp_dma_tx = data; |
136 | 168 | ||
137 | dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", | 169 | dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", |
138 | OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2)); | 170 | MCBSP_READ(mcbsp_dma_tx, SPCR2)); |
139 | 171 | ||
140 | /* We can free the channels */ | 172 | /* We can free the channels */ |
141 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); | 173 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); |
@@ -149,7 +181,7 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
149 | struct omap_mcbsp *mcbsp_dma_rx = data; | 181 | struct omap_mcbsp *mcbsp_dma_rx = data; |
150 | 182 | ||
151 | dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", | 183 | dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", |
152 | OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2)); | 184 | MCBSP_READ(mcbsp_dma_rx, SPCR2)); |
153 | 185 | ||
154 | /* We can free the channels */ | 186 | /* We can free the channels */ |
155 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); | 187 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); |
@@ -167,7 +199,6 @@ static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | |||
167 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | 199 | void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) |
168 | { | 200 | { |
169 | struct omap_mcbsp *mcbsp; | 201 | struct omap_mcbsp *mcbsp; |
170 | void __iomem *io_base; | ||
171 | 202 | ||
172 | if (!omap_mcbsp_check_valid_id(id)) { | 203 | if (!omap_mcbsp_check_valid_id(id)) { |
173 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 204 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
@@ -175,30 +206,280 @@ void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg *config) | |||
175 | } | 206 | } |
176 | mcbsp = id_to_mcbsp_ptr(id); | 207 | mcbsp = id_to_mcbsp_ptr(id); |
177 | 208 | ||
178 | io_base = mcbsp->io_base; | ||
179 | dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n", | 209 | dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n", |
180 | mcbsp->id, mcbsp->phys_base); | 210 | mcbsp->id, mcbsp->phys_base); |
181 | 211 | ||
182 | /* We write the given config */ | 212 | /* We write the given config */ |
183 | OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2); | 213 | MCBSP_WRITE(mcbsp, SPCR2, config->spcr2); |
184 | OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1); | 214 | MCBSP_WRITE(mcbsp, SPCR1, config->spcr1); |
185 | OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2); | 215 | MCBSP_WRITE(mcbsp, RCR2, config->rcr2); |
186 | OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1); | 216 | MCBSP_WRITE(mcbsp, RCR1, config->rcr1); |
187 | OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2); | 217 | MCBSP_WRITE(mcbsp, XCR2, config->xcr2); |
188 | OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1); | 218 | MCBSP_WRITE(mcbsp, XCR1, config->xcr1); |
189 | OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2); | 219 | MCBSP_WRITE(mcbsp, SRGR2, config->srgr2); |
190 | OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1); | 220 | MCBSP_WRITE(mcbsp, SRGR1, config->srgr1); |
191 | OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2); | 221 | MCBSP_WRITE(mcbsp, MCR2, config->mcr2); |
192 | OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1); | 222 | MCBSP_WRITE(mcbsp, MCR1, config->mcr1); |
193 | OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0); | 223 | MCBSP_WRITE(mcbsp, PCR0, config->pcr0); |
194 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { | 224 | if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) { |
195 | OMAP_MCBSP_WRITE(io_base, XCCR, config->xccr); | 225 | MCBSP_WRITE(mcbsp, XCCR, config->xccr); |
196 | OMAP_MCBSP_WRITE(io_base, RCCR, config->rccr); | 226 | MCBSP_WRITE(mcbsp, RCCR, config->rccr); |
197 | } | 227 | } |
198 | } | 228 | } |
199 | EXPORT_SYMBOL(omap_mcbsp_config); | 229 | EXPORT_SYMBOL(omap_mcbsp_config); |
200 | 230 | ||
201 | #ifdef CONFIG_ARCH_OMAP34XX | 231 | #ifdef CONFIG_ARCH_OMAP3 |
232 | static void omap_st_on(struct omap_mcbsp *mcbsp) | ||
233 | { | ||
234 | unsigned int w; | ||
235 | |||
236 | /* | ||
237 | * Sidetone uses McBSP ICLK - which must not idle when sidetones | ||
238 | * are enabled or sidetones start sounding ugly. | ||
239 | */ | ||
240 | w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
241 | w &= ~(1 << (mcbsp->id - 2)); | ||
242 | cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
243 | |||
244 | /* Enable McBSP Sidetone */ | ||
245 | w = MCBSP_READ(mcbsp, SSELCR); | ||
246 | MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN); | ||
247 | |||
248 | w = MCBSP_ST_READ(mcbsp, SYSCONFIG); | ||
249 | MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); | ||
250 | |||
251 | /* Enable Sidetone from Sidetone Core */ | ||
252 | w = MCBSP_ST_READ(mcbsp, SSELCR); | ||
253 | MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN); | ||
254 | } | ||
255 | |||
256 | static void omap_st_off(struct omap_mcbsp *mcbsp) | ||
257 | { | ||
258 | unsigned int w; | ||
259 | |||
260 | w = MCBSP_ST_READ(mcbsp, SSELCR); | ||
261 | MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN)); | ||
262 | |||
263 | w = MCBSP_ST_READ(mcbsp, SYSCONFIG); | ||
264 | MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE); | ||
265 | |||
266 | w = MCBSP_READ(mcbsp, SSELCR); | ||
267 | MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); | ||
268 | |||
269 | w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
270 | w |= 1 << (mcbsp->id - 2); | ||
271 | cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); | ||
272 | } | ||
273 | |||
274 | static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) | ||
275 | { | ||
276 | u16 val, i; | ||
277 | |||
278 | val = MCBSP_ST_READ(mcbsp, SYSCONFIG); | ||
279 | MCBSP_ST_WRITE(mcbsp, SYSCONFIG, val & ~(ST_AUTOIDLE)); | ||
280 | |||
281 | val = MCBSP_ST_READ(mcbsp, SSELCR); | ||
282 | |||
283 | if (val & ST_COEFFWREN) | ||
284 | MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); | ||
285 | |||
286 | MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN); | ||
287 | |||
288 | for (i = 0; i < 128; i++) | ||
289 | MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]); | ||
290 | |||
291 | i = 0; | ||
292 | |||
293 | val = MCBSP_ST_READ(mcbsp, SSELCR); | ||
294 | while (!(val & ST_COEFFWRDONE) && (++i < 1000)) | ||
295 | val = MCBSP_ST_READ(mcbsp, SSELCR); | ||
296 | |||
297 | MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN)); | ||
298 | |||
299 | if (i == 1000) | ||
300 | dev_err(mcbsp->dev, "McBSP FIR load error!\n"); | ||
301 | } | ||
302 | |||
303 | static void omap_st_chgain(struct omap_mcbsp *mcbsp) | ||
304 | { | ||
305 | u16 w; | ||
306 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | ||
307 | |||
308 | w = MCBSP_ST_READ(mcbsp, SYSCONFIG); | ||
309 | MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE)); | ||
310 | |||
311 | w = MCBSP_ST_READ(mcbsp, SSELCR); | ||
312 | |||
313 | MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \ | ||
314 | ST_CH1GAIN(st_data->ch1gain)); | ||
315 | } | ||
316 | |||
317 | int omap_st_set_chgain(unsigned int id, int channel, s16 chgain) | ||
318 | { | ||
319 | struct omap_mcbsp *mcbsp; | ||
320 | struct omap_mcbsp_st_data *st_data; | ||
321 | int ret = 0; | ||
322 | |||
323 | if (!omap_mcbsp_check_valid_id(id)) { | ||
324 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
325 | return -ENODEV; | ||
326 | } | ||
327 | |||
328 | mcbsp = id_to_mcbsp_ptr(id); | ||
329 | st_data = mcbsp->st_data; | ||
330 | |||
331 | if (!st_data) | ||
332 | return -ENOENT; | ||
333 | |||
334 | spin_lock_irq(&mcbsp->lock); | ||
335 | if (channel == 0) | ||
336 | st_data->ch0gain = chgain; | ||
337 | else if (channel == 1) | ||
338 | st_data->ch1gain = chgain; | ||
339 | else | ||
340 | ret = -EINVAL; | ||
341 | |||
342 | if (st_data->enabled) | ||
343 | omap_st_chgain(mcbsp); | ||
344 | spin_unlock_irq(&mcbsp->lock); | ||
345 | |||
346 | return ret; | ||
347 | } | ||
348 | EXPORT_SYMBOL(omap_st_set_chgain); | ||
349 | |||
350 | int omap_st_get_chgain(unsigned int id, int channel, s16 *chgain) | ||
351 | { | ||
352 | struct omap_mcbsp *mcbsp; | ||
353 | struct omap_mcbsp_st_data *st_data; | ||
354 | int ret = 0; | ||
355 | |||
356 | if (!omap_mcbsp_check_valid_id(id)) { | ||
357 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
358 | return -ENODEV; | ||
359 | } | ||
360 | |||
361 | mcbsp = id_to_mcbsp_ptr(id); | ||
362 | st_data = mcbsp->st_data; | ||
363 | |||
364 | if (!st_data) | ||
365 | return -ENOENT; | ||
366 | |||
367 | spin_lock_irq(&mcbsp->lock); | ||
368 | if (channel == 0) | ||
369 | *chgain = st_data->ch0gain; | ||
370 | else if (channel == 1) | ||
371 | *chgain = st_data->ch1gain; | ||
372 | else | ||
373 | ret = -EINVAL; | ||
374 | spin_unlock_irq(&mcbsp->lock); | ||
375 | |||
376 | return ret; | ||
377 | } | ||
378 | EXPORT_SYMBOL(omap_st_get_chgain); | ||
379 | |||
380 | static int omap_st_start(struct omap_mcbsp *mcbsp) | ||
381 | { | ||
382 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | ||
383 | |||
384 | if (st_data && st_data->enabled && !st_data->running) { | ||
385 | omap_st_fir_write(mcbsp, st_data->taps); | ||
386 | omap_st_chgain(mcbsp); | ||
387 | |||
388 | if (!mcbsp->free) { | ||
389 | omap_st_on(mcbsp); | ||
390 | st_data->running = 1; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | int omap_st_enable(unsigned int id) | ||
398 | { | ||
399 | struct omap_mcbsp *mcbsp; | ||
400 | struct omap_mcbsp_st_data *st_data; | ||
401 | |||
402 | if (!omap_mcbsp_check_valid_id(id)) { | ||
403 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
404 | return -ENODEV; | ||
405 | } | ||
406 | |||
407 | mcbsp = id_to_mcbsp_ptr(id); | ||
408 | st_data = mcbsp->st_data; | ||
409 | |||
410 | if (!st_data) | ||
411 | return -ENODEV; | ||
412 | |||
413 | spin_lock_irq(&mcbsp->lock); | ||
414 | st_data->enabled = 1; | ||
415 | omap_st_start(mcbsp); | ||
416 | spin_unlock_irq(&mcbsp->lock); | ||
417 | |||
418 | return 0; | ||
419 | } | ||
420 | EXPORT_SYMBOL(omap_st_enable); | ||
421 | |||
422 | static int omap_st_stop(struct omap_mcbsp *mcbsp) | ||
423 | { | ||
424 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | ||
425 | |||
426 | if (st_data && st_data->running) { | ||
427 | if (!mcbsp->free) { | ||
428 | omap_st_off(mcbsp); | ||
429 | st_data->running = 0; | ||
430 | } | ||
431 | } | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | int omap_st_disable(unsigned int id) | ||
437 | { | ||
438 | struct omap_mcbsp *mcbsp; | ||
439 | struct omap_mcbsp_st_data *st_data; | ||
440 | int ret = 0; | ||
441 | |||
442 | if (!omap_mcbsp_check_valid_id(id)) { | ||
443 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
444 | return -ENODEV; | ||
445 | } | ||
446 | |||
447 | mcbsp = id_to_mcbsp_ptr(id); | ||
448 | st_data = mcbsp->st_data; | ||
449 | |||
450 | if (!st_data) | ||
451 | return -ENODEV; | ||
452 | |||
453 | spin_lock_irq(&mcbsp->lock); | ||
454 | omap_st_stop(mcbsp); | ||
455 | st_data->enabled = 0; | ||
456 | spin_unlock_irq(&mcbsp->lock); | ||
457 | |||
458 | return ret; | ||
459 | } | ||
460 | EXPORT_SYMBOL(omap_st_disable); | ||
461 | |||
462 | int omap_st_is_enabled(unsigned int id) | ||
463 | { | ||
464 | struct omap_mcbsp *mcbsp; | ||
465 | struct omap_mcbsp_st_data *st_data; | ||
466 | |||
467 | if (!omap_mcbsp_check_valid_id(id)) { | ||
468 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
469 | return -ENODEV; | ||
470 | } | ||
471 | |||
472 | mcbsp = id_to_mcbsp_ptr(id); | ||
473 | st_data = mcbsp->st_data; | ||
474 | |||
475 | if (!st_data) | ||
476 | return -ENODEV; | ||
477 | |||
478 | |||
479 | return st_data->enabled; | ||
480 | } | ||
481 | EXPORT_SYMBOL(omap_st_is_enabled); | ||
482 | |||
202 | /* | 483 | /* |
203 | * omap_mcbsp_set_tx_threshold configures how to deal | 484 | * omap_mcbsp_set_tx_threshold configures how to deal |
204 | * with transmit threshold. the threshold value and handler can be | 485 | * with transmit threshold. the threshold value and handler can be |
@@ -207,7 +488,6 @@ EXPORT_SYMBOL(omap_mcbsp_config); | |||
207 | void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) | 488 | void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) |
208 | { | 489 | { |
209 | struct omap_mcbsp *mcbsp; | 490 | struct omap_mcbsp *mcbsp; |
210 | void __iomem *io_base; | ||
211 | 491 | ||
212 | if (!cpu_is_omap34xx()) | 492 | if (!cpu_is_omap34xx()) |
213 | return; | 493 | return; |
@@ -217,9 +497,8 @@ void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold) | |||
217 | return; | 497 | return; |
218 | } | 498 | } |
219 | mcbsp = id_to_mcbsp_ptr(id); | 499 | mcbsp = id_to_mcbsp_ptr(id); |
220 | io_base = mcbsp->io_base; | ||
221 | 500 | ||
222 | OMAP_MCBSP_WRITE(io_base, THRSH2, threshold); | 501 | MCBSP_WRITE(mcbsp, THRSH2, threshold); |
223 | } | 502 | } |
224 | EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); | 503 | EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); |
225 | 504 | ||
@@ -231,7 +510,6 @@ EXPORT_SYMBOL(omap_mcbsp_set_tx_threshold); | |||
231 | void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) | 510 | void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) |
232 | { | 511 | { |
233 | struct omap_mcbsp *mcbsp; | 512 | struct omap_mcbsp *mcbsp; |
234 | void __iomem *io_base; | ||
235 | 513 | ||
236 | if (!cpu_is_omap34xx()) | 514 | if (!cpu_is_omap34xx()) |
237 | return; | 515 | return; |
@@ -241,9 +519,8 @@ void omap_mcbsp_set_rx_threshold(unsigned int id, u16 threshold) | |||
241 | return; | 519 | return; |
242 | } | 520 | } |
243 | mcbsp = id_to_mcbsp_ptr(id); | 521 | mcbsp = id_to_mcbsp_ptr(id); |
244 | io_base = mcbsp->io_base; | ||
245 | 522 | ||
246 | OMAP_MCBSP_WRITE(io_base, THRSH1, threshold); | 523 | MCBSP_WRITE(mcbsp, THRSH1, threshold); |
247 | } | 524 | } |
248 | EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); | 525 | EXPORT_SYMBOL(omap_mcbsp_set_rx_threshold); |
249 | 526 | ||
@@ -298,9 +575,7 @@ int omap_mcbsp_get_dma_op_mode(unsigned int id) | |||
298 | } | 575 | } |
299 | mcbsp = id_to_mcbsp_ptr(id); | 576 | mcbsp = id_to_mcbsp_ptr(id); |
300 | 577 | ||
301 | spin_lock_irq(&mcbsp->lock); | ||
302 | dma_op_mode = mcbsp->dma_op_mode; | 578 | dma_op_mode = mcbsp->dma_op_mode; |
303 | spin_unlock_irq(&mcbsp->lock); | ||
304 | 579 | ||
305 | return dma_op_mode; | 580 | return dma_op_mode; |
306 | } | 581 | } |
@@ -315,21 +590,18 @@ static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) | |||
315 | if (cpu_is_omap34xx()) { | 590 | if (cpu_is_omap34xx()) { |
316 | u16 syscon; | 591 | u16 syscon; |
317 | 592 | ||
318 | syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); | 593 | syscon = MCBSP_READ(mcbsp, SYSCON); |
319 | syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); | 594 | syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); |
320 | 595 | ||
321 | spin_lock_irq(&mcbsp->lock); | ||
322 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { | 596 | if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) { |
323 | syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | | 597 | syscon |= (ENAWAKEUP | SIDLEMODE(0x02) | |
324 | CLOCKACTIVITY(0x02)); | 598 | CLOCKACTIVITY(0x02)); |
325 | OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, | 599 | MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN); |
326 | XRDYEN | RRDYEN); | ||
327 | } else { | 600 | } else { |
328 | syscon |= SIDLEMODE(0x01); | 601 | syscon |= SIDLEMODE(0x01); |
329 | } | 602 | } |
330 | spin_unlock_irq(&mcbsp->lock); | ||
331 | 603 | ||
332 | OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); | 604 | MCBSP_WRITE(mcbsp, SYSCON, syscon); |
333 | } | 605 | } |
334 | } | 606 | } |
335 | 607 | ||
@@ -341,7 +613,7 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) | |||
341 | if (cpu_is_omap34xx()) { | 613 | if (cpu_is_omap34xx()) { |
342 | u16 syscon; | 614 | u16 syscon; |
343 | 615 | ||
344 | syscon = OMAP_MCBSP_READ(mcbsp->io_base, SYSCON); | 616 | syscon = MCBSP_READ(mcbsp, SYSCON); |
345 | syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); | 617 | syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03)); |
346 | /* | 618 | /* |
347 | * HW bug workaround - If no_idle mode is taken, we need to | 619 | * HW bug workaround - If no_idle mode is taken, we need to |
@@ -349,17 +621,19 @@ static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) | |||
349 | * device will not hit retention anymore. | 621 | * device will not hit retention anymore. |
350 | */ | 622 | */ |
351 | syscon |= SIDLEMODE(0x02); | 623 | syscon |= SIDLEMODE(0x02); |
352 | OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); | 624 | MCBSP_WRITE(mcbsp, SYSCON, syscon); |
353 | 625 | ||
354 | syscon &= ~(SIDLEMODE(0x03)); | 626 | syscon &= ~(SIDLEMODE(0x03)); |
355 | OMAP_MCBSP_WRITE(mcbsp->io_base, SYSCON, syscon); | 627 | MCBSP_WRITE(mcbsp, SYSCON, syscon); |
356 | 628 | ||
357 | OMAP_MCBSP_WRITE(mcbsp->io_base, WAKEUPEN, 0); | 629 | MCBSP_WRITE(mcbsp, WAKEUPEN, 0); |
358 | } | 630 | } |
359 | } | 631 | } |
360 | #else | 632 | #else |
361 | static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} | 633 | static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp) {} |
362 | static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} | 634 | static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp) {} |
635 | static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} | ||
636 | static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} | ||
363 | #endif | 637 | #endif |
364 | 638 | ||
365 | /* | 639 | /* |
@@ -396,6 +670,7 @@ EXPORT_SYMBOL(omap_mcbsp_set_io_type); | |||
396 | int omap_mcbsp_request(unsigned int id) | 670 | int omap_mcbsp_request(unsigned int id) |
397 | { | 671 | { |
398 | struct omap_mcbsp *mcbsp; | 672 | struct omap_mcbsp *mcbsp; |
673 | void *reg_cache; | ||
399 | int err; | 674 | int err; |
400 | 675 | ||
401 | if (!omap_mcbsp_check_valid_id(id)) { | 676 | if (!omap_mcbsp_check_valid_id(id)) { |
@@ -404,15 +679,21 @@ int omap_mcbsp_request(unsigned int id) | |||
404 | } | 679 | } |
405 | mcbsp = id_to_mcbsp_ptr(id); | 680 | mcbsp = id_to_mcbsp_ptr(id); |
406 | 681 | ||
682 | reg_cache = kzalloc(omap_mcbsp_cache_size, GFP_KERNEL); | ||
683 | if (!reg_cache) { | ||
684 | return -ENOMEM; | ||
685 | } | ||
686 | |||
407 | spin_lock(&mcbsp->lock); | 687 | spin_lock(&mcbsp->lock); |
408 | if (!mcbsp->free) { | 688 | if (!mcbsp->free) { |
409 | dev_err(mcbsp->dev, "McBSP%d is currently in use\n", | 689 | dev_err(mcbsp->dev, "McBSP%d is currently in use\n", |
410 | mcbsp->id); | 690 | mcbsp->id); |
411 | spin_unlock(&mcbsp->lock); | 691 | err = -EBUSY; |
412 | return -EBUSY; | 692 | goto err_kfree; |
413 | } | 693 | } |
414 | 694 | ||
415 | mcbsp->free = 0; | 695 | mcbsp->free = 0; |
696 | mcbsp->reg_cache = reg_cache; | ||
416 | spin_unlock(&mcbsp->lock); | 697 | spin_unlock(&mcbsp->lock); |
417 | 698 | ||
418 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) | 699 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request) |
@@ -428,8 +709,8 @@ int omap_mcbsp_request(unsigned int id) | |||
428 | * Make sure that transmitter, receiver and sample-rate generator are | 709 | * Make sure that transmitter, receiver and sample-rate generator are |
429 | * not running before activating IRQs. | 710 | * not running before activating IRQs. |
430 | */ | 711 | */ |
431 | OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR1, 0); | 712 | MCBSP_WRITE(mcbsp, SPCR1, 0); |
432 | OMAP_MCBSP_WRITE(mcbsp->io_base, SPCR2, 0); | 713 | MCBSP_WRITE(mcbsp, SPCR2, 0); |
433 | 714 | ||
434 | if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { | 715 | if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { |
435 | /* We need to get IRQs here */ | 716 | /* We need to get IRQs here */ |
@@ -440,7 +721,7 @@ int omap_mcbsp_request(unsigned int id) | |||
440 | dev_err(mcbsp->dev, "Unable to request TX IRQ %d " | 721 | dev_err(mcbsp->dev, "Unable to request TX IRQ %d " |
441 | "for McBSP%d\n", mcbsp->tx_irq, | 722 | "for McBSP%d\n", mcbsp->tx_irq, |
442 | mcbsp->id); | 723 | mcbsp->id); |
443 | return err; | 724 | goto err_clk_disable; |
444 | } | 725 | } |
445 | 726 | ||
446 | init_completion(&mcbsp->rx_irq_completion); | 727 | init_completion(&mcbsp->rx_irq_completion); |
@@ -450,18 +731,38 @@ int omap_mcbsp_request(unsigned int id) | |||
450 | dev_err(mcbsp->dev, "Unable to request RX IRQ %d " | 731 | dev_err(mcbsp->dev, "Unable to request RX IRQ %d " |
451 | "for McBSP%d\n", mcbsp->rx_irq, | 732 | "for McBSP%d\n", mcbsp->rx_irq, |
452 | mcbsp->id); | 733 | mcbsp->id); |
453 | free_irq(mcbsp->tx_irq, (void *)mcbsp); | 734 | goto err_free_irq; |
454 | return err; | ||
455 | } | 735 | } |
456 | } | 736 | } |
457 | 737 | ||
458 | return 0; | 738 | return 0; |
739 | err_free_irq: | ||
740 | free_irq(mcbsp->tx_irq, (void *)mcbsp); | ||
741 | err_clk_disable: | ||
742 | if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->free) | ||
743 | mcbsp->pdata->ops->free(id); | ||
744 | |||
745 | /* Do procedure specific to omap34xx arch, if applicable */ | ||
746 | omap34xx_mcbsp_free(mcbsp); | ||
747 | |||
748 | clk_disable(mcbsp->fclk); | ||
749 | clk_disable(mcbsp->iclk); | ||
750 | |||
751 | spin_lock(&mcbsp->lock); | ||
752 | mcbsp->free = 1; | ||
753 | mcbsp->reg_cache = NULL; | ||
754 | err_kfree: | ||
755 | spin_unlock(&mcbsp->lock); | ||
756 | kfree(reg_cache); | ||
757 | |||
758 | return err; | ||
459 | } | 759 | } |
460 | EXPORT_SYMBOL(omap_mcbsp_request); | 760 | EXPORT_SYMBOL(omap_mcbsp_request); |
461 | 761 | ||
462 | void omap_mcbsp_free(unsigned int id) | 762 | void omap_mcbsp_free(unsigned int id) |
463 | { | 763 | { |
464 | struct omap_mcbsp *mcbsp; | 764 | struct omap_mcbsp *mcbsp; |
765 | void *reg_cache; | ||
465 | 766 | ||
466 | if (!omap_mcbsp_check_valid_id(id)) { | 767 | if (!omap_mcbsp_check_valid_id(id)) { |
467 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 768 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
@@ -484,16 +785,18 @@ void omap_mcbsp_free(unsigned int id) | |||
484 | free_irq(mcbsp->tx_irq, (void *)mcbsp); | 785 | free_irq(mcbsp->tx_irq, (void *)mcbsp); |
485 | } | 786 | } |
486 | 787 | ||
487 | spin_lock(&mcbsp->lock); | 788 | reg_cache = mcbsp->reg_cache; |
488 | if (mcbsp->free) { | ||
489 | dev_err(mcbsp->dev, "McBSP%d was not reserved\n", | ||
490 | mcbsp->id); | ||
491 | spin_unlock(&mcbsp->lock); | ||
492 | return; | ||
493 | } | ||
494 | 789 | ||
495 | mcbsp->free = 1; | 790 | spin_lock(&mcbsp->lock); |
791 | if (mcbsp->free) | ||
792 | dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); | ||
793 | else | ||
794 | mcbsp->free = 1; | ||
795 | mcbsp->reg_cache = NULL; | ||
496 | spin_unlock(&mcbsp->lock); | 796 | spin_unlock(&mcbsp->lock); |
797 | |||
798 | if (reg_cache) | ||
799 | kfree(reg_cache); | ||
497 | } | 800 | } |
498 | EXPORT_SYMBOL(omap_mcbsp_free); | 801 | EXPORT_SYMBOL(omap_mcbsp_free); |
499 | 802 | ||
@@ -505,7 +808,6 @@ EXPORT_SYMBOL(omap_mcbsp_free); | |||
505 | void omap_mcbsp_start(unsigned int id, int tx, int rx) | 808 | void omap_mcbsp_start(unsigned int id, int tx, int rx) |
506 | { | 809 | { |
507 | struct omap_mcbsp *mcbsp; | 810 | struct omap_mcbsp *mcbsp; |
508 | void __iomem *io_base; | ||
509 | int idle; | 811 | int idle; |
510 | u16 w; | 812 | u16 w; |
511 | 813 | ||
@@ -514,28 +816,30 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) | |||
514 | return; | 816 | return; |
515 | } | 817 | } |
516 | mcbsp = id_to_mcbsp_ptr(id); | 818 | mcbsp = id_to_mcbsp_ptr(id); |
517 | io_base = mcbsp->io_base; | ||
518 | 819 | ||
519 | mcbsp->rx_word_length = (OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7; | 820 | if (cpu_is_omap34xx()) |
520 | mcbsp->tx_word_length = (OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7; | 821 | omap_st_start(mcbsp); |
822 | |||
823 | mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7; | ||
824 | mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7; | ||
521 | 825 | ||
522 | idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | | 826 | idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) | |
523 | OMAP_MCBSP_READ(io_base, SPCR1)) & 1); | 827 | MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1); |
524 | 828 | ||
525 | if (idle) { | 829 | if (idle) { |
526 | /* Start the sample generator */ | 830 | /* Start the sample generator */ |
527 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 831 | w = MCBSP_READ_CACHE(mcbsp, SPCR2); |
528 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6)); | 832 | MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6)); |
529 | } | 833 | } |
530 | 834 | ||
531 | /* Enable transmitter and receiver */ | 835 | /* Enable transmitter and receiver */ |
532 | tx &= 1; | 836 | tx &= 1; |
533 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 837 | w = MCBSP_READ_CACHE(mcbsp, SPCR2); |
534 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | tx); | 838 | MCBSP_WRITE(mcbsp, SPCR2, w | tx); |
535 | 839 | ||
536 | rx &= 1; | 840 | rx &= 1; |
537 | w = OMAP_MCBSP_READ(io_base, SPCR1); | 841 | w = MCBSP_READ_CACHE(mcbsp, SPCR1); |
538 | OMAP_MCBSP_WRITE(io_base, SPCR1, w | rx); | 842 | MCBSP_WRITE(mcbsp, SPCR1, w | rx); |
539 | 843 | ||
540 | /* | 844 | /* |
541 | * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec | 845 | * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec |
@@ -547,18 +851,18 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) | |||
547 | 851 | ||
548 | if (idle) { | 852 | if (idle) { |
549 | /* Start frame sync */ | 853 | /* Start frame sync */ |
550 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 854 | w = MCBSP_READ_CACHE(mcbsp, SPCR2); |
551 | OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7)); | 855 | MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7)); |
552 | } | 856 | } |
553 | 857 | ||
554 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | 858 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { |
555 | /* Release the transmitter and receiver */ | 859 | /* Release the transmitter and receiver */ |
556 | w = OMAP_MCBSP_READ(io_base, XCCR); | 860 | w = MCBSP_READ_CACHE(mcbsp, XCCR); |
557 | w &= ~(tx ? XDISABLE : 0); | 861 | w &= ~(tx ? XDISABLE : 0); |
558 | OMAP_MCBSP_WRITE(io_base, XCCR, w); | 862 | MCBSP_WRITE(mcbsp, XCCR, w); |
559 | w = OMAP_MCBSP_READ(io_base, RCCR); | 863 | w = MCBSP_READ_CACHE(mcbsp, RCCR); |
560 | w &= ~(rx ? RDISABLE : 0); | 864 | w &= ~(rx ? RDISABLE : 0); |
561 | OMAP_MCBSP_WRITE(io_base, RCCR, w); | 865 | MCBSP_WRITE(mcbsp, RCCR, w); |
562 | } | 866 | } |
563 | 867 | ||
564 | /* Dump McBSP Regs */ | 868 | /* Dump McBSP Regs */ |
@@ -569,7 +873,6 @@ EXPORT_SYMBOL(omap_mcbsp_start); | |||
569 | void omap_mcbsp_stop(unsigned int id, int tx, int rx) | 873 | void omap_mcbsp_stop(unsigned int id, int tx, int rx) |
570 | { | 874 | { |
571 | struct omap_mcbsp *mcbsp; | 875 | struct omap_mcbsp *mcbsp; |
572 | void __iomem *io_base; | ||
573 | int idle; | 876 | int idle; |
574 | u16 w; | 877 | u16 w; |
575 | 878 | ||
@@ -579,36 +882,38 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) | |||
579 | } | 882 | } |
580 | 883 | ||
581 | mcbsp = id_to_mcbsp_ptr(id); | 884 | mcbsp = id_to_mcbsp_ptr(id); |
582 | io_base = mcbsp->io_base; | ||
583 | 885 | ||
584 | /* Reset transmitter */ | 886 | /* Reset transmitter */ |
585 | tx &= 1; | 887 | tx &= 1; |
586 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | 888 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { |
587 | w = OMAP_MCBSP_READ(io_base, XCCR); | 889 | w = MCBSP_READ_CACHE(mcbsp, XCCR); |
588 | w |= (tx ? XDISABLE : 0); | 890 | w |= (tx ? XDISABLE : 0); |
589 | OMAP_MCBSP_WRITE(io_base, XCCR, w); | 891 | MCBSP_WRITE(mcbsp, XCCR, w); |
590 | } | 892 | } |
591 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 893 | w = MCBSP_READ_CACHE(mcbsp, SPCR2); |
592 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~tx); | 894 | MCBSP_WRITE(mcbsp, SPCR2, w & ~tx); |
593 | 895 | ||
594 | /* Reset receiver */ | 896 | /* Reset receiver */ |
595 | rx &= 1; | 897 | rx &= 1; |
596 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | 898 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { |
597 | w = OMAP_MCBSP_READ(io_base, RCCR); | 899 | w = MCBSP_READ_CACHE(mcbsp, RCCR); |
598 | w |= (rx ? RDISABLE : 0); | 900 | w |= (rx ? RDISABLE : 0); |
599 | OMAP_MCBSP_WRITE(io_base, RCCR, w); | 901 | MCBSP_WRITE(mcbsp, RCCR, w); |
600 | } | 902 | } |
601 | w = OMAP_MCBSP_READ(io_base, SPCR1); | 903 | w = MCBSP_READ_CACHE(mcbsp, SPCR1); |
602 | OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~rx); | 904 | MCBSP_WRITE(mcbsp, SPCR1, w & ~rx); |
603 | 905 | ||
604 | idle = !((OMAP_MCBSP_READ(io_base, SPCR2) | | 906 | idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) | |
605 | OMAP_MCBSP_READ(io_base, SPCR1)) & 1); | 907 | MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1); |
606 | 908 | ||
607 | if (idle) { | 909 | if (idle) { |
608 | /* Reset the sample rate generator */ | 910 | /* Reset the sample rate generator */ |
609 | w = OMAP_MCBSP_READ(io_base, SPCR2); | 911 | w = MCBSP_READ_CACHE(mcbsp, SPCR2); |
610 | OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6)); | 912 | MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6)); |
611 | } | 913 | } |
914 | |||
915 | if (cpu_is_omap34xx()) | ||
916 | omap_st_stop(mcbsp); | ||
612 | } | 917 | } |
613 | EXPORT_SYMBOL(omap_mcbsp_stop); | 918 | EXPORT_SYMBOL(omap_mcbsp_stop); |
614 | 919 | ||
@@ -616,7 +921,6 @@ EXPORT_SYMBOL(omap_mcbsp_stop); | |||
616 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | 921 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) |
617 | { | 922 | { |
618 | struct omap_mcbsp *mcbsp; | 923 | struct omap_mcbsp *mcbsp; |
619 | void __iomem *base; | ||
620 | 924 | ||
621 | if (!omap_mcbsp_check_valid_id(id)) { | 925 | if (!omap_mcbsp_check_valid_id(id)) { |
622 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 926 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
@@ -624,28 +928,26 @@ int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | |||
624 | } | 928 | } |
625 | 929 | ||
626 | mcbsp = id_to_mcbsp_ptr(id); | 930 | mcbsp = id_to_mcbsp_ptr(id); |
627 | base = mcbsp->io_base; | ||
628 | 931 | ||
629 | writew(buf, base + OMAP_MCBSP_REG_DXR1); | 932 | MCBSP_WRITE(mcbsp, DXR1, buf); |
630 | /* if frame sync error - clear the error */ | 933 | /* if frame sync error - clear the error */ |
631 | if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) { | 934 | if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) { |
632 | /* clear error */ | 935 | /* clear error */ |
633 | writew(readw(base + OMAP_MCBSP_REG_SPCR2) & (~XSYNC_ERR), | 936 | MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2)); |
634 | base + OMAP_MCBSP_REG_SPCR2); | ||
635 | /* resend */ | 937 | /* resend */ |
636 | return -1; | 938 | return -1; |
637 | } else { | 939 | } else { |
638 | /* wait for transmit confirmation */ | 940 | /* wait for transmit confirmation */ |
639 | int attemps = 0; | 941 | int attemps = 0; |
640 | while (!(readw(base + OMAP_MCBSP_REG_SPCR2) & XRDY)) { | 942 | while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) { |
641 | if (attemps++ > 1000) { | 943 | if (attemps++ > 1000) { |
642 | writew(readw(base + OMAP_MCBSP_REG_SPCR2) & | 944 | MCBSP_WRITE(mcbsp, SPCR2, |
643 | (~XRST), | 945 | MCBSP_READ_CACHE(mcbsp, SPCR2) & |
644 | base + OMAP_MCBSP_REG_SPCR2); | 946 | (~XRST)); |
645 | udelay(10); | 947 | udelay(10); |
646 | writew(readw(base + OMAP_MCBSP_REG_SPCR2) | | 948 | MCBSP_WRITE(mcbsp, SPCR2, |
647 | (XRST), | 949 | MCBSP_READ_CACHE(mcbsp, SPCR2) | |
648 | base + OMAP_MCBSP_REG_SPCR2); | 950 | (XRST)); |
649 | udelay(10); | 951 | udelay(10); |
650 | dev_err(mcbsp->dev, "Could not write to" | 952 | dev_err(mcbsp->dev, "Could not write to" |
651 | " McBSP%d Register\n", mcbsp->id); | 953 | " McBSP%d Register\n", mcbsp->id); |
@@ -661,7 +963,6 @@ EXPORT_SYMBOL(omap_mcbsp_pollwrite); | |||
661 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) | 963 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) |
662 | { | 964 | { |
663 | struct omap_mcbsp *mcbsp; | 965 | struct omap_mcbsp *mcbsp; |
664 | void __iomem *base; | ||
665 | 966 | ||
666 | if (!omap_mcbsp_check_valid_id(id)) { | 967 | if (!omap_mcbsp_check_valid_id(id)) { |
667 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | 968 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); |
@@ -669,26 +970,24 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf) | |||
669 | } | 970 | } |
670 | mcbsp = id_to_mcbsp_ptr(id); | 971 | mcbsp = id_to_mcbsp_ptr(id); |
671 | 972 | ||
672 | base = mcbsp->io_base; | ||
673 | /* if frame sync error - clear the error */ | 973 | /* if frame sync error - clear the error */ |
674 | if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) { | 974 | if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) { |
675 | /* clear error */ | 975 | /* clear error */ |
676 | writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~RSYNC_ERR), | 976 | MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1)); |
677 | base + OMAP_MCBSP_REG_SPCR1); | ||
678 | /* resend */ | 977 | /* resend */ |
679 | return -1; | 978 | return -1; |
680 | } else { | 979 | } else { |
681 | /* wait for recieve confirmation */ | 980 | /* wait for recieve confirmation */ |
682 | int attemps = 0; | 981 | int attemps = 0; |
683 | while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & RRDY)) { | 982 | while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) { |
684 | if (attemps++ > 1000) { | 983 | if (attemps++ > 1000) { |
685 | writew(readw(base + OMAP_MCBSP_REG_SPCR1) & | 984 | MCBSP_WRITE(mcbsp, SPCR1, |
686 | (~RRST), | 985 | MCBSP_READ_CACHE(mcbsp, SPCR1) & |
687 | base + OMAP_MCBSP_REG_SPCR1); | 986 | (~RRST)); |
688 | udelay(10); | 987 | udelay(10); |
689 | writew(readw(base + OMAP_MCBSP_REG_SPCR1) | | 988 | MCBSP_WRITE(mcbsp, SPCR1, |
690 | (RRST), | 989 | MCBSP_READ_CACHE(mcbsp, SPCR1) | |
691 | base + OMAP_MCBSP_REG_SPCR1); | 990 | (RRST)); |
692 | udelay(10); | 991 | udelay(10); |
693 | dev_err(mcbsp->dev, "Could not read from" | 992 | dev_err(mcbsp->dev, "Could not read from" |
694 | " McBSP%d Register\n", mcbsp->id); | 993 | " McBSP%d Register\n", mcbsp->id); |
@@ -696,7 +995,7 @@ int omap_mcbsp_pollread(unsigned int id, u16 *buf) | |||
696 | } | 995 | } |
697 | } | 996 | } |
698 | } | 997 | } |
699 | *buf = readw(base + OMAP_MCBSP_REG_DRR1); | 998 | *buf = MCBSP_READ(mcbsp, DRR1); |
700 | 999 | ||
701 | return 0; | 1000 | return 0; |
702 | } | 1001 | } |
@@ -708,7 +1007,6 @@ EXPORT_SYMBOL(omap_mcbsp_pollread); | |||
708 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) | 1007 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) |
709 | { | 1008 | { |
710 | struct omap_mcbsp *mcbsp; | 1009 | struct omap_mcbsp *mcbsp; |
711 | void __iomem *io_base; | ||
712 | omap_mcbsp_word_length word_length; | 1010 | omap_mcbsp_word_length word_length; |
713 | 1011 | ||
714 | if (!omap_mcbsp_check_valid_id(id)) { | 1012 | if (!omap_mcbsp_check_valid_id(id)) { |
@@ -717,21 +1015,19 @@ void omap_mcbsp_xmit_word(unsigned int id, u32 word) | |||
717 | } | 1015 | } |
718 | 1016 | ||
719 | mcbsp = id_to_mcbsp_ptr(id); | 1017 | mcbsp = id_to_mcbsp_ptr(id); |
720 | io_base = mcbsp->io_base; | ||
721 | word_length = mcbsp->tx_word_length; | 1018 | word_length = mcbsp->tx_word_length; |
722 | 1019 | ||
723 | wait_for_completion(&mcbsp->tx_irq_completion); | 1020 | wait_for_completion(&mcbsp->tx_irq_completion); |
724 | 1021 | ||
725 | if (word_length > OMAP_MCBSP_WORD_16) | 1022 | if (word_length > OMAP_MCBSP_WORD_16) |
726 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); | 1023 | MCBSP_WRITE(mcbsp, DXR2, word >> 16); |
727 | OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); | 1024 | MCBSP_WRITE(mcbsp, DXR1, word & 0xffff); |
728 | } | 1025 | } |
729 | EXPORT_SYMBOL(omap_mcbsp_xmit_word); | 1026 | EXPORT_SYMBOL(omap_mcbsp_xmit_word); |
730 | 1027 | ||
731 | u32 omap_mcbsp_recv_word(unsigned int id) | 1028 | u32 omap_mcbsp_recv_word(unsigned int id) |
732 | { | 1029 | { |
733 | struct omap_mcbsp *mcbsp; | 1030 | struct omap_mcbsp *mcbsp; |
734 | void __iomem *io_base; | ||
735 | u16 word_lsb, word_msb = 0; | 1031 | u16 word_lsb, word_msb = 0; |
736 | omap_mcbsp_word_length word_length; | 1032 | omap_mcbsp_word_length word_length; |
737 | 1033 | ||
@@ -742,13 +1038,12 @@ u32 omap_mcbsp_recv_word(unsigned int id) | |||
742 | mcbsp = id_to_mcbsp_ptr(id); | 1038 | mcbsp = id_to_mcbsp_ptr(id); |
743 | 1039 | ||
744 | word_length = mcbsp->rx_word_length; | 1040 | word_length = mcbsp->rx_word_length; |
745 | io_base = mcbsp->io_base; | ||
746 | 1041 | ||
747 | wait_for_completion(&mcbsp->rx_irq_completion); | 1042 | wait_for_completion(&mcbsp->rx_irq_completion); |
748 | 1043 | ||
749 | if (word_length > OMAP_MCBSP_WORD_16) | 1044 | if (word_length > OMAP_MCBSP_WORD_16) |
750 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | 1045 | word_msb = MCBSP_READ(mcbsp, DRR2); |
751 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | 1046 | word_lsb = MCBSP_READ(mcbsp, DRR1); |
752 | 1047 | ||
753 | return (word_lsb | (word_msb << 16)); | 1048 | return (word_lsb | (word_msb << 16)); |
754 | } | 1049 | } |
@@ -757,7 +1052,6 @@ EXPORT_SYMBOL(omap_mcbsp_recv_word); | |||
757 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | 1052 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) |
758 | { | 1053 | { |
759 | struct omap_mcbsp *mcbsp; | 1054 | struct omap_mcbsp *mcbsp; |
760 | void __iomem *io_base; | ||
761 | omap_mcbsp_word_length tx_word_length; | 1055 | omap_mcbsp_word_length tx_word_length; |
762 | omap_mcbsp_word_length rx_word_length; | 1056 | omap_mcbsp_word_length rx_word_length; |
763 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 1057 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
@@ -767,7 +1061,6 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
767 | return -ENODEV; | 1061 | return -ENODEV; |
768 | } | 1062 | } |
769 | mcbsp = id_to_mcbsp_ptr(id); | 1063 | mcbsp = id_to_mcbsp_ptr(id); |
770 | io_base = mcbsp->io_base; | ||
771 | tx_word_length = mcbsp->tx_word_length; | 1064 | tx_word_length = mcbsp->tx_word_length; |
772 | rx_word_length = mcbsp->rx_word_length; | 1065 | rx_word_length = mcbsp->rx_word_length; |
773 | 1066 | ||
@@ -775,14 +1068,16 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
775 | return -EINVAL; | 1068 | return -EINVAL; |
776 | 1069 | ||
777 | /* First we wait for the transmitter to be ready */ | 1070 | /* First we wait for the transmitter to be ready */ |
778 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | 1071 | spcr2 = MCBSP_READ(mcbsp, SPCR2); |
779 | while (!(spcr2 & XRDY)) { | 1072 | while (!(spcr2 & XRDY)) { |
780 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | 1073 | spcr2 = MCBSP_READ(mcbsp, SPCR2); |
781 | if (attempts++ > 1000) { | 1074 | if (attempts++ > 1000) { |
782 | /* We must reset the transmitter */ | 1075 | /* We must reset the transmitter */ |
783 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST)); | 1076 | MCBSP_WRITE(mcbsp, SPCR2, |
1077 | MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST)); | ||
784 | udelay(10); | 1078 | udelay(10); |
785 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 1079 | MCBSP_WRITE(mcbsp, SPCR2, |
1080 | MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST); | ||
786 | udelay(10); | 1081 | udelay(10); |
787 | dev_err(mcbsp->dev, "McBSP%d transmitter not " | 1082 | dev_err(mcbsp->dev, "McBSP%d transmitter not " |
788 | "ready\n", mcbsp->id); | 1083 | "ready\n", mcbsp->id); |
@@ -792,18 +1087,20 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
792 | 1087 | ||
793 | /* Now we can push the data */ | 1088 | /* Now we can push the data */ |
794 | if (tx_word_length > OMAP_MCBSP_WORD_16) | 1089 | if (tx_word_length > OMAP_MCBSP_WORD_16) |
795 | OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16); | 1090 | MCBSP_WRITE(mcbsp, DXR2, word >> 16); |
796 | OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff); | 1091 | MCBSP_WRITE(mcbsp, DXR1, word & 0xffff); |
797 | 1092 | ||
798 | /* We wait for the receiver to be ready */ | 1093 | /* We wait for the receiver to be ready */ |
799 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | 1094 | spcr1 = MCBSP_READ(mcbsp, SPCR1); |
800 | while (!(spcr1 & RRDY)) { | 1095 | while (!(spcr1 & RRDY)) { |
801 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | 1096 | spcr1 = MCBSP_READ(mcbsp, SPCR1); |
802 | if (attempts++ > 1000) { | 1097 | if (attempts++ > 1000) { |
803 | /* We must reset the receiver */ | 1098 | /* We must reset the receiver */ |
804 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST)); | 1099 | MCBSP_WRITE(mcbsp, SPCR1, |
1100 | MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST)); | ||
805 | udelay(10); | 1101 | udelay(10); |
806 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 1102 | MCBSP_WRITE(mcbsp, SPCR1, |
1103 | MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST); | ||
807 | udelay(10); | 1104 | udelay(10); |
808 | dev_err(mcbsp->dev, "McBSP%d receiver not " | 1105 | dev_err(mcbsp->dev, "McBSP%d receiver not " |
809 | "ready\n", mcbsp->id); | 1106 | "ready\n", mcbsp->id); |
@@ -813,8 +1110,8 @@ int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | |||
813 | 1110 | ||
814 | /* Receiver is ready, let's read the dummy data */ | 1111 | /* Receiver is ready, let's read the dummy data */ |
815 | if (rx_word_length > OMAP_MCBSP_WORD_16) | 1112 | if (rx_word_length > OMAP_MCBSP_WORD_16) |
816 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | 1113 | word_msb = MCBSP_READ(mcbsp, DRR2); |
817 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | 1114 | word_lsb = MCBSP_READ(mcbsp, DRR1); |
818 | 1115 | ||
819 | return 0; | 1116 | return 0; |
820 | } | 1117 | } |
@@ -824,7 +1121,6 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
824 | { | 1121 | { |
825 | struct omap_mcbsp *mcbsp; | 1122 | struct omap_mcbsp *mcbsp; |
826 | u32 clock_word = 0; | 1123 | u32 clock_word = 0; |
827 | void __iomem *io_base; | ||
828 | omap_mcbsp_word_length tx_word_length; | 1124 | omap_mcbsp_word_length tx_word_length; |
829 | omap_mcbsp_word_length rx_word_length; | 1125 | omap_mcbsp_word_length rx_word_length; |
830 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | 1126 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; |
@@ -835,7 +1131,6 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
835 | } | 1131 | } |
836 | 1132 | ||
837 | mcbsp = id_to_mcbsp_ptr(id); | 1133 | mcbsp = id_to_mcbsp_ptr(id); |
838 | io_base = mcbsp->io_base; | ||
839 | 1134 | ||
840 | tx_word_length = mcbsp->tx_word_length; | 1135 | tx_word_length = mcbsp->tx_word_length; |
841 | rx_word_length = mcbsp->rx_word_length; | 1136 | rx_word_length = mcbsp->rx_word_length; |
@@ -844,14 +1139,16 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
844 | return -EINVAL; | 1139 | return -EINVAL; |
845 | 1140 | ||
846 | /* First we wait for the transmitter to be ready */ | 1141 | /* First we wait for the transmitter to be ready */ |
847 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | 1142 | spcr2 = MCBSP_READ(mcbsp, SPCR2); |
848 | while (!(spcr2 & XRDY)) { | 1143 | while (!(spcr2 & XRDY)) { |
849 | spcr2 = OMAP_MCBSP_READ(io_base, SPCR2); | 1144 | spcr2 = MCBSP_READ(mcbsp, SPCR2); |
850 | if (attempts++ > 1000) { | 1145 | if (attempts++ > 1000) { |
851 | /* We must reset the transmitter */ | 1146 | /* We must reset the transmitter */ |
852 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST)); | 1147 | MCBSP_WRITE(mcbsp, SPCR2, |
1148 | MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST)); | ||
853 | udelay(10); | 1149 | udelay(10); |
854 | OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST); | 1150 | MCBSP_WRITE(mcbsp, SPCR2, |
1151 | MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST); | ||
855 | udelay(10); | 1152 | udelay(10); |
856 | dev_err(mcbsp->dev, "McBSP%d transmitter not " | 1153 | dev_err(mcbsp->dev, "McBSP%d transmitter not " |
857 | "ready\n", mcbsp->id); | 1154 | "ready\n", mcbsp->id); |
@@ -861,18 +1158,20 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
861 | 1158 | ||
862 | /* We first need to enable the bus clock */ | 1159 | /* We first need to enable the bus clock */ |
863 | if (tx_word_length > OMAP_MCBSP_WORD_16) | 1160 | if (tx_word_length > OMAP_MCBSP_WORD_16) |
864 | OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16); | 1161 | MCBSP_WRITE(mcbsp, DXR2, clock_word >> 16); |
865 | OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff); | 1162 | MCBSP_WRITE(mcbsp, DXR1, clock_word & 0xffff); |
866 | 1163 | ||
867 | /* We wait for the receiver to be ready */ | 1164 | /* We wait for the receiver to be ready */ |
868 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | 1165 | spcr1 = MCBSP_READ(mcbsp, SPCR1); |
869 | while (!(spcr1 & RRDY)) { | 1166 | while (!(spcr1 & RRDY)) { |
870 | spcr1 = OMAP_MCBSP_READ(io_base, SPCR1); | 1167 | spcr1 = MCBSP_READ(mcbsp, SPCR1); |
871 | if (attempts++ > 1000) { | 1168 | if (attempts++ > 1000) { |
872 | /* We must reset the receiver */ | 1169 | /* We must reset the receiver */ |
873 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST)); | 1170 | MCBSP_WRITE(mcbsp, SPCR1, |
1171 | MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST)); | ||
874 | udelay(10); | 1172 | udelay(10); |
875 | OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST); | 1173 | MCBSP_WRITE(mcbsp, SPCR1, |
1174 | MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST); | ||
876 | udelay(10); | 1175 | udelay(10); |
877 | dev_err(mcbsp->dev, "McBSP%d receiver not " | 1176 | dev_err(mcbsp->dev, "McBSP%d receiver not " |
878 | "ready\n", mcbsp->id); | 1177 | "ready\n", mcbsp->id); |
@@ -882,8 +1181,8 @@ int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | |||
882 | 1181 | ||
883 | /* Receiver is ready, there is something for us */ | 1182 | /* Receiver is ready, there is something for us */ |
884 | if (rx_word_length > OMAP_MCBSP_WORD_16) | 1183 | if (rx_word_length > OMAP_MCBSP_WORD_16) |
885 | word_msb = OMAP_MCBSP_READ(io_base, DRR2); | 1184 | word_msb = MCBSP_READ(mcbsp, DRR2); |
886 | word_lsb = OMAP_MCBSP_READ(io_base, DRR1); | 1185 | word_lsb = MCBSP_READ(mcbsp, DRR1); |
887 | 1186 | ||
888 | word[0] = (word_lsb | (word_msb << 16)); | 1187 | word[0] = (word_lsb | (word_msb << 16)); |
889 | 1188 | ||
@@ -1097,7 +1396,7 @@ void omap_mcbsp_set_spi_mode(unsigned int id, | |||
1097 | } | 1396 | } |
1098 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | 1397 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); |
1099 | 1398 | ||
1100 | #ifdef CONFIG_ARCH_OMAP34XX | 1399 | #ifdef CONFIG_ARCH_OMAP3 |
1101 | #define max_thres(m) (mcbsp->pdata->buffer_size) | 1400 | #define max_thres(m) (mcbsp->pdata->buffer_size) |
1102 | #define valid_threshold(m, val) ((val) <= max_thres(m)) | 1401 | #define valid_threshold(m, val) ((val) <= max_thres(m)) |
1103 | #define THRESHOLD_PROP_BUILDER(prop) \ | 1402 | #define THRESHOLD_PROP_BUILDER(prop) \ |
@@ -1145,9 +1444,7 @@ static ssize_t dma_op_mode_show(struct device *dev, | |||
1145 | ssize_t len = 0; | 1444 | ssize_t len = 0; |
1146 | const char * const *s; | 1445 | const char * const *s; |
1147 | 1446 | ||
1148 | spin_lock_irq(&mcbsp->lock); | ||
1149 | dma_op_mode = mcbsp->dma_op_mode; | 1447 | dma_op_mode = mcbsp->dma_op_mode; |
1150 | spin_unlock_irq(&mcbsp->lock); | ||
1151 | 1448 | ||
1152 | for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) { | 1449 | for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) { |
1153 | if (dma_op_mode == i) | 1450 | if (dma_op_mode == i) |
@@ -1190,6 +1487,64 @@ unlock: | |||
1190 | 1487 | ||
1191 | static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); | 1488 | static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store); |
1192 | 1489 | ||
1490 | static ssize_t st_taps_show(struct device *dev, | ||
1491 | struct device_attribute *attr, char *buf) | ||
1492 | { | ||
1493 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); | ||
1494 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | ||
1495 | ssize_t status = 0; | ||
1496 | int i; | ||
1497 | |||
1498 | spin_lock_irq(&mcbsp->lock); | ||
1499 | for (i = 0; i < st_data->nr_taps; i++) | ||
1500 | status += sprintf(&buf[status], (i ? ", %d" : "%d"), | ||
1501 | st_data->taps[i]); | ||
1502 | if (i) | ||
1503 | status += sprintf(&buf[status], "\n"); | ||
1504 | spin_unlock_irq(&mcbsp->lock); | ||
1505 | |||
1506 | return status; | ||
1507 | } | ||
1508 | |||
1509 | static ssize_t st_taps_store(struct device *dev, | ||
1510 | struct device_attribute *attr, | ||
1511 | const char *buf, size_t size) | ||
1512 | { | ||
1513 | struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); | ||
1514 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | ||
1515 | int val, tmp, status, i = 0; | ||
1516 | |||
1517 | spin_lock_irq(&mcbsp->lock); | ||
1518 | memset(st_data->taps, 0, sizeof(st_data->taps)); | ||
1519 | st_data->nr_taps = 0; | ||
1520 | |||
1521 | do { | ||
1522 | status = sscanf(buf, "%d%n", &val, &tmp); | ||
1523 | if (status < 0 || status == 0) { | ||
1524 | size = -EINVAL; | ||
1525 | goto out; | ||
1526 | } | ||
1527 | if (val < -32768 || val > 32767) { | ||
1528 | size = -EINVAL; | ||
1529 | goto out; | ||
1530 | } | ||
1531 | st_data->taps[i++] = val; | ||
1532 | buf += tmp; | ||
1533 | if (*buf != ',') | ||
1534 | break; | ||
1535 | buf++; | ||
1536 | } while (1); | ||
1537 | |||
1538 | st_data->nr_taps = i; | ||
1539 | |||
1540 | out: | ||
1541 | spin_unlock_irq(&mcbsp->lock); | ||
1542 | |||
1543 | return size; | ||
1544 | } | ||
1545 | |||
1546 | static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store); | ||
1547 | |||
1193 | static const struct attribute *additional_attrs[] = { | 1548 | static const struct attribute *additional_attrs[] = { |
1194 | &dev_attr_max_tx_thres.attr, | 1549 | &dev_attr_max_tx_thres.attr, |
1195 | &dev_attr_max_rx_thres.attr, | 1550 | &dev_attr_max_rx_thres.attr, |
@@ -1211,6 +1566,60 @@ static inline void __devexit omap_additional_remove(struct device *dev) | |||
1211 | sysfs_remove_group(&dev->kobj, &additional_attr_group); | 1566 | sysfs_remove_group(&dev->kobj, &additional_attr_group); |
1212 | } | 1567 | } |
1213 | 1568 | ||
1569 | static const struct attribute *sidetone_attrs[] = { | ||
1570 | &dev_attr_st_taps.attr, | ||
1571 | NULL, | ||
1572 | }; | ||
1573 | |||
1574 | static const struct attribute_group sidetone_attr_group = { | ||
1575 | .attrs = (struct attribute **)sidetone_attrs, | ||
1576 | }; | ||
1577 | |||
1578 | int __devinit omap_st_add(struct omap_mcbsp *mcbsp) | ||
1579 | { | ||
1580 | struct omap_mcbsp_platform_data *pdata = mcbsp->pdata; | ||
1581 | struct omap_mcbsp_st_data *st_data; | ||
1582 | int err; | ||
1583 | |||
1584 | st_data = kzalloc(sizeof(*mcbsp->st_data), GFP_KERNEL); | ||
1585 | if (!st_data) { | ||
1586 | err = -ENOMEM; | ||
1587 | goto err1; | ||
1588 | } | ||
1589 | |||
1590 | st_data->io_base_st = ioremap(pdata->phys_base_st, SZ_4K); | ||
1591 | if (!st_data->io_base_st) { | ||
1592 | err = -ENOMEM; | ||
1593 | goto err2; | ||
1594 | } | ||
1595 | |||
1596 | err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group); | ||
1597 | if (err) | ||
1598 | goto err3; | ||
1599 | |||
1600 | mcbsp->st_data = st_data; | ||
1601 | return 0; | ||
1602 | |||
1603 | err3: | ||
1604 | iounmap(st_data->io_base_st); | ||
1605 | err2: | ||
1606 | kfree(st_data); | ||
1607 | err1: | ||
1608 | return err; | ||
1609 | |||
1610 | } | ||
1611 | |||
1612 | static void __devexit omap_st_remove(struct omap_mcbsp *mcbsp) | ||
1613 | { | ||
1614 | struct omap_mcbsp_st_data *st_data = mcbsp->st_data; | ||
1615 | |||
1616 | if (st_data) { | ||
1617 | sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group); | ||
1618 | iounmap(st_data->io_base_st); | ||
1619 | kfree(st_data); | ||
1620 | } | ||
1621 | } | ||
1622 | |||
1214 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) | 1623 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) |
1215 | { | 1624 | { |
1216 | mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; | 1625 | mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT; |
@@ -1224,6 +1633,12 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) | |||
1224 | if (omap_additional_add(mcbsp->dev)) | 1633 | if (omap_additional_add(mcbsp->dev)) |
1225 | dev_warn(mcbsp->dev, | 1634 | dev_warn(mcbsp->dev, |
1226 | "Unable to create additional controls\n"); | 1635 | "Unable to create additional controls\n"); |
1636 | |||
1637 | if (mcbsp->id == 2 || mcbsp->id == 3) | ||
1638 | if (omap_st_add(mcbsp)) | ||
1639 | dev_warn(mcbsp->dev, | ||
1640 | "Unable to create sidetone controls\n"); | ||
1641 | |||
1227 | } else { | 1642 | } else { |
1228 | mcbsp->max_tx_thres = -EINVAL; | 1643 | mcbsp->max_tx_thres = -EINVAL; |
1229 | mcbsp->max_rx_thres = -EINVAL; | 1644 | mcbsp->max_rx_thres = -EINVAL; |
@@ -1232,13 +1647,17 @@ static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) | |||
1232 | 1647 | ||
1233 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) | 1648 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) |
1234 | { | 1649 | { |
1235 | if (cpu_is_omap34xx()) | 1650 | if (cpu_is_omap34xx()) { |
1236 | omap_additional_remove(mcbsp->dev); | 1651 | omap_additional_remove(mcbsp->dev); |
1652 | |||
1653 | if (mcbsp->id == 2 || mcbsp->id == 3) | ||
1654 | omap_st_remove(mcbsp); | ||
1655 | } | ||
1237 | } | 1656 | } |
1238 | #else | 1657 | #else |
1239 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} | 1658 | static inline void __devinit omap34xx_device_init(struct omap_mcbsp *mcbsp) {} |
1240 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {} | 1659 | static inline void __devexit omap34xx_device_exit(struct omap_mcbsp *mcbsp) {} |
1241 | #endif /* CONFIG_ARCH_OMAP34XX */ | 1660 | #endif /* CONFIG_ARCH_OMAP3 */ |
1242 | 1661 | ||
1243 | /* | 1662 | /* |
1244 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. | 1663 | * McBSP1 and McBSP3 are directly mapped on 1610 and 1510. |