mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-31 04:01:48 -04:00
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (82 commits) mtd: fix build error in m25p80.c mtd: Remove redundant mutex from mtd_blkdevs.c MTD: Fix wrong check register_blkdev return value Revert "mtd: cleanup Kconfig dependencies" mtd: cfi_cmdset_0002: make sector erase command variable mtd: cfi_cmdset_0002: add CFI detection for SST 38VF640x chips mtd: cfi_util: add support for switching SST 39VF640xB chips into QRY mode mtd: cfi_cmdset_0001: use defined value of P_ID_INTEL_PERFORMANCE instead of hardcoded one block2mtd: dubious assignment P4080/mtd: Fix the freescale lbc issue with 36bit mode P4080/eLBC: Make Freescale elbc interrupt common to elbc devices mtd: phram: use KBUILD_MODNAME mtd: OneNAND: S5PC110: Fix double call suspend & resume function mtd: nand: fix MTD_MODE_RAW writes jffs2: use kmemdup mtd: sm_ftl: cosmetic, use bool when possible mtd: r852: remove useless pci powerup/down from suspend/resume routines mtd: blktrans: fix a race vs kthread_stop mtd: blktrans: kill BKL mtd: allow to unload the mtdtrans module if its block devices aren't open ... Fix up trivial whitespace-introduced conflict in drivers/mtd/mtdchar.c
This commit is contained in:
commit
79346507ad
71 changed files with 3412 additions and 1159 deletions
|
|
@ -682,9 +682,12 @@ config 4xx_SOC
|
|||
bool
|
||||
|
||||
config FSL_LBC
|
||||
bool
|
||||
bool "Freescale Local Bus support"
|
||||
depends on FSL_SOC
|
||||
help
|
||||
Freescale Localbus support
|
||||
Enables reporting of errors from the Freescale local bus
|
||||
controller. Also contains some common code used by
|
||||
drivers for specific local bus peripherals.
|
||||
|
||||
config FSL_GTM
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
/* Freescale Local Bus Controller
|
||||
*
|
||||
* Copyright (c) 2006-2007 Freescale Semiconductor
|
||||
* Copyright © 2006-2007, 2010 Freescale Semiconductor
|
||||
*
|
||||
* Authors: Nick Spence <nick.spence@freescale.com>,
|
||||
* Scott Wood <scottwood@freescale.com>
|
||||
* Jack Lan <jack.lan@freescale.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -26,6 +27,8 @@
|
|||
#include <linux/compiler.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
struct fsl_lbc_bank {
|
||||
__be32 br; /**< Base Register */
|
||||
|
|
@ -125,13 +128,23 @@ struct fsl_lbc_regs {
|
|||
#define LTESR_ATMW 0x00800000
|
||||
#define LTESR_ATMR 0x00400000
|
||||
#define LTESR_CS 0x00080000
|
||||
#define LTESR_UPM 0x00000002
|
||||
#define LTESR_CC 0x00000001
|
||||
#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
|
||||
#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
|
||||
| LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
|
||||
| LTESR_CC)
|
||||
#define LTESR_CLEAR 0xFFFFFFFF
|
||||
#define LTECCR_CLEAR 0xFFFFFFFF
|
||||
#define LTESR_STATUS LTESR_MASK
|
||||
#define LTEIR_ENABLE LTESR_MASK
|
||||
#define LTEDR_ENABLE 0x00000000
|
||||
__be32 ltedr; /**< Transfer Error Disable Register */
|
||||
__be32 lteir; /**< Transfer Error Interrupt Register */
|
||||
__be32 lteatr; /**< Transfer Error Attributes Register */
|
||||
__be32 ltear; /**< Transfer Error Address Register */
|
||||
u8 res6[0xC];
|
||||
__be32 lteccr; /**< Transfer Error ECC Register */
|
||||
u8 res6[0x8];
|
||||
__be32 lbcr; /**< Configuration Register */
|
||||
#define LBCR_LDIS 0x80000000
|
||||
#define LBCR_LDIS_SHIFT 31
|
||||
|
|
@ -235,6 +248,7 @@ struct fsl_upm {
|
|||
int width;
|
||||
};
|
||||
|
||||
extern u32 fsl_lbc_addr(phys_addr_t addr_base);
|
||||
extern int fsl_lbc_find(phys_addr_t addr_base);
|
||||
extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
|
||||
|
||||
|
|
@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
|
|||
cpu_relax();
|
||||
}
|
||||
|
||||
/* overview of the fsl lbc controller */
|
||||
|
||||
struct fsl_lbc_ctrl {
|
||||
/* device info */
|
||||
struct device *dev;
|
||||
struct fsl_lbc_regs __iomem *regs;
|
||||
int irq;
|
||||
wait_queue_head_t irq_wait;
|
||||
spinlock_t lock;
|
||||
void *nand;
|
||||
|
||||
/* status read from LTESR by irq handler */
|
||||
unsigned int irq_status;
|
||||
};
|
||||
|
||||
extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
|
||||
u32 mar);
|
||||
extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
|
||||
|
||||
#endif /* __ASM_FSL_LBC_H */
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
/*
|
||||
* Freescale LBC and UPM routines.
|
||||
*
|
||||
* Copyright (c) 2007-2008 MontaVista Software, Inc.
|
||||
* Copyright © 2007-2008 MontaVista Software, Inc.
|
||||
* Copyright © 2010 Freescale Semiconductor
|
||||
*
|
||||
* Author: Anton Vorontsov <avorontsov@ru.mvista.com>
|
||||
* Author: Jack Lan <Jack.Lan@freescale.com>
|
||||
* Author: Roy Zang <tie-fei.zang@freescale.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -19,39 +22,37 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <asm/prom.h>
|
||||
#include <asm/fsl_lbc.h>
|
||||
|
||||
static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
|
||||
static struct fsl_lbc_regs __iomem *fsl_lbc_regs;
|
||||
struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
|
||||
EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
|
||||
|
||||
static char __initdata *compat_lbc[] = {
|
||||
"fsl,pq2-localbus",
|
||||
"fsl,pq2pro-localbus",
|
||||
"fsl,pq3-localbus",
|
||||
"fsl,elbc",
|
||||
};
|
||||
|
||||
static int __init fsl_lbc_init(void)
|
||||
/**
|
||||
* fsl_lbc_addr - convert the base address
|
||||
* @addr_base: base address of the memory bank
|
||||
*
|
||||
* This function converts a base address of lbc into the right format for the
|
||||
* BR register. If the SOC has eLBC then it returns 32bit physical address
|
||||
* else it convers a 34bit local bus physical address to correct format of
|
||||
* 32bit address for BR register (Example: MPC8641).
|
||||
*/
|
||||
u32 fsl_lbc_addr(phys_addr_t addr_base)
|
||||
{
|
||||
struct device_node *lbus;
|
||||
int i;
|
||||
struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
|
||||
u32 addr = addr_base & 0xffff8000;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) {
|
||||
lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]);
|
||||
if (lbus)
|
||||
goto found;
|
||||
}
|
||||
return -ENODEV;
|
||||
if (of_device_is_compatible(np, "fsl,elbc"))
|
||||
return addr;
|
||||
|
||||
found:
|
||||
fsl_lbc_regs = of_iomap(lbus, 0);
|
||||
of_node_put(lbus);
|
||||
if (!fsl_lbc_regs)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
return addr | ((addr_base & 0x300000000ull) >> 19);
|
||||
}
|
||||
arch_initcall(fsl_lbc_init);
|
||||
EXPORT_SYMBOL(fsl_lbc_addr);
|
||||
|
||||
/**
|
||||
* fsl_lbc_find - find Localbus bank
|
||||
|
|
@ -65,15 +66,17 @@ arch_initcall(fsl_lbc_init);
|
|||
int fsl_lbc_find(phys_addr_t addr_base)
|
||||
{
|
||||
int i;
|
||||
struct fsl_lbc_regs __iomem *lbc;
|
||||
|
||||
if (!fsl_lbc_regs)
|
||||
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) {
|
||||
__be32 br = in_be32(&fsl_lbc_regs->bank[i].br);
|
||||
__be32 or = in_be32(&fsl_lbc_regs->bank[i].or);
|
||||
lbc = fsl_lbc_ctrl_dev->regs;
|
||||
for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
|
||||
__be32 br = in_be32(&lbc->bank[i].br);
|
||||
__be32 or = in_be32(&lbc->bank[i].or);
|
||||
|
||||
if (br & BR_V && (br & or & BR_BA) == addr_base)
|
||||
if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
@ -94,22 +97,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
|
|||
{
|
||||
int bank;
|
||||
__be32 br;
|
||||
struct fsl_lbc_regs __iomem *lbc;
|
||||
|
||||
bank = fsl_lbc_find(addr_base);
|
||||
if (bank < 0)
|
||||
return bank;
|
||||
|
||||
br = in_be32(&fsl_lbc_regs->bank[bank].br);
|
||||
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
|
||||
lbc = fsl_lbc_ctrl_dev->regs;
|
||||
br = in_be32(&lbc->bank[bank].br);
|
||||
|
||||
switch (br & BR_MSEL) {
|
||||
case BR_MS_UPMA:
|
||||
upm->mxmr = &fsl_lbc_regs->mamr;
|
||||
upm->mxmr = &lbc->mamr;
|
||||
break;
|
||||
case BR_MS_UPMB:
|
||||
upm->mxmr = &fsl_lbc_regs->mbmr;
|
||||
upm->mxmr = &lbc->mbmr;
|
||||
break;
|
||||
case BR_MS_UPMC:
|
||||
upm->mxmr = &fsl_lbc_regs->mcmr;
|
||||
upm->mxmr = &lbc->mcmr;
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
@ -148,9 +156,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
|
|||
int ret = 0;
|
||||
unsigned long flags;
|
||||
|
||||
if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
|
||||
return -ENODEV;
|
||||
|
||||
spin_lock_irqsave(&fsl_lbc_lock, flags);
|
||||
|
||||
out_be32(&fsl_lbc_regs->mar, mar);
|
||||
out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
|
||||
|
||||
switch (upm->width) {
|
||||
case 8:
|
||||
|
|
@ -172,3 +183,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
|
|||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(fsl_upm_run_pattern);
|
||||
|
||||
static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
|
||||
{
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
|
||||
/* clear event registers */
|
||||
setbits32(&lbc->ltesr, LTESR_CLEAR);
|
||||
out_be32(&lbc->lteatr, 0);
|
||||
out_be32(&lbc->ltear, 0);
|
||||
out_be32(&lbc->lteccr, LTECCR_CLEAR);
|
||||
out_be32(&lbc->ltedr, LTEDR_ENABLE);
|
||||
|
||||
/* Enable interrupts for any detected events */
|
||||
out_be32(&lbc->lteir, LTEIR_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: This interrupt is used to report localbus events of various kinds,
|
||||
* such as transaction errors on the chipselects.
|
||||
*/
|
||||
|
||||
static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
|
||||
{
|
||||
struct fsl_lbc_ctrl *ctrl = data;
|
||||
struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
|
||||
u32 status;
|
||||
|
||||
status = in_be32(&lbc->ltesr);
|
||||
if (!status)
|
||||
return IRQ_NONE;
|
||||
|
||||
out_be32(&lbc->ltesr, LTESR_CLEAR);
|
||||
out_be32(&lbc->lteatr, 0);
|
||||
out_be32(&lbc->ltear, 0);
|
||||
ctrl->irq_status = status;
|
||||
|
||||
if (status & LTESR_BM)
|
||||
dev_err(ctrl->dev, "Local bus monitor time-out: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
if (status & LTESR_WP)
|
||||
dev_err(ctrl->dev, "Write protect error: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
if (status & LTESR_ATMW)
|
||||
dev_err(ctrl->dev, "Atomic write error: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
if (status & LTESR_ATMR)
|
||||
dev_err(ctrl->dev, "Atomic read error: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
if (status & LTESR_CS)
|
||||
dev_err(ctrl->dev, "Chip select error: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
if (status & LTESR_UPM)
|
||||
;
|
||||
if (status & LTESR_FCT) {
|
||||
dev_err(ctrl->dev, "FCM command time-out: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
smp_wmb();
|
||||
wake_up(&ctrl->irq_wait);
|
||||
}
|
||||
if (status & LTESR_PAR) {
|
||||
dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
smp_wmb();
|
||||
wake_up(&ctrl->irq_wait);
|
||||
}
|
||||
if (status & LTESR_CC) {
|
||||
smp_wmb();
|
||||
wake_up(&ctrl->irq_wait);
|
||||
}
|
||||
if (status & ~LTESR_MASK)
|
||||
dev_err(ctrl->dev, "Unknown error: "
|
||||
"LTESR 0x%08X\n", status);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
/*
|
||||
* fsl_lbc_ctrl_probe
|
||||
*
|
||||
* called by device layer when it finds a device matching
|
||||
* one our driver can handled. This code allocates all of
|
||||
* the resources needed for the controller only. The
|
||||
* resources for the NAND banks themselves are allocated
|
||||
* in the chip probe function.
|
||||
*/
|
||||
|
||||
static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!dev->dev.of_node) {
|
||||
dev_err(&dev->dev, "Device OF-Node is NULL");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
|
||||
if (!fsl_lbc_ctrl_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
|
||||
|
||||
spin_lock_init(&fsl_lbc_ctrl_dev->lock);
|
||||
init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
|
||||
|
||||
fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
|
||||
if (!fsl_lbc_ctrl_dev->regs) {
|
||||
dev_err(&dev->dev, "failed to get memory region\n");
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
|
||||
if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
|
||||
dev_err(&dev->dev, "failed to get irq resource\n");
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
fsl_lbc_ctrl_dev->dev = &dev->dev;
|
||||
|
||||
ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
|
||||
"fsl-lbc", fsl_lbc_ctrl_dev);
|
||||
if (ret != 0) {
|
||||
dev_err(&dev->dev, "failed to install irq (%d)\n",
|
||||
fsl_lbc_ctrl_dev->irq);
|
||||
ret = fsl_lbc_ctrl_dev->irq;
|
||||
goto err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
iounmap(fsl_lbc_ctrl_dev->regs);
|
||||
kfree(fsl_lbc_ctrl_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct of_device_id fsl_lbc_match[] = {
|
||||
{ .compatible = "fsl,elbc", },
|
||||
{ .compatible = "fsl,pq3-localbus", },
|
||||
{ .compatible = "fsl,pq2-localbus", },
|
||||
{ .compatible = "fsl,pq2pro-localbus", },
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver fsl_lbc_ctrl_driver = {
|
||||
.driver = {
|
||||
.name = "fsl-lbc",
|
||||
.of_match_table = fsl_lbc_match,
|
||||
},
|
||||
.probe = fsl_lbc_ctrl_probe,
|
||||
};
|
||||
|
||||
static int __init fsl_lbc_init(void)
|
||||
{
|
||||
return platform_driver_register(&fsl_lbc_ctrl_driver);
|
||||
}
|
||||
module_init(fsl_lbc_init);
|
||||
|
|
|
|||
Loading…
Reference in a new issue