diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/ps2ser.c | 31 | ||||
-rw-r--r-- | drivers/misc/fsl_law.c | 65 | ||||
-rw-r--r-- | drivers/mtd/nand/fsl_upm.c | 128 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 46 |
4 files changed, 158 insertions, 112 deletions
diff --git a/drivers/input/ps2ser.c b/drivers/input/ps2ser.c index 4e304f7..c1741ea 100644 --- a/drivers/input/ps2ser.c +++ b/drivers/input/ps2ser.c @@ -49,7 +49,8 @@ DECLARE_GLOBAL_DATA_PTR; #error CONFIG_PS2SERIAL must be in 1 ... 6 #endif -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) #if CONFIG_PS2SERIAL == 1 #define COM_BASE (CFG_CCSRBAR+0x4500) @@ -65,7 +66,9 @@ static int ps2ser_getc_hw(void); static void ps2ser_interrupt(void *dev_id); extern struct serial_state rs_table[]; /* in serial.c */ -#if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8555) +#if !defined(CONFIG_MPC5xxx) && !defined(CONFIG_MPC8540) && \ + !defined(CONFIG_MPC8541) && !defined(CONFIG_MPC8548) && \ + !defined(CONFIG_MPC8555) static struct serial_state *state; #endif @@ -120,7 +123,8 @@ int ps2ser_init(void) return (0); } -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) int ps2ser_init(void) { NS16550_t com_port = (NS16550_t)COM_BASE; @@ -186,7 +190,8 @@ void ps2ser_putc(int chr) { #ifdef CONFIG_MPC5xxx volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) NS16550_t com_port = (NS16550_t)COM_BASE; #endif #ifdef DEBUG @@ -197,7 +202,8 @@ void ps2ser_putc(int chr) while (!(psc->psc_status & PSC_SR_TXRDY)); psc->psc_buffer_8 = chr; -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) while ((com_port->lsr & LSR_THRE) == 0); com_port->thr = chr; #else @@ -211,7 +217,8 @@ static int ps2ser_getc_hw(void) { #ifdef CONFIG_MPC5xxx volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) NS16550_t com_port = (NS16550_t)COM_BASE; #endif int res = -1; @@ -220,7 +227,8 @@ static int ps2ser_getc_hw(void) if (psc->psc_status & PSC_SR_RXRDY) { res = (psc->psc_buffer_8); } -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) if (com_port->lsr & LSR_DR) { res = com_port->rbr; } @@ -279,7 +287,8 @@ static void ps2ser_interrupt(void *dev_id) { #ifdef CONFIG_MPC5xxx volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE; -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) NS16550_t com_port = (NS16550_t)COM_BASE; #endif int chr; @@ -289,7 +298,8 @@ static void ps2ser_interrupt(void *dev_id) chr = ps2ser_getc_hw(); #ifdef CONFIG_MPC5xxx status = psc->psc_status; -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) status = com_port->lsr; #else status = ps2ser_in(UART_IIR); @@ -305,7 +315,8 @@ static void ps2ser_interrupt(void *dev_id) } #ifdef CONFIG_MPC5xxx } while (status & PSC_SR_RXRDY); -#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || defined(CONFIG_MPC8555) +#elif defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8548) || defined(CONFIG_MPC8555) } while (status & LSR_DR); #else } while (status & UART_IIR_RDI); diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c index dca6a4d..48ece4f 100644 --- a/drivers/misc/fsl_law.c +++ b/drivers/misc/fsl_law.c @@ -27,8 +27,22 @@ #include <asm/fsl_law.h> #include <asm/io.h> +DECLARE_GLOBAL_DATA_PTR; + #define LAWAR_EN 0x80000000 -#define FSL_HW_NUM_LAWS 10 /* number of LAWs in the hw implementation */ +/* number of LAWs in the hw implementation */ +#if defined(CONFIG_MPC8540) || defined(CONFIG_MPC8541) || \ + defined(CONFIG_MPC8560) || defined(CONFIG_MPC8555) +#define FSL_HW_NUM_LAWS 8 +#elif defined(CONFIG_MPC8548) || defined(CONFIG_MPC8544) || \ + defined(CONFIG_MPC8568) || \ + defined(CONFIG_MPC8641) || defined(CONFIG_MPC8610) +#define FSL_HW_NUM_LAWS 10 +#elif defined(CONFIG_MPC8572) +#define FSL_HW_NUM_LAWS 12 +#else +#error FSL_HW_NUM_LAWS not defined for this platform +#endif void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) { @@ -36,18 +50,53 @@ void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) volatile u32 *lawbar = base + 8 * idx; volatile u32 *lawar = base + 8 * idx + 2; + gd->used_laws |= (1 << idx); + out_be32(lawbar, addr >> 12); out_be32(lawar, LAWAR_EN | ((u32)id << 20) | (u32)sz); return ; } +int set_next_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + u32 idx = ffz(gd->used_laws); + + if (idx >= FSL_HW_NUM_LAWS) + return -1; + + set_law(idx, addr, sz, id); + + return idx; +} + +int set_last_law(phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + u32 idx; + + /* we have no LAWs free */ + if (gd->used_laws == -1) + return -1; + + /* grab the last free law */ + idx = __ilog2(~(gd->used_laws)); + + if (idx >= FSL_HW_NUM_LAWS) + return -1; + + set_law(idx, addr, sz, id); + + return idx; +} + void disable_law(u8 idx) { volatile u32 *base = (volatile u32 *)(CFG_IMMR + 0xc08); volatile u32 *lawbar = base + 8 * idx; volatile u32 *lawar = base + 8 * idx + 2; + gd->used_laws &= ~(1 << idx); + out_be32(lawar, 0); out_be32(lawbar, 0); @@ -75,14 +124,16 @@ void print_laws(void) void init_laws(void) { int i; - u8 law_idx = 0; - for (i = 0; i < num_law_entries; i++) { - if (law_table[i].index != -1) - law_idx = law_table[i].index; + gd->used_laws = ~((1 << FSL_HW_NUM_LAWS) - 1); - set_law(law_idx++, law_table[i].addr, - law_table[i].size, law_table[i].trgt_id); + for (i = 0; i < num_law_entries; i++) { + if (law_table[i].index == -1) + set_next_law(law_table[i].addr, law_table[i].size, + law_table[i].trgt_id); + else + set_law(law_table[i].index, law_table[i].addr, + law_table[i].size, law_table[i].trgt_id); } return ; diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c index 5cc410a..67ae9c8 100644 --- a/drivers/mtd/nand/fsl_upm.c +++ b/drivers/mtd/nand/fsl_upm.c @@ -20,112 +20,83 @@ #include <linux/mtd/fsl_upm.h> #include <nand.h> -#define FSL_UPM_MxMR_OP_NO (0 << 28) /* normal operation */ -#define FSL_UPM_MxMR_OP_WA (1 << 28) /* write array */ -#define FSL_UPM_MxMR_OP_RA (2 << 28) /* read array */ -#define FSL_UPM_MxMR_OP_RP (3 << 28) /* run pattern */ +static int fsl_upm_in_pattern; static void fsl_upm_start_pattern(struct fsl_upm *upm, u32 pat_offset) { - out_be32(upm->mxmr, FSL_UPM_MxMR_OP_RP | pat_offset); + clrsetbits_be32(upm->mxmr, MxMR_MAD_MSK, MxMR_OP_RUNP | pat_offset); } static void fsl_upm_end_pattern(struct fsl_upm *upm) { - out_be32(upm->mxmr, FSL_UPM_MxMR_OP_NO); - while (in_be32(upm->mxmr) != FSL_UPM_MxMR_OP_NO) + clrbits_be32(upm->mxmr, MxMR_OP_RUNP); + + while (in_be32(upm->mxmr) & MxMR_OP_RUNP) eieio(); } static void fsl_upm_run_pattern(struct fsl_upm *upm, int width, u32 cmd) { - out_be32(upm->mar, cmd << (32 - width * 8)); - out_8(upm->io_addr, 0x0); -} - -static void fsl_upm_setup(struct fsl_upm *upm) -{ - int i; - - /* write upm array */ - out_be32(upm->mxmr, FSL_UPM_MxMR_OP_WA); - - for (i = 0; i < 64; i++) { - out_be32(upm->mdr, upm->array[i]); + out_be32(upm->mar, cmd << (32 - width)); + switch (width) { + case 8: out_8(upm->io_addr, 0x0); + break; + case 16: + out_be16(upm->io_addr, 0x0); + break; + case 32: + out_be32(upm->io_addr, 0x0); + break; } - - /* normal operation */ - out_be32(upm->mxmr, FSL_UPM_MxMR_OP_NO); - while (in_be32(upm->mxmr) != FSL_UPM_MxMR_OP_NO) - eieio(); } -static void fun_cmdfunc(struct mtd_info *mtd, unsigned command, int column, - int page_addr) +static void nand_hwcontrol (struct mtd_info *mtd, int cmd) { struct nand_chip *chip = mtd->priv; struct fsl_upm_nand *fun = chip->priv; - fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); - - if (command == NAND_CMD_SEQIN) { - int readcmd; - - if (column >= mtd->oobblock) { - /* OOB area */ - column -= mtd->oobblock; - readcmd = NAND_CMD_READOOB; - } else if (column < 256) { - /* First 256 bytes --> READ0 */ - readcmd = NAND_CMD_READ0; - } else { - column -= 256; - readcmd = NAND_CMD_READ1; - } - fsl_upm_run_pattern(&fun->upm, fun->width, readcmd); + switch (cmd) { + case NAND_CTL_SETCLE: + fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); + fsl_upm_in_pattern++; + break; + case NAND_CTL_SETALE: + fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); + fsl_upm_in_pattern++; + break; + case NAND_CTL_CLRCLE: + case NAND_CTL_CLRALE: + fsl_upm_end_pattern(&fun->upm); + fsl_upm_in_pattern--; + break; } +} - fsl_upm_run_pattern(&fun->upm, fun->width, command); - - fsl_upm_end_pattern(&fun->upm); - - fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); - - if (column != -1) - fsl_upm_run_pattern(&fun->upm, fun->width, column); +static void nand_write_byte(struct mtd_info *mtd, u_char byte) +{ + struct nand_chip *chip = mtd->priv; - if (page_addr != -1) { - fsl_upm_run_pattern(&fun->upm, fun->width, page_addr); - fsl_upm_run_pattern(&fun->upm, fun->width, - (page_addr >> 8) & 0xFF); - if (chip->chipsize > (32 << 20)) { - fsl_upm_run_pattern(&fun->upm, fun->width, - (page_addr >> 16) & 0x0f); - } - } + if (fsl_upm_in_pattern) { + struct fsl_upm_nand *fun = chip->priv; - fsl_upm_end_pattern(&fun->upm); + fsl_upm_run_pattern(&fun->upm, fun->width, byte); - if (fun->wait_pattern) { /* * Some boards/chips needs this. At least on MPC8360E-RDK we * need it. Probably weird chip, because I don't see any need * for this on MPC8555E + Samsung K9F1G08U0A. Usually here are * 0-2 unexpected busy states per block read. */ - while (!fun->dev_ready()) - debug("unexpected busy state\n"); + if (fun->wait_pattern) { + while (!fun->dev_ready()) + debug("unexpected busy state\n"); + } + } else { + out_8(chip->IO_ADDR_W, byte); } } -static void nand_write_byte(struct mtd_info *mtd, u_char byte) -{ - struct nand_chip *chip = mtd->priv; - - out_8(chip->IO_ADDR_W, byte); -} - static u8 nand_read_byte(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; @@ -164,10 +135,6 @@ static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len) return 0; } -static void nand_hwcontrol(struct mtd_info *mtd, int cmd) -{ -} - static int nand_dev_ready(struct mtd_info *mtd) { struct nand_chip *chip = mtd->priv; @@ -178,23 +145,20 @@ static int nand_dev_ready(struct mtd_info *mtd) int fsl_upm_nand_init(struct nand_chip *chip, struct fsl_upm_nand *fun) { - /* yet only 8 bit accessors implemented */ - if (fun->width != 1) + if (fun->width != 8 && fun->width != 16 && fun->width != 32) return -ENOSYS; - fsl_upm_setup(&fun->upm); - chip->priv = fun; chip->chip_delay = fun->chip_delay; chip->eccmode = NAND_ECC_SOFT; - chip->cmdfunc = fun_cmdfunc; chip->hwcontrol = nand_hwcontrol; chip->read_byte = nand_read_byte; chip->read_buf = nand_read_buf; chip->write_byte = nand_write_byte; chip->write_buf = nand_write_buf; chip->verify_buf = nand_verify_buf; - chip->dev_ready = nand_dev_ready; + if (fun->dev_ready) + chip->dev_ready = nand_dev_ready; return 0; } diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5aef31c..740d3fc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -113,18 +113,22 @@ static struct nand_oobinfo nand_oob_64 = { .oobfree = { {2, 38} } }; -/* This is used for padding purposes in nand_write_oob */ -static u_char ffchars[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +static struct nand_oobinfo nand_oob_128 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 48, + .eccpos = { + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}, + .oobfree = { {2, 78} } }; +/* This is used for padding purposes in nand_write_oob */ +static u_char *ffchars; + /* * NAND low-level MTD interface functions */ @@ -193,6 +197,10 @@ static void nand_release_device (struct mtd_info *mtd) { struct nand_chip *this = mtd->priv; this->select_chip(mtd, -1); /* De-select the NAND device */ + if (ffchars) { + kfree(ffchars); + ffchars = NULL; + } } #endif @@ -891,7 +899,7 @@ static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int pa u_char *oob_buf, struct nand_oobinfo *oobsel, int cached) { int i, status; - u_char ecc_code[32]; + u_char ecc_code[NAND_MAX_OOBSIZE]; int eccmode = oobsel->useecc ? this->eccmode : NAND_ECC_NONE; uint *oob_config = oobsel->eccpos; int datidx = 0, eccidx = 0, eccsteps = this->eccsteps; @@ -1112,8 +1120,8 @@ static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, int read = 0, oob = 0, ecc_status = 0, ecc_failed = 0; struct nand_chip *this = mtd->priv; u_char *data_poi, *oob_data = oob_buf; - u_char ecc_calc[32]; - u_char ecc_code[32]; + u_char ecc_calc[NAND_MAX_OOBSIZE]; + u_char ecc_code[NAND_MAX_OOBSIZE]; int eccmode, eccsteps; unsigned *oob_config; int datidx; @@ -1811,6 +1819,15 @@ static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len, size_t * if (NAND_MUST_PAD(this)) { /* Write out desired data */ this->cmdfunc (mtd, NAND_CMD_SEQIN, mtd->oobblock, page & this->pagemask); + if (!ffchars) { + if (!(ffchars = kmalloc (mtd->oobsize, GFP_KERNEL))) { + DEBUG (MTD_DEBUG_LEVEL0, "nand_write_oob: " + "No memory for padding array, need %d bytes", mtd->oobsize); + ret = -ENOMEM; + goto out; + } + memset(ffchars, 0xff, mtd->oobsize); + } /* prepad 0xff for partial programming */ this->write_buf(mtd, ffchars, column); /* write data */ @@ -2479,6 +2496,9 @@ int nand_scan (struct mtd_info *mtd, int maxchips) case 64: this->autooob = &nand_oob_64; break; + case 128: + this->autooob = &nand_oob_128; + break; default: printk (KERN_WARNING "No oob scheme defined for oobsize %d\n", mtd->oobsize); |