mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-06-23 15:11:16 +00:00
mtd: denali: split the generic driver and PCI layer
The Denali controller can also be found in SoC devices attached to a simple bus. Move the PCI specific parts into denali_pci so that we can add a denali_dt that uses the same driver but for a device tree driver instead of a PCI based device. Signed-off-by: Jamie Iles <jamie@jamieiles.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
This commit is contained in:
parent
30fad64325
commit
2a0a288ec2
5 changed files with 188 additions and 134 deletions
|
@ -57,8 +57,15 @@ config MTD_NAND_AUTCPU12
|
||||||
access the SmartMediaCard.
|
access the SmartMediaCard.
|
||||||
|
|
||||||
config MTD_NAND_DENALI
|
config MTD_NAND_DENALI
|
||||||
depends on PCI
|
tristate "Support Denali NAND controller"
|
||||||
|
help
|
||||||
|
Enable support for the Denali NAND controller. This should be
|
||||||
|
combined with either the PCI or platform drivers to provide device
|
||||||
|
registration.
|
||||||
|
|
||||||
|
config MTD_NAND_DENALI_PCI
|
||||||
tristate "Support Denali NAND controller on Intel Moorestown"
|
tristate "Support Denali NAND controller on Intel Moorestown"
|
||||||
|
depends on PCI && MTD_NAND_DENALI
|
||||||
help
|
help
|
||||||
Enable the driver for NAND flash on Intel Moorestown, using the
|
Enable the driver for NAND flash on Intel Moorestown, using the
|
||||||
Denali NAND controller core.
|
Denali NAND controller core.
|
||||||
|
@ -66,7 +73,7 @@ config MTD_NAND_DENALI
|
||||||
config MTD_NAND_DENALI_SCRATCH_REG_ADDR
|
config MTD_NAND_DENALI_SCRATCH_REG_ADDR
|
||||||
hex "Denali NAND size scratch register address"
|
hex "Denali NAND size scratch register address"
|
||||||
default "0xFF108018"
|
default "0xFF108018"
|
||||||
depends on MTD_NAND_DENALI
|
depends on MTD_NAND_DENALI_PCI
|
||||||
help
|
help
|
||||||
Some platforms place the NAND chip size in a scratch register
|
Some platforms place the NAND chip size in a scratch register
|
||||||
because (some versions of) the driver aren't able to automatically
|
because (some versions of) the driver aren't able to automatically
|
||||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_MTD_NAND_SPIA) += spia.o
|
||||||
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
|
obj-$(CONFIG_MTD_NAND_AMS_DELTA) += ams-delta.o
|
||||||
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
|
obj-$(CONFIG_MTD_NAND_AUTCPU12) += autcpu12.o
|
||||||
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
|
obj-$(CONFIG_MTD_NAND_DENALI) += denali.o
|
||||||
|
obj-$(CONFIG_MTD_NAND_DENALI_PCI) += denali_pci.o
|
||||||
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
|
obj-$(CONFIG_MTD_NAND_AU1550) += au1550nd.o
|
||||||
obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
|
obj-$(CONFIG_MTD_NAND_BF5XX) += bf5xx_nand.o
|
||||||
obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
|
obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB) += ppchameleonevb.o
|
||||||
|
|
|
@ -16,14 +16,12 @@
|
||||||
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
#include <linux/mutex.h>
|
#include <linux/mutex.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pci.h>
|
|
||||||
#include <linux/mtd/mtd.h>
|
#include <linux/mtd/mtd.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
|
||||||
|
@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
|
||||||
* format the bank into the proper bits for the controller */
|
* format the bank into the proper bits for the controller */
|
||||||
#define BANK(x) ((x) << 24)
|
#define BANK(x) ((x) << 24)
|
||||||
|
|
||||||
/* List of platforms this NAND controller has be integrated into */
|
|
||||||
static const struct pci_device_id denali_pci_ids[] = {
|
|
||||||
{ PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
|
|
||||||
{ PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
|
|
||||||
{ /* end: all zeroes */ }
|
|
||||||
};
|
|
||||||
|
|
||||||
/* forward declarations */
|
/* forward declarations */
|
||||||
static void clear_interrupts(struct denali_nand_info *denali);
|
static void clear_interrupts(struct denali_nand_info *denali);
|
||||||
static uint32_t wait_for_irq(struct denali_nand_info *denali,
|
static uint32_t wait_for_irq(struct denali_nand_info *denali,
|
||||||
|
@ -699,7 +690,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
|
||||||
|
|
||||||
if (comp_res == 0) {
|
if (comp_res == 0) {
|
||||||
/* timeout */
|
/* timeout */
|
||||||
printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
|
pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n",
|
||||||
intr_status, irq_mask);
|
intr_status, irq_mask);
|
||||||
|
|
||||||
intr_status = 0;
|
intr_status = 0;
|
||||||
|
@ -1305,8 +1296,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
|
||||||
/* TODO: Read OOB data */
|
/* TODO: Read OOB data */
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printk(KERN_ERR ": unsupported command"
|
pr_err(": unsupported command received 0x%x\n", cmd);
|
||||||
" received 0x%x\n", cmd);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1425,107 +1415,48 @@ void denali_drv_init(struct denali_nand_info *denali)
|
||||||
denali->irq_status = 0;
|
denali->irq_status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* driver entry point */
|
int denali_init(struct denali_nand_info *denali)
|
||||||
static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|
||||||
{
|
{
|
||||||
int ret = -ENODEV;
|
int ret;
|
||||||
resource_size_t csr_base, mem_base;
|
|
||||||
unsigned long csr_len, mem_len;
|
|
||||||
struct denali_nand_info *denali;
|
|
||||||
|
|
||||||
denali = kzalloc(sizeof(*denali), GFP_KERNEL);
|
if (denali->platform == INTEL_CE4100) {
|
||||||
if (!denali)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
ret = pci_enable_device(dev);
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
|
|
||||||
goto failed_alloc_memery;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id->driver_data == INTEL_CE4100) {
|
|
||||||
/* Due to a silicon limitation, we can only support
|
/* Due to a silicon limitation, we can only support
|
||||||
* ONFI timing mode 1 and below.
|
* ONFI timing mode 1 and below.
|
||||||
*/
|
*/
|
||||||
if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
|
if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
|
||||||
printk(KERN_ERR "Intel CE4100 only supports"
|
pr_err("Intel CE4100 only supports ONFI timing mode 1 or below\n");
|
||||||
" ONFI timing mode 1 or below\n");
|
return -EINVAL;
|
||||||
ret = -EINVAL;
|
|
||||||
goto failed_enable_dev;
|
|
||||||
}
|
|
||||||
denali->platform = INTEL_CE4100;
|
|
||||||
mem_base = pci_resource_start(dev, 0);
|
|
||||||
mem_len = pci_resource_len(dev, 1);
|
|
||||||
csr_base = pci_resource_start(dev, 1);
|
|
||||||
csr_len = pci_resource_len(dev, 1);
|
|
||||||
} else {
|
|
||||||
denali->platform = INTEL_MRST;
|
|
||||||
csr_base = pci_resource_start(dev, 0);
|
|
||||||
csr_len = pci_resource_len(dev, 0);
|
|
||||||
mem_base = pci_resource_start(dev, 1);
|
|
||||||
mem_len = pci_resource_len(dev, 1);
|
|
||||||
if (!mem_len) {
|
|
||||||
mem_base = csr_base + csr_len;
|
|
||||||
mem_len = csr_len;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is 32-bit DMA supported? */
|
/* Is 32-bit DMA supported? */
|
||||||
ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
|
ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
|
||||||
if (ret) {
|
if (ret) {
|
||||||
printk(KERN_ERR "Spectra: no usable DMA configuration\n");
|
pr_err("Spectra: no usable DMA configuration\n");
|
||||||
goto failed_enable_dev;
|
return ret;
|
||||||
}
|
}
|
||||||
denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
|
denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf,
|
||||||
DENALI_BUF_SIZE,
|
DENALI_BUF_SIZE,
|
||||||
DMA_BIDIRECTIONAL);
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
|
if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
|
||||||
dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
|
dev_err(denali->dev, "Spectra: failed to map DMA buffer\n");
|
||||||
goto failed_enable_dev;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
denali->mtd.dev.parent = denali->dev;
|
||||||
pci_set_master(dev);
|
|
||||||
denali->dev = &dev->dev;
|
|
||||||
denali->mtd.dev.parent = &dev->dev;
|
|
||||||
|
|
||||||
ret = pci_request_regions(dev, DENALI_NAND_NAME);
|
|
||||||
if (ret) {
|
|
||||||
printk(KERN_ERR "Spectra: Unable to request memory regions\n");
|
|
||||||
goto failed_dma_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
denali->flash_reg = ioremap_nocache(csr_base, csr_len);
|
|
||||||
if (!denali->flash_reg) {
|
|
||||||
printk(KERN_ERR "Spectra: Unable to remap memory region\n");
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto failed_req_regions;
|
|
||||||
}
|
|
||||||
|
|
||||||
denali->flash_mem = ioremap_nocache(mem_base, mem_len);
|
|
||||||
if (!denali->flash_mem) {
|
|
||||||
printk(KERN_ERR "Spectra: ioremap_nocache failed!");
|
|
||||||
ret = -ENOMEM;
|
|
||||||
goto failed_remap_reg;
|
|
||||||
}
|
|
||||||
|
|
||||||
denali_hw_init(denali);
|
denali_hw_init(denali);
|
||||||
denali_drv_init(denali);
|
denali_drv_init(denali);
|
||||||
|
|
||||||
/* denali_isr register is done after all the hardware
|
/* denali_isr register is done after all the hardware
|
||||||
* initilization is finished*/
|
* initilization is finished*/
|
||||||
if (request_irq(dev->irq, denali_isr, IRQF_SHARED,
|
if (request_irq(denali->irq, denali_isr, IRQF_SHARED,
|
||||||
DENALI_NAND_NAME, denali)) {
|
DENALI_NAND_NAME, denali)) {
|
||||||
printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
|
pr_err("Spectra: Unable to allocate IRQ\n");
|
||||||
ret = -ENODEV;
|
return -ENODEV;
|
||||||
goto failed_remap_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now that our ISR is registered, we can enable interrupts */
|
/* now that our ISR is registered, we can enable interrupts */
|
||||||
denali_set_intr_modes(denali, true);
|
denali_set_intr_modes(denali, true);
|
||||||
|
|
||||||
pci_set_drvdata(dev, denali);
|
|
||||||
|
|
||||||
denali->mtd.name = "denali-nand";
|
denali->mtd.name = "denali-nand";
|
||||||
denali->mtd.owner = THIS_MODULE;
|
denali->mtd.owner = THIS_MODULE;
|
||||||
denali->mtd.priv = &denali->nand;
|
denali->mtd.priv = &denali->nand;
|
||||||
|
@ -1549,8 +1480,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
*/
|
*/
|
||||||
if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
|
if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
|
||||||
ret = -ENODEV;
|
ret = -ENODEV;
|
||||||
printk(KERN_ERR "Spectra: device size not supported by this "
|
pr_err("Spectra: device size not supported by this version of MTD.");
|
||||||
"version of MTD.");
|
|
||||||
goto failed_req_irq;
|
goto failed_req_irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1602,8 +1532,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
|
} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
|
||||||
ECC_8BITS * (denali->mtd.writesize /
|
ECC_8BITS * (denali->mtd.writesize /
|
||||||
ECC_SECTOR_SIZE))) {
|
ECC_SECTOR_SIZE))) {
|
||||||
printk(KERN_ERR "Your NAND chip OOB is not large enough to"
|
pr_err("Your NAND chip OOB is not large enough to \
|
||||||
" contain 8bit ECC correction codes");
|
contain 8bit ECC correction codes");
|
||||||
goto failed_req_irq;
|
goto failed_req_irq;
|
||||||
} else {
|
} else {
|
||||||
denali->nand.ecc.strength = 8;
|
denali->nand.ecc.strength = 8;
|
||||||
|
@ -1655,56 +1585,24 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
|
|
||||||
ret = mtd_device_register(&denali->mtd, NULL, 0);
|
ret = mtd_device_register(&denali->mtd, NULL, 0);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
|
dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
|
||||||
ret);
|
ret);
|
||||||
goto failed_req_irq;
|
goto failed_req_irq;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
failed_req_irq:
|
failed_req_irq:
|
||||||
denali_irq_cleanup(dev->irq, denali);
|
denali_irq_cleanup(denali->irq, denali);
|
||||||
failed_remap_mem:
|
|
||||||
iounmap(denali->flash_mem);
|
|
||||||
failed_remap_reg:
|
|
||||||
iounmap(denali->flash_reg);
|
|
||||||
failed_req_regions:
|
|
||||||
pci_release_regions(dev);
|
|
||||||
failed_dma_map:
|
|
||||||
dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
|
|
||||||
DMA_BIDIRECTIONAL);
|
|
||||||
failed_enable_dev:
|
|
||||||
pci_disable_device(dev);
|
|
||||||
failed_alloc_memery:
|
|
||||||
kfree(denali);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(denali_init);
|
||||||
|
|
||||||
/* driver exit point */
|
/* driver exit point */
|
||||||
static void denali_pci_remove(struct pci_dev *dev)
|
void denali_remove(struct denali_nand_info *denali)
|
||||||
{
|
{
|
||||||
struct denali_nand_info *denali = pci_get_drvdata(dev);
|
denali_irq_cleanup(denali->irq, denali);
|
||||||
|
dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
|
||||||
nand_release(&denali->mtd);
|
DMA_BIDIRECTIONAL);
|
||||||
|
|
||||||
denali_irq_cleanup(dev->irq, denali);
|
|
||||||
|
|
||||||
iounmap(denali->flash_reg);
|
|
||||||
iounmap(denali->flash_mem);
|
|
||||||
pci_release_regions(dev);
|
|
||||||
pci_disable_device(dev);
|
|
||||||
dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE,
|
|
||||||
DMA_BIDIRECTIONAL);
|
|
||||||
pci_set_drvdata(dev, NULL);
|
|
||||||
kfree(denali);
|
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(denali_remove);
|
||||||
MODULE_DEVICE_TABLE(pci, denali_pci_ids);
|
|
||||||
|
|
||||||
static struct pci_driver denali_pci_driver = {
|
|
||||||
.name = DENALI_NAND_NAME,
|
|
||||||
.id_table = denali_pci_ids,
|
|
||||||
.probe = denali_pci_probe,
|
|
||||||
.remove = denali_pci_remove,
|
|
||||||
};
|
|
||||||
|
|
||||||
module_pci_driver(denali_pci_driver);
|
|
||||||
|
|
|
@ -487,6 +487,7 @@ struct denali_nand_info {
|
||||||
uint32_t irq_status;
|
uint32_t irq_status;
|
||||||
int irq_debug_array[32];
|
int irq_debug_array[32];
|
||||||
int idx;
|
int idx;
|
||||||
|
int irq;
|
||||||
|
|
||||||
uint32_t devnum; /* represent how many nands connected */
|
uint32_t devnum; /* represent how many nands connected */
|
||||||
uint32_t fwblks; /* represent how many blocks FW used */
|
uint32_t fwblks; /* represent how many blocks FW used */
|
||||||
|
@ -496,4 +497,7 @@ struct denali_nand_info {
|
||||||
uint32_t max_banks;
|
uint32_t max_banks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern int denali_init(struct denali_nand_info *denali);
|
||||||
|
extern void denali_remove(struct denali_nand_info *denali);
|
||||||
|
|
||||||
#endif /*_LLD_NAND_*/
|
#endif /*_LLD_NAND_*/
|
||||||
|
|
144
drivers/mtd/nand/denali_pci.c
Normal file
144
drivers/mtd/nand/denali_pci.c
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* NAND Flash Controller Device Driver
|
||||||
|
* Copyright © 2009-2010, Intel Corporation and its suppliers.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "denali.h"
|
||||||
|
|
||||||
|
#define DENALI_NAND_NAME "denali-nand-pci"
|
||||||
|
|
||||||
|
/* List of platforms this NAND controller has be integrated into */
|
||||||
|
static DEFINE_PCI_DEVICE_TABLE(denali_pci_ids) = {
|
||||||
|
{ PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 },
|
||||||
|
{ PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST },
|
||||||
|
{ /* end: all zeroes */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(pci, denali_pci_ids);
|
||||||
|
|
||||||
|
static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
|
{
|
||||||
|
int ret = -ENODEV;
|
||||||
|
resource_size_t csr_base, mem_base;
|
||||||
|
unsigned long csr_len, mem_len;
|
||||||
|
struct denali_nand_info *denali;
|
||||||
|
|
||||||
|
denali = kzalloc(sizeof(*denali), GFP_KERNEL);
|
||||||
|
if (!denali)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
ret = pci_enable_device(dev);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("Spectra: pci_enable_device failed.\n");
|
||||||
|
goto failed_alloc_memery;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id->driver_data == INTEL_CE4100) {
|
||||||
|
denali->platform = INTEL_CE4100;
|
||||||
|
mem_base = pci_resource_start(dev, 0);
|
||||||
|
mem_len = pci_resource_len(dev, 1);
|
||||||
|
csr_base = pci_resource_start(dev, 1);
|
||||||
|
csr_len = pci_resource_len(dev, 1);
|
||||||
|
} else {
|
||||||
|
denali->platform = INTEL_MRST;
|
||||||
|
csr_base = pci_resource_start(dev, 0);
|
||||||
|
csr_len = pci_resource_len(dev, 0);
|
||||||
|
mem_base = pci_resource_start(dev, 1);
|
||||||
|
mem_len = pci_resource_len(dev, 1);
|
||||||
|
if (!mem_len) {
|
||||||
|
mem_base = csr_base + csr_len;
|
||||||
|
mem_len = csr_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pci_set_master(dev);
|
||||||
|
denali->dev = &dev->dev;
|
||||||
|
denali->irq = dev->irq;
|
||||||
|
|
||||||
|
ret = pci_request_regions(dev, DENALI_NAND_NAME);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("Spectra: Unable to request memory regions\n");
|
||||||
|
goto failed_enable_dev;
|
||||||
|
}
|
||||||
|
|
||||||
|
denali->flash_reg = ioremap_nocache(csr_base, csr_len);
|
||||||
|
if (!denali->flash_reg) {
|
||||||
|
pr_err("Spectra: Unable to remap memory region\n");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto failed_req_regions;
|
||||||
|
}
|
||||||
|
|
||||||
|
denali->flash_mem = ioremap_nocache(mem_base, mem_len);
|
||||||
|
if (!denali->flash_mem) {
|
||||||
|
pr_err("Spectra: ioremap_nocache failed!");
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto failed_remap_reg;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = denali_init(denali);
|
||||||
|
if (ret)
|
||||||
|
goto failed_remap_mem;
|
||||||
|
|
||||||
|
pci_set_drvdata(dev, denali);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed_remap_mem:
|
||||||
|
iounmap(denali->flash_mem);
|
||||||
|
failed_remap_reg:
|
||||||
|
iounmap(denali->flash_reg);
|
||||||
|
failed_req_regions:
|
||||||
|
pci_release_regions(dev);
|
||||||
|
failed_enable_dev:
|
||||||
|
pci_disable_device(dev);
|
||||||
|
failed_alloc_memery:
|
||||||
|
kfree(denali);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* driver exit point */
|
||||||
|
static void denali_pci_remove(struct pci_dev *dev)
|
||||||
|
{
|
||||||
|
struct denali_nand_info *denali = pci_get_drvdata(dev);
|
||||||
|
|
||||||
|
denali_remove(denali);
|
||||||
|
iounmap(denali->flash_reg);
|
||||||
|
iounmap(denali->flash_mem);
|
||||||
|
pci_release_regions(dev);
|
||||||
|
pci_disable_device(dev);
|
||||||
|
pci_set_drvdata(dev, NULL);
|
||||||
|
kfree(denali);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pci_driver denali_pci_driver = {
|
||||||
|
.name = DENALI_NAND_NAME,
|
||||||
|
.id_table = denali_pci_ids,
|
||||||
|
.probe = denali_pci_probe,
|
||||||
|
.remove = denali_pci_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __devinit denali_init_pci(void)
|
||||||
|
{
|
||||||
|
pr_info("Spectra MTD driver built on %s @ %s\n", __DATE__, __TIME__);
|
||||||
|
return pci_register_driver(&denali_pci_driver);
|
||||||
|
}
|
||||||
|
module_init(denali_init_pci);
|
||||||
|
|
||||||
|
static void __devexit denali_exit_pci(void)
|
||||||
|
{
|
||||||
|
pci_unregister_driver(&denali_pci_driver);
|
||||||
|
}
|
||||||
|
module_exit(denali_exit_pci);
|
Loading…
Add table
Add a link
Reference in a new issue