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