diff --git a/[refs] b/[refs] index 51ca190ae162..445c0f01fd8e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6cd3c7e2b1dc1e3cc28ffcef074d0b8182b6e501 +refs/heads/master: 2fa36399e63c911134f28b6878aada9b395c4209 diff --git a/trunk/arch/mips/include/asm/cpu.h b/trunk/arch/mips/include/asm/cpu.h index 95e40c1e8ed1..f21b7c04e95a 100644 --- a/trunk/arch/mips/include/asm/cpu.h +++ b/trunk/arch/mips/include/asm/cpu.h @@ -197,6 +197,7 @@ #define PRID_REV_VR4181A 0x0070 /* Same as VR4122 */ #define PRID_REV_VR4130 0x0080 #define PRID_REV_34K_V1_0_2 0x0022 +#define PRID_REV_LOONGSON1B 0x0020 #define PRID_REV_LOONGSON2E 0x0002 #define PRID_REV_LOONGSON2F 0x0003 @@ -261,7 +262,7 @@ enum cpu_type_enum { */ CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K, CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350, - CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC, + CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_LOONGSON1, CPU_M14KC, /* * MIPS64 class processors diff --git a/trunk/arch/mips/include/asm/module.h b/trunk/arch/mips/include/asm/module.h index 530008048c62..7531ecd654d6 100644 --- a/trunk/arch/mips/include/asm/module.h +++ b/trunk/arch/mips/include/asm/module.h @@ -117,6 +117,8 @@ search_module_dbetables(unsigned long addr) #define MODULE_PROC_FAMILY "RM9000 " #elif defined CONFIG_CPU_SB1 #define MODULE_PROC_FAMILY "SB1 " +#elif defined CONFIG_CPU_LOONGSON1 +#define MODULE_PROC_FAMILY "LOONGSON1 " #elif defined CONFIG_CPU_LOONGSON2 #define MODULE_PROC_FAMILY "LOONGSON2 " #elif defined CONFIG_CPU_CAVIUM_OCTEON diff --git a/trunk/arch/mips/kernel/cpu-probe.c b/trunk/arch/mips/kernel/cpu-probe.c index f4630e1082ab..1b51046191e8 100644 --- a/trunk/arch/mips/kernel/cpu-probe.c +++ b/trunk/arch/mips/kernel/cpu-probe.c @@ -190,6 +190,7 @@ void __init check_wait(void) case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: case CPU_JZRISC: + case CPU_LOONGSON1: case CPU_XLR: case CPU_XLP: cpu_wait = r4k_wait; @@ -330,6 +331,154 @@ static inline void cpu_probe_vmbits(struct cpuinfo_mips *c) #endif } +static char unknown_isa[] __cpuinitdata = KERN_ERR \ + "Unsupported ISA type, c0.config0: %d."; + +static inline unsigned int decode_config0(struct cpuinfo_mips *c) +{ + unsigned int config0; + int isa; + + config0 = read_c0_config(); + + if (((config0 & MIPS_CONF_MT) >> 7) == 1) + c->options |= MIPS_CPU_TLB; + isa = (config0 & MIPS_CONF_AT) >> 13; + switch (isa) { + case 0: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M32R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M32R2; + break; + default: + goto unknown; + } + break; + case 2: + switch ((config0 & MIPS_CONF_AR) >> 10) { + case 0: + c->isa_level = MIPS_CPU_ISA_M64R1; + break; + case 1: + c->isa_level = MIPS_CPU_ISA_M64R2; + break; + default: + goto unknown; + } + break; + default: + goto unknown; + } + + return config0 & MIPS_CONF_M; + +unknown: + panic(unknown_isa, config0); +} + +static inline unsigned int decode_config1(struct cpuinfo_mips *c) +{ + unsigned int config1; + + config1 = read_c0_config1(); + + if (config1 & MIPS_CONF1_MD) + c->ases |= MIPS_ASE_MDMX; + if (config1 & MIPS_CONF1_WR) + c->options |= MIPS_CPU_WATCH; + if (config1 & MIPS_CONF1_CA) + c->ases |= MIPS_ASE_MIPS16; + if (config1 & MIPS_CONF1_EP) + c->options |= MIPS_CPU_EJTAG; + if (config1 & MIPS_CONF1_FP) { + c->options |= MIPS_CPU_FPU; + c->options |= MIPS_CPU_32FPR; + } + if (cpu_has_tlb) + c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; + + return config1 & MIPS_CONF_M; +} + +static inline unsigned int decode_config2(struct cpuinfo_mips *c) +{ + unsigned int config2; + + config2 = read_c0_config2(); + + if (config2 & MIPS_CONF2_SL) + c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; + + return config2 & MIPS_CONF_M; +} + +static inline unsigned int decode_config3(struct cpuinfo_mips *c) +{ + unsigned int config3; + + config3 = read_c0_config3(); + + if (config3 & MIPS_CONF3_SM) + c->ases |= MIPS_ASE_SMARTMIPS; + if (config3 & MIPS_CONF3_DSP) + c->ases |= MIPS_ASE_DSP; + if (config3 & MIPS_CONF3_VINT) + c->options |= MIPS_CPU_VINT; + if (config3 & MIPS_CONF3_VEIC) + c->options |= MIPS_CPU_VEIC; + if (config3 & MIPS_CONF3_MT) + c->ases |= MIPS_ASE_MIPSMT; + if (config3 & MIPS_CONF3_ULRI) + c->options |= MIPS_CPU_ULRI; + + return config3 & MIPS_CONF_M; +} + +static inline unsigned int decode_config4(struct cpuinfo_mips *c) +{ + unsigned int config4; + + config4 = read_c0_config4(); + + if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT + && cpu_has_tlb) + c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; + + c->kscratch_mask = (config4 >> 16) & 0xff; + + return config4 & MIPS_CONF_M; +} + +static void __cpuinit decode_configs(struct cpuinfo_mips *c) +{ + int ok; + + /* MIPS32 or MIPS64 compliant CPU. */ + c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | + MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; + + c->scache.flags = MIPS_CACHE_NOT_PRESENT; + + ok = decode_config0(c); /* Read Config registers. */ + BUG_ON(!ok); /* Arch spec violation! */ + if (ok) + ok = decode_config1(c); + if (ok) + ok = decode_config2(c); + if (ok) + ok = decode_config3(c); + if (ok) + ok = decode_config4(c); + + mips_probe_watch_registers(c); + + if (cpu_has_mips_r2) + c->core = read_c0_ebase() & 0x3ff; +} + #define R4K_OPTS (MIPS_CPU_TLB | MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE \ | MIPS_CPU_COUNTER) @@ -638,155 +787,19 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) MIPS_CPU_32FPR; c->tlbsize = 64; break; - } -} - -static char unknown_isa[] __cpuinitdata = KERN_ERR \ - "Unsupported ISA type, c0.config0: %d."; + case PRID_IMP_LOONGSON1: + decode_configs(c); -static inline unsigned int decode_config0(struct cpuinfo_mips *c) -{ - unsigned int config0; - int isa; + c->cputype = CPU_LOONGSON1; - config0 = read_c0_config(); - - if (((config0 & MIPS_CONF_MT) >> 7) == 1) - c->options |= MIPS_CPU_TLB; - isa = (config0 & MIPS_CONF_AT) >> 13; - switch (isa) { - case 0: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M32R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M32R2; + switch (c->processor_id & PRID_REV_MASK) { + case PRID_REV_LOONGSON1B: + __cpu_name[cpu] = "Loongson 1B"; break; - default: - goto unknown; } - break; - case 2: - switch ((config0 & MIPS_CONF_AR) >> 10) { - case 0: - c->isa_level = MIPS_CPU_ISA_M64R1; - break; - case 1: - c->isa_level = MIPS_CPU_ISA_M64R2; - break; - default: - goto unknown; - } - break; - default: - goto unknown; - } - - return config0 & MIPS_CONF_M; - -unknown: - panic(unknown_isa, config0); -} -static inline unsigned int decode_config1(struct cpuinfo_mips *c) -{ - unsigned int config1; - - config1 = read_c0_config1(); - - if (config1 & MIPS_CONF1_MD) - c->ases |= MIPS_ASE_MDMX; - if (config1 & MIPS_CONF1_WR) - c->options |= MIPS_CPU_WATCH; - if (config1 & MIPS_CONF1_CA) - c->ases |= MIPS_ASE_MIPS16; - if (config1 & MIPS_CONF1_EP) - c->options |= MIPS_CPU_EJTAG; - if (config1 & MIPS_CONF1_FP) { - c->options |= MIPS_CPU_FPU; - c->options |= MIPS_CPU_32FPR; + break; } - if (cpu_has_tlb) - c->tlbsize = ((config1 & MIPS_CONF1_TLBS) >> 25) + 1; - - return config1 & MIPS_CONF_M; -} - -static inline unsigned int decode_config2(struct cpuinfo_mips *c) -{ - unsigned int config2; - - config2 = read_c0_config2(); - - if (config2 & MIPS_CONF2_SL) - c->scache.flags &= ~MIPS_CACHE_NOT_PRESENT; - - return config2 & MIPS_CONF_M; -} - -static inline unsigned int decode_config3(struct cpuinfo_mips *c) -{ - unsigned int config3; - - config3 = read_c0_config3(); - - if (config3 & MIPS_CONF3_SM) - c->ases |= MIPS_ASE_SMARTMIPS; - if (config3 & MIPS_CONF3_DSP) - c->ases |= MIPS_ASE_DSP; - if (config3 & MIPS_CONF3_VINT) - c->options |= MIPS_CPU_VINT; - if (config3 & MIPS_CONF3_VEIC) - c->options |= MIPS_CPU_VEIC; - if (config3 & MIPS_CONF3_MT) - c->ases |= MIPS_ASE_MIPSMT; - if (config3 & MIPS_CONF3_ULRI) - c->options |= MIPS_CPU_ULRI; - - return config3 & MIPS_CONF_M; -} - -static inline unsigned int decode_config4(struct cpuinfo_mips *c) -{ - unsigned int config4; - - config4 = read_c0_config4(); - - if ((config4 & MIPS_CONF4_MMUEXTDEF) == MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT - && cpu_has_tlb) - c->tlbsize += (config4 & MIPS_CONF4_MMUSIZEEXT) * 0x40; - - c->kscratch_mask = (config4 >> 16) & 0xff; - - return config4 & MIPS_CONF_M; -} - -static void __cpuinit decode_configs(struct cpuinfo_mips *c) -{ - int ok; - - /* MIPS32 or MIPS64 compliant CPU. */ - c->options = MIPS_CPU_4KEX | MIPS_CPU_4K_CACHE | MIPS_CPU_COUNTER | - MIPS_CPU_DIVEC | MIPS_CPU_LLSC | MIPS_CPU_MCHECK; - - c->scache.flags = MIPS_CACHE_NOT_PRESENT; - - ok = decode_config0(c); /* Read Config registers. */ - BUG_ON(!ok); /* Arch spec violation! */ - if (ok) - ok = decode_config1(c); - if (ok) - ok = decode_config2(c); - if (ok) - ok = decode_config3(c); - if (ok) - ok = decode_config4(c); - - mips_probe_watch_registers(c); - - if (cpu_has_mips_r2) - c->core = read_c0_ebase() & 0x3ff; } static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu) diff --git a/trunk/arch/mips/kernel/perf_event_mipsxx.c b/trunk/arch/mips/kernel/perf_event_mipsxx.c index eb5e394a4650..2f28d3b55687 100644 --- a/trunk/arch/mips/kernel/perf_event_mipsxx.c +++ b/trunk/arch/mips/kernel/perf_event_mipsxx.c @@ -1559,6 +1559,11 @@ init_hw_perf_events(void) mipspmu.general_event_map = &mipsxxcore_event_map; mipspmu.cache_event_map = &mipsxxcore_cache_map; break; + case CPU_LOONGSON1: + mipspmu.name = "mips/loongson1"; + mipspmu.general_event_map = &mipsxxcore_event_map; + mipspmu.cache_event_map = &mipsxxcore_cache_map; + break; case CPU_CAVIUM_OCTEON: case CPU_CAVIUM_OCTEON_PLUS: case CPU_CAVIUM_OCTEON2: diff --git a/trunk/arch/mips/kernel/traps.c b/trunk/arch/mips/kernel/traps.c index c3c293543703..9be3df1fa8a4 100644 --- a/trunk/arch/mips/kernel/traps.c +++ b/trunk/arch/mips/kernel/traps.c @@ -1253,6 +1253,7 @@ static inline void parity_protection_init(void) case CPU_5KC: case CPU_5KE: + case CPU_LOONGSON1: write_c0_ecc(0x80000000); back_to_back_c0_hazard(); /* Set the PE bit (bit 31) in the c0_errctl register. */ diff --git a/trunk/arch/mips/oprofile/common.c b/trunk/arch/mips/oprofile/common.c index b6e378211a2c..f80480a5a032 100644 --- a/trunk/arch/mips/oprofile/common.c +++ b/trunk/arch/mips/oprofile/common.c @@ -85,6 +85,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) case CPU_34K: case CPU_1004K: case CPU_74K: + case CPU_LOONGSON1: case CPU_SB1: case CPU_SB1A: case CPU_R10000: diff --git a/trunk/arch/mips/oprofile/op_model_mipsxx.c b/trunk/arch/mips/oprofile/op_model_mipsxx.c index 4d80a856048d..056da6224163 100644 --- a/trunk/arch/mips/oprofile/op_model_mipsxx.c +++ b/trunk/arch/mips/oprofile/op_model_mipsxx.c @@ -374,6 +374,10 @@ static int __init mipsxx_init(void) op_model_mipsxx_ops.cpu_type = "mips/sb1"; break; + case CPU_LOONGSON1: + op_model_mipsxx_ops.cpu_type = "mips/loongson1"; + break; + default: printk(KERN_ERR "Profiling unsupported for this CPU\n"); diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index b18abf31fd08..cd2fe350e724 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -144,15 +144,6 @@ config SPI_EP93XX This enables using the Cirrus EP93xx SPI controller in master mode. -config SPI_FALCON - tristate "Falcon SPI controller support" - depends on SOC_FALCON - help - The external bus unit (EBU) found on the FALC-ON SoC has SPI - emulation that is designed for serial flash access. This driver - has only been tested with m25p80 type chips. The hardware has no - support for other types of SPI peripherals. - config SPI_GPIO tristate "GPIO-based bitbanging SPI Master" depends on GENERIC_GPIO diff --git a/trunk/drivers/spi/Makefile b/trunk/drivers/spi/Makefile index b5cbab2b5ab0..9d75d2198ff5 100644 --- a/trunk/drivers/spi/Makefile +++ b/trunk/drivers/spi/Makefile @@ -26,7 +26,6 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmio.o obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o -obj-$(CONFIG_SPI_FALCON) += spi-falcon.o obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o diff --git a/trunk/drivers/spi/spi-falcon.c b/trunk/drivers/spi/spi-falcon.c deleted file mode 100644 index 8f6aa735a24c..000000000000 --- a/trunk/drivers/spi/spi-falcon.c +++ /dev/null @@ -1,469 +0,0 @@ -/* - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - * - * Copyright (C) 2012 Thomas Langer - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRV_NAME "sflash-falcon" - -#define FALCON_SPI_XFER_BEGIN (1 << 0) -#define FALCON_SPI_XFER_END (1 << 1) - -/* Bus Read Configuration Register0 */ -#define BUSRCON0 0x00000010 -/* Bus Write Configuration Register0 */ -#define BUSWCON0 0x00000018 -/* Serial Flash Configuration Register */ -#define SFCON 0x00000080 -/* Serial Flash Time Register */ -#define SFTIME 0x00000084 -/* Serial Flash Status Register */ -#define SFSTAT 0x00000088 -/* Serial Flash Command Register */ -#define SFCMD 0x0000008C -/* Serial Flash Address Register */ -#define SFADDR 0x00000090 -/* Serial Flash Data Register */ -#define SFDATA 0x00000094 -/* Serial Flash I/O Control Register */ -#define SFIO 0x00000098 -/* EBU Clock Control Register */ -#define EBUCC 0x000000C4 - -/* Dummy Phase Length */ -#define SFCMD_DUMLEN_OFFSET 16 -#define SFCMD_DUMLEN_MASK 0x000F0000 -/* Chip Select */ -#define SFCMD_CS_OFFSET 24 -#define SFCMD_CS_MASK 0x07000000 -/* field offset */ -#define SFCMD_ALEN_OFFSET 20 -#define SFCMD_ALEN_MASK 0x00700000 -/* SCK Rise-edge Position */ -#define SFTIME_SCKR_POS_OFFSET 8 -#define SFTIME_SCKR_POS_MASK 0x00000F00 -/* SCK Period */ -#define SFTIME_SCK_PER_OFFSET 0 -#define SFTIME_SCK_PER_MASK 0x0000000F -/* SCK Fall-edge Position */ -#define SFTIME_SCKF_POS_OFFSET 12 -#define SFTIME_SCKF_POS_MASK 0x0000F000 -/* Device Size */ -#define SFCON_DEV_SIZE_A23_0 0x03000000 -#define SFCON_DEV_SIZE_MASK 0x0F000000 -/* Read Data Position */ -#define SFTIME_RD_POS_MASK 0x000F0000 -/* Data Output */ -#define SFIO_UNUSED_WD_MASK 0x0000000F -/* Command Opcode mask */ -#define SFCMD_OPC_MASK 0x000000FF -/* dlen bytes of data to write */ -#define SFCMD_DIR_WRITE 0x00000100 -/* Data Length offset */ -#define SFCMD_DLEN_OFFSET 9 -/* Command Error */ -#define SFSTAT_CMD_ERR 0x20000000 -/* Access Command Pending */ -#define SFSTAT_CMD_PEND 0x00400000 -/* Frequency set to 100MHz. */ -#define EBUCC_EBUDIV_SELF100 0x00000001 -/* Serial Flash */ -#define BUSRCON0_AGEN_SERIAL_FLASH 0xF0000000 -/* 8-bit multiplexed */ -#define BUSRCON0_PORTW_8_BIT_MUX 0x00000000 -/* Serial Flash */ -#define BUSWCON0_AGEN_SERIAL_FLASH 0xF0000000 -/* Chip Select after opcode */ -#define SFCMD_KEEP_CS_KEEP_SELECTED 0x00008000 - -#define CLOCK_100M 100000000 -#define CLOCK_50M 50000000 - -struct falcon_sflash { - u32 sfcmd; /* for caching of opcode, direction, ... */ - struct spi_master *master; -}; - -int falcon_sflash_xfer(struct spi_device *spi, struct spi_transfer *t, - unsigned long flags) -{ - struct device *dev = &spi->dev; - struct falcon_sflash *priv = spi_master_get_devdata(spi->master); - const u8 *txp = t->tx_buf; - u8 *rxp = t->rx_buf; - unsigned int bytelen = ((8 * t->len + 7) / 8); - unsigned int len, alen, dumlen; - u32 val; - enum { - state_init, - state_command_prepare, - state_write, - state_read, - state_disable_cs, - state_end - } state = state_init; - - do { - switch (state) { - case state_init: /* detect phase of upper layer sequence */ - { - /* initial write ? */ - if (flags & FALCON_SPI_XFER_BEGIN) { - if (!txp) { - dev_err(dev, - "BEGIN without tx data!\n"); - return -ENODATA; - } - /* - * Prepare the parts of the sfcmd register, - * which should not change during a sequence! - * Only exception are the length fields, - * especially alen and dumlen. - */ - - priv->sfcmd = ((spi->chip_select - << SFCMD_CS_OFFSET) - & SFCMD_CS_MASK); - priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED; - priv->sfcmd |= *txp; - txp++; - bytelen--; - if (bytelen) { - /* - * more data: - * maybe address and/or dummy - */ - state = state_command_prepare; - break; - } else { - dev_dbg(dev, "write cmd %02X\n", - priv->sfcmd & SFCMD_OPC_MASK); - } - } - /* continued write ? */ - if (txp && bytelen) { - state = state_write; - break; - } - /* read data? */ - if (rxp && bytelen) { - state = state_read; - break; - } - /* end of sequence? */ - if (flags & FALCON_SPI_XFER_END) - state = state_disable_cs; - else - state = state_end; - break; - } - /* collect tx data for address and dummy phase */ - case state_command_prepare: - { - /* txp is valid, already checked */ - val = 0; - alen = 0; - dumlen = 0; - while (bytelen > 0) { - if (alen < 3) { - val = (val << 8) | (*txp++); - alen++; - } else if ((dumlen < 15) && (*txp == 0)) { - /* - * assume dummy bytes are set to 0 - * from upper layer - */ - dumlen++; - txp++; - } else { - break; - } - bytelen--; - } - priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK); - priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) | - (dumlen << SFCMD_DUMLEN_OFFSET); - if (alen > 0) - ltq_ebu_w32(val, SFADDR); - - dev_dbg(dev, "wr %02X, alen=%d (addr=%06X) dlen=%d\n", - priv->sfcmd & SFCMD_OPC_MASK, - alen, val, dumlen); - - if (bytelen > 0) { - /* continue with write */ - state = state_write; - } else if (flags & FALCON_SPI_XFER_END) { - /* end of sequence? */ - state = state_disable_cs; - } else { - /* - * go to end and expect another - * call (read or write) - */ - state = state_end; - } - break; - } - case state_write: - { - /* txp still valid */ - priv->sfcmd |= SFCMD_DIR_WRITE; - len = 0; - val = 0; - do { - if (bytelen--) - val |= (*txp++) << (8 * len++); - if ((flags & FALCON_SPI_XFER_END) - && (bytelen == 0)) { - priv->sfcmd &= - ~SFCMD_KEEP_CS_KEEP_SELECTED; - } - if ((len == 4) || (bytelen == 0)) { - ltq_ebu_w32(val, SFDATA); - ltq_ebu_w32(priv->sfcmd - | (len<sfcmd &= ~(SFCMD_ALEN_MASK - | SFCMD_DUMLEN_MASK); - } - } while (bytelen); - state = state_end; - break; - } - case state_read: - { - /* read data */ - priv->sfcmd &= ~SFCMD_DIR_WRITE; - do { - if ((flags & FALCON_SPI_XFER_END) - && (bytelen <= 4)) { - priv->sfcmd &= - ~SFCMD_KEEP_CS_KEEP_SELECTED; - } - len = (bytelen > 4) ? 4 : bytelen; - bytelen -= len; - ltq_ebu_w32(priv->sfcmd - | (len << SFCMD_DLEN_OFFSET), SFCMD); - priv->sfcmd &= ~(SFCMD_ALEN_MASK - | SFCMD_DUMLEN_MASK); - do { - val = ltq_ebu_r32(SFSTAT); - if (val & SFSTAT_CMD_ERR) { - /* reset error status */ - dev_err(dev, "SFSTAT: CMD_ERR"); - dev_err(dev, " (%x)\n", val); - ltq_ebu_w32(SFSTAT_CMD_ERR, - SFSTAT); - return -EBADE; - } - } while (val & SFSTAT_CMD_PEND); - val = ltq_ebu_r32(SFDATA); - do { - *rxp = (val & 0xFF); - rxp++; - val >>= 8; - len--; - } while (len); - } while (bytelen); - state = state_end; - break; - } - case state_disable_cs: - { - priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED; - ltq_ebu_w32(priv->sfcmd | (0 << SFCMD_DLEN_OFFSET), - SFCMD); - val = ltq_ebu_r32(SFSTAT); - if (val & SFSTAT_CMD_ERR) { - /* reset error status */ - dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val); - ltq_ebu_w32(SFSTAT_CMD_ERR, SFSTAT); - return -EBADE; - } - state = state_end; - break; - } - case state_end: - break; - } - } while (state != state_end); - - return 0; -} - -static int falcon_sflash_setup(struct spi_device *spi) -{ - unsigned int i; - unsigned long flags; - - if (spi->chip_select > 0) - return -ENODEV; - - spin_lock_irqsave(&ebu_lock, flags); - - if (spi->max_speed_hz >= CLOCK_100M) { - /* set EBU clock to 100 MHz */ - ltq_sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, EBUCC); - i = 1; /* divider */ - } else { - /* set EBU clock to 50 MHz */ - ltq_sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, EBUCC); - - /* search for suitable divider */ - for (i = 1; i < 7; i++) { - if (CLOCK_50M / i <= spi->max_speed_hz) - break; - } - } - - /* setup period of serial clock */ - ltq_ebu_w32_mask(SFTIME_SCKF_POS_MASK - | SFTIME_SCKR_POS_MASK - | SFTIME_SCK_PER_MASK, - (i << SFTIME_SCKR_POS_OFFSET) - | (i << (SFTIME_SCK_PER_OFFSET + 1)), - SFTIME); - - /* - * set some bits of unused_wd, to not trigger HOLD/WP - * signals on non QUAD flashes - */ - ltq_ebu_w32((SFIO_UNUSED_WD_MASK & (0x8 | 0x4)), SFIO); - - ltq_ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX, - BUSRCON0); - ltq_ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, BUSWCON0); - /* set address wrap around to maximum for 24-bit addresses */ - ltq_ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, SFCON); - - spin_unlock_irqrestore(&ebu_lock, flags); - - return 0; -} - -static int falcon_sflash_prepare_xfer(struct spi_master *master) -{ - return 0; -} - -static int falcon_sflash_unprepare_xfer(struct spi_master *master) -{ - return 0; -} - -static int falcon_sflash_xfer_one(struct spi_master *master, - struct spi_message *m) -{ - struct falcon_sflash *priv = spi_master_get_devdata(master); - struct spi_transfer *t; - unsigned long spi_flags; - unsigned long flags; - int ret = 0; - - priv->sfcmd = 0; - m->actual_length = 0; - - spi_flags = FALCON_SPI_XFER_BEGIN; - list_for_each_entry(t, &m->transfers, transfer_list) { - if (list_is_last(&t->transfer_list, &m->transfers)) - spi_flags |= FALCON_SPI_XFER_END; - - spin_lock_irqsave(&ebu_lock, flags); - ret = falcon_sflash_xfer(m->spi, t, spi_flags); - spin_unlock_irqrestore(&ebu_lock, flags); - - if (ret) - break; - - m->actual_length += t->len; - - WARN_ON(t->delay_usecs || t->cs_change); - spi_flags = 0; - } - - m->status = ret; - m->complete(m->context); - - return 0; -} - -static int __devinit falcon_sflash_probe(struct platform_device *pdev) -{ - struct falcon_sflash *priv; - struct spi_master *master; - int ret; - - if (ltq_boot_select() != BS_SPI) { - dev_err(&pdev->dev, "invalid bootstrap options\n"); - return -ENODEV; - } - - master = spi_alloc_master(&pdev->dev, sizeof(*priv)); - if (!master) - return -ENOMEM; - - priv = spi_master_get_devdata(master); - priv->master = master; - - master->mode_bits = SPI_MODE_3; - master->num_chipselect = 1; - master->bus_num = -1; - master->setup = falcon_sflash_setup; - master->prepare_transfer_hardware = falcon_sflash_prepare_xfer; - master->transfer_one_message = falcon_sflash_xfer_one; - master->unprepare_transfer_hardware = falcon_sflash_unprepare_xfer; - master->dev.of_node = pdev->dev.of_node; - - platform_set_drvdata(pdev, priv); - - ret = spi_register_master(master); - if (ret) - spi_master_put(master); - return ret; -} - -static int __devexit falcon_sflash_remove(struct platform_device *pdev) -{ - struct falcon_sflash *priv = platform_get_drvdata(pdev); - - spi_unregister_master(priv->master); - - return 0; -} - -static const struct of_device_id falcon_sflash_match[] = { - { .compatible = "lantiq,sflash-falcon" }, - {}, -}; -MODULE_DEVICE_TABLE(of, falcon_sflash_match); - -static struct platform_driver falcon_sflash_driver = { - .probe = falcon_sflash_probe, - .remove = __devexit_p(falcon_sflash_remove), - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - .of_match_table = falcon_sflash_match, - } -}; - -module_platform_driver(falcon_sflash_driver); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Lantiq Falcon SPI/SFLASH controller driver");