diff options
Diffstat (limited to 'target/linux/bcm53xx/patches-3.14')
41 files changed, 0 insertions, 8873 deletions
diff --git a/target/linux/bcm53xx/patches-3.14/001-mtd-spi-nor.patch b/target/linux/bcm53xx/patches-3.14/001-mtd-spi-nor.patch deleted file mode 100644 index 8b6ed43f98..0000000000 --- a/target/linux/bcm53xx/patches-3.14/001-mtd-spi-nor.patch +++ /dev/null @@ -1,2443 +0,0 @@ -This patches adds the SPI-NOR device support code form kernel 3.17-rc1. -This patch does not contain any further code not in this mainline kernel. - ---- a/drivers/mtd/Kconfig -+++ b/drivers/mtd/Kconfig -@@ -366,6 +366,8 @@ source "drivers/mtd/onenand/Kconfig" - - source "drivers/mtd/lpddr/Kconfig" - -+source "drivers/mtd/spi-nor/Kconfig" -+ - source "drivers/mtd/ubi/Kconfig" - - endif # MTD ---- a/drivers/mtd/Makefile -+++ b/drivers/mtd/Makefile -@@ -35,4 +35,5 @@ inftl-objs := inftlcore.o inftlmount.o - - obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ - -+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/ - obj-$(CONFIG_MTD_UBI) += ubi/ ---- /dev/null -+++ b/drivers/mtd/spi-nor/fsl-quadspi.c -@@ -0,0 +1,1009 @@ -+/* -+ * Freescale QuadSPI driver. -+ * -+ * Copyright (C) 2013 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/interrupt.h> -+#include <linux/errno.h> -+#include <linux/platform_device.h> -+#include <linux/sched.h> -+#include <linux/delay.h> -+#include <linux/io.h> -+#include <linux/clk.h> -+#include <linux/err.h> -+#include <linux/of.h> -+#include <linux/of_device.h> -+#include <linux/timer.h> -+#include <linux/jiffies.h> -+#include <linux/completion.h> -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/partitions.h> -+#include <linux/mtd/spi-nor.h> -+ -+/* The registers */ -+#define QUADSPI_MCR 0x00 -+#define QUADSPI_MCR_RESERVED_SHIFT 16 -+#define QUADSPI_MCR_RESERVED_MASK (0xF << QUADSPI_MCR_RESERVED_SHIFT) -+#define QUADSPI_MCR_MDIS_SHIFT 14 -+#define QUADSPI_MCR_MDIS_MASK (1 << QUADSPI_MCR_MDIS_SHIFT) -+#define QUADSPI_MCR_CLR_TXF_SHIFT 11 -+#define QUADSPI_MCR_CLR_TXF_MASK (1 << QUADSPI_MCR_CLR_TXF_SHIFT) -+#define QUADSPI_MCR_CLR_RXF_SHIFT 10 -+#define QUADSPI_MCR_CLR_RXF_MASK (1 << QUADSPI_MCR_CLR_RXF_SHIFT) -+#define QUADSPI_MCR_DDR_EN_SHIFT 7 -+#define QUADSPI_MCR_DDR_EN_MASK (1 << QUADSPI_MCR_DDR_EN_SHIFT) -+#define QUADSPI_MCR_END_CFG_SHIFT 2 -+#define QUADSPI_MCR_END_CFG_MASK (3 << QUADSPI_MCR_END_CFG_SHIFT) -+#define QUADSPI_MCR_SWRSTHD_SHIFT 1 -+#define QUADSPI_MCR_SWRSTHD_MASK (1 << QUADSPI_MCR_SWRSTHD_SHIFT) -+#define QUADSPI_MCR_SWRSTSD_SHIFT 0 -+#define QUADSPI_MCR_SWRSTSD_MASK (1 << QUADSPI_MCR_SWRSTSD_SHIFT) -+ -+#define QUADSPI_IPCR 0x08 -+#define QUADSPI_IPCR_SEQID_SHIFT 24 -+#define QUADSPI_IPCR_SEQID_MASK (0xF << QUADSPI_IPCR_SEQID_SHIFT) -+ -+#define QUADSPI_BUF0CR 0x10 -+#define QUADSPI_BUF1CR 0x14 -+#define QUADSPI_BUF2CR 0x18 -+#define QUADSPI_BUFXCR_INVALID_MSTRID 0xe -+ -+#define QUADSPI_BUF3CR 0x1c -+#define QUADSPI_BUF3CR_ALLMST_SHIFT 31 -+#define QUADSPI_BUF3CR_ALLMST (1 << QUADSPI_BUF3CR_ALLMST_SHIFT) -+ -+#define QUADSPI_BFGENCR 0x20 -+#define QUADSPI_BFGENCR_PAR_EN_SHIFT 16 -+#define QUADSPI_BFGENCR_PAR_EN_MASK (1 << (QUADSPI_BFGENCR_PAR_EN_SHIFT)) -+#define QUADSPI_BFGENCR_SEQID_SHIFT 12 -+#define QUADSPI_BFGENCR_SEQID_MASK (0xF << QUADSPI_BFGENCR_SEQID_SHIFT) -+ -+#define QUADSPI_BUF0IND 0x30 -+#define QUADSPI_BUF1IND 0x34 -+#define QUADSPI_BUF2IND 0x38 -+#define QUADSPI_SFAR 0x100 -+ -+#define QUADSPI_SMPR 0x108 -+#define QUADSPI_SMPR_DDRSMP_SHIFT 16 -+#define QUADSPI_SMPR_DDRSMP_MASK (7 << QUADSPI_SMPR_DDRSMP_SHIFT) -+#define QUADSPI_SMPR_FSDLY_SHIFT 6 -+#define QUADSPI_SMPR_FSDLY_MASK (1 << QUADSPI_SMPR_FSDLY_SHIFT) -+#define QUADSPI_SMPR_FSPHS_SHIFT 5 -+#define QUADSPI_SMPR_FSPHS_MASK (1 << QUADSPI_SMPR_FSPHS_SHIFT) -+#define QUADSPI_SMPR_HSENA_SHIFT 0 -+#define QUADSPI_SMPR_HSENA_MASK (1 << QUADSPI_SMPR_HSENA_SHIFT) -+ -+#define QUADSPI_RBSR 0x10c -+#define QUADSPI_RBSR_RDBFL_SHIFT 8 -+#define QUADSPI_RBSR_RDBFL_MASK (0x3F << QUADSPI_RBSR_RDBFL_SHIFT) -+ -+#define QUADSPI_RBCT 0x110 -+#define QUADSPI_RBCT_WMRK_MASK 0x1F -+#define QUADSPI_RBCT_RXBRD_SHIFT 8 -+#define QUADSPI_RBCT_RXBRD_USEIPS (0x1 << QUADSPI_RBCT_RXBRD_SHIFT) -+ -+#define QUADSPI_TBSR 0x150 -+#define QUADSPI_TBDR 0x154 -+#define QUADSPI_SR 0x15c -+#define QUADSPI_SR_IP_ACC_SHIFT 1 -+#define QUADSPI_SR_IP_ACC_MASK (0x1 << QUADSPI_SR_IP_ACC_SHIFT) -+#define QUADSPI_SR_AHB_ACC_SHIFT 2 -+#define QUADSPI_SR_AHB_ACC_MASK (0x1 << QUADSPI_SR_AHB_ACC_SHIFT) -+ -+#define QUADSPI_FR 0x160 -+#define QUADSPI_FR_TFF_MASK 0x1 -+ -+#define QUADSPI_SFA1AD 0x180 -+#define QUADSPI_SFA2AD 0x184 -+#define QUADSPI_SFB1AD 0x188 -+#define QUADSPI_SFB2AD 0x18c -+#define QUADSPI_RBDR 0x200 -+ -+#define QUADSPI_LUTKEY 0x300 -+#define QUADSPI_LUTKEY_VALUE 0x5AF05AF0 -+ -+#define QUADSPI_LCKCR 0x304 -+#define QUADSPI_LCKER_LOCK 0x1 -+#define QUADSPI_LCKER_UNLOCK 0x2 -+ -+#define QUADSPI_RSER 0x164 -+#define QUADSPI_RSER_TFIE (0x1 << 0) -+ -+#define QUADSPI_LUT_BASE 0x310 -+ -+/* -+ * The definition of the LUT register shows below: -+ * -+ * --------------------------------------------------- -+ * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | -+ * --------------------------------------------------- -+ */ -+#define OPRND0_SHIFT 0 -+#define PAD0_SHIFT 8 -+#define INSTR0_SHIFT 10 -+#define OPRND1_SHIFT 16 -+ -+/* Instruction set for the LUT register. */ -+#define LUT_STOP 0 -+#define LUT_CMD 1 -+#define LUT_ADDR 2 -+#define LUT_DUMMY 3 -+#define LUT_MODE 4 -+#define LUT_MODE2 5 -+#define LUT_MODE4 6 -+#define LUT_READ 7 -+#define LUT_WRITE 8 -+#define LUT_JMP_ON_CS 9 -+#define LUT_ADDR_DDR 10 -+#define LUT_MODE_DDR 11 -+#define LUT_MODE2_DDR 12 -+#define LUT_MODE4_DDR 13 -+#define LUT_READ_DDR 14 -+#define LUT_WRITE_DDR 15 -+#define LUT_DATA_LEARN 16 -+ -+/* -+ * The PAD definitions for LUT register. -+ * -+ * The pad stands for the lines number of IO[0:3]. -+ * For example, the Quad read need four IO lines, so you should -+ * set LUT_PAD4 which means we use four IO lines. -+ */ -+#define LUT_PAD1 0 -+#define LUT_PAD2 1 -+#define LUT_PAD4 2 -+ -+/* Oprands for the LUT register. */ -+#define ADDR24BIT 0x18 -+#define ADDR32BIT 0x20 -+ -+/* Macros for constructing the LUT register. */ -+#define LUT0(ins, pad, opr) \ -+ (((opr) << OPRND0_SHIFT) | ((LUT_##pad) << PAD0_SHIFT) | \ -+ ((LUT_##ins) << INSTR0_SHIFT)) -+ -+#define LUT1(ins, pad, opr) (LUT0(ins, pad, opr) << OPRND1_SHIFT) -+ -+/* other macros for LUT register. */ -+#define QUADSPI_LUT(x) (QUADSPI_LUT_BASE + (x) * 4) -+#define QUADSPI_LUT_NUM 64 -+ -+/* SEQID -- we can have 16 seqids at most. */ -+#define SEQID_QUAD_READ 0 -+#define SEQID_WREN 1 -+#define SEQID_WRDI 2 -+#define SEQID_RDSR 3 -+#define SEQID_SE 4 -+#define SEQID_CHIP_ERASE 5 -+#define SEQID_PP 6 -+#define SEQID_RDID 7 -+#define SEQID_WRSR 8 -+#define SEQID_RDCR 9 -+#define SEQID_EN4B 10 -+#define SEQID_BRWR 11 -+ -+enum fsl_qspi_devtype { -+ FSL_QUADSPI_VYBRID, -+ FSL_QUADSPI_IMX6SX, -+}; -+ -+struct fsl_qspi_devtype_data { -+ enum fsl_qspi_devtype devtype; -+ int rxfifo; -+ int txfifo; -+}; -+ -+static struct fsl_qspi_devtype_data vybrid_data = { -+ .devtype = FSL_QUADSPI_VYBRID, -+ .rxfifo = 128, -+ .txfifo = 64 -+}; -+ -+static struct fsl_qspi_devtype_data imx6sx_data = { -+ .devtype = FSL_QUADSPI_IMX6SX, -+ .rxfifo = 128, -+ .txfifo = 512 -+}; -+ -+#define FSL_QSPI_MAX_CHIP 4 -+struct fsl_qspi { -+ struct mtd_info mtd[FSL_QSPI_MAX_CHIP]; -+ struct spi_nor nor[FSL_QSPI_MAX_CHIP]; -+ void __iomem *iobase; -+ void __iomem *ahb_base; /* Used when read from AHB bus */ -+ u32 memmap_phy; -+ struct clk *clk, *clk_en; -+ struct device *dev; -+ struct completion c; -+ struct fsl_qspi_devtype_data *devtype_data; -+ u32 nor_size; -+ u32 nor_num; -+ u32 clk_rate; -+ unsigned int chip_base_addr; /* We may support two chips. */ -+}; -+ -+static inline int is_vybrid_qspi(struct fsl_qspi *q) -+{ -+ return q->devtype_data->devtype == FSL_QUADSPI_VYBRID; -+} -+ -+static inline int is_imx6sx_qspi(struct fsl_qspi *q) -+{ -+ return q->devtype_data->devtype == FSL_QUADSPI_IMX6SX; -+} -+ -+/* -+ * An IC bug makes us to re-arrange the 32-bit data. -+ * The following chips, such as IMX6SLX, have fixed this bug. -+ */ -+static inline u32 fsl_qspi_endian_xchg(struct fsl_qspi *q, u32 a) -+{ -+ return is_vybrid_qspi(q) ? __swab32(a) : a; -+} -+ -+static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q) -+{ -+ writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); -+ writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR); -+} -+ -+static inline void fsl_qspi_lock_lut(struct fsl_qspi *q) -+{ -+ writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY); -+ writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR); -+} -+ -+static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id) -+{ -+ struct fsl_qspi *q = dev_id; -+ u32 reg; -+ -+ /* clear interrupt */ -+ reg = readl(q->iobase + QUADSPI_FR); -+ writel(reg, q->iobase + QUADSPI_FR); -+ -+ if (reg & QUADSPI_FR_TFF_MASK) -+ complete(&q->c); -+ -+ dev_dbg(q->dev, "QUADSPI_FR : 0x%.8x:0x%.8x\n", q->chip_base_addr, reg); -+ return IRQ_HANDLED; -+} -+ -+static void fsl_qspi_init_lut(struct fsl_qspi *q) -+{ -+ void __iomem *base = q->iobase; -+ int rxfifo = q->devtype_data->rxfifo; -+ u32 lut_base; -+ u8 cmd, addrlen, dummy; -+ int i; -+ -+ fsl_qspi_unlock_lut(q); -+ -+ /* Clear all the LUT table */ -+ for (i = 0; i < QUADSPI_LUT_NUM; i++) -+ writel(0, base + QUADSPI_LUT_BASE + i * 4); -+ -+ /* Quad Read */ -+ lut_base = SEQID_QUAD_READ * 4; -+ -+ if (q->nor_size <= SZ_16M) { -+ cmd = SPINOR_OP_READ_1_1_4; -+ addrlen = ADDR24BIT; -+ dummy = 8; -+ } else { -+ /* use the 4-byte address */ -+ cmd = SPINOR_OP_READ_1_1_4; -+ addrlen = ADDR32BIT; -+ dummy = 8; -+ } -+ -+ writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ writel(LUT0(DUMMY, PAD1, dummy) | LUT1(READ, PAD4, rxfifo), -+ base + QUADSPI_LUT(lut_base + 1)); -+ -+ /* Write enable */ -+ lut_base = SEQID_WREN * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_WREN), base + QUADSPI_LUT(lut_base)); -+ -+ /* Page Program */ -+ lut_base = SEQID_PP * 4; -+ -+ if (q->nor_size <= SZ_16M) { -+ cmd = SPINOR_OP_PP; -+ addrlen = ADDR24BIT; -+ } else { -+ /* use the 4-byte address */ -+ cmd = SPINOR_OP_PP; -+ addrlen = ADDR32BIT; -+ } -+ -+ writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ writel(LUT0(WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1)); -+ -+ /* Read Status */ -+ lut_base = SEQID_RDSR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(READ, PAD1, 0x1), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Erase a sector */ -+ lut_base = SEQID_SE * 4; -+ -+ if (q->nor_size <= SZ_16M) { -+ cmd = SPINOR_OP_SE; -+ addrlen = ADDR24BIT; -+ } else { -+ /* use the 4-byte address */ -+ cmd = SPINOR_OP_SE; -+ addrlen = ADDR32BIT; -+ } -+ -+ writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Erase the whole chip */ -+ lut_base = SEQID_CHIP_ERASE * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* READ ID */ -+ lut_base = SEQID_RDID * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(READ, PAD1, 0x8), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Write Register */ -+ lut_base = SEQID_WRSR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(WRITE, PAD1, 0x2), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Read Configuration Register */ -+ lut_base = SEQID_RDCR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(READ, PAD1, 0x1), -+ base + QUADSPI_LUT(lut_base)); -+ -+ /* Write disable */ -+ lut_base = SEQID_WRDI * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_WRDI), base + QUADSPI_LUT(lut_base)); -+ -+ /* Enter 4 Byte Mode (Micron) */ -+ lut_base = SEQID_EN4B * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_EN4B), base + QUADSPI_LUT(lut_base)); -+ -+ /* Enter 4 Byte Mode (Spansion) */ -+ lut_base = SEQID_BRWR * 4; -+ writel(LUT0(CMD, PAD1, SPINOR_OP_BRWR), base + QUADSPI_LUT(lut_base)); -+ -+ fsl_qspi_lock_lut(q); -+} -+ -+/* Get the SEQID for the command */ -+static int fsl_qspi_get_seqid(struct fsl_qspi *q, u8 cmd) -+{ -+ switch (cmd) { -+ case SPINOR_OP_READ_1_1_4: -+ return SEQID_QUAD_READ; -+ case SPINOR_OP_WREN: -+ return SEQID_WREN; -+ case SPINOR_OP_WRDI: -+ return SEQID_WRDI; -+ case SPINOR_OP_RDSR: -+ return SEQID_RDSR; -+ case SPINOR_OP_SE: -+ return SEQID_SE; -+ case SPINOR_OP_CHIP_ERASE: -+ return SEQID_CHIP_ERASE; -+ case SPINOR_OP_PP: -+ return SEQID_PP; -+ case SPINOR_OP_RDID: -+ return SEQID_RDID; -+ case SPINOR_OP_WRSR: -+ return SEQID_WRSR; -+ case SPINOR_OP_RDCR: -+ return SEQID_RDCR; -+ case SPINOR_OP_EN4B: -+ return SEQID_EN4B; -+ case SPINOR_OP_BRWR: -+ return SEQID_BRWR; -+ default: -+ dev_err(q->dev, "Unsupported cmd 0x%.2x\n", cmd); -+ break; -+ } -+ return -EINVAL; -+} -+ -+static int -+fsl_qspi_runcmd(struct fsl_qspi *q, u8 cmd, unsigned int addr, int len) -+{ -+ void __iomem *base = q->iobase; -+ int seqid; -+ u32 reg, reg2; -+ int err; -+ -+ init_completion(&q->c); -+ dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len:%d, cmd:%.2x\n", -+ q->chip_base_addr, addr, len, cmd); -+ -+ /* save the reg */ -+ reg = readl(base + QUADSPI_MCR); -+ -+ writel(q->memmap_phy + q->chip_base_addr + addr, base + QUADSPI_SFAR); -+ writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS, -+ base + QUADSPI_RBCT); -+ writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR); -+ -+ do { -+ reg2 = readl(base + QUADSPI_SR); -+ if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) { -+ udelay(1); -+ dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2); -+ continue; -+ } -+ break; -+ } while (1); -+ -+ /* trigger the LUT now */ -+ seqid = fsl_qspi_get_seqid(q, cmd); -+ writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR); -+ -+ /* Wait for the interrupt. */ -+ err = wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000)); -+ if (!err) { -+ dev_err(q->dev, -+ "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n", -+ cmd, addr, readl(base + QUADSPI_FR), -+ readl(base + QUADSPI_SR)); -+ err = -ETIMEDOUT; -+ } else { -+ err = 0; -+ } -+ -+ /* restore the MCR */ -+ writel(reg, base + QUADSPI_MCR); -+ -+ return err; -+} -+ -+/* Read out the data from the QUADSPI_RBDR buffer registers. */ -+static void fsl_qspi_read_data(struct fsl_qspi *q, int len, u8 *rxbuf) -+{ -+ u32 tmp; -+ int i = 0; -+ -+ while (len > 0) { -+ tmp = readl(q->iobase + QUADSPI_RBDR + i * 4); -+ tmp = fsl_qspi_endian_xchg(q, tmp); -+ dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n", -+ q->chip_base_addr, tmp); -+ -+ if (len >= 4) { -+ *((u32 *)rxbuf) = tmp; -+ rxbuf += 4; -+ } else { -+ memcpy(rxbuf, &tmp, len); -+ break; -+ } -+ -+ len -= 4; -+ i++; -+ } -+} -+ -+/* -+ * If we have changed the content of the flash by writing or erasing, -+ * we need to invalidate the AHB buffer. If we do not do so, we may read out -+ * the wrong data. The spec tells us reset the AHB domain and Serial Flash -+ * domain at the same time. -+ */ -+static inline void fsl_qspi_invalid(struct fsl_qspi *q) -+{ -+ u32 reg; -+ -+ reg = readl(q->iobase + QUADSPI_MCR); -+ reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK; -+ writel(reg, q->iobase + QUADSPI_MCR); -+ -+ /* -+ * The minimum delay : 1 AHB + 2 SFCK clocks. -+ * Delay 1 us is enough. -+ */ -+ udelay(1); -+ -+ reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK); -+ writel(reg, q->iobase + QUADSPI_MCR); -+} -+ -+static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor, -+ u8 opcode, unsigned int to, u32 *txbuf, -+ unsigned count, size_t *retlen) -+{ -+ int ret, i, j; -+ u32 tmp; -+ -+ dev_dbg(q->dev, "to 0x%.8x:0x%.8x, len : %d\n", -+ q->chip_base_addr, to, count); -+ -+ /* clear the TX FIFO. */ -+ tmp = readl(q->iobase + QUADSPI_MCR); -+ writel(tmp | QUADSPI_MCR_CLR_RXF_MASK, q->iobase + QUADSPI_MCR); -+ -+ /* fill the TX data to the FIFO */ -+ for (j = 0, i = ((count + 3) / 4); j < i; j++) { -+ tmp = fsl_qspi_endian_xchg(q, *txbuf); -+ writel(tmp, q->iobase + QUADSPI_TBDR); -+ txbuf++; -+ } -+ -+ /* Trigger it */ -+ ret = fsl_qspi_runcmd(q, opcode, to, count); -+ -+ if (ret == 0 && retlen) -+ *retlen += count; -+ -+ return ret; -+} -+ -+static void fsl_qspi_set_map_addr(struct fsl_qspi *q) -+{ -+ int nor_size = q->nor_size; -+ void __iomem *base = q->iobase; -+ -+ writel(nor_size + q->memmap_phy, base + QUADSPI_SFA1AD); -+ writel(nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD); -+ writel(nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD); -+ writel(nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD); -+} -+ -+/* -+ * There are two different ways to read out the data from the flash: -+ * the "IP Command Read" and the "AHB Command Read". -+ * -+ * The IC guy suggests we use the "AHB Command Read" which is faster -+ * then the "IP Command Read". (What's more is that there is a bug in -+ * the "IP Command Read" in the Vybrid.) -+ * -+ * After we set up the registers for the "AHB Command Read", we can use -+ * the memcpy to read the data directly. A "missed" access to the buffer -+ * causes the controller to clear the buffer, and use the sequence pointed -+ * by the QUADSPI_BFGENCR[SEQID] to initiate a read from the flash. -+ */ -+static void fsl_qspi_init_abh_read(struct fsl_qspi *q) -+{ -+ void __iomem *base = q->iobase; -+ int seqid; -+ -+ /* AHB configuration for access buffer 0/1/2 .*/ -+ writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR); -+ writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR); -+ writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR); -+ writel(QUADSPI_BUF3CR_ALLMST, base + QUADSPI_BUF3CR); -+ -+ /* We only use the buffer3 */ -+ writel(0, base + QUADSPI_BUF0IND); -+ writel(0, base + QUADSPI_BUF1IND); -+ writel(0, base + QUADSPI_BUF2IND); -+ -+ /* Set the default lut sequence for AHB Read. */ -+ seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode); -+ writel(seqid << QUADSPI_BFGENCR_SEQID_SHIFT, -+ q->iobase + QUADSPI_BFGENCR); -+} -+ -+/* We use this function to do some basic init for spi_nor_scan(). */ -+static int fsl_qspi_nor_setup(struct fsl_qspi *q) -+{ -+ void __iomem *base = q->iobase; -+ u32 reg; -+ int ret; -+ -+ /* the default frequency, we will change it in the future.*/ -+ ret = clk_set_rate(q->clk, 66000000); -+ if (ret) -+ return ret; -+ -+ /* Init the LUT table. */ -+ fsl_qspi_init_lut(q); -+ -+ /* Disable the module */ -+ writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK, -+ base + QUADSPI_MCR); -+ -+ reg = readl(base + QUADSPI_SMPR); -+ writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK -+ | QUADSPI_SMPR_FSPHS_MASK -+ | QUADSPI_SMPR_HSENA_MASK -+ | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR); -+ -+ /* Enable the module */ -+ writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK, -+ base + QUADSPI_MCR); -+ -+ /* enable the interrupt */ -+ writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER); -+ -+ return 0; -+} -+ -+static int fsl_qspi_nor_setup_last(struct fsl_qspi *q) -+{ -+ unsigned long rate = q->clk_rate; -+ int ret; -+ -+ if (is_imx6sx_qspi(q)) -+ rate *= 4; -+ -+ ret = clk_set_rate(q->clk, rate); -+ if (ret) -+ return ret; -+ -+ /* Init the LUT table again. */ -+ fsl_qspi_init_lut(q); -+ -+ /* Init for AHB read */ -+ fsl_qspi_init_abh_read(q); -+ -+ return 0; -+} -+ -+static struct of_device_id fsl_qspi_dt_ids[] = { -+ { .compatible = "fsl,vf610-qspi", .data = (void *)&vybrid_data, }, -+ { .compatible = "fsl,imx6sx-qspi", .data = (void *)&imx6sx_data, }, -+ { /* sentinel */ } -+}; -+MODULE_DEVICE_TABLE(of, fsl_qspi_dt_ids); -+ -+static void fsl_qspi_set_base_addr(struct fsl_qspi *q, struct spi_nor *nor) -+{ -+ q->chip_base_addr = q->nor_size * (nor - q->nor); -+} -+ -+static int fsl_qspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len) -+{ -+ int ret; -+ struct fsl_qspi *q = nor->priv; -+ -+ ret = fsl_qspi_runcmd(q, opcode, 0, len); -+ if (ret) -+ return ret; -+ -+ fsl_qspi_read_data(q, len, buf); -+ return 0; -+} -+ -+static int fsl_qspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len, -+ int write_enable) -+{ -+ struct fsl_qspi *q = nor->priv; -+ int ret; -+ -+ if (!buf) { -+ ret = fsl_qspi_runcmd(q, opcode, 0, 1); -+ if (ret) -+ return ret; -+ -+ if (opcode == SPINOR_OP_CHIP_ERASE) -+ fsl_qspi_invalid(q); -+ -+ } else if (len > 0) { -+ ret = fsl_qspi_nor_write(q, nor, opcode, 0, -+ (u32 *)buf, len, NULL); -+ } else { -+ dev_err(q->dev, "invalid cmd %d\n", opcode); -+ ret = -EINVAL; -+ } -+ -+ return ret; -+} -+ -+static void fsl_qspi_write(struct spi_nor *nor, loff_t to, -+ size_t len, size_t *retlen, const u_char *buf) -+{ -+ struct fsl_qspi *q = nor->priv; -+ -+ fsl_qspi_nor_write(q, nor, nor->program_opcode, to, -+ (u32 *)buf, len, retlen); -+ -+ /* invalid the data in the AHB buffer. */ -+ fsl_qspi_invalid(q); -+} -+ -+static int fsl_qspi_read(struct spi_nor *nor, loff_t from, -+ size_t len, size_t *retlen, u_char *buf) -+{ -+ struct fsl_qspi *q = nor->priv; -+ u8 cmd = nor->read_opcode; -+ int ret; -+ -+ dev_dbg(q->dev, "cmd [%x],read from (0x%p, 0x%.8x, 0x%.8x),len:%d\n", -+ cmd, q->ahb_base, q->chip_base_addr, (unsigned int)from, len); -+ -+ /* Wait until the previous command is finished. */ -+ ret = nor->wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* Read out the data directly from the AHB buffer.*/ -+ memcpy(buf, q->ahb_base + q->chip_base_addr + from, len); -+ -+ *retlen += len; -+ return 0; -+} -+ -+static int fsl_qspi_erase(struct spi_nor *nor, loff_t offs) -+{ -+ struct fsl_qspi *q = nor->priv; -+ int ret; -+ -+ dev_dbg(nor->dev, "%dKiB at 0x%08x:0x%08x\n", -+ nor->mtd->erasesize / 1024, q->chip_base_addr, (u32)offs); -+ -+ /* Wait until finished previous write command. */ -+ ret = nor->wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* Send write enable, then erase commands. */ -+ ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); -+ if (ret) -+ return ret; -+ -+ ret = fsl_qspi_runcmd(q, nor->erase_opcode, offs, 0); -+ if (ret) -+ return ret; -+ -+ fsl_qspi_invalid(q); -+ return 0; -+} -+ -+static int fsl_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ struct fsl_qspi *q = nor->priv; -+ int ret; -+ -+ ret = clk_enable(q->clk_en); -+ if (ret) -+ return ret; -+ -+ ret = clk_enable(q->clk); -+ if (ret) { -+ clk_disable(q->clk_en); -+ return ret; -+ } -+ -+ fsl_qspi_set_base_addr(q, nor); -+ return 0; -+} -+ -+static void fsl_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ struct fsl_qspi *q = nor->priv; -+ -+ clk_disable(q->clk); -+ clk_disable(q->clk_en); -+} -+ -+static int fsl_qspi_probe(struct platform_device *pdev) -+{ -+ struct device_node *np = pdev->dev.of_node; -+ struct mtd_part_parser_data ppdata; -+ struct device *dev = &pdev->dev; -+ struct fsl_qspi *q; -+ struct resource *res; -+ struct spi_nor *nor; -+ struct mtd_info *mtd; -+ int ret, i = 0; -+ bool has_second_chip = false; -+ const struct of_device_id *of_id = -+ of_match_device(fsl_qspi_dt_ids, &pdev->dev); -+ -+ q = devm_kzalloc(dev, sizeof(*q), GFP_KERNEL); -+ if (!q) -+ return -ENOMEM; -+ -+ q->nor_num = of_get_child_count(dev->of_node); -+ if (!q->nor_num || q->nor_num > FSL_QSPI_MAX_CHIP) -+ return -ENODEV; -+ -+ /* find the resources */ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "QuadSPI"); -+ q->iobase = devm_ioremap_resource(dev, res); -+ if (IS_ERR(q->iobase)) { -+ ret = PTR_ERR(q->iobase); -+ goto map_failed; -+ } -+ -+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, -+ "QuadSPI-memory"); -+ q->ahb_base = devm_ioremap_resource(dev, res); -+ if (IS_ERR(q->ahb_base)) { -+ ret = PTR_ERR(q->ahb_base); -+ goto map_failed; -+ } -+ q->memmap_phy = res->start; -+ -+ /* find the clocks */ -+ q->clk_en = devm_clk_get(dev, "qspi_en"); -+ if (IS_ERR(q->clk_en)) { -+ ret = PTR_ERR(q->clk_en); -+ goto map_failed; -+ } -+ -+ q->clk = devm_clk_get(dev, "qspi"); -+ if (IS_ERR(q->clk)) { -+ ret = PTR_ERR(q->clk); -+ goto map_failed; -+ } -+ -+ ret = clk_prepare_enable(q->clk_en); -+ if (ret) { -+ dev_err(dev, "can not enable the qspi_en clock\n"); -+ goto map_failed; -+ } -+ -+ ret = clk_prepare_enable(q->clk); -+ if (ret) { -+ clk_disable_unprepare(q->clk_en); -+ dev_err(dev, "can not enable the qspi clock\n"); -+ goto map_failed; -+ } -+ -+ /* find the irq */ -+ ret = platform_get_irq(pdev, 0); -+ if (ret < 0) { -+ dev_err(dev, "failed to get the irq\n"); -+ goto irq_failed; -+ } -+ -+ ret = devm_request_irq(dev, ret, -+ fsl_qspi_irq_handler, 0, pdev->name, q); -+ if (ret) { -+ dev_err(dev, "failed to request irq.\n"); -+ goto irq_failed; -+ } -+ -+ q->dev = dev; -+ q->devtype_data = (struct fsl_qspi_devtype_data *)of_id->data; -+ platform_set_drvdata(pdev, q); -+ -+ ret = fsl_qspi_nor_setup(q); -+ if (ret) -+ goto irq_failed; -+ -+ if (of_get_property(np, "fsl,qspi-has-second-chip", NULL)) -+ has_second_chip = true; -+ -+ /* iterate the subnodes. */ -+ for_each_available_child_of_node(dev->of_node, np) { -+ const struct spi_device_id *id; -+ char modalias[40]; -+ -+ /* skip the holes */ -+ if (!has_second_chip) -+ i *= 2; -+ -+ nor = &q->nor[i]; -+ mtd = &q->mtd[i]; -+ -+ nor->mtd = mtd; -+ nor->dev = dev; -+ nor->priv = q; -+ mtd->priv = nor; -+ -+ /* fill the hooks */ -+ nor->read_reg = fsl_qspi_read_reg; -+ nor->write_reg = fsl_qspi_write_reg; -+ nor->read = fsl_qspi_read; -+ nor->write = fsl_qspi_write; -+ nor->erase = fsl_qspi_erase; -+ -+ nor->prepare = fsl_qspi_prep; -+ nor->unprepare = fsl_qspi_unprep; -+ -+ if (of_modalias_node(np, modalias, sizeof(modalias)) < 0) -+ goto map_failed; -+ -+ id = spi_nor_match_id(modalias); -+ if (!id) -+ goto map_failed; -+ -+ ret = of_property_read_u32(np, "spi-max-frequency", -+ &q->clk_rate); -+ if (ret < 0) -+ goto map_failed; -+ -+ /* set the chip address for READID */ -+ fsl_qspi_set_base_addr(q, nor); -+ -+ ret = spi_nor_scan(nor, id, SPI_NOR_QUAD); -+ if (ret) -+ goto map_failed; -+ -+ ppdata.of_node = np; -+ ret = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0); -+ if (ret) -+ goto map_failed; -+ -+ /* Set the correct NOR size now. */ -+ if (q->nor_size == 0) { -+ q->nor_size = mtd->size; -+ -+ /* Map the SPI NOR to accessiable address */ -+ fsl_qspi_set_map_addr(q); -+ } -+ -+ /* -+ * The TX FIFO is 64 bytes in the Vybrid, but the Page Program -+ * may writes 265 bytes per time. The write is working in the -+ * unit of the TX FIFO, not in the unit of the SPI NOR's page -+ * size. -+ * -+ * So shrink the spi_nor->page_size if it is larger then the -+ * TX FIFO. -+ */ -+ if (nor->page_size > q->devtype_data->txfifo) -+ nor->page_size = q->devtype_data->txfifo; -+ -+ i++; -+ } -+ -+ /* finish the rest init. */ -+ ret = fsl_qspi_nor_setup_last(q); -+ if (ret) -+ goto last_init_failed; -+ -+ clk_disable(q->clk); -+ clk_disable(q->clk_en); -+ dev_info(dev, "QuadSPI SPI NOR flash driver\n"); -+ return 0; -+ -+last_init_failed: -+ for (i = 0; i < q->nor_num; i++) -+ mtd_device_unregister(&q->mtd[i]); -+ -+irq_failed: -+ clk_disable_unprepare(q->clk); -+ clk_disable_unprepare(q->clk_en); -+map_failed: -+ dev_err(dev, "Freescale QuadSPI probe failed\n"); -+ return ret; -+} -+ -+static int fsl_qspi_remove(struct platform_device *pdev) -+{ -+ struct fsl_qspi *q = platform_get_drvdata(pdev); -+ int i; -+ -+ for (i = 0; i < q->nor_num; i++) -+ mtd_device_unregister(&q->mtd[i]); -+ -+ /* disable the hardware */ -+ writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR); -+ writel(0x0, q->iobase + QUADSPI_RSER); -+ -+ clk_unprepare(q->clk); -+ clk_unprepare(q->clk_en); -+ return 0; -+} -+ -+static struct platform_driver fsl_qspi_driver = { -+ .driver = { -+ .name = "fsl-quadspi", -+ .bus = &platform_bus_type, -+ .owner = THIS_MODULE, -+ .of_match_table = fsl_qspi_dt_ids, -+ }, -+ .probe = fsl_qspi_probe, -+ .remove = fsl_qspi_remove, -+}; -+module_platform_driver(fsl_qspi_driver); -+ -+MODULE_DESCRIPTION("Freescale QuadSPI Controller Driver"); -+MODULE_AUTHOR("Freescale Semiconductor Inc."); -+MODULE_LICENSE("GPL v2"); ---- /dev/null -+++ b/drivers/mtd/spi-nor/Kconfig -@@ -0,0 +1,17 @@ -+menuconfig MTD_SPI_NOR -+ tristate "SPI-NOR device support" -+ depends on MTD -+ help -+ This is the framework for the SPI NOR which can be used by the SPI -+ device drivers and the SPI-NOR device driver. -+ -+if MTD_SPI_NOR -+ -+config SPI_FSL_QUADSPI -+ tristate "Freescale Quad SPI controller" -+ depends on ARCH_MXC -+ help -+ This enables support for the Quad SPI controller in master mode. -+ We only connect the NOR to this controller now. -+ -+endif # MTD_SPI_NOR ---- /dev/null -+++ b/drivers/mtd/spi-nor/Makefile -@@ -0,0 +1,2 @@ -+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o -+obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o ---- /dev/null -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -0,0 +1,1160 @@ -+/* -+ * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with -+ * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c -+ * -+ * Copyright (C) 2005, Intec Automation Inc. -+ * Copyright (C) 2014, Freescale Semiconductor, Inc. -+ * -+ * This code 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. -+ */ -+ -+#include <linux/err.h> -+#include <linux/errno.h> -+#include <linux/module.h> -+#include <linux/device.h> -+#include <linux/mutex.h> -+#include <linux/math64.h> -+ -+#include <linux/mtd/cfi.h> -+#include <linux/mtd/mtd.h> -+#include <linux/of_platform.h> -+#include <linux/spi/flash.h> -+#include <linux/mtd/spi-nor.h> -+ -+/* Define max times to check status register before we give up. */ -+#define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ -+ -+#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) -+ -+/* -+ * Read the status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_sr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1); -+ if (ret < 0) { -+ pr_err("error %d reading SR\n", (int) ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Read the flag status register, returning its value in the location -+ * Return the status register value. -+ * Returns negative if error occurred. -+ */ -+static int read_fsr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1); -+ if (ret < 0) { -+ pr_err("error %d reading FSR\n", ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Read configuration register, returning its value in the -+ * location. Return the configuration register value. -+ * Returns negative if error occured. -+ */ -+static int read_cr(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading CR\n", ret); -+ return ret; -+ } -+ -+ return val; -+} -+ -+/* -+ * Dummy Cycle calculation for different type of read. -+ * It can be used to support more commands with -+ * different dummy cycle requirements. -+ */ -+static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor) -+{ -+ switch (nor->flash_read) { -+ case SPI_NOR_FAST: -+ case SPI_NOR_DUAL: -+ case SPI_NOR_QUAD: -+ return 1; -+ case SPI_NOR_NORMAL: -+ return 0; -+ } -+ return 0; -+} -+ -+/* -+ * Write status register 1 byte -+ * Returns negative if error occurred. -+ */ -+static inline int write_sr(struct spi_nor *nor, u8 val) -+{ -+ nor->cmd_buf[0] = val; -+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); -+} -+ -+/* -+ * Set write enable latch with Write Enable command. -+ * Returns negative if error occurred. -+ */ -+static inline int write_enable(struct spi_nor *nor) -+{ -+ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0); -+} -+ -+/* -+ * Send write disble instruction to the chip. -+ */ -+static inline int write_disable(struct spi_nor *nor) -+{ -+ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0); -+} -+ -+static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd) -+{ -+ return mtd->priv; -+} -+ -+/* Enable/disable 4-byte addressing mode. */ -+static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) -+{ -+ int status; -+ bool need_wren = false; -+ u8 cmd; -+ -+ switch (JEDEC_MFR(jedec_id)) { -+ case CFI_MFR_ST: /* Micron, actually */ -+ /* Some Micron need WREN command; all will accept it */ -+ need_wren = true; -+ case CFI_MFR_MACRONIX: -+ case 0xEF /* winbond */: -+ if (need_wren) -+ write_enable(nor); -+ -+ cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B; -+ status = nor->write_reg(nor, cmd, NULL, 0, 0); -+ if (need_wren) -+ write_disable(nor); -+ -+ return status; -+ default: -+ /* Spansion style */ -+ nor->cmd_buf[0] = enable << 7; -+ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); -+ } -+} -+ -+static int spi_nor_wait_till_ready(struct spi_nor *nor) -+{ -+ unsigned long deadline; -+ int sr; -+ -+ deadline = jiffies + MAX_READY_WAIT_JIFFIES; -+ -+ do { -+ cond_resched(); -+ -+ sr = read_sr(nor); -+ if (sr < 0) -+ break; -+ else if (!(sr & SR_WIP)) -+ return 0; -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ return -ETIMEDOUT; -+} -+ -+static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) -+{ -+ unsigned long deadline; -+ int sr; -+ int fsr; -+ -+ deadline = jiffies + MAX_READY_WAIT_JIFFIES; -+ -+ do { -+ cond_resched(); -+ -+ sr = read_sr(nor); -+ if (sr < 0) { -+ break; -+ } else if (!(sr & SR_WIP)) { -+ fsr = read_fsr(nor); -+ if (fsr < 0) -+ break; -+ if (fsr & FSR_READY) -+ return 0; -+ } -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ return -ETIMEDOUT; -+} -+ -+/* -+ * Service routine to read status register until ready, or timeout occurs. -+ * Returns non-zero if error. -+ */ -+static int wait_till_ready(struct spi_nor *nor) -+{ -+ return nor->wait_till_ready(nor); -+} -+ -+/* -+ * Erase the whole flash memory -+ * -+ * Returns 0 if successful, non-zero otherwise. -+ */ -+static int erase_chip(struct spi_nor *nor) -+{ -+ int ret; -+ -+ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); -+ -+ /* Wait until finished previous write command. */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* Send write enable, then erase commands. */ -+ write_enable(nor); -+ -+ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); -+} -+ -+static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ int ret = 0; -+ -+ mutex_lock(&nor->lock); -+ -+ if (nor->prepare) { -+ ret = nor->prepare(nor, ops); -+ if (ret) { -+ dev_err(nor->dev, "failed in the preparation.\n"); -+ mutex_unlock(&nor->lock); -+ return ret; -+ } -+ } -+ return ret; -+} -+ -+static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops) -+{ -+ if (nor->unprepare) -+ nor->unprepare(nor, ops); -+ mutex_unlock(&nor->lock); -+} -+ -+/* -+ * Erase an address range on the nor chip. The address range may extend -+ * one or more erase sectors. Return an error is there is a problem erasing. -+ */ -+static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ u32 addr, len; -+ uint32_t rem; -+ int ret; -+ -+ dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr, -+ (long long)instr->len); -+ -+ div_u64_rem(instr->len, mtd->erasesize, &rem); -+ if (rem) -+ return -EINVAL; -+ -+ addr = instr->addr; -+ len = instr->len; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_ERASE); -+ if (ret) -+ return ret; -+ -+ /* whole-chip erase? */ -+ if (len == mtd->size) { -+ if (erase_chip(nor)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -+ /* REVISIT in some cases we could speed up erasing large regions -+ * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up -+ * to use "small sector erase", but that's not always optimal. -+ */ -+ -+ /* "sector"-at-a-time erase */ -+ } else { -+ while (len) { -+ if (nor->erase(nor, addr)) { -+ ret = -EIO; -+ goto erase_err; -+ } -+ -+ addr += mtd->erasesize; -+ len -= mtd->erasesize; -+ } -+ } -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ -+ instr->state = MTD_ERASE_DONE; -+ mtd_erase_callback(instr); -+ -+ return ret; -+ -+erase_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); -+ instr->state = MTD_ERASE_FAILED; -+ return ret; -+} -+ -+static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ uint32_t offset = ofs; -+ uint8_t status_old, status_new; -+ int ret = 0; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous command */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto err; -+ -+ status_old = read_sr(nor); -+ -+ if (offset < mtd->size - (mtd->size / 2)) -+ status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0; -+ else if (offset < mtd->size - (mtd->size / 4)) -+ status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; -+ else if (offset < mtd->size - (mtd->size / 8)) -+ status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; -+ else if (offset < mtd->size - (mtd->size / 16)) -+ status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; -+ else if (offset < mtd->size - (mtd->size / 32)) -+ status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; -+ else if (offset < mtd->size - (mtd->size / 64)) -+ status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; -+ else -+ status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; -+ -+ /* Only modify protection if it will not unlock other areas */ -+ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) > -+ (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { -+ write_enable(nor); -+ ret = write_sr(nor, status_new); -+ if (ret) -+ goto err; -+ } -+ -+err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK); -+ return ret; -+} -+ -+static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ uint32_t offset = ofs; -+ uint8_t status_old, status_new; -+ int ret = 0; -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous command */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto err; -+ -+ status_old = read_sr(nor); -+ -+ if (offset+len > mtd->size - (mtd->size / 64)) -+ status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0); -+ else if (offset+len > mtd->size - (mtd->size / 32)) -+ status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0; -+ else if (offset+len > mtd->size - (mtd->size / 16)) -+ status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1; -+ else if (offset+len > mtd->size - (mtd->size / 8)) -+ status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0; -+ else if (offset+len > mtd->size - (mtd->size / 4)) -+ status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2; -+ else if (offset+len > mtd->size - (mtd->size / 2)) -+ status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0; -+ else -+ status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1; -+ -+ /* Only modify protection if it will not lock other areas */ -+ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) < -+ (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) { -+ write_enable(nor); -+ ret = write_sr(nor, status_new); -+ if (ret) -+ goto err; -+ } -+ -+err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK); -+ return ret; -+} -+ -+struct flash_info { -+ /* JEDEC id zero means "no ID" (most older chips); otherwise it has -+ * a high byte of zero plus three data bytes: the manufacturer id, -+ * then a two byte device id. -+ */ -+ u32 jedec_id; -+ u16 ext_id; -+ -+ /* The size listed here is what works with SPINOR_OP_SE, which isn't -+ * necessarily called a "sector" by the vendor. -+ */ -+ unsigned sector_size; -+ u16 n_sectors; -+ -+ u16 page_size; -+ u16 addr_width; -+ -+ u16 flags; -+#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -+#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -+#define SST_WRITE 0x04 /* use SST byte programming */ -+#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -+#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -+#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -+#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -+#define USE_FSR 0x80 /* use flag status register */ -+}; -+ -+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -+ ((kernel_ulong_t)&(struct flash_info) { \ -+ .jedec_id = (_jedec_id), \ -+ .ext_id = (_ext_id), \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = 256, \ -+ .flags = (_flags), \ -+ }) -+ -+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \ -+ ((kernel_ulong_t)&(struct flash_info) { \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = (_page_size), \ -+ .addr_width = (_addr_width), \ -+ .flags = (_flags), \ -+ }) -+ -+/* NOTE: double check command sets and memory organization when you add -+ * more nor chips. This current list focusses on newer chips, which -+ * have been converging on command sets which including JEDEC ID. -+ */ -+const struct spi_device_id spi_nor_ids[] = { -+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */ -+ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, -+ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, -+ -+ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) }, -+ { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) }, -+ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) }, -+ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) }, -+ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) }, -+ { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) }, -+ -+ /* EON -- en25xxx */ -+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) }, -+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) }, -+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) }, -+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) }, -+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) }, -+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) }, -+ -+ /* ESMT */ -+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* Everspin */ -+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ -+ /* GigaDevice */ -+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ /* Intel/Numonyx -- xxxs33b */ -+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) }, -+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) }, -+ -+ /* Macronix */ -+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) }, -+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) }, -+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) }, -+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) }, -+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) }, -+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) }, -+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) }, -+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) }, -+ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) }, -+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, -+ -+ /* Micron */ -+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, -+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, -+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, -+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, -+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, -+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, -+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, -+ -+ /* PMC */ -+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) }, -+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) }, -+ -+ /* Spansion -- single (large) sector size only, at least -+ * for the chips listed here (without boot sectors). -+ */ -+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) }, -+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) }, -+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) }, -+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, -+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, -+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, -+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, -+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, -+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, -+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) }, -+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) }, -+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) }, -+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) }, -+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -+ -+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */ -+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, -+ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) }, -+ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) }, -+ { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) }, -+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) }, -+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, -+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, -+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ -+ /* ST Microelectronics -- newer production may have feature updates */ -+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, -+ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) }, -+ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) }, -+ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) }, -+ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) }, -+ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) }, -+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, -+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, -+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, -+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, -+ -+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, -+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, -+ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) }, -+ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) }, -+ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) }, -+ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) }, -+ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) }, -+ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) }, -+ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) }, -+ -+ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) }, -+ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) }, -+ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) }, -+ -+ { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) }, -+ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) }, -+ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) }, -+ -+ { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) }, -+ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, -+ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, -+ -+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ -+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, -+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) }, -+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) }, -+ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) }, -+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, -+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, -+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) }, -+ -+ /* Catalyst / On Semiconductor -- non-JEDEC */ -+ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, -+ { }, -+}; -+EXPORT_SYMBOL_GPL(spi_nor_ids); -+ -+static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) -+{ -+ int tmp; -+ u8 id[5]; -+ u32 jedec; -+ u16 ext_jedec; -+ struct flash_info *info; -+ -+ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); -+ if (tmp < 0) { -+ dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); -+ return ERR_PTR(tmp); -+ } -+ jedec = id[0]; -+ jedec = jedec << 8; -+ jedec |= id[1]; -+ jedec = jedec << 8; -+ jedec |= id[2]; -+ -+ ext_jedec = id[3] << 8 | id[4]; -+ -+ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { -+ info = (void *)spi_nor_ids[tmp].driver_data; -+ if (info->jedec_id == jedec) { -+ if (info->ext_id == 0 || info->ext_id == ext_jedec) -+ return &spi_nor_ids[tmp]; -+ } -+ } -+ dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); -+ return ERR_PTR(-ENODEV); -+} -+ -+static const struct spi_device_id *jedec_probe(struct spi_nor *nor) -+{ -+ return nor->read_id(nor); -+} -+ -+static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, -+ size_t *retlen, u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ int ret; -+ -+ dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ); -+ if (ret) -+ return ret; -+ -+ ret = nor->read(nor, from, len, retlen, buf); -+ -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ); -+ return ret; -+} -+ -+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ size_t actual; -+ int ret; -+ -+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous write command. */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ -+ write_enable(nor); -+ -+ nor->sst_write_second = false; -+ -+ actual = to % 2; -+ /* Start write from odd address. */ -+ if (actual) { -+ nor->program_opcode = SPINOR_OP_BP; -+ -+ /* write one byte. */ -+ nor->write(nor, to, 1, retlen, buf); -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ } -+ to += actual; -+ -+ /* Write out most of the data here. */ -+ for (; actual < len - 1; actual += 2) { -+ nor->program_opcode = SPINOR_OP_AAI_WP; -+ -+ /* write two bytes. */ -+ nor->write(nor, to, 2, retlen, buf + actual); -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ to += 2; -+ nor->sst_write_second = true; -+ } -+ nor->sst_write_second = false; -+ -+ write_disable(nor); -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ -+ /* Write out trailing byte if it exists. */ -+ if (actual != len) { -+ write_enable(nor); -+ -+ nor->program_opcode = SPINOR_OP_BP; -+ nor->write(nor, to, 1, retlen, buf + actual); -+ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto time_out; -+ write_disable(nor); -+ } -+time_out: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+ return ret; -+} -+ -+/* -+ * Write an address range to the nor chip. Data must be written in -+ * FLASH_PAGESIZE chunks. The address range may be any size provided -+ * it is within the physical boundaries. -+ */ -+static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len, -+ size_t *retlen, const u_char *buf) -+{ -+ struct spi_nor *nor = mtd_to_spi_nor(mtd); -+ u32 page_offset, page_size, i; -+ int ret; -+ -+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len); -+ -+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE); -+ if (ret) -+ return ret; -+ -+ /* Wait until finished previous write command. */ -+ ret = wait_till_ready(nor); -+ if (ret) -+ goto write_err; -+ -+ write_enable(nor); -+ -+ page_offset = to & (nor->page_size - 1); -+ -+ /* do all the bytes fit onto one page? */ -+ if (page_offset + len <= nor->page_size) { -+ nor->write(nor, to, len, retlen, buf); -+ } else { -+ /* the size of data remaining on the first page */ -+ page_size = nor->page_size - page_offset; -+ nor->write(nor, to, page_size, retlen, buf); -+ -+ /* write everything in nor->page_size chunks */ -+ for (i = page_size; i < len; i += page_size) { -+ page_size = len - i; -+ if (page_size > nor->page_size) -+ page_size = nor->page_size; -+ -+ wait_till_ready(nor); -+ write_enable(nor); -+ -+ nor->write(nor, to + i, page_size, retlen, buf + i); -+ } -+ } -+ -+write_err: -+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -+ return 0; -+} -+ -+static int macronix_quad_enable(struct spi_nor *nor) -+{ -+ int ret, val; -+ -+ val = read_sr(nor); -+ write_enable(nor); -+ -+ nor->cmd_buf[0] = val | SR_QUAD_EN_MX; -+ nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); -+ -+ if (wait_till_ready(nor)) -+ return 1; -+ -+ ret = read_sr(nor); -+ if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) { -+ dev_err(nor->dev, "Macronix Quad bit not set\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+/* -+ * Write status Register and configuration register with 2 bytes -+ * The first byte will be written to the status register, while the -+ * second byte will be written to the configuration register. -+ * Return negative if error occured. -+ */ -+static int write_sr_cr(struct spi_nor *nor, u16 val) -+{ -+ nor->cmd_buf[0] = val & 0xff; -+ nor->cmd_buf[1] = (val >> 8); -+ -+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0); -+} -+ -+static int spansion_quad_enable(struct spi_nor *nor) -+{ -+ int ret; -+ int quad_en = CR_QUAD_EN_SPAN << 8; -+ -+ write_enable(nor); -+ -+ ret = write_sr_cr(nor, quad_en); -+ if (ret < 0) { -+ dev_err(nor->dev, -+ "error while writing configuration register\n"); -+ return -EINVAL; -+ } -+ -+ /* read back and check it */ -+ ret = read_cr(nor); -+ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) { -+ dev_err(nor->dev, "Spansion Quad bit not set\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ -+static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) -+{ -+ int status; -+ -+ switch (JEDEC_MFR(jedec_id)) { -+ case CFI_MFR_MACRONIX: -+ status = macronix_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Macronix quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ default: -+ status = spansion_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Spansion quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; -+ } -+} -+ -+static int spi_nor_check(struct spi_nor *nor) -+{ -+ if (!nor->dev || !nor->read || !nor->write || -+ !nor->read_reg || !nor->write_reg || !nor->erase) { -+ pr_err("spi-nor: please fill all the necessary fields!\n"); -+ return -EINVAL; -+ } -+ -+ if (!nor->read_id) -+ nor->read_id = spi_nor_read_id; -+ if (!nor->wait_till_ready) -+ nor->wait_till_ready = spi_nor_wait_till_ready; -+ -+ return 0; -+} -+ -+int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, -+ enum read_mode mode) -+{ -+ struct flash_info *info; -+ struct flash_platform_data *data; -+ struct device *dev = nor->dev; -+ struct mtd_info *mtd = nor->mtd; -+ struct device_node *np = dev->of_node; -+ int ret; -+ int i; -+ -+ ret = spi_nor_check(nor); -+ if (ret) -+ return ret; -+ -+ /* Platform data helps sort out which chip type we have, as -+ * well as how this board partitions it. If we don't have -+ * a chip ID, try the JEDEC id commands; they'll work for most -+ * newer chips, even if we don't recognize the particular chip. -+ */ -+ data = dev_get_platdata(dev); -+ if (data && data->type) { -+ const struct spi_device_id *plat_id; -+ -+ for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { -+ plat_id = &spi_nor_ids[i]; -+ if (strcmp(data->type, plat_id->name)) -+ continue; -+ break; -+ } -+ -+ if (i < ARRAY_SIZE(spi_nor_ids) - 1) -+ id = plat_id; -+ else -+ dev_warn(dev, "unrecognized id %s\n", data->type); -+ } -+ -+ info = (void *)id->driver_data; -+ -+ if (info->jedec_id) { -+ const struct spi_device_id *jid; -+ -+ jid = jedec_probe(nor); -+ if (IS_ERR(jid)) { -+ return PTR_ERR(jid); -+ } else if (jid != id) { -+ /* -+ * JEDEC knows better, so overwrite platform ID. We -+ * can't trust partitions any longer, but we'll let -+ * mtd apply them anyway, since some partitions may be -+ * marked read-only, and we don't want to lose that -+ * information, even if it's not 100% accurate. -+ */ -+ dev_warn(dev, "found %s, expected %s\n", -+ jid->name, id->name); -+ id = jid; -+ info = (void *)jid->driver_data; -+ } -+ } -+ -+ mutex_init(&nor->lock); -+ -+ /* -+ * Atmel, SST and Intel/Numonyx serial nor tend to power -+ * up with the software protection bits set -+ */ -+ -+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || -+ JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || -+ JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { -+ write_enable(nor); -+ write_sr(nor, 0); -+ } -+ -+ if (data && data->name) -+ mtd->name = data->name; -+ else -+ mtd->name = dev_name(dev); -+ -+ mtd->type = MTD_NORFLASH; -+ mtd->writesize = 1; -+ mtd->flags = MTD_CAP_NORFLASH; -+ mtd->size = info->sector_size * info->n_sectors; -+ mtd->_erase = spi_nor_erase; -+ mtd->_read = spi_nor_read; -+ -+ /* nor protection support for STmicro chips */ -+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { -+ mtd->_lock = spi_nor_lock; -+ mtd->_unlock = spi_nor_unlock; -+ } -+ -+ /* sst nor chips use AAI word program */ -+ if (info->flags & SST_WRITE) -+ mtd->_write = sst_write; -+ else -+ mtd->_write = spi_nor_write; -+ -+ if ((info->flags & USE_FSR) && -+ nor->wait_till_ready == spi_nor_wait_till_ready) -+ nor->wait_till_ready = spi_nor_wait_till_fsr_ready; -+ -+ /* prefer "small sector" erase if possible */ -+ if (info->flags & SECT_4K) { -+ nor->erase_opcode = SPINOR_OP_BE_4K; -+ mtd->erasesize = 4096; -+ } else if (info->flags & SECT_4K_PMC) { -+ nor->erase_opcode = SPINOR_OP_BE_4K_PMC; -+ mtd->erasesize = 4096; -+ } else { -+ nor->erase_opcode = SPINOR_OP_SE; -+ mtd->erasesize = info->sector_size; -+ } -+ -+ if (info->flags & SPI_NOR_NO_ERASE) -+ mtd->flags |= MTD_NO_ERASE; -+ -+ mtd->dev.parent = dev; -+ nor->page_size = info->page_size; -+ mtd->writebufsize = nor->page_size; -+ -+ if (np) { -+ /* If we were instantiated by DT, use it */ -+ if (of_property_read_bool(np, "m25p,fast-read")) -+ nor->flash_read = SPI_NOR_FAST; -+ else -+ nor->flash_read = SPI_NOR_NORMAL; -+ } else { -+ /* If we weren't instantiated by DT, default to fast-read */ -+ nor->flash_read = SPI_NOR_FAST; -+ } -+ -+ /* Some devices cannot do fast-read, no matter what DT tells us */ -+ if (info->flags & SPI_NOR_NO_FR) -+ nor->flash_read = SPI_NOR_NORMAL; -+ -+ /* Quad/Dual-read mode takes precedence over fast/normal */ -+ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { -+ ret = set_quad_mode(nor, info->jedec_id); -+ if (ret) { -+ dev_err(dev, "quad mode not supported\n"); -+ return ret; -+ } -+ nor->flash_read = SPI_NOR_QUAD; -+ } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) { -+ nor->flash_read = SPI_NOR_DUAL; -+ } -+ -+ /* Default commands */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ_1_1_4; -+ break; -+ case SPI_NOR_DUAL: -+ nor->read_opcode = SPINOR_OP_READ_1_1_2; -+ break; -+ case SPI_NOR_FAST: -+ nor->read_opcode = SPINOR_OP_READ_FAST; -+ break; -+ case SPI_NOR_NORMAL: -+ nor->read_opcode = SPINOR_OP_READ; -+ break; -+ default: -+ dev_err(dev, "No Read opcode defined\n"); -+ return -EINVAL; -+ } -+ -+ nor->program_opcode = SPINOR_OP_PP; -+ -+ if (info->addr_width) -+ nor->addr_width = info->addr_width; -+ else if (mtd->size > 0x1000000) { -+ /* enable 4-byte addressing if the device exceeds 16MiB */ -+ nor->addr_width = 4; -+ if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { -+ /* Dedicated 4-byte command set */ -+ switch (nor->flash_read) { -+ case SPI_NOR_QUAD: -+ nor->read_opcode = SPINOR_OP_READ4_1_1_4; -+ break; -+ case SPI_NOR_DUAL: -+ nor->read_opcode = SPINOR_OP_READ4_1_1_2; -+ break; -+ case SPI_NOR_FAST: -+ nor->read_opcode = SPINOR_OP_READ4_FAST; -+ break; -+ case SPI_NOR_NORMAL: -+ nor->read_opcode = SPINOR_OP_READ4; -+ break; -+ } -+ nor->program_opcode = SPINOR_OP_PP_4B; -+ /* No small sector erase for 4-byte command set */ -+ nor->erase_opcode = SPINOR_OP_SE_4B; -+ mtd->erasesize = info->sector_size; -+ } else -+ set_4byte(nor, info->jedec_id, 1); -+ } else { -+ nor->addr_width = 3; -+ } -+ -+ nor->read_dummy = spi_nor_read_dummy_cycles(nor); -+ -+ dev_info(dev, "%s (%lld Kbytes)\n", id->name, -+ (long long)mtd->size >> 10); -+ -+ dev_dbg(dev, -+ "mtd .name = %s, .size = 0x%llx (%lldMiB), " -+ ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n", -+ mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20), -+ mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions); -+ -+ if (mtd->numeraseregions) -+ for (i = 0; i < mtd->numeraseregions; i++) -+ dev_dbg(dev, -+ "mtd.eraseregions[%d] = { .offset = 0x%llx, " -+ ".erasesize = 0x%.8x (%uKiB), " -+ ".numblocks = %d }\n", -+ i, (long long)mtd->eraseregions[i].offset, -+ mtd->eraseregions[i].erasesize, -+ mtd->eraseregions[i].erasesize / 1024, -+ mtd->eraseregions[i].numblocks); -+ return 0; -+} -+EXPORT_SYMBOL_GPL(spi_nor_scan); -+ -+const struct spi_device_id *spi_nor_match_id(char *name) -+{ -+ const struct spi_device_id *id = spi_nor_ids; -+ -+ while (id->name[0]) { -+ if (!strcmp(name, id->name)) -+ return id; -+ id++; -+ } -+ return NULL; -+} -+EXPORT_SYMBOL_GPL(spi_nor_match_id); -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>"); -+MODULE_AUTHOR("Mike Lavender"); -+MODULE_DESCRIPTION("framework for SPI NOR"); ---- /dev/null -+++ b/include/linux/mtd/spi-nor.h -@@ -0,0 +1,218 @@ -+/* -+ * Copyright (C) 2014 Freescale Semiconductor, Inc. -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ */ -+ -+#ifndef __LINUX_MTD_SPI_NOR_H -+#define __LINUX_MTD_SPI_NOR_H -+ -+/* -+ * Note on opcode nomenclature: some opcodes have a format like -+ * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number -+ * of I/O lines used for the opcode, address, and data (respectively). The -+ * FUNCTION has an optional suffix of '4', to represent an opcode which -+ * requires a 4-byte (32-bit) address. -+ */ -+ -+/* Flash opcodes. */ -+#define SPINOR_OP_WREN 0x06 /* Write enable */ -+#define SPINOR_OP_RDSR 0x05 /* Read status register */ -+#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */ -+#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */ -+#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */ -+#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */ -+#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */ -+#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */ -+#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */ -+#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */ -+#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */ -+#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */ -+#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */ -+#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */ -+#define SPINOR_OP_RDCR 0x35 /* Read configuration register */ -+#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */ -+ -+/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */ -+#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */ -+#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */ -+#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */ -+#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */ -+#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */ -+#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */ -+ -+/* Used for SST flashes only. */ -+#define SPINOR_OP_BP 0x02 /* Byte program */ -+#define SPINOR_OP_WRDI 0x04 /* Write disable */ -+#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */ -+ -+/* Used for Macronix and Winbond flashes. */ -+#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */ -+#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */ -+ -+/* Used for Spansion flashes only. */ -+#define SPINOR_OP_BRWR 0x17 /* Bank register write */ -+ -+/* Status Register bits. */ -+#define SR_WIP 1 /* Write in progress */ -+#define SR_WEL 2 /* Write enable latch */ -+/* meaning of other SR_* bits may differ between vendors */ -+#define SR_BP0 4 /* Block protect 0 */ -+#define SR_BP1 8 /* Block protect 1 */ -+#define SR_BP2 0x10 /* Block protect 2 */ -+#define SR_SRWD 0x80 /* SR write protect */ -+ -+#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ -+ -+/* Flag Status Register bits */ -+#define FSR_READY 0x80 -+ -+/* Configuration Register bits. */ -+#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */ -+ -+enum read_mode { -+ SPI_NOR_NORMAL = 0, -+ SPI_NOR_FAST, -+ SPI_NOR_DUAL, -+ SPI_NOR_QUAD, -+}; -+ -+/** -+ * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer -+ * @wren: command for "Write Enable", or 0x00 for not required -+ * @cmd: command for operation -+ * @cmd_pins: number of pins to send @cmd (1, 2, 4) -+ * @addr: address for operation -+ * @addr_pins: number of pins to send @addr (1, 2, 4) -+ * @addr_width: number of address bytes -+ * (3,4, or 0 for address not required) -+ * @mode: mode data -+ * @mode_pins: number of pins to send @mode (1, 2, 4) -+ * @mode_cycles: number of mode cycles (0 for mode not required) -+ * @dummy_cycles: number of dummy cycles (0 for dummy not required) -+ */ -+struct spi_nor_xfer_cfg { -+ u8 wren; -+ u8 cmd; -+ u8 cmd_pins; -+ u32 addr; -+ u8 addr_pins; -+ u8 addr_width; -+ u8 mode; -+ u8 mode_pins; -+ u8 mode_cycles; -+ u8 dummy_cycles; -+}; -+ -+#define SPI_NOR_MAX_CMD_SIZE 8 -+enum spi_nor_ops { -+ SPI_NOR_OPS_READ = 0, -+ SPI_NOR_OPS_WRITE, -+ SPI_NOR_OPS_ERASE, -+ SPI_NOR_OPS_LOCK, -+ SPI_NOR_OPS_UNLOCK, -+}; -+ -+/** -+ * struct spi_nor - Structure for defining a the SPI NOR layer -+ * @mtd: point to a mtd_info structure -+ * @lock: the lock for the read/write/erase/lock/unlock operations -+ * @dev: point to a spi device, or a spi nor controller device. -+ * @page_size: the page size of the SPI NOR -+ * @addr_width: number of address bytes -+ * @erase_opcode: the opcode for erasing a sector -+ * @read_opcode: the read opcode -+ * @read_dummy: the dummy needed by the read operation -+ * @program_opcode: the program opcode -+ * @flash_read: the mode of the read -+ * @sst_write_second: used by the SST write operation -+ * @cfg: used by the read_xfer/write_xfer -+ * @cmd_buf: used by the write_reg -+ * @prepare: [OPTIONAL] do some preparations for the -+ * read/write/erase/lock/unlock operations -+ * @unprepare: [OPTIONAL] do some post work after the -+ * read/write/erase/lock/unlock operations -+ * @read_xfer: [OPTIONAL] the read fundamental primitive -+ * @write_xfer: [OPTIONAL] the writefundamental primitive -+ * @read_reg: [DRIVER-SPECIFIC] read out the register -+ * @write_reg: [DRIVER-SPECIFIC] write data to the register -+ * @read_id: [REPLACEABLE] read out the ID data, and find -+ * the proper spi_device_id -+ * @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready -+ * @read: [DRIVER-SPECIFIC] read data from the SPI NOR -+ * @write: [DRIVER-SPECIFIC] write data to the SPI NOR -+ * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR -+ * at the offset @offs -+ * @priv: the private data -+ */ -+struct spi_nor { -+ struct mtd_info *mtd; -+ struct mutex lock; -+ struct device *dev; -+ u32 page_size; -+ u8 addr_width; -+ u8 erase_opcode; -+ u8 read_opcode; -+ u8 read_dummy; -+ u8 program_opcode; -+ enum read_mode flash_read; -+ bool sst_write_second; -+ struct spi_nor_xfer_cfg cfg; -+ u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; -+ -+ int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops); -+ void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops); -+ int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, -+ u8 *buf, size_t len); -+ int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg, -+ u8 *buf, size_t len); -+ int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); -+ int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, -+ int write_enable); -+ const struct spi_device_id *(*read_id)(struct spi_nor *nor); -+ int (*wait_till_ready)(struct spi_nor *nor); -+ -+ int (*read)(struct spi_nor *nor, loff_t from, -+ size_t len, size_t *retlen, u_char *read_buf); -+ void (*write)(struct spi_nor *nor, loff_t to, -+ size_t len, size_t *retlen, const u_char *write_buf); -+ int (*erase)(struct spi_nor *nor, loff_t offs); -+ -+ void *priv; -+}; -+ -+/** -+ * spi_nor_scan() - scan the SPI NOR -+ * @nor: the spi_nor structure -+ * @id: the spi_device_id provided by the driver -+ * @mode: the read mode supported by the driver -+ * -+ * The drivers can use this fuction to scan the SPI NOR. -+ * In the scanning, it will try to get all the necessary information to -+ * fill the mtd_info{} and the spi_nor{}. -+ * -+ * The board may assigns a spi_device_id with @id which be used to compared with -+ * the spi_device_id detected by the scanning. -+ * -+ * Return: 0 for success, others for failure. -+ */ -+int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, -+ enum read_mode mode); -+extern const struct spi_device_id spi_nor_ids[]; -+ -+/** -+ * spi_nor_match_id() - find the spi_device_id by the name -+ * @name: the name of the spi_device_id -+ * -+ * The drivers use this function to find the spi_device_id -+ * specified by the @name. -+ * -+ * Return: returns the right spi_device_id pointer on success, -+ * and returns NULL on failure. -+ */ -+const struct spi_device_id *spi_nor_match_id(char *name); -+ -+#endif diff --git a/target/linux/bcm53xx/patches-3.14/002-mtd-spi-nor-from-3.18.patch b/target/linux/bcm53xx/patches-3.14/002-mtd-spi-nor-from-3.18.patch deleted file mode 100644 index 873861ab63..0000000000 --- a/target/linux/bcm53xx/patches-3.14/002-mtd-spi-nor-from-3.18.patch +++ /dev/null @@ -1,219 +0,0 @@ ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -28,6 +28,8 @@ - - #define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) - -+static const struct spi_device_id *spi_nor_match_id(const char *name); -+ - /* - * Read the status register, returning its value in the location - * Return the status register value. -@@ -473,7 +475,7 @@ struct flash_info { - * more nor chips. This current list focusses on newer chips, which - * have been converging on command sets which including JEDEC ID. - */ --const struct spi_device_id spi_nor_ids[] = { -+static const struct spi_device_id spi_nor_ids[] = { - /* Atmel -- some are (confusingly) marketed as "DataFlash" */ - { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) }, - { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) }, -@@ -611,6 +613,7 @@ const struct spi_device_id spi_nor_ids[] - { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) }, - { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) }, - { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) }, -+ { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) }, - - /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */ - { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) }, -@@ -623,7 +626,6 @@ const struct spi_device_id spi_nor_ids[] - { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) }, - { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) }, - { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) }, -- { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, - { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) }, - { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) }, - { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) }, -@@ -637,7 +639,6 @@ const struct spi_device_id spi_nor_ids[] - { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, - { }, - }; --EXPORT_SYMBOL_GPL(spi_nor_ids); - - static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) - { -@@ -671,11 +672,6 @@ static const struct spi_device_id *spi_n - return ERR_PTR(-ENODEV); - } - --static const struct spi_device_id *jedec_probe(struct spi_nor *nor) --{ -- return nor->read_id(nor); --} -- - static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) - { -@@ -916,11 +912,10 @@ static int spi_nor_check(struct spi_nor - return 0; - } - --int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, -- enum read_mode mode) -+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode) - { -+ const struct spi_device_id *id = NULL; - struct flash_info *info; -- struct flash_platform_data *data; - struct device *dev = nor->dev; - struct mtd_info *mtd = nor->mtd; - struct device_node *np = dev->of_node; -@@ -931,34 +926,16 @@ int spi_nor_scan(struct spi_nor *nor, co - if (ret) - return ret; - -- /* Platform data helps sort out which chip type we have, as -- * well as how this board partitions it. If we don't have -- * a chip ID, try the JEDEC id commands; they'll work for most -- * newer chips, even if we don't recognize the particular chip. -- */ -- data = dev_get_platdata(dev); -- if (data && data->type) { -- const struct spi_device_id *plat_id; -- -- for (i = 0; i < ARRAY_SIZE(spi_nor_ids) - 1; i++) { -- plat_id = &spi_nor_ids[i]; -- if (strcmp(data->type, plat_id->name)) -- continue; -- break; -- } -- -- if (i < ARRAY_SIZE(spi_nor_ids) - 1) -- id = plat_id; -- else -- dev_warn(dev, "unrecognized id %s\n", data->type); -- } -+ id = spi_nor_match_id(name); -+ if (!id) -+ return -ENOENT; - - info = (void *)id->driver_data; - - if (info->jedec_id) { - const struct spi_device_id *jid; - -- jid = jedec_probe(nor); -+ jid = nor->read_id(nor); - if (IS_ERR(jid)) { - return PTR_ERR(jid); - } else if (jid != id) { -@@ -990,11 +967,8 @@ int spi_nor_scan(struct spi_nor *nor, co - write_sr(nor, 0); - } - -- if (data && data->name) -- mtd->name = data->name; -- else -+ if (!mtd->name) - mtd->name = dev_name(dev); -- - mtd->type = MTD_NORFLASH; - mtd->writesize = 1; - mtd->flags = MTD_CAP_NORFLASH; -@@ -1018,6 +992,7 @@ int spi_nor_scan(struct spi_nor *nor, co - nor->wait_till_ready == spi_nor_wait_till_ready) - nor->wait_till_ready = spi_nor_wait_till_fsr_ready; - -+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS - /* prefer "small sector" erase if possible */ - if (info->flags & SECT_4K) { - nor->erase_opcode = SPINOR_OP_BE_4K; -@@ -1025,7 +1000,9 @@ int spi_nor_scan(struct spi_nor *nor, co - } else if (info->flags & SECT_4K_PMC) { - nor->erase_opcode = SPINOR_OP_BE_4K_PMC; - mtd->erasesize = 4096; -- } else { -+ } else -+#endif -+ { - nor->erase_opcode = SPINOR_OP_SE; - mtd->erasesize = info->sector_size; - } -@@ -1141,7 +1118,7 @@ int spi_nor_scan(struct spi_nor *nor, co - } - EXPORT_SYMBOL_GPL(spi_nor_scan); - --const struct spi_device_id *spi_nor_match_id(char *name) -+static const struct spi_device_id *spi_nor_match_id(const char *name) - { - const struct spi_device_id *id = spi_nor_ids; - -@@ -1152,7 +1129,6 @@ const struct spi_device_id *spi_nor_matc - } - return NULL; - } --EXPORT_SYMBOL_GPL(spi_nor_match_id); - - MODULE_LICENSE("GPL"); - MODULE_AUTHOR("Huang Shijie <shijie8@gmail.com>"); ---- a/drivers/mtd/spi-nor/Kconfig -+++ b/drivers/mtd/spi-nor/Kconfig -@@ -7,6 +7,20 @@ menuconfig MTD_SPI_NOR - - if MTD_SPI_NOR - -+config MTD_SPI_NOR_USE_4K_SECTORS -+ bool "Use small 4096 B erase sectors" -+ default y -+ help -+ Many flash memories support erasing small (4096 B) sectors. Depending -+ on the usage this feature may provide performance gain in comparison -+ to erasing whole blocks (32/64 KiB). -+ Changing a small part of the flash's contents is usually faster with -+ small sectors. On the other hand erasing should be faster when using -+ 64 KiB block instead of 16 × 4 KiB sectors. -+ -+ Please note that some tools/drivers/filesystems may not work with -+ 4096 B erase size (e.g. UBIFS requires 15 KiB as a minimum). -+ - config SPI_FSL_QUADSPI - tristate "Freescale Quad SPI controller" - depends on ARCH_MXC ---- a/include/linux/mtd/spi-nor.h -+++ b/include/linux/mtd/spi-nor.h -@@ -187,32 +187,17 @@ struct spi_nor { - /** - * spi_nor_scan() - scan the SPI NOR - * @nor: the spi_nor structure -- * @id: the spi_device_id provided by the driver -+ * @name: the chip type name - * @mode: the read mode supported by the driver - * - * The drivers can use this fuction to scan the SPI NOR. - * In the scanning, it will try to get all the necessary information to - * fill the mtd_info{} and the spi_nor{}. - * -- * The board may assigns a spi_device_id with @id which be used to compared with -- * the spi_device_id detected by the scanning. -+ * The chip type name can be provided through the @name parameter. - * - * Return: 0 for success, others for failure. - */ --int spi_nor_scan(struct spi_nor *nor, const struct spi_device_id *id, -- enum read_mode mode); --extern const struct spi_device_id spi_nor_ids[]; -- --/** -- * spi_nor_match_id() - find the spi_device_id by the name -- * @name: the name of the spi_device_id -- * -- * The drivers use this function to find the spi_device_id -- * specified by the @name. -- * -- * Return: returns the right spi_device_id pointer on success, -- * and returns NULL on failure. -- */ --const struct spi_device_id *spi_nor_match_id(char *name); -+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode); - - #endif diff --git a/target/linux/bcm53xx/patches-3.14/003-mtd-spi-nor-from-3.19.patch b/target/linux/bcm53xx/patches-3.14/003-mtd-spi-nor-from-3.19.patch deleted file mode 100644 index 5451b9c6a4..0000000000 --- a/target/linux/bcm53xx/patches-3.14/003-mtd-spi-nor-from-3.19.patch +++ /dev/null @@ -1,662 +0,0 @@ ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -26,7 +26,38 @@ - /* Define max times to check status register before we give up. */ - #define MAX_READY_WAIT_JIFFIES (40 * HZ) /* M25P16 specs 40s max chip erase */ - --#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16) -+#define SPI_NOR_MAX_ID_LEN 6 -+ -+struct flash_info { -+ /* -+ * This array stores the ID bytes. -+ * The first three bytes are the JEDIC ID. -+ * JEDEC ID zero means "no ID" (mostly older chips). -+ */ -+ u8 id[SPI_NOR_MAX_ID_LEN]; -+ u8 id_len; -+ -+ /* The size listed here is what works with SPINOR_OP_SE, which isn't -+ * necessarily called a "sector" by the vendor. -+ */ -+ unsigned sector_size; -+ u16 n_sectors; -+ -+ u16 page_size; -+ u16 addr_width; -+ -+ u16 flags; -+#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ -+#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ -+#define SST_WRITE 0x04 /* use SST byte programming */ -+#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ -+#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ -+#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ -+#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ -+#define USE_FSR 0x80 /* use flag status register */ -+}; -+ -+#define JEDEC_MFR(info) ((info)->id[0]) - - static const struct spi_device_id *spi_nor_match_id(const char *name); - -@@ -98,7 +129,7 @@ static inline int spi_nor_read_dummy_cyc - case SPI_NOR_FAST: - case SPI_NOR_DUAL: - case SPI_NOR_QUAD: -- return 1; -+ return 8; - case SPI_NOR_NORMAL: - return 0; - } -@@ -138,13 +169,14 @@ static inline struct spi_nor *mtd_to_spi - } - - /* Enable/disable 4-byte addressing mode. */ --static inline int set_4byte(struct spi_nor *nor, u32 jedec_id, int enable) -+static inline int set_4byte(struct spi_nor *nor, struct flash_info *info, -+ int enable) - { - int status; - bool need_wren = false; - u8 cmd; - -- switch (JEDEC_MFR(jedec_id)) { -+ switch (JEDEC_MFR(info)) { - case CFI_MFR_ST: /* Micron, actually */ - /* Some Micron need WREN command; all will accept it */ - need_wren = true; -@@ -165,81 +197,74 @@ static inline int set_4byte(struct spi_n - return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0); - } - } -- --static int spi_nor_wait_till_ready(struct spi_nor *nor) -+static inline int spi_nor_sr_ready(struct spi_nor *nor) - { -- unsigned long deadline; -- int sr; -- -- deadline = jiffies + MAX_READY_WAIT_JIFFIES; -- -- do { -- cond_resched(); -+ int sr = read_sr(nor); -+ if (sr < 0) -+ return sr; -+ else -+ return !(sr & SR_WIP); -+} - -- sr = read_sr(nor); -- if (sr < 0) -- break; -- else if (!(sr & SR_WIP)) -- return 0; -- } while (!time_after_eq(jiffies, deadline)); -+static inline int spi_nor_fsr_ready(struct spi_nor *nor) -+{ -+ int fsr = read_fsr(nor); -+ if (fsr < 0) -+ return fsr; -+ else -+ return fsr & FSR_READY; -+} - -- return -ETIMEDOUT; -+static int spi_nor_ready(struct spi_nor *nor) -+{ -+ int sr, fsr; -+ sr = spi_nor_sr_ready(nor); -+ if (sr < 0) -+ return sr; -+ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1; -+ if (fsr < 0) -+ return fsr; -+ return sr && fsr; - } - --static int spi_nor_wait_till_fsr_ready(struct spi_nor *nor) -+/* -+ * Service routine to read status register until ready, or timeout occurs. -+ * Returns non-zero if error. -+ */ -+static int spi_nor_wait_till_ready(struct spi_nor *nor) - { - unsigned long deadline; -- int sr; -- int fsr; -+ int timeout = 0, ret; - - deadline = jiffies + MAX_READY_WAIT_JIFFIES; - -- do { -+ while (!timeout) { -+ if (time_after_eq(jiffies, deadline)) -+ timeout = 1; -+ -+ ret = spi_nor_ready(nor); -+ if (ret < 0) -+ return ret; -+ if (ret) -+ return 0; -+ - cond_resched(); -+ } - -- sr = read_sr(nor); -- if (sr < 0) { -- break; -- } else if (!(sr & SR_WIP)) { -- fsr = read_fsr(nor); -- if (fsr < 0) -- break; -- if (fsr & FSR_READY) -- return 0; -- } -- } while (!time_after_eq(jiffies, deadline)); -+ dev_err(nor->dev, "flash operation timed out\n"); - - return -ETIMEDOUT; - } - - /* -- * Service routine to read status register until ready, or timeout occurs. -- * Returns non-zero if error. -- */ --static int wait_till_ready(struct spi_nor *nor) --{ -- return nor->wait_till_ready(nor); --} -- --/* - * Erase the whole flash memory - * - * Returns 0 if successful, non-zero otherwise. - */ - static int erase_chip(struct spi_nor *nor) - { -- int ret; -- - dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10)); - -- /* Wait until finished previous write command. */ -- ret = wait_till_ready(nor); -- if (ret) -- return ret; -- -- /* Send write enable, then erase commands. */ -- write_enable(nor); -- - return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0); - } - -@@ -294,11 +319,17 @@ static int spi_nor_erase(struct mtd_info - - /* whole-chip erase? */ - if (len == mtd->size) { -+ write_enable(nor); -+ - if (erase_chip(nor)) { - ret = -EIO; - goto erase_err; - } - -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto erase_err; -+ - /* REVISIT in some cases we could speed up erasing large regions - * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up - * to use "small sector erase", but that's not always optimal. -@@ -307,6 +338,8 @@ static int spi_nor_erase(struct mtd_info - /* "sector"-at-a-time erase */ - } else { - while (len) { -+ write_enable(nor); -+ - if (nor->erase(nor, addr)) { - ret = -EIO; - goto erase_err; -@@ -314,9 +347,15 @@ static int spi_nor_erase(struct mtd_info - - addr += mtd->erasesize; - len -= mtd->erasesize; -+ -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto erase_err; - } - } - -+ write_disable(nor); -+ - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE); - - instr->state = MTD_ERASE_DONE; -@@ -341,11 +380,6 @@ static int spi_nor_lock(struct mtd_info - if (ret) - return ret; - -- /* Wait until finished previous command */ -- ret = wait_till_ready(nor); -- if (ret) -- goto err; -- - status_old = read_sr(nor); - - if (offset < mtd->size - (mtd->size / 2)) -@@ -388,11 +422,6 @@ static int spi_nor_unlock(struct mtd_inf - if (ret) - return ret; - -- /* Wait until finished previous command */ -- ret = wait_till_ready(nor); -- if (ret) -- goto err; -- - status_old = read_sr(nor); - - if (offset+len > mtd->size - (mtd->size / 64)) -@@ -424,38 +453,34 @@ err: - return ret; - } - --struct flash_info { -- /* JEDEC id zero means "no ID" (most older chips); otherwise it has -- * a high byte of zero plus three data bytes: the manufacturer id, -- * then a two byte device id. -- */ -- u32 jedec_id; -- u16 ext_id; -- -- /* The size listed here is what works with SPINOR_OP_SE, which isn't -- * necessarily called a "sector" by the vendor. -- */ -- unsigned sector_size; -- u16 n_sectors; -- -- u16 page_size; -- u16 addr_width; -- -- u16 flags; --#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */ --#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */ --#define SST_WRITE 0x04 /* use SST byte programming */ --#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */ --#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */ --#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */ --#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */ --#define USE_FSR 0x80 /* use flag status register */ --}; -- -+/* Used when the "_ext_id" is two bytes at most */ - #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ - ((kernel_ulong_t)&(struct flash_info) { \ -- .jedec_id = (_jedec_id), \ -- .ext_id = (_ext_id), \ -+ .id = { \ -+ ((_jedec_id) >> 16) & 0xff, \ -+ ((_jedec_id) >> 8) & 0xff, \ -+ (_jedec_id) & 0xff, \ -+ ((_ext_id) >> 8) & 0xff, \ -+ (_ext_id) & 0xff, \ -+ }, \ -+ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ -+ .sector_size = (_sector_size), \ -+ .n_sectors = (_n_sectors), \ -+ .page_size = 256, \ -+ .flags = (_flags), \ -+ }) -+ -+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ -+ ((kernel_ulong_t)&(struct flash_info) { \ -+ .id = { \ -+ ((_jedec_id) >> 16) & 0xff, \ -+ ((_jedec_id) >> 8) & 0xff, \ -+ (_jedec_id) & 0xff, \ -+ ((_ext_id) >> 16) & 0xff, \ -+ ((_ext_id) >> 8) & 0xff, \ -+ (_ext_id) & 0xff, \ -+ }, \ -+ .id_len = 6, \ - .sector_size = (_sector_size), \ - .n_sectors = (_n_sectors), \ - .page_size = 256, \ -@@ -507,6 +532,9 @@ static const struct spi_device_id spi_no - { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, - { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) }, - -+ /* Fujitsu */ -+ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) }, -+ - /* GigaDevice */ - { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, - { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, -@@ -532,6 +560,7 @@ static const struct spi_device_id spi_no - { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, - - /* Micron */ -+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, - { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, - { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, - { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, -@@ -556,6 +585,7 @@ static const struct spi_device_id spi_no - { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) }, - { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) }, - { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) }, -+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, - { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) }, - { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) }, - { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) }, -@@ -577,6 +607,7 @@ static const struct spi_device_id spi_no - { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) }, - { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) }, - { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) }, -+ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) }, - - /* ST Microelectronics -- newer production may have feature updates */ - { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) }, -@@ -588,7 +619,6 @@ static const struct spi_device_id spi_no - { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) }, - { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) }, - { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) }, -- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, - - { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) }, - { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) }, -@@ -643,32 +673,24 @@ static const struct spi_device_id spi_no - static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) - { - int tmp; -- u8 id[5]; -- u32 jedec; -- u16 ext_jedec; -+ u8 id[SPI_NOR_MAX_ID_LEN]; - struct flash_info *info; - -- tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); -+ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); - if (tmp < 0) { - dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); - return ERR_PTR(tmp); - } -- jedec = id[0]; -- jedec = jedec << 8; -- jedec |= id[1]; -- jedec = jedec << 8; -- jedec |= id[2]; -- -- ext_jedec = id[3] << 8 | id[4]; - - for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { - info = (void *)spi_nor_ids[tmp].driver_data; -- if (info->jedec_id == jedec) { -- if (info->ext_id == 0 || info->ext_id == ext_jedec) -+ if (info->id_len) { -+ if (!memcmp(info->id, id, info->id_len)) - return &spi_nor_ids[tmp]; - } - } -- dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); -+ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", -+ id[0], id[1], id[2]); - return ERR_PTR(-ENODEV); - } - -@@ -703,11 +725,6 @@ static int sst_write(struct mtd_info *mt - if (ret) - return ret; - -- /* Wait until finished previous write command. */ -- ret = wait_till_ready(nor); -- if (ret) -- goto time_out; -- - write_enable(nor); - - nor->sst_write_second = false; -@@ -719,7 +736,7 @@ static int sst_write(struct mtd_info *mt - - /* write one byte. */ - nor->write(nor, to, 1, retlen, buf); -- ret = wait_till_ready(nor); -+ ret = spi_nor_wait_till_ready(nor); - if (ret) - goto time_out; - } -@@ -731,7 +748,7 @@ static int sst_write(struct mtd_info *mt - - /* write two bytes. */ - nor->write(nor, to, 2, retlen, buf + actual); -- ret = wait_till_ready(nor); -+ ret = spi_nor_wait_till_ready(nor); - if (ret) - goto time_out; - to += 2; -@@ -740,7 +757,7 @@ static int sst_write(struct mtd_info *mt - nor->sst_write_second = false; - - write_disable(nor); -- ret = wait_till_ready(nor); -+ ret = spi_nor_wait_till_ready(nor); - if (ret) - goto time_out; - -@@ -751,7 +768,7 @@ static int sst_write(struct mtd_info *mt - nor->program_opcode = SPINOR_OP_BP; - nor->write(nor, to, 1, retlen, buf + actual); - -- ret = wait_till_ready(nor); -+ ret = spi_nor_wait_till_ready(nor); - if (ret) - goto time_out; - write_disable(nor); -@@ -779,11 +796,6 @@ static int spi_nor_write(struct mtd_info - if (ret) - return ret; - -- /* Wait until finished previous write command. */ -- ret = wait_till_ready(nor); -- if (ret) -- goto write_err; -- - write_enable(nor); - - page_offset = to & (nor->page_size - 1); -@@ -802,16 +814,20 @@ static int spi_nor_write(struct mtd_info - if (page_size > nor->page_size) - page_size = nor->page_size; - -- wait_till_ready(nor); -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ goto write_err; -+ - write_enable(nor); - - nor->write(nor, to + i, page_size, retlen, buf + i); - } - } - -+ ret = spi_nor_wait_till_ready(nor); - write_err: - spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE); -- return 0; -+ return ret; - } - - static int macronix_quad_enable(struct spi_nor *nor) -@@ -824,7 +840,7 @@ static int macronix_quad_enable(struct s - nor->cmd_buf[0] = val | SR_QUAD_EN_MX; - nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0); - -- if (wait_till_ready(nor)) -+ if (spi_nor_wait_till_ready(nor)) - return 1; - - ret = read_sr(nor); -@@ -874,11 +890,11 @@ static int spansion_quad_enable(struct s - return 0; - } - --static int set_quad_mode(struct spi_nor *nor, u32 jedec_id) -+static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) - { - int status; - -- switch (JEDEC_MFR(jedec_id)) { -+ switch (JEDEC_MFR(info)) { - case CFI_MFR_MACRONIX: - status = macronix_quad_enable(nor); - if (status) { -@@ -904,11 +920,6 @@ static int spi_nor_check(struct spi_nor - return -EINVAL; - } - -- if (!nor->read_id) -- nor->read_id = spi_nor_read_id; -- if (!nor->wait_till_ready) -- nor->wait_till_ready = spi_nor_wait_till_ready; -- - return 0; - } - -@@ -926,16 +937,24 @@ int spi_nor_scan(struct spi_nor *nor, co - if (ret) - return ret; - -- id = spi_nor_match_id(name); -- if (!id) -+ /* Try to auto-detect if chip name wasn't specified */ -+ if (!name) -+ id = spi_nor_read_id(nor); -+ else -+ id = spi_nor_match_id(name); -+ if (IS_ERR_OR_NULL(id)) - return -ENOENT; - - info = (void *)id->driver_data; - -- if (info->jedec_id) { -+ /* -+ * If caller has specified name of flash model that can normally be -+ * detected using JEDEC, let's verify it. -+ */ -+ if (name && info->id_len) { - const struct spi_device_id *jid; - -- jid = nor->read_id(nor); -+ jid = spi_nor_read_id(nor); - if (IS_ERR(jid)) { - return PTR_ERR(jid); - } else if (jid != id) { -@@ -960,9 +979,9 @@ int spi_nor_scan(struct spi_nor *nor, co - * up with the software protection bits set - */ - -- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL || -- JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL || -- JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) { -+ if (JEDEC_MFR(info) == CFI_MFR_ATMEL || -+ JEDEC_MFR(info) == CFI_MFR_INTEL || -+ JEDEC_MFR(info) == CFI_MFR_SST) { - write_enable(nor); - write_sr(nor, 0); - } -@@ -977,7 +996,7 @@ int spi_nor_scan(struct spi_nor *nor, co - mtd->_read = spi_nor_read; - - /* nor protection support for STmicro chips */ -- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ST) { -+ if (JEDEC_MFR(info) == CFI_MFR_ST) { - mtd->_lock = spi_nor_lock; - mtd->_unlock = spi_nor_unlock; - } -@@ -988,9 +1007,8 @@ int spi_nor_scan(struct spi_nor *nor, co - else - mtd->_write = spi_nor_write; - -- if ((info->flags & USE_FSR) && -- nor->wait_till_ready == spi_nor_wait_till_ready) -- nor->wait_till_ready = spi_nor_wait_till_fsr_ready; -+ if (info->flags & USE_FSR) -+ nor->flags |= SNOR_F_USE_FSR; - - #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS - /* prefer "small sector" erase if possible */ -@@ -1031,7 +1049,7 @@ int spi_nor_scan(struct spi_nor *nor, co - - /* Quad/Dual-read mode takes precedence over fast/normal */ - if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) { -- ret = set_quad_mode(nor, info->jedec_id); -+ ret = set_quad_mode(nor, info); - if (ret) { - dev_err(dev, "quad mode not supported\n"); - return ret; -@@ -1067,7 +1085,7 @@ int spi_nor_scan(struct spi_nor *nor, co - else if (mtd->size > 0x1000000) { - /* enable 4-byte addressing if the device exceeds 16MiB */ - nor->addr_width = 4; -- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_AMD) { -+ if (JEDEC_MFR(info) == CFI_MFR_AMD) { - /* Dedicated 4-byte command set */ - switch (nor->flash_read) { - case SPI_NOR_QUAD: -@@ -1088,7 +1106,7 @@ int spi_nor_scan(struct spi_nor *nor, co - nor->erase_opcode = SPINOR_OP_SE_4B; - mtd->erasesize = info->sector_size; - } else -- set_4byte(nor, info->jedec_id, 1); -+ set_4byte(nor, info, 1); - } else { - nor->addr_width = 3; - } ---- a/include/linux/mtd/spi-nor.h -+++ b/include/linux/mtd/spi-nor.h -@@ -116,6 +116,10 @@ enum spi_nor_ops { - SPI_NOR_OPS_UNLOCK, - }; - -+enum spi_nor_option_flags { -+ SNOR_F_USE_FSR = BIT(0), -+}; -+ - /** - * struct spi_nor - Structure for defining a the SPI NOR layer - * @mtd: point to a mtd_info structure -@@ -129,6 +133,7 @@ enum spi_nor_ops { - * @program_opcode: the program opcode - * @flash_read: the mode of the read - * @sst_write_second: used by the SST write operation -+ * @flags: flag options for the current SPI-NOR (SNOR_F_*) - * @cfg: used by the read_xfer/write_xfer - * @cmd_buf: used by the write_reg - * @prepare: [OPTIONAL] do some preparations for the -@@ -139,9 +144,6 @@ enum spi_nor_ops { - * @write_xfer: [OPTIONAL] the writefundamental primitive - * @read_reg: [DRIVER-SPECIFIC] read out the register - * @write_reg: [DRIVER-SPECIFIC] write data to the register -- * @read_id: [REPLACEABLE] read out the ID data, and find -- * the proper spi_device_id -- * @wait_till_ready: [REPLACEABLE] wait till the NOR becomes ready - * @read: [DRIVER-SPECIFIC] read data from the SPI NOR - * @write: [DRIVER-SPECIFIC] write data to the SPI NOR - * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR -@@ -160,6 +162,7 @@ struct spi_nor { - u8 program_opcode; - enum read_mode flash_read; - bool sst_write_second; -+ u32 flags; - struct spi_nor_xfer_cfg cfg; - u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE]; - -@@ -172,8 +175,6 @@ struct spi_nor { - int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len); - int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len, - int write_enable); -- const struct spi_device_id *(*read_id)(struct spi_nor *nor); -- int (*wait_till_ready)(struct spi_nor *nor); - - int (*read)(struct spi_nor *nor, loff_t from, - size_t len, size_t *retlen, u_char *read_buf); diff --git a/target/linux/bcm53xx/patches-3.14/004-mtd-spi-nor-from-3.20.patch b/target/linux/bcm53xx/patches-3.14/004-mtd-spi-nor-from-3.20.patch deleted file mode 100644 index 8a20da6279..0000000000 --- a/target/linux/bcm53xx/patches-3.14/004-mtd-spi-nor-from-3.20.patch +++ /dev/null @@ -1,116 +0,0 @@ ---- a/drivers/mtd/spi-nor/spi-nor.c -+++ b/drivers/mtd/spi-nor/spi-nor.c -@@ -538,6 +538,7 @@ static const struct spi_device_id spi_no - /* GigaDevice */ - { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) }, - { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) }, -+ { "gd25q128", INFO(0xc84018, 0, 64 * 1024, 256, SECT_4K) }, - - /* Intel/Numonyx -- xxxs33b */ - { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) }, -@@ -560,14 +561,14 @@ static const struct spi_device_id spi_no - { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) }, - - /* Micron */ -- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) }, -- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) }, -- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) }, -- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) }, -- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) }, -- { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) }, -- { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) }, -- { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR) }, -+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, SPI_NOR_QUAD_READ) }, -+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, SPI_NOR_QUAD_READ) }, -+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, -+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, SPI_NOR_QUAD_READ) }, -+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) }, -+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, -+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) }, - - /* PMC */ - { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) }, -@@ -890,6 +891,45 @@ static int spansion_quad_enable(struct s - return 0; - } - -+static int micron_quad_enable(struct spi_nor *nor) -+{ -+ int ret; -+ u8 val; -+ -+ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading EVCR\n", ret); -+ return ret; -+ } -+ -+ write_enable(nor); -+ -+ /* set EVCR, enable quad I/O */ -+ nor->cmd_buf[0] = val & ~EVCR_QUAD_EN_MICRON; -+ ret = nor->write_reg(nor, SPINOR_OP_WD_EVCR, nor->cmd_buf, 1, 0); -+ if (ret < 0) { -+ dev_err(nor->dev, "error while writing EVCR register\n"); -+ return ret; -+ } -+ -+ ret = spi_nor_wait_till_ready(nor); -+ if (ret) -+ return ret; -+ -+ /* read EVCR and check it */ -+ ret = nor->read_reg(nor, SPINOR_OP_RD_EVCR, &val, 1); -+ if (ret < 0) { -+ dev_err(nor->dev, "error %d reading EVCR\n", ret); -+ return ret; -+ } -+ if (val & EVCR_QUAD_EN_MICRON) { -+ dev_err(nor->dev, "Micron EVCR Quad bit not clear\n"); -+ return -EINVAL; -+ } -+ -+ return 0; -+} -+ - static int set_quad_mode(struct spi_nor *nor, struct flash_info *info) - { - int status; -@@ -902,6 +942,13 @@ static int set_quad_mode(struct spi_nor - return -EINVAL; - } - return status; -+ case CFI_MFR_ST: -+ status = micron_quad_enable(nor); -+ if (status) { -+ dev_err(nor->dev, "Micron quad-read not enabled\n"); -+ return -EINVAL; -+ } -+ return status; - default: - status = spansion_quad_enable(nor); - if (status) { ---- a/include/linux/mtd/spi-nor.h -+++ b/include/linux/mtd/spi-nor.h -@@ -56,6 +56,10 @@ - /* Used for Spansion flashes only. */ - #define SPINOR_OP_BRWR 0x17 /* Bank register write */ - -+/* Used for Micron flashes only. */ -+#define SPINOR_OP_RD_EVCR 0x65 /* Read EVCR register */ -+#define SPINOR_OP_WD_EVCR 0x61 /* Write EVCR register */ -+ - /* Status Register bits. */ - #define SR_WIP 1 /* Write in progress */ - #define SR_WEL 2 /* Write enable latch */ -@@ -67,6 +71,9 @@ - - #define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */ - -+/* Enhanced Volatile Configuration Register bits */ -+#define EVCR_QUAD_EN_MICRON 0x80 /* Micron Quad I/O */ -+ - /* Flag Status Register bits */ - #define FSR_READY 0x80 - diff --git a/target/linux/bcm53xx/patches-3.14/040-ARM-BCM5301X-initial-support-for-the-BCM5301X-BCM470.patch b/target/linux/bcm53xx/patches-3.14/040-ARM-BCM5301X-initial-support-for-the-BCM5301X-BCM470.patch deleted file mode 100644 index c12d8df0b7..0000000000 --- a/target/linux/bcm53xx/patches-3.14/040-ARM-BCM5301X-initial-support-for-the-BCM5301X-BCM470.patch +++ /dev/null @@ -1,148 +0,0 @@ -From 5b293ebe757213993ae93b6cbbf5e1d09b75ac2f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:43 +0100 -Subject: [PATCH 1/3] ARM: BCM5301X: initial support for the BCM5301X/BCM470X - SoCs with ARM CPU - -This patch adds support for the BCM5301X/BCM470X SoCs with an ARM CPUs. -Currently just booting to a shell is working and nothing else, no -Ethernet, wifi, flash, ... -I have some pending patches to make Ethernet work for this device. -Mostly device tree support for bcma is missing. - -This SoC is used in small office and home router with Broadcom SoCs -it's internal name is Northstar. This code should support the BCM4707, -BCM4708, BCM4709, BCM53010, BCM53011 and BCM53012 SoC. It uses one or -two ARM Cortex A9 Cores, some highlights are 2 PCIe 2.0 controllers, -4 Gigabit Ethernet MACs and a USB 3.0 host controller. - -This SoC uses a dual core CPU, but this is currently not implemented. -More information about this SoC can be found here: -http://www.anandtech.com/show/5925/broadcom-announces-bcm4708x-and-bcm5301x-socs-for-80211ac-routers - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - Documentation/devicetree/bindings/arm/bcm4708.txt | 8 ++++++ - MAINTAINERS | 8 ++++++ - arch/arm/configs/multi_v7_defconfig | 1 + - arch/arm/mach-bcm/Kconfig | 26 +++++++++++++++++++ - arch/arm/mach-bcm/Makefile | 1 + - arch/arm/mach-bcm/bcm_5301x.c | 28 +++++++++++++++++++++ - 6 files changed, 72 insertions(+) - create mode 100644 Documentation/devicetree/bindings/arm/bcm4708.txt - create mode 100644 arch/arm/mach-bcm/bcm_5301x.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/arm/bcm4708.txt -@@ -0,0 +1,8 @@ -+Broadcom BCM4708 device tree bindings -+------------------------------------------- -+ -+Boards with the BCM4708 SoC shall have the following properties: -+ -+Required root node property: -+ -+compatible = "brcm,bcm4708"; ---- a/MAINTAINERS -+++ b/MAINTAINERS -@@ -1883,6 +1883,14 @@ F: arch/arm/boot/dts/bcm2835* - F: arch/arm/configs/bcm2835_defconfig - F: drivers/*/*bcm2835* - -+BROADCOM BCM5301X ARM ARCHICTURE -+M: Hauke Mehrtens <hauke@hauke-m.de> -+L: linux-arm-kernel@lists.infradead.org -+S: Maintained -+F: arch/arm/mach-bcm/bcm_5301x.c -+F: arch/arm/boot/dts/bcm5301x.dtsi -+F: arch/arm/boot/dts/bcm470* -+ - BROADCOM TG3 GIGABIT ETHERNET DRIVER - M: Nithin Nayak Sujir <nsujir@broadcom.com> - M: Michael Chan <mchan@broadcom.com> ---- a/arch/arm/configs/multi_v7_defconfig -+++ b/arch/arm/configs/multi_v7_defconfig -@@ -11,6 +11,7 @@ CONFIG_ARCH_MVEBU=y - CONFIG_MACH_ARMADA_370=y - CONFIG_MACH_ARMADA_XP=y - CONFIG_ARCH_BCM=y -+CONFIG_ARCH_BCM_5301X=y - CONFIG_ARCH_BCM_MOBILE=y - CONFIG_ARCH_BERLIN=y - CONFIG_MACH_BERLIN_BG2=y ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -32,6 +32,32 @@ config ARCH_BCM_MOBILE - BCM11130, BCM11140, BCM11351, BCM28145 and - BCM28155 variants. - -+config ARCH_BCM_5301X -+ bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 -+ depends on MMU -+ select ARM_GIC -+ select CACHE_L2X0 -+ select HAVE_ARM_SCU if SMP -+ select HAVE_ARM_TWD if SMP -+ select HAVE_SMP -+ select COMMON_CLK -+ select GENERIC_CLOCKEVENTS -+ select ARM_GLOBAL_TIMER -+ select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK -+ select MIGHT_HAVE_PCI -+ help -+ Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. -+ -+ This is a network SoC line mostly used in home routers and -+ wifi access points, it's internal name is Northstar. -+ This inclused the following SoC: BCM53010, BCM53011, BCM53012, -+ BCM53014, BCM53015, BCM53016, BCM53017, BCM53018, BCM4707, -+ BCM4708 and BCM4709. -+ -+ Do not confuse this with the BCM4760 which is a totally -+ different SoC or with the older BCM47XX and BCM53XX based -+ network SoC using a MIPS CPU, they are supported by arch/mips/bcm47xx -+ - endmenu - - endif ---- a/arch/arm/mach-bcm/Makefile -+++ b/arch/arm/mach-bcm/Makefile -@@ -13,3 +13,4 @@ - obj-$(CONFIG_ARCH_BCM_MOBILE) := board_bcm281xx.o bcm_kona_smc.o bcm_kona_smc_asm.o kona.o - plus_sec := $(call as-instr,.arch_extension sec,+sec) - AFLAGS_bcm_kona_smc_asm.o :=-Wa,-march=armv7-a$(plus_sec) -+obj-$(CONFIG_ARCH_BCM_5301X) += bcm_5301x.o ---- /dev/null -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -0,0 +1,28 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * -+ * Copyright 2013 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+#include <linux/of_platform.h> -+#include <asm/hardware/cache-l2x0.h> -+ -+#include <asm/mach/arch.h> -+ -+ -+static void __init bcm5301x_dt_init(void) -+{ -+ l2x0_of_init(0, ~0UL); -+ of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); -+} -+ -+static const char __initconst *bcm5301x_dt_compat[] = { -+ "brcm,bcm4708", -+ NULL, -+}; -+ -+DT_MACHINE_START(BCM5301X, "BCM5301X") -+ .init_machine = bcm5301x_dt_init, -+ .dt_compat = bcm5301x_dt_compat, -+MACHINE_END diff --git a/target/linux/bcm53xx/patches-3.14/041-ARM-BCM5301X-add-early-debugging-support.patch b/target/linux/bcm53xx/patches-3.14/041-ARM-BCM5301X-add-early-debugging-support.patch deleted file mode 100644 index 2e028a8dc3..0000000000 --- a/target/linux/bcm53xx/patches-3.14/041-ARM-BCM5301X-add-early-debugging-support.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 065802756b20d878c83290c115f212fc1631cba7 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:44 +0100 -Subject: [PATCH 2/3] ARM: BCM5301X: add early debugging support - -This adds support for early debugging of BCM5301X SoC. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - arch/arm/Kconfig.debug | 7 +++++++ - 1 file changed, 7 insertions(+) - ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -106,6 +106,11 @@ choice - depends on ARCH_BCM2835 - select DEBUG_UART_PL01X - -+ config DEBUG_BCM_5301X -+ bool "Kernel low-level debugging on BCM5301X UART1" -+ depends on ARCH_BCM_5301X -+ select DEBUG_UART_PL01X -+ - config DEBUG_BCM_KONA_UART - bool "Kernel low-level debugging messages via BCM KONA UART" - depends on ARCH_BCM -@@ -1023,6 +1028,7 @@ config DEBUG_UART_PHYS - default 0x101f1000 if ARCH_VERSATILE - default 0x101fb000 if DEBUG_NOMADIK_UART - default 0x16000000 if ARCH_INTEGRATOR -+ default 0x18000300 if DEBUG_BCM_5301X - default 0x1c090000 if DEBUG_VEXPRESS_UART0_RS1 - default 0x20060000 if DEBUG_RK29_UART0 - default 0x20064000 if DEBUG_RK29_UART1 || DEBUG_RK3X_UART2 -@@ -1071,6 +1077,7 @@ config DEBUG_UART_VIRT - default 0xf0009000 if DEBUG_CNS3XXX - default 0xf01fb000 if DEBUG_NOMADIK_UART - default 0xf0201000 if DEBUG_BCM2835 -+ default 0xf1000300 if DEBUG_BCM_5301X - default 0xf11f1000 if ARCH_VERSATILE - default 0xf1600000 if ARCH_INTEGRATOR - default 0xf1c28000 if DEBUG_SUNXI_UART0 diff --git a/target/linux/bcm53xx/patches-3.14/042-ARM-BCM5301X-workaround-suppress-fault.patch b/target/linux/bcm53xx/patches-3.14/042-ARM-BCM5301X-workaround-suppress-fault.patch deleted file mode 100644 index 41a9dd1ac2..0000000000 --- a/target/linux/bcm53xx/patches-3.14/042-ARM-BCM5301X-workaround-suppress-fault.patch +++ /dev/null @@ -1,93 +0,0 @@ -From fdf4850cb5b2e5e549a18b8b41abb001bfb19e9c Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:46 +0100 -Subject: [PATCH 3/3] ARM: BCM5301X: workaround suppress fault - -Without this patch I am getting a unhandled fault exception like this -one after "Freeing unused kernel memory": - -Freeing unused kernel memory: 1260K (c02c1000 - c03fc000) -Unhandled fault: imprecise external abort (0x1c06) at 0xb6f89005 -Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000007 - -The address which is here 0xb6f89005 changes from boot to boot, with a -new build the changes are bigger. With kernel 3.10 I have also seen -this fault at different places in the boot process, but starting with -3.11 they are always occurring after the "Freeing unused kernel memory" -message. I never was able to completely boot to userspace without this -handler. The abort code is constant 0x1c06. This fault just happens -once in the boot process I have never seen it happing twice or more. - -I also tried changing the CPSR.A bit to 0 in init_early, with this code -like Afzal suggested, but that did not change anything: -asm volatile("mrs r12, cpsr\n" - "bic r12, r12, #0x00000100\n" - "msr cpsr_c, r12" ::: "r12", "cc", "memory"); - -Disabling the L2 cache by building with CONFIG_CACHE_L2X0 unset did not -help. - -This workaround was copied from the vendor code including most of the -comments. It says it they think this is caused by the CFE boot loader -used on this device. I do not have any access to any datasheet or -errata document to check this. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - arch/arm/mach-bcm/bcm_5301x.c | 33 +++++++++++++++++++++++++++++++++ - 1 file changed, 33 insertions(+) - ---- a/arch/arm/mach-bcm/bcm_5301x.c -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -9,8 +9,40 @@ - #include <asm/hardware/cache-l2x0.h> - - #include <asm/mach/arch.h> -+#include <asm/siginfo.h> -+#include <asm/signal.h> - - -+static bool first_fault = true; -+ -+static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, -+ struct pt_regs *regs) -+{ -+ if (fsr == 0x1c06 && first_fault) { -+ first_fault = false; -+ -+ /* -+ * These faults with code 0x1c06 happens for no good reason, -+ * possibly left over from the CFE boot loader. -+ */ -+ pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", -+ addr, fsr); -+ -+ /* Returning non-zero causes fault display and panic */ -+ return 0; -+ } -+ -+ /* Others should cause a fault */ -+ return 1; -+} -+ -+static void __init bcm5301x_init_early(void) -+{ -+ /* Install our hook */ -+ hook_fault_code(16 + 6, bcm5301x_abort_handler, SIGBUS, BUS_OBJERR, -+ "imprecise external abort"); -+} -+ - static void __init bcm5301x_dt_init(void) - { - l2x0_of_init(0, ~0UL); -@@ -23,6 +55,7 @@ static const char __initconst *bcm5301x_ - }; - - DT_MACHINE_START(BCM5301X, "BCM5301X") -+ .init_early = bcm5301x_init_early, - .init_machine = bcm5301x_dt_init, - .dt_compat = bcm5301x_dt_compat, - MACHINE_END diff --git a/target/linux/bcm53xx/patches-3.14/043-ARM-BCM5301X-add-dts-files-for-BCM4708-SoC.patch b/target/linux/bcm53xx/patches-3.14/043-ARM-BCM5301X-add-dts-files-for-BCM4708-SoC.patch deleted file mode 100644 index 4e98ec8255..0000000000 --- a/target/linux/bcm53xx/patches-3.14/043-ARM-BCM5301X-add-dts-files-for-BCM4708-SoC.patch +++ /dev/null @@ -1,204 +0,0 @@ -From d27509f19b5f93ea3425cfef782bb3c6541cd44d Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Tue, 4 Feb 2014 00:01:45 +0100 -Subject: [PATCH] ARM: BCM5301X: add dts files for BCM4708 SoC - -This uses the newly added BCM5301X SoC code. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Acked-by: Arnd Bergmann <arnd@arndb.de> -Acked-by: Christian Daudt <bcm@fixthebug.org> -Signed-off-by: Matt Porter <mporter@linaro.org> ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 35 ++++++++++ - arch/arm/boot/dts/bcm4708.dtsi | 34 ++++++++++ - arch/arm/boot/dts/bcm5301x.dtsi | 95 +++++++++++++++++++++++++++ - 4 files changed, 165 insertions(+) - create mode 100644 arch/arm/boot/dts/bcm4708-netgear-r6250.dts - create mode 100644 arch/arm/boot/dts/bcm4708.dtsi - create mode 100644 arch/arm/boot/dts/bcm5301x.dtsi - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -50,6 +50,7 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rp - dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \ - bcm28155-ap.dtb - dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb -+dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -0,0 +1,35 @@ -+/* -+ * Broadcom BCM470X / BCM5301X arm platform code. -+ * DTS for Netgear R6250 V1 -+ * -+ * Copyright 2013 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "netgear,r6250v1", "brcm,bcm4708"; -+ model = "Netgear R6250 V1 (BCM4708)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708.dtsi -@@ -0,0 +1,34 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for BCM4708 SoC. -+ * -+ * Copyright 2013-2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include "bcm5301x.dtsi" -+ -+/ { -+ compatible = "brcm,bcm4708"; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ -+ cpu@1 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x1>; -+ }; -+ }; -+ -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -0,0 +1,95 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * Generic DTS part for all BCM53010, BCM53011, BCM53012, BCM53014, BCM53015, -+ * BCM53016, BCM53017, BCM53018, BCM4707, BCM4708 and BCM4709 SoCs -+ * -+ * Copyright 2013-2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include <dt-bindings/interrupt-controller/irq.h> -+#include <dt-bindings/interrupt-controller/arm-gic.h> -+#include "skeleton.dtsi" -+ -+/ { -+ interrupt-parent = <&gic>; -+ -+ chipcommonA { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x18000000 0x00001000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ uart0: serial@0300 { -+ compatible = "ns16550"; -+ reg = <0x0300 0x100>; -+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; -+ clock-frequency = <100000000>; -+ status = "disabled"; -+ }; -+ -+ uart1: serial@0400 { -+ compatible = "ns16550"; -+ reg = <0x0400 0x100>; -+ interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; -+ clock-frequency = <100000000>; -+ status = "disabled"; -+ }; -+ }; -+ -+ mpcore { -+ compatible = "simple-bus"; -+ ranges = <0x00000000 0x19020000 0x00003000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ scu@0000 { -+ compatible = "arm,cortex-a9-scu"; -+ reg = <0x0000 0x100>; -+ }; -+ -+ timer@0200 { -+ compatible = "arm,cortex-a9-global-timer"; -+ reg = <0x0200 0x100>; -+ interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clk_periph>; -+ }; -+ -+ local-timer@0600 { -+ compatible = "arm,cortex-a9-twd-timer"; -+ reg = <0x0600 0x100>; -+ interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>; -+ clocks = <&clk_periph>; -+ }; -+ -+ gic: interrupt-controller@1000 { -+ compatible = "arm,cortex-a9-gic"; -+ #interrupt-cells = <3>; -+ #address-cells = <0>; -+ interrupt-controller; -+ reg = <0x1000 0x1000>, -+ <0x0100 0x100>; -+ }; -+ -+ L2: cache-controller@2000 { -+ compatible = "arm,pl310-cache"; -+ reg = <0x2000 0x1000>; -+ cache-unified; -+ cache-level = <2>; -+ }; -+ }; -+ -+ clocks { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ /* As long as we do not have a real clock driver us this -+ * fixed clock */ -+ clk_periph: periph { -+ compatible = "fixed-clock"; -+ #clock-cells = <0>; -+ clock-frequency = <400000000>; -+ }; -+ }; -+}; diff --git a/target/linux/bcm53xx/patches-3.14/044-0-ARM-BCM5301X-fix-early-serial-console.patch b/target/linux/bcm53xx/patches-3.14/044-0-ARM-BCM5301X-fix-early-serial-console.patch deleted file mode 100644 index 4ead8c45a1..0000000000 --- a/target/linux/bcm53xx/patches-3.14/044-0-ARM-BCM5301X-fix-early-serial-console.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 140bd60383309e82b5cae3294a907c11a0a12b90 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 14 Sep 2014 21:43:40 +0200 -Subject: [PATCH] ARM: BCM5301X: fix early serial console - -This device actually has a 8250 serial with a shift of 0. -Tested this on a BCM4708. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> -Signed-off-by: Arnd Bergmann <arnd@arndb.de> ---- - arch/arm/Kconfig.debug | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug -index 1c4889d..a528843 100644 ---- a/arch/arm/Kconfig.debug -+++ b/arch/arm/Kconfig.debug -@@ -109,7 +109,7 @@ choice - config DEBUG_BCM_5301X - bool "Kernel low-level debugging on BCM5301X UART1" - depends on ARCH_BCM_5301X -- select DEBUG_UART_PL01X -+ select DEBUG_UART_8250 - - config DEBUG_BCM_KONA_UART - bool "Kernel low-level debugging messages via BCM KONA UART" -@@ -1132,7 +1132,7 @@ config DEBUG_UART_VIRT - config DEBUG_UART_8250_SHIFT - int "Register offset shift for the 8250 debug UART" - depends on DEBUG_LL_UART_8250 || DEBUG_UART_8250 -- default 0 if FOOTBRIDGE || ARCH_IOP32X -+ default 0 if FOOTBRIDGE || ARCH_IOP32X || DEBUG_BCM_5301X - default 2 - - config DEBUG_UART_8250_WORD --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/044-ARM-BCM5301X-Add-Broadcom-s-bus-axi-to-the-DTS-file.patch b/target/linux/bcm53xx/patches-3.14/044-ARM-BCM5301X-Add-Broadcom-s-bus-axi-to-the-DTS-file.patch deleted file mode 100644 index ac52aa0162..0000000000 --- a/target/linux/bcm53xx/patches-3.14/044-ARM-BCM5301X-Add-Broadcom-s-bus-axi-to-the-DTS-file.patch +++ /dev/null @@ -1,43 +0,0 @@ -From a2533caee935fff97e3e8dbfad5cc159e6bf6034 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 1 Oct 2014 09:21:07 +0200 -Subject: [PATCH 1/2] ARM: BCM5301X: Add Broadcom's bus-axi to the DTS file -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/bcm5301x.dtsi | 16 ++++++++++++++++ - 1 file changed, 16 insertions(+) - ---- a/arch/arm/boot/dts/bcm5301x.dtsi -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -8,6 +8,7 @@ - * Licensed under the GNU/GPL. See COPYING for details. - */ - -+#include <dt-bindings/gpio/gpio.h> - #include <dt-bindings/interrupt-controller/irq.h> - #include <dt-bindings/interrupt-controller/arm-gic.h> - #include "skeleton.dtsi" -@@ -92,4 +93,19 @@ - clock-frequency = <400000000>; - }; - }; -+ -+ axi@18000000 { -+ compatible = "brcm,bus-axi"; -+ reg = <0x18000000 0x1000>; -+ ranges = <0x00000000 0x18000000 0x00100000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ chipcommon: chipcommon@0 { -+ reg = <0x00000000 0x1000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ }; -+ }; - }; diff --git a/target/linux/bcm53xx/patches-3.14/045-ARM-BCM5301X-Add-LEDs-for-Netgear-R6250-V1.patch b/target/linux/bcm53xx/patches-3.14/045-ARM-BCM5301X-Add-LEDs-for-Netgear-R6250-V1.patch deleted file mode 100644 index c394f3c481..0000000000 --- a/target/linux/bcm53xx/patches-3.14/045-ARM-BCM5301X-Add-LEDs-for-Netgear-R6250-V1.patch +++ /dev/null @@ -1,54 +0,0 @@ -From b7e4d148906685882a081e7e50692313c5a8724e Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 1 Oct 2014 09:23:09 +0200 -Subject: [PATCH 2/2] ARM: BCM5301X: Add LEDs for Netgear R6250 V1 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 34 +++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - ---- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -32,4 +32,38 @@ - status = "okay"; - }; - }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ logo { -+ label = "bcm53xx:white:logo"; -+ gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ power0 { -+ label = "bcm53xx:green:power"; -+ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ power1 { -+ label = "bcm53xx:amber:power"; -+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ usb { -+ label = "bcm53xx:blue:usb"; -+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wireless { -+ label = "bcm53xx:blue:wireless"; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ }; - }; diff --git a/target/linux/bcm53xx/patches-3.14/046-ARM-BCM5301X-Add-IRQs-to-Broadcom-s-bus-axi-in-DTS-f.patch b/target/linux/bcm53xx/patches-3.14/046-ARM-BCM5301X-Add-IRQs-to-Broadcom-s-bus-axi-in-DTS-f.patch deleted file mode 100644 index 35cd0ca90a..0000000000 --- a/target/linux/bcm53xx/patches-3.14/046-ARM-BCM5301X-Add-IRQs-to-Broadcom-s-bus-axi-in-DTS-f.patch +++ /dev/null @@ -1,58 +0,0 @@ -From dec378827c4aaab6c46ecdd5fc2c3b3155d68743 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Wed, 24 Sep 2014 23:50:07 +0200 -Subject: [PATCH] ARM: BCM5301X: Add IRQs to Broadcom's bus-axi in DTS file - -IRQ support for Broadcom's bus-axi driver bcma was merged into John -Linville's wireless tree and will show up in 3.19. This patch makes use -of this feature in the DTS file for the the BCM5301X SoCs. I left the -PCIe controller out, because this still needs some discussion. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/bcm5301x.dtsi | 34 ++++++++++++++++++++++++++++++++++ - 1 file changed, 34 insertions(+) - ---- a/arch/arm/boot/dts/bcm5301x.dtsi -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -101,6 +101,40 @@ - #address-cells = <1>; - #size-cells = <1>; - -+ #interrupt-cells = <1>; -+ interrupt-map-mask = <0x000fffff 0xffff>; -+ interrupt-map = -+ /* ChipCommon */ -+ <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* USB 2.0 Controller */ -+ <0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* USB 3.0 Controller */ -+ <0x00023000 0 &gic GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 0 */ -+ <0x00024000 0 &gic GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 1 */ -+ <0x00025000 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 2 */ -+ <0x00026000 0 &gic GIC_SPI 149 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* Ethernet Controller 3 */ -+ <0x00027000 0 &gic GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* NAND Controller */ -+ <0x00028000 0 &gic GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 1 &gic GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 2 &gic GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 3 &gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 4 &gic GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 5 &gic GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 6 &gic GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00028000 7 &gic GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>; -+ - chipcommon: chipcommon@0 { - reg = <0x00000000 0x1000>; - diff --git a/target/linux/bcm53xx/patches-3.14/047-ARM-BCM5301X-Add-buttons-for-Netgear-R6250.patch b/target/linux/bcm53xx/patches-3.14/047-ARM-BCM5301X-Add-buttons-for-Netgear-R6250.patch deleted file mode 100644 index 2b9b900064..0000000000 --- a/target/linux/bcm53xx/patches-3.14/047-ARM-BCM5301X-Add-buttons-for-Netgear-R6250.patch +++ /dev/null @@ -1,57 +0,0 @@ -From f6f8234439737171e571a41264280e844a429699 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Sun, 30 Nov 2014 18:28:29 +0100 -Subject: [PATCH] ARM: BCM5301X: Add buttons for Netgear R6250 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 25 +++++++++++++++++++++++++ - arch/arm/boot/dts/bcm5301x.dtsi | 1 + - 2 files changed, 26 insertions(+) - ---- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -66,4 +66,29 @@ - linux,default-trigger = "default-off"; - }; - }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ poll-interval = <200>; -+ -+ wps { -+ label = "WPS"; -+ linux,code = <KEY_WPS_BUTTON>; -+ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>; -+ }; -+ -+ rfkill { -+ label = "WiFi"; -+ linux,code = <KEY_RFKILL>; -+ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>; -+ }; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>; -+ }; -+ }; - }; ---- a/arch/arm/boot/dts/bcm5301x.dtsi -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -9,6 +9,7 @@ - */ - - #include <dt-bindings/gpio/gpio.h> -+#include <dt-bindings/input/input.h> - #include <dt-bindings/interrupt-controller/irq.h> - #include <dt-bindings/interrupt-controller/arm-gic.h> - #include "skeleton.dtsi" diff --git a/target/linux/bcm53xx/patches-3.14/048-ARM-BCM5301X-Add-DT-for-Netgear-R6300-V2.patch b/target/linux/bcm53xx/patches-3.14/048-ARM-BCM5301X-Add-DT-for-Netgear-R6300-V2.patch deleted file mode 100644 index a9e049a731..0000000000 --- a/target/linux/bcm53xx/patches-3.14/048-ARM-BCM5301X-Add-DT-for-Netgear-R6300-V2.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 302a5ef29d497449280422576a1b55c72fc0ba4c Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 4 Dec 2014 10:22:02 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Netgear R6300 V2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/Makefile | 4 +- - arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 84 ++++++++++++++++++++++++++ - 2 files changed, 87 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -50,7 +50,9 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rp - dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm11351-brt.dtb \ - bcm28155-ap.dtb - dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb --dtb-$(CONFIG_ARCH_BCM_5301X) += bcm4708-netgear-r6250.dtb -+dtb-$(CONFIG_ARCH_BCM_5301X) += \ -+ bcm4708-netgear-r6250.dtb \ -+ bcm4708-netgear-r6300-v2.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -@@ -0,0 +1,84 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Netgear R6300 V2 -+ * -+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "netgear,r6300v2", "brcm,bcm4708"; -+ model = "Netgear R6300 V2 (BCM4708)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ logo { -+ label = "bcm53xx:white:logo"; -+ gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ power0 { -+ label = "bcm53xx:green:power"; -+ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ power1 { -+ label = "bcm53xx:amber:power"; -+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ usb { -+ label = "bcm53xx:blue:usb"; -+ gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wireless { -+ label = "bcm53xx:blue:wireless"; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ poll-interval = <200>; -+ -+ wps { -+ label = "WPS"; -+ linux,code = <KEY_WPS_BUTTON>; -+ gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>; -+ }; -+ -+ rfkill { -+ label = "WiFi"; -+ linux,code = <KEY_RFKILL>; -+ gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>; -+ }; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; diff --git a/target/linux/bcm53xx/patches-3.14/049-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-1750DHP.patch b/target/linux/bcm53xx/patches-3.14/049-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-1750DHP.patch deleted file mode 100644 index 01d85aa030..0000000000 --- a/target/linux/bcm53xx/patches-3.14/049-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-1750DHP.patch +++ /dev/null @@ -1,93 +0,0 @@ -From e336a14d2a2aa4431a8acc9eb3305b37f26fb696 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 4 Dec 2014 10:22:58 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WZR-1750DHP -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 64 +++++++++++++++++++++++ - 2 files changed, 65 insertions(+) - create mode 100644 arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -51,6 +51,7 @@ dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm1135 - bcm28155-ap.dtb - dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb - dtb-$(CONFIG_ARCH_BCM_5301X) += \ -+ bcm4708-buffalo-wzr-1750dhp.dtb \ - bcm4708-netgear-r6250.dtb \ - bcm4708-netgear-r6300-v2.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -@@ -0,0 +1,64 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Buffalo WZR-1750DHP -+ * -+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "buffalo,wzr-1750dhp", "brcm,bcm4708"; -+ model = "Buffalo WZR-1750DHP (BCM4708)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ poll-interval = <200>; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ }; -+ -+ aoss { -+ label = "AOSS"; -+ linux,code = <KEY_WPS_BUTTON>; -+ gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>; -+ }; -+ -+ /* Commit mode set by switch? */ -+ mode { -+ label = "Mode"; -+ linux,code = <KEY_SETUP>; -+ gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>; -+ }; -+ -+ /* Switch: AP mode */ -+ sw_ap { -+ label = "AP"; -+ linux,code = <BTN_0>; -+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>; -+ }; -+ -+ eject { -+ label = "USB eject"; -+ linux,code = <KEY_EJECTCD>; -+ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; diff --git a/target/linux/bcm53xx/patches-3.14/050-ARM-BCM5301X-Add-DT-for-Asus-RT-N18U.patch b/target/linux/bcm53xx/patches-3.14/050-ARM-BCM5301X-Add-DT-for-Asus-RT-N18U.patch deleted file mode 100644 index edcabcd994..0000000000 --- a/target/linux/bcm53xx/patches-3.14/050-ARM-BCM5301X-Add-DT-for-Asus-RT-N18U.patch +++ /dev/null @@ -1,140 +0,0 @@ -From ae2ed35a40007bf737da452df7081a453bf89ce3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 4 Dec 2014 10:23:33 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-N18U -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/Makefile | 3 +- - arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 78 +++++++++++++++++++++++++++++ - arch/arm/boot/dts/bcm47081.dtsi | 26 ++++++++++ - 3 files changed, 106 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts - create mode 100644 arch/arm/boot/dts/bcm47081.dtsi - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -53,7 +53,8 @@ dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rp - dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4708-buffalo-wzr-1750dhp.dtb \ - bcm4708-netgear-r6250.dtb \ -- bcm4708-netgear-r6300-v2.dtb -+ bcm4708-netgear-r6300-v2.dtb \ -+ bcm47081-asus-rt-n18u.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -@@ -0,0 +1,78 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Asus RT-N18U -+ * -+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm47081.dtsi" -+ -+/ { -+ compatible = "asus,rt-n18u", "brcm,bcm47081", "brcm,bcm4708"; -+ model = "Asus RT-N18U (BCM47081)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ power { -+ label = "bcm53xx:blue:power"; -+ gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ usb2 { -+ label = "bcm53xx:blue:usb2"; -+ gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wan { -+ label = "bcm53xx:blue:wan"; -+ gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ lan { -+ label = "bcm53xx:blue:lan"; -+ gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ usb3 { -+ label = "bcm53xx:blue:usb3"; -+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>; -+ linux,default-trigger = "default-off"; -+ }; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ poll-interval = <200>; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; -+ }; -+ -+ wps { -+ label = "WPS"; -+ linux,code = <KEY_WPS_BUTTON>; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; ---- /dev/null -+++ b/arch/arm/boot/dts/bcm47081.dtsi -@@ -0,0 +1,26 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for BCM47081 SoC. -+ * -+ * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include "bcm5301x.dtsi" -+ -+/ { -+ compatible = "brcm,bcm47081"; -+ -+ cpus { -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ cpu@0 { -+ device_type = "cpu"; -+ compatible = "arm,cortex-a9"; -+ next-level-cache = <&L2>; -+ reg = <0x0>; -+ }; -+ }; -+}; diff --git a/target/linux/bcm53xx/patches-3.14/051-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-600DHP2.patch b/target/linux/bcm53xx/patches-3.14/051-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-600DHP2.patch deleted file mode 100644 index da5274f807..0000000000 --- a/target/linux/bcm53xx/patches-3.14/051-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-600DHP2.patch +++ /dev/null @@ -1,88 +0,0 @@ -From dd7733da69f198f576d7f52f6bc5a860fe24930d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 4 Dec 2014 10:24:02 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WZR-600DHP2 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/Makefile | 3 +- - arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 57 ++++++++++++++++++++++ - 2 files changed, 59 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts - ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -54,7 +54,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4708-buffalo-wzr-1750dhp.dtb \ - bcm4708-netgear-r6250.dtb \ - bcm4708-netgear-r6300-v2.dtb \ -- bcm47081-asus-rt-n18u.dtb -+ bcm47081-asus-rt-n18u.dtb \ -+ bcm47081-buffalo-wzr-600dhp2.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -@@ -0,0 +1,57 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Buffalo WZR-600DHP2 -+ * -+ * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm47081.dtsi" -+ -+/ { -+ compatible = "buffalo,wzr-600dhp2", "brcm,bcm47081", "brcm,bcm4708"; -+ model = "Buffalo WZR-600DHP2 (BCM47081)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ poll-interval = <200>; -+ -+ aoss { -+ label = "AOSS"; -+ linux,code = <KEY_WPS_BUTTON>; -+ gpios = <&chipcommon 9 GPIO_ACTIVE_LOW>; -+ }; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ }; -+ -+ /* Switch device mode? */ -+ mode { -+ label = "Mode"; -+ linux,code = <KEY_SETUP>; -+ gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>; -+ }; -+ -+ eject { -+ label = "USB eject"; -+ linux,code = <KEY_EJECTCD>; -+ gpios = <&chipcommon 15 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; diff --git a/target/linux/bcm53xx/patches-3.14/052-ARM-BCM5301X-Add-DT-for-Luxul-XWC-1000.patch b/target/linux/bcm53xx/patches-3.14/052-ARM-BCM5301X-Add-DT-for-Luxul-XWC-1000.patch deleted file mode 100644 index dfbab9d470..0000000000 --- a/target/linux/bcm53xx/patches-3.14/052-ARM-BCM5301X-Add-DT-for-Luxul-XWC-1000.patch +++ /dev/null @@ -1,97 +0,0 @@ -From e27a09ae9369e10bc589ef4d720ecf4abcbcec50 Mon Sep 17 00:00:00 2001 -From: Dan Haab <dhaab@luxul.com> -Date: Mon, 19 Jan 2015 12:45:37 -0700 -Subject: [PATCH] ARM: BCM5301X: Add DT for Luxul XWC-1000 - -Luxul XWC-1000 is a controller device based on BCM4708 SoC. The only -unusual thing in its DTS file is "ubi" partition on NAND flash. - -Signed-off-by: Dan Haab <dhaab@luxul.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/Makefile | 1 + - arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 60 ++++++++++++++++++++++++++++ - 2 files changed, 61 insertions(+) - create mode 100644 arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 91bd5bd..ff4a5ae 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -52,6 +52,7 @@ dtb-$(CONFIG_ARCH_BCM_MOBILE) += bcm1135 - dtb-$(CONFIG_ARCH_BCM2835) += bcm2835-rpi-b.dtb - dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4708-buffalo-wzr-1750dhp.dtb \ -+ bcm4708-luxul-xwc-1000.dtb \ - bcm4708-netgear-r6250.dtb \ - bcm4708-netgear-r6300-v2.dtb \ - bcm47081-asus-rt-n18u.dtb \ -diff --git a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts -new file mode 100644 -index 0000000..946c728 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts -@@ -0,0 +1,60 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Luxul XWC-1000 -+ * -+ * Copyright 2014 Luxul Inc. -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "luxul,xwc-1000", "brcm,bcm4708"; -+ model = "Luxul XWC-1000 (BCM4708)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ axi@18000000 { -+ nand@28000 { -+ reg = <0x00028000 0x1000>; -+ #address-cells = <1>; -+ #size-cells = <1>; -+ -+ partition@0 { -+ label = "ubi"; -+ reg = <0x00000000 0x08000000>; -+ }; -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ status { -+ label = "bcm53xx:green:status"; -+ gpios = <&chipcommon 0 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "timer"; -+ }; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/053-ARM-BCM5301X-Drop-unused-poll-interval-from-gpio-key.patch b/target/linux/bcm53xx/patches-3.14/053-ARM-BCM5301X-Drop-unused-poll-interval-from-gpio-key.patch deleted file mode 100644 index 177b360d9e..0000000000 --- a/target/linux/bcm53xx/patches-3.14/053-ARM-BCM5301X-Drop-unused-poll-interval-from-gpio-key.patch +++ /dev/null @@ -1,84 +0,0 @@ -From 78b745a4b05c920beaa66dfb140af134b5fc2425 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 14 Jan 2015 08:20:48 +0100 -Subject: [PATCH] ARM: BCM5301X: Drop unused poll-interval from gpio-keys -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -It was accidentally left (& copied & pasted all around) from our -experiments with gpio-keys-polled. - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 1 - - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 1 - - arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 1 - - arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 1 - - arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 1 - - 5 files changed, 5 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -index 5fc0fae..13d51a9 100644 ---- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -@@ -27,7 +27,6 @@ - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; -- poll-interval = <200>; - - restart { - label = "Reset"; -diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -index 4ed7de1..f18c9d9 100644 ---- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -71,7 +71,6 @@ - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; -- poll-interval = <200>; - - wps { - label = "WPS"; -diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -index 12fc2a01..3991042 100644 ---- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -@@ -61,7 +61,6 @@ - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; -- poll-interval = <200>; - - wps { - label = "WPS"; -diff --git a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -index fb76378..0ee85ea 100644 ---- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -@@ -61,7 +61,6 @@ - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; -- poll-interval = <200>; - - restart { - label = "Reset"; -diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -index bbb414f..e23dbbf 100644 ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -@@ -27,7 +27,6 @@ - compatible = "gpio-keys"; - #address-cells = <1>; - #size-cells = <0>; -- poll-interval = <200>; - - aoss { - label = "AOSS"; --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/054-ARM-BCM5301X-Add-LEDs-for-Buffalo-devices.patch b/target/linux/bcm53xx/patches-3.14/054-ARM-BCM5301X-Add-LEDs-for-Buffalo-devices.patch deleted file mode 100644 index d9a66076dc..0000000000 --- a/target/linux/bcm53xx/patches-3.14/054-ARM-BCM5301X-Add-LEDs-for-Buffalo-devices.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 8115a4e8d687427fbc1aa3774f50551563bf87f9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 14 Jan 2015 08:20:49 +0100 -Subject: [PATCH] ARM: BCM5301X: Add LEDs for Buffalo devices -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 67 ++++++++++++++++++++++ - arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 67 ++++++++++++++++++++++ - 2 files changed, 134 insertions(+) - -diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -index 13d51a9..b359c1e 100644 ---- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -@@ -23,6 +23,73 @@ - reg = <0x00000000 0x08000000>; - }; - -+ spi { -+ compatible = "spi-gpio"; -+ num-chipselects = <1>; -+ gpio-sck = <&chipcommon 7 0>; -+ gpio-mosi = <&chipcommon 4 0>; -+ cs-gpios = <&chipcommon 6 0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hc595: gpio_spi@0 { -+ compatible = "fairchild,74hc595"; -+ reg = <0>; -+ registers-number = <1>; -+ spi-max-frequency = <100000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ power0 { -+ label = "bcm53xx:red:power"; -+ gpios = <&hc595 1 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ power1 { -+ label = "bcm53xx:white:power"; -+ gpios = <&hc595 2 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ router0 { -+ label = "bcm53xx:blue:router"; -+ gpios = <&hc595 3 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ router1 { -+ label = "bcm53xx:amber:router"; -+ gpios = <&hc595 4 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wan { -+ label = "bcm53xx:blue:wan"; -+ gpios = <&hc595 5 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ wireless0 { -+ label = "bcm53xx:blue:wireless"; -+ gpios = <&hc595 6 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wireless1 { -+ label = "bcm53xx:amber:wireless"; -+ gpios = <&hc595 7 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ }; -+ - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; -diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -index e23dbbf..db9131e 100644 ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -@@ -23,6 +23,73 @@ - reg = <0x00000000 0x08000000>; - }; - -+ spi { -+ compatible = "spi-gpio"; -+ num-chipselects = <1>; -+ gpio-sck = <&chipcommon 7 0>; -+ gpio-mosi = <&chipcommon 4 0>; -+ cs-gpios = <&chipcommon 6 0>; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ hc595: gpio_spi@0 { -+ compatible = "fairchild,74hc595"; -+ reg = <0>; -+ registers-number = <1>; -+ spi-max-frequency = <100000>; -+ -+ gpio-controller; -+ #gpio-cells = <2>; -+ -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ power0 { -+ label = "bcm53xx:green:power"; -+ gpios = <&hc595 1 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ power1 { -+ label = "bcm53xx:red:power"; -+ gpios = <&hc595 2 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ router0 { -+ label = "bcm53xx:green:router"; -+ gpios = <&hc595 3 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ router1 { -+ label = "bcm53xx:amber:router"; -+ gpios = <&hc595 4 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wan { -+ label = "bcm53xx:green:wan"; -+ gpios = <&hc595 5 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-on"; -+ }; -+ -+ wireless0 { -+ label = "bcm53xx:green:wireless"; -+ gpios = <&hc595 6 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ -+ wireless1 { -+ label = "bcm53xx:amber:wireless"; -+ gpios = <&hc595 7 GPIO_ACTIVE_HIGH>; -+ linux,default-trigger = "default-off"; -+ }; -+ }; -+ - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/055-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-900DHP.patch b/target/linux/bcm53xx/patches-3.14/055-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-900DHP.patch deleted file mode 100644 index 70b38136a8..0000000000 --- a/target/linux/bcm53xx/patches-3.14/055-ARM-BCM5301X-Add-DT-for-Buffalo-WZR-900DHP.patch +++ /dev/null @@ -1,73 +0,0 @@ -From 5b1864b899d2b591402704dd0f6528c8661f1817 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Tue, 20 Jan 2015 22:42:16 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Buffalo WZR-900DHP -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/boot/dts/Makefile | 3 +- - arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts | 37 +++++++++++++++++++++++ - 2 files changed, 39 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index ff4a5ae..0de664e 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -56,7 +56,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4708-netgear-r6250.dtb \ - bcm4708-netgear-r6300-v2.dtb \ - bcm47081-asus-rt-n18u.dtb \ -- bcm47081-buffalo-wzr-600dhp2.dtb -+ bcm47081-buffalo-wzr-600dhp2.dtb \ -+ bcm47081-buffalo-wzr-900dhp.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb ---- /dev/null -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -@@ -0,0 +1,37 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Buffalo WZR-900DHP -+ * -+ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm47081.dtsi" -+ -+/ { -+ compatible = "buffalo,wzr-900dhp", "brcm,bcm47081", "brcm,bcm4708"; -+ model = "Buffalo WZR-900DHP (BCM47081)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000>; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/110-firmware-backport-NVRAM-driver.patch b/target/linux/bcm53xx/patches-3.14/110-firmware-backport-NVRAM-driver.patch deleted file mode 100644 index eeabb54354..0000000000 --- a/target/linux/bcm53xx/patches-3.14/110-firmware-backport-NVRAM-driver.patch +++ /dev/null @@ -1,119 +0,0 @@ -From 0509f6dcc46d10ea4bb8c70494dc7ae11bcb3f01 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 10 Dec 2014 21:14:10 +0100 -Subject: [PATCH] firmware: backport NVRAM driver -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/Kconfig | 2 ++ - drivers/firmware/Kconfig | 1 + - drivers/firmware/Makefile | 1 + - drivers/firmware/broadcom/bcm47xx_nvram.c | 3 ++- - drivers/net/ethernet/broadcom/b44.c | 2 +- - drivers/net/ethernet/broadcom/bgmac.c | 2 +- - drivers/ssb/driver_chipcommon_pmu.c | 2 +- - 7 files changed, 9 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig -index 4733d32..ab18030 100644 ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -2286,6 +2286,8 @@ source "net/Kconfig" - - source "drivers/Kconfig" - -+source "drivers/firmware/Kconfig" -+ - source "fs/Kconfig" - - source "arch/arm/Kconfig.debug" -diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig -index 4198388..ffbc9e4 100644 ---- a/drivers/firmware/Kconfig -+++ b/drivers/firmware/Kconfig -@@ -132,6 +132,7 @@ config ISCSI_IBFT - detect iSCSI boot parameters dynamically during system boot, say Y. - Otherwise, say N. - -+source "drivers/firmware/broadcom/Kconfig" - source "drivers/firmware/google/Kconfig" - source "drivers/firmware/efi/Kconfig" - -diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile -index 5373dc5..e251f2b 100644 ---- a/drivers/firmware/Makefile -+++ b/drivers/firmware/Makefile -@@ -12,6 +12,7 @@ obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o - obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o - obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o - -+obj-y += broadcom/ - obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ - obj-$(CONFIG_EFI) += efi/ - obj-$(CONFIG_UEFI_CPER) += efi/ -diff --git a/drivers/firmware/broadcom/bcm47xx_nvram.c b/drivers/firmware/broadcom/bcm47xx_nvram.c -index b6e1cc7..8ca7358 100644 ---- a/drivers/firmware/broadcom/bcm47xx_nvram.c -+++ b/drivers/firmware/broadcom/bcm47xx_nvram.c -@@ -11,6 +11,7 @@ - * option) any later version. - */ - -+#include <linux/io.h> - #include <linux/types.h> - #include <linux/module.h> - #include <linux/kernel.h> -@@ -34,7 +35,7 @@ struct nvram_header { - }; - - static char nvram_buf[NVRAM_SPACE]; --static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000}; -+static const u32 nvram_sizes[] = {0x8000, 0xF000, 0x10000, 0x160000, 0x180000}; - - static u32 find_nvram_size(void __iomem *end) - { -diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c -index 8a7bf7d..bf3bcd6 100644 ---- a/drivers/net/ethernet/broadcom/b44.c -+++ b/drivers/net/ethernet/broadcom/b44.c -@@ -400,7 +400,7 @@ static void b44_set_flow_ctrl(struct b44 *bp, u32 local, u32 remote) - } - - #ifdef CONFIG_BCM47XX --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - static void b44_wap54g10_workaround(struct b44 *bp) - { - char buf[20]; -diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c -index 34c7bc8..943707f 100644 ---- a/drivers/net/ethernet/broadcom/bgmac.c -+++ b/drivers/net/ethernet/broadcom/bgmac.c -@@ -17,7 +17,7 @@ - #include <linux/interrupt.h> - #include <linux/dma-mapping.h> - #include <linux/platform_data/b53.h> --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - - static const struct bcma_device_id bgmac_bcma_tbl[] = { - BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_4706_MAC_GBIT, BCMA_ANY_REV, BCMA_ANY_CLASS), -diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c -index 1173a09..0942841 100644 ---- a/drivers/ssb/driver_chipcommon_pmu.c -+++ b/drivers/ssb/driver_chipcommon_pmu.c -@@ -14,7 +14,7 @@ - #include <linux/delay.h> - #include <linux/export.h> - #ifdef CONFIG_BCM47XX --#include <bcm47xx_nvram.h> -+#include <linux/bcm47xx_nvram.h> - #endif - - #include "ssb_private.h" --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch b/target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch deleted file mode 100644 index e316a661ea..0000000000 --- a/target/linux/bcm53xx/patches-3.14/112-bcm53xx-sprom-add-sprom-driver.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 4e0ab3269a6d260a41a3673157753147f5f71341 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sun, 4 May 2014 13:19:20 +0200 -Subject: [PATCH 03/17] bcm47xx-sprom: add Broadcom sprom parser driver - -This driver needs an nvram driver and fetches the sprom values from the -nvram and provides it to any other driver. The calibration data for the -wifi chip the mac address and some more board description data is -stores in the sprom. - -This is based on a copy of arch/mips/bcm47xx/sprom.c and my plan is to -make the bcm47xx MIPS SoCs also use this driver some time later. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - .../devicetree/bindings/misc/bcm47xx-sprom.txt | 16 + - drivers/misc/Kconfig | 11 + - drivers/misc/Makefile | 1 + - drivers/misc/bcm47xx-sprom.c | 690 +++++++++++++++++++++ - 4 files changed, 718 insertions(+) - create mode 100644 Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt - create mode 100644 drivers/misc/bcm47xx-sprom.c - ---- /dev/null -+++ b/Documentation/devicetree/bindings/misc/bcm47xx-sprom.txt -@@ -0,0 +1,16 @@ -+Broadcom bcm47xx/bcm53xx sprom converter -+ -+This driver provbides an sprom based on a given nvram. -+ -+Required properties: -+ -+- compatible : brcm,bcm47xx-sprom -+ -+- nvram : reference to a nvram driver, e.g. bcm47xx-nvram -+ -+Example: -+ -+sprom0: sprom@0 { -+ compatible = "brcm,bcm47xx-sprom"; -+ nvram = <&nvram0>; -+}; ---- a/drivers/misc/Kconfig -+++ b/drivers/misc/Kconfig -@@ -515,6 +515,17 @@ config SRAM - the genalloc API. It is supposed to be used for small on-chip SRAM - areas found on many SoCs. - -+config BCM47XX_SPROM -+ tristate "BCM47XX sprom driver" -+ help -+ This driver parses the sprom from a given nvram which is found on -+ Broadcom bcm47xx and bcm53xx SoCs. -+ -+ The sprom contains board configuration data like the -+ calibration data fro the wifi chips, the mac addresses used -+ by the board and many other board configuration data. This -+ driver will provide the sprom to bcma. -+ - source "drivers/misc/c2port/Kconfig" - source "drivers/misc/eeprom/Kconfig" - source "drivers/misc/cb710/Kconfig" ---- a/drivers/misc/Makefile -+++ b/drivers/misc/Makefile -@@ -54,3 +54,4 @@ obj-$(CONFIG_LATTICE_ECP3_CONFIG) += lat - obj-$(CONFIG_SRAM) += sram.o - obj-y += mic/ - obj-$(CONFIG_GENWQE) += genwqe/ -+obj-$(CONFIG_BCM47XX_SPROM) += bcm47xx-sprom.o diff --git a/target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch b/target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch deleted file mode 100644 index 4044b44ff2..0000000000 --- a/target/linux/bcm53xx/patches-3.14/130-ARM-BCM5301X-register-bcma-bus.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 414f0ad9b3a8e8ee6eaf09c6d79d5f448ac28630 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sat, 25 Jan 2014 17:03:07 +0100 -Subject: [PATCH 07/17] ARM: BCM5301X: register bcma bus - ---- - arch/arm/boot/dts/bcm4708.dtsi | 58 ++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 58 insertions(+) - ---- a/arch/arm/boot/dts/bcm5301x.dtsi -+++ b/arch/arm/boot/dts/bcm5301x.dtsi -@@ -95,12 +95,23 @@ - }; - }; - -+ nvram0: nvram@1c000000 { -+ compatible = "brcm,bcm47xx-nvram"; -+ reg = <0x1c000000 0x01000000>; -+ }; -+ -+ sprom0: sprom@0 { -+ compatible = "brcm,bcm47xx-sprom"; -+ nvram = <&nvram0>; -+ }; -+ - axi@18000000 { - compatible = "brcm,bus-axi"; - reg = <0x18000000 0x1000>; - ranges = <0x00000000 0x18000000 0x00100000>; - #address-cells = <1>; - #size-cells = <1>; -+ sprom = <&sprom0>; - - #interrupt-cells = <1>; - interrupt-map-mask = <0x000fffff 0xffff>; -@@ -108,6 +119,30 @@ - /* ChipCommon */ - <0x00000000 0 &gic GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>, - -+ /* PCIe Controller 0 */ -+ <0x00012000 0 &gic GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 2 &gic GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 3 &gic GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 4 &gic GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00012000 5 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 1 */ -+ <0x00013000 0 &gic GIC_SPI 132 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 1 &gic GIC_SPI 133 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 2 &gic GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 3 &gic GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 4 &gic GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00013000 5 &gic GIC_SPI 137 IRQ_TYPE_LEVEL_HIGH>, -+ -+ /* PCIe Controller 2 */ -+ <0x00014000 0 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 1 &gic GIC_SPI 138 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 2 &gic GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 3 &gic GIC_SPI 141 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 4 &gic GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>, -+ <0x00014000 5 &gic GIC_SPI 143 IRQ_TYPE_LEVEL_HIGH>, -+ - /* USB 2.0 Controller */ - <0x00021000 0 &gic GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>, - diff --git a/target/linux/bcm53xx/patches-3.14/131-ARM-BCM5301X-add-restart-support.patch b/target/linux/bcm53xx/patches-3.14/131-ARM-BCM5301X-add-restart-support.patch deleted file mode 100644 index 792d4b93ea..0000000000 --- a/target/linux/bcm53xx/patches-3.14/131-ARM-BCM5301X-add-restart-support.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 28b11a8b1258214b3b5d58bb6e3bbcb0fc9fd4fe Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 31 Jul 2014 07:28:05 +0200 -Subject: [PATCH] ARM: BCM5301X: add restart support -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/mach-bcm/bcm_5301x.c | 31 +++++++++++++++++++++++++++++++ - 1 file changed, 31 insertions(+) - ---- a/arch/arm/mach-bcm/bcm_5301x.c -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -12,9 +12,26 @@ - #include <asm/siginfo.h> - #include <asm/signal.h> - -+#include <linux/bcma/bcma.h> - - static bool first_fault = true; - -+static struct bcma_bus *bcm5301x_get_bcma_bus(void) -+{ -+ struct device_node *np; -+ struct platform_device *pdev; -+ -+ np = of_find_compatible_node(NULL, NULL, "brcm,bus-axi"); -+ if (!np) -+ return NULL; -+ -+ pdev = of_find_device_by_node(np); -+ if (!pdev) -+ return NULL; -+ -+ return platform_get_drvdata(pdev); -+} -+ - static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, - struct pt_regs *regs) - { -@@ -49,6 +66,19 @@ static void __init bcm5301x_dt_init(void - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); - } - -+static void bcm5301x_restart(enum reboot_mode mode, const char *cmd) -+{ -+ struct bcma_bus *bus = bcm5301x_get_bcma_bus(); -+ -+ if (bus) -+ bcma_chipco_watchdog_timer_set(&bus->drv_cc, 1); -+ else -+ pr_warn("Unable to access bcma bus\n"); -+ -+ while (1) -+ ; -+} -+ - static const char __initconst *bcm5301x_dt_compat[] = { - "brcm,bcm4708", - NULL, -@@ -57,5 +87,6 @@ static const char __initconst *bcm5301x_ - DT_MACHINE_START(BCM5301X, "BCM5301X") - .init_early = bcm5301x_init_early, - .init_machine = bcm5301x_dt_init, -+ .restart = bcm5301x_restart, - .dt_compat = bcm5301x_dt_compat, - MACHINE_END diff --git a/target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch b/target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch deleted file mode 100644 index 8413e91ad8..0000000000 --- a/target/linux/bcm53xx/patches-3.14/150-pci-do-not-probe-too-early.patch +++ /dev/null @@ -1,29 +0,0 @@ -From cf72936c001056de1cfcb27dd9a232f5484ec59c Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Thu, 29 May 2014 20:54:15 +0200 -Subject: [PATCH 12/17] pci: do not probe too early - -Probing is done before the PCIe bridge is fully activated and the -address spaces does not get assigned to the PCIe devices. Without the -address space the driver can not register to this device. With this -patch the driver reregistration is done later. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/pci/probe.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/drivers/pci/probe.c -+++ b/drivers/pci/probe.c -@@ -1915,7 +1915,10 @@ struct pci_bus *pci_scan_root_bus(struct - if (!found) - pci_bus_update_busn_res_end(b, max); - -- pci_bus_add_devices(b); -+ /* this should be done in arch/arm/kernel/bios32.c, because the -+ resources for the PCI devices are initilized later and doing -+ it here will fail. */ -+ /* pci_bus_add_devices(b); */ - return b; - } - EXPORT_SYMBOL(pci_scan_root_bus); diff --git a/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch b/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch deleted file mode 100644 index d3e1a59edf..0000000000 --- a/target/linux/bcm53xx/patches-3.14/170-pcie2-bcma-add-new-PCIe2-driver-for-bcma.patch +++ /dev/null @@ -1,535 +0,0 @@ -From cf067bf8bb993d6cfdc42d750ae241c43f88403f Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Mon, 12 May 2014 11:55:20 +0200 -Subject: [PATCH 1/2] PCI: BCM5301X: add PCIe2 driver for BCM5301X SoCs - -This driver supports the PCIe controller found on the BCM4708 and -similar SoCs. The controller itself is automatically detected by bcma. - -This controller is found on SoCs usually used in SOHO routers to -connect the wifi cards to the SoC. All the of the BCM5301X SoCs I know -of have 2 or 3 of these controllers in the SoC. - -I had to use PCI domains otherwise the pci_create_root_bus() function -in drivers/pci/probe.c would fail for the second controller being -registered because pci_find_bus() would find the same PCIe bus again -and assume it is already registered, which ends up in a kernel panic in -pcibios_init_hw() in arch/arm/kernel/bios32.c - -The ARM PCI code assumes that every controller has an I/O space and -adds a dummy area if the driver does not specify one. This will work -for the first controller, but when we register the second one this will -result in an error. To prevent this problem we add an empty I/O space. - -Currently I have problems with probing the devices on the bus, because -pci_bus_add_devices() is called too early in pci_scan_root_bus() in -drivers/pci/probe.c, before pci_bus_assign_resources() was called in -pci_common_init_dev() in arch/arm/kernel/bios32.c. When the devices are -added too early they do not have any resources and adding fails. I have -to remove the call to pci_bus_add_devices() in pci_scan_root_bus() to -make registration work, calling pci_bus_add_devices() later again does -not fix this problem. - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - arch/arm/mach-bcm/Kconfig | 1 + - drivers/pci/host/Kconfig | 7 + - drivers/pci/host/Makefile | 1 + - drivers/pci/host/pci-host-bcm5301x.c | 428 +++++++++++++++++++++++++++++++++++ - 4 files changed, 437 insertions(+) - create mode 100644 drivers/pci/host/pci-host-bcm5301x.c - ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -45,6 +45,7 @@ config ARCH_BCM_5301X - select ARM_GLOBAL_TIMER - select CLKSRC_ARM_GLOBAL_TIMER_SCHED_CLOCK - select MIGHT_HAVE_PCI -+ select PCI_DOMAINS if PCI - help - Support for Broadcom BCM470X and BCM5301X SoCs with ARM CPU cores. - ---- a/drivers/pci/host/Kconfig -+++ b/drivers/pci/host/Kconfig -@@ -33,4 +33,11 @@ config PCI_RCAR_GEN2 - There are 3 internal PCI controllers available with a single - built-in EHCI/OHCI host controller present on each one. - -+config PCI_BCM5301X -+ bool "BCM5301X PCIe2 host controller" -+ depends on BCMA && OF && ARM && PCI_DOMAINS -+ help -+ Say Y here if you want to support the PCIe host controller found -+ on Broadcom BCM5301X and BCM470X (Northstar) SoCs. -+ - endmenu ---- a/drivers/pci/host/Makefile -+++ b/drivers/pci/host/Makefile -@@ -4,3 +4,4 @@ obj-$(CONFIG_PCI_IMX6) += pci-imx6.o - obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o - obj-$(CONFIG_PCI_TEGRA) += pci-tegra.o - obj-$(CONFIG_PCI_RCAR_GEN2) += pci-rcar-gen2.o -+obj-$(CONFIG_PCI_BCM5301X) += pci-host-bcm5301x.o ---- /dev/null -+++ b/drivers/pci/host/pci-host-bcm5301x.c -@@ -0,0 +1,460 @@ -+/* -+ * Northstar PCI-Express driver -+ * Only supports Root-Complex (RC) mode -+ * -+ * Notes: -+ * PCI Domains are being used to identify the PCIe port 1:1. -+ * -+ * Only MEM access is supported, PAX does not support IO. -+ * -+ * Copyright 2012-2014, Broadcom Corporation -+ * Copyright 2014, Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/delay.h> -+#include <linux/pci.h> -+#include <linux/io.h> -+#include <linux/ioport.h> -+#include <linux/bcma/bcma.h> -+#include <linux/bcma/bcma_driver_pcie2.h> -+ -+#define SOC_PCIE_HDR_OFF 0x400 /* 256 bytes per function */ -+ -+#define PCI_LINK_STATUS_CTRL_2_OFFSET 0xDC -+#define PCI_TARGET_LINK_SPEED_MASK 0xF -+#define PCI_TARGET_LINK_SPEED_GEN2 0x2 -+#define PCI_TARGET_LINK_SPEED_GEN1 0x1 -+ -+static int bcma_pcie2_map_irq(const struct pci_dev *pdev, u8 slot, u8 pin) -+{ -+ struct pci_sys_data *sys = pdev->sysdata; -+ struct bcma_device *bdev = sys->private_data; -+ -+ return bcma_core_irq(bdev, 5); -+} -+ -+static u32 bcma_pcie2_cfg_base(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where) -+{ -+ int slot = PCI_SLOT(devfn); -+ int fn = PCI_FUNC(devfn); -+ u32 addr_reg; -+ -+ if (busno == 0) { -+ if (slot >= 1) -+ return 0; -+ bcma_write32(bdev, BCMA_CORE_PCIE2_CONFIGINDADDR, -+ where & 0xffc); -+ return BCMA_CORE_PCIE2_CONFIGINDDATA; -+ } -+ if (fn > 1) -+ return 0; -+ addr_reg = (busno & 0xff) << 20 | (slot << 15) | (fn << 12) | -+ (where & 0xffc) | (1 & 0x3); -+ -+ bcma_write32(bdev, BCMA_CORE_PCIE2_CFG_ADDR, addr_reg); -+ return BCMA_CORE_PCIE2_CFG_DATA; -+} -+ -+static u32 bcma_pcie2_read_config(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, int size) -+{ -+ u32 base; -+ u32 data_reg; -+ u32 mask; -+ int shift; -+ -+ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); -+ -+ if (!base) -+ return ~0UL; -+ -+ data_reg = bcma_read32(bdev, base); -+ -+ if (size == 4) -+ return data_reg; -+ -+ mask = (1 << (size * 8)) - 1; -+ shift = (where % 4) * 8; -+ return (data_reg >> shift) & mask; -+} -+ -+static void bcma_pcie2_write_config(struct bcma_device *bdev, int busno, -+ unsigned int devfn, int where, int size, -+ u32 val) -+{ -+ u32 base; -+ u32 data_reg; -+ -+ base = bcma_pcie2_cfg_base(bdev, busno, devfn, where); -+ -+ if (!base) -+ return; -+ -+ if (size < 4) { -+ u32 mask = (1 << (size * 8)) - 1; -+ int shift = (where % 4) * 8; -+ -+ data_reg = bcma_read32(bdev, base); -+ data_reg &= ~(mask << shift); -+ data_reg |= (val & mask) << shift; -+ } else { -+ data_reg = val; -+ } -+ -+ bcma_write32(bdev, base, data_reg); -+} -+ -+static int bcma_pcie2_read_config_pci(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 *val) -+{ -+ struct pci_sys_data *sys = bus->sysdata; -+ struct bcma_device *bdev = sys->private_data; -+ -+ *val = bcma_pcie2_read_config(bdev, bus->number, devfn, where, size); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+static int bcma_pcie2_write_config_pci(struct pci_bus *bus, unsigned int devfn, -+ int where, int size, u32 val) -+{ -+ struct pci_sys_data *sys = bus->sysdata; -+ struct bcma_device *bdev = sys->private_data; -+ -+ bcma_pcie2_write_config(bdev, bus->number, devfn, where, size, val); -+ -+ return PCIBIOS_SUCCESSFUL; -+} -+ -+/* -+ * Methods for accessing configuration registers -+ */ -+static struct pci_ops bcma_pcie2_ops = { -+ .read = bcma_pcie2_read_config_pci, -+ .write = bcma_pcie2_write_config_pci, -+}; -+ -+/* NS: CLASS field is R/O, and set to wrong 0x200 value */ -+static void bcma_pcie2_fixup_class(struct pci_dev *dev) -+{ -+ dev->class = PCI_CLASS_BRIDGE_PCI << 8; -+} -+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8011, bcma_pcie2_fixup_class); -+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_BROADCOM, 0x8012, bcma_pcie2_fixup_class); -+ -+/* -+ * Check link status, return 0 if link is up in RC mode, -+ * otherwise return non-zero -+ */ -+static int bcma_pcie2_check_link(struct bcma_device *bdev, struct pci_sys_data *sys) -+{ -+ u32 tmp32; -+ u16 tmp16; -+ u16 pos; -+ u8 nlw; -+ /* -+ * Setup callback (bcma_pcie2_setup) is called in pcibios_init_hw before -+ * creating bus root, so we don't have it here yet. On the other hand -+ * we really want to use pci_bus_find_capability helper to check NLW. -+ * Let's fake simple pci_bus just to query for capabilities. -+ */ -+ struct pci_bus bus = { -+ .number = 0, -+ .ops = &bcma_pcie2_ops, -+ .sysdata = sys, -+ }; -+ -+ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_LINK_STATUS); -+ dev_dbg(&bdev->dev, "link status: 0x%08x\n", tmp32); -+ -+ tmp32 = bcma_read32(bdev, BCMA_CORE_PCIE2_STRAP_STATUS); -+ dev_dbg(&bdev->dev, "strap status: 0x%08x\n", tmp32); -+ -+ /* check link status to see if link is active */ -+ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP); -+ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, &tmp16); -+ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> PCI_EXP_LNKSTA_NLW_SHIFT; -+ -+ if (nlw == 0) { -+ /* try GEN 1 link speed */ -+ tmp32 = bcma_pcie2_read_config(bdev, 0, 0, -+ PCI_LINK_STATUS_CTRL_2_OFFSET, 4); -+ if ((tmp32 & PCI_TARGET_LINK_SPEED_MASK) == -+ PCI_TARGET_LINK_SPEED_GEN2) { -+ tmp32 &= ~PCI_TARGET_LINK_SPEED_MASK; -+ tmp32 |= PCI_TARGET_LINK_SPEED_GEN1; -+ bcma_pcie2_write_config(bdev, 0, 0, -+ PCI_LINK_STATUS_CTRL_2_OFFSET, 4, tmp32); -+ tmp32 = bcma_pcie2_read_config(bdev, 0, 0, -+ PCI_LINK_STATUS_CTRL_2_OFFSET, 4); -+ msleep(100); -+ -+ pos = pci_bus_find_capability(&bus, 0, PCI_CAP_ID_EXP); -+ pci_bus_read_config_word(&bus, 0, pos + PCI_EXP_LNKSTA, -+ &tmp16); -+ nlw = (tmp16 & PCI_EXP_LNKSTA_NLW) >> -+ PCI_EXP_LNKSTA_NLW_SHIFT; -+ } -+ } -+ -+ dev_info(&bdev->dev, "link: %s\n", nlw ? "UP" : "DOWN"); -+ return nlw ? 0 : -ENODEV; -+} -+ -+/* -+ * Initializte the PCIe controller -+ */ -+static void bcma_pcie2_hw_init(struct bcma_device *bdev) -+{ -+ u32 tmp32; -+ u16 tmp16; -+ -+ /* Change MPS and MRRS to 512 */ -+ tmp16 = bcma_pcie2_read_config(bdev, 0, 0, 0x4d4, 2); -+ tmp16 &= ~7; -+ tmp16 |= 2; -+ bcma_pcie2_write_config(bdev, 0, 0, 0x4d4, 2, tmp16); -+ -+ tmp32 = bcma_pcie2_read_config(bdev, 0, 0, 0xb4, 4); -+ tmp32 &= ~((7 << 12) | (7 << 5)); -+ tmp32 |= (2 << 12) | (2 << 5); -+ bcma_pcie2_write_config(bdev, 0, 0, 0xb4, 4, tmp32); -+ -+ /* -+ * Turn-on Root-Complex (RC) mode, from reset default of EP -+ * The mode is set by straps, can be overwritten via DMU -+ * register <cru_straps_control> bit 5, "1" means RC -+ */ -+ -+ /* Send a downstream reset */ -+ bcma_write32(bdev, BCMA_CORE_PCIE2_CLK_CONTROL, -+ PCIE2_CLKC_RST_OE | PCIE2_CLKC_RST); -+ usleep_range(250, 400); -+ bcma_write32(bdev, BCMA_CORE_PCIE2_CLK_CONTROL, PCIE2_CLKC_RST_OE); -+ msleep(250); -+ -+ /* TBD: take care of PM, check we're on */ -+} -+ -+/* -+ * Setup the address translation -+ * -+ * NOTE: All PCI-to-CPU address mapping are 1:1 for simplicity -+ */ -+static int bcma_pcie2_map_init(struct bcma_device *bdev, u32 addr) -+{ -+ /* 64MB alignment */ -+ if (!addr || (addr & (SZ_64M - 1))) -+ return -EINVAL; -+ -+ bcma_write32(bdev, BCMA_CORE_PCIE2_OMAP0_LOWER, addr); -+ bcma_write32(bdev, BCMA_CORE_PCIE2_OARR0, addr | 0x01); -+ -+ bcma_write32(bdev, BCMA_CORE_PCIE2_OMAP1_LOWER, addr + SZ_64M); -+ bcma_write32(bdev, BCMA_CORE_PCIE2_OARR1, (addr + SZ_64M) | 0x01); -+ -+ /* -+ * Inbound address translation setup -+ * Northstar only maps up to 128 MiB inbound, DRAM could be up to 1 GiB. -+ * -+ * For now allow access to entire DRAM, assuming it is less than 128MiB, -+ * otherwise DMA bouncing mechanism may be required. -+ * Also consider DMA mask to limit DMA physical address -+ */ -+ /* 64-bit LE regs, write low word, high is 0 at reset */ -+ bcma_write32(bdev, BCMA_CORE_PCIE2_FUNC0_IMAP1, PHYS_OFFSET | 0x1); -+ bcma_write32(bdev, BCMA_CORE_PCIE2_IARR1_LOWER, -+ PHYS_OFFSET | ((SZ_128M >> 20) & 0xff)); -+ return 0; -+} -+ -+/* -+ * Setup PCIE Host bridge -+ */ -+static int bcma_pcie2_bridge_init(struct bcma_device *bdev, u32 addr, u32 size) -+{ -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_PRIMARY_BUS, 1, 0); -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_SECONDARY_BUS, 1, 1); -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_SUBORDINATE_BUS, 1, 4); -+ -+ bcma_pcie2_read_config(bdev, 0, 0, PCI_PRIMARY_BUS, 1); -+ bcma_pcie2_read_config(bdev, 0, 0, PCI_SECONDARY_BUS, 1); -+ bcma_pcie2_read_config(bdev, 0, 0, PCI_SUBORDINATE_BUS, 1); -+ -+ /* MEM_BASE, MEM_LIM require 1MB alignment */ -+ if (((addr >> 16) & 0xf) || (((addr + size) >> 16) & 0xf)) -+ return -EINVAL; -+ -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_MEMORY_BASE, 2, addr >> 16); -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_MEMORY_LIMIT, 2, -+ (addr + size) >> 16); -+ -+ /* These registers are not supported on the NS */ -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_IO_BASE_UPPER16, 2, 0); -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_IO_LIMIT_UPPER16, 2, 0); -+ -+ /* Force class to that of a Bridge */ -+ bcma_pcie2_write_config(bdev, 0, 0, PCI_CLASS_DEVICE, 2, -+ PCI_CLASS_BRIDGE_PCI); -+ -+ bcma_pcie2_read_config(bdev, 0, 0, PCI_CLASS_DEVICE, 2); -+ bcma_pcie2_read_config(bdev, 0, 0, PCI_MEMORY_BASE, 2); -+ bcma_pcie2_read_config(bdev, 0, 0, PCI_MEMORY_LIMIT, 2); -+ return 0; -+} -+ -+static void bcma_pcie2_3rd_init(struct bcma_bus *bus) -+{ -+ /* PCIE PLL block register (base 0x8000) */ -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x57fe8000); -+ /* Check PCIE PLL lock status */ -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x00000088, 0x67c60000); -+} -+ -+/* To improve PCIE phy jitter */ -+static void bcma_pcie2_improve_phy_jitter(struct bcma_bus *bus, int phyaddr) -+{ -+ u32 val; -+ -+ /* Change blkaddr */ -+ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x1f << 18) | -+ (2 << 16) | (0x863 << 4); -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); -+ -+ /* Write 0x0190 to 0x13 regaddr */ -+ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x13 << 18) | -+ (2 << 16) | 0x0190; -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); -+ -+ /* Write 0x0191 to 0x19 regaddr */ -+ val = (1 << 30) | (1 << 28) | (phyaddr << 23) | (0x19 << 18) | -+ (2 << 16) | 0x0191; -+ bcma_chipco_b_mii_write(&bus->drv_cc_b, 0x0000009a, val); -+} -+ -+static int bcma_pcie2_setup(int nr, struct pci_sys_data *sys) -+{ -+ struct bcma_device *bdev = sys->private_data; -+ struct bcma_bus *bus = bdev->bus; -+ struct resource *res; -+ struct bcma_device *arm_core; -+ u32 cru_straps_ctrl; -+ int ret; -+ int phyaddr; -+ -+ if (bdev->core_unit == 2) { -+ arm_core = bcma_find_core(bus, BCMA_CORE_ARMCA9); -+ cru_straps_ctrl = bcma_read32(arm_core, 0x2a0); -+ -+ /* 3rd PCIE is not selected */ -+ if (cru_straps_ctrl & 0x10) -+ return -ENODEV; -+ -+ bcma_pcie2_3rd_init(bus); -+ phyaddr = 0xf; -+ } else { -+ phyaddr = bdev->core_unit; -+ } -+ bcma_pcie2_improve_phy_jitter(bus, phyaddr); -+ -+ /* create mem resource */ -+ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); -+ if (!res) -+ return -EINVAL; -+ -+ res->start = bdev->addr_s[0]; -+ res->end = bdev->addr_s[0] + SZ_128M -1; -+ res->name = "PCIe dummy IO space"; -+ res->flags = IORESOURCE_MEM; -+ -+ pci_add_resource(&sys->resources, res); -+ -+ /* This PCIe controller does not support IO Mem, so use a dummy one. */ -+ res = devm_kzalloc(&bdev->dev, sizeof(*res), GFP_KERNEL); -+ if (!res) -+ return -EINVAL; -+ -+ res->start = 0; -+ res->end = 0; -+ res->name = "PCIe dummy IO space"; -+ res->flags = IORESOURCE_IO; -+ -+ pci_add_resource(&sys->resources, res); -+ -+ bcma_pcie2_hw_init(bdev); -+ ret = bcma_pcie2_map_init(bdev, bdev->addr_s[0]); -+ if (ret) -+ return ret; -+ -+ /* -+ * Skip inactive ports - -+ * will need to change this for hot-plugging -+ */ -+ ret = bcma_pcie2_check_link(bdev, sys); -+ if (ret) -+ return ret; -+ -+ ret = bcma_pcie2_bridge_init(bdev, bdev->addr_s[0], SZ_128M); -+ if (ret) -+ return ret; -+ -+ return 1; -+} -+ -+static int bcma_pcie2_probe(struct bcma_device *bdev) -+{ -+ struct hw_pci hw = { -+ .nr_controllers = 1, -+ .domain = bdev->core_unit, -+ .private_data = (void **)&bdev, -+ .setup = bcma_pcie2_setup, -+ .map_irq = bcma_pcie2_map_irq, -+ .ops = &bcma_pcie2_ops, -+ }; -+ -+ dev_info(&bdev->dev, "initializing PCIe controller\n"); -+ -+ /* Announce this port to ARM/PCI common code */ -+ pci_common_init_dev(&bdev->dev, &hw); -+ -+ /* Setup virtual-wire interrupts */ -+ bcma_write32(bdev, BCMA_CORE_PCIE2_SYS_RC_INTX_EN, 0xf); -+ -+ /* Enable memory and bus master */ -+ bcma_write32(bdev, SOC_PCIE_HDR_OFF + 4, 0x6); -+ -+ return 0; -+} -+ -+static const struct bcma_device_id bcma_pcie2_table[] = { -+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_PCIEG2, BCMA_ANY_REV, BCMA_ANY_CLASS), -+ BCMA_CORETABLE_END -+}; -+MODULE_DEVICE_TABLE(bcma, bcma_pcie2_table); -+ -+static struct bcma_driver bcma_pcie2_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = bcma_pcie2_table, -+ .probe = bcma_pcie2_probe, -+}; -+ -+static int __init bcma_pcie2_init(void) -+{ -+ return bcma_driver_register(&bcma_pcie2_driver); -+} -+module_init(bcma_pcie2_init); -+ -+static void __exit bcma_pcie2_exit(void) -+{ -+ bcma_driver_unregister(&bcma_pcie2_driver); -+} -+module_exit(bcma_pcie2_exit); -+ -+MODULE_AUTHOR("Hauke Mehrtens"); -+MODULE_DESCRIPTION("BCM5301X PCIe host controller"); -+MODULE_LICENSE("GPLv2"); diff --git a/target/linux/bcm53xx/patches-3.14/180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch b/target/linux/bcm53xx/patches-3.14/180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch deleted file mode 100644 index f79e729995..0000000000 --- a/target/linux/bcm53xx/patches-3.14/180-spi-bcm53xx-driver-for-SPI-controller-on-Broadcom-bc.patch +++ /dev/null @@ -1,435 +0,0 @@ -From a59f3fa1dd4cb284171a53cb7a614ad947c544f6 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 13 Aug 2014 14:11:39 +0200 -Subject: [PATCH V2] spi: bcm53xx: driver for SPI controller on Broadcom bcma - SoC -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Broadcom 53xx ARM SoCs use bcma bus that contains various cores (AKA -devices). If board has a serial flash, it's connected over SPI and the -bcma bus includes a SPI controller. Example log from such a board: -bus0: Found chip with id 53010, rev 0x00 and package 0x02 -(...) -bus0: Core 18 found: SPI flash controller (manuf 0x4BF, id 0x50A, rev 0x01, class 0x0) - -This patch adds a bcma driver for SPI core, it registers SPI master -controller and "bcm53xxspiflash" SPI device. - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- -Since RFC: Add Signed-off-by - Update to compile on top of for-next -V2: Use wait timeout - Describe bcm53xxspi_calc_timeout a bit - Use devm_spi_register_master - -Thanks Mark for your comments! ---- - drivers/spi/Kconfig | 6 + - drivers/spi/Makefile | 1 + - drivers/spi/spi-bcm53xx.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++ - drivers/spi/spi-bcm53xx.h | 72 +++++++++++ - 4 files changed, 374 insertions(+) - create mode 100644 drivers/spi/spi-bcm53xx.c - create mode 100644 drivers/spi/spi-bcm53xx.h - ---- a/drivers/spi/Kconfig -+++ b/drivers/spi/Kconfig -@@ -112,6 +112,12 @@ config SPI_AU1550 - If you say yes to this option, support will be included for the - PSC SPI controller found on Au1550, Au1200 and Au1300 series. - -+config SPI_BCM53XX -+ tristate "Broadcom BCM53xx SPI controller" -+ depends on ARCH_BCM_5301X -+ help -+ Enable support for the SPI controller on Broadcom BCM53xx ARM SoCs. -+ - config SPI_BCM63XX - tristate "Broadcom BCM63xx SPI controller" - depends on BCM63XX ---- a/drivers/spi/Makefile -+++ b/drivers/spi/Makefile -@@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_ATMEL) += spi-atmel.o - obj-$(CONFIG_SPI_ATH79) += spi-ath79.o - obj-$(CONFIG_SPI_AU1550) += spi-au1550.o - obj-$(CONFIG_SPI_BCM2835) += spi-bcm2835.o -+obj-$(CONFIG_SPI_BCM53XX) += spi-bcm53xx.o - obj-$(CONFIG_SPI_BCM63XX) += spi-bcm63xx.o - obj-$(CONFIG_SPI_BCM63XX_HSSPI) += spi-bcm63xx-hsspi.o - obj-$(CONFIG_SPI_BFIN5XX) += spi-bfin5xx.o ---- /dev/null -+++ b/drivers/spi/spi-bcm53xx.c -@@ -0,0 +1,295 @@ -+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/delay.h> -+#include <linux/bcma/bcma.h> -+#include <linux/spi/spi.h> -+ -+#include "spi-bcm53xx.h" -+ -+#define BCM53XXSPI_MAX_SPI_BAUD 13500000 /* 216 MHz? */ -+ -+/* The longest observed required wait was 19 ms */ -+#define BCM53XXSPI_SPE_TIMEOUT_MS 80 -+ -+struct bcm53xxspi { -+ struct bcma_device *core; -+ struct spi_master *master; -+ -+ size_t read_offset; -+}; -+ -+static inline u32 bcm53xxspi_read(struct bcm53xxspi *b53spi, u16 offset) -+{ -+ return bcma_read32(b53spi->core, offset); -+} -+ -+static inline void bcm53xxspi_write(struct bcm53xxspi *b53spi, u16 offset, -+ u32 value) -+{ -+ bcma_write32(b53spi->core, offset, value); -+} -+ -+static inline unsigned int bcm53xxspi_calc_timeout(size_t len) -+{ -+ /* Do some magic calculation based on length and buad. Add 10% and 1. */ -+ return (len * 9000 / BCM53XXSPI_MAX_SPI_BAUD * 110 / 100) + 1; -+} -+ -+static int bcm53xxspi_wait(struct bcm53xxspi *b53spi, unsigned int timeout_ms) -+{ -+ unsigned long deadline; -+ u32 tmp; -+ -+ /* SPE bit has to be 0 before we read MSPI STATUS */ -+ deadline = jiffies + BCM53XXSPI_SPE_TIMEOUT_MS * HZ / 1000; -+ do { -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); -+ if (!(tmp & B53SPI_MSPI_SPCR2_SPE)) -+ break; -+ udelay(5); -+ } while (!time_after_eq(jiffies, deadline)); -+ -+ if (tmp & B53SPI_MSPI_SPCR2_SPE) -+ goto spi_timeout; -+ -+ /* Check status */ -+ deadline = jiffies + timeout_ms * HZ / 1000; -+ do { -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_MSPI_STATUS); -+ if (tmp & B53SPI_MSPI_MSPI_STATUS_SPIF) { -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0); -+ return 0; -+ } -+ -+ cpu_relax(); -+ udelay(100); -+ } while (!time_after_eq(jiffies, deadline)); -+ -+spi_timeout: -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_MSPI_STATUS, 0); -+ -+ pr_err("Timeout waiting for SPI to be ready!\n"); -+ -+ return -EBUSY; -+} -+ -+static void bcm53xxspi_buf_write(struct bcm53xxspi *b53spi, u8 *w_buf, -+ size_t len, bool cont) -+{ -+ u32 tmp; -+ int i; -+ -+ for (i = 0; i < len; i++) { -+ /* Transmit Register File MSB */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_TXRAM + 4 * (i * 2), -+ (unsigned int)w_buf[i]); -+ } -+ -+ for (i = 0; i < len; i++) { -+ tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | -+ B53SPI_CDRAM_PCS_DSCK; -+ if (!cont && i == len - 1) -+ tmp &= ~B53SPI_CDRAM_CONT; -+ tmp &= ~0x1; -+ /* Command Register File */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp); -+ } -+ -+ /* Set queue pointers */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, len - 1); -+ -+ if (cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); -+ -+ /* Start SPI transfer */ -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); -+ tmp |= B53SPI_MSPI_SPCR2_SPE; -+ if (cont) -+ tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD; -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp); -+ -+ /* Wait for SPI to finish */ -+ bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len)); -+ -+ if (!cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); -+ -+ b53spi->read_offset = len; -+} -+ -+static void bcm53xxspi_buf_read(struct bcm53xxspi *b53spi, u8 *r_buf, -+ size_t len, bool cont) -+{ -+ u32 tmp; -+ int i; -+ -+ for (i = 0; i < b53spi->read_offset + len; i++) { -+ tmp = B53SPI_CDRAM_CONT | B53SPI_CDRAM_PCS_DISABLE_ALL | -+ B53SPI_CDRAM_PCS_DSCK; -+ if (!cont && i == b53spi->read_offset + len - 1) -+ tmp &= ~B53SPI_CDRAM_CONT; -+ tmp &= ~0x1; -+ /* Command Register File */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_CDRAM + 4 * i, tmp); -+ } -+ -+ /* Set queue pointers */ -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_NEWQP, 0); -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_ENDQP, -+ b53spi->read_offset + len - 1); -+ -+ if (cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 1); -+ -+ /* Start SPI transfer */ -+ tmp = bcm53xxspi_read(b53spi, B53SPI_MSPI_SPCR2); -+ tmp |= B53SPI_MSPI_SPCR2_SPE; -+ if (cont) -+ tmp |= B53SPI_MSPI_SPCR2_CONT_AFTER_CMD; -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_SPCR2, tmp); -+ -+ /* Wait for SPI to finish */ -+ bcm53xxspi_wait(b53spi, bcm53xxspi_calc_timeout(len)); -+ -+ if (!cont) -+ bcm53xxspi_write(b53spi, B53SPI_MSPI_WRITE_LOCK, 0); -+ -+ for (i = 0; i < len; ++i) { -+ int offset = b53spi->read_offset + i; -+ -+ /* Data stored in the transmit register file LSB */ -+ r_buf[i] = (u8)bcm53xxspi_read(b53spi, B53SPI_MSPI_RXRAM + 4 * (1 + offset * 2)); -+ } -+ -+ b53spi->read_offset = 0; -+} -+ -+static int bcm53xxspi_transfer_one(struct spi_master *master, -+ struct spi_device *spi, -+ struct spi_transfer *t) -+{ -+ struct bcm53xxspi *b53spi = spi_master_get_devdata(master); -+ u8 *buf; -+ size_t left; -+ -+ if (t->tx_buf) { -+ buf = (u8 *)t->tx_buf; -+ left = t->len; -+ while (left) { -+ size_t to_write = min_t(size_t, 16, left); -+ bool cont = left - to_write > 0; -+ -+ bcm53xxspi_buf_write(b53spi, buf, to_write, cont); -+ left -= to_write; -+ buf += to_write; -+ } -+ } -+ -+ if (t->rx_buf) { -+ buf = (u8 *)t->rx_buf; -+ left = t->len; -+ while (left) { -+ size_t to_read = min_t(size_t, 16 - b53spi->read_offset, -+ left); -+ bool cont = left - to_read > 0; -+ -+ bcm53xxspi_buf_read(b53spi, buf, to_read, cont); -+ left -= to_read; -+ buf += to_read; -+ } -+ } -+ -+ return 0; -+} -+ -+/************************************************** -+ * BCMA -+ **************************************************/ -+ -+struct spi_board_info bcm53xx_info = { -+ .modalias = "bcm53xxspiflash", -+}; -+ -+static const struct bcma_device_id bcm53xxspi_bcma_tbl[] = { -+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_QSPI, BCMA_ANY_REV, BCMA_ANY_CLASS), -+ BCMA_CORETABLE_END -+}; -+MODULE_DEVICE_TABLE(bcma, bcm53xxspi_bcma_tbl); -+ -+static int bcm53xxspi_bcma_probe(struct bcma_device *core) -+{ -+ struct bcm53xxspi *b53spi; -+ struct spi_master *master; -+ int err; -+ -+ if (core->bus->drv_cc.core->id.rev != 42) { -+ pr_err("SPI on SoC with unsupported ChipCommon rev\n"); -+ return -ENOTSUPP; -+ } -+ -+ master = spi_alloc_master(&core->dev, sizeof(*b53spi)); -+ if (!master) -+ return -ENOMEM; -+ -+ b53spi = spi_master_get_devdata(master); -+ b53spi->master = master; -+ b53spi->core = core; -+ -+ master->transfer_one = bcm53xxspi_transfer_one; -+ -+ bcma_set_drvdata(core, b53spi); -+ -+ err = devm_spi_register_master(&core->dev, master); -+ if (err) { -+ spi_master_put(master); -+ bcma_set_drvdata(core, NULL); -+ goto out; -+ } -+ -+ /* Broadcom SoCs (at least with the CC rev 42) use SPI for flash only */ -+ spi_new_device(master, &bcm53xx_info); -+ -+out: -+ return err; -+} -+ -+static void bcm53xxspi_bcma_remove(struct bcma_device *core) -+{ -+ struct bcm53xxspi *b53spi = bcma_get_drvdata(core); -+ -+ spi_unregister_master(b53spi->master); -+} -+ -+static struct bcma_driver bcm53xxspi_bcma_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = bcm53xxspi_bcma_tbl, -+ .probe = bcm53xxspi_bcma_probe, -+ .remove = bcm53xxspi_bcma_remove, -+}; -+ -+/************************************************** -+ * Init & exit -+ **************************************************/ -+ -+static int __init bcm53xxspi_module_init(void) -+{ -+ int err = 0; -+ -+ err = bcma_driver_register(&bcm53xxspi_bcma_driver); -+ if (err) -+ pr_err("Failed to register bcma driver: %d\n", err); -+ -+ return err; -+} -+ -+static void __exit bcm53xxspi_module_exit(void) -+{ -+ bcma_driver_unregister(&bcm53xxspi_bcma_driver); -+} -+ -+module_init(bcm53xxspi_module_init); -+module_exit(bcm53xxspi_module_exit); ---- /dev/null -+++ b/drivers/spi/spi-bcm53xx.h -@@ -0,0 +1,72 @@ -+#ifndef SPI_BCM53XX_H -+#define SPI_BCM53XX_H -+ -+#define B53SPI_BSPI_REVISION_ID 0x000 -+#define B53SPI_BSPI_SCRATCH 0x004 -+#define B53SPI_BSPI_MAST_N_BOOT_CTRL 0x008 -+#define B53SPI_BSPI_BUSY_STATUS 0x00c -+#define B53SPI_BSPI_INTR_STATUS 0x010 -+#define B53SPI_BSPI_B0_STATUS 0x014 -+#define B53SPI_BSPI_B0_CTRL 0x018 -+#define B53SPI_BSPI_B1_STATUS 0x01c -+#define B53SPI_BSPI_B1_CTRL 0x020 -+#define B53SPI_BSPI_STRAP_OVERRIDE_CTRL 0x024 -+#define B53SPI_BSPI_FLEX_MODE_ENABLE 0x028 -+#define B53SPI_BSPI_BITS_PER_CYCLE 0x02c -+#define B53SPI_BSPI_BITS_PER_PHASE 0x030 -+#define B53SPI_BSPI_CMD_AND_MODE_BYTE 0x034 -+#define B53SPI_BSPI_BSPI_FLASH_UPPER_ADDR_BYTE 0x038 -+#define B53SPI_BSPI_BSPI_XOR_VALUE 0x03c -+#define B53SPI_BSPI_BSPI_XOR_ENABLE 0x040 -+#define B53SPI_BSPI_BSPI_PIO_MODE_ENABLE 0x044 -+#define B53SPI_BSPI_BSPI_PIO_IODIR 0x048 -+#define B53SPI_BSPI_BSPI_PIO_DATA 0x04c -+ -+/* RAF */ -+#define B53SPI_RAF_START_ADDR 0x100 -+#define B53SPI_RAF_NUM_WORDS 0x104 -+#define B53SPI_RAF_CTRL 0x108 -+#define B53SPI_RAF_FULLNESS 0x10c -+#define B53SPI_RAF_WATERMARK 0x110 -+#define B53SPI_RAF_STATUS 0x114 -+#define B53SPI_RAF_READ_DATA 0x118 -+#define B53SPI_RAF_WORD_CNT 0x11c -+#define B53SPI_RAF_CURR_ADDR 0x120 -+ -+/* MSPI */ -+#define B53SPI_MSPI_SPCR0_LSB 0x200 -+#define B53SPI_MSPI_SPCR0_MSB 0x204 -+#define B53SPI_MSPI_SPCR1_LSB 0x208 -+#define B53SPI_MSPI_SPCR1_MSB 0x20c -+#define B53SPI_MSPI_NEWQP 0x210 -+#define B53SPI_MSPI_ENDQP 0x214 -+#define B53SPI_MSPI_SPCR2 0x218 -+#define B53SPI_MSPI_SPCR2_SPE 0x00000040 -+#define B53SPI_MSPI_SPCR2_CONT_AFTER_CMD 0x00000080 -+#define B53SPI_MSPI_MSPI_STATUS 0x220 -+#define B53SPI_MSPI_MSPI_STATUS_SPIF 0x00000001 -+#define B53SPI_MSPI_CPTQP 0x224 -+#define B53SPI_MSPI_TXRAM 0x240 /* 32 registers, up to 0x2b8 */ -+#define B53SPI_MSPI_RXRAM 0x2c0 /* 32 registers, up to 0x33c */ -+#define B53SPI_MSPI_CDRAM 0x340 /* 16 registers, up to 0x37c */ -+#define B53SPI_CDRAM_PCS_PCS0 0x00000001 -+#define B53SPI_CDRAM_PCS_PCS1 0x00000002 -+#define B53SPI_CDRAM_PCS_PCS2 0x00000004 -+#define B53SPI_CDRAM_PCS_PCS3 0x00000008 -+#define B53SPI_CDRAM_PCS_DISABLE_ALL 0x0000000f -+#define B53SPI_CDRAM_PCS_DSCK 0x00000010 -+#define B53SPI_CDRAM_BITSE 0x00000040 -+#define B53SPI_CDRAM_CONT 0x00000080 -+#define B53SPI_MSPI_WRITE_LOCK 0x380 -+#define B53SPI_MSPI_DISABLE_FLUSH_GEN 0x384 -+ -+/* Interrupt */ -+#define B53SPI_INTR_RAF_LR_FULLNESS_REACHED 0x3a0 -+#define B53SPI_INTR_RAF_LR_TRUNCATED 0x3a4 -+#define B53SPI_INTR_RAF_LR_IMPATIENT 0x3a8 -+#define B53SPI_INTR_RAF_LR_SESSION_DONE 0x3ac -+#define B53SPI_INTR_RAF_LR_OVERREAD 0x3b0 -+#define B53SPI_INTR_MSPI_DONE 0x3b4 -+#define B53SPI_INTR_MSPI_HALT_SET_TRANSACTION_DONE 0x3b8 -+ -+#endif /* SPI_BCM53XX_H */ diff --git a/target/linux/bcm53xx/patches-3.14/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch b/target/linux/bcm53xx/patches-3.14/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch deleted file mode 100644 index 88770964bb..0000000000 --- a/target/linux/bcm53xx/patches-3.14/300-ARM-BCM5301X-Disable-MMU-and-Dcache-for-decompression.patch +++ /dev/null @@ -1,195 +0,0 @@ -From 26023cdfacaf116545b1087b9d1fe50dc6fbda10 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 24 Sep 2014 22:14:07 +0200 -Subject: [PATCH] ARM: BCM5301X: Disable MMU and Dcache for decompression -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Without this fix kernel was randomly hanging in ~25% of tries during -early init. Hangs used to happen at random places in the start_kernel. - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/compressed/Makefile | 5 + - arch/arm/boot/compressed/head-bcm_5301x-mpcore.S | 37 +++++++ - arch/arm/boot/compressed/mpcore_cache.S | 118 +++++++++++++++++++++++ - 3 files changed, 160 insertions(+) - create mode 100644 arch/arm/boot/compressed/head-bcm_5301x-mpcore.S - create mode 100644 arch/arm/boot/compressed/mpcore_cache.S - ---- a/arch/arm/boot/compressed/Makefile -+++ b/arch/arm/boot/compressed/Makefile -@@ -44,6 +44,11 @@ ifeq ($(CONFIG_ARCH_ACORN),y) - OBJS += ll_char_wr.o font.o - endif - -+ifeq ($(CONFIG_ARCH_BCM_5301X),y) -+OBJS += head-bcm_5301x-mpcore.o -+OBJS += mpcore_cache.o -+endif -+ - ifeq ($(CONFIG_ARCH_SA1100),y) - OBJS += head-sa1100.o - endif ---- /dev/null -+++ b/arch/arm/boot/compressed/head-bcm_5301x-mpcore.S -@@ -0,0 +1,37 @@ -+/* -+ * -+ * Platform specific tweaks. This is merged into head.S by the linker. -+ * -+ */ -+ -+#include <linux/linkage.h> -+#include <asm/assembler.h> -+#include <asm/cp15.h> -+ -+ .section ".start", "ax" -+ -+/* -+ * This code section is spliced into the head code by the linker -+ */ -+ -+__plat_uncompress_start: -+ -+ @ Preserve r8/r7 i.e. kernel entry values -+ mov r12, r8 -+ -+ @ Clear MMU enable and Dcache enable bits -+ mrc p15, 0, r0, c1, c0, 0 @ Read SCTLR -+ bic r0, #CR_C|CR_M -+ mcr p15, 0, r0, c1, c0, 0 @ Write SCTLR -+ nop -+ -+ @ Call the cache invalidation routine -+ bl v7_all_dcache_invalidate -+ nop -+ mov r0,#0 -+ ldr r3, =0x19022000 @ L2 cache controller, control reg -+ str r0, [r3, #0x100] @ Disable L2 cache -+ nop -+ -+ @ Restore -+ mov r8, r12 ---- /dev/null -+++ b/arch/arm/boot/compressed/mpcore_cache.S -@@ -0,0 +1,118 @@ -+/***************************************************************************** -+* Copyright 2003 - 2008 Broadcom Corporation. All rights reserved. -+* -+* Unless you and Broadcom execute a separate written software license -+* agreement governing use of this software, this software is licensed to you -+* under the terms of the GNU General Public License version 2, available at -+* http://www.broadcom.com/licenses/GPLv2.php (the "GPL"). -+* -+* Notwithstanding the above, under no circumstances may you combine this -+* software in any way with any other Broadcom software provided under a -+* license other than the GPL, without Broadcom's express prior written -+* consent. -+*****************************************************************************/ -+ -+#include <linux/linkage.h> -+#include <linux/init.h> -+ -+ __INIT -+ -+/* -+ * v7_l1_cache_invalidate -+ * -+ * Invalidate contents of L1 cache without flushing its contents -+ * into outer cache and memory. This is needed when the contents -+ * of the cache are unpredictable after power-up. -+ * -+ * corrupts r0-r6 -+ */ -+ -+ENTRY(v7_l1_cache_invalidate) -+ mov r0, #0 -+ mcr p15, 2, r0, c0, c0, 0 @ set cache level to 1 -+ mrc p15, 1, r0, c0, c0, 0 @ read CLIDR -+ -+ ldr r1, =0x7fff -+ and r2, r1, r0, lsr #13 @ get max # of index size -+ -+ ldr r1, =0x3ff -+ and r3, r1, r0, lsr #3 @ NumWays - 1 -+ add r2, r2, #1 @ NumSets -+ -+ and r0, r0, #0x7 -+ add r0, r0, #4 @ SetShift -+ -+ clz r1, r3 @ WayShift -+ add r4, r3, #1 @ NumWays -+1: sub r2, r2, #1 @ NumSets-- -+ mov r3, r4 @ Temp = NumWays -+2: subs r3, r3, #1 @ Temp-- -+ mov r5, r3, lsl r1 -+ mov r6, r2, lsl r0 -+ orr r5, r5, r6 @ Reg = (Temp<<WayShift)|(NumSets<<SetShift) -+ mcr p15, 0, r5, c7, c6, 2 @ Invalidate line -+ bgt 2b -+ cmp r2, #0 -+ bgt 1b -+ dsb -+ mov r0,#0 -+ mcr p15,0,r0,c7,c5,0 /* Invalidate icache */ -+ isb -+ mov pc, lr -+ENDPROC(v7_l1_cache_invalidate) -+ -+/* -+ * v7_all_dcache_invalidate -+ * -+ * Invalidate without flushing the contents of all cache levels -+ * accesible by the current processor core. -+ * This is useful when the contents of cache memory are undetermined -+ * at power-up. -+ * Corrupted registers: r0-r7, r9-r11 -+ * -+ * Based on cache-v7.S: v7_flush_dcache_all() -+ */ -+ -+ENTRY(v7_all_dcache_invalidate) -+ mrc p15, 1, r0, c0, c0, 1 @ read clidr -+ ands r3, r0, #0x7000000 @ extract loc from clidr -+ mov r3, r3, lsr #23 @ left align loc bit field -+ beq finished @ if loc is 0, then no need to clean -+ mov r10, #0 @ start clean at cache level 0 -+loop1: -+ add r2, r10, r10, lsr #1 @ work out 3x current cache level -+ mov r1, r0, lsr r2 @ extract cache type bits from clidr -+ and r1, r1, #7 @ mask of bits for current cache only -+ cmp r1, #2 @ see what cache we have at this level -+ blt skip @ skip if no cache, or just i-cache -+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr -+ isb @ isb to sych the new cssr&csidr -+ mrc p15, 1, r1, c0, c0, 0 @ read the new csidr -+ and r2, r1, #7 @ extract the length of the cache lines -+ add r2, r2, #4 @ add 4 (line length offset) -+ ldr r4, =0x3ff -+ ands r4, r4, r1, lsr #3 @ find maximum number on the way size -+ clz r5, r4 @ find bit pos of way size increment -+ ldr r7, =0x7fff -+ ands r7, r7, r1, lsr #13 @ extract max number of the index size -+loop2: -+ mov r9, r4 @ create working copy of max way size -+loop3: -+ orr r11, r10, r9, lsl r5 @ factor way and cache number into r11 -+ orr r11, r11, r7, lsl r2 @ factor index number into r11 -+ mcr p15, 0, r11, c7, c6, 2 @ Invalidate line -+ subs r9, r9, #1 @ decrement the way -+ bge loop3 -+ subs r7, r7, #1 @ decrement the index -+ bge loop2 -+skip: -+ add r10, r10, #2 @ increment cache number -+ cmp r3, r10 -+ bgt loop1 -+finished: -+ mov r10, #0 @ swith back to cache level 0 -+ mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr -+ dsb -+ isb -+ mov pc, lr -+ENDPROC(v7_all_dcache_invalidate) diff --git a/target/linux/bcm53xx/patches-3.14/302-ARM-BCM5301X-select-GPIOLIB-as-optional.patch b/target/linux/bcm53xx/patches-3.14/302-ARM-BCM5301X-select-GPIOLIB-as-optional.patch deleted file mode 100644 index 887650e4f7..0000000000 --- a/target/linux/bcm53xx/patches-3.14/302-ARM-BCM5301X-select-GPIOLIB-as-optional.patch +++ /dev/null @@ -1,29 +0,0 @@ -From e7b1065712e769eb4de7b9d4aa222a4531c2b8fd Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Sat, 20 Sep 2014 18:21:19 +0200 -Subject: [PATCH V2] ARM: BCM5301X: select GPIOLIB as optional -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -All routers (or 99% of them) based on BCM5301X use GPIOs to control LEDs -and buttons. - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- -V2: Don't select GPIOLIB. We may still think about making it default at - some point, but we dont' really require it to boot successfully. ---- - arch/arm/mach-bcm/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/arm/mach-bcm/Kconfig -+++ b/arch/arm/mach-bcm/Kconfig -@@ -35,6 +35,7 @@ config ARCH_BCM_MOBILE - config ARCH_BCM_5301X - bool "Broadcom BCM470X / BCM5301X ARM SoC" if ARCH_MULTI_V7 - depends on MMU -+ select ARCH_WANT_OPTIONAL_GPIOLIB - select ARM_GIC - select CACHE_L2X0 - select HAVE_ARM_SCU if SMP diff --git a/target/linux/bcm53xx/patches-3.14/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch b/target/linux/bcm53xx/patches-3.14/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch deleted file mode 100644 index 51ea2bee24..0000000000 --- a/target/linux/bcm53xx/patches-3.14/303-ARM-BCM5310X-Enable-earlyprintk-on-tested-devices.patch +++ /dev/null @@ -1,82 +0,0 @@ -From eb1075cc48d3c315c7403822c33da9588ab76492 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 14 Jan 2015 08:33:25 +0100 -Subject: [PATCH] ARM: BCM5310X: Enable earlyprintk on tested devices -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 2 +- - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 2 +- - arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 2 +- - arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 2 +- - 4 files changed, 4 insertions(+), 4 deletions(-) - -diff --git a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -index 5fc0fae..fcb17c6 100644 ---- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -@@ -16,7 +16,7 @@ - model = "Buffalo WZR-1750DHP (BCM4708)"; - - chosen { -- bootargs = "console=ttyS0,115200"; -+ bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { -diff --git a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -index 4ed7de1..05e80b1 100644 ---- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -16,7 +16,7 @@ - model = "Netgear R6250 V1 (BCM4708)"; - - chosen { -- bootargs = "console=ttyS0,115200"; -+ bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { -diff --git a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -index fb76378..5dc50e1 100644 ---- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -@@ -16,7 +16,7 @@ - model = "Asus RT-N18U (BCM47081)"; - - chosen { -- bootargs = "console=ttyS0,115200"; -+ bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { -diff --git a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -index bbb414f..20903a5 100644 ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -@@ -16,7 +16,7 @@ - model = "Buffalo WZR-600DHP2 (BCM47081)"; - - chosen { -- bootargs = "console=ttyS0,115200"; -+ bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -@@ -16,7 +16,7 @@ - model = "Buffalo WZR-900DHP (BCM47081)"; - - chosen { -- bootargs = "console=ttyS0,115200"; -+ bootargs = "console=ttyS0,115200 earlyprintk"; - }; - - memory { --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch b/target/linux/bcm53xx/patches-3.14/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch deleted file mode 100644 index 183b53ff9c..0000000000 --- a/target/linux/bcm53xx/patches-3.14/306-ARM-BCM5301X-Specify-RAM-on-devices-by-including-HIG.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 36b2fbb3badf0e32b371e1f7579a95d4fe25c0e1 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 14 Jan 2015 09:13:58 +0100 -Subject: [PATCH] ARM: BCM5301X: Specify RAM on devices by including HIGHMEM -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 3 ++- - arch/arm/boot/dts/bcm4708-netgear-r6250.dts | 3 ++- - arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 3 ++- - arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 3 ++- - arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 3 ++- - 5 files changed, 10 insertions(+), 5 deletions(-) - ---- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -@@ -20,7 +20,8 @@ - }; - - memory { -- reg = <0x00000000 0x08000000>; -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x18000000>; - }; - - spi { ---- a/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6250.dts -@@ -20,7 +20,8 @@ - }; - - memory { -- reg = <0x00000000 0x08000000>; -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; - }; - - chipcommonA { ---- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -@@ -20,7 +20,8 @@ - }; - - memory { -- reg = <0x00000000 0x08000000>; -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; - }; - - leds { ---- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -@@ -20,7 +20,8 @@ - }; - - memory { -- reg = <0x00000000 0x08000000>; -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; - }; - - leds { ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -@@ -20,7 +20,8 @@ - }; - - memory { -- reg = <0x00000000 0x08000000>; -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; - }; - - spi { ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -@@ -20,7 +20,8 @@ - }; - - memory { -- reg = <0x00000000 0x08000000>; -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; - }; - - gpio-keys { diff --git a/target/linux/bcm53xx/patches-3.14/322-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch b/target/linux/bcm53xx/patches-3.14/322-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch deleted file mode 100644 index 54dd0d165b..0000000000 --- a/target/linux/bcm53xx/patches-3.14/322-ARM-BCM5301X-Add-DT-for-Asus-RT-AC87U.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 0cc8daf2488539f734150e64c799e3a4dd014cd8 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Mon, 19 Jan 2015 11:34:45 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Asus RT-AC87U -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/Makefile | 3 +- - arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts | 44 +++++++++++++++++++++++++++++ - 2 files changed, 46 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts - ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts -@@ -0,0 +1,44 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Asus RT-AC87U -+ * -+ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "asus,rt-ac87u", "brcm,bcm4709", "brcm,bcm4708"; -+ model = "Asus RT-AC87U (BCM4709)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200 earlyprintk"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; -+ }; -+ -+ gpio-keys { -+ compatible = "gpio-keys"; -+ #address-cells = <1>; -+ #size-cells = <0>; -+ -+ wps { -+ label = "WPS"; -+ linux,code = <KEY_WPS_BUTTON>; -+ gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>; -+ }; -+ -+ restart { -+ label = "Reset"; -+ linux,code = <KEY_RESTART>; -+ gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>; -+ }; -+ }; -+}; ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -57,7 +57,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm4708-netgear-r6300-v2.dtb \ - bcm47081-asus-rt-n18u.dtb \ - bcm47081-buffalo-wzr-600dhp2.dtb \ -- bcm47081-buffalo-wzr-900dhp.dtb -+ bcm47081-buffalo-wzr-900dhp.dtb \ -+ bcm4709-asus-rt-ac87u.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb diff --git a/target/linux/bcm53xx/patches-3.14/323-ARM-BCM5301X-Add-DT-for-Netgear-R8000.patch b/target/linux/bcm53xx/patches-3.14/323-ARM-BCM5301X-Add-DT-for-Netgear-R8000.patch deleted file mode 100644 index 72f83af2c6..0000000000 --- a/target/linux/bcm53xx/patches-3.14/323-ARM-BCM5301X-Add-DT-for-Netgear-R8000.patch +++ /dev/null @@ -1,87 +0,0 @@ -From f3389cf7bc90d5702adcd4c100b49baf7a813bb9 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Wed, 28 Jan 2015 22:39:39 +0100 -Subject: [PATCH] ARM: BCM5301X: Add DT for Netgear R8000 -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/Makefile | 3 ++- - arch/arm/boot/dts/bcm4709-netgear-r8000.dts | 26 ++++++++++++++++++++++++++ - 2 files changed, 28 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/bcm4709-netgear-r8000.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile -index 25445c2..e93e9e4 100644 ---- a/arch/arm/boot/dts/Makefile -+++ b/arch/arm/boot/dts/Makefile -@@ -58,7 +58,8 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \ - bcm47081-asus-rt-n18u.dtb \ - bcm47081-buffalo-wzr-600dhp2.dtb \ - bcm47081-buffalo-wzr-900dhp.dtb \ -- bcm4709-asus-rt-ac87u.dtb -+ bcm4709-asus-rt-ac87u.dtb \ -+ bcm4709-netgear-r8000.dtb - dtb-$(CONFIG_ARCH_BERLIN) += \ - berlin2-sony-nsz-gs7.dtb \ - berlin2cd-google-chromecast.dtb -diff --git a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -new file mode 100644 -index 0000000..2d7e388 ---- /dev/null -+++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -@@ -0,0 +1,26 @@ -+/* -+ * Broadcom BCM470X / BCM5301X ARM platform code. -+ * DTS for Netgear R8000 -+ * -+ * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ */ -+ -+/dts-v1/; -+ -+#include "bcm4708.dtsi" -+ -+/ { -+ compatible = "netgear,r8000", "brcm,bcm4709", "brcm,bcm4708"; -+ model = "Netgear R8000 (BCM4709)"; -+ -+ chosen { -+ bootargs = "console=ttyS0,115200 earlyprintk"; -+ }; -+ -+ memory { -+ reg = <0x00000000 0x08000000 -+ 0x88000000 0x08000000>; -+ }; -+}; ---- a/arch/arm/mach-bcm/bcm_5301x.c -+++ b/arch/arm/mach-bcm/bcm_5301x.c -@@ -35,15 +35,16 @@ static struct bcma_bus *bcm5301x_get_bcm - static int bcm5301x_abort_handler(unsigned long addr, unsigned int fsr, - struct pt_regs *regs) - { -- if (fsr == 0x1c06 && first_fault) { -+ if ((fsr == 0x1406 || fsr == 0x1c06) && first_fault) { - first_fault = false; - - /* -- * These faults with code 0x1c06 happens for no good reason, -- * possibly left over from the CFE boot loader. -+ * These faults with codes 0x1406 (BCM4709) or 0x1c06 happens -+ * for no good reason, possibly left over from the CFE boot -+ * loader. - */ - pr_warn("External imprecise Data abort at addr=%#lx, fsr=%#x ignored.\n", -- addr, fsr); -+ addr, fsr); - - /* Returning non-zero causes fault display and panic */ - return 0; --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch b/target/linux/bcm53xx/patches-3.14/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch deleted file mode 100644 index fe7e0a1607..0000000000 --- a/target/linux/bcm53xx/patches-3.14/351-ARM-BCM5301X-Enable-ChipCommon-UART-serial-console.patch +++ /dev/null @@ -1,149 +0,0 @@ -From 6c223da976a9225ba9fae8d6f891a8fffaae6092 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Fri, 5 Dec 2014 17:38:40 +0100 -Subject: [PATCH] ARM: BCM5301X: Enable ChipCommon UART (serial console) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts | 10 ++++++++++ - arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts | 10 ++++++++++ - arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts | 10 ++++++++++ - arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts | 10 ++++++++++ - 4 files changed, 40 insertions(+) - ---- a/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -+++ b/arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts -@@ -91,6 +91,16 @@ - }; - }; - -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+ - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; ---- a/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -+++ b/arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts -@@ -24,6 +24,16 @@ - 0x88000000 0x08000000>; - }; - -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+ - leds { - compatible = "gpio-leds"; - ---- a/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -+++ b/arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts -@@ -24,6 +24,16 @@ - 0x88000000 0x08000000>; - }; - -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+ - leds { - compatible = "gpio-leds"; - ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts -@@ -24,6 +24,16 @@ - 0x88000000 0x08000000>; - }; - -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+ - spi { - compatible = "spi-gpio"; - num-chipselects = <1>; ---- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts -+++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts -@@ -23,6 +23,16 @@ - reg = <0x00000000 0x08000000>; - }; - -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+ - axi@18000000 { - nand@28000 { - reg = <0x00028000 0x1000>; ---- a/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -+++ b/arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts -@@ -24,6 +24,16 @@ - 0x88000000 0x08000000>; - }; - -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ }; -+ }; -+ - gpio-keys { - compatible = "gpio-keys"; - #address-cells = <1>; ---- a/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -+++ b/arch/arm/boot/dts/bcm4709-netgear-r8000.dts -@@ -23,4 +23,16 @@ - reg = <0x00000000 0x08000000 - 0x88000000 0x08000000>; - }; -+ -+ chipcommonA { -+ uart0: serial@0300 { -+ status = "okay"; -+ clock-frequency = <125000000>; -+ }; -+ -+ uart1: serial@0400 { -+ status = "okay"; -+ clock-frequency = <125000000>; -+ }; -+ }; - }; diff --git a/target/linux/bcm53xx/patches-3.14/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch b/target/linux/bcm53xx/patches-3.14/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch deleted file mode 100644 index d58d99c8f3..0000000000 --- a/target/linux/bcm53xx/patches-3.14/400-mtd-bcm47xxpart-scan-whole-flash-on-ARCH_BCM_5301X.patch +++ /dev/null @@ -1,36 +0,0 @@ -From d658c21d6697293a928434fd6ac19264b5a8948d Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Fri, 30 Jan 2015 08:25:54 +0100 -Subject: [PATCH] mtd: bcm47xxpart: scan whole flash on ARCH_BCM_5301X -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - drivers/mtd/bcm47xxpart.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c -index ee3e010..f13c824 100644 ---- a/drivers/mtd/bcm47xxpart.c -+++ b/drivers/mtd/bcm47xxpart.c -@@ -120,9 +120,15 @@ static int bcm47xxpart_parse(struct mtd_info *master, - /* Parse block by block looking for magics */ - for (offset = 0; offset <= master->size - blocksize; - offset += blocksize) { -+#ifndef CONFIG_ARCH_BCM_5301X -+ /* -+ * ARM routers may have partitions in higher memory. E.g. -+ * Netgear R8000 has board_data at 0x2600000. -+ */ - /* Nothing more in higher memory */ - if (offset >= 0x2000000) - break; -+#endif - - if (curr_part >= BCM47XXPART_MAX_PARTS) { - pr_warn("Reached maximum number of partitions, scanning stopped!\n"); --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch b/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch deleted file mode 100644 index 41ef3b300e..0000000000 --- a/target/linux/bcm53xx/patches-3.14/404-mtd-bcm53xxspiflash-new-driver-for-SPI-flahes-on-Bro.patch +++ /dev/null @@ -1,19 +0,0 @@ ---- a/drivers/mtd/spi-nor/Kconfig -+++ b/drivers/mtd/spi-nor/Kconfig -@@ -28,4 +28,10 @@ config SPI_FSL_QUADSPI - This enables support for the Quad SPI controller in master mode. - We only connect the NOR to this controller now. - -+config MTD_SPI_BCM53XXSPIFLASH -+ tristate "SPI-NOR flashes connected to the Broadcom ARM SoC" -+ depends on MTD_SPI_NOR -+ help -+ SPI driver for flashes used on Broadcom ARM SoCs. -+ - endif # MTD_SPI_NOR ---- a/drivers/mtd/spi-nor/Makefile -+++ b/drivers/mtd/spi-nor/Makefile -@@ -1,2 +1,3 @@ - obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o - obj-$(CONFIG_SPI_FSL_QUADSPI) += fsl-quadspi.o -+obj-$(CONFIG_MTD_SPI_BCM53XXSPIFLASH) += bcm53xxspiflash.o diff --git a/target/linux/bcm53xx/patches-3.14/420-mtd-bcm5301x_nand.patch b/target/linux/bcm53xx/patches-3.14/420-mtd-bcm5301x_nand.patch deleted file mode 100644 index 19c8116140..0000000000 --- a/target/linux/bcm53xx/patches-3.14/420-mtd-bcm5301x_nand.patch +++ /dev/null @@ -1,1608 +0,0 @@ ---- a/drivers/mtd/nand/Kconfig -+++ b/drivers/mtd/nand/Kconfig -@@ -510,4 +510,10 @@ config MTD_NAND_XWAY - Enables support for NAND Flash chips on Lantiq XWAY SoCs. NAND is attached - to the External Bus Unit (EBU). - -+config MTD_NAND_BCM -+ tristate "Support for NAND on some Broadcom SoC" -+ help -+ This driver is currently used for the NAND flash controller on the -+ Broadcom BCM5301X (NorthStar) SoCs. -+ - endif # MTD_NAND ---- a/drivers/mtd/nand/Makefile -+++ b/drivers/mtd/nand/Makefile -@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_JZ4740) += jz4740 - obj-$(CONFIG_MTD_NAND_GPMI_NAND) += gpmi-nand/ - obj-$(CONFIG_MTD_NAND_XWAY) += xway_nand.o - obj-$(CONFIG_MTD_NAND_BCM47XXNFLASH) += bcm47xxnflash/ -+obj-$(CONFIG_MTD_NAND_BCM) += bcm_nand.o - - nand-objs := nand_base.o nand_bbt.o ---- /dev/null -+++ b/drivers/mtd/nand/bcm_nand.c -@@ -0,0 +1,1583 @@ -+/* -+ * Nortstar NAND controller driver -+ * -+ * (c) Broadcom, Inc. 2012 All Rights Reserved. -+ * Copyright 2014 Hauke Mehrtens <hauke@hauke-m.de> -+ * -+ * Licensed under the GNU/GPL. See COPYING for details. -+ * -+ * This module interfaces the NAND controller and hardware ECC capabilities -+ * tp the generic NAND chip support in the NAND library. -+ * -+ * Notes: -+ * This driver depends on generic NAND driver, but works at the -+ * page level for operations. -+ * -+ * When a page is written, the ECC calculated also protects the OOB -+ * bytes not taken by ECC, and so the OOB must be combined with any -+ * OOB data that preceded the page-write operation in order for the -+ * ECC to be calculated correctly. -+ * Also, when the page is erased, but OOB data is not, HW ECC will -+ * indicate an error, because it checks OOB too, which calls for some -+ * help from the software in this driver. -+ * -+ * TBD: -+ * Block locking/unlocking support, OTP support -+ */ -+ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/io.h> -+#include <linux/ioport.h> -+#include <linux/interrupt.h> -+#include <linux/delay.h> -+#include <linux/err.h> -+#include <linux/slab.h> -+#include <linux/bcma/bcma.h> -+#include <linux/of_irq.h> -+ -+#include <linux/mtd/mtd.h> -+#include <linux/mtd/nand.h> -+#include <linux/mtd/partitions.h> -+ -+#define NANDC_MAX_CHIPS 2 /* Only 2 CSn supported in NorthStar */ -+ -+/* -+ * Driver private control structure -+ */ -+struct bcmnand_ctrl { -+ struct mtd_info mtd; -+ struct nand_chip nand; -+ struct bcma_device *core; -+ -+ struct completion op_completion; -+ -+ struct nand_ecclayout ecclayout; -+ int cmd_ret; /* saved error code */ -+ unsigned char oob_index; -+ unsigned char id_byte_index; -+ unsigned char chip_num; -+ unsigned char last_cmd; -+ unsigned char ecc_level; -+ unsigned char sector_size_shift; -+ unsigned char sec_per_page_shift; -+}; -+ -+ -+/* -+ * IRQ numbers - offset from first irq in nandc_irq resource -+ */ -+#define NANDC_IRQ_RD_MISS 0 -+#define NANDC_IRQ_ERASE_COMPLETE 1 -+#define NANDC_IRQ_COPYBACK_COMPLETE 2 -+#define NANDC_IRQ_PROGRAM_COMPLETE 3 -+#define NANDC_IRQ_CONTROLLER_RDY 4 -+#define NANDC_IRQ_RDBSY_RDY 5 -+#define NANDC_IRQ_ECC_UNCORRECTABLE 6 -+#define NANDC_IRQ_ECC_CORRECTABLE 7 -+#define NANDC_IRQ_NUM 8 -+ -+struct bcmnand_reg_field { -+ unsigned int reg; -+ unsigned int pos; -+ unsigned int width; -+}; -+ -+/* -+ * REGISTERS -+ * -+ * Individual bit-fields aof registers are specificed here -+ * for clarity, and the rest of the code will access each field -+ * as if it was its own register. -+ * -+ * Following registers are off <reg_base>: -+ */ -+#define REG_BIT_FIELD(r, p, w) ((struct bcmnand_reg_field){(r), (p), (w)}) -+ -+#define NANDC_8KB_PAGE_SUPPORT REG_BIT_FIELD(0x0, 31, 1) -+#define NANDC_REV_MAJOR REG_BIT_FIELD(0x0, 8, 8) -+#define NANDC_REV_MINOR REG_BIT_FIELD(0x0, 0, 8) -+ -+#define NANDC_CMD_START_OPCODE REG_BIT_FIELD(0x4, 24, 5) -+ -+#define NANDC_CMD_CS_SEL REG_BIT_FIELD(0x8, 16, 3) -+#define NANDC_CMD_EXT_ADDR REG_BIT_FIELD(0x8, 0, 16) -+ -+#define NANDC_CMD_ADDRESS REG_BIT_FIELD(0xc, 0, 32) -+#define NANDC_CMD_END_ADDRESS REG_BIT_FIELD(0x10, 0, 32) -+ -+#define NANDC_INT_STATUS REG_BIT_FIELD(0x14, 0, 32) -+#define NANDC_INT_STAT_CTLR_RDY REG_BIT_FIELD(0x14, 31, 1) -+#define NANDC_INT_STAT_FLASH_RDY REG_BIT_FIELD(0x14, 30, 1) -+#define NANDC_INT_STAT_CACHE_VALID REG_BIT_FIELD(0x14, 29, 1) -+#define NANDC_INT_STAT_SPARE_VALID REG_BIT_FIELD(0x14, 28, 1) -+#define NANDC_INT_STAT_ERASED REG_BIT_FIELD(0x14, 27, 1) -+#define NANDC_INT_STAT_PLANE_RDY REG_BIT_FIELD(0x14, 26, 1) -+#define NANDC_INT_STAT_FLASH_STATUS REG_BIT_FIELD(0x14, 0, 8) -+ -+#define NANDC_CS_LOCK REG_BIT_FIELD(0x18, 31, 1) -+#define NANDC_CS_AUTO_CONFIG REG_BIT_FIELD(0x18, 30, 1) -+#define NANDC_CS_NAND_WP REG_BIT_FIELD(0x18, 29, 1) -+#define NANDC_CS_BLK0_WP REG_BIT_FIELD(0x18, 28, 1) -+#define NANDC_CS_SW_USING_CS(n) REG_BIT_FIELD(0x18, 8+(n), 1) -+#define NANDC_CS_MAP_SEL_CS(n) REG_BIT_FIELD(0x18, 0+(n), 1) -+ -+#define NANDC_XOR_ADDR_BLK0_ONLY REG_BIT_FIELD(0x1c, 31, 1) -+#define NANDC_XOR_ADDR_CS(n) REG_BIT_FIELD(0x1c, 0+(n), 1) -+ -+#define NANDC_LL_OP_RET_IDLE REG_BIT_FIELD(0x20, 31, 1) -+#define NANDC_LL_OP_CLE REG_BIT_FIELD(0x20, 19, 1) -+#define NANDC_LL_OP_ALE REG_BIT_FIELD(0x20, 18, 1) -+#define NANDC_LL_OP_WE REG_BIT_FIELD(0x20, 17, 1) -+#define NANDC_LL_OP_RE REG_BIT_FIELD(0x20, 16, 1) -+#define NANDC_LL_OP_DATA REG_BIT_FIELD(0x20, 0, 16) -+ -+#define NANDC_MPLANE_ADDR_EXT REG_BIT_FIELD(0x24, 0, 16) -+#define NANDC_MPLANE_ADDR REG_BIT_FIELD(0x28, 0, 32) -+ -+#define NANDC_ACC_CTRL_CS(n) REG_BIT_FIELD(0x50+((n)<<4), 0, 32) -+#define NANDC_ACC_CTRL_RD_ECC(n) REG_BIT_FIELD(0x50+((n)<<4), 31, 1) -+#define NANDC_ACC_CTRL_WR_ECC(n) REG_BIT_FIELD(0x50+((n)<<4), 30, 1) -+#define NANDC_ACC_CTRL_CE_CARE(n) REG_BIT_FIELD(0x50+((n)<<4), 29, 1) -+#define NANDC_ACC_CTRL_PGM_RDIN(n) REG_BIT_FIELD(0x50+((n)<<4), 28, 1) -+#define NANDC_ACC_CTRL_ERA_ECC_ERR(n) REG_BIT_FIELD(0x50+((n)<<4), 27, 1) -+#define NANDC_ACC_CTRL_PGM_PARTIAL(n) REG_BIT_FIELD(0x50+((n)<<4), 26, 1) -+#define NANDC_ACC_CTRL_WR_PREEMPT(n) REG_BIT_FIELD(0x50+((n)<<4), 25, 1) -+#define NANDC_ACC_CTRL_PG_HIT(n) REG_BIT_FIELD(0x50+((n)<<4), 24, 1) -+#define NANDC_ACC_CTRL_PREFETCH(n) REG_BIT_FIELD(0x50+((n)<<4), 23, 1) -+#define NANDC_ACC_CTRL_CACHE_MODE(n) REG_BIT_FIELD(0x50+((n)<<4), 22, 1) -+#define NANDC_ACC_CTRL_CACHE_LASTPG(n) REG_BIT_FIELD(0x50+((n)<<4), 21, 1) -+#define NANDC_ACC_CTRL_ECC_LEVEL(n) REG_BIT_FIELD(0x50+((n)<<4), 16, 5) -+#define NANDC_ACC_CTRL_SECTOR_1K(n) REG_BIT_FIELD(0x50+((n)<<4), 7, 1) -+#define NANDC_ACC_CTRL_SPARE_SIZE(n) REG_BIT_FIELD(0x50+((n)<<4), 0, 7) -+ -+#define NANDC_CONFIG_CS(n) REG_BIT_FIELD(0x54+((n)<<4), 0, 32) -+#define NANDC_CONFIG_LOCK(n) REG_BIT_FIELD(0x54+((n)<<4), 31, 1) -+#define NANDC_CONFIG_BLK_SIZE(n) REG_BIT_FIELD(0x54+((n)<<4), 28, 3) -+#define NANDC_CONFIG_CHIP_SIZE(n) REG_BIT_FIELD(0x54+((n)<<4), 24, 4) -+#define NANDC_CONFIG_CHIP_WIDTH(n) REG_BIT_FIELD(0x54+((n)<<4), 23, 1) -+#define NANDC_CONFIG_PAGE_SIZE(n) REG_BIT_FIELD(0x54+((n)<<4), 20, 2) -+#define NANDC_CONFIG_FUL_ADDR_BYTES(n) REG_BIT_FIELD(0x54+((n)<<4), 16, 3) -+#define NANDC_CONFIG_COL_ADDR_BYTES(n) REG_BIT_FIELD(0x54+((n)<<4), 12, 3) -+#define NANDC_CONFIG_BLK_ADDR_BYTES(n) REG_BIT_FIELD(0x54+((n)<<4), 8, 3) -+ -+#define NANDC_TIMING_1_CS(n) REG_BIT_FIELD(0x58+((n)<<4), 0, 32) -+#define NANDC_TIMING_2_CS(n) REG_BIT_FIELD(0x5c+((n)<<4), 0, 32) -+ /* Individual bits for Timing registers - TBD */ -+ -+#define NANDC_CORR_STAT_THRESH_CS(n) REG_BIT_FIELD(0xc0, 6*(n), 6) -+ -+#define NANDC_BLK_WP_END_ADDR REG_BIT_FIELD(0xc8, 0, 32) -+ -+#define NANDC_MPLANE_ERASE_CYC2_OPCODE REG_BIT_FIELD(0xcc, 24, 8) -+#define NANDC_MPLANE_READ_STAT_OPCODE REG_BIT_FIELD(0xcc, 16, 8) -+#define NANDC_MPLANE_PROG_ODD_OPCODE REG_BIT_FIELD(0xcc, 8, 8) -+#define NANDC_MPLANE_PROG_TRL_OPCODE REG_BIT_FIELD(0xcc, 0, 8) -+ -+#define NANDC_MPLANE_PGCACHE_TRL_OPCODE REG_BIT_FIELD(0xd0, 24, 8) -+#define NANDC_MPLANE_READ_STAT2_OPCODE REG_BIT_FIELD(0xd0, 16, 8) -+#define NANDC_MPLANE_READ_EVEN_OPCODE REG_BIT_FIELD(0xd0, 8, 8) -+#define NANDC_MPLANE_READ_ODD__OPCODE REG_BIT_FIELD(0xd0, 0, 8) -+ -+#define NANDC_MPLANE_CTRL_ERASE_CYC2_EN REG_BIT_FIELD(0xd4, 31, 1) -+#define NANDC_MPLANE_CTRL_RD_ADDR_SIZE REG_BIT_FIELD(0xd4, 30, 1) -+#define NANDC_MPLANE_CTRL_RD_CYC_ADDR REG_BIT_FIELD(0xd4, 29, 1) -+#define NANDC_MPLANE_CTRL_RD_COL_ADDR REG_BIT_FIELD(0xd4, 28, 1) -+ -+#define NANDC_UNCORR_ERR_COUNT REG_BIT_FIELD(0xfc, 0, 32) -+ -+#define NANDC_CORR_ERR_COUNT REG_BIT_FIELD(0x100, 0, 32) -+ -+#define NANDC_READ_CORR_BIT_COUNT REG_BIT_FIELD(0x104, 0, 32) -+ -+#define NANDC_BLOCK_LOCK_STATUS REG_BIT_FIELD(0x108, 0, 8) -+ -+#define NANDC_ECC_CORR_ADDR_CS REG_BIT_FIELD(0x10c, 16, 3) -+#define NANDC_ECC_CORR_ADDR_EXT REG_BIT_FIELD(0x10c, 0, 16) -+ -+#define NANDC_ECC_CORR_ADDR REG_BIT_FIELD(0x110, 0, 32) -+ -+#define NANDC_ECC_UNC_ADDR_CS REG_BIT_FIELD(0x114, 16, 3) -+#define NANDC_ECC_UNC_ADDR_EXT REG_BIT_FIELD(0x114, 0, 16) -+ -+#define NANDC_ECC_UNC_ADDR REG_BIT_FIELD(0x118, 0, 32) -+ -+#define NANDC_READ_ADDR_CS REG_BIT_FIELD(0x11c, 16, 3) -+#define NANDC_READ_ADDR_EXT REG_BIT_FIELD(0x11c, 0, 16) -+#define NANDC_READ_ADDR REG_BIT_FIELD(0x120, 0, 32) -+ -+#define NANDC_PROG_ADDR_CS REG_BIT_FIELD(0x124, 16, 3) -+#define NANDC_PROG_ADDR_EXT REG_BIT_FIELD(0x124, 0, 16) -+#define NANDC_PROG_ADDR REG_BIT_FIELD(0x128, 0, 32) -+ -+#define NANDC_CPYBK_ADDR_CS REG_BIT_FIELD(0x12c, 16, 3) -+#define NANDC_CPYBK_ADDR_EXT REG_BIT_FIELD(0x12c, 0, 16) -+#define NANDC_CPYBK_ADDR REG_BIT_FIELD(0x130, 0, 32) -+ -+#define NANDC_ERASE_ADDR_CS REG_BIT_FIELD(0x134, 16, 3) -+#define NANDC_ERASE_ADDR_EXT REG_BIT_FIELD(0x134, 0, 16) -+#define NANDC_ERASE_ADDR REG_BIT_FIELD(0x138, 0, 32) -+ -+#define NANDC_INV_READ_ADDR_CS REG_BIT_FIELD(0x13c, 16, 3) -+#define NANDC_INV_READ_ADDR_EXT REG_BIT_FIELD(0x13c, 0, 16) -+#define NANDC_INV_READ_ADDR REG_BIT_FIELD(0x140, 0, 32) -+ -+#define NANDC_INIT_STAT REG_BIT_FIELD(0x144, 0, 32) -+#define NANDC_INIT_ONFI_DONE REG_BIT_FIELD(0x144, 31, 1) -+#define NANDC_INIT_DEVID_DONE REG_BIT_FIELD(0x144, 30, 1) -+#define NANDC_INIT_SUCCESS REG_BIT_FIELD(0x144, 29, 1) -+#define NANDC_INIT_FAIL REG_BIT_FIELD(0x144, 28, 1) -+#define NANDC_INIT_BLANK REG_BIT_FIELD(0x144, 27, 1) -+#define NANDC_INIT_TIMEOUT REG_BIT_FIELD(0x144, 26, 1) -+#define NANDC_INIT_UNC_ERROR REG_BIT_FIELD(0x144, 25, 1) -+#define NANDC_INIT_CORR_ERROR REG_BIT_FIELD(0x144, 24, 1) -+#define NANDC_INIT_PARAM_RDY REG_BIT_FIELD(0x144, 23, 1) -+#define NANDC_INIT_AUTH_FAIL REG_BIT_FIELD(0x144, 22, 1) -+ -+#define NANDC_ONFI_STAT REG_BIT_FIELD(0x148, 0, 32) -+#define NANDC_ONFI_DEBUG REG_BIT_FIELD(0x148, 28, 4) -+#define NANDC_ONFI_PRESENT REG_BIT_FIELD(0x148, 27, 1) -+#define NANDC_ONFI_BADID_PG2 REG_BIT_FIELD(0x148, 5, 1) -+#define NANDC_ONFI_BADID_PG1 REG_BIT_FIELD(0x148, 4, 1) -+#define NANDC_ONFI_BADID_PG0 REG_BIT_FIELD(0x148, 3, 1) -+#define NANDC_ONFI_BADCRC_PG2 REG_BIT_FIELD(0x148, 2, 1) -+#define NANDC_ONFI_BADCRC_PG1 REG_BIT_FIELD(0x148, 1, 1) -+#define NANDC_ONFI_BADCRC_PG0 REG_BIT_FIELD(0x148, 0, 1) -+ -+#define NANDC_ONFI_DEBUG_DATA REG_BIT_FIELD(0x14c, 0, 32) -+ -+#define NANDC_SEMAPHORE REG_BIT_FIELD(0x150, 0, 8) -+ -+#define NANDC_DEVID_BYTE(b) REG_BIT_FIELD(0x194+((b)&0x4), \ -+ 24-(((b)&3)<<3), 8) -+ -+#define NANDC_LL_RDDATA REG_BIT_FIELD(0x19c, 0, 16) -+ -+#define NANDC_INT_N_REG(n) REG_BIT_FIELD(0xf00|((n)<<2), 0, 1) -+#define NANDC_INT_DIREC_READ_MISS REG_BIT_FIELD(0xf00, 0, 1) -+#define NANDC_INT_ERASE_DONE REG_BIT_FIELD(0xf04, 0, 1) -+#define NANDC_INT_CPYBK_DONE REG_BIT_FIELD(0xf08, 0, 1) -+#define NANDC_INT_PROGRAM_DONE REG_BIT_FIELD(0xf0c, 0, 1) -+#define NANDC_INT_CONTROLLER_RDY REG_BIT_FIELD(0xf10, 0, 1) -+#define NANDC_INT_RDBSY_RDY REG_BIT_FIELD(0xf14, 0, 1) -+#define NANDC_INT_ECC_UNCORRECTABLE REG_BIT_FIELD(0xf18, 0, 1) -+#define NANDC_INT_ECC_CORRECTABLE REG_BIT_FIELD(0xf1c, 0, 1) -+ -+/* -+ * Following registers are treated as contigous IO memory, offset is from -+ * <reg_base>, and the data is in big-endian byte order -+ */ -+#define NANDC_SPARE_AREA_READ_OFF 0x200 -+#define NANDC_SPARE_AREA_WRITE_OFF 0x280 -+#define NANDC_CACHE_OFF 0x400 -+#define NANDC_CACHE_SIZE (128*4) -+ -+struct bcmnand_areg_field { -+ unsigned int reg; -+ unsigned int pos; -+ unsigned int width; -+}; -+ -+/* -+ * Following are IDM (a.k.a. Slave Wrapper) registers are off <idm_base>: -+ */ -+#define IDMREG_BIT_FIELD(r, p, w) ((struct bcmnand_areg_field){(r), (p), (w)}) -+ -+#define NANDC_IDM_AXI_BIG_ENDIAN IDMREG_BIT_FIELD(0x408, 28, 1) -+#define NANDC_IDM_APB_LITTLE_ENDIAN IDMREG_BIT_FIELD(0x408, 24, 1) -+#define NANDC_IDM_TM IDMREG_BIT_FIELD(0x408, 16, 5) -+#define NANDC_IDM_IRQ_CORRECABLE_EN IDMREG_BIT_FIELD(0x408, 9, 1) -+#define NANDC_IDM_IRQ_UNCORRECABLE_EN IDMREG_BIT_FIELD(0x408, 8, 1) -+#define NANDC_IDM_IRQ_RDYBSY_RDY_EN IDMREG_BIT_FIELD(0x408, 7, 1) -+#define NANDC_IDM_IRQ_CONTROLLER_RDY_EN IDMREG_BIT_FIELD(0x408, 6, 1) -+#define NANDC_IDM_IRQ_PRPOGRAM_COMP_EN IDMREG_BIT_FIELD(0x408, 5, 1) -+#define NANDC_IDM_IRQ_COPYBK_COMP_EN IDMREG_BIT_FIELD(0x408, 4, 1) -+#define NANDC_IDM_IRQ_ERASE_COMP_EN IDMREG_BIT_FIELD(0x408, 3, 1) -+#define NANDC_IDM_IRQ_READ_MISS_EN IDMREG_BIT_FIELD(0x408, 2, 1) -+#define NANDC_IDM_IRQ_N_EN(n) IDMREG_BIT_FIELD(0x408, 2+(n), 1) -+ -+#define NANDC_IDM_CLOCK_EN IDMREG_BIT_FIELD(0x408, 0, 1) -+ -+#define NANDC_IDM_IO_ECC_CORR IDMREG_BIT_FIELD(0x500, 3, 1) -+#define NANDC_IDM_IO_ECC_UNCORR IDMREG_BIT_FIELD(0x500, 2, 1) -+#define NANDC_IDM_IO_RDYBSY IDMREG_BIT_FIELD(0x500, 1, 1) -+#define NANDC_IDM_IO_CTRL_RDY IDMREG_BIT_FIELD(0x500, 0, 1) -+ -+#define NANDC_IDM_RESET IDMREG_BIT_FIELD(0x800, 0, 1) -+ /* Remaining IDM registers do not seem to be useful, skipped */ -+ -+/* -+ * NAND Controller has its own command opcodes -+ * different from opcodes sent to the actual flash chip -+ */ -+#define NANDC_CMD_OPCODE_NULL 0 -+#define NANDC_CMD_OPCODE_PAGE_READ 1 -+#define NANDC_CMD_OPCODE_SPARE_READ 2 -+#define NANDC_CMD_OPCODE_STATUS_READ 3 -+#define NANDC_CMD_OPCODE_PAGE_PROG 4 -+#define NANDC_CMD_OPCODE_SPARE_PROG 5 -+#define NANDC_CMD_OPCODE_DEVID_READ 7 -+#define NANDC_CMD_OPCODE_BLOCK_ERASE 8 -+#define NANDC_CMD_OPCODE_FLASH_RESET 9 -+ -+/* -+ * NAND Controller hardware ECC data size -+ * -+ * The following table contains the number of bytes needed for -+ * each of the ECC levels, per "sector", which is either 512 or 1024 bytes. -+ * The actual layout is as follows: -+ * The entire spare area is equally divided into as many sections as there -+ * are sectors per page, and the ECC data is located at the end of each -+ * of these sections. -+ * For example, given a 2K per page and 64 bytes spare device, configured for -+ * sector size 1k and ECC level of 4, the spare area will be divided into 2 -+ * sections 32 bytes each, and the last 14 bytes of 32 in each section will -+ * be filled with ECC data. -+ * Note: the name of the algorythm and the number of error bits it can correct -+ * is of no consequence to this driver, therefore omitted. -+ */ -+struct bcmnand_ecc_size_s { -+ unsigned char sector_size_shift; -+ unsigned char ecc_level; -+ unsigned char ecc_bytes_per_sec; -+ unsigned char reserved; -+}; -+ -+static const struct bcmnand_ecc_size_s bcmnand_ecc_sizes[] = { -+ { 9, 0, 0 }, -+ { 10, 0, 0 }, -+ { 9, 1, 2 }, -+ { 10, 1, 4 }, -+ { 9, 2, 4 }, -+ { 10, 2, 7 }, -+ { 9, 3, 6 }, -+ { 10, 3, 11 }, -+ { 9, 4, 7 }, -+ { 10, 4, 14 }, -+ { 9, 5, 9 }, -+ { 10, 5, 18 }, -+ { 9, 6, 11 }, -+ { 10, 6, 21 }, -+ { 9, 7, 13 }, -+ { 10, 7, 25 }, -+ { 9, 8, 14 }, -+ { 10, 8, 28 }, -+ -+ { 9, 9, 16 }, -+ { 9, 10, 18 }, -+ { 9, 11, 20 }, -+ { 9, 12, 21 }, -+ -+ { 10, 9, 32 }, -+ { 10, 10, 35 }, -+ { 10, 11, 39 }, -+ { 10, 12, 42 }, -+}; -+ -+/* -+ * Populate the various fields that depend on how -+ * the hardware ECC data is located in the spare area -+ * -+ * For this controiller, it is easier to fill-in these -+ * structures at run time. -+ * -+ * The bad-block marker is assumed to occupy one byte -+ * at chip->badblockpos, which must be in the first -+ * sector of the spare area, namely it is either -+ * at offset 0 or 5. -+ * Some chips use both for manufacturer's bad block -+ * markers, but we ingore that issue here, and assume only -+ * one byte is used as bad-block marker always. -+ */ -+static int bcmnand_hw_ecc_layout(struct bcmnand_ctrl *ctrl) -+{ -+ struct nand_ecclayout *layout; -+ struct device *dev = &ctrl->core->dev; -+ unsigned int i, j, k; -+ unsigned int ecc_per_sec, oob_per_sec; -+ unsigned int bbm_pos = ctrl->nand.badblockpos; -+ -+ /* Caclculate spare area per sector size */ -+ oob_per_sec = ctrl->mtd.oobsize >> ctrl->sec_per_page_shift; -+ -+ /* Try to calculate the amount of ECC bytes per sector with a formula */ -+ if (ctrl->sector_size_shift == 9) -+ ecc_per_sec = ((ctrl->ecc_level * 14) + 7) >> 3; -+ else if (ctrl->sector_size_shift == 10) -+ ecc_per_sec = ((ctrl->ecc_level * 14) + 3) >> 2; -+ else -+ ecc_per_sec = oob_per_sec + 1; /* cause an error if not in table */ -+ -+ /* Now find out the answer according to the table */ -+ for (i = 0; i < ARRAY_SIZE(bcmnand_ecc_sizes); i++) { -+ if (bcmnand_ecc_sizes[i].ecc_level == ctrl->ecc_level && -+ bcmnand_ecc_sizes[i].sector_size_shift == -+ ctrl->sector_size_shift) { -+ break; -+ } -+ } -+ -+ /* Table match overrides formula */ -+ if (bcmnand_ecc_sizes[i].ecc_level == ctrl->ecc_level && -+ bcmnand_ecc_sizes[i].sector_size_shift == ctrl->sector_size_shift) -+ ecc_per_sec = bcmnand_ecc_sizes[i].ecc_bytes_per_sec; -+ -+ /* Return an error if calculated ECC leaves no room for OOB */ -+ if ((ctrl->sec_per_page_shift != 0 && ecc_per_sec >= oob_per_sec) || -+ (ctrl->sec_per_page_shift == 0 && ecc_per_sec >= (oob_per_sec - 1))) { -+ dev_err(dev, "ECC level %d too high, leaves no room for OOB data\n", -+ ctrl->ecc_level); -+ return -EINVAL; -+ } -+ -+ /* Fill in the needed fields */ -+ ctrl->nand.ecc.size = ctrl->mtd.writesize >> ctrl->sec_per_page_shift; -+ ctrl->nand.ecc.bytes = ecc_per_sec; -+ ctrl->nand.ecc.steps = 1 << ctrl->sec_per_page_shift; -+ ctrl->nand.ecc.total = ecc_per_sec << ctrl->sec_per_page_shift; -+ ctrl->nand.ecc.strength = ctrl->ecc_level; -+ -+ /* Build an ecc layout data structure */ -+ layout = &ctrl->ecclayout; -+ memset(layout, 0, sizeof(*layout)); -+ -+ /* Total number of bytes used by HW ECC */ -+ layout->eccbytes = ecc_per_sec << ctrl->sec_per_page_shift; -+ -+ /* Location for each of the HW ECC bytes */ -+ for (i = j = 0, k = 1; -+ i < ARRAY_SIZE(layout->eccpos) && i < layout->eccbytes; -+ i++, j++) { -+ /* switch sector # */ -+ if (j == ecc_per_sec) { -+ j = 0; -+ k++; -+ } -+ /* save position of each HW-generated ECC byte */ -+ layout->eccpos[i] = (oob_per_sec * k) - ecc_per_sec + j; -+ -+ /* Check that HW ECC does not overlap bad-block marker */ -+ if (bbm_pos == layout->eccpos[i]) { -+ dev_err(dev, "ECC level %d too high, HW ECC collides with bad-block marker position\n", -+ ctrl->ecc_level); -+ return -EINVAL; -+ } -+ } -+ -+ /* Location of all user-available OOB byte-ranges */ -+ for (i = 0; i < ARRAY_SIZE(layout->oobfree); i++) { -+ struct nand_oobfree *oobfree = &layout->oobfree[i]; -+ -+ if (i >= (1 << ctrl->sec_per_page_shift)) -+ break; -+ oobfree->offset = oob_per_sec * i; -+ oobfree->length = oob_per_sec - ecc_per_sec; -+ -+ /* Bad-block marker must be in the first sector spare area */ -+ if (WARN_ON(bbm_pos >= (oobfree->offset + oobfree->length))) -+ return -EINVAL; -+ -+ if (i != 0) -+ continue; -+ -+ /* Remove bad-block marker from available byte range */ -+ if (bbm_pos == oobfree->offset) { -+ oobfree->offset += 1; -+ oobfree->length -= 1; -+ } else if (bbm_pos == (oobfree->offset + oobfree->length - 1)) { -+ oobfree->length -= 1; -+ } else { -+ layout->oobfree[i + 1].offset = bbm_pos + 1; -+ layout->oobfree[i + 1].length = -+ oobfree->length - bbm_pos - 1; -+ oobfree->length = bbm_pos; -+ i++; -+ } -+ } -+ -+ layout->oobavail = ((oob_per_sec - ecc_per_sec) -+ << ctrl->sec_per_page_shift) - 1; -+ -+ ctrl->mtd.oobavail = layout->oobavail; -+ ctrl->nand.ecc.layout = layout; -+ -+ /* Output layout for debugging */ -+ dev_dbg(dev, "Spare area=%d eccbytes %d, ecc bytes located at:\n", -+ ctrl->mtd.oobsize, layout->eccbytes); -+ for (i = j = 0; -+ i < ARRAY_SIZE(layout->eccpos) && i < layout->eccbytes; i++) -+ pr_debug(" %d", layout->eccpos[i]); -+ pr_debug("\n"); -+ -+ dev_dbg(dev, "Available %d bytes at (off,len):\n", layout->oobavail); -+ for (i = 0; i < ARRAY_SIZE(layout->oobfree); i++) -+ pr_debug("(%d,%d) ", layout->oobfree[i].offset, -+ layout->oobfree[i].length); -+ pr_debug("\n"); -+ -+ return 0; -+} -+ -+/* -+ * Register bit-field manipulation routines -+ */ -+ -+static inline unsigned int bcmnand_reg_read(struct bcmnand_ctrl *ctrl, -+ struct bcmnand_reg_field rbf) -+{ -+ u32 val; -+ -+ val = bcma_read32(ctrl->core, rbf.reg); -+ val >>= rbf.pos; -+ val &= (1 << rbf.width) - 1; -+ -+ return val; -+} -+ -+static inline void bcmnand_reg_write(struct bcmnand_ctrl *ctrl, -+ struct bcmnand_reg_field rbf, -+ unsigned newval) -+{ -+ u32 val, msk; -+ -+ msk = (1 << rbf.width) - 1; -+ msk <<= rbf.pos; -+ newval <<= rbf.pos; -+ newval &= msk; -+ -+ val = bcma_read32(ctrl->core, rbf.reg); -+ val &= ~msk; -+ val |= newval; -+ bcma_write32(ctrl->core, rbf.reg, val); -+} -+ -+static inline unsigned int bcmnand_reg_aread(struct bcmnand_ctrl *ctrl, -+ struct bcmnand_areg_field rbf) -+{ -+ u32 val; -+ -+ val = bcma_aread32(ctrl->core, rbf.reg); -+ val >>= rbf.pos; -+ val &= (1 << rbf.width) - 1; -+ -+ return val; -+} -+ -+static inline void bcmnand_reg_awrite(struct bcmnand_ctrl *ctrl, -+ struct bcmnand_areg_field rbf, -+ unsigned int newval) -+{ -+ u32 val, msk; -+ -+ msk = (1 << rbf.width) - 1; -+ msk <<= rbf.pos; -+ newval <<= rbf.pos; -+ newval &= msk; -+ -+ val = bcma_aread32(ctrl->core, rbf.reg); -+ val &= ~msk; -+ val |= newval; -+ bcma_awrite32(ctrl->core, rbf.reg, val); -+} -+ -+/* -+ * NAND Interface - dev_ready -+ * -+ * Return 1 iff device is ready, 0 otherwise -+ */ -+static int bcmnand_dev_ready(struct mtd_info *mtd) -+{ -+ struct nand_chip *chip = mtd->priv; -+ struct bcmnand_ctrl *ctrl = chip->priv; -+ -+ return bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY); -+} -+ -+/* -+ * Interrupt service routines -+ */ -+static irqreturn_t bcmnand_isr(int irq, void *dev_id) -+{ -+ struct bcmnand_ctrl *ctrl = dev_id; -+ int irq_off; -+ -+ irq_off = irq - ctrl->core->irq; -+ WARN_ON(irq_off < 0 || irq_off >= NANDC_IRQ_NUM); -+ -+ if (!bcmnand_reg_read(ctrl, NANDC_INT_N_REG(irq_off))) -+ return IRQ_NONE; -+ -+ /* Acknowledge interrupt */ -+ bcmnand_reg_write(ctrl, NANDC_INT_N_REG(irq_off), 1); -+ -+ /* Wake up task */ -+ complete(&ctrl->op_completion); -+ -+ return IRQ_HANDLED; -+} -+ -+static int bcmnand_wait_interrupt(struct bcmnand_ctrl *ctrl, -+ unsigned int irq_off, -+ unsigned int timeout_usec) -+{ -+ long timeout_jiffies; -+ int ret = 0; -+ -+ reinit_completion(&ctrl->op_completion); -+ -+ /* Acknowledge interrupt */ -+ bcmnand_reg_write(ctrl, NANDC_INT_N_REG(irq_off), 1); -+ -+ /* Enable IRQ to wait on */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 1); -+ -+ timeout_jiffies = 1 + usecs_to_jiffies(timeout_usec); -+ -+ if (irq_off != NANDC_IRQ_CONTROLLER_RDY || -+ 0 == bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)) { -+ -+ timeout_jiffies = wait_for_completion_interruptible_timeout( -+ &ctrl->op_completion, timeout_jiffies); -+ -+ if (timeout_jiffies < 0) -+ ret = timeout_jiffies; -+ if (timeout_jiffies == 0) -+ ret = -ETIME; -+ } -+ -+ /* Disable IRQ, we're done waiting */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 0); -+ -+ if (bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)) -+ ret = 0; -+ -+ return ret; -+} -+ -+/* -+ * wait for command completion -+ */ -+static int bcmnand_wait_cmd(struct bcmnand_ctrl *ctrl, unsigned int timeout_usec) -+{ -+ unsigned int retries; -+ -+ if (bcmnand_reg_read(ctrl, NANDC_INT_STAT_CTLR_RDY)) -+ return 0; -+ -+ /* If the timeout is long, wait for interrupt */ -+ if (timeout_usec >= jiffies_to_usecs(1) >> 4) -+ return bcmnand_wait_interrupt( -+ ctrl, NANDC_IRQ_CONTROLLER_RDY, timeout_usec); -+ -+ /* Wait for completion of the prior command */ -+ retries = (timeout_usec >> 3) + 1; -+ -+ while (retries-- && -+ 0 == bcmnand_reg_read(ctrl, NANDC_INT_STAT_CTLR_RDY)) { -+ cpu_relax(); -+ udelay(6); -+ } -+ -+ if (retries == 0) -+ return -ETIME; -+ -+ return 0; -+} -+ -+ -+/* -+ * NAND Interface - waitfunc -+ */ -+static int bcmnand_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) -+{ -+ struct bcmnand_ctrl *ctrl = chip->priv; -+ unsigned int to; -+ int ret; -+ -+ /* figure out timeout based on what command is on */ -+ switch (ctrl->last_cmd) { -+ default: -+ case NAND_CMD_ERASE1: -+ case NAND_CMD_ERASE2: -+ to = 1 << 16; -+ break; -+ case NAND_CMD_STATUS: -+ case NAND_CMD_RESET: -+ to = 256; -+ break; -+ case NAND_CMD_READID: -+ to = 1024; -+ break; -+ case NAND_CMD_READ1: -+ case NAND_CMD_READ0: -+ to = 2048; -+ break; -+ case NAND_CMD_PAGEPROG: -+ to = 4096; -+ break; -+ case NAND_CMD_READOOB: -+ to = 512; -+ break; -+ } -+ -+ /* deliver deferred error code if any */ -+ ret = ctrl->cmd_ret; -+ if (ret < 0) -+ ctrl->cmd_ret = 0; -+ else -+ ret = bcmnand_wait_cmd(ctrl, to); -+ -+ /* Timeout */ -+ if (ret < 0) -+ return NAND_STATUS_FAIL; -+ -+ ret = bcmnand_reg_read(ctrl, NANDC_INT_STAT_FLASH_STATUS); -+ -+ return ret; -+} -+ -+/* -+ * NAND Interface - read_oob -+ */ -+static int bcmnand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, -+ int page) -+{ -+ struct bcmnand_ctrl *ctrl = chip->priv; -+ unsigned int n = ctrl->chip_num; -+ void __iomem *ctrl_spare; -+ unsigned int spare_per_sec, sector; -+ u64 nand_addr; -+ -+ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_READ_OFF; -+ -+ /* Set the page address for the following commands */ -+ nand_addr = ((u64)page << chip->page_shift); -+ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); -+ -+ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; -+ -+ /* Disable ECC validation for spare area reads */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_RD_ECC(n), 0); -+ -+ /* Loop all sectors in page */ -+ for (sector = 0; sector < (1<<ctrl->sec_per_page_shift); sector++) { -+ unsigned int col; -+ -+ col = (sector << ctrl->sector_size_shift); -+ -+ /* Issue command to read partial page */ -+ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr + col); -+ -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_SPARE_READ); -+ -+ /* Wait for the command to complete */ -+ if (bcmnand_wait_cmd(ctrl, (sector == 0) ? 10000 : 100)) -+ return -EIO; -+ -+ if (!bcmnand_reg_read(ctrl, NANDC_INT_STAT_SPARE_VALID)) -+ return -EIO; -+ -+ /* Set controller to Little Endian mode for copying */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1); -+ -+ memcpy(chip->oob_poi + sector * spare_per_sec, -+ ctrl_spare, spare_per_sec); -+ -+ /* Return to Big Endian mode for commands etc */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); -+ } -+ -+ return 0; -+} -+ -+/* -+ * NAND Interface - write_oob -+ */ -+static int bcmnand_write_oob(struct mtd_info *mtd, struct nand_chip *chip, -+ int page) -+{ -+ struct bcmnand_ctrl *ctrl = chip->priv; -+ unsigned int n = ctrl->chip_num; -+ void __iomem *ctrl_spare; -+ unsigned int spare_per_sec, sector, num_sec; -+ u64 nand_addr; -+ int to, status = 0; -+ -+ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_WRITE_OFF; -+ -+ /* Disable ECC generation for spare area writes */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_WR_ECC(n), 0); -+ -+ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; -+ -+ /* Set the page address for the following commands */ -+ nand_addr = ((u64)page << chip->page_shift); -+ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); -+ -+ /* Must allow partial programming to change spare area only */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PGM_PARTIAL(n), 1); -+ -+ num_sec = 1 << ctrl->sec_per_page_shift; -+ /* Loop all sectors in page */ -+ for (sector = 0; sector < num_sec; sector++) { -+ unsigned int col; -+ -+ /* Spare area accessed by the data sector offset */ -+ col = (sector << ctrl->sector_size_shift); -+ -+ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr + col); -+ -+ /* Set controller to Little Endian mode for copying */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1); -+ -+ memcpy(ctrl_spare, chip->oob_poi + sector * spare_per_sec, -+ spare_per_sec); -+ -+ /* Return to Big Endian mode for commands etc */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); -+ -+ /* Push spare bytes into internal buffer, last goes to flash */ -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_SPARE_PROG); -+ -+ if (sector == (num_sec - 1)) -+ to = 1 << 16; -+ else -+ to = 1 << 10; -+ -+ if (bcmnand_wait_cmd(ctrl, to)) -+ return -EIO; -+ } -+ -+ /* Restore partial programming inhibition */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PGM_PARTIAL(n), 0); -+ -+ status = bcmnand_waitfunc(mtd, chip); -+ return status & NAND_STATUS_FAIL ? -EIO : 0; -+} -+ -+/* -+ * verify that a buffer is all erased -+ */ -+static bool bcmnand_buf_erased(const void *buf, unsigned int len) -+{ -+ unsigned int i; -+ const u32 *p = buf; -+ -+ for (i = 0; i < (len >> 2); i++) { -+ if (p[i] != 0xffffffff) -+ return false; -+ } -+ return true; -+} -+ -+/* -+ * read a page, with or without ECC checking -+ */ -+static int bcmnand_read_page_do(struct mtd_info *mtd, struct nand_chip *chip, -+ uint8_t *buf, int page, bool ecc) -+{ -+ struct bcmnand_ctrl *ctrl = chip->priv; -+ unsigned int n = ctrl->chip_num; -+ void __iomem *ctrl_cache; -+ void __iomem *ctrl_spare; -+ unsigned int data_bytes; -+ unsigned int spare_per_sec; -+ unsigned int sector, to = 1 << 16; -+ u32 err_soft_reg, err_hard_reg; -+ unsigned int hard_err_count = 0; -+ int ret; -+ u64 nand_addr; -+ -+ ctrl_cache = ctrl->core->io_addr + NANDC_CACHE_OFF; -+ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_READ_OFF; -+ -+ /* Reset ECC error stats */ -+ err_hard_reg = bcmnand_reg_read(ctrl, NANDC_UNCORR_ERR_COUNT); -+ err_soft_reg = bcmnand_reg_read(ctrl, NANDC_READ_CORR_BIT_COUNT); -+ -+ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; -+ -+ /* Set the page address for the following commands */ -+ nand_addr = ((u64)page << chip->page_shift); -+ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); -+ -+ /* Enable ECC validation for ecc page reads */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_RD_ECC(n), ecc); -+ -+ /* Loop all sectors in page */ -+ for (sector = 0; sector < (1 << ctrl->sec_per_page_shift); sector++) { -+ data_bytes = 0; -+ -+ /* Copy partial sectors sized by cache reg */ -+ while (data_bytes < (1<<ctrl->sector_size_shift)) { -+ unsigned int col; -+ -+ col = data_bytes + (sector << ctrl->sector_size_shift); -+ -+ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, -+ nand_addr + col); -+ -+ /* Issue command to read partial page */ -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_PAGE_READ); -+ -+ /* Wait for the command to complete */ -+ ret = bcmnand_wait_cmd(ctrl, to); -+ if (ret < 0) -+ return ret; -+ -+ /* Set controller to Little Endian mode for copying */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 1); -+ -+ if (data_bytes == 0) { -+ memcpy(chip->oob_poi + sector * spare_per_sec, -+ ctrl_spare, spare_per_sec); -+ } -+ -+ memcpy(buf + col, ctrl_cache, NANDC_CACHE_SIZE); -+ data_bytes += NANDC_CACHE_SIZE; -+ -+ /* Return to Big Endian mode for commands etc */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); -+ -+ /* Next iterations should go fast */ -+ to = 1 << 10; -+ -+ /* capture hard errors for each partial */ -+ if (err_hard_reg != bcmnand_reg_read(ctrl, NANDC_UNCORR_ERR_COUNT)) { -+ int era = bcmnand_reg_read(ctrl, NANDC_INT_STAT_ERASED); -+ -+ if (!era && -+ !bcmnand_buf_erased(buf + col, NANDC_CACHE_SIZE)) -+ hard_err_count++; -+ -+ err_hard_reg = bcmnand_reg_read(ctrl, -+ NANDC_UNCORR_ERR_COUNT); -+ } -+ } -+ } -+ -+ if (!ecc) -+ return 0; -+ -+ /* Report hard ECC errors */ -+ if (hard_err_count) -+ mtd->ecc_stats.failed++; -+ -+ /* Get ECC soft error stats */ -+ mtd->ecc_stats.corrected += err_soft_reg - -+ bcmnand_reg_read(ctrl, NANDC_READ_CORR_BIT_COUNT); -+ -+ return 0; -+} -+ -+/* -+ * NAND Interface - read_page_ecc -+ */ -+static int bcmnand_read_page_ecc(struct mtd_info *mtd, struct nand_chip *chip, -+ uint8_t *buf, int oob_required, int page) -+{ -+ return bcmnand_read_page_do(mtd, chip, buf, page, true); -+} -+ -+/* -+ * NAND Interface - read_page_raw -+ */ -+static int bcmnand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, -+ uint8_t *buf, int oob_required, int page) -+{ -+ return bcmnand_read_page_do(mtd, chip, buf, page, true); -+} -+ -+/* -+ * do page write, with or without ECC generation enabled -+ */ -+static int bcmnand_write_page_do(struct mtd_info *mtd, struct nand_chip *chip, -+ const uint8_t *buf, bool ecc) -+{ -+ struct bcmnand_ctrl *ctrl = chip->priv; -+ unsigned int n = ctrl->chip_num; -+ void __iomem *ctrl_cache; -+ void __iomem *ctrl_spare; -+ unsigned int spare_per_sec, sector, num_sec; -+ unsigned int data_bytes, spare_bytes; -+ int i, to; -+ uint8_t *tmp_poi; -+ u32 nand_addr; -+ -+ ctrl_cache = ctrl->core->io_addr + NANDC_CACHE_OFF; -+ ctrl_spare = ctrl->core->io_addr + NANDC_SPARE_AREA_WRITE_OFF; -+ -+ /* Get start-of-page address */ -+ nand_addr = bcmnand_reg_read(ctrl, NANDC_CMD_ADDRESS); -+ -+ tmp_poi = kmalloc(mtd->oobsize, GFP_KERNEL); -+ if (!tmp_poi) -+ return -ENOMEM; -+ -+ /* Retreive pre-existing OOB values */ -+ memcpy(tmp_poi, chip->oob_poi, mtd->oobsize); -+ ctrl->cmd_ret = bcmnand_read_oob(mtd, chip, -+ nand_addr >> chip->page_shift); -+ if (ctrl->cmd_ret < 0) { -+ kfree(tmp_poi); -+ return ctrl->cmd_ret; -+ } -+ -+ /* Apply new OOB data bytes just like they would end up on the chip */ -+ for (i = 0; i < mtd->oobsize; i++) -+ chip->oob_poi[i] &= tmp_poi[i]; -+ kfree(tmp_poi); -+ -+ spare_per_sec = mtd->oobsize >> ctrl->sec_per_page_shift; -+ -+ /* Enable ECC generation for ecc page write, if requested */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_WR_ECC(n), ecc); -+ -+ spare_bytes = 0; -+ num_sec = 1 << ctrl->sec_per_page_shift; -+ -+ /* Loop all sectors in page */ -+ for (sector = 0; sector < num_sec; sector++) { -+ data_bytes = 0; -+ -+ /* Copy partial sectors sized by cache reg */ -+ while (data_bytes < (1<<ctrl->sector_size_shift)) { -+ unsigned int col; -+ -+ col = data_bytes + -+ (sector << ctrl->sector_size_shift); -+ -+ /* Set address of 512-byte sub-page */ -+ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, -+ nand_addr + col); -+ -+ /* Set controller to Little Endian mode for copying */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, -+ 1); -+ -+ /* Set spare area is written at each sector start */ -+ if (data_bytes == 0) { -+ memcpy(ctrl_spare, -+ chip->oob_poi + spare_bytes, -+ spare_per_sec); -+ spare_bytes += spare_per_sec; -+ } -+ -+ /* Copy sub-page data */ -+ memcpy(ctrl_cache, buf + col, NANDC_CACHE_SIZE); -+ data_bytes += NANDC_CACHE_SIZE; -+ -+ /* Return to Big Endian mode for commands etc */ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); -+ -+ /* Push data into internal cache */ -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_PAGE_PROG); -+ -+ /* Wait for the command to complete */ -+ if (sector == (num_sec - 1)) -+ to = 1 << 16; -+ else -+ to = 1 << 10; -+ ctrl->cmd_ret = bcmnand_wait_cmd(ctrl, to); -+ if (ctrl->cmd_ret < 0) -+ return ctrl->cmd_ret; -+ } -+ } -+ return 0; -+} -+ -+/* -+ * NAND Interface = write_page_ecc -+ */ -+static int bcmnand_write_page_ecc(struct mtd_info *mtd, struct nand_chip *chip, -+ const uint8_t *buf, int oob_required) -+{ -+ return bcmnand_write_page_do(mtd, chip, buf, true); -+} -+ -+/* -+ * NAND Interface = write_page_raw -+ */ -+static int bcmnand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, -+ const uint8_t *buf, int oob_required) -+{ -+ return bcmnand_write_page_do(mtd, chip, buf, false); -+} -+ -+/* -+ * MTD Interface - read_byte -+ * -+ * This function emulates simple controllers behavior -+ * for just a few relevant commands -+ */ -+static uint8_t bcmnand_read_byte(struct mtd_info *mtd) -+{ -+ struct nand_chip *nand = mtd->priv; -+ struct bcmnand_ctrl *ctrl = nand->priv; -+ struct device *dev = &ctrl->core->dev; -+ uint8_t b = ~0; -+ -+ switch (ctrl->last_cmd) { -+ case NAND_CMD_READID: -+ if (ctrl->id_byte_index < 8) { -+ b = bcmnand_reg_read(ctrl, NANDC_DEVID_BYTE( -+ ctrl->id_byte_index)); -+ ctrl->id_byte_index++; -+ } -+ break; -+ case NAND_CMD_READOOB: -+ if (ctrl->oob_index < mtd->oobsize) -+ b = nand->oob_poi[ctrl->oob_index++]; -+ break; -+ case NAND_CMD_STATUS: -+ b = bcmnand_reg_read(ctrl, NANDC_INT_STAT_FLASH_STATUS); -+ break; -+ default: -+ dev_err(dev, "got unkown command: 0x%x in read_byte\n", -+ ctrl->last_cmd); -+ } -+ return b; -+} -+ -+/* -+ * MTD Interface - read_word -+ * -+ * Can not be tested without x16 chip, but the SoC does not support x16 i/f. -+ */ -+static u16 bcmnand_read_word(struct mtd_info *mtd) -+{ -+ u16 w = ~0; -+ -+ w = bcmnand_read_byte(mtd); -+ barrier(); -+ w |= bcmnand_read_byte(mtd) << 8; -+ -+ return w; -+} -+ -+/* -+ * MTD Interface - select a chip from an array -+ */ -+static void bcmnand_select_chip(struct mtd_info *mtd, int chip) -+{ -+ struct nand_chip *nand = mtd->priv; -+ struct bcmnand_ctrl *ctrl = nand->priv; -+ -+ ctrl->chip_num = chip; -+ bcmnand_reg_write(ctrl, NANDC_CMD_CS_SEL, chip); -+} -+ -+/* -+ * NAND Interface - emulate low-level NAND commands -+ * -+ * Only a few low-level commands are really needed by generic NAND, -+ * and they do not call for CMD_LL operations the controller can support. -+ */ -+static void bcmnand_cmdfunc(struct mtd_info *mtd, unsigned int command, -+ int column, int page_addr) -+{ -+ struct nand_chip *nand = mtd->priv; -+ struct bcmnand_ctrl *ctrl = nand->priv; -+ struct device *dev = &ctrl->core->dev; -+ u64 nand_addr; -+ unsigned int to = 1; -+ -+ ctrl->last_cmd = command; -+ -+ /* Set address for some commands */ -+ switch (command) { -+ case NAND_CMD_ERASE1: -+ column = 0; -+ /*FALLTHROUGH*/ -+ case NAND_CMD_SEQIN: -+ case NAND_CMD_READ0: -+ case NAND_CMD_READ1: -+ WARN_ON(column >= mtd->writesize); -+ nand_addr = (u64) column | -+ ((u64)page_addr << nand->page_shift); -+ bcmnand_reg_write(ctrl, NANDC_CMD_EXT_ADDR, nand_addr >> 32); -+ bcmnand_reg_write(ctrl, NANDC_CMD_ADDRESS, nand_addr); -+ break; -+ case NAND_CMD_ERASE2: -+ case NAND_CMD_RESET: -+ case NAND_CMD_READID: -+ case NAND_CMD_READOOB: -+ case NAND_CMD_PAGEPROG: -+ default: -+ /* Do nothing, address not used */ -+ break; -+ } -+ -+ /* Issue appropriate command to controller */ -+ switch (command) { -+ case NAND_CMD_SEQIN: -+ /* Only need to load command address, done */ -+ return; -+ -+ case NAND_CMD_RESET: -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_FLASH_RESET); -+ to = 1 << 8; -+ break; -+ -+ case NAND_CMD_READID: -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_DEVID_READ); -+ ctrl->id_byte_index = 0; -+ to = 1 << 8; -+ break; -+ -+ case NAND_CMD_READ0: -+ case NAND_CMD_READ1: -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_PAGE_READ); -+ to = 1 << 15; -+ break; -+ case NAND_CMD_STATUS: -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_STATUS_READ); -+ to = 1 << 8; -+ break; -+ case NAND_CMD_ERASE1: -+ return; -+ -+ case NAND_CMD_ERASE2: -+ bcmnand_reg_write(ctrl, NANDC_CMD_START_OPCODE, -+ NANDC_CMD_OPCODE_BLOCK_ERASE); -+ to = 1 << 18; -+ break; -+ -+ case NAND_CMD_PAGEPROG: -+ /* Cmd already set from write_page */ -+ return; -+ -+ case NAND_CMD_READOOB: -+ /* Emulate simple interface */ -+ bcmnand_read_oob(mtd, nand, page_addr); -+ ctrl->oob_index = 0; -+ return; -+ -+ default: -+ dev_err(dev, "got unkown command: 0x%x in cmdfunc\n", -+ ctrl->last_cmd); -+ } -+ -+ /* Wait for command to complete */ -+ ctrl->cmd_ret = bcmnand_wait_cmd(ctrl, to); -+ -+} -+ -+static int bcmnand_scan(struct mtd_info *mtd) -+{ -+ struct nand_chip *nand = mtd->priv; -+ struct bcmnand_ctrl *ctrl = nand->priv; -+ struct device *dev = &ctrl->core->dev; -+ bool sector_1k = false; -+ unsigned int chip_num = 0; -+ int ecc_level = 0; -+ int ret; -+ -+ ret = nand_scan_ident(mtd, NANDC_MAX_CHIPS, NULL); -+ if (ret) -+ return ret; -+ -+ /* Get configuration from first chip */ -+ sector_1k = bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_SECTOR_1K(0)); -+ ecc_level = bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(0)); -+ mtd->writesize_shift = nand->page_shift; -+ -+ ctrl->ecc_level = ecc_level; -+ ctrl->sector_size_shift = sector_1k ? 10 : 9; -+ -+ /* Configure spare area, tweak as needed */ -+ do { -+ ctrl->sec_per_page_shift = -+ mtd->writesize_shift - ctrl->sector_size_shift; -+ -+ /* will return -EINVAL if OOB space exhausted */ -+ ret = bcmnand_hw_ecc_layout(ctrl); -+ -+ /* First try to bump sector size to 1k, then decrease level */ -+ if (ret && nand->page_shift > 9 && ctrl->sector_size_shift < 10) -+ ctrl->sector_size_shift = 10; -+ else if (ret) -+ ctrl->ecc_level--; -+ -+ } while (ret && ctrl->ecc_level > 0); -+ -+ if (WARN_ON(ctrl->ecc_level == 0)) -+ return -ENOENT; -+ -+ if ((ctrl->sector_size_shift > 9) != (sector_1k == 1)) { -+ dev_info(dev, "sector size adjusted to 1k\n"); -+ sector_1k = 1; -+ } -+ -+ if (ecc_level != ctrl->ecc_level) { -+ dev_info(dev, "ECC level adjusted from %u to %u\n", -+ ecc_level, ctrl->ecc_level); -+ ecc_level = ctrl->ecc_level; -+ } -+ -+ /* handle the hardware chip config registers */ -+ for (chip_num = 0; chip_num < nand->numchips; chip_num++) { -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_SECTOR_1K(chip_num), -+ sector_1k); -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(chip_num), -+ ecc_level); -+ -+ /* Large pages: no partial page programming */ -+ if (mtd->writesize > 512) { -+ bcmnand_reg_write(ctrl, -+ NANDC_ACC_CTRL_PGM_RDIN(chip_num), 0); -+ bcmnand_reg_write(ctrl, -+ NANDC_ACC_CTRL_PGM_PARTIAL(chip_num), 0); -+ } -+ -+ /* Do not raise ECC error when reading erased pages */ -+ /* This bit has only partial effect, driver needs to help */ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_ERA_ECC_ERR(chip_num), -+ 0); -+ -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PG_HIT(chip_num), 0); -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_PREFETCH(chip_num), 0); -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_CACHE_MODE(chip_num), 0); -+ bcmnand_reg_write(ctrl, NANDC_ACC_CTRL_CACHE_LASTPG(chip_num), -+ 0); -+ -+ /* TBD: consolidate or at least verify the s/w and h/w geometries agree */ -+ } -+ -+ /* Allow writing on device */ -+ if (!(nand->options & NAND_ROM)) -+ bcmnand_reg_write(ctrl, NANDC_CS_NAND_WP, 0); -+ -+ dev_dbg(dev, "layout.oobavail=%d\n", nand->ecc.layout->oobavail); -+ -+ ret = nand_scan_tail(mtd); -+ -+ if (nand->badblockbits == 0) -+ nand->badblockbits = 8; -+ if (WARN_ON((1 << nand->page_shift) != mtd->writesize)) -+ return -EIO; -+ -+ /* Spit out some key chip parameters as detected by nand_base */ -+ dev_dbg(dev, "erasesize=%d writesize=%d oobsize=%d page_shift=%d badblockpos=%d badblockbits=%d\n", -+ mtd->erasesize, mtd->writesize, mtd->oobsize, -+ nand->page_shift, nand->badblockpos, nand->badblockbits); -+ -+ return ret; -+} -+ -+/* -+ * main intiailization function -+ */ -+static int bcmnand_ctrl_init(struct bcmnand_ctrl *ctrl) -+{ -+ unsigned int chip; -+ struct nand_chip *nand; -+ struct mtd_info *mtd; -+ struct device *dev = &ctrl->core->dev; -+ int ret; -+ -+ /* Software variables init */ -+ nand = &ctrl->nand; -+ mtd = &ctrl->mtd; -+ -+ init_completion(&ctrl->op_completion); -+ -+ mtd->priv = nand; -+ mtd->owner = THIS_MODULE; -+ mtd->name = KBUILD_MODNAME; -+ -+ nand->priv = ctrl; -+ -+ nand->chip_delay = 5; /* not used */ -+ nand->IO_ADDR_R = nand->IO_ADDR_W = (void *)~0L; -+ -+ if (bcmnand_reg_read(ctrl, NANDC_CONFIG_CHIP_WIDTH(0))) -+ nand->options |= NAND_BUSWIDTH_16; -+ nand->options |= NAND_SKIP_BBTSCAN; /* Dont need BBTs */ -+ -+ nand->options |= NAND_NO_SUBPAGE_WRITE; /* Subpages unsupported */ -+ -+ nand->dev_ready = bcmnand_dev_ready; -+ nand->read_byte = bcmnand_read_byte; -+ nand->read_word = bcmnand_read_word; -+ nand->select_chip = bcmnand_select_chip; -+ nand->cmdfunc = bcmnand_cmdfunc; -+ nand->waitfunc = bcmnand_waitfunc; -+ -+ nand->ecc.mode = NAND_ECC_HW; -+ nand->ecc.read_page_raw = bcmnand_read_page_raw; -+ nand->ecc.write_page_raw = bcmnand_write_page_raw; -+ nand->ecc.read_page = bcmnand_read_page_ecc; -+ nand->ecc.write_page = bcmnand_write_page_ecc; -+ nand->ecc.read_oob = bcmnand_read_oob; -+ nand->ecc.write_oob = bcmnand_write_oob; -+ -+ /* Set AUTO_CNFIG bit - try to auto-detect chips */ -+ bcmnand_reg_write(ctrl, NANDC_CS_AUTO_CONFIG, 1); -+ -+ usleep_range(1000, 1500); -+ -+ /* Print out current chip config */ -+ for (chip = 0; chip < NANDC_MAX_CHIPS; chip++) { -+ dev_dbg(dev, "chip[%d]: size=%#x block=%#x page=%#x ecc_level=%#x\n", -+ chip, -+ bcmnand_reg_read(ctrl, NANDC_CONFIG_CHIP_SIZE(chip)), -+ bcmnand_reg_read(ctrl, NANDC_CONFIG_BLK_SIZE(chip)), -+ bcmnand_reg_read(ctrl, NANDC_CONFIG_PAGE_SIZE(chip)), -+ bcmnand_reg_read(ctrl, NANDC_ACC_CTRL_ECC_LEVEL(chip))); -+ } -+ -+ dev_dbg(dev, "Nand controller is reads=%d\n", -+ bcmnand_reg_aread(ctrl, NANDC_IDM_IO_CTRL_RDY)); -+ -+ ret = bcmnand_scan(mtd); -+ if (ret) { -+ dev_err(dev, "scanning the nand flash chip failed with %i\n", -+ ret); -+ return ret; -+ } -+ -+ return 0; -+} -+ -+static int bcmnand_idm_init(struct bcmnand_ctrl *ctrl) -+{ -+ int irq_off; -+ unsigned int retries = 0x1000; -+ struct device *dev = &ctrl->core->dev; -+ -+ if (bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) -+ dev_info(dev, "stuck in reset\n"); -+ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_RESET, 1); -+ if (!bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) { -+ dev_err(dev, "reset of failed\n"); -+ return -EIO; -+ } -+ -+ while (bcmnand_reg_aread(ctrl, NANDC_IDM_RESET)) { -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_RESET, 0); -+ cpu_relax(); -+ usleep_range(100, 150); -+ if (!(retries--)) { -+ dev_err(dev, "did not came back from reset\n"); -+ return -ETIMEDOUT; -+ } -+ } -+ -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_CLOCK_EN, 1); -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_APB_LITTLE_ENDIAN, 0); -+ udelay(10); -+ -+ dev_info(dev, "NAND Controller rev %d.%02d\n", -+ bcmnand_reg_read(ctrl, NANDC_REV_MAJOR), -+ bcmnand_reg_read(ctrl, NANDC_REV_MINOR)); -+ -+ usleep_range(250, 350); -+ -+ /* Disable all IRQs */ -+ for (irq_off = 0; irq_off < NANDC_IRQ_NUM; irq_off++) -+ bcmnand_reg_awrite(ctrl, NANDC_IDM_IRQ_N_EN(irq_off), 0); -+ -+ return 0; -+} -+ -+static const char * const part_probes[] = { "ofpart", "bcm47xxpart", NULL }; -+ -+/* -+ * Top-level init function -+ */ -+static int bcmnand_probe(struct bcma_device *core) -+{ -+ struct mtd_part_parser_data parser_data; -+ struct device *dev = &core->dev; -+ struct bcmnand_ctrl *ctrl; -+ int res, i, irq; -+ -+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); -+ if (!ctrl) -+ return -ENOMEM; -+ -+ bcma_set_drvdata(core, ctrl); -+ -+ ctrl->mtd.dev.parent = &core->dev; -+ ctrl->core = core; -+ -+ /* Acquire all interrupt lines */ -+ for (i = 0; i < NANDC_IRQ_NUM; i++) { -+ irq = bcma_core_irq(core, i); -+ if (!irq) { -+ dev_err(dev, "IRQ idx %i not available\n", i); -+ return -ENOENT; -+ } -+ res = devm_request_irq(dev, irq, bcmnand_isr, 0, -+ KBUILD_MODNAME, ctrl); -+ if (res < 0) { -+ dev_err(dev, "problem requesting irq: %i (idx: %i)\n", -+ irq, i); -+ return res; -+ } -+ } -+ -+ res = bcmnand_idm_init(ctrl); -+ if (res) -+ return res; -+ -+ res = bcmnand_ctrl_init(ctrl); -+ if (res) -+ return res; -+ -+ parser_data.of_node = dev->of_node; -+ res = mtd_device_parse_register(&ctrl->mtd, part_probes, &parser_data, NULL, 0); -+ if (res) { -+ dev_err(dev, "Failed to register MTD device: %d\n", res); -+ return res; -+ } -+ return 0; -+} -+ -+static void bcmnand_remove(struct bcma_device *core) -+{ -+ struct bcmnand_ctrl *ctrl = bcma_get_drvdata(core); -+ -+ mtd_device_unregister(&ctrl->mtd); -+} -+ -+static const struct bcma_device_id bcmnand_bcma_tbl[] = { -+ BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_NS_NAND, BCMA_ANY_REV, BCMA_ANY_CLASS), -+ BCMA_CORETABLE_END -+}; -+MODULE_DEVICE_TABLE(bcma, bgmac_bcma_tbl); -+ -+static struct bcma_driver bcmnand_bcma_driver = { -+ .name = KBUILD_MODNAME, -+ .id_table = bcmnand_bcma_tbl, -+ .probe = bcmnand_probe, -+ .remove = bcmnand_remove, -+}; -+ -+static int __init bcmnand_init(void) -+{ -+ return bcma_driver_register(&bcmnand_bcma_driver); -+} -+ -+static void __exit bcmnand_exit(void) -+{ -+ bcma_driver_unregister(&bcmnand_bcma_driver); -+} -+ -+module_init(bcmnand_init) -+module_exit(bcmnand_exit) -+ -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Hauke Mehrtens"); -+MODULE_DESCRIPTION("Northstar on-chip NAND Flash Controller driver"); diff --git a/target/linux/bcm53xx/patches-3.14/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch b/target/linux/bcm53xx/patches-3.14/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch deleted file mode 100644 index b8229cd38c..0000000000 --- a/target/linux/bcm53xx/patches-3.14/500-UBI-Detect-EOF-mark-and-erase-all-remaining-blocks.patch +++ /dev/null @@ -1,34 +0,0 @@ -From f41f8b42db092e505382f7120994de21590dff48 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Thu, 16 Oct 2014 20:52:16 +0200 -Subject: [PATCH] UBI: Detect EOF mark and erase all remaining blocks -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- - drivers/mtd/ubi/io.c | 5 +++++ - 1 file changed, 5 insertions(+) - ---- a/drivers/mtd/ubi/io.c -+++ b/drivers/mtd/ubi/io.c -@@ -727,6 +727,7 @@ bad: - * o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty) - * o a negative error code in case of failure. - */ -+static bool erase_all_next = false; - int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, - struct ubi_ec_hdr *ec_hdr, int verbose) - { -@@ -753,6 +754,10 @@ int ubi_io_read_ec_hdr(struct ubi_device - } - - magic = be32_to_cpu(ec_hdr->magic); -+ if (magic == 0xdeadc0de) -+ erase_all_next = true; -+ if (erase_all_next) -+ return read_err ? UBI_IO_FF_BITFLIPS : UBI_IO_FF; - if (magic != UBI_EC_HDR_MAGIC) { - if (mtd_is_eccerr(read_err)) - return UBI_IO_BAD_HDR_EBADMSG; diff --git a/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch b/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch deleted file mode 100644 index 6ae555b4dc..0000000000 --- a/target/linux/bcm53xx/patches-3.14/800-bcma-use-two-different-initcalls-if-built-in.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 666bdfc027cde41a171862dc698987a378c8b66a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com> -Date: Mon, 9 Feb 2015 18:00:42 +0100 -Subject: [PATCH RFC] bcma: use two different initcalls if built-in -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -This is needed as we can't initialize bus during fs_initcall. -Initialization requires SPROM which depends on NVRAM which depends on -mtd. Since mtd, spi, nand, spi-nor use standard module_init, we have to -do the same in bcma. -Without this we'll try to initialize SPROM without having a ready SPROM -proviver registered using bcma_arch_register_fallback_sprom. - -Signed-off-by: Rafał Miłecki <zajec5@gmail.com> ---- -While this patch seems to work and I can compile bcma as built-in and -module, I'm not too proud of it. I don't really like these #if(n)def -tricks and I'm afraid bcma_modinit may be called even if -bcma_modinit_early failed. - -Do you see any better idea of solving this? ---- - drivers/bcma/main.c | 16 ++++++++++++++-- - 1 file changed, 14 insertions(+), 2 deletions(-) - -diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c -index 9635f10..c394207 100644 ---- a/drivers/bcma/main.c -+++ b/drivers/bcma/main.c -@@ -637,13 +637,25 @@ static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) - core->id.rev, core->id.class); - } - -+/* Bus has to be registered early, before any bcma driver */ -+static int __init bcma_modinit_early(void) -+{ -+ return bus_register(&bcma_bus_type); -+} -+#ifndef MODULE -+fs_initcall(bcma_modinit_early); -+#endif -+ -+/* Initialization has to be done later with SPI/mtd/NAND/SPROM available */ - static int __init bcma_modinit(void) - { - int err; - -- err = bus_register(&bcma_bus_type); -+#ifdef MODULE -+ err = bcma_modinit_early(); - if (err) - return err; -+#endif - - err = bcma_host_soc_register_driver(); - if (err) { -@@ -660,7 +672,7 @@ static int __init bcma_modinit(void) - - return err; - } --fs_initcall(bcma_modinit); -+module_init(bcma_modinit); - - static void __exit bcma_modexit(void) - { --- -1.8.4.5 - diff --git a/target/linux/bcm53xx/patches-3.14/900-bgmac-some-fixes-to-get-bgmac-work.patch b/target/linux/bcm53xx/patches-3.14/900-bgmac-some-fixes-to-get-bgmac-work.patch deleted file mode 100644 index caf2f3338a..0000000000 --- a/target/linux/bcm53xx/patches-3.14/900-bgmac-some-fixes-to-get-bgmac-work.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 0bd576e93a188fd3aab769b622fb3d35fa9bc7a7 Mon Sep 17 00:00:00 2001 -From: Hauke Mehrtens <hauke@hauke-m.de> -Date: Sat, 3 May 2014 19:55:38 +0200 -Subject: [PATCH 15/15] bgmac: some fixes to get bgmac work - -Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> ---- - drivers/net/ethernet/broadcom/Kconfig | 2 +- - drivers/net/phy/phy_device.c | 2 +- - 2 files changed, 2 insertions(+), 2 deletions(-) - ---- a/drivers/net/ethernet/broadcom/Kconfig -+++ b/drivers/net/ethernet/broadcom/Kconfig -@@ -131,7 +131,7 @@ config BNX2X_SRIOV - - config BGMAC - tristate "BCMA bus GBit core support" -- depends on BCMA_HOST_SOC && HAS_DMA && BCM47XX -+ depends on BCMA_HOST_SOC && HAS_DMA - select PHYLIB - ---help--- - This driver supports GBit MAC and BCM4706 GBit MAC cores on BCMA bus. ---- a/drivers/net/phy/phy_device.c -+++ b/drivers/net/phy/phy_device.c -@@ -898,7 +898,7 @@ int genphy_update_link(struct phy_device - return status; - - if ((status & BMSR_LSTATUS) == 0) -- phydev->link = 0; -+ phydev->link = 1; - else - phydev->link = 1; - |