aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-u300/clock.c6
-rw-r--r--arch/arm/mach-u300/core.c47
-rw-r--r--arch/arm/mach-u300/include/mach/u300-regs.h2
-rw-r--r--arch/arm/plat-pxa/include/plat/pxa3xx_nand.h18
-rw-r--r--arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h97
-rw-r--r--arch/powerpc/Kconfig7
-rw-r--r--arch/powerpc/include/asm/fsl_lbc.h34
-rw-r--r--arch/powerpc/sysdev/fsl_lbc.c244
8 files changed, 397 insertions, 58 deletions
diff --git a/arch/arm/mach-u300/clock.c b/arch/arm/mach-u300/clock.c
index 60acf9e708ae..7458fc6df5c6 100644
--- a/arch/arm/mach-u300/clock.c
+++ b/arch/arm/mach-u300/clock.c
@@ -66,7 +66,7 @@ static DEFINE_SPINLOCK(syscon_resetreg_lock);
66 * AMBA bus 66 * AMBA bus
67 * | 67 * |
68 * +- CPU 68 * +- CPU
69 * +- NANDIF NAND Flash interface 69 * +- FSMC NANDIF NAND Flash interface
70 * +- SEMI Shared Memory interface 70 * +- SEMI Shared Memory interface
71 * +- ISP Image Signal Processor (U335 only) 71 * +- ISP Image Signal Processor (U335 only)
72 * +- CDS (U335 only) 72 * +- CDS (U335 only)
@@ -726,7 +726,7 @@ static struct clk cpu_clk = {
726}; 726};
727 727
728static struct clk nandif_clk = { 728static struct clk nandif_clk = {
729 .name = "NANDIF", 729 .name = "FSMC",
730 .parent = &amba_clk, 730 .parent = &amba_clk,
731 .hw_ctrld = false, 731 .hw_ctrld = false,
732 .reset = true, 732 .reset = true,
@@ -1259,7 +1259,7 @@ static struct clk_lookup lookups[] = {
1259 /* Connected directly to the AMBA bus */ 1259 /* Connected directly to the AMBA bus */
1260 DEF_LOOKUP("amba", &amba_clk), 1260 DEF_LOOKUP("amba", &amba_clk),
1261 DEF_LOOKUP("cpu", &cpu_clk), 1261 DEF_LOOKUP("cpu", &cpu_clk),
1262 DEF_LOOKUP("fsmc", &nandif_clk), 1262 DEF_LOOKUP("fsmc-nand", &nandif_clk),
1263 DEF_LOOKUP("semi", &semi_clk), 1263 DEF_LOOKUP("semi", &semi_clk),
1264#ifdef CONFIG_MACH_U300_BS335 1264#ifdef CONFIG_MACH_U300_BS335
1265 DEF_LOOKUP("isp", &isp_clk), 1265 DEF_LOOKUP("isp", &isp_clk),
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index ea41c236be0f..aa53ee22438f 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -21,7 +21,8 @@
21#include <linux/gpio.h> 21#include <linux/gpio.h>
22#include <linux/clk.h> 22#include <linux/clk.h>
23#include <linux/err.h> 23#include <linux/err.h>
24#include <mach/coh901318.h> 24#include <linux/mtd/nand.h>
25#include <linux/mtd/fsmc.h>
25 26
26#include <asm/types.h> 27#include <asm/types.h>
27#include <asm/setup.h> 28#include <asm/setup.h>
@@ -30,6 +31,7 @@
30#include <asm/mach/map.h> 31#include <asm/mach/map.h>
31#include <asm/mach/irq.h> 32#include <asm/mach/irq.h>
32 33
34#include <mach/coh901318.h>
33#include <mach/hardware.h> 35#include <mach/hardware.h>
34#include <mach/syscon.h> 36#include <mach/syscon.h>
35#include <mach/dma_channels.h> 37#include <mach/dma_channels.h>
@@ -285,6 +287,13 @@ static struct resource rtc_resources[] = {
285 */ 287 */
286static struct resource fsmc_resources[] = { 288static struct resource fsmc_resources[] = {
287 { 289 {
290 .name = "nand_data",
291 .start = U300_NAND_CS0_PHYS_BASE,
292 .end = U300_NAND_CS0_PHYS_BASE + SZ_16K - 1,
293 .flags = IORESOURCE_MEM,
294 },
295 {
296 .name = "fsmc_regs",
288 .start = U300_NAND_IF_PHYS_BASE, 297 .start = U300_NAND_IF_PHYS_BASE,
289 .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1, 298 .end = U300_NAND_IF_PHYS_BASE + SZ_4K - 1,
290 .flags = IORESOURCE_MEM, 299 .flags = IORESOURCE_MEM,
@@ -1429,11 +1438,39 @@ static struct platform_device rtc_device = {
1429 .resource = rtc_resources, 1438 .resource = rtc_resources,
1430}; 1439};
1431 1440
1432static struct platform_device fsmc_device = { 1441static struct mtd_partition u300_partitions[] = {
1433 .name = "nandif", 1442 {
1443 .name = "bootrecords",
1444 .offset = 0,
1445 .size = SZ_128K,
1446 },
1447 {
1448 .name = "free",
1449 .offset = SZ_128K,
1450 .size = 8064 * SZ_1K,
1451 },
1452 {
1453 .name = "platform",
1454 .offset = 8192 * SZ_1K,
1455 .size = 253952 * SZ_1K,
1456 },
1457};
1458
1459static struct fsmc_nand_platform_data nand_platform_data = {
1460 .partitions = u300_partitions,
1461 .nr_partitions = ARRAY_SIZE(u300_partitions),
1462 .options = NAND_SKIP_BBTSCAN,
1463 .width = FSMC_NAND_BW8,
1464};
1465
1466static struct platform_device nand_device = {
1467 .name = "fsmc-nand",
1434 .id = -1, 1468 .id = -1,
1435 .num_resources = ARRAY_SIZE(fsmc_resources),
1436 .resource = fsmc_resources, 1469 .resource = fsmc_resources,
1470 .num_resources = ARRAY_SIZE(fsmc_resources),
1471 .dev = {
1472 .platform_data = &nand_platform_data,
1473 },
1437}; 1474};
1438 1475
1439static struct platform_device ave_device = { 1476static struct platform_device ave_device = {
@@ -1465,7 +1502,7 @@ static struct platform_device *platform_devs[] __initdata = {
1465 &keypad_device, 1502 &keypad_device,
1466 &rtc_device, 1503 &rtc_device,
1467 &gpio_device, 1504 &gpio_device,
1468 &fsmc_device, 1505 &nand_device,
1469 &wdog_device, 1506 &wdog_device,
1470 &ave_device 1507 &ave_device
1471}; 1508};
diff --git a/arch/arm/mach-u300/include/mach/u300-regs.h b/arch/arm/mach-u300/include/mach/u300-regs.h
index 56721a0cd2af..8b85df4c8d8f 100644
--- a/arch/arm/mach-u300/include/mach/u300-regs.h
+++ b/arch/arm/mach-u300/include/mach/u300-regs.h
@@ -20,11 +20,9 @@
20 20
21/* NAND Flash CS0 */ 21/* NAND Flash CS0 */
22#define U300_NAND_CS0_PHYS_BASE 0x80000000 22#define U300_NAND_CS0_PHYS_BASE 0x80000000
23#define U300_NAND_CS0_VIRT_BASE 0xff040000
24 23
25/* NFIF */ 24/* NFIF */
26#define U300_NAND_IF_PHYS_BASE 0x9f800000 25#define U300_NAND_IF_PHYS_BASE 0x9f800000
27#define U300_NAND_IF_VIRT_BASE 0xff030000
28 26
29/* AHB Peripherals */ 27/* AHB Peripherals */
30#define U300_AHB_PER_PHYS_BASE 0xa0000000 28#define U300_AHB_PER_PHYS_BASE 0xa0000000
diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 3478eae32d8a..01a8448e471c 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -30,15 +30,15 @@ struct pxa3xx_nand_cmdset {
30}; 30};
31 31
32struct pxa3xx_nand_flash { 32struct pxa3xx_nand_flash {
33 const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ 33 uint32_t chip_id;
34 const struct pxa3xx_nand_cmdset *cmdset; 34 unsigned int page_per_block; /* Pages per block (PG_PER_BLK) */
35 35 unsigned int page_size; /* Page size in bytes (PAGE_SZ) */
36 uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ 36 unsigned int flash_width; /* Width of Flash memory (DWIDTH_M) */
37 uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ 37 unsigned int dfc_width; /* Width of flash controller(DWIDTH_C) */
38 uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ 38 unsigned int num_blocks; /* Number of physical blocks in Flash */
39 uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ 39
40 uint32_t num_blocks; /* Number of physical blocks in Flash */ 40 struct pxa3xx_nand_cmdset *cmdset; /* NAND command set */
41 uint32_t chip_id; 41 struct pxa3xx_nand_timing *timing; /* NAND Flash timing */
42}; 42};
43 43
44struct pxa3xx_nand_platform_data { 44struct pxa3xx_nand_platform_data {
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
new file mode 100644
index 000000000000..5325084d5c48
--- /dev/null
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
@@ -0,0 +1,97 @@
1#ifndef __BCM963XX_TAG_H
2#define __BCM963XX_TAG_H
3
4#define TAGVER_LEN 4 /* Length of Tag Version */
5#define TAGLAYOUT_LEN 4 /* Length of FlashLayoutVer */
6#define SIG1_LEN 20 /* Company Signature 1 Length */
7#define SIG2_LEN 14 /* Company Signature 2 Lenght */
8#define BOARDID_LEN 16 /* Length of BoardId */
9#define ENDIANFLAG_LEN 2 /* Endian Flag Length */
10#define CHIPID_LEN 6 /* Chip Id Length */
11#define IMAGE_LEN 10 /* Length of Length Field */
12#define ADDRESS_LEN 12 /* Length of Address field */
13#define DUALFLAG_LEN 2 /* Dual Image flag Length */
14#define INACTIVEFLAG_LEN 2 /* Inactie Flag Length */
15#define RSASIG_LEN 20 /* Length of RSA Signature in tag */
16#define TAGINFO1_LEN 30 /* Length of vendor information field1 in tag */
17#define FLASHLAYOUTVER_LEN 4 /* Length of Flash Layout Version String tag */
18#define TAGINFO2_LEN 16 /* Length of vendor information field2 in tag */
19#define CRC_LEN 4 /* Length of CRC in bytes */
20#define ALTTAGINFO_LEN 54 /* Alternate length for vendor information; Pirelli */
21
22#define NUM_PIRELLI 2
23#define IMAGETAG_CRC_START 0xFFFFFFFF
24
25#define PIRELLI_BOARDS { \
26 "AGPF-S0", \
27 "DWV-S0", \
28}
29
30/*
31 * The broadcom firmware assumes the rootfs starts the image,
32 * therefore uses the rootfs start (flash_image_address)
33 * to determine where to flash the image. Since we have the kernel first
34 * we have to give it the kernel address, but the crc uses the length
35 * associated with this address (root_length), which is added to the kernel
36 * length (kernel_length) to determine the length of image to flash and thus
37 * needs to be rootfs + deadcode (jffs2 EOF marker)
38*/
39
40struct bcm_tag {
41 /* 0-3: Version of the image tag */
42 char tag_version[TAGVER_LEN];
43 /* 4-23: Company Line 1 */
44 char sig_1[SIG1_LEN];
45 /* 24-37: Company Line 2 */
46 char sig_2[SIG2_LEN];
47 /* 38-43: Chip this image is for */
48 char chip_id[CHIPID_LEN];
49 /* 44-59: Board name */
50 char board_id[BOARDID_LEN];
51 /* 60-61: Map endianness -- 1 BE 0 LE */
52 char big_endian[ENDIANFLAG_LEN];
53 /* 62-71: Total length of image */
54 char total_length[IMAGE_LEN];
55 /* 72-83: Address in memory of CFE */
56 char cfe__address[ADDRESS_LEN];
57 /* 84-93: Size of CFE */
58 char cfe_length[IMAGE_LEN];
59 /* 94-105: Address in memory of image start
60 * (kernel for OpenWRT, rootfs for stock firmware)
61 */
62 char flash_image_start[ADDRESS_LEN];
63 /* 106-115: Size of rootfs */
64 char root_length[IMAGE_LEN];
65 /* 116-127: Address in memory of kernel */
66 char kernel_address[ADDRESS_LEN];
67 /* 128-137: Size of kernel */
68 char kernel_length[IMAGE_LEN];
69 /* 138-139: Unused at the moment */
70 char dual_image[DUALFLAG_LEN];
71 /* 140-141: Unused at the moment */
72 char inactive_flag[INACTIVEFLAG_LEN];
73 /* 142-161: RSA Signature (not used; some vendors may use this) */
74 char rsa_signature[RSASIG_LEN];
75 /* 162-191: Compilation and related information (not used in OpenWrt) */
76 char information1[TAGINFO1_LEN];
77 /* 192-195: Version flash layout */
78 char flash_layout_ver[FLASHLAYOUTVER_LEN];
79 /* 196-199: kernel+rootfs CRC32 */
80 char fskernel_crc[CRC_LEN];
81 /* 200-215: Unused except on Alice Gate where is is information */
82 char information2[TAGINFO2_LEN];
83 /* 216-219: CRC32 of image less imagetag (kernel for Alice Gate) */
84 char image_crc[CRC_LEN];
85 /* 220-223: CRC32 of rootfs partition */
86 char rootfs_crc[CRC_LEN];
87 /* 224-227: CRC32 of kernel partition */
88 char kernel_crc[CRC_LEN];
89 /* 228-235: Unused at present */
90 char reserved1[8];
91 /* 236-239: CRC32 of header excluding tagVersion */
92 char header_crc[CRC_LEN];
93 /* 240-255: Unused at present */
94 char reserved2[16];
95};
96
97#endif /* __BCM63XX_TAG_H */
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 4b1e521d966f..29158913a66b 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -688,9 +688,12 @@ config 4xx_SOC
688 bool 688 bool
689 689
690config FSL_LBC 690config FSL_LBC
691 bool 691 bool "Freescale Local Bus support"
692 depends on FSL_SOC
692 help 693 help
693 Freescale Localbus support 694 Enables reporting of errors from the Freescale local bus
695 controller. Also contains some common code used by
696 drivers for specific local bus peripherals.
694 697
695config FSL_GTM 698config FSL_GTM
696 bool 699 bool
diff --git a/arch/powerpc/include/asm/fsl_lbc.h b/arch/powerpc/include/asm/fsl_lbc.h
index 1b5a21041f9b..5c1bf3466749 100644
--- a/arch/powerpc/include/asm/fsl_lbc.h
+++ b/arch/powerpc/include/asm/fsl_lbc.h
@@ -1,9 +1,10 @@
1/* Freescale Local Bus Controller 1/* Freescale Local Bus Controller
2 * 2 *
3 * Copyright (c) 2006-2007 Freescale Semiconductor 3 * Copyright © 2006-2007, 2010 Freescale Semiconductor
4 * 4 *
5 * Authors: Nick Spence <nick.spence@freescale.com>, 5 * Authors: Nick Spence <nick.spence@freescale.com>,
6 * Scott Wood <scottwood@freescale.com> 6 * Scott Wood <scottwood@freescale.com>
7 * Jack Lan <jack.lan@freescale.com>
7 * 8 *
8 * This program is free software; you can redistribute it and/or modify 9 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 10 * it under the terms of the GNU General Public License as published by
@@ -26,6 +27,8 @@
26#include <linux/compiler.h> 27#include <linux/compiler.h>
27#include <linux/types.h> 28#include <linux/types.h>
28#include <linux/io.h> 29#include <linux/io.h>
30#include <linux/device.h>
31#include <linux/spinlock.h>
29 32
30struct fsl_lbc_bank { 33struct fsl_lbc_bank {
31 __be32 br; /**< Base Register */ 34 __be32 br; /**< Base Register */
@@ -125,13 +128,23 @@ struct fsl_lbc_regs {
125#define LTESR_ATMW 0x00800000 128#define LTESR_ATMW 0x00800000
126#define LTESR_ATMR 0x00400000 129#define LTESR_ATMR 0x00400000
127#define LTESR_CS 0x00080000 130#define LTESR_CS 0x00080000
131#define LTESR_UPM 0x00000002
128#define LTESR_CC 0x00000001 132#define LTESR_CC 0x00000001
129#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC) 133#define LTESR_NAND_MASK (LTESR_FCT | LTESR_PAR | LTESR_CC)
134#define LTESR_MASK (LTESR_BM | LTESR_FCT | LTESR_PAR | LTESR_WP \
135 | LTESR_ATMW | LTESR_ATMR | LTESR_CS | LTESR_UPM \
136 | LTESR_CC)
137#define LTESR_CLEAR 0xFFFFFFFF
138#define LTECCR_CLEAR 0xFFFFFFFF
139#define LTESR_STATUS LTESR_MASK
140#define LTEIR_ENABLE LTESR_MASK
141#define LTEDR_ENABLE 0x00000000
130 __be32 ltedr; /**< Transfer Error Disable Register */ 142 __be32 ltedr; /**< Transfer Error Disable Register */
131 __be32 lteir; /**< Transfer Error Interrupt Register */ 143 __be32 lteir; /**< Transfer Error Interrupt Register */
132 __be32 lteatr; /**< Transfer Error Attributes Register */ 144 __be32 lteatr; /**< Transfer Error Attributes Register */
133 __be32 ltear; /**< Transfer Error Address Register */ 145 __be32 ltear; /**< Transfer Error Address Register */
134 u8 res6[0xC]; 146 __be32 lteccr; /**< Transfer Error ECC Register */
147 u8 res6[0x8];
135 __be32 lbcr; /**< Configuration Register */ 148 __be32 lbcr; /**< Configuration Register */
136#define LBCR_LDIS 0x80000000 149#define LBCR_LDIS 0x80000000
137#define LBCR_LDIS_SHIFT 31 150#define LBCR_LDIS_SHIFT 31
@@ -235,6 +248,7 @@ struct fsl_upm {
235 int width; 248 int width;
236}; 249};
237 250
251extern u32 fsl_lbc_addr(phys_addr_t addr_base);
238extern int fsl_lbc_find(phys_addr_t addr_base); 252extern int fsl_lbc_find(phys_addr_t addr_base);
239extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm); 253extern int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm);
240 254
@@ -265,7 +279,23 @@ static inline void fsl_upm_end_pattern(struct fsl_upm *upm)
265 cpu_relax(); 279 cpu_relax();
266} 280}
267 281
282/* overview of the fsl lbc controller */
283
284struct fsl_lbc_ctrl {
285 /* device info */
286 struct device *dev;
287 struct fsl_lbc_regs __iomem *regs;
288 int irq;
289 wait_queue_head_t irq_wait;
290 spinlock_t lock;
291 void *nand;
292
293 /* status read from LTESR by irq handler */
294 unsigned int irq_status;
295};
296
268extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, 297extern int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base,
269 u32 mar); 298 u32 mar);
299extern struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
270 300
271#endif /* __ASM_FSL_LBC_H */ 301#endif /* __ASM_FSL_LBC_H */
diff --git a/arch/powerpc/sysdev/fsl_lbc.c b/arch/powerpc/sysdev/fsl_lbc.c
index dceb8d1a843d..4fcb5a4e60dd 100644
--- a/arch/powerpc/sysdev/fsl_lbc.c
+++ b/arch/powerpc/sysdev/fsl_lbc.c
@@ -1,9 +1,12 @@
1/* 1/*
2 * Freescale LBC and UPM routines. 2 * Freescale LBC and UPM routines.
3 * 3 *
4 * Copyright (c) 2007-2008 MontaVista Software, Inc. 4 * Copyright © 2007-2008 MontaVista Software, Inc.
5 * Copyright © 2010 Freescale Semiconductor
5 * 6 *
6 * Author: Anton Vorontsov <avorontsov@ru.mvista.com> 7 * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
8 * Author: Jack Lan <Jack.Lan@freescale.com>
9 * Author: Roy Zang <tie-fei.zang@freescale.com>
7 * 10 *
8 * This program is free software; you can redistribute it and/or modify 11 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by 12 * it under the terms of the GNU General Public License as published by
@@ -19,39 +22,37 @@
19#include <linux/types.h> 22#include <linux/types.h>
20#include <linux/io.h> 23#include <linux/io.h>
21#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/slab.h>
26#include <linux/platform_device.h>
27#include <linux/interrupt.h>
28#include <linux/mod_devicetable.h>
22#include <asm/prom.h> 29#include <asm/prom.h>
23#include <asm/fsl_lbc.h> 30#include <asm/fsl_lbc.h>
24 31
25static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock); 32static spinlock_t fsl_lbc_lock = __SPIN_LOCK_UNLOCKED(fsl_lbc_lock);
26static struct fsl_lbc_regs __iomem *fsl_lbc_regs; 33struct fsl_lbc_ctrl *fsl_lbc_ctrl_dev;
34EXPORT_SYMBOL(fsl_lbc_ctrl_dev);
27 35
28static char __initdata *compat_lbc[] = { 36/**
29 "fsl,pq2-localbus", 37 * fsl_lbc_addr - convert the base address
30 "fsl,pq2pro-localbus", 38 * @addr_base: base address of the memory bank
31 "fsl,pq3-localbus", 39 *
32 "fsl,elbc", 40 * This function converts a base address of lbc into the right format for the
33}; 41 * BR register. If the SOC has eLBC then it returns 32bit physical address
34 42 * else it convers a 34bit local bus physical address to correct format of
35static int __init fsl_lbc_init(void) 43 * 32bit address for BR register (Example: MPC8641).
44 */
45u32 fsl_lbc_addr(phys_addr_t addr_base)
36{ 46{
37 struct device_node *lbus; 47 struct device_node *np = fsl_lbc_ctrl_dev->dev->of_node;
38 int i; 48 u32 addr = addr_base & 0xffff8000;
39 49
40 for (i = 0; i < ARRAY_SIZE(compat_lbc); i++) { 50 if (of_device_is_compatible(np, "fsl,elbc"))
41 lbus = of_find_compatible_node(NULL, NULL, compat_lbc[i]); 51 return addr;
42 if (lbus)
43 goto found;
44 }
45 return -ENODEV;
46 52
47found: 53 return addr | ((addr_base & 0x300000000ull) >> 19);
48 fsl_lbc_regs = of_iomap(lbus, 0);
49 of_node_put(lbus);
50 if (!fsl_lbc_regs)
51 return -ENOMEM;
52 return 0;
53} 54}
54arch_initcall(fsl_lbc_init); 55EXPORT_SYMBOL(fsl_lbc_addr);
55 56
56/** 57/**
57 * fsl_lbc_find - find Localbus bank 58 * fsl_lbc_find - find Localbus bank
@@ -65,15 +66,17 @@ arch_initcall(fsl_lbc_init);
65int fsl_lbc_find(phys_addr_t addr_base) 66int fsl_lbc_find(phys_addr_t addr_base)
66{ 67{
67 int i; 68 int i;
69 struct fsl_lbc_regs __iomem *lbc;
68 70
69 if (!fsl_lbc_regs) 71 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
70 return -ENODEV; 72 return -ENODEV;
71 73
72 for (i = 0; i < ARRAY_SIZE(fsl_lbc_regs->bank); i++) { 74 lbc = fsl_lbc_ctrl_dev->regs;
73 __be32 br = in_be32(&fsl_lbc_regs->bank[i].br); 75 for (i = 0; i < ARRAY_SIZE(lbc->bank); i++) {
74 __be32 or = in_be32(&fsl_lbc_regs->bank[i].or); 76 __be32 br = in_be32(&lbc->bank[i].br);
77 __be32 or = in_be32(&lbc->bank[i].or);
75 78
76 if (br & BR_V && (br & or & BR_BA) == addr_base) 79 if (br & BR_V && (br & or & BR_BA) == fsl_lbc_addr(addr_base))
77 return i; 80 return i;
78 } 81 }
79 82
@@ -94,22 +97,27 @@ int fsl_upm_find(phys_addr_t addr_base, struct fsl_upm *upm)
94{ 97{
95 int bank; 98 int bank;
96 __be32 br; 99 __be32 br;
100 struct fsl_lbc_regs __iomem *lbc;
97 101
98 bank = fsl_lbc_find(addr_base); 102 bank = fsl_lbc_find(addr_base);
99 if (bank < 0) 103 if (bank < 0)
100 return bank; 104 return bank;
101 105
102 br = in_be32(&fsl_lbc_regs->bank[bank].br); 106 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
107 return -ENODEV;
108
109 lbc = fsl_lbc_ctrl_dev->regs;
110 br = in_be32(&lbc->bank[bank].br);
103 111
104 switch (br & BR_MSEL) { 112 switch (br & BR_MSEL) {
105 case BR_MS_UPMA: 113 case BR_MS_UPMA:
106 upm->mxmr = &fsl_lbc_regs->mamr; 114 upm->mxmr = &lbc->mamr;
107 break; 115 break;
108 case BR_MS_UPMB: 116 case BR_MS_UPMB:
109 upm->mxmr = &fsl_lbc_regs->mbmr; 117 upm->mxmr = &lbc->mbmr;
110 break; 118 break;
111 case BR_MS_UPMC: 119 case BR_MS_UPMC:
112 upm->mxmr = &fsl_lbc_regs->mcmr; 120 upm->mxmr = &lbc->mcmr;
113 break; 121 break;
114 default: 122 default:
115 return -EINVAL; 123 return -EINVAL;
@@ -148,9 +156,12 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
148 int ret = 0; 156 int ret = 0;
149 unsigned long flags; 157 unsigned long flags;
150 158
159 if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
160 return -ENODEV;
161
151 spin_lock_irqsave(&fsl_lbc_lock, flags); 162 spin_lock_irqsave(&fsl_lbc_lock, flags);
152 163
153 out_be32(&fsl_lbc_regs->mar, mar); 164 out_be32(&fsl_lbc_ctrl_dev->regs->mar, mar);
154 165
155 switch (upm->width) { 166 switch (upm->width) {
156 case 8: 167 case 8:
@@ -172,3 +183,166 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
172 return ret; 183 return ret;
173} 184}
174EXPORT_SYMBOL(fsl_upm_run_pattern); 185EXPORT_SYMBOL(fsl_upm_run_pattern);
186
187static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
188{
189 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
190
191 /* clear event registers */
192 setbits32(&lbc->ltesr, LTESR_CLEAR);
193 out_be32(&lbc->lteatr, 0);
194 out_be32(&lbc->ltear, 0);
195 out_be32(&lbc->lteccr, LTECCR_CLEAR);
196 out_be32(&lbc->ltedr, LTEDR_ENABLE);
197
198 /* Enable interrupts for any detected events */
199 out_be32(&lbc->lteir, LTEIR_ENABLE);
200
201 return 0;
202}
203
204/*
205 * NOTE: This interrupt is used to report localbus events of various kinds,
206 * such as transaction errors on the chipselects.
207 */
208
209static irqreturn_t fsl_lbc_ctrl_irq(int irqno, void *data)
210{
211 struct fsl_lbc_ctrl *ctrl = data;
212 struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
213 u32 status;
214
215 status = in_be32(&lbc->ltesr);
216 if (!status)
217 return IRQ_NONE;
218
219 out_be32(&lbc->ltesr, LTESR_CLEAR);
220 out_be32(&lbc->lteatr, 0);
221 out_be32(&lbc->ltear, 0);
222 ctrl->irq_status = status;
223
224 if (status & LTESR_BM)
225 dev_err(ctrl->dev, "Local bus monitor time-out: "
226 "LTESR 0x%08X\n", status);
227 if (status & LTESR_WP)
228 dev_err(ctrl->dev, "Write protect error: "
229 "LTESR 0x%08X\n", status);
230 if (status & LTESR_ATMW)
231 dev_err(ctrl->dev, "Atomic write error: "
232 "LTESR 0x%08X\n", status);
233 if (status & LTESR_ATMR)
234 dev_err(ctrl->dev, "Atomic read error: "
235 "LTESR 0x%08X\n", status);
236 if (status & LTESR_CS)
237 dev_err(ctrl->dev, "Chip select error: "
238 "LTESR 0x%08X\n", status);
239 if (status & LTESR_UPM)
240 ;
241 if (status & LTESR_FCT) {
242 dev_err(ctrl->dev, "FCM command time-out: "
243 "LTESR 0x%08X\n", status);
244 smp_wmb();
245 wake_up(&ctrl->irq_wait);
246 }
247 if (status & LTESR_PAR) {
248 dev_err(ctrl->dev, "Parity or Uncorrectable ECC error: "
249 "LTESR 0x%08X\n", status);
250 smp_wmb();
251 wake_up(&ctrl->irq_wait);
252 }
253 if (status & LTESR_CC) {
254 smp_wmb();
255 wake_up(&ctrl->irq_wait);
256 }
257 if (status & ~LTESR_MASK)
258 dev_err(ctrl->dev, "Unknown error: "
259 "LTESR 0x%08X\n", status);
260 return IRQ_HANDLED;
261}
262
263/*
264 * fsl_lbc_ctrl_probe
265 *
266 * called by device layer when it finds a device matching
267 * one our driver can handled. This code allocates all of
268 * the resources needed for the controller only. The
269 * resources for the NAND banks themselves are allocated
270 * in the chip probe function.
271*/
272
273static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)
274{
275 int ret;
276
277 if (!dev->dev.of_node) {
278 dev_err(&dev->dev, "Device OF-Node is NULL");
279 return -EFAULT;
280 }
281
282 fsl_lbc_ctrl_dev = kzalloc(sizeof(*fsl_lbc_ctrl_dev), GFP_KERNEL);
283 if (!fsl_lbc_ctrl_dev)
284 return -ENOMEM;
285
286 dev_set_drvdata(&dev->dev, fsl_lbc_ctrl_dev);
287
288 spin_lock_init(&fsl_lbc_ctrl_dev->lock);
289 init_waitqueue_head(&fsl_lbc_ctrl_dev->irq_wait);
290
291 fsl_lbc_ctrl_dev->regs = of_iomap(dev->dev.of_node, 0);
292 if (!fsl_lbc_ctrl_dev->regs) {
293 dev_err(&dev->dev, "failed to get memory region\n");
294 ret = -ENODEV;
295 goto err;
296 }
297
298 fsl_lbc_ctrl_dev->irq = irq_of_parse_and_map(dev->dev.of_node, 0);
299 if (fsl_lbc_ctrl_dev->irq == NO_IRQ) {
300 dev_err(&dev->dev, "failed to get irq resource\n");
301 ret = -ENODEV;
302 goto err;
303 }
304
305 fsl_lbc_ctrl_dev->dev = &dev->dev;
306
307 ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
308 if (ret < 0)
309 goto err;
310
311 ret = request_irq(fsl_lbc_ctrl_dev->irq, fsl_lbc_ctrl_irq, 0,
312 "fsl-lbc", fsl_lbc_ctrl_dev);
313 if (ret != 0) {
314 dev_err(&dev->dev, "failed to install irq (%d)\n",
315 fsl_lbc_ctrl_dev->irq);
316 ret = fsl_lbc_ctrl_dev->irq;
317 goto err;
318 }
319
320 return 0;
321
322err:
323 iounmap(fsl_lbc_ctrl_dev->regs);
324 kfree(fsl_lbc_ctrl_dev);
325 return ret;
326}
327
328static const struct of_device_id fsl_lbc_match[] = {
329 { .compatible = "fsl,elbc", },
330 { .compatible = "fsl,pq3-localbus", },
331 { .compatible = "fsl,pq2-localbus", },
332 { .compatible = "fsl,pq2pro-localbus", },
333 {},
334};
335
336static struct platform_driver fsl_lbc_ctrl_driver = {
337 .driver = {
338 .name = "fsl-lbc",
339 .of_match_table = fsl_lbc_match,
340 },
341 .probe = fsl_lbc_ctrl_probe,
342};
343
344static int __init fsl_lbc_init(void)
345{
346 return platform_driver_register(&fsl_lbc_ctrl_driver);
347}
348module_init(fsl_lbc_init);