Merge branch 'fixes' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'fixes' of master.kernel.org:/home/rmk/linux-2.6-arm: ALSA: AACI: fix timeout duration ALSA: AACI: fix timeout condition checking ARM: 6636/1: ep93xx: default multiplexed gpio ports to gpio mode ARM: 6637/1: Make the argument to virt_to_phys() "const volatile" ARM: twd: ensure timer reload is reprogrammed on entry to periodic mode ARM: 6635/2: Configure reference clock for Versatile Express timers ARM: versatile: name configuration options after actual board names ARM: realview: name configuration options after actual board names ARM: realview,vexpress: fix section mismatch warning for pen_release ARM: 6632/3: mmci: stop using the blockend interrupts
This commit is contained in:
@@ -50,6 +50,12 @@
|
|||||||
#define SCPCELLID2 0xFF8
|
#define SCPCELLID2 0xFF8
|
||||||
#define SCPCELLID3 0xFFC
|
#define SCPCELLID3 0xFFC
|
||||||
|
|
||||||
|
#define SCCTRL_TIMEREN0SEL_REFCLK (0 << 15)
|
||||||
|
#define SCCTRL_TIMEREN0SEL_TIMCLK (1 << 15)
|
||||||
|
|
||||||
|
#define SCCTRL_TIMEREN1SEL_REFCLK (0 << 17)
|
||||||
|
#define SCCTRL_TIMEREN1SEL_TIMCLK (1 << 17)
|
||||||
|
|
||||||
static inline void sysctl_soft_reset(void __iomem *base)
|
static inline void sysctl_soft_reset(void __iomem *base)
|
||||||
{
|
{
|
||||||
/* writing any value to SCSYSSTAT reg will reset system */
|
/* writing any value to SCSYSSTAT reg will reset system */
|
||||||
|
@@ -188,7 +188,7 @@
|
|||||||
* translation for translating DMA addresses. Use the driver
|
* translation for translating DMA addresses. Use the driver
|
||||||
* DMA support - see dma-mapping.h.
|
* DMA support - see dma-mapping.h.
|
||||||
*/
|
*/
|
||||||
static inline unsigned long virt_to_phys(void *x)
|
static inline unsigned long virt_to_phys(const volatile void *x)
|
||||||
{
|
{
|
||||||
return __virt_to_phys((unsigned long)(x));
|
return __virt_to_phys((unsigned long)(x));
|
||||||
}
|
}
|
||||||
|
@@ -36,6 +36,7 @@ static void twd_set_mode(enum clock_event_mode mode,
|
|||||||
/* timer load already set up */
|
/* timer load already set up */
|
||||||
ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
|
ctrl = TWD_TIMER_CONTROL_ENABLE | TWD_TIMER_CONTROL_IT_ENABLE
|
||||||
| TWD_TIMER_CONTROL_PERIODIC;
|
| TWD_TIMER_CONTROL_PERIODIC;
|
||||||
|
__raw_writel(twd_timer_rate / HZ, twd_base + TWD_TIMER_LOAD);
|
||||||
break;
|
break;
|
||||||
case CLOCK_EVT_MODE_ONESHOT:
|
case CLOCK_EVT_MODE_ONESHOT:
|
||||||
/* period set, and timer enabled in 'next_event' hook */
|
/* period set, and timer enabled in 'next_event' hook */
|
||||||
@@ -81,7 +82,7 @@ int twd_timer_ack(void)
|
|||||||
|
|
||||||
static void __cpuinit twd_calibrate_rate(void)
|
static void __cpuinit twd_calibrate_rate(void)
|
||||||
{
|
{
|
||||||
unsigned long load, count;
|
unsigned long count;
|
||||||
u64 waitjiffies;
|
u64 waitjiffies;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -116,10 +117,6 @@ static void __cpuinit twd_calibrate_rate(void)
|
|||||||
printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
|
printk("%lu.%02luMHz.\n", twd_timer_rate / 1000000,
|
||||||
(twd_timer_rate / 1000000) % 100);
|
(twd_timer_rate / 1000000) % 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
load = twd_timer_rate / HZ;
|
|
||||||
|
|
||||||
__raw_writel(load, twd_base + TWD_TIMER_LOAD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -427,6 +427,13 @@ void __init ep93xx_gpio_init(void)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* Set Ports C, D, E, G, and H for GPIO use */
|
||||||
|
ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_KEYS |
|
||||||
|
EP93XX_SYSCON_DEVCFG_GONK |
|
||||||
|
EP93XX_SYSCON_DEVCFG_EONIDE |
|
||||||
|
EP93XX_SYSCON_DEVCFG_GONIDE |
|
||||||
|
EP93XX_SYSCON_DEVCFG_HONIDE);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
|
for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
|
||||||
gpiochip_add(&ep93xx_gpio_banks[i].chip);
|
gpiochip_add(&ep93xx_gpio_banks[i].chip);
|
||||||
}
|
}
|
||||||
|
@@ -2,52 +2,56 @@ menu "RealView platform type"
|
|||||||
depends on ARCH_REALVIEW
|
depends on ARCH_REALVIEW
|
||||||
|
|
||||||
config MACH_REALVIEW_EB
|
config MACH_REALVIEW_EB
|
||||||
bool "Support RealView/EB platform"
|
bool "Support RealView(R) Emulation Baseboard"
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) RealView Emulation Baseboard platform.
|
Include support for the ARM(R) RealView(R) Emulation Baseboard
|
||||||
|
platform.
|
||||||
|
|
||||||
config REALVIEW_EB_A9MP
|
config REALVIEW_EB_A9MP
|
||||||
bool "Support Multicore Cortex-A9"
|
bool "Support Multicore Cortex-A9 Tile"
|
||||||
depends on MACH_REALVIEW_EB
|
depends on MACH_REALVIEW_EB
|
||||||
select CPU_V7
|
select CPU_V7
|
||||||
help
|
help
|
||||||
Enable support for the Cortex-A9MPCore tile on the Realview platform.
|
Enable support for the Cortex-A9MPCore tile fitted to the
|
||||||
|
Realview(R) Emulation Baseboard platform.
|
||||||
|
|
||||||
config REALVIEW_EB_ARM11MP
|
config REALVIEW_EB_ARM11MP
|
||||||
bool "Support ARM11MPCore tile"
|
bool "Support ARM11MPCore Tile"
|
||||||
depends on MACH_REALVIEW_EB
|
depends on MACH_REALVIEW_EB
|
||||||
select CPU_V6
|
select CPU_V6
|
||||||
select ARCH_HAS_BARRIERS if SMP
|
select ARCH_HAS_BARRIERS if SMP
|
||||||
help
|
help
|
||||||
Enable support for the ARM11MPCore tile on the Realview platform.
|
Enable support for the ARM11MPCore tile fitted to the Realview(R)
|
||||||
|
Emulation Baseboard platform.
|
||||||
|
|
||||||
config REALVIEW_EB_ARM11MP_REVB
|
config REALVIEW_EB_ARM11MP_REVB
|
||||||
bool "Support ARM11MPCore RevB tile"
|
bool "Support ARM11MPCore RevB Tile"
|
||||||
depends on REALVIEW_EB_ARM11MP
|
depends on REALVIEW_EB_ARM11MP
|
||||||
help
|
help
|
||||||
Enable support for the ARM11MPCore RevB tile on the Realview
|
Enable support for the ARM11MPCore Revision B tile on the
|
||||||
platform. Since there are device address differences, a
|
Realview(R) Emulation Baseboard platform. Since there are device
|
||||||
kernel built with this option enabled is not compatible with
|
address differences, a kernel built with this option enabled is
|
||||||
other revisions of the ARM11MPCore tile.
|
not compatible with other revisions of the ARM11MPCore tile.
|
||||||
|
|
||||||
config MACH_REALVIEW_PB11MP
|
config MACH_REALVIEW_PB11MP
|
||||||
bool "Support RealView/PB11MPCore platform"
|
bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
|
||||||
select CPU_V6
|
select CPU_V6
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
select HAVE_PATA_PLATFORM
|
select HAVE_PATA_PLATFORM
|
||||||
select ARCH_HAS_BARRIERS if SMP
|
select ARCH_HAS_BARRIERS if SMP
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) RealView MPCore Platform Baseboard.
|
Include support for the ARM(R) RealView(R) Platform Baseboard for
|
||||||
PB11MPCore is a platform with an on-board ARM11MPCore and has
|
the ARM11MPCore. This platform has an on-board ARM11MPCore and has
|
||||||
support for PCI-E and Compact Flash.
|
support for PCI-E and Compact Flash.
|
||||||
|
|
||||||
config MACH_REALVIEW_PB1176
|
config MACH_REALVIEW_PB1176
|
||||||
bool "Support RealView/PB1176 platform"
|
bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
|
||||||
select CPU_V6
|
select CPU_V6
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) RealView ARM1176 Platform Baseboard.
|
Include support for the ARM(R) RealView(R) Platform Baseboard for
|
||||||
|
ARM1176JZF-S.
|
||||||
|
|
||||||
config REALVIEW_PB1176_SECURE_FLASH
|
config REALVIEW_PB1176_SECURE_FLASH
|
||||||
bool "Allow access to the secure flash memory block"
|
bool "Allow access to the secure flash memory block"
|
||||||
@@ -59,23 +63,24 @@ config REALVIEW_PB1176_SECURE_FLASH
|
|||||||
block (64MB @ 0x3c000000) is required.
|
block (64MB @ 0x3c000000) is required.
|
||||||
|
|
||||||
config MACH_REALVIEW_PBA8
|
config MACH_REALVIEW_PBA8
|
||||||
bool "Support RealView/PB-A8 platform"
|
bool "Support RealView(R) Platform Baseboard for Cortex(tm)-A8 platform"
|
||||||
select CPU_V7
|
select CPU_V7
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
select HAVE_PATA_PLATFORM
|
select HAVE_PATA_PLATFORM
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) RealView Cortex-A8 Platform Baseboard.
|
Include support for the ARM(R) RealView Platform Baseboard for
|
||||||
PB-A8 is a platform with an on-board Cortex-A8 and has support for
|
Cortex(tm)-A8. This platform has an on-board Cortex-A8 and has
|
||||||
PCI-E and Compact Flash.
|
support for PCI-E and Compact Flash.
|
||||||
|
|
||||||
config MACH_REALVIEW_PBX
|
config MACH_REALVIEW_PBX
|
||||||
bool "Support RealView/PBX platform"
|
bool "Support RealView(R) Platform Baseboard Explore"
|
||||||
select ARM_GIC
|
select ARM_GIC
|
||||||
select HAVE_PATA_PLATFORM
|
select HAVE_PATA_PLATFORM
|
||||||
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
|
select ARCH_SPARSEMEM_ENABLE if CPU_V7 && !REALVIEW_HIGH_PHYS_OFFSET
|
||||||
select ZONE_DMA if SPARSEMEM
|
select ZONE_DMA if SPARSEMEM
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) RealView PBX platform.
|
Include support for the ARM(R) RealView(R) Platform Baseboard
|
||||||
|
Explore.
|
||||||
|
|
||||||
config REALVIEW_HIGH_PHYS_OFFSET
|
config REALVIEW_HIGH_PHYS_OFFSET
|
||||||
bool "High physical base address for the RealView platform"
|
bool "High physical base address for the RealView platform"
|
||||||
|
@@ -41,7 +41,7 @@ volatile int __cpuinitdata pen_release = -1;
|
|||||||
* observers, irrespective of whether they're taking part in coherency
|
* observers, irrespective of whether they're taking part in coherency
|
||||||
* or not. This is necessary for the hotplug code to work reliably.
|
* or not. This is necessary for the hotplug code to work reliably.
|
||||||
*/
|
*/
|
||||||
static void write_pen_release(int val)
|
static void __cpuinit write_pen_release(int val)
|
||||||
{
|
{
|
||||||
pen_release = val;
|
pen_release = val;
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
@@ -2,17 +2,19 @@ menu "Versatile platform type"
|
|||||||
depends on ARCH_VERSATILE
|
depends on ARCH_VERSATILE
|
||||||
|
|
||||||
config ARCH_VERSATILE_PB
|
config ARCH_VERSATILE_PB
|
||||||
bool "Support Versatile/PB platform"
|
bool "Support Versatile Platform Baseboard for ARM926EJ-S"
|
||||||
select CPU_ARM926T
|
select CPU_ARM926T
|
||||||
select MIGHT_HAVE_PCI
|
select MIGHT_HAVE_PCI
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) Versatile/PB platform.
|
Include support for the ARM(R) Versatile Platform Baseboard
|
||||||
|
for the ARM926EJ-S.
|
||||||
|
|
||||||
config MACH_VERSATILE_AB
|
config MACH_VERSATILE_AB
|
||||||
bool "Support Versatile/AB platform"
|
bool "Support Versatile Application Baseboard for ARM926EJ-S"
|
||||||
select CPU_ARM926T
|
select CPU_ARM926T
|
||||||
help
|
help
|
||||||
Include support for the ARM(R) Versatile/AP platform.
|
Include support for the ARM(R) Versatile Application Baseboard
|
||||||
|
for the ARM926EJ-S.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
@@ -39,7 +39,7 @@ volatile int __cpuinitdata pen_release = -1;
|
|||||||
* observers, irrespective of whether they're taking part in coherency
|
* observers, irrespective of whether they're taking part in coherency
|
||||||
* or not. This is necessary for the hotplug code to work reliably.
|
* or not. This is necessary for the hotplug code to work reliably.
|
||||||
*/
|
*/
|
||||||
static void write_pen_release(int val)
|
static void __cpuinit write_pen_release(int val)
|
||||||
{
|
{
|
||||||
pen_release = val;
|
pen_release = val;
|
||||||
smp_wmb();
|
smp_wmb();
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include <asm/mach/time.h>
|
#include <asm/mach/time.h>
|
||||||
#include <asm/hardware/arm_timer.h>
|
#include <asm/hardware/arm_timer.h>
|
||||||
#include <asm/hardware/timer-sp.h>
|
#include <asm/hardware/timer-sp.h>
|
||||||
|
#include <asm/hardware/sp810.h>
|
||||||
|
|
||||||
#include <mach/motherboard.h>
|
#include <mach/motherboard.h>
|
||||||
|
|
||||||
@@ -50,8 +51,16 @@ void __init v2m_map_io(struct map_desc *tile, size_t num)
|
|||||||
|
|
||||||
static void __init v2m_timer_init(void)
|
static void __init v2m_timer_init(void)
|
||||||
{
|
{
|
||||||
|
u32 scctrl;
|
||||||
|
|
||||||
versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
|
versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
|
||||||
|
|
||||||
|
/* Select 1MHz TIMCLK as the reference clock for SP804 timers */
|
||||||
|
scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL));
|
||||||
|
scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
|
||||||
|
scctrl |= SCCTRL_TIMEREN1SEL_TIMCLK;
|
||||||
|
writel(scctrl, MMIO_P2V(V2M_SYSCTL + SCCTRL));
|
||||||
|
|
||||||
writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
|
writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
|
||||||
writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
|
writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
|
||||||
|
|
||||||
|
@@ -46,10 +46,6 @@ static unsigned int fmax = 515633;
|
|||||||
* is asserted (likewise for RX)
|
* is asserted (likewise for RX)
|
||||||
* @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
|
* @fifohalfsize: number of bytes that can be written when MCI_TXFIFOHALFEMPTY
|
||||||
* is asserted (likewise for RX)
|
* is asserted (likewise for RX)
|
||||||
* @broken_blockend: the MCI_DATABLOCKEND is broken on the hardware
|
|
||||||
* and will not work at all.
|
|
||||||
* @broken_blockend_dma: the MCI_DATABLOCKEND is broken on the hardware when
|
|
||||||
* using DMA.
|
|
||||||
* @sdio: variant supports SDIO
|
* @sdio: variant supports SDIO
|
||||||
* @st_clkdiv: true if using a ST-specific clock divider algorithm
|
* @st_clkdiv: true if using a ST-specific clock divider algorithm
|
||||||
*/
|
*/
|
||||||
@@ -59,8 +55,6 @@ struct variant_data {
|
|||||||
unsigned int datalength_bits;
|
unsigned int datalength_bits;
|
||||||
unsigned int fifosize;
|
unsigned int fifosize;
|
||||||
unsigned int fifohalfsize;
|
unsigned int fifohalfsize;
|
||||||
bool broken_blockend;
|
|
||||||
bool broken_blockend_dma;
|
|
||||||
bool sdio;
|
bool sdio;
|
||||||
bool st_clkdiv;
|
bool st_clkdiv;
|
||||||
};
|
};
|
||||||
@@ -76,7 +70,6 @@ static struct variant_data variant_u300 = {
|
|||||||
.fifohalfsize = 8 * 4,
|
.fifohalfsize = 8 * 4,
|
||||||
.clkreg_enable = 1 << 13, /* HWFCEN */
|
.clkreg_enable = 1 << 13, /* HWFCEN */
|
||||||
.datalength_bits = 16,
|
.datalength_bits = 16,
|
||||||
.broken_blockend_dma = true,
|
|
||||||
.sdio = true,
|
.sdio = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,7 +79,6 @@ static struct variant_data variant_ux500 = {
|
|||||||
.clkreg = MCI_CLK_ENABLE,
|
.clkreg = MCI_CLK_ENABLE,
|
||||||
.clkreg_enable = 1 << 14, /* HWFCEN */
|
.clkreg_enable = 1 << 14, /* HWFCEN */
|
||||||
.datalength_bits = 24,
|
.datalength_bits = 24,
|
||||||
.broken_blockend = true,
|
|
||||||
.sdio = true,
|
.sdio = true,
|
||||||
.st_clkdiv = true,
|
.st_clkdiv = true,
|
||||||
};
|
};
|
||||||
@@ -210,8 +202,6 @@ static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
|
|||||||
host->data = data;
|
host->data = data;
|
||||||
host->size = data->blksz * data->blocks;
|
host->size = data->blksz * data->blocks;
|
||||||
host->data_xfered = 0;
|
host->data_xfered = 0;
|
||||||
host->blockend = false;
|
|
||||||
host->dataend = false;
|
|
||||||
|
|
||||||
mmci_init_sg(host, data);
|
mmci_init_sg(host, data);
|
||||||
|
|
||||||
@@ -288,21 +278,26 @@ static void
|
|||||||
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
||||||
unsigned int status)
|
unsigned int status)
|
||||||
{
|
{
|
||||||
struct variant_data *variant = host->variant;
|
|
||||||
|
|
||||||
/* First check for errors */
|
/* First check for errors */
|
||||||
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
|
if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
|
||||||
dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
|
u32 remain, success;
|
||||||
if (status & MCI_DATACRCFAIL)
|
|
||||||
data->error = -EILSEQ;
|
|
||||||
else if (status & MCI_DATATIMEOUT)
|
|
||||||
data->error = -ETIMEDOUT;
|
|
||||||
else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN))
|
|
||||||
data->error = -EIO;
|
|
||||||
|
|
||||||
/* Force-complete the transaction */
|
/* Calculate how far we are into the transfer */
|
||||||
host->blockend = true;
|
remain = readl(host->base + MMCIDATACNT) << 2;
|
||||||
host->dataend = true;
|
success = data->blksz * data->blocks - remain;
|
||||||
|
|
||||||
|
dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
|
||||||
|
if (status & MCI_DATACRCFAIL) {
|
||||||
|
/* Last block was not successful */
|
||||||
|
host->data_xfered = ((success / data->blksz) - 1 * data->blksz);
|
||||||
|
data->error = -EILSEQ;
|
||||||
|
} else if (status & MCI_DATATIMEOUT) {
|
||||||
|
host->data_xfered = success;
|
||||||
|
data->error = -ETIMEDOUT;
|
||||||
|
} else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
|
||||||
|
host->data_xfered = success;
|
||||||
|
data->error = -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We hit an error condition. Ensure that any data
|
* We hit an error condition. Ensure that any data
|
||||||
@@ -321,61 +316,14 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (status & MCI_DATABLOCKEND)
|
||||||
* On ARM variants in PIO mode, MCI_DATABLOCKEND
|
dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
|
||||||
* is always sent first, and we increase the
|
|
||||||
* transfered number of bytes for that IRQ. Then
|
|
||||||
* MCI_DATAEND follows and we conclude the transaction.
|
|
||||||
*
|
|
||||||
* On the Ux500 single-IRQ variant MCI_DATABLOCKEND
|
|
||||||
* doesn't seem to immediately clear from the status,
|
|
||||||
* so we can't use it keep count when only one irq is
|
|
||||||
* used because the irq will hit for other reasons, and
|
|
||||||
* then the flag is still up. So we use the MCI_DATAEND
|
|
||||||
* IRQ at the end of the entire transfer because
|
|
||||||
* MCI_DATABLOCKEND is broken.
|
|
||||||
*
|
|
||||||
* In the U300, the IRQs can arrive out-of-order,
|
|
||||||
* e.g. MCI_DATABLOCKEND sometimes arrives after MCI_DATAEND,
|
|
||||||
* so for this case we use the flags "blockend" and
|
|
||||||
* "dataend" to make sure both IRQs have arrived before
|
|
||||||
* concluding the transaction. (This does not apply
|
|
||||||
* to the Ux500 which doesn't fire MCI_DATABLOCKEND
|
|
||||||
* at all.) In DMA mode it suffers from the same problem
|
|
||||||
* as the Ux500.
|
|
||||||
*/
|
|
||||||
if (status & MCI_DATABLOCKEND) {
|
|
||||||
/*
|
|
||||||
* Just being a little over-cautious, we do not
|
|
||||||
* use this progressive update if the hardware blockend
|
|
||||||
* flag is unreliable: since it can stay high between
|
|
||||||
* IRQs it will corrupt the transfer counter.
|
|
||||||
*/
|
|
||||||
if (!variant->broken_blockend)
|
|
||||||
host->data_xfered += data->blksz;
|
|
||||||
host->blockend = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (status & MCI_DATAEND)
|
if (status & MCI_DATAEND) {
|
||||||
host->dataend = true;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* On variants with broken blockend we shall only wait for dataend,
|
|
||||||
* on others we must sync with the blockend signal since they can
|
|
||||||
* appear out-of-order.
|
|
||||||
*/
|
|
||||||
if (host->dataend && (host->blockend || variant->broken_blockend)) {
|
|
||||||
mmci_stop_data(host);
|
mmci_stop_data(host);
|
||||||
|
|
||||||
/* Reset these flags */
|
if (!data->error)
|
||||||
host->blockend = false;
|
/* The error clause is handled above, success! */
|
||||||
host->dataend = false;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Variants with broken blockend flags need to handle the
|
|
||||||
* end of the entire transfer here.
|
|
||||||
*/
|
|
||||||
if (variant->broken_blockend && !data->error)
|
|
||||||
host->data_xfered += data->blksz * data->blocks;
|
host->data_xfered += data->blksz * data->blocks;
|
||||||
|
|
||||||
if (!data->stop) {
|
if (!data->stop) {
|
||||||
@@ -770,7 +718,6 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
|
|||||||
struct variant_data *variant = id->data;
|
struct variant_data *variant = id->data;
|
||||||
struct mmci_host *host;
|
struct mmci_host *host;
|
||||||
struct mmc_host *mmc;
|
struct mmc_host *mmc;
|
||||||
unsigned int mask;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* must have platform data */
|
/* must have platform data */
|
||||||
@@ -951,12 +898,7 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
|
|||||||
goto irq0_free;
|
goto irq0_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
mask = MCI_IRQENABLE;
|
writel(MCI_IRQENABLE, host->base + MMCIMASK0);
|
||||||
/* Don't use the datablockend flag if it's broken */
|
|
||||||
if (variant->broken_blockend)
|
|
||||||
mask &= ~MCI_DATABLOCKEND;
|
|
||||||
|
|
||||||
writel(mask, host->base + MMCIMASK0);
|
|
||||||
|
|
||||||
amba_set_drvdata(dev, mmc);
|
amba_set_drvdata(dev, mmc);
|
||||||
|
|
||||||
|
@@ -137,7 +137,7 @@
|
|||||||
#define MCI_IRQENABLE \
|
#define MCI_IRQENABLE \
|
||||||
(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \
|
(MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \
|
||||||
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
|
MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \
|
||||||
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATABLOCKENDMASK)
|
MCI_CMDRESPENDMASK|MCI_CMDSENTMASK)
|
||||||
|
|
||||||
/* These interrupts are directed to IRQ1 when two IRQ lines are available */
|
/* These interrupts are directed to IRQ1 when two IRQ lines are available */
|
||||||
#define MCI_IRQ1MASK \
|
#define MCI_IRQ1MASK \
|
||||||
@@ -177,9 +177,6 @@ struct mmci_host {
|
|||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
unsigned int oldstat;
|
unsigned int oldstat;
|
||||||
|
|
||||||
bool blockend;
|
|
||||||
bool dataend;
|
|
||||||
|
|
||||||
/* pio stuff */
|
/* pio stuff */
|
||||||
struct sg_mapping_iter sg_miter;
|
struct sg_mapping_iter sg_miter;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
|
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
#define DRIVER_NAME "aaci-pl041"
|
#define DRIVER_NAME "aaci-pl041"
|
||||||
|
|
||||||
|
#define FRAME_PERIOD_US 21
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PM support is not complete. Turn it off.
|
* PM support is not complete. Turn it off.
|
||||||
*/
|
*/
|
||||||
@@ -64,8 +66,8 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
|
|||||||
unsigned short val)
|
unsigned short val)
|
||||||
{
|
{
|
||||||
struct aaci *aaci = ac97->private_data;
|
struct aaci *aaci = ac97->private_data;
|
||||||
|
int timeout;
|
||||||
u32 v;
|
u32 v;
|
||||||
int timeout = 5000;
|
|
||||||
|
|
||||||
if (ac97->num >= 4)
|
if (ac97->num >= 4)
|
||||||
return;
|
return;
|
||||||
@@ -81,14 +83,17 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
|
|||||||
writel(val << 4, aaci->base + AACI_SL2TX);
|
writel(val << 4, aaci->base + AACI_SL2TX);
|
||||||
writel(reg << 12, aaci->base + AACI_SL1TX);
|
writel(reg << 12, aaci->base + AACI_SL1TX);
|
||||||
|
|
||||||
/*
|
/* Initially, wait one frame period */
|
||||||
* Wait for the transmission of both slots to complete.
|
udelay(FRAME_PERIOD_US);
|
||||||
*/
|
|
||||||
|
/* And then wait an additional eight frame periods for it to be sent */
|
||||||
|
timeout = FRAME_PERIOD_US * 8;
|
||||||
do {
|
do {
|
||||||
|
udelay(1);
|
||||||
v = readl(aaci->base + AACI_SLFR);
|
v = readl(aaci->base + AACI_SLFR);
|
||||||
} while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout);
|
} while ((v & (SLFR_1TXB|SLFR_2TXB)) && --timeout);
|
||||||
|
|
||||||
if (!timeout)
|
if (v & (SLFR_1TXB|SLFR_2TXB))
|
||||||
dev_err(&aaci->dev->dev,
|
dev_err(&aaci->dev->dev,
|
||||||
"timeout waiting for write to complete\n");
|
"timeout waiting for write to complete\n");
|
||||||
|
|
||||||
@@ -101,9 +106,8 @@ static void aaci_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
|
|||||||
static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
|
static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
|
||||||
{
|
{
|
||||||
struct aaci *aaci = ac97->private_data;
|
struct aaci *aaci = ac97->private_data;
|
||||||
|
int timeout, retries = 10;
|
||||||
u32 v;
|
u32 v;
|
||||||
int timeout = 5000;
|
|
||||||
int retries = 10;
|
|
||||||
|
|
||||||
if (ac97->num >= 4)
|
if (ac97->num >= 4)
|
||||||
return ~0;
|
return ~0;
|
||||||
@@ -117,35 +121,34 @@ static unsigned short aaci_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
|
|||||||
*/
|
*/
|
||||||
writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
|
writel((reg << 12) | (1 << 19), aaci->base + AACI_SL1TX);
|
||||||
|
|
||||||
/*
|
/* Initially, wait one frame period */
|
||||||
* Wait for the transmission to complete.
|
udelay(FRAME_PERIOD_US);
|
||||||
*/
|
|
||||||
|
/* And then wait an additional eight frame periods for it to be sent */
|
||||||
|
timeout = FRAME_PERIOD_US * 8;
|
||||||
do {
|
do {
|
||||||
|
udelay(1);
|
||||||
v = readl(aaci->base + AACI_SLFR);
|
v = readl(aaci->base + AACI_SLFR);
|
||||||
} while ((v & SLFR_1TXB) && --timeout);
|
} while ((v & SLFR_1TXB) && --timeout);
|
||||||
|
|
||||||
if (!timeout) {
|
if (v & SLFR_1TXB) {
|
||||||
dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
|
dev_err(&aaci->dev->dev, "timeout on slot 1 TX busy\n");
|
||||||
v = ~0;
|
v = ~0;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* Now wait for the response frame */
|
||||||
* Give the AC'97 codec more than enough time
|
udelay(FRAME_PERIOD_US);
|
||||||
* to respond. (42us = ~2 frames at 48kHz.)
|
|
||||||
*/
|
|
||||||
udelay(42);
|
|
||||||
|
|
||||||
/*
|
/* And then wait an additional eight frame periods for data */
|
||||||
* Wait for slot 2 to indicate data.
|
timeout = FRAME_PERIOD_US * 8;
|
||||||
*/
|
|
||||||
timeout = 5000;
|
|
||||||
do {
|
do {
|
||||||
|
udelay(1);
|
||||||
cond_resched();
|
cond_resched();
|
||||||
v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
|
v = readl(aaci->base + AACI_SLFR) & (SLFR_1RXV|SLFR_2RXV);
|
||||||
} while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout);
|
} while ((v != (SLFR_1RXV|SLFR_2RXV)) && --timeout);
|
||||||
|
|
||||||
if (!timeout) {
|
if (v != (SLFR_1RXV|SLFR_2RXV)) {
|
||||||
dev_err(&aaci->dev->dev, "timeout on RX valid\n");
|
dev_err(&aaci->dev->dev, "timeout on RX valid\n");
|
||||||
v = ~0;
|
v = ~0;
|
||||||
goto out;
|
goto out;
|
||||||
@@ -179,6 +182,7 @@ aaci_chan_wait_ready(struct aaci_runtime *aacirun, unsigned long mask)
|
|||||||
int timeout = 5000;
|
int timeout = 5000;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
udelay(1);
|
||||||
val = readl(aacirun->base + AACI_SR);
|
val = readl(aacirun->base + AACI_SR);
|
||||||
} while (val & mask && timeout--);
|
} while (val & mask && timeout--);
|
||||||
}
|
}
|
||||||
@@ -874,7 +878,7 @@ static int __devinit aaci_probe_ac97(struct aaci *aaci)
|
|||||||
* Give the AC'97 codec more than enough time
|
* Give the AC'97 codec more than enough time
|
||||||
* to wake up. (42us = ~2 frames at 48kHz.)
|
* to wake up. (42us = ~2 frames at 48kHz.)
|
||||||
*/
|
*/
|
||||||
udelay(42);
|
udelay(FRAME_PERIOD_US * 2);
|
||||||
|
|
||||||
ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
|
ret = snd_ac97_bus(aaci->card, 0, &aaci_bus_ops, aaci, &ac97_bus);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
Reference in New Issue
Block a user