From 149484e125771614e8df7356bfe98360827d8a8d Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 19 Jul 2011 10:06:09 -0700 Subject: mtd: replace DEBUG() with pr_debug() Start moving away from the MTD_DEBUG_LEVEL messages. The dynamic debugging feature is a generic kernel feature that provides more flexibility. (See Documentation/dynamic-debug-howto.txt) Also fix some punctuation, indentation, and capitalization that went along with the affected lines. Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 727fd9c53199..5a478b51463f 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -145,8 +145,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) if (((major << 8) | minor) < 0x3131) { /* CFI version 1.0 => don't trust bootloc */ - DEBUG(MTD_DEBUG_LEVEL1, - "%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", + pr_debug("%s: JEDEC Vendor ID is 0x%02X Device ID is 0x%02X\n", map->name, cfi->mfr, cfi->id); /* AFAICS all 29LV400 with a bottom boot block have a device ID @@ -166,8 +165,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) * the 8-bit device ID. */ (cfi->mfr == CFI_MFR_MACRONIX)) { - DEBUG(MTD_DEBUG_LEVEL1, - "%s: Macronix MX29LV400C with bottom boot block" + pr_debug("%s: Macronix MX29LV400C with bottom boot block" " detected\n", map->name); extp->TopBottom = 2; /* bottom boot */ } else @@ -178,8 +176,7 @@ static void fixup_amd_bootblock(struct mtd_info *mtd) extp->TopBottom = 2; /* bottom boot */ } - DEBUG(MTD_DEBUG_LEVEL1, - "%s: AMD CFI PRI V%c.%c has no boot block field;" + pr_debug("%s: AMD CFI PRI V%c.%c has no boot block field;" " deduced %s from Device ID\n", map->name, major, minor, extp->TopBottom == 2 ? "bottom" : "top"); } @@ -191,7 +188,7 @@ static void fixup_use_write_buffers(struct mtd_info *mtd) struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; if (cfi->cfiq->BufWriteTimeoutTyp) { - DEBUG(MTD_DEBUG_LEVEL1, "Using buffer write method\n" ); + pr_debug("Using buffer write method\n" ); mtd->write = cfi_amdstd_write_buffers; } } @@ -443,7 +440,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) mtd->writesize = 1; mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; - DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n", + pr_debug("MTD %s(): write buffer size %d\n", __func__, mtd->writebufsize); mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; @@ -1163,7 +1160,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, return ret; } - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", + pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", __func__, adr, datum.x[0] ); /* @@ -1174,7 +1171,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, */ oldd = map_read(map, adr); if (map_word_equal(map, oldd, datum)) { - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): NOP\n", + pr_debug("MTD %s(): NOP\n", __func__); goto op_done; } @@ -1400,7 +1397,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, datum = map_word_load(map, buf); - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", + pr_debug("MTD %s(): WRITE 0x%.8lx(0x%.8lx)\n", __func__, adr, datum.x[0] ); XIP_INVAL_CACHED_RANGE(map, adr, len); @@ -1587,7 +1584,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) return ret; } - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", + pr_debug("MTD %s(): ERASE 0x%.8lx\n", __func__, chip->start ); XIP_INVAL_CACHED_RANGE(map, adr, map->size); @@ -1675,7 +1672,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, return ret; } - DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", + pr_debug("MTD %s(): ERASE 0x%.8lx\n", __func__, adr ); XIP_INVAL_CACHED_RANGE(map, adr, len); @@ -1801,7 +1798,7 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip, goto out_unlock; chip->state = FL_LOCKING; - DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", + pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, @@ -1837,7 +1834,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip, goto out_unlock; chip->state = FL_UNLOCKING; - DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): LOCK 0x%08lx len %d\n", + pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, -- cgit v1.2.3 From 326a368bb0636c63a95f7c14c3512915db5068d1 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 19 Jul 2011 10:06:10 -0700 Subject: mtd: cleanup style on pr_debug messages Signed-off-by: Brian Norris Signed-off-by: Artem Bityutskiy Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 5a478b51463f..e0ee968bdd61 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -440,8 +440,8 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) mtd->writesize = 1; mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; - pr_debug("MTD %s(): write buffer size %d\n", - __func__, mtd->writebufsize); + pr_debug("MTD %s(): write buffer size %d\n", __func__, + mtd->writebufsize); mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; @@ -1798,8 +1798,7 @@ static int do_atmel_lock(struct map_info *map, struct flchip *chip, goto out_unlock; chip->state = FL_LOCKING; - pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", - __func__, adr, len); + pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); @@ -1834,8 +1833,7 @@ static int do_atmel_unlock(struct map_info *map, struct flchip *chip, goto out_unlock; chip->state = FL_UNLOCKING; - pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", - __func__, adr, len); + pr_debug("MTD %s(): LOCK 0x%08lx len %d\n", __func__, adr, len); cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); -- cgit v1.2.3 From 9cc857e0ccaf70da9e26def69f91705b1038cd64 Mon Sep 17 00:00:00 2001 From: "Ira W. Snyder" Date: Fri, 6 Jan 2012 11:29:19 -0800 Subject: mtd: cfi: AMD/Fujitsu compatibles: add panic write support This allows the mtdoops driver to work on flash chips using the AMD/Fujitsu compatible command set. As the code comments note, the locks used throughout the normal code paths in the driver are ignored, so that the chance of writing out the kernel's last messages are maximized. Signed-off-by: Ira W. Snyder Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 240 ++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index e0ee968bdd61..4a5227404614 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -59,6 +59,9 @@ static void cfi_amdstd_resume (struct mtd_info *); static int cfi_amdstd_reboot(struct notifier_block *, unsigned long, void *); static int cfi_amdstd_secsi_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); +static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf); + static void cfi_amdstd_destroy(struct mtd_info *); struct mtd_info *cfi_cmdset_0002(struct map_info *, int); @@ -443,6 +446,7 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) pr_debug("MTD %s(): write buffer size %d\n", __func__, mtd->writebufsize); + mtd->panic_write = cfi_amdstd_panic_write; mtd->reboot_notifier.notifier_call = cfi_amdstd_reboot; if (cfi->cfi_mode==CFI_MODE_CFI){ @@ -1562,6 +1566,242 @@ static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, return 0; } +/* + * Wait for the flash chip to become ready to write data + * + * This is only called during the panic_write() path. When panic_write() + * is called, the kernel is in the process of a panic, and will soon be + * dead. Therefore we don't take any locks, and attempt to get access + * to the chip as soon as possible. + */ +static int cfi_amdstd_panic_wait(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + int retries = 10; + int i; + + /* + * If the driver thinks the chip is idle, and no toggle bits + * are changing, then the chip is actually idle for sure. + */ + if (chip->state == FL_READY && chip_ready(map, adr)) + return 0; + + /* + * Try several times to reset the chip and then wait for it + * to become idle. The upper limit of a few milliseconds of + * delay isn't a big problem: the kernel is dying anyway. It + * is more important to save the messages. + */ + while (retries > 0) { + const unsigned long timeo = (HZ / 1000) + 1; + + /* send the reset command */ + map_write(map, CMD(0xF0), chip->start); + + /* wait for the chip to become ready */ + for (i = 0; i < jiffies_to_usecs(timeo); i++) { + if (chip_ready(map, adr)) + return 0; + + udelay(1); + } + } + + /* the chip never became ready */ + return -EBUSY; +} + +/* + * Write out one word of data to a single flash chip during a kernel panic + * + * This is only called during the panic_write() path. When panic_write() + * is called, the kernel is in the process of a panic, and will soon be + * dead. Therefore we don't take any locks, and attempt to get access + * to the chip as soon as possible. + * + * The implementation of this routine is intentionally similar to + * do_write_oneword(), in order to ease code maintenance. + */ +static int do_panic_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, map_word datum) +{ + const unsigned long uWriteTimeout = (HZ / 1000) + 1; + struct cfi_private *cfi = map->fldrv_priv; + int retry_cnt = 0; + map_word oldd; + int ret = 0; + int i; + + adr += chip->start; + + ret = cfi_amdstd_panic_wait(map, chip, adr); + if (ret) + return ret; + + pr_debug("MTD %s(): PANIC WRITE 0x%.8lx(0x%.8lx)\n", + __func__, adr, datum.x[0]); + + /* + * Check for a NOP for the case when the datum to write is already + * present - it saves time and works around buggy chips that corrupt + * data at other locations when 0xff is written to a location that + * already contains 0xff. + */ + oldd = map_read(map, adr); + if (map_word_equal(map, oldd, datum)) { + pr_debug("MTD %s(): NOP\n", __func__); + goto op_done; + } + + ENABLE_VPP(map); + +retry: + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->device_type, NULL); + cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, cfi->device_type, NULL); + map_write(map, datum, adr); + + for (i = 0; i < jiffies_to_usecs(uWriteTimeout); i++) { + if (chip_ready(map, adr)) + break; + + udelay(1); + } + + if (!chip_good(map, adr, datum)) { + /* reset on all failures. */ + map_write(map, CMD(0xF0), chip->start); + /* FIXME - should have reset delay before continuing */ + + if (++retry_cnt <= MAX_WORD_RETRIES) + goto retry; + + ret = -EIO; + } + +op_done: + DISABLE_VPP(map); + return ret; +} + +/* + * Write out some data during a kernel panic + * + * This is used by the mtdoops driver to save the dying messages from a + * kernel which has panic'd. + * + * This routine ignores all of the locking used throughout the rest of the + * driver, in order to ensure that the data gets written out no matter what + * state this driver (and the flash chip itself) was in when the kernel crashed. + * + * The implementation of this routine is intentionally similar to + * cfi_amdstd_write_words(), in order to ease code maintenance. + */ +static int cfi_amdstd_panic_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + unsigned long ofs, chipstart; + int ret = 0; + int chipnum; + + *retlen = 0; + if (!len) + return 0; + + chipnum = to >> cfi->chipshift; + ofs = to - (chipnum << cfi->chipshift); + chipstart = cfi->chips[chipnum].start; + + /* If it's not bus aligned, do the first byte write */ + if (ofs & (map_bankwidth(map) - 1)) { + unsigned long bus_ofs = ofs & ~(map_bankwidth(map) - 1); + int i = ofs - bus_ofs; + int n = 0; + map_word tmp_buf; + + ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], bus_ofs); + if (ret) + return ret; + + /* Load 'tmp_buf' with old contents of flash */ + tmp_buf = map_read(map, bus_ofs + chipstart); + + /* Number of bytes to copy from buffer */ + n = min_t(int, len, map_bankwidth(map) - i); + + tmp_buf = map_word_load_partial(map, tmp_buf, buf, i, n); + + ret = do_panic_write_oneword(map, &cfi->chips[chipnum], + bus_ofs, tmp_buf); + if (ret) + return ret; + + ofs += n; + buf += n; + (*retlen) += n; + len -= n; + + if (ofs >> cfi->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + } + } + + /* We are now aligned, write as much as possible */ + while (len >= map_bankwidth(map)) { + map_word datum; + + datum = map_word_load(map, buf); + + ret = do_panic_write_oneword(map, &cfi->chips[chipnum], + ofs, datum); + if (ret) + return ret; + + ofs += map_bankwidth(map); + buf += map_bankwidth(map); + (*retlen) += map_bankwidth(map); + len -= map_bankwidth(map); + + if (ofs >> cfi->chipshift) { + chipnum++; + ofs = 0; + if (chipnum == cfi->numchips) + return 0; + + chipstart = cfi->chips[chipnum].start; + } + } + + /* Write the trailing bytes if any */ + if (len & (map_bankwidth(map) - 1)) { + map_word tmp_buf; + + ret = cfi_amdstd_panic_wait(map, &cfi->chips[chipnum], ofs); + if (ret) + return ret; + + tmp_buf = map_read(map, ofs + chipstart); + + tmp_buf = map_word_load_partial(map, tmp_buf, buf, 0, len); + + ret = do_panic_write_oneword(map, &cfi->chips[chipnum], + ofs, tmp_buf); + if (ret) + return ret; + + (*retlen) += len; + } + + return 0; +} + /* * Handle devices with one erase region, that only implement -- cgit v1.2.3 From 4550615250121fa4dea180111534664b878e79db Mon Sep 17 00:00:00 2001 From: Paul Parsons Date: Wed, 7 Mar 2012 14:11:16 +0000 Subject: mtd: chips: cfi_cmdset_0002: Match ENABLE_VPP()/DISABLE_VPP() calls This patch is part of a set which fixes unnecessary flash erase and write errors resulting from the MTD CFI driver turning off vpp while an erase is in progress. This patch ensures that only those flash operations which call ENABLE_VPP() can then call DISABLE_VPP(). Other operations should never call DISABLE_VPP(). Signed-off-by: Paul Parsons Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 4a5227404614..9b7ff5579d2e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -774,8 +774,6 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad case FL_READY: case FL_STATUS: - /* We should really make set_vpp() count, rather than doing this */ - DISABLE_VPP(map); break; default: printk(KERN_ERR "MTD: put_chip() called with oldstate %d!!\n", chip->oldstate); @@ -1238,6 +1236,7 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, xip_enable(map, chip, adr); op_done: chip->state = FL_READY; + DISABLE_VPP(map); put_chip(map, chip, adr); mutex_unlock(&chip->mutex); @@ -1480,6 +1479,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, ret = -EIO; op_done: chip->state = FL_READY; + DISABLE_VPP(map); put_chip(map, chip, adr); mutex_unlock(&chip->mutex); @@ -1889,6 +1889,7 @@ static int __xipram do_erase_chip(struct map_info *map, struct flchip *chip) chip->state = FL_READY; xip_enable(map, chip, adr); + DISABLE_VPP(map); put_chip(map, chip, adr); mutex_unlock(&chip->mutex); @@ -1979,6 +1980,7 @@ static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, } chip->state = FL_READY; + DISABLE_VPP(map); put_chip(map, chip, adr); mutex_unlock(&chip->mutex); return ret; -- cgit v1.2.3 From 107eb41c50973ed0252f04f2c5c3c85d4dbdfd09 Mon Sep 17 00:00:00 2001 From: Javier Martin Date: Fri, 11 May 2012 12:15:41 +0200 Subject: mtd: add fixup for S29NS512P NOR flash. Spansion S29NS512P flash uses a 16bit transfer to report number of sectors instead of two 8bit accesses as CFI specifies. Artem: remove warning message which said that we are applying the fixup - no need to scary the user unnecessarily. Signed-off-by: Javier Martin Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 9b7ff5579d2e..23ee97f37b08 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -332,6 +332,19 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd) } } +static void fixup_s29ns512p_sectors(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + + /* + * S29NS512P flash uses more than 8bits to report number of sectors, + * which is not permitted by CFI. + */ + cfi->cfiq->EraseRegionInfo[0] = 0x020001ff; + pr_warning("%s: Bad S29NS512P CFI data, adjust to 512 sectors\n", mtd->name); +} + /* Used to fix CFI-Tables of chips without Extended Query Tables */ static struct cfi_fixup cfi_nopri_fixup_table[] = { { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ @@ -362,6 +375,7 @@ static struct cfi_fixup cfi_fixup_table[] = { { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors }, { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors }, { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors }, + { CFI_MFR_AMD, 0x3f00, fixup_s29ns512p_sectors }, { CFI_MFR_SST, 0x536a, fixup_sst38vf640x_sectorsize }, /* SST38VF6402 */ { CFI_MFR_SST, 0x536b, fixup_sst38vf640x_sectorsize }, /* SST38VF6401 */ { CFI_MFR_SST, 0x536c, fixup_sst38vf640x_sectorsize }, /* SST38VF6404 */ -- cgit v1.2.3 From 1634970fcabbaa62eea4375d578f0e317539abb4 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Sun, 13 May 2012 23:34:24 -0500 Subject: mtd: cfi_cmdset_0002: Slight cleanup of fixup messages These should be semicolons, not commas. Signed-off-by: David Woodhouse Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 23ee97f37b08..a7daa419cf24 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -317,7 +317,7 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd) if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { cfi->cfiq->EraseRegionInfo[0] |= 0x0040; - pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name); + pr_warning("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n", mtd->name); } } @@ -328,7 +328,7 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd) if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; - pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name); + pr_warning("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n", mtd->name); } } @@ -342,7 +342,7 @@ static void fixup_s29ns512p_sectors(struct mtd_info *mtd) * which is not permitted by CFI. */ cfi->cfiq->EraseRegionInfo[0] = 0x020001ff; - pr_warning("%s: Bad S29NS512P CFI data, adjust to 512 sectors\n", mtd->name); + pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name); } /* Used to fix CFI-Tables of chips without Extended Query Tables */ -- cgit v1.2.3 From 47287442d981a3d86c272226e4fe2222a78cf5d3 Mon Sep 17 00:00:00 2001 From: Gerlando Falauto Date: Tue, 3 Jul 2012 09:09:47 +0200 Subject: mtd: cfi_cmdset_0002: Micron M29EW bugfixes as per TN-13-07 Fix the following issues with Micron's (formerly Numonyx) M29EW NOR flash chips, as documented on TN-13-07: - Correcting Erase Suspend Hang Ups (page 20) - Resolving the Delay After Resume Issue (page 22) Signed-off-by: Gerlando Falauto Signed-off-by: Artem Bityutskiy Signed-off-by: David Woodhouse Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index a7daa419cf24..7e5564e9e759 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -431,6 +431,68 @@ static void cfi_fixup_major_minor(struct cfi_private *cfi, } } +static int is_m29ew(struct cfi_private *cfi) +{ + if (cfi->mfr == CFI_MFR_INTEL && + ((cfi->device_type == CFI_DEVICETYPE_X8 && (cfi->id & 0xff) == 0x7e) || + (cfi->device_type == CFI_DEVICETYPE_X16 && cfi->id == 0x227e))) + return 1; + return 0; +} + +/* + * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 20: + * Some revisions of the M29EW suffer from erase suspend hang ups. In + * particular, it can occur when the sequence + * Erase Confirm -> Suspend -> Program -> Resume + * causes a lockup due to internal timing issues. The consequence is that the + * erase cannot be resumed without inserting a dummy command after programming + * and prior to resuming. [...] The work-around is to issue a dummy write cycle + * that writes an F0 command code before the RESUME command. + */ +static void cfi_fixup_m29ew_erase_suspend(struct map_info *map, + unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + /* before resume, insert a dummy 0xF0 cycle for Micron M29EW devices */ + if (is_m29ew(cfi)) + map_write(map, CMD(0xF0), adr); +} + +/* + * From TN-13-07: Patching the Linux Kernel and U-Boot for M29 Flash, page 22: + * + * Some revisions of the M29EW (for example, A1 and A2 step revisions) + * are affected by a problem that could cause a hang up when an ERASE SUSPEND + * command is issued after an ERASE RESUME operation without waiting for a + * minimum delay. The result is that once the ERASE seems to be completed + * (no bits are toggling), the contents of the Flash memory block on which + * the erase was ongoing could be inconsistent with the expected values + * (typically, the array value is stuck to the 0xC0, 0xC4, 0x80, or 0x84 + * values), causing a consequent failure of the ERASE operation. + * The occurrence of this issue could be high, especially when file system + * operations on the Flash are intensive. As a result, it is recommended + * that a patch be applied. Intensive file system operations can cause many + * calls to the garbage routine to free Flash space (also by erasing physical + * Flash blocks) and as a result, many consecutive SUSPEND and RESUME + * commands can occur. The problem disappears when a delay is inserted after + * the RESUME command by using the udelay() function available in Linux. + * The DELAY value must be tuned based on the customer's platform. + * The maximum value that fixes the problem in all cases is 500us. + * But, in our experience, a delay of 30 µs to 50 µs is sufficient + * in most cases. + * We have chosen 500µs because this latency is acceptable. + */ +static void cfi_fixup_m29ew_delay_after_resume(struct cfi_private *cfi) +{ + /* + * Resolving the Delay After Resume Issue see Micron TN-13-07 + * Worst case delay must be 500µs but 30-50µs should be ok as well + */ + if (is_m29ew(cfi)) + cfi_udelay(500); +} + struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) { struct cfi_private *cfi = map->fldrv_priv; @@ -776,7 +838,10 @@ static void put_chip(struct map_info *map, struct flchip *chip, unsigned long ad switch(chip->oldstate) { case FL_ERASING: + cfi_fixup_m29ew_erase_suspend(map, + chip->in_progress_block_addr); map_write(map, cfi->sector_erase_cmd, chip->in_progress_block_addr); + cfi_fixup_m29ew_delay_after_resume(cfi); chip->oldstate = FL_READY; chip->state = FL_ERASING; break; @@ -916,6 +981,8 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, /* Disallow XIP again */ local_irq_disable(); + /* Correct Erase Suspend Hangups for M29EW */ + cfi_fixup_m29ew_erase_suspend(map, adr); /* Resume the write or erase operation */ map_write(map, cfi->sector_erase_cmd, adr); chip->state = oldstate; -- cgit v1.2.3 From dc5e48a118558ba1964c6b69ffa307f15197dde3 Mon Sep 17 00:00:00 2001 From: Harald Nordgard-Hansen Date: Fri, 23 Nov 2012 23:11:03 +0100 Subject: mtd: fix recovery after failed write-buffer operation in cfi_cmdset_0002.c When working on a problem with some flash chips that lock up during write-buffer operations, I think there may be a bug in the linux handling of chips using cfi_cmdset_0002.c. The datasheets I have found for a number of these chips all specify that when aborting a write-buffer command, it is not enough to use the standard reset. Rather a "write-to-buffer-reset command" is needed. This command is quite similar for all chips, the main variance seem to be if the final 0xF0 can go to any address or must go to addr_unlock1. The bug is then in the recovery handling when timing out at the end of do_write_buffer, where using the normal reset command is not sufficient. Without this change, if the write-buffer command fails then any following operations on the flash also fail. Signed-off-by: Harald Nordgard-Hansen Signed-off-by: Artem Bityutskiy Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 7e5564e9e759..a35416cbdbb4 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1549,8 +1549,20 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, UDELAY(map, chip, adr, 1); } - /* reset on all failures. */ - map_write( map, CMD(0xF0), chip->start ); + /* + * Recovery from write-buffer programming failures requires + * the write-to-buffer-reset sequence. Since the last part + * of the sequence also works as a normal reset, we can run + * the same commands regardless of why we are here. + * See e.g. + * http://www.spansion.com/Support/Application%20Notes/MirrorBit_Write_Buffer_Prog_Page_Buffer_Read_AN.pdf + */ + cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, + cfi->device_type, NULL); + cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, + cfi->device_type, NULL); + cfi_send_gen_cmd(0xF0, cfi->addr_unlock1, chip->start, map, cfi, + cfi->device_type, NULL); xip_enable(map, chip, adr); /* FIXME - should have reset delay before continuing */ -- cgit v1.2.3 From cb9bf3fbddd6a4fa1c763207575cdf36925a62a7 Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Thu, 11 Apr 2013 17:05:00 +0800 Subject: ENGR00256417: MLB: can't receive data in wait mode For MLB uses iram for data transfer, and there's a missing of dependency on iram in MLB's clock setting, MLB can't receive data in wait mode. We need to add ocram clock dependency in MLB clock. Signed-off-by: Terry Lv --- arch/arm/mach-mx6/clock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index 83544284776e..c70a1c088027 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -1152,7 +1152,11 @@ static int _clk_pll_mlb_main_enable(struct clk *clk) reg = __raw_readl(pllbase); reg &= ~ANADIG_PLL_BYPASS; - reg = 0x0da20800; + reg = (0x3 << ANADIG_PLL_MLB_FLT_RES_CFG_OFFSET) | + (0x3 << ANADIG_PLL_MLB_RX_CLK_DELAY_CFG_OFFSET) | + (0x2 << ANADIG_PLL_MLB_VDDD_DELAY_CFG_OFFSET) | + (0x1 << ANADIG_PLL_MLB_VDDA_DELAY_CFG_OFFSET) | + (ANADIG_PLL_HOLD_RING_OFF); __raw_writel(reg, pllbase); return 0; @@ -4888,6 +4892,7 @@ static int _clk_mlb_set_parent(struct clk *clk, struct clk *parent) static struct clk mlb150_clk = { __INIT_CLK_DEBUG(mlb150_clk) .id = 0, + .secondary = &ocram_clk, .set_parent = _clk_mlb_set_parent, .enable_reg = MXC_CCM_CCGR3, .enable_shift = MXC_CCM_CCGRx_CG9_OFFSET, -- cgit v1.2.3 From 808863866d2c17aeb3e70a7fcd094bd96db4b601 Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Mon, 1 Apr 2013 16:02:35 -0500 Subject: ENGR00257847-1 MX6Q/DL-Fix Ethernet performance issue when WAIT mode is active All of the interrupts from the ENET block are not routed to the GPC block. Hence ENET interrupts are not able to wake up the SOC when the system is in WAIT mode. And the ENET interrupt gets serviced only when another interrupt causes the SOC to exit WAIT mode. This impacts the ENET performance. To fix the issue two options: 1. Route the ENET interrupt to a GPIO. Need to enable the CONFIG_MX6_ENET_IRQ_TO_GPIO in the config. This patch provides support for routing the ENET interrupt to GPIO_1_6. Routing to this GPIO requires no HW board mods. If the GPIO_1_6 is being used for some other peripheral, this patch can be followed to route the ENET interrupt to any other GPIO though a HW mode maybe required. 2. If the GPIO mechanism cannot be used and is not enabled by the above mentioned config, the patch will disable entry to WAIT mode until ENET clock is active. When the ENET clock is disabled, WAIT mode will be automatically enetered. Signed-off-by: Ranjani Vaidyanathan --- arch/arm/configs/imx6_defconfig | 1 + arch/arm/mach-mx6/Kconfig | 7 ++++ arch/arm/mach-mx6/board-mx6q_arm2.c | 17 +++++++++- arch/arm/mach-mx6/board-mx6q_arm2.h | 6 +++- arch/arm/mach-mx6/board-mx6q_sabreauto.c | 18 +++++++++- arch/arm/mach-mx6/board-mx6q_sabreauto.h | 4 +++ arch/arm/mach-mx6/board-mx6q_sabrelite.c | 17 ++++++++++ arch/arm/mach-mx6/board-mx6q_sabresd.c | 16 +++++++++ arch/arm/mach-mx6/board-mx6q_sabresd.h | 4 +++ arch/arm/mach-mx6/clock.c | 22 +++++++++++-- arch/arm/mach-mx6/system.c | 51 +++++++++++++++++------------ arch/arm/plat-mxc/include/mach/iomux-mx6q.h | 21 +++++++++--- 12 files changed, 154 insertions(+), 30 deletions(-) diff --git a/arch/arm/configs/imx6_defconfig b/arch/arm/configs/imx6_defconfig index fc897eddcfa3..5ad4a002676d 100644 --- a/arch/arm/configs/imx6_defconfig +++ b/arch/arm/configs/imx6_defconfig @@ -331,6 +331,7 @@ CONFIG_ARCH_MXC_AUDMUX_V2=y CONFIG_IRAM_ALLOC=y CONFIG_CLK_DEBUG=y CONFIG_DMA_ZONE_SIZE=184 +#CONFIG_MX6_ENET_IRQ_TO_GPIO is not set # # System MMU diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig index 59d8ab313f73..df954b40d8e8 100644 --- a/arch/arm/mach-mx6/Kconfig +++ b/arch/arm/mach-mx6/Kconfig @@ -319,4 +319,11 @@ config MACH_IMX_BLUETOOTH_RFKILL ---help--- Say Y to get the standard rfkill interface of Bluetooth +config MX6_ENET_IRQ_TO_GPIO + bool "Route ENET interrupts to GPIO" + default n + help + Enabling this will direct all the ENET interrupts to a board specific GPIO. + This will allow the system to enter WAIT mode when ENET is active. + endif diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.c b/arch/arm/mach-mx6/board-mx6q_arm2.c index 1e42f4f2193a..97b601de2ddd 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.c +++ b/arch/arm/mach-mx6/board-mx6q_arm2.c @@ -155,6 +155,12 @@ #define MX6_ARM2_CAN2_STBY MX6_ARM2_IO_EXP_GPIO2(1) +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO +#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) +#define IOMUX_OBSRV_MUX1_OFFSET 0x3c +#define OBSRV_MUX1_MASK 0x3f +#define OBSRV_MUX1_ENET_IRQ 0x9 +#endif #define BMCR_PDOWN 0x0800 /* PHY Powerdown */ @@ -387,6 +393,9 @@ static struct fec_platform_data fec_data __initdata = { .init = mx6_arm2_fec_phy_init, .power_hibernate = mx6_arm2_fec_power_hibernate, .phy = PHY_INTERFACE_MODE_RGMII, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + .gpio_irq = MX6_ENET_IRQ, +#endif }; static int mx6_arm2_spi_cs[] = { @@ -2173,8 +2182,14 @@ static void __init mx6_arm2_init(void) imx6q_add_anatop_thermal_imx(1, &mx6_arm2_anatop_thermal_data); - if (!esai_record) + if (!esai_record) { imx6_init_fec(fec_data); +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); +#endif + } imx6q_add_pm_imx(0, &mx6_arm2_pm_data); imx6q_add_sdhci_usdhc_imx(3, &mx6_arm2_sd4_data); diff --git a/arch/arm/mach-mx6/board-mx6q_arm2.h b/arch/arm/mach-mx6/board-mx6q_arm2.h index 8295c6e36905..2a6a2052b3f9 100644 --- a/arch/arm/mach-mx6/board-mx6q_arm2.h +++ b/arch/arm/mach-mx6/board-mx6q_arm2.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2013 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2012, 2013 Freescale Semiconductor, Inc. All Rights Reserved. * * 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 @@ -183,10 +183,14 @@ static iomux_v3_cfg_t mx6q_arm2_pads[] = { /* USBOTG ID pin */ MX6Q_PAD_GPIO_1__USBOTG_ID, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, +#else /* MLB150 */ MX6Q_PAD_GPIO_3__MLB_MLBCLK, MX6Q_PAD_GPIO_6__MLB_MLBSIG, MX6Q_PAD_GPIO_2__MLB_MLBDAT, +#endif }; static iomux_v3_cfg_t mx6q_arm2_i2c3_pads[] = { diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.c b/arch/arm/mach-mx6/board-mx6q_sabreauto.c index 134b94af99d8..fb590f576a0d 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.c +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.c @@ -114,6 +114,13 @@ #define SABREAUTO_MAX7310_2_BASE_ADDR IMX_GPIO_NR(8, 8) #define SABREAUTO_MAX7310_3_BASE_ADDR IMX_GPIO_NR(8, 16) +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO +#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) +#define IOMUX_OBSRV_MUX1_OFFSET 0x3c +#define OBSRV_MUX1_MASK 0x3f +#define OBSRV_MUX1_ENET_IRQ 0x9 +#endif + #define SABREAUTO_IO_EXP_GPIO1(x) (SABREAUTO_MAX7310_1_BASE_ADDR + (x)) #define SABREAUTO_IO_EXP_GPIO2(x) (SABREAUTO_MAX7310_2_BASE_ADDR + (x)) #define SABREAUTO_IO_EXP_GPIO3(x) (SABREAUTO_MAX7310_3_BASE_ADDR + (x)) @@ -404,6 +411,9 @@ static struct fec_platform_data fec_data __initdata = { .init = mx6q_sabreauto_fec_phy_init, .power_hibernate = mx6q_sabreauto_fec_power_hibernate, .phy = PHY_INTERFACE_MODE_RGMII, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + .gpio_irq = MX6_ENET_IRQ, +#endif }; static int mx6q_sabreauto_spi_cs[] = { @@ -1667,9 +1677,15 @@ static void __init mx6_board_init(void) imx6q_add_anatop_thermal_imx(1, &mx6q_sabreauto_anatop_thermal_data); - if (!can0_enable) + if (!can0_enable) { imx6_init_fec(fec_data); +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); +#endif + } imx6q_add_pm_imx(0, &mx6q_sabreauto_pm_data); imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabreauto_sd3_data); diff --git a/arch/arm/mach-mx6/board-mx6q_sabreauto.h b/arch/arm/mach-mx6/board-mx6q_sabreauto.h index 41d0c560f416..e4d62f1baaa5 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabreauto.h +++ b/arch/arm/mach-mx6/board-mx6q_sabreauto.h @@ -208,10 +208,14 @@ static iomux_v3_cfg_t mx6q_sabreauto_pads[] = { /* HDMI */ MX6Q_PAD_EIM_A25__HDMI_TX_CEC_LINE, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, +#else /* MLB150 */ MX6Q_PAD_ENET_TXD1__MLB_MLBCLK, MX6Q_PAD_GPIO_6__MLB_MLBSIG, MX6Q_PAD_GPIO_2__MLB_MLBDAT, +#endif }; static iomux_v3_cfg_t mx6q_sabreauto_can0_pads[] = { diff --git a/arch/arm/mach-mx6/board-mx6q_sabrelite.c b/arch/arm/mach-mx6/board-mx6q_sabrelite.c index a0f19d2e6821..e1075fec4b68 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabrelite.c +++ b/arch/arm/mach-mx6/board-mx6q_sabrelite.c @@ -93,6 +93,13 @@ #define MX6Q_SABRELITE_CSI0_RST IMX_GPIO_NR(1, 8) #define MX6Q_SABRELITE_CSI0_PWN IMX_GPIO_NR(1, 6) +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO +#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) +#define IOMUX_OBSRV_MUX1_OFFSET 0x3c +#define OBSRV_MUX1_MASK 0x3f +#define OBSRV_MUX1_ENET_IRQ 0x9 +#endif + #define MX6Q_SABRELITE_SD3_WP_PADCFG (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_22K_UP | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_HYS) @@ -321,7 +328,9 @@ static iomux_v3_cfg_t mx6q_sabrelite_csi0_sensor_pads[] = { MX6Q_PAD_CSI0_MCLK__IPU1_CSI0_HSYNC, MX6Q_PAD_CSI0_PIXCLK__IPU1_CSI0_PIXCLK, MX6Q_PAD_CSI0_VSYNC__IPU1_CSI0_VSYNC, +#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO MX6Q_PAD_GPIO_6__GPIO_1_6, /* J5 - Camera GP */ +#endif MX6Q_PAD_GPIO_8__GPIO_1_8, /* J5 - Camera Reset */ MX6Q_PAD_SD1_DAT0__GPIO_1_16, /* J5 - Camera GP */ MX6Q_PAD_NANDF_D5__GPIO_2_5, /* J16 - MIPI GP */ @@ -467,6 +476,9 @@ static int mx6q_sabrelite_fec_phy_init(struct phy_device *phydev) static struct fec_platform_data fec_data __initdata = { .init = mx6q_sabrelite_fec_phy_init, .phy = PHY_INTERFACE_MODE_RGMII, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + .gpio_irq = MX6_ENET_IRQ, +#endif }; static int mx6q_sabrelite_spi_cs[] = { @@ -1199,6 +1211,11 @@ static void __init mx6_sabrelite_board_init(void) imx6q_add_anatop_thermal_imx(1, &mx6q_sabrelite_anatop_thermal_data); imx6_init_fec(fec_data); +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); +#endif imx6q_add_pm_imx(0, &mx6q_sabrelite_pm_data); imx6q_add_sdhci_usdhc_imx(3, &mx6q_sabrelite_sd4_data); imx6q_add_sdhci_usdhc_imx(2, &mx6q_sabrelite_sd3_data); diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.c b/arch/arm/mach-mx6/board-mx6q_sabresd.c index a7edf4c6f3ad..ac9b8f8391d9 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.c +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.c @@ -198,6 +198,13 @@ #define SABRESD_ELAN_RST IMX_GPIO_NR(3, 8) #define SABRESD_ELAN_INT IMX_GPIO_NR(3, 28) +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO +#define MX6_ENET_IRQ IMX_GPIO_NR(1, 6) +#define IOMUX_OBSRV_MUX1_OFFSET 0x3c +#define OBSRV_MUX1_MASK 0x3f +#define OBSRV_MUX1_ENET_IRQ 0x9 +#endif + static struct clk *sata_clk; static struct clk *clko; static int mma8451_position = 1; @@ -291,6 +298,9 @@ static int mx6q_sabresd_fec_phy_init(struct phy_device *phydev) static struct fec_platform_data fec_data __initdata = { .init = mx6q_sabresd_fec_phy_init, .phy = PHY_INTERFACE_MODE_RGMII, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + .gpio_irq = MX6_ENET_IRQ, +#endif }; static int mx6q_sabresd_spi_cs[] = { @@ -1780,6 +1790,12 @@ static void __init mx6_sabresd_board_init(void) imx6q_add_anatop_thermal_imx(1, &mx6q_sabresd_anatop_thermal_data); imx6_init_fec(fec_data); +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + /* Make sure the IOMUX_OBSRV_MUX1 is set to ENET_IRQ. */ + mxc_iomux_set_specialbits_register(IOMUX_OBSRV_MUX1_OFFSET, + OBSRV_MUX1_ENET_IRQ, OBSRV_MUX1_MASK); +#endif + imx6q_add_pm_imx(0, &mx6q_sabresd_pm_data); /* Move sd4 to first because sd4 connect to emmc. diff --git a/arch/arm/mach-mx6/board-mx6q_sabresd.h b/arch/arm/mach-mx6/board-mx6q_sabresd.h index 73ee909e50ef..b2bb8c923f0f 100644 --- a/arch/arm/mach-mx6/board-mx6q_sabresd.h +++ b/arch/arm/mach-mx6/board-mx6q_sabresd.h @@ -132,9 +132,13 @@ static iomux_v3_cfg_t mx6q_sabresd_pads[] = { MX6Q_PAD_KEY_COL3__I2C2_SCL, MX6Q_PAD_KEY_ROW3__I2C2_SDA, +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1, +#else /* I2C3 */ MX6Q_PAD_GPIO_3__I2C3_SCL, /* GPIO1[3] */ MX6Q_PAD_GPIO_6__I2C3_SDA, +#endif /* DISPLAY */ MX6Q_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK, diff --git a/arch/arm/mach-mx6/clock.c b/arch/arm/mach-mx6/clock.c index c70a1c088027..412423dd7879 100644 --- a/arch/arm/mach-mx6/clock.c +++ b/arch/arm/mach-mx6/clock.c @@ -50,6 +50,7 @@ extern int lp_med_freq; extern int wait_mode_arm_podf; extern int lp_audio_freq; extern int cur_arm_podf; +extern bool enet_is_active; void __iomem *apll_base; @@ -3727,6 +3728,23 @@ static unsigned long _clk_enet_get_rate(struct clk *clk) return 500000000 / div; } +static int _clk_enet_enable(struct clk *clk) +{ +#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO + enet_is_active = true; +#endif + _clk_enable(clk); + return 0; +} + +static void _clk_enet_disable(struct clk *clk) +{ + _clk_disable(clk); +#ifndef CONFIG_MX6_ENET_IRQ_TO_GPIO + enet_is_active = false; +#endif +} + static struct clk enet_clk[] = { { __INIT_CLK_DEBUG(enet_clk) @@ -3734,8 +3752,8 @@ static struct clk enet_clk[] = { .parent = &pll8_enet_main_clk, .enable_reg = MXC_CCM_CCGR1, .enable_shift = MXC_CCM_CCGRx_CG5_OFFSET, - .enable = _clk_enable, - .disable = _clk_disable, + .enable = _clk_enet_enable, + .disable = _clk_enet_disable, .set_rate = _clk_enet_set_rate, .get_rate = _clk_enet_get_rate, .secondary = &enet_clk[1], diff --git a/arch/arm/mach-mx6/system.c b/arch/arm/mach-mx6/system.c index f6ffa2999ed2..4990a4a0abbb 100644 --- a/arch/arm/mach-mx6/system.c +++ b/arch/arm/mach-mx6/system.c @@ -57,6 +57,7 @@ volatile unsigned int num_cpu_idle; volatile unsigned int num_cpu_idle_lock = 0x0; int wait_mode_arm_podf; int cur_arm_podf; +bool enet_is_active; void arch_idle_with_workaround(int cpu); extern void *mx6sl_wfi_iram_base; @@ -350,7 +351,7 @@ void arch_idle_single_core(void) } } -void arch_idle_with_workaround(cpu) +void arch_idle_with_workaround(int cpu) { u32 podf = wait_mode_arm_podf; @@ -369,18 +370,10 @@ void arch_idle_with_workaround(cpu) } -void arch_idle_multi_core(void) +void arch_idle_multi_core(int cpu) { u32 reg; - int cpu = smp_processor_id(); -#ifdef CONFIG_LOCAL_TIMERS - if (!tick_broadcast_oneshot_active() - || !tick_oneshot_mode_active()) - return; - - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); -#endif /* iMX6Q and iMX6DL */ if ((cpu_is_mx6q() && chip_rev >= IMX_CHIP_REVISION_1_2) || (cpu_is_mx6dl() && chip_rev >= IMX_CHIP_REVISION_1_1)) { @@ -398,24 +391,37 @@ void arch_idle_multi_core(void) ca9_do_idle(); } else arch_idle_with_workaround(cpu); -#ifdef CONFIG_LOCAL_TIMERS - clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); -#endif - } void arch_idle(void) { + int cpu = smp_processor_id(); + if (enable_wait_mode) { - mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); +#ifdef CONFIG_LOCAL_TIMERS + if (!tick_broadcast_oneshot_active() + || !tick_oneshot_mode_active()) + return; + + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu); +#endif + if (enet_is_active) + /* Don't allow the chip to enter WAIT mode if enet is active + * and the GPIO workaround for ENET interrupts is not used, + * since all ENET interrupts donot wake up the SOC. + */ + mxc_cpu_lp_set(WAIT_CLOCKED); + else + mxc_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF); if (mem_clk_on_in_wait) { u32 reg; /* * MX6SL, MX6Q (TO1.2 or later) and - * MX6DL (TO1.1 or later) have a bit in CCM_CGPR that - * when cleared keeps the clocks to memories ON - * when ARM is in WFI. This mode can be used when - * IPG clock is very low (12MHz) and the ARM:IPG ratio + * MX6DL (TO1.1 or later) have a bit in + * CCM_CGPR that when cleared keeps the + * clocks to memories ON when ARM is in WFI. + * This mode can be used when IPG clock is + * very low (12MHz) and the ARM:IPG ratio * perhaps cannot be maintained. */ reg = __raw_readl(MXC_CCM_CGPR); @@ -427,8 +433,11 @@ void arch_idle(void) /* iMX6SL or iMX6DLS */ arch_idle_single_core(); else - arch_idle_multi_core(); - } else { + arch_idle_multi_core(cpu); +#ifdef CONFIG_LOCAL_TIMERS + clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu); +#endif + } else { mxc_cpu_lp_set(WAIT_CLOCKED); ca9_do_idle(); } diff --git a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h index 4cc8ad9eb512..557fc4398cd1 100644 --- a/arch/arm/plat-mxc/include/mach/iomux-mx6q.h +++ b/arch/arm/plat-mxc/include/mach/iomux-mx6q.h @@ -97,6 +97,9 @@ PAD_CTL_SPEED_MED | PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_100K_UP) +#define ENET_IRQ_PAD_CTRL (PAD_CTL_SRE_FAST | PAD_CTL_DSE_40ohm | \ + PAD_CTL_SPEED_MED) + #define _MX6Q_PAD_SD2_DAT1__USDHC2_DAT1 \ IOMUX_PAD(0x0360, 0x004C, 0, 0x0000, 0, 0) #define _MX6Q_PAD_SD2_DAT1__ECSPI5_SS0 \ @@ -2329,8 +2332,13 @@ #define _MX6Q_PAD_GPIO_6__ESAI1_SCKT \ IOMUX_PAD(0x0600, 0x0230, 0, 0x0870, 1, 0) +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO +#define _MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ + IOMUX_PAD(0x0600, 0x0230, 1 | IOMUX_CONFIG_SION, 0x0000, 0, 0) +#else #define _MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ IOMUX_PAD(0x0600, 0x0230, 1, 0x0000, 0, 0) +#endif #define _MX6Q_PAD_GPIO_6__I2C3_SDA \ IOMUX_PAD(0x0600, 0x0230, 2 | IOMUX_CONFIG_SION, 0x08AC, 1, 0) #define _MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 \ @@ -5932,22 +5940,27 @@ #define MX6Q_PAD_GPIO_3__MLB_MLBCLK \ (_MX6Q_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(MX6Q_MLB150_PAD_CTRL)) -#define MX6Q_PAD_GPIO_6__ESAI1_SCKT \ - (_MX6Q_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL)) +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO +#define MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ + (_MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(ENET_IRQ_PAD_CTRL)) +#else #define MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 \ (_MX6Q_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL)) +#define MX6Q_PAD_GPIO_6__ESAI1_SCKT \ + (_MX6Q_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL)) +#define MX6Q_PAD_GPIO_6__GPIO_1_6 \ + (_MX6Q_PAD_GPIO_6__GPIO_1_6 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__I2C3_SDA \ (_MX6Q_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 \ (_MX6Q_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB \ (_MX6Q_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL)) -#define MX6Q_PAD_GPIO_6__GPIO_1_6 \ - (_MX6Q_PAD_GPIO_6__GPIO_1_6 | MUX_PAD_CTRL(NO_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__USDHC2_LCTL \ (_MX6Q_PAD_GPIO_6__USDHC2_LCTL | MUX_PAD_CTRL(MX6Q_USDHC_PAD_CTRL)) #define MX6Q_PAD_GPIO_6__MLB_MLBSIG \ (_MX6Q_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(MX6Q_MLB150_PAD_CTRL)) +#endif #define MX6Q_PAD_GPIO_2__ESAI1_FST \ (_MX6Q_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL)) -- cgit v1.2.3 From bae4d40849f3acdd9663f5a0857c9415ed7e6d5d Mon Sep 17 00:00:00 2001 From: Ranjani Vaidyanathan Date: Mon, 1 Apr 2013 16:03:31 -0500 Subject: ENGR00257847-2 MX6Q/DL-Fix Ethernet performance issue when WAIT mode is active All of the interrupts from the ENET block are not routed to the GPC block. Hence ENET interrupts are not able to wake up the SOC when the system is in WAIT mode. And the ENET interrupt gets serviced only when another interrupt causes the SOC to exit WAIT mode. This impacts the ENET performance. To fix the issue two options: 1. Route the ENET interrupt to a GPIO. Need to enable the CONFIG_MX6_ENET_IRQ_TO_GPIO in the config. 2. If the GPIO mechanism cannot be used and is not enabled by the above mentioned config, the patch will disable entry to WAIT mode until ENET clock is active. When the ENET clock is disabled, WAIT mode will be automatically enetered. Signed-off-by: Ranjani Vaidyanathan --- drivers/net/fec.c | 17 +++++++++++++++++ include/linux/fec.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 5f0e4e0e3a3e..fc65bdc96241 100755 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -1866,6 +1867,17 @@ fec_probe(struct platform_device *pdev) if (pdata) fep->phy_interface = pdata->phy; +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + gpio_request(pdata->gpio_irq, "gpio_enet_irq"); + gpio_direction_input(pdata->gpio_irq); + + irq = gpio_to_irq(pdata->gpio_irq); + ret = request_irq(irq, fec_enet_interrupt, + IRQF_TRIGGER_RISING, + pdev->name, ndev); + if (ret) + goto failed_irq; +#else /* This device has up to three irqs on some platforms */ for (i = 0; i < 3; i++) { irq = platform_get_irq(pdev, i); @@ -1880,6 +1892,7 @@ fec_probe(struct platform_device *pdev) goto failed_irq; } } +#endif fep->clk = clk_get(&pdev->dev, "fec_clk"); if (IS_ERR(fep->clk)) { @@ -1930,11 +1943,15 @@ failed_init: clk_disable(fep->clk); clk_put(fep->clk); failed_clk: +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + free_irq(irq, ndev); +#else for (i = 0; i < 3; i++) { irq = platform_get_irq(pdev, i); if (irq > 0) free_irq(irq, ndev); } +#endif failed_irq: iounmap(fep->hwp); failed_ioremap: diff --git a/include/linux/fec.h b/include/linux/fec.h index 97a56d4add74..a9d659456eba 100644 --- a/include/linux/fec.h +++ b/include/linux/fec.h @@ -21,6 +21,9 @@ struct fec_platform_data { int (*power_hibernate) (struct phy_device *); phy_interface_t phy; unsigned char mac[ETH_ALEN]; +#ifdef CONFIG_MX6_ENET_IRQ_TO_GPIO + unsigned int gpio_irq; +#endif }; #endif -- cgit v1.2.3 From 5b1d3406a8897abc0d9714fb4be01655b9021a62 Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Fri, 12 Apr 2013 12:08:07 +0800 Subject: ENGR00258357-1: mlb: Remove MLB150_ from macro define names Remove MLB150_ from macro define names to make code clean. Signed-off-by: Terry Lv --- drivers/mxc/mlb/mxc_mlb150.c | 708 +++++++++++++++++++++---------------------- 1 file changed, 354 insertions(+), 354 deletions(-) diff --git a/drivers/mxc/mlb/mxc_mlb150.c b/drivers/mxc/mlb/mxc_mlb150.c index e3ecbe20446f..580480e1ca57 100755 --- a/drivers/mxc/mlb/mxc_mlb150.c +++ b/drivers/mxc/mlb/mxc_mlb150.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright (C) 2011-2013 Freescale Semiconductor, Inc. All Rights Reserved. * * 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 @@ -43,155 +43,155 @@ /*! * MLB module memory map registers define */ -#define MLB150_REG_MLBC0 0x0 -#define MLB150_MLBC0_MLBEN (0x1) -#define MLB150_MLBC0_MLBCLK_MASK (0x7 << 2) -#define MLB150_MLBC0_MLBCLK_SHIFT (2) -#define MLB150_MLBC0_MLBPEN (0x1 << 5) -#define MLB150_MLBC0_MLBLK (0x1 << 7) -#define MLB150_MLBC0_ASYRETRY (0x1 << 12) -#define MLB150_MLBC0_CTLRETRY (0x1 << 12) -#define MLB150_MLBC0_FCNT_MASK (0x7 << 15) -#define MLB150_MLBC0_FCNT_SHIFT (15) - -#define MLB150_REG_MLBPC0 0x8 -#define MLB150_MLBPC0_MCLKHYS (0x1 << 11) - -#define MLB150_REG_MS0 0xC -#define MLB150_REG_MS1 0x14 - -#define MLB150_REG_MSS 0x20 -#define MLB150_MSS_RSTSYSCMD (0x1) -#define MLB150_MSS_LKSYSCMD (0x1 << 1) -#define MLB150_MSS_ULKSYSCMD (0x1 << 2) -#define MLB150_MSS_CSSYSCMD (0x1 << 3) -#define MLB150_MSS_SWSYSCMD (0x1 << 4) -#define MLB150_MSS_SERVREQ (0x1 << 5) - -#define MLB150_REG_MSD 0x24 - -#define MLB150_REG_MIEN 0x2C -#define MLB150_MIEN_ISOC_PE (0x1) -#define MLB150_MIEN_ISOC_BUFO (0x1 << 1) -#define MLB150_MIEN_SYNC_PE (0x1 << 16) -#define MLB150_MIEN_ARX_DONE (0x1 << 17) -#define MLB150_MIEN_ARX_PE (0x1 << 18) -#define MLB150_MIEN_ARX_BREAK (0x1 << 19) -#define MLB150_MIEN_ATX_DONE (0x1 << 20) -#define MLB150_MIEN_ATX_PE (0x1 << 21) -#define MLB150_MIEN_ATX_BREAK (0x1 << 22) -#define MLB150_MIEN_CRX_DONE (0x1 << 24) -#define MLB150_MIEN_CRX_PE (0x1 << 25) -#define MLB150_MIEN_CRX_BREAK (0x1 << 26) -#define MLB150_MIEN_CTX_DONE (0x1 << 27) -#define MLB150_MIEN_CTX_PE (0x1 << 28) -#define MLB150_MIEN_CTX_BREAK (0x1 << 29) - -#define MLB150_REG_MLBPC2 0x34 -#define MLB150_REG_MLBPC1 0x38 -#define MLB150_MLBPC1_VAL (0x00000888) - -#define MLB150_REG_MLBC1 0x3C -#define MLB150_MLBC1_LOCK (0x1 << 6) -#define MLB150_MLBC1_CLKM (0x1 << 7) -#define MLB150_MLBC1_NDA_MASK (0xFF << 8) -#define MLB150_MLBC1_NDA_SHIFT (8) - -#define MLB150_REG_HCTL 0x80 -#define MLB150_HCTL_RST0 (0x1) -#define MLB150_HCTL_RST1 (0x1 << 1) -#define MLB150_HCTL_EN (0x1 << 15) - -#define MLB150_REG_HCMR0 0x88 -#define MLB150_REG_HCMR1 0x8C -#define MLB150_REG_HCER0 0x90 -#define MLB150_REG_HCER1 0x94 -#define MLB150_REG_HCBR0 0x98 -#define MLB150_REG_HCBR1 0x9C - -#define MLB150_REG_MDAT0 0xC0 -#define MLB150_REG_MDAT1 0xC4 -#define MLB150_REG_MDAT2 0xC8 -#define MLB150_REG_MDAT3 0xCC - -#define MLB150_REG_MDWE0 0xD0 -#define MLB150_REG_MDWE1 0xD4 -#define MLB150_REG_MDWE2 0xD8 -#define MLB150_REG_MDWE3 0xDC - -#define MLB150_REG_MCTL 0xE0 -#define MLB150_MCTL_XCMP (0x1) - -#define MLB150_REG_MADR 0xE4 -#define MLB150_MADR_WNR (0x1 << 31) -#define MLB150_MADR_TB (0x1 << 30) -#define MLB150_MADR_ADDR_MASK (0x7f << 8) -#define MLB150_MADR_ADDR_SHIFT (0) - -#define MLB150_REG_ACTL 0x3C0 -#define MLB150_ACTL_MPB (0x1 << 4) -#define MLB150_ACTL_DMAMODE (0x1 << 2) -#define MLB150_ACTL_SMX (0x1 << 1) -#define MLB150_ACTL_SCE (0x1) - -#define MLB150_REG_ACSR0 0x3D0 -#define MLB150_REG_ACSR1 0x3D4 -#define MLB150_REG_ACMR0 0x3D8 -#define MLB150_REG_ACMR1 0x3DC - -#define MLB150_REG_CAT_MDATn(ch) (MLB150_REG_MDAT0 + ((ch % 8) >> 1) * 4) -#define MLB150_REG_CAT_MDWEn(ch) (MLB150_REG_MDWE0 + ((ch % 8) >> 1) * 4) - -#define MLB150_LOGIC_CH_NUM (64) -#define MLB150_BUF_CDT_OFFSET (0x0) -#define MLB150_BUF_ADT_OFFSET (0x40) -#define MLB150_BUF_CAT_MLB_OFFSET (0x80) -#define MLB150_BUF_CAT_HBI_OFFSET (0x88) -#define MLB150_BUF_CTR_END_OFFSET (0x8F) - -#define MLB150_CAT_MODE_RX (0x1 << 0) -#define MLB150_CAT_MODE_TX (0x1 << 1) -#define MLB150_CAT_MODE_INBOUND_DMA (0x1 << 8) -#define MLB150_CAT_MODE_OUTBOUND_DMA (0x1 << 9) - -#define MLB150_CH_SYNC_BUF_DEP (128 * 4 * 4) -#define MLB150_CH_CTRL_BUF_DEP (64) -#define MLB150_CH_ASYNC_BUF_DEP (2048) -#define MLB150_CH_ISOC_BLK_SIZE (196) -#define MLB150_CH_ISOC_BLK_NUM (3) -#define MLB150_CH_ISOC_BUF_DEP (MLB150_CH_ISOC_BLK_SIZE * MLB150_CH_ISOC_BLK_NUM) - -#define MLB150_CH_SYNC_DBR_BUF_OFFSET (0x0) -#define MLB150_CH_CTRL_DBR_BUF_OFFSET (MLB150_CH_SYNC_DBR_BUF_OFFSET + 2 * MLB150_CH_SYNC_BUF_DEP) -#define MLB150_CH_ASYNC_DBR_BUF_OFFSET (MLB150_CH_CTRL_DBR_BUF_OFFSET + 2 * MLB150_CH_CTRL_BUF_DEP) -#define MLB150_CH_ISOC_DBR_BUF_OFFSET (MLB150_CH_ASYNC_DBR_BUF_OFFSET + 2 * MLB150_CH_ASYNC_BUF_DEP) +#define REG_MLBC0 0x0 +#define MLBC0_MLBEN (0x1) +#define MLBC0_MLBCLK_MASK (0x7 << 2) +#define MLBC0_MLBCLK_SHIFT (2) +#define MLBC0_MLBPEN (0x1 << 5) +#define MLBC0_MLBLK (0x1 << 7) +#define MLBC0_ASYRETRY (0x1 << 12) +#define MLBC0_CTLRETRY (0x1 << 12) +#define MLBC0_FCNT_MASK (0x7 << 15) +#define MLBC0_FCNT_SHIFT (15) + +#define REG_MLBPC0 0x8 +#define MLBPC0_MCLKHYS (0x1 << 11) + +#define REG_MS0 0xC +#define REG_MS1 0x14 + +#define REG_MSS 0x20 +#define MSS_RSTSYSCMD (0x1) +#define MSS_LKSYSCMD (0x1 << 1) +#define MSS_ULKSYSCMD (0x1 << 2) +#define MSS_CSSYSCMD (0x1 << 3) +#define MSS_SWSYSCMD (0x1 << 4) +#define MSS_SERVREQ (0x1 << 5) + +#define REG_MSD 0x24 + +#define REG_MIEN 0x2C +#define MIEN_ISOC_PE (0x1) +#define MIEN_ISOC_BUFO (0x1 << 1) +#define MIEN_SYNC_PE (0x1 << 16) +#define MIEN_ARX_DONE (0x1 << 17) +#define MIEN_ARX_PE (0x1 << 18) +#define MIEN_ARX_BREAK (0x1 << 19) +#define MIEN_ATX_DONE (0x1 << 20) +#define MIEN_ATX_PE (0x1 << 21) +#define MIEN_ATX_BREAK (0x1 << 22) +#define MIEN_CRX_DONE (0x1 << 24) +#define MIEN_CRX_PE (0x1 << 25) +#define MIEN_CRX_BREAK (0x1 << 26) +#define MIEN_CTX_DONE (0x1 << 27) +#define MIEN_CTX_PE (0x1 << 28) +#define MIEN_CTX_BREAK (0x1 << 29) + +#define REG_MLBPC2 0x34 +#define REG_MLBPC1 0x38 +#define MLBPC1_VAL (0x00000888) + +#define REG_MLBC1 0x3C +#define MLBC1_LOCK (0x1 << 6) +#define MLBC1_CLKM (0x1 << 7) +#define MLBC1_NDA_MASK (0xFF << 8) +#define MLBC1_NDA_SHIFT (8) + +#define REG_HCTL 0x80 +#define HCTL_RST0 (0x1) +#define HCTL_RST1 (0x1 << 1) +#define HCTL_EN (0x1 << 15) + +#define REG_HCMR0 0x88 +#define REG_HCMR1 0x8C +#define REG_HCER0 0x90 +#define REG_HCER1 0x94 +#define REG_HCBR0 0x98 +#define REG_HCBR1 0x9C + +#define REG_MDAT0 0xC0 +#define REG_MDAT1 0xC4 +#define REG_MDAT2 0xC8 +#define REG_MDAT3 0xCC + +#define REG_MDWE0 0xD0 +#define REG_MDWE1 0xD4 +#define REG_MDWE2 0xD8 +#define REG_MDWE3 0xDC + +#define REG_MCTL 0xE0 +#define MCTL_XCMP (0x1) + +#define REG_MADR 0xE4 +#define MADR_WNR (0x1 << 31) +#define MADR_TB (0x1 << 30) +#define MADR_ADDR_MASK (0x7f << 8) +#define MADR_ADDR_SHIFT (0) + +#define REG_ACTL 0x3C0 +#define ACTL_MPB (0x1 << 4) +#define ACTL_DMAMODE (0x1 << 2) +#define ACTL_SMX (0x1 << 1) +#define ACTL_SCE (0x1) + +#define REG_ACSR0 0x3D0 +#define REG_ACSR1 0x3D4 +#define REG_ACMR0 0x3D8 +#define REG_ACMR1 0x3DC + +#define REG_CAT_MDATn(ch) (REG_MDAT0 + ((ch % 8) >> 1) * 4) +#define REG_CAT_MDWEn(ch) (REG_MDWE0 + ((ch % 8) >> 1) * 4) + +#define LOGIC_CH_NUM (64) +#define BUF_CDT_OFFSET (0x0) +#define BUF_ADT_OFFSET (0x40) +#define BUF_CAT_MLB_OFFSET (0x80) +#define BUF_CAT_HBI_OFFSET (0x88) +#define BUF_CTR_END_OFFSET (0x8F) + +#define CAT_MODE_RX (0x1 << 0) +#define CAT_MODE_TX (0x1 << 1) +#define CAT_MODE_INBOUND_DMA (0x1 << 8) +#define CAT_MODE_OUTBOUND_DMA (0x1 << 9) + +#define CH_SYNC_BUF_DEP (128 * 4 * 4) +#define CH_CTRL_BUF_DEP (64) +#define CH_ASYNC_BUF_DEP (2048) +#define CH_ISOC_BLK_SIZE (196) +#define CH_ISOC_BLK_NUM (3) +#define CH_ISOC_BUF_DEP (CH_ISOC_BLK_SIZE * CH_ISOC_BLK_NUM) + +#define CH_SYNC_DBR_BUF_OFFSET (0x0) +#define CH_CTRL_DBR_BUF_OFFSET (CH_SYNC_DBR_BUF_OFFSET + 2 * CH_SYNC_BUF_DEP) +#define CH_ASYNC_DBR_BUF_OFFSET (CH_CTRL_DBR_BUF_OFFSET + 2 * CH_CTRL_BUF_DEP) +#define CH_ISOC_DBR_BUF_OFFSET (CH_ASYNC_DBR_BUF_OFFSET + 2 * CH_ASYNC_BUF_DEP) static u32 mlb150_ch_packet_buf_size[4] = { - MLB150_CH_SYNC_BUF_DEP, - MLB150_CH_CTRL_BUF_DEP, - MLB150_CH_ASYNC_BUF_DEP, - MLB150_CH_ISOC_BUF_DEP + CH_SYNC_BUF_DEP, + CH_CTRL_BUF_DEP, + CH_ASYNC_BUF_DEP, + CH_ISOC_BUF_DEP }; -#define MLB150_DBR_BUF_START 0x00000 +#define DBR_BUF_START 0x00000 -#define MLB150_CDT_LEN (16) -#define MLB150_ADT_LEN (16) -#define MLB150_CAT_LEN (2) +#define CDT_LEN (16) +#define ADT_LEN (16) +#define CAT_LEN (2) -#define MLB150_CDT_SZ (MLB150_CDT_LEN * MLB150_LOGIC_CH_NUM) -#define MLB150_ADT_SZ (MLB150_ADT_LEN * MLB150_LOGIC_CH_NUM) -#define MLB150_CAT_SZ (MLB150_CAT_LEN * MLB150_LOGIC_CH_NUM * 2) +#define CDT_SZ (CDT_LEN * LOGIC_CH_NUM) +#define ADT_SZ (ADT_LEN * LOGIC_CH_NUM) +#define CAT_SZ (CAT_LEN * LOGIC_CH_NUM * 2) -#define MLB150_CDT_BASE(base) (base + MLB150_BUF_CDT_OFFSET) -#define MLB150_ADT_BASE(base) (base + MLB150_BUF_ADT_OFFSET) -#define MLB150_CAT_MLB_BASE(base) (base + MLB150_BUF_CAT_MLB_OFFSET) -#define MLB150_CAT_HBI_BASE(base) (base + MLB150_BUF_CAT_HBI_OFFSET) +#define CDT_BASE(base) (base + BUF_CDT_OFFSET) +#define ADT_BASE(base) (base + BUF_ADT_OFFSET) +#define CAT_MLB_BASE(base) (base + BUF_CAT_MLB_OFFSET) +#define CAT_HBI_BASE(base) (base + BUF_CAT_HBI_OFFSET) -#define MLB150_CDTn_ADDR(base, n) (base + MLB150_BUF_CDT_OFFSET + n * MLB150_CDT_LEN) -#define MLB150_ADTn_ADDR(base, n) (base + MLB150_BUF_ADT_OFFSET + n * MLB150_ADT_LEN) -#define MLB150_CATn_MLB_ADDR(base, n) (base + MLB150_BUF_CAT_MLB_OFFSET + n * MLB150_CAT_LEN) -#define MLB150_CATn_HBI_ADDR(base, n) (base + MLB150_BUF_CAT_HBI_OFFSET + n * MLB150_CAT_LEN) +#define CDTn_ADDR(base, n) (base + BUF_CDT_OFFSET + n * CDT_LEN) +#define ADTn_ADDR(base, n) (base + BUF_ADT_OFFSET + n * ADT_LEN) +#define CATn_MLB_ADDR(base, n) (base + BUF_CAT_MLB_OFFSET + n * CAT_LEN) +#define CATn_HBI_ADDR(base, n) (base + BUF_CAT_HBI_OFFSET + n * CAT_LEN) #define CAT_CL_SHIFT (0x0) #define CAT_CT_SHIFT (8) @@ -277,15 +277,15 @@ enum MLB_CTYPE { MLB_CTYPE_ISOC, }; -enum MLB150_CLK_SPEED { - MLB150_CLK_256FS, - MLB150_CLK_512FS, - MLB150_CLK_1024FS, - MLB150_CLK_2048FS, - MLB150_CLK_3072FS, - MLB150_CLK_4096FS, - MLB150_CLK_6144FS, - MLB150_CLK_8192FS, +enum CLK_SPEED { + CLK_256FS, + CLK_512FS, + CLK_1024FS, + CLK_2048FS, + CLK_3072FS, + CLK_4096FS, + CLK_6144FS, + CLK_8192FS, }; /*! @@ -351,7 +351,7 @@ struct mlb_dev_info { /* channel type */ const unsigned int channel_type; /* ch fps */ - enum MLB150_CLK_SPEED fps; + enum CLK_SPEED fps; /* channel info for tx/rx */ struct mlb_channel_info channels[2]; /* rx ring buffer */ @@ -377,16 +377,16 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_SYNC, .channels = { [0] = { - .buf_size = MLB150_CH_SYNC_BUF_DEP, - .dbr_buf_head = MLB150_CH_SYNC_DBR_BUF_OFFSET, + .buf_size = CH_SYNC_BUF_DEP, + .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[0].channels[0]. buf_lock), }, [1] = { - .buf_size = MLB150_CH_SYNC_BUF_DEP, - .dbr_buf_head = MLB150_CH_SYNC_DBR_BUF_OFFSET - + MLB150_CH_SYNC_BUF_DEP, + .buf_size = CH_SYNC_BUF_DEP, + .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET + + CH_SYNC_BUF_DEP, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[0].channels[1]. buf_lock), @@ -403,16 +403,16 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_CTRL, .channels = { [0] = { - .buf_size = MLB150_CH_CTRL_BUF_DEP, - .dbr_buf_head = MLB150_CH_CTRL_DBR_BUF_OFFSET, + .buf_size = CH_CTRL_BUF_DEP, + .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[1].channels[0]. buf_lock), }, [1] = { - .buf_size = MLB150_CH_CTRL_BUF_DEP, - .dbr_buf_head = MLB150_CH_CTRL_DBR_BUF_OFFSET - + MLB150_CH_CTRL_BUF_DEP, + .buf_size = CH_CTRL_BUF_DEP, + .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET + + CH_CTRL_BUF_DEP, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[1].channels[1]. buf_lock), @@ -429,16 +429,16 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_ASYNC, .channels = { [0] = { - .buf_size = MLB150_CH_ASYNC_BUF_DEP, - .dbr_buf_head = MLB150_CH_ASYNC_DBR_BUF_OFFSET, + .buf_size = CH_ASYNC_BUF_DEP, + .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[2].channels[0]. buf_lock), }, [1] = { - .buf_size = MLB150_CH_ASYNC_BUF_DEP, - .dbr_buf_head = MLB150_CH_ASYNC_DBR_BUF_OFFSET - + MLB150_CH_ASYNC_BUF_DEP, + .buf_size = CH_ASYNC_BUF_DEP, + .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET + + CH_ASYNC_BUF_DEP, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[2].channels[1]. buf_lock), @@ -455,16 +455,16 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_ISOC, .channels = { [0] = { - .buf_size = MLB150_CH_ISOC_BUF_DEP, - .dbr_buf_head = MLB150_CH_ISOC_DBR_BUF_OFFSET, + .buf_size = CH_ISOC_BUF_DEP, + .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[3].channels[0]. buf_lock), }, [1] = { - .buf_size = MLB150_CH_ISOC_BUF_DEP, - .dbr_buf_head = MLB150_CH_ISOC_DBR_BUF_OFFSET - + MLB150_CH_ISOC_BUF_DEP, + .buf_size = CH_ISOC_BUF_DEP, + .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET + + CH_ISOC_BUF_DEP, .buf_lock = __RW_LOCK_UNLOCKED(mlb_devinfo[3].channels[1]. buf_lock), @@ -496,38 +496,38 @@ DEFINE_SPINLOCK(ctr_lock); static void mlb150_dev_dump_reg(void) { pr_debug("mxc_mlb150: Dump registers:\n"); - DUMP_REG(MLB150_REG_MLBC0); - DUMP_REG(MLB150_REG_MLBPC0); - DUMP_REG(MLB150_REG_MS0); - DUMP_REG(MLB150_REG_MS1); - DUMP_REG(MLB150_REG_MSS); - DUMP_REG(MLB150_REG_MSD); - DUMP_REG(MLB150_REG_MIEN); - DUMP_REG(MLB150_REG_MLBPC2); - DUMP_REG(MLB150_REG_MLBPC1); - DUMP_REG(MLB150_REG_MLBC1); - DUMP_REG(MLB150_REG_HCTL); - DUMP_REG(MLB150_REG_HCMR0); - DUMP_REG(MLB150_REG_HCMR1); - DUMP_REG(MLB150_REG_HCER0); - DUMP_REG(MLB150_REG_HCER1); - DUMP_REG(MLB150_REG_HCBR0); - DUMP_REG(MLB150_REG_HCBR1); - DUMP_REG(MLB150_REG_MDAT0); - DUMP_REG(MLB150_REG_MDAT1); - DUMP_REG(MLB150_REG_MDAT2); - DUMP_REG(MLB150_REG_MDAT3); - DUMP_REG(MLB150_REG_MDWE0); - DUMP_REG(MLB150_REG_MDWE1); - DUMP_REG(MLB150_REG_MDWE2); - DUMP_REG(MLB150_REG_MDWE3); - DUMP_REG(MLB150_REG_MCTL); - DUMP_REG(MLB150_REG_MADR); - DUMP_REG(MLB150_REG_ACTL); - DUMP_REG(MLB150_REG_ACSR0); - DUMP_REG(MLB150_REG_ACSR1); - DUMP_REG(MLB150_REG_ACMR0); - DUMP_REG(MLB150_REG_ACMR1); + DUMP_REG(REG_MLBC0); + DUMP_REG(REG_MLBPC0); + DUMP_REG(REG_MS0); + DUMP_REG(REG_MS1); + DUMP_REG(REG_MSS); + DUMP_REG(REG_MSD); + DUMP_REG(REG_MIEN); + DUMP_REG(REG_MLBPC2); + DUMP_REG(REG_MLBPC1); + DUMP_REG(REG_MLBC1); + DUMP_REG(REG_HCTL); + DUMP_REG(REG_HCMR0); + DUMP_REG(REG_HCMR1); + DUMP_REG(REG_HCER0); + DUMP_REG(REG_HCER1); + DUMP_REG(REG_HCBR0); + DUMP_REG(REG_HCBR1); + DUMP_REG(REG_MDAT0); + DUMP_REG(REG_MDAT1); + DUMP_REG(REG_MDAT2); + DUMP_REG(REG_MDAT3); + DUMP_REG(REG_MDWE0); + DUMP_REG(REG_MDWE1); + DUMP_REG(REG_MDWE2); + DUMP_REG(REG_MDWE3); + DUMP_REG(REG_MCTL); + DUMP_REG(REG_MADR); + DUMP_REG(REG_ACTL); + DUMP_REG(REG_ACSR0); + DUMP_REG(REG_ACSR1); + DUMP_REG(REG_ACMR0); + DUMP_REG(REG_ACMR1); } static void mlb150_dev_dump_hex(const u8 *buf, u32 len) @@ -614,10 +614,10 @@ static void mlb150_dev_dump_hex(const u8 *buf, u32 len) static inline void mlb150_dev_enable_ctr_write(u32 mdat0_bits_en, u32 mdat1_bits_en, u32 mdat2_bits_en, u32 mdat3_bits_en) { - __raw_writel(mdat0_bits_en, mlb_base + MLB150_REG_MDWE0); - __raw_writel(mdat1_bits_en, mlb_base + MLB150_REG_MDWE1); - __raw_writel(mdat2_bits_en, mlb_base + MLB150_REG_MDWE2); - __raw_writel(mdat3_bits_en, mlb_base + MLB150_REG_MDWE3); + __raw_writel(mdat0_bits_en, mlb_base + REG_MDWE0); + __raw_writel(mdat1_bits_en, mlb_base + REG_MDWE1); + __raw_writel(mdat2_bits_en, mlb_base + REG_MDWE2); + __raw_writel(mdat3_bits_en, mlb_base + REG_MDWE3); } static inline u8 mlb150_dev_dbr_read(u32 dbr_addr) @@ -627,20 +627,20 @@ static inline u8 mlb150_dev_dbr_read(u32 dbr_addr) unsigned long flags; spin_lock_irqsave(&ctr_lock, flags); - __raw_writel(MLB150_MADR_TB | dbr_addr, - mlb_base + MLB150_REG_MADR); + __raw_writel(MADR_TB | dbr_addr, + mlb_base + REG_MADR); - while ((!(__raw_readl(mlb_base + MLB150_REG_MCTL) - & MLB150_MCTL_XCMP)) && + while ((!(__raw_readl(mlb_base + REG_MCTL) + & MCTL_XCMP)) && timeout--) ; if (unlikely(0 == timeout)) return -ETIME; - dbr_val = __raw_readl(mlb_base + MLB150_REG_MDAT0) & 0x000000ff; + dbr_val = __raw_readl(mlb_base + REG_MDAT0) & 0x000000ff; - __raw_writel(0, mlb_base + MLB150_REG_MCTL); + __raw_writel(0, mlb_base + REG_MCTL); spin_unlock_irqrestore(&ctr_lock, flags); return dbr_val; @@ -653,20 +653,20 @@ static inline s32 mlb150_dev_dbr_write(u32 dbr_addr, u8 dbr_val) unsigned long flags; spin_lock_irqsave(&ctr_lock, flags); - __raw_writel(mdat0, mlb_base + MLB150_REG_MDAT0); + __raw_writel(mdat0, mlb_base + REG_MDAT0); - __raw_writel(MLB150_MADR_WNR | MLB150_MADR_TB | dbr_addr, - mlb_base + MLB150_REG_MADR); + __raw_writel(MADR_WNR | MADR_TB | dbr_addr, + mlb_base + REG_MADR); - while ((!(__raw_readl(mlb_base + MLB150_REG_MCTL) - & MLB150_MCTL_XCMP)) && + while ((!(__raw_readl(mlb_base + REG_MCTL) + & MCTL_XCMP)) && timeout--) ; if (unlikely(timeout <= 0)) return -ETIME; - __raw_writel(0, mlb_base + MLB150_REG_MCTL); + __raw_writel(0, mlb_base + REG_MCTL); spin_unlock_irqrestore(&ctr_lock, flags); return 0; @@ -678,10 +678,10 @@ static s32 mlb150_dev_ctr_read(u32 ctr_offset, u32 *ctr_val) unsigned long flags; spin_lock_irqsave(&ctr_lock, flags); - __raw_writel(ctr_offset, mlb_base + MLB150_REG_MADR); + __raw_writel(ctr_offset, mlb_base + REG_MADR); - while ((!(__raw_readl(mlb_base + MLB150_REG_MCTL) - & MLB150_MCTL_XCMP)) && + while ((!(__raw_readl(mlb_base + REG_MCTL) + & MCTL_XCMP)) && timeout--) ; @@ -690,12 +690,12 @@ static s32 mlb150_dev_ctr_read(u32 ctr_offset, u32 *ctr_val) return -ETIME; } - ctr_val[0] = __raw_readl(mlb_base + MLB150_REG_MDAT0); - ctr_val[1] = __raw_readl(mlb_base + MLB150_REG_MDAT1); - ctr_val[2] = __raw_readl(mlb_base + MLB150_REG_MDAT2); - ctr_val[3] = __raw_readl(mlb_base + MLB150_REG_MDAT3); + ctr_val[0] = __raw_readl(mlb_base + REG_MDAT0); + ctr_val[1] = __raw_readl(mlb_base + REG_MDAT1); + ctr_val[2] = __raw_readl(mlb_base + REG_MDAT2); + ctr_val[3] = __raw_readl(mlb_base + REG_MDAT3); - __raw_writel(0, mlb_base + MLB150_REG_MCTL); + __raw_writel(0, mlb_base + REG_MCTL); spin_unlock_irqrestore(&ctr_lock, flags); @@ -709,16 +709,16 @@ static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val) spin_lock_irqsave(&ctr_lock, flags); - __raw_writel(ctr_val[0], mlb_base + MLB150_REG_MDAT0); - __raw_writel(ctr_val[1], mlb_base + MLB150_REG_MDAT1); - __raw_writel(ctr_val[2], mlb_base + MLB150_REG_MDAT2); - __raw_writel(ctr_val[3], mlb_base + MLB150_REG_MDAT3); + __raw_writel(ctr_val[0], mlb_base + REG_MDAT0); + __raw_writel(ctr_val[1], mlb_base + REG_MDAT1); + __raw_writel(ctr_val[2], mlb_base + REG_MDAT2); + __raw_writel(ctr_val[3], mlb_base + REG_MDAT3); - __raw_writel(MLB150_MADR_WNR | ctr_offset, - mlb_base + MLB150_REG_MADR); + __raw_writel(MADR_WNR | ctr_offset, + mlb_base + REG_MADR); - while ((!(__raw_readl(mlb_base + MLB150_REG_MCTL) - & MLB150_MCTL_XCMP)) && + while ((!(__raw_readl(mlb_base + REG_MCTL) + & MCTL_XCMP)) && timeout--) ; @@ -727,7 +727,7 @@ static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val) return -ETIME; } - __raw_writel(0, mlb_base + MLB150_REG_MCTL); + __raw_writel(0, mlb_base + REG_MCTL); spin_unlock_irqrestore(&ctr_lock, flags); @@ -762,11 +762,11 @@ static s32 mlb150_dev_get_adt_sts(u32 ch) u32 reg; spin_lock_irqsave(&ctr_lock, flags); - __raw_writel(MLB150_BUF_ADT_OFFSET + ch, - mlb_base + MLB150_REG_MADR); + __raw_writel(BUF_ADT_OFFSET + ch, + mlb_base + REG_MADR); - while ((!(__raw_readl(mlb_base + MLB150_REG_MCTL) - & MLB150_MCTL_XCMP)) && + while ((!(__raw_readl(mlb_base + REG_MCTL) + & MCTL_XCMP)) && timeout--) ; @@ -775,9 +775,9 @@ static s32 mlb150_dev_get_adt_sts(u32 ch) return -ETIME; } - reg = __raw_readl(mlb_base + MLB150_REG_MDAT1); + reg = __raw_readl(mlb_base + REG_MDAT1); - __raw_writel(0, mlb_base + MLB150_REG_MCTL); + __raw_writel(0, mlb_base + REG_MCTL); spin_unlock_irqrestore(&ctr_lock, flags); #ifdef DEBUG_ADT @@ -802,22 +802,22 @@ static s32 mlb150_dev_cat_write(u32 ctr_offset, u32 ch, const u16 cat_val) } #define mlb150_dev_cat_mlb_read(ch, cat_val) \ - mlb150_dev_cat_read(MLB150_BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val) + mlb150_dev_cat_read(BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val) #define mlb150_dev_cat_mlb_write(ch, cat_val) \ - mlb150_dev_cat_write(MLB150_BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val) + mlb150_dev_cat_write(BUF_CAT_MLB_OFFSET + (ch >> 3), ch, cat_val) #define mlb150_dev_cat_hbi_read(ch, cat_val) \ - mlb150_dev_cat_read(MLB150_BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val) + mlb150_dev_cat_read(BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val) #define mlb150_dev_cat_hbi_write(ch, cat_val) \ - mlb150_dev_cat_write(MLB150_BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val) + mlb150_dev_cat_write(BUF_CAT_HBI_OFFSET + (ch >> 3), ch, cat_val) #define mlb150_dev_cdt_read(ch, cdt_val) \ - mlb150_dev_ctr_read(MLB150_BUF_CDT_OFFSET + ch, cdt_val) + mlb150_dev_ctr_read(BUF_CDT_OFFSET + ch, cdt_val) #define mlb150_dev_cdt_write(ch, cdt_val) \ - mlb150_dev_ctr_write(MLB150_BUF_CDT_OFFSET + ch, cdt_val) + mlb150_dev_ctr_write(BUF_CDT_OFFSET + ch, cdt_val) #define mlb150_dev_adt_read(ch, adt_val) \ - mlb150_dev_ctr_read(MLB150_BUF_ADT_OFFSET + ch, adt_val) + mlb150_dev_ctr_read(BUF_ADT_OFFSET + ch, adt_val) #define mlb150_dev_adt_write(ch, adt_val) \ - mlb150_dev_ctr_write(MLB150_BUF_ADT_OFFSET + ch, adt_val) + mlb150_dev_ctr_write(BUF_ADT_OFFSET + ch, adt_val) #ifdef DEBUG static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) @@ -826,8 +826,8 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) u32 ctr_val[4] = { 0 }; pr_debug("mxc_mlb150: CDT Table"); - for (i = MLB150_BUF_CDT_OFFSET + ch_start; - i < MLB150_BUF_CDT_OFFSET + ch_end; + for (i = BUF_CDT_OFFSET + ch_start; + i < BUF_CDT_OFFSET + ch_end; ++i) { mlb150_dev_ctr_read(i, ctr_val); pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", @@ -835,8 +835,8 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) } pr_debug("mxc_mlb150: ADT Table"); - for (i = MLB150_BUF_ADT_OFFSET + ch_start; - i < MLB150_BUF_ADT_OFFSET + ch_end; + for (i = BUF_ADT_OFFSET + ch_start; + i < BUF_ADT_OFFSET + ch_end; ++i) { mlb150_dev_ctr_read(i, ctr_val); pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", @@ -844,8 +844,8 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) } pr_debug("mxc_mlb150: CAT MLB Table"); - for (i = MLB150_BUF_CAT_MLB_OFFSET + (ch_start >> 3); - i < MLB150_BUF_CAT_MLB_OFFSET + (ch_end >> 3) + 1; + for (i = BUF_CAT_MLB_OFFSET + (ch_start >> 3); + i < BUF_CAT_MLB_OFFSET + (ch_end >> 3) + 1; ++i) { mlb150_dev_ctr_read(i, ctr_val); pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", @@ -853,8 +853,8 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) } pr_debug("mxc_mlb150: CAT HBI Table"); - for (i = MLB150_BUF_CAT_HBI_OFFSET + (ch_start >> 3); - i < MLB150_BUF_CAT_HBI_OFFSET + (ch_end >> 3) + 1; + for (i = BUF_CAT_HBI_OFFSET + (ch_start >> 3); + i < BUF_CAT_HBI_OFFSET + (ch_end >> 3) + 1; ++i) { mlb150_dev_ctr_read(i, ctr_val); pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", @@ -869,11 +869,11 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) static inline s32 mlb150_dev_enable_dma_irq(u32 enable) { if (enable) { - __raw_writel(0xffffffff, mlb_base + MLB150_REG_ACMR0); - __raw_writel(0xffffffff, mlb_base + MLB150_REG_ACMR1); + __raw_writel(0xffffffff, mlb_base + REG_ACMR0); + __raw_writel(0xffffffff, mlb_base + REG_ACMR1); } else { - __raw_writel(0x0, mlb_base + MLB150_REG_ACMR0); - __raw_writel(0x0, mlb_base + MLB150_REG_ACMR1); + __raw_writel(0x0, mlb_base + REG_ACMR0); + __raw_writel(0x0, mlb_base + REG_ACMR1); } return 0; @@ -892,10 +892,10 @@ static s32 mlb150_dev_init_ir_amba_ahb(void) * ACTL.SCE = 0, hardware clears on read * ACTL.SCE = 1, software writes a '1' to clear */ /* We only support DMA MODE 1 */ - reg = __raw_readl(mlb_base + MLB150_REG_ACTL); - reg |= MLB150_ACTL_DMAMODE; -#ifdef MLB150_MULTIPLE_PACKAGE_MODE - reg |= MLB150_REG_ACTL_MPB; + reg = __raw_readl(mlb_base + REG_ACTL); + reg |= ACTL_DMAMODE; +#ifdef MULTIPLE_PACKAGE_MODE + reg |= REG_ACTL_MPB; #endif /* Step 3. Select 1 or 2 interrupt signals: @@ -904,10 +904,10 @@ static s32 mlb150_dev_init_ir_amba_ahb(void) * ACTL.SMX = 1: singel interrupt all channels on ahb_init[0] * */ /* - reg |= MLB150_ACTL_SMX; + reg |= ACTL_SMX; */ - __raw_writel(reg, mlb_base + MLB150_REG_ACTL); + __raw_writel(reg, mlb_base + REG_ACTL); return 0; } @@ -916,19 +916,19 @@ static inline s32 mlb150_dev_enable_ir_mlb(u32 enable) { /* Step 1, Select the MSn to be cleared by software, * writing a '0' to the appropriate bits */ - __raw_writel(0, mlb_base + MLB150_REG_MS0); - __raw_writel(0, mlb_base + MLB150_REG_MS1); + __raw_writel(0, mlb_base + REG_MS0); + __raw_writel(0, mlb_base + REG_MS1); /* Step 1, Program MIEN to enable protocol error * interrupts for all active MLB channels */ if (enable) - __raw_writel(MLB150_MIEN_CTX_PE | - MLB150_MIEN_CRX_PE | MLB150_MIEN_ATX_PE | - MLB150_MIEN_ARX_PE | MLB150_MIEN_SYNC_PE | - MLB150_MIEN_ISOC_PE, - mlb_base + MLB150_REG_MIEN); + __raw_writel(MIEN_CTX_PE | + MIEN_CRX_PE | MIEN_ATX_PE | + MIEN_ARX_PE | MIEN_SYNC_PE | + MIEN_ISOC_PE, + mlb_base + REG_MIEN); else - __raw_writel(0, mlb_base + MLB150_REG_MIEN); + __raw_writel(0, mlb_base + REG_MIEN); return 0; } @@ -937,20 +937,20 @@ static inline int mlb150_enable_pll(void) { u32 c0_val; - __raw_writel(MLB150_MLBPC1_VAL, - mlb_base + MLB150_REG_MLBPC1); + __raw_writel(MLBPC1_VAL, + mlb_base + REG_MLBPC1); - c0_val = __raw_readl(mlb_base + MLB150_REG_MLBC0); - if (c0_val & MLB150_MLBC0_MLBPEN) { - c0_val &= ~MLB150_MLBC0_MLBPEN; + c0_val = __raw_readl(mlb_base + REG_MLBC0); + if (c0_val & MLBC0_MLBPEN) { + c0_val &= ~MLBC0_MLBPEN; __raw_writel(c0_val, - mlb_base + MLB150_REG_MLBC0); + mlb_base + REG_MLBC0); } clk_enable(mlb_pll_clk); - c0_val |= (MLB150_MLBC0_MLBPEN); - __raw_writel(c0_val, mlb_base + MLB150_REG_MLBC0); + c0_val |= (MLBC0_MLBPEN); + __raw_writel(c0_val, mlb_base + REG_MLBC0); return 0; } @@ -961,12 +961,12 @@ static inline int mlb150_disable_pll(void) clk_disable(mlb_pll_clk); - c0_val = __raw_readl(mlb_base + MLB150_REG_MLBC0); + c0_val = __raw_readl(mlb_base + REG_MLBC0); - __raw_writel(0x0, mlb_base + MLB150_REG_MLBPC1); + __raw_writel(0x0, mlb_base + REG_MLBPC1); - c0_val &= ~MLB150_MLBC0_MLBPEN; - __raw_writel(c0_val, mlb_base + MLB150_REG_MLBC0); + c0_val &= ~MLBC0_MLBPEN; + __raw_writel(c0_val, mlb_base + REG_MLBC0); return 0; } @@ -976,27 +976,27 @@ static void mlb150_dev_init(void) u32 c0_val, hctl_val; /* Disable EN bits */ - c0_val = __raw_readl(mlb_base + MLB150_REG_MLBC0); - c0_val &= ~MLB150_MLBC0_MLBEN; - __raw_writel(c0_val, mlb_base + MLB150_REG_MLBC0); + c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val &= ~MLBC0_MLBEN; + __raw_writel(c0_val, mlb_base + REG_MLBC0); - hctl_val = __raw_readl(mlb_base + MLB150_REG_HCTL); - hctl_val &= ~MLB150_HCTL_EN; - __raw_writel(hctl_val, mlb_base + MLB150_REG_HCTL); + hctl_val = __raw_readl(mlb_base + REG_HCTL); + hctl_val &= ~HCTL_EN; + __raw_writel(hctl_val, mlb_base + REG_HCTL); /* Step 1, Configure the MediaLB interface */ /* Select pin mode and clock, 3-pin and 256fs */ - c0_val = __raw_readl(mlb_base + MLB150_REG_MLBC0); - c0_val &= ~(MLB150_MLBC0_MLBPEN | MLB150_MLBC0_MLBCLK_MASK); - __raw_writel(c0_val, mlb_base + MLB150_REG_MLBC0); + c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val &= ~(MLBC0_MLBPEN | MLBC0_MLBCLK_MASK); + __raw_writel(c0_val, mlb_base + REG_MLBC0); - c0_val |= MLB150_MLBC0_MLBEN; - __raw_writel(c0_val, mlb_base + MLB150_REG_MLBC0); + c0_val |= MLBC0_MLBEN; + __raw_writel(c0_val, mlb_base + REG_MLBC0); /* Step 2, Configure the HBI interface */ - __raw_writel(0xffffffff, mlb_base + MLB150_REG_HCMR0); - __raw_writel(0xffffffff, mlb_base + MLB150_REG_HCMR1); - __raw_writel(MLB150_HCTL_EN, mlb_base + MLB150_REG_HCTL); + __raw_writel(0xffffffff, mlb_base + REG_HCMR0); + __raw_writel(0xffffffff, mlb_base + REG_HCMR1); + __raw_writel(HCTL_EN, mlb_base + REG_HCTL); mlb150_dev_init_ir_amba_ahb(); @@ -1008,8 +1008,8 @@ static s32 mlb150_dev_reset_cdt(void) int i = 0; u32 ctr_val[4] = { 0 }; - for (i = 0; i < (MLB150_LOGIC_CH_NUM); ++i) - mlb150_dev_ctr_write(MLB150_BUF_CDT_OFFSET + i, ctr_val); + for (i = 0; i < (LOGIC_CH_NUM); ++i) + mlb150_dev_ctr_write(BUF_CDT_OFFSET + i, ctr_val); return 0; } @@ -1029,25 +1029,25 @@ static s32 mlb150_dev_init_ch_cdt(u32 ch, enum MLB_CTYPE ctype, u32 ch_func) switch (ctype) { case MLB_CTYPE_SYNC: /* For synchronous channels: (BD + 1) = 4 * m * bpf */ - cdt_val[3] |= (MLB150_CH_SYNC_BUF_DEP - 1) << CDT_BD_SHIFT; + cdt_val[3] |= (CH_SYNC_BUF_DEP - 1) << CDT_BD_SHIFT; break; case MLB_CTYPE_CTRL: /* For control channels: (BD + 1) >= max packet length (64) */ /* BD */ - cdt_val[3] |= ((MLB150_CH_CTRL_BUF_DEP - 1) << CDT_BD_SHIFT); + cdt_val[3] |= ((CH_CTRL_BUF_DEP - 1) << CDT_BD_SHIFT); break; case MLB_CTYPE_ASYNC: /* For asynchronous channels: (BD + 1) >= max packet length * 1024 for a MOST Data packet (MDP); * 1536 for a MOST Ethernet Packet (MEP) */ - cdt_val[3] |= ((MLB150_CH_ASYNC_BUF_DEP - 1) << CDT_BD_SHIFT); + cdt_val[3] |= ((CH_ASYNC_BUF_DEP - 1) << CDT_BD_SHIFT); break; case MLB_CTYPE_ISOC: /* For isochronous channels: (BD + 1) mod (BS + 1) = 0 */ /* BS */ - cdt_val[1] |= (MLB150_CH_ISOC_BLK_SIZE - 1); + cdt_val[1] |= (CH_ISOC_BLK_SIZE - 1); /* BD */ - cdt_val[3] |= (MLB150_CH_ISOC_BUF_DEP - 1) + cdt_val[3] |= (CH_ISOC_BUF_DEP - 1) << CDT_BD_SHIFT; break; default: @@ -1098,7 +1098,7 @@ static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cat_mode, enum MLB_CTYPE ctype) cat_val = CAT_CE | (ctype << CAT_CT_SHIFT) | ch; - if (cat_mode & MLB150_CAT_MODE_OUTBOUND_DMA) + if (cat_mode & CAT_MODE_OUTBOUND_DMA) cat_val |= CAT_RNW; if (MLB_CTYPE_SYNC == ctype) @@ -1108,8 +1108,8 @@ static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cat_mode, enum MLB_CTYPE ctype) ch, ctype, cat_val); switch (cat_mode) { - case MLB150_CAT_MODE_RX | MLB150_CAT_MODE_INBOUND_DMA: - case MLB150_CAT_MODE_TX | MLB150_CAT_MODE_OUTBOUND_DMA: + case CAT_MODE_RX | CAT_MODE_INBOUND_DMA: + case CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA: if (unlikely(mlb150_dev_cat_mlb_write(ch, cat_val))) return -ETIME; #ifdef DEBUG_CTR @@ -1123,8 +1123,8 @@ static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cat_mode, enum MLB_CTYPE ctype) } #endif break; - case MLB150_CAT_MODE_TX | MLB150_CAT_MODE_INBOUND_DMA: - case MLB150_CAT_MODE_RX | MLB150_CAT_MODE_OUTBOUND_DMA: + case CAT_MODE_TX | CAT_MODE_INBOUND_DMA: + case CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA: if (unlikely(mlb150_dev_cat_hbi_write(ch, cat_val))) return -ETIME; #ifdef DEBUG_CTR @@ -1161,9 +1161,9 @@ static s32 mlb150_dev_reset_cat(void) int i = 0; u32 ctr_val[4] = { 0 }; - for (i = 0; i < (MLB150_LOGIC_CH_NUM >> 3); ++i) { - mlb150_dev_ctr_write(MLB150_BUF_CAT_MLB_OFFSET + i, ctr_val); - mlb150_dev_ctr_write(MLB150_BUF_CAT_HBI_OFFSET + i, ctr_val); + for (i = 0; i < (LOGIC_CH_NUM >> 3); ++i) { + mlb150_dev_ctr_write(BUF_CAT_MLB_OFFSET + i, ctr_val); + mlb150_dev_ctr_write(BUF_CAT_HBI_OFFSET + i, ctr_val); } return 0; @@ -1182,16 +1182,16 @@ static s32 mlb150_dev_init_rfb(u32 rx_ch, u32 tx_ch, enum MLB_CTYPE ctype) /* Step 4&5, Program the CAT for the inbound and outbound DMA */ mlb150_dev_init_ch_cat(rx_ch, - MLB150_CAT_MODE_RX | MLB150_CAT_MODE_INBOUND_DMA, + CAT_MODE_RX | CAT_MODE_INBOUND_DMA, ctype); mlb150_dev_init_ch_cat(rx_ch, - MLB150_CAT_MODE_RX | MLB150_CAT_MODE_OUTBOUND_DMA, + CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA, ctype); mlb150_dev_init_ch_cat(tx_ch, - MLB150_CAT_MODE_TX | MLB150_CAT_MODE_INBOUND_DMA, + CAT_MODE_TX | CAT_MODE_INBOUND_DMA, ctype); mlb150_dev_init_ch_cat(tx_ch, - MLB150_CAT_MODE_TX | MLB150_CAT_MODE_OUTBOUND_DMA, + CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA, ctype); return 0; @@ -1202,8 +1202,8 @@ static s32 mlb150_dev_reset_adt(void) int i = 0; u32 ctr_val[4] = { 0 }; - for (i = 0; i < (MLB150_LOGIC_CH_NUM); ++i) - mlb150_dev_ctr_write(MLB150_BUF_ADT_OFFSET + i, ctr_val); + for (i = 0; i < (LOGIC_CH_NUM); ++i) + mlb150_dev_ctr_write(BUF_ADT_OFFSET + i, ctr_val); return 0; } @@ -1344,16 +1344,16 @@ static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 tx_ch) /* Check that MediaLB clock is running (MLBC1.CLKM = 0) * If MLBC1.CLKM = 1, clear the register bit, wait one * APB or I/O clock cycle and repeat the check */ - while ((__raw_readl(mlb_base + MLB150_REG_MLBC1) & MLB150_MLBC1_CLKM) + while ((__raw_readl(mlb_base + REG_MLBC1) & MLBC1_CLKM) || timeout--) - __raw_writel(~MLB150_MLBC1_CLKM, mlb_base + MLB150_REG_MLBC1); + __raw_writel(~MLBC1_CLKM, mlb_base + REG_MLBC1); if (unlikely(0 == timeout)) return -ETIME; timeout = 10000; /* Poll for MLB lock (MLBC0.MLBLK = 1) */ - while (!(__raw_readl(mlb_base + MLB150_REG_MLBC0) & MLB150_MLBC0_MLBLK) + while (!(__raw_readl(mlb_base + REG_MLBC0) & MLBC0_MLBLK) || timeout--) ; @@ -1376,8 +1376,8 @@ static void mlb150_dev_exit(void) mlb150_dev_enable_dma_irq(0); mlb150_dev_enable_ir_mlb(0); - __raw_writel(0, mlb_base + MLB150_REG_HCTL); - __raw_writel(0, mlb_base + MLB150_REG_MLBC0); + __raw_writel(0, mlb_base + REG_HCTL); + __raw_writel(0, mlb_base + REG_MLBC0); } /*! @@ -1435,7 +1435,7 @@ static void mlb_channel_enable(int chan_dev_id, int on) ADT_PS2 | ADT_MEP2, 0xffffffff, 0xffffffff); - if (pdevinfo->fps >= MLB150_CLK_2048FS) + if (pdevinfo->fps >= CLK_2048FS) mlb150_enable_pll(); atomic_set(&pdevinfo->on, 1); @@ -1454,7 +1454,7 @@ static void mlb_channel_enable(int chan_dev_id, int on) atomic_set(&mlb_devinfo[chan_dev_id].on, 0); - if (mlb_devinfo[chan_dev_id].fps >= MLB150_CLK_2048FS) + if (mlb_devinfo[chan_dev_id].fps >= CLK_2048FS) mlb150_disable_pll(); } } @@ -1536,17 +1536,17 @@ static irqreturn_t mlb_ahb_isr(int irq, void *dev_id) /* Step 5, Read the ACSRn registers to determine which channel or * channels are causing the interrupt */ - acsr0 = __raw_readl(mlb_base + MLB150_REG_ACSR0); - acsr1 = __raw_readl(mlb_base + MLB150_REG_ACSR1); + acsr0 = __raw_readl(mlb_base + REG_ACSR0); + acsr1 = __raw_readl(mlb_base + REG_ACSR1); - hcer0 = __raw_readl(mlb_base + MLB150_REG_HCER0); - hcer1 = __raw_readl(mlb_base + MLB150_REG_HCER1); + hcer0 = __raw_readl(mlb_base + REG_HCER0); + hcer1 = __raw_readl(mlb_base + REG_HCER1); /* Step 6, If ACTL.SCE = 1, write the result of step 5 back to ACSR0 * and ACSR1 to clear the interrupt */ - if (MLB150_ACTL_SCE & __raw_readl(mlb_base + MLB150_REG_ACTL)) { - __raw_writel(acsr0, mlb_base + MLB150_REG_ACSR0); - __raw_writel(acsr1, mlb_base + MLB150_REG_ACSR1); + if (ACTL_SCE & __raw_readl(mlb_base + REG_ACTL)) { + __raw_writel(acsr0, mlb_base + REG_ACSR0); + __raw_writel(acsr1, mlb_base + REG_ACSR1); } for (minor = 0; minor < MLB_MINOR_DEVICES; minor++) { @@ -1593,8 +1593,8 @@ static irqreturn_t mlb_isr(int irq, void *dev_id) /* Step 4, Read the MSn register to determine which channel(s) * are causing the interrupt */ - ms0 = __raw_readl(mlb_base + MLB150_REG_MS0); - ms1 = __raw_readl(mlb_base + MLB150_REG_MS1); + ms0 = __raw_readl(mlb_base + REG_MS0); + ms1 = __raw_readl(mlb_base + REG_MS1); pr_debug("mxc_mlb150: mlb interrupt:0x%08x 0x%08x\n", (u32)ms0, (u32)ms1); @@ -1869,8 +1869,8 @@ static long mxc_mlb150_ioctl(struct file *filp, if (plat_data->fps_sel) plat_data->fps_sel(fps); - c0_val = __raw_readl(mlb_base + MLB150_REG_MLBC0); - c0_val &= ~MLB150_MLBC0_MLBCLK_MASK; + c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val &= ~MLBC0_MLBCLK_MASK; /* check fps value */ switch (fps) { @@ -1878,26 +1878,26 @@ static long mxc_mlb150_ioctl(struct file *filp, case 512: case 1024: mlb_devinfo[minor].fps = fps >> 9; - c0_val &= ~MLB150_MLBC0_MLBPEN; + c0_val &= ~MLBC0_MLBPEN; c0_val |= (fps >> 9) - << MLB150_MLBC0_MLBCLK_SHIFT; + << MLBC0_MLBCLK_SHIFT; break; case 2048: case 3072: case 4096: mlb_devinfo[minor].fps = (fps >> 10) + 1; c0_val |= ((fps >> 10) + 1) - << MLB150_MLBC0_MLBCLK_SHIFT; + << MLBC0_MLBCLK_SHIFT; break; case 6144: mlb_devinfo[minor].fps = fps >> 10; c0_val |= ((fps >> 10) + 1) - << MLB150_MLBC0_MLBCLK_SHIFT; + << MLBC0_MLBCLK_SHIFT; break; case 8192: mlb_devinfo[minor].fps = (fps >> 10) - 1; c0_val |= ((fps >> 10) - 1) - << MLB150_MLBC0_MLBCLK_SHIFT; + << MLBC0_MLBCLK_SHIFT; break; default: pr_debug("mxc_mlb150: invalid fps argument: %d\n", @@ -1905,11 +1905,11 @@ static long mxc_mlb150_ioctl(struct file *filp, return -EINVAL; } - __raw_writel(c0_val, mlb_base + MLB150_REG_MLBC0); + __raw_writel(c0_val, mlb_base + REG_MLBC0); pr_debug("mxc_mlb150: set fps to %d, MLBC0: 0x%08x\n", fps, - (u32)__raw_readl(mlb_base + MLB150_REG_MLBC0)); + (u32)__raw_readl(mlb_base + REG_MLBC0)); break; } @@ -1943,13 +1943,13 @@ static long mxc_mlb150_ioctl(struct file *filp, return -EFAULT; } - c1_val = __raw_readl(mlb_base + MLB150_REG_MLBC1); - c1_val &= ~MLB150_MLBC1_NDA_MASK; - c1_val |= devaddr << MLB150_MLBC1_NDA_SHIFT; - __raw_writel(c1_val, mlb_base + MLB150_REG_MLBC1); + c1_val = __raw_readl(mlb_base + REG_MLBC1); + c1_val &= ~MLBC1_NDA_MASK; + c1_val |= devaddr << MLBC1_NDA_SHIFT; + __raw_writel(c1_val, mlb_base + REG_MLBC1); pr_debug("mxc_mlb150: set dev addr, dev addr: %d, " "MLBC1: 0x%08x\n", devaddr, - (u32)__raw_readl(mlb_base + MLB150_REG_MLBC1)); + (u32)__raw_readl(mlb_base + REG_MLBC1)); break; } -- cgit v1.2.3 From b297cf95f1c837a9d61c92f121b86d5406682d02 Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Fri, 12 Apr 2013 12:16:10 +0800 Subject: ENGR00258357-2: mlb: Add more debug msgs in DEBUG mode Changes are: 1. Use print_hex_dump to print buffer in DEBUG mode. 2. Add more debug msgs. Signed-off-by: Terry Lv --- drivers/mxc/mlb/mxc_mlb150.c | 211 ++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 124 deletions(-) diff --git a/drivers/mxc/mlb/mxc_mlb150.c b/drivers/mxc/mlb/mxc_mlb150.c index 580480e1ca57..3fbba6d91155 100755 --- a/drivers/mxc/mlb/mxc_mlb150.c +++ b/drivers/mxc/mlb/mxc_mlb150.c @@ -288,25 +288,6 @@ enum CLK_SPEED { CLK_8192FS, }; -/*! - * Ring buffer - */ -#define MLB_RING_BUF_INIT(r) { \ - r->wpos = 0; \ - r->rpos = 0; \ -} - -#define MLB_RING_BUF_IS_FULL(r) (((r->wpos + 1) % TRANS_RING_NODES) == r->rpos) -#define MLB_RING_BUF_IS_EMPTY(r) (r->rpos == r->wpos) -#define MLB_RING_BUF_ENQUE(r, buf) { \ - memcpy(r->node[r->wpos].data, buf, r->node.size); \ - r->wpos = (r->wpos + 1) % TRANS_RING_NODES; \ -} -#define MLB_RING_BUF_DEQUE(r, buf) { \ - memcpy(buf, r->node[r->rpos].data, r->node.size); \ - r->rpos = (r->rpos + 1) % TRANS_RING_NODES; \ -} - struct mlb_ringbuf { u32 wpos; u32 rpos; @@ -532,82 +513,8 @@ static void mlb150_dev_dump_reg(void) static void mlb150_dev_dump_hex(const u8 *buf, u32 len) { - u32 i, remain, round_len; - - pr_debug("buf: 0x%08x, len: %d\n", (u32)buf, len); - remain = len & 0x7; - round_len = len - remain; - for (i = 0; i < round_len; i += 8) { - pr_debug("%02x %02x %02x %02x %02x %02x %02x %02x\n", - *(buf + i), - *(buf + i + 1), - *(buf + i + 2), - *(buf + i + 3), - *(buf + i + 4), - *(buf + i + 5), - *(buf + i + 6), - *(buf + i + 7)); - } - - if (remain) { - i = round_len; - switch (remain) { - case 1: - pr_debug("%02x\n", - *(buf + i)); - break; - case 2: - pr_debug("%02x %02x\n", - *(buf + i), - *(buf + i + 1)); - break; - case 3: - pr_debug("%02x %02x %02x\n", - *(buf + i), - *(buf + i + 1), - *(buf + i + 2)); - break; - case 4: - pr_debug("%02x %02x %02x %02x\n", - *(buf + i), - *(buf + i + 1), - *(buf + i + 2), - *(buf + i + 3)); - break; - case 5: - pr_debug("%02x %02x %02x %02x %02x\n", - *(buf + i), - *(buf + i + 1), - *(buf + i + 2), - *(buf + i + 3), - *(buf + i + 4)); - break; - case 6: - pr_debug("%02x %02x %02x %02x %02x %02x\n", - *(buf + i), - *(buf + i + 1), - *(buf + i + 2), - *(buf + i + 3), - *(buf + i + 4), - *(buf + i + 5)); - break; - case 7: - pr_debug("%02x %02x %02x %02x %02x %02x %02x\n", - *(buf + i), - *(buf + i + 1), - *(buf + i + 2), - *(buf + i + 3), - *(buf + i + 4), - *(buf + i + 5), - *(buf + i + 6)); - break; - default: - break; - } - } - - if (i % 8 != 0) - pr_debug("\n"); + print_hex_dump(KERN_DEBUG, "CTR DUMP:", + DUMP_PREFIX_OFFSET, 8, 1, buf, len, 0); } #endif @@ -620,6 +527,7 @@ static inline void mlb150_dev_enable_ctr_write(u32 mdat0_bits_en, __raw_writel(mdat3_bits_en, mlb_base + REG_MDWE3); } +#ifdef DEBUG static inline u8 mlb150_dev_dbr_read(u32 dbr_addr) { s32 timeout = 1000; @@ -635,7 +543,8 @@ static inline u8 mlb150_dev_dbr_read(u32 dbr_addr) timeout--) ; - if (unlikely(0 == timeout)) + if (0 == timeout) { + spin_unlock_irqrestore(&ctr_lock, flags); return -ETIME; dbr_val = __raw_readl(mlb_base + REG_MDAT0) & 0x000000ff; @@ -663,8 +572,10 @@ static inline s32 mlb150_dev_dbr_write(u32 dbr_addr, u8 dbr_val) timeout--) ; - if (unlikely(timeout <= 0)) + if (timeout <= 0) { + spin_unlock_irqrestore(&ctr_lock, flags); return -ETIME; + } __raw_writel(0, mlb_base + REG_MCTL); spin_unlock_irqrestore(&ctr_lock, flags); @@ -672,6 +583,30 @@ static inline s32 mlb150_dev_dbr_write(u32 dbr_addr, u8 dbr_val) return 0; } +static inline s32 mlb150_dev_dbr_dump(u32 addr, u32 size) +{ + u8 *dump_buf = NULL; + u8 *buf_ptr = NULL; + s32 i; + + dump_buf = kzalloc(size, GFP_KERNEL); + if (!dump_buf) { + pr_err("can't allocate enough memory\n"); + return -ENOMEM; + } + + for (i = 0, buf_ptr = dump_buf; + i < size; ++i, ++buf_ptr) + *buf_ptr = mlb150_dev_dbr_read(addr + i); + + mlb150_dev_dump_hex(dump_buf, size); + + kfree(dump_buf); + + return 0; +} +#endif + static s32 mlb150_dev_ctr_read(u32 ctr_offset, u32 *ctr_val) { s32 timeout = 1000; @@ -685,7 +620,8 @@ static s32 mlb150_dev_ctr_read(u32 ctr_offset, u32 *ctr_val) timeout--) ; - if (unlikely(timeout <= 0)) { + if (timeout <= 0) { + spin_unlock_irqrestore(&ctr_lock, flags); pr_debug("mxc_mlb150: Read CTR timeout\n"); return -ETIME; } @@ -722,7 +658,8 @@ static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val) timeout--) ; - if (unlikely(timeout <= 0)) { + if (timeout <= 0) { + spin_unlock_irqrestore(&ctr_lock, flags); pr_debug("mxc_mlb150: Write CTR timeout\n"); return -ETIME; } @@ -743,6 +680,13 @@ static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val) return 0; else { pr_debug("mxc_mlb150: ctr write failed\n"); + pr_debug("offset: 0x%x\n", ctr_offset); + pr_debug("Write: 0x%x 0x%x 0x%x 0x%x\n", + ctr_val[3], ctr_val[2], + ctr_val[1], ctr_val[0]); + pr_debug("Read: 0x%x 0x%x 0x%x 0x%x\n", + ctr_rd[3], ctr_rd[2], + ctr_rd[1], ctr_rd[0]); return -EBADE; } } else { @@ -755,37 +699,23 @@ static s32 mlb150_dev_ctr_write(u32 ctr_offset, const u32 *ctr_val) return 0; } -static s32 mlb150_dev_get_adt_sts(u32 ch) +#ifdef DEBUG +static s32 mlb150_dev_cat_read(u32 ctr_offset, u32 ch, u16 *cat_val) { - s32 timeout = 1000; - unsigned long flags; - u32 reg; - - spin_lock_irqsave(&ctr_lock, flags); - __raw_writel(BUF_ADT_OFFSET + ch, - mlb_base + REG_MADR); - - while ((!(__raw_readl(mlb_base + REG_MCTL) - & MCTL_XCMP)) && - timeout--) - ; + u16 ctr_val[8] = { 0 }; - if (unlikely(timeout <= 0)) { - pr_debug("mxc_mlb150: Read CTR timeout\n"); + if (mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val)) return -ETIME; - } - - reg = __raw_readl(mlb_base + REG_MDAT1); - - __raw_writel(0, mlb_base + REG_MCTL); - spin_unlock_irqrestore(&ctr_lock, flags); -#ifdef DEBUG_ADT - pr_debug("mxc_mlb150: Get ch %d adt sts: 0x%08x\n", ch, reg); -#endif + /* + * Use u16 array to get u32 array value, + * need to convert + * */ + cat_val = ctr_val[ch % 8]; - return reg; + return 0; } +#endif static s32 mlb150_dev_cat_write(u32 ctr_offset, u32 ch, const u16 cat_val) { @@ -819,6 +749,39 @@ static s32 mlb150_dev_cat_write(u32 ctr_offset, u32 ch, const u16 cat_val) #define mlb150_dev_adt_write(ch, adt_val) \ mlb150_dev_ctr_write(BUF_ADT_OFFSET + ch, adt_val) +static s32 mlb150_dev_get_adt_sts(u32 ch) +{ + s32 timeout = 1000; + unsigned long flags; + u32 reg; + + spin_lock_irqsave(&ctr_lock, flags); + __raw_writel(BUF_ADT_OFFSET + ch, + mlb_base + REG_MADR); + + while ((!(__raw_readl(mlb_base + REG_MCTL) + & MCTL_XCMP)) && + timeout--) + ; + + if (timeout <= 0) { + spin_unlock_irqrestore(&ctr_lock, flags); + pr_debug("mxc_mlb150: Read CTR timeout\n"); + return -ETIME; + } + + reg = __raw_readl(mlb_base + REG_MDAT1); + + __raw_writel(0, mlb_base + REG_MCTL); + spin_unlock_irqrestore(&ctr_lock, flags); + +#ifdef DEBUG_ADT + pr_debug("mxc_mlb150: Get ch %d adt sts: 0x%08x\n", ch, reg); +#endif + + return reg; +} + #ifdef DEBUG static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) { -- cgit v1.2.3 From 5f4d5dc2175730d8f992d4e37a8f42ed17437339 Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Fri, 12 Apr 2013 15:18:50 +0800 Subject: ENGR00258357-3: mlb: Reset whole CDR in init function Reset whole CDR in init function. This will make mlb connection to MITB more stable. This is a missed part in mx6 rm's mlb section, but new in mlb's latest spec DS62420AP2.pdf 12.1.1-1. Without this patch, mlb may receive irq from MITB during initialization. It might cause some connection issue that mlb can't receive data sometimes. It was treat to be MITB's fault before we get the latest spec. Signed-off-by: Terry Lv --- drivers/mxc/mlb/mxc_mlb150.c | 191 ++++++++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 46 deletions(-) diff --git a/drivers/mxc/mlb/mxc_mlb150.c b/drivers/mxc/mlb/mxc_mlb150.c index 3fbba6d91155..5f6f0e57230c 100755 --- a/drivers/mxc/mlb/mxc_mlb150.c +++ b/drivers/mxc/mlb/mxc_mlb150.c @@ -142,6 +142,9 @@ #define REG_CAT_MDATn(ch) (REG_MDAT0 + ((ch % 8) >> 1) * 4) #define REG_CAT_MDWEn(ch) (REG_MDWE0 + ((ch % 8) >> 1) * 4) +#define INT_AHB0_CH_START (0) +#define INT_AHB1_CH_START (32) + #define LOGIC_CH_NUM (64) #define BUF_CDT_OFFSET (0x0) #define BUF_ADT_OFFSET (0x40) @@ -246,11 +249,6 @@ static u32 mlb150_ch_packet_buf_size[4] = { #define ADT_MEP1 (0x1 << 11) #define ADT_MEP2 (0x1 << 27) -#define MLB_CONTROL_TX_CHANN (0 << 4) -#define MLB_CONTROL_RX_CHANN (1 << 4) -#define MLB_ASYNC_TX_CHANN (2 << 4) -#define MLB_ASYNC_RX_CHANN (3 << 4) - #define MLB_MINOR_DEVICES 4 #define MLB_CONTROL_DEV_NAME "ctrl" #define MLB_ASYNC_DEV_NAME "async" @@ -352,6 +350,23 @@ struct mlb_dev_info { spinlock_t event_lock; }; +#define SYNC_RX_CL_AHB0 0 +#define CTRL_RX_CL_AHB0 1 +#define ASYNC_RX_CL_AHB0 2 +#define ISOC_RX_CL_AHB0 3 +#define SYNC_TX_CL_AHB0 4 +#define CTRL_TX_CL_AHB0 5 +#define ASYNC_TX_CL_AHB0 6 +#define ISOC_TX_CL_AHB0 7 + +#define SYNC_RX_CL_AHB1 32 +#define CTRL_RX_CL_AHB1 33 +#define ASYNC_RX_CL_AHB1 34 +#define ISOC_RX_CL_AHB1 35 +#define SYNC_TX_CL_AHB1 36 +#define CTRL_TX_CL_AHB1 37 +#define ASYNC_TX_CL_AHB1 38 +#define ISOC_TX_CL_AHB1 39 static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { { .dev_name = MLB_SYNC_DEV_NAME, @@ -934,43 +949,14 @@ static inline int mlb150_disable_pll(void) return 0; } -static void mlb150_dev_init(void) -{ - u32 c0_val, hctl_val; - - /* Disable EN bits */ - c0_val = __raw_readl(mlb_base + REG_MLBC0); - c0_val &= ~MLBC0_MLBEN; - __raw_writel(c0_val, mlb_base + REG_MLBC0); - - hctl_val = __raw_readl(mlb_base + REG_HCTL); - hctl_val &= ~HCTL_EN; - __raw_writel(hctl_val, mlb_base + REG_HCTL); - - /* Step 1, Configure the MediaLB interface */ - /* Select pin mode and clock, 3-pin and 256fs */ - c0_val = __raw_readl(mlb_base + REG_MLBC0); - c0_val &= ~(MLBC0_MLBPEN | MLBC0_MLBCLK_MASK); - __raw_writel(c0_val, mlb_base + REG_MLBC0); - - c0_val |= MLBC0_MLBEN; - __raw_writel(c0_val, mlb_base + REG_MLBC0); - - /* Step 2, Configure the HBI interface */ - __raw_writel(0xffffffff, mlb_base + REG_HCMR0); - __raw_writel(0xffffffff, mlb_base + REG_HCMR1); - __raw_writel(HCTL_EN, mlb_base + REG_HCTL); - - mlb150_dev_init_ir_amba_ahb(); - - mlb150_dev_enable_ir_mlb(1); -} - static s32 mlb150_dev_reset_cdt(void) { int i = 0; u32 ctr_val[4] = { 0 }; + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff); + for (i = 0; i < (LOGIC_CH_NUM); ++i) mlb150_dev_ctr_write(BUF_CDT_OFFSET + i, ctr_val); @@ -1124,6 +1110,9 @@ static s32 mlb150_dev_reset_cat(void) int i = 0; u32 ctr_val[4] = { 0 }; + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff); + for (i = 0; i < (LOGIC_CH_NUM >> 3); ++i) { mlb150_dev_ctr_write(BUF_CAT_MLB_OFFSET + i, ctr_val); mlb150_dev_ctr_write(BUF_CAT_HBI_OFFSET + i, ctr_val); @@ -1165,12 +1154,66 @@ static s32 mlb150_dev_reset_adt(void) int i = 0; u32 ctr_val[4] = { 0 }; + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff); + for (i = 0; i < (LOGIC_CH_NUM); ++i) mlb150_dev_ctr_write(BUF_ADT_OFFSET + i, ctr_val); return 0; } +static s32 mlb150_dev_reset_whole_ctr(void) +{ + mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff); + mlb150_dev_reset_cdt(); + mlb150_dev_reset_adt(); + mlb150_dev_reset_cat(); + + return 0; +} + +#define CLR_REG(reg) __raw_writel(0x0, mlb_base + reg) + +static s32 mlb150_dev_reset_all_regs(void) +{ + CLR_REG(REG_MLBC0); + CLR_REG(REG_MLBPC0); + CLR_REG(REG_MS0); + CLR_REG(REG_MS1); + CLR_REG(REG_MSS); + CLR_REG(REG_MSD); + CLR_REG(REG_MIEN); + CLR_REG(REG_MLBPC2); + CLR_REG(REG_MLBPC1); + CLR_REG(REG_MLBC1); + CLR_REG(REG_HCTL); + CLR_REG(REG_HCMR0); + CLR_REG(REG_HCMR1); + CLR_REG(REG_HCER0); + CLR_REG(REG_HCER1); + CLR_REG(REG_HCBR0); + CLR_REG(REG_HCBR1); + CLR_REG(REG_MDAT0); + CLR_REG(REG_MDAT1); + CLR_REG(REG_MDAT2); + CLR_REG(REG_MDAT3); + CLR_REG(REG_MDWE0); + CLR_REG(REG_MDWE1); + CLR_REG(REG_MDWE2); + CLR_REG(REG_MDWE3); + CLR_REG(REG_MCTL); + CLR_REG(REG_MADR); + CLR_REG(REG_ACTL); + CLR_REG(REG_ACSR0); + CLR_REG(REG_ACSR1); + CLR_REG(REG_ACMR0); + CLR_REG(REG_ACMR1); + + return 0; +} + static inline s32 mlb150_dev_set_ch_amba_ahb(u32 ch, enum MLB_CTYPE ctype, u32 dne_sts, u32 buf_addr) { @@ -1300,6 +1343,71 @@ static s32 mlb150_dev_init_amba_ahb(struct mlb_channel_info *rx_chinfo, return 0; } +static void mlb150_dev_exit(void) +{ + u32 c0_val, hctl_val; + + /* Disable EN bits */ + c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val &= ~(MLBC0_MLBEN | MLBC0_MLBPEN); + __raw_writel(c0_val, mlb_base + REG_MLBC0); + + hctl_val = __raw_readl(mlb_base + REG_HCTL); + hctl_val &= ~HCTL_EN; + __raw_writel(hctl_val, mlb_base + REG_HCTL); + + __raw_writel(0x0, mlb_base + REG_HCMR0); + __raw_writel(0x0, mlb_base + REG_HCMR1); + + mlb150_dev_enable_dma_irq(0); + mlb150_dev_enable_ir_mlb(0); +} + +static void mlb150_dev_init(void) +{ + u32 c0_val; + u32 ch_rx_mask = (1 << SYNC_RX_CL_AHB0) | (1 << CTRL_RX_CL_AHB0) + | (1 << ASYNC_RX_CL_AHB0) | (1 << ISOC_RX_CL_AHB0) + | (1 << SYNC_TX_CL_AHB0) | (1 << CTRL_TX_CL_AHB0) + | (1 << ASYNC_TX_CL_AHB0) | (1 << ISOC_TX_CL_AHB0); + u32 ch_tx_mask = (1 << (SYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (CTRL_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ASYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ISOC_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (SYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (CTRL_TX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ASYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ISOC_TX_CL_AHB1 - INT_AHB1_CH_START)); + + /* Disable EN bits */ + mlb150_dev_exit(); + + /* Step 1. Initialize CTR and registers + * a. Set all bit of the CTR (CAT, CDT, and ADT) to 0. */ + mlb150_dev_reset_whole_ctr(); + + /* a. Set all bit of the CTR (CAT, CDT, and ADT) to 0. */ + mlb150_dev_reset_all_regs(); + + /* Step 2, Configure the MediaLB interface */ + /* Select pin mode and clock, 3-pin and 256fs */ + c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val &= ~(MLBC0_MLBPEN | MLBC0_MLBCLK_MASK); + __raw_writel(c0_val, mlb_base + REG_MLBC0); + + c0_val |= MLBC0_MLBEN; + __raw_writel(c0_val, mlb_base + REG_MLBC0); + + /* Step 3, Configure the HBI interface */ + __raw_writel(ch_rx_mask, mlb_base + REG_HCMR0); + __raw_writel(ch_tx_mask, mlb_base + REG_HCMR1); + __raw_writel(HCTL_EN, mlb_base + REG_HCTL); + + mlb150_dev_init_ir_amba_ahb(); + + mlb150_dev_enable_ir_mlb(1); +} + static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 tx_ch) { u32 timeout = 10000; @@ -1334,15 +1442,6 @@ static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 tx_ch) return 0; } -static void mlb150_dev_exit(void) -{ - mlb150_dev_enable_dma_irq(0); - mlb150_dev_enable_ir_mlb(0); - - __raw_writel(0, mlb_base + REG_HCTL); - __raw_writel(0, mlb_base + REG_MLBC0); -} - /*! * MLB receive start function * -- cgit v1.2.3 From b4570bd7fce38384f01eed2a0cd5ff1c28165ad8 Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Fri, 12 Apr 2013 15:33:56 +0800 Subject: ENGR00258357-4: mlb: Group static variables to structure mlb_data Group static variables to structure mlb_data. Use mlb_data as platform data to be passed to file operation functions. Change accordingly functions for this change. Signed-off-by: Terry Lv --- drivers/mxc/mlb/mxc_mlb150.c | 969 ++++++++++++++++++++++++------------------- 1 file changed, 536 insertions(+), 433 deletions(-) diff --git a/drivers/mxc/mlb/mxc_mlb150.c b/drivers/mxc/mlb/mxc_mlb150.c index 5f6f0e57230c..4fa3ff873e1f 100755 --- a/drivers/mxc/mlb/mxc_mlb150.c +++ b/drivers/mxc/mlb/mxc_mlb150.c @@ -52,7 +52,7 @@ #define MLBC0_ASYRETRY (0x1 << 12) #define MLBC0_CTLRETRY (0x1 << 12) #define MLBC0_FCNT_MASK (0x7 << 15) -#define MLBC0_FCNT_SHIFT (15) +#define MLBC0_FCNT_SHIFT (15) #define REG_MLBPC0 0x8 #define MLBPC0_MCLKHYS (0x1 << 11) @@ -70,7 +70,7 @@ #define REG_MSD 0x24 -#define REG_MIEN 0x2C +#define REG_MIEN 0x2C #define MIEN_ISOC_PE (0x1) #define MIEN_ISOC_BUFO (0x1 << 1) #define MIEN_SYNC_PE (0x1 << 16) @@ -97,7 +97,7 @@ #define MLBC1_NDA_MASK (0xFF << 8) #define MLBC1_NDA_SHIFT (8) -#define REG_HCTL 0x80 +#define REG_HCTL 0x80 #define HCTL_RST0 (0x1) #define HCTL_RST1 (0x1 << 1) #define HCTL_EN (0x1 << 15) @@ -119,20 +119,20 @@ #define REG_MDWE2 0xD8 #define REG_MDWE3 0xDC -#define REG_MCTL 0xE0 +#define REG_MCTL 0xE0 #define MCTL_XCMP (0x1) -#define REG_MADR 0xE4 -#define MADR_WNR (0x1 << 31) +#define REG_MADR 0xE4 +#define MADR_WNR (0x1 << 31) #define MADR_TB (0x1 << 30) #define MADR_ADDR_MASK (0x7f << 8) #define MADR_ADDR_SHIFT (0) -#define REG_ACTL 0x3C0 -#define ACTL_MPB (0x1 << 4) +#define REG_ACTL 0x3C0 +#define ACTL_MPB (0x1 << 4) #define ACTL_DMAMODE (0x1 << 2) -#define ACTL_SMX (0x1 << 1) -#define ACTL_SCE (0x1) +#define ACTL_SMX (0x1 << 1) +#define ACTL_SCE (0x1) #define REG_ACSR0 0x3D0 #define REG_ACSR1 0x3D4 @@ -182,9 +182,9 @@ static u32 mlb150_ch_packet_buf_size[4] = { #define ADT_LEN (16) #define CAT_LEN (2) -#define CDT_SZ (CDT_LEN * LOGIC_CH_NUM) -#define ADT_SZ (ADT_LEN * LOGIC_CH_NUM) -#define CAT_SZ (CAT_LEN * LOGIC_CH_NUM * 2) +#define CDT_SZ (CDT_LEN * LOGIC_CH_NUM) +#define ADT_SZ (ADT_LEN * LOGIC_CH_NUM) +#define CAT_SZ (CAT_LEN * LOGIC_CH_NUM * 2) #define CDT_BASE(base) (base + BUF_CDT_OFFSET) #define ADT_BASE(base) (base + BUF_ADT_OFFSET) @@ -262,7 +262,8 @@ static u32 mlb150_ch_packet_buf_size[4] = { /* max package data size */ #define ASYNC_PACKET_SIZE 1024 #define CTRL_PACKET_SIZE 64 -#define TRANS_RING_NODES 10 + +#define TRANS_RING_NODES (1 << 3) #define MLB_IRAM_SIZE (MLB_MINOR_DEVICES * (PING_BUF_MAX_SIZE + PONG_BUF_MAX_SIZE)) #define _get_txchan(dev) mlb_devinfo[dev].channels[TX_CHANNEL] @@ -287,40 +288,22 @@ enum CLK_SPEED { }; struct mlb_ringbuf { - u32 wpos; - u32 rpos; - u32 size; - /* Last buffer is for package drop */ - u8 *virt_bufs[TRANS_RING_NODES + 1]; + s8 *virt_bufs[TRANS_RING_NODES + 1]; u32 phy_addrs[TRANS_RING_NODES + 1]; + s32 head; + s32 tail; + s32 unit_size; + s32 total_size; + rwlock_t rb_lock ____cacheline_aligned; /* ring index lock */ }; struct mlb_channel_info { - - /* channel address */ - s32 address; + /* Input MLB channel address */ + u32 address; + /* Internal AHB channel label */ + u32 cl; /* DBR buf head */ u32 dbr_buf_head; - /* ping buffer head */ - u32 ping_buf_head; - /* pong buffer head */ - u32 pong_buf_head; - /* ping buffer physical head */ - u32 ping_phy_head; - /* pong buffer physical head */ - u32 pong_phy_head; - /* channel buffer size */ - u32 buf_size; - /* channel buffer current ptr */ - u32 buf_ptr; - /* channel buffer phy addr */ - u32 buf_phy_addr; - /* packet start indicator */ - u32 ps_ind; - /* packet remain size */ - u32 pkt_remain_size; - /* buffer spin lock */ - rwlock_t buf_lock; }; struct mlb_dev_info { @@ -333,8 +316,11 @@ struct mlb_dev_info { enum CLK_SPEED fps; /* channel info for tx/rx */ struct mlb_channel_info channels[2]; - /* rx ring buffer */ - struct mlb_ringbuf rx_bufs; + /* ring buffer */ + u8 *rbuf_base_virt; + u32 rbuf_base_phy; + struct mlb_ringbuf rx_rbuf; + struct mlb_ringbuf tx_rbuf; /* exception event */ unsigned long ex_event; /* tx busy indicator */ @@ -344,12 +330,49 @@ struct mlb_dev_info { /* device open count */ atomic_t opencnt; /* wait queue head for channel */ - wait_queue_head_t rd_wq; - wait_queue_head_t wt_wq; + wait_queue_head_t rx_wq; + wait_queue_head_t tx_wq; + /* TX OK */ + s32 tx_ok; /* spinlock for event access */ spinlock_t event_lock; + /* Block size for isoc mode + * This variable can be configured in ioctl */ + u32 isoc_blksz; + /* Quads number for sync mode + * This variable can be confifured in ioctl */ + u32 sync_quad; + /* Buffer depth in cdt */ + u32 cdt_buf_dep; + /* Buffer depth in adt */ + u32 adt_buf_dep; + /* Buffer size to hold data */ + u32 buf_size; }; +struct mlb_data { + struct mlb_dev_info *devinfo; + struct clk *clk_mlb3p; + struct clk *clk_mlb6p; + struct cdev cdev; + struct class *class; /* device class */ + dev_t firstdev; +#ifdef CONFIG_REGULATOR + struct regulator *nvcc; +#endif + u32 membase; /* mlb module base address */ + u32 irq_ahb0; + u32 irq_ahb1; + u32 irq_mlb; +}; + +/* For optimization, we use fixed channel label for + * input channels of each mode */ +/* SYNC: CL = 0 for RX, CL = 64 for TX + * CTRL: CL = 1 for RX, CL = 65 for TX + * ASYNC: CL = 2 for RX, CL = 66 for TX + * ISOC: CL = 3 for RX, CL = 67 for TX + * */ #define SYNC_RX_CL_AHB0 0 #define CTRL_RX_CL_AHB0 1 #define ASYNC_RX_CL_AHB0 2 @@ -367,31 +390,49 @@ struct mlb_dev_info { #define CTRL_TX_CL_AHB1 37 #define ASYNC_TX_CL_AHB1 38 #define ISOC_TX_CL_AHB1 39 + +#define SYNC_RX_CL SYNC_RX_CL_AHB0 +#define CTRL_RX_CL CTRL_RX_CL_AHB0 +#define ASYNC_RX_CL ASYNC_RX_CL_AHB0 +#define ISOC_RX_CL ISOC_RX_CL_AHB0 + +#define SYNC_TX_CL SYNC_TX_CL_AHB0 +#define CTRL_TX_CL CTRL_TX_CL_AHB0 +#define ASYNC_TX_CL ASYNC_TX_CL_AHB0 +#define ISOC_TX_CL ISOC_TX_CL_AHB0 + static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { { .dev_name = MLB_SYNC_DEV_NAME, .channel_type = MLB_CTYPE_SYNC, .channels = { [0] = { - .buf_size = CH_SYNC_BUF_DEP, + .cl = SYNC_TX_CL, .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[0].channels[0]. - buf_lock), }, [1] = { - .buf_size = CH_SYNC_BUF_DEP, + .cl = SYNC_RX_CL, .dbr_buf_head = CH_SYNC_DBR_BUF_OFFSET - + CH_SYNC_BUF_DEP, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[0].channels[1]. - buf_lock), + + CH_SYNC_BUF_SZ, }, }, + .rx_rbuf = { + .unit_size = CH_SYNC_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[0].rx_rbuf.rb_lock), + }, + .tx_rbuf = { + .unit_size = CH_SYNC_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[0].tx_rbuf.rb_lock), + }, + .cdt_buf_dep = CH_SYNC_CDT_BUF_DEP, + .adt_buf_dep = CH_SYNC_ADT_BUF_DEP, + .buf_size = CH_SYNC_BUF_SZ, .on = ATOMIC_INIT(0), .opencnt = ATOMIC_INIT(0), - .rd_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[0].rd_wq), - .wt_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[0].wt_wq), + .rx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[0].rx_wq), + .tx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[0].tx_wq), .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[0].event_lock), }, { @@ -399,25 +440,32 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_CTRL, .channels = { [0] = { - .buf_size = CH_CTRL_BUF_DEP, + .cl = CTRL_TX_CL, .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[1].channels[0]. - buf_lock), }, [1] = { - .buf_size = CH_CTRL_BUF_DEP, + .cl = CTRL_RX_CL, .dbr_buf_head = CH_CTRL_DBR_BUF_OFFSET - + CH_CTRL_BUF_DEP, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[1].channels[1]. - buf_lock), + + CH_CTRL_BUF_SZ, }, }, + .rx_rbuf = { + .unit_size = CH_CTRL_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[1].rx_rbuf.rb_lock), + }, + .tx_rbuf = { + .unit_size = CH_CTRL_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[1].tx_rbuf.rb_lock), + }, + .cdt_buf_dep = CH_CTRL_CDT_BUF_DEP, + .adt_buf_dep = CH_CTRL_ADT_BUF_DEP, + .buf_size = CH_CTRL_BUF_SZ, .on = ATOMIC_INIT(0), .opencnt = ATOMIC_INIT(0), - .rd_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[1].rd_wq), - .wt_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[1].wt_wq), + .rx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[1].rx_wq), + .tx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[1].tx_wq), .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[1].event_lock), }, { @@ -425,25 +473,32 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_ASYNC, .channels = { [0] = { - .buf_size = CH_ASYNC_BUF_DEP, + .cl = ASYNC_TX_CL, .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[2].channels[0]. - buf_lock), }, [1] = { - .buf_size = CH_ASYNC_BUF_DEP, + .cl = ASYNC_RX_CL, .dbr_buf_head = CH_ASYNC_DBR_BUF_OFFSET - + CH_ASYNC_BUF_DEP, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[2].channels[1]. - buf_lock), + + CH_ASYNC_BUF_SZ, }, }, + .rx_rbuf = { + .unit_size = CH_ASYNC_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[2].rx_rbuf.rb_lock), + }, + .tx_rbuf = { + .unit_size = CH_ASYNC_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[2].tx_rbuf.rb_lock), + }, + .cdt_buf_dep = CH_ASYNC_CDT_BUF_DEP, + .adt_buf_dep = CH_ASYNC_ADT_BUF_DEP, + .buf_size = CH_ASYNC_BUF_SZ, .on = ATOMIC_INIT(0), .opencnt = ATOMIC_INIT(0), - .rd_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[2].rd_wq), - .wt_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[2].wt_wq), + .rx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[2].rx_wq), + .tx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[2].tx_wq), .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[2].event_lock), }, { @@ -451,42 +506,42 @@ static struct mlb_dev_info mlb_devinfo[MLB_MINOR_DEVICES] = { .channel_type = MLB_CTYPE_ISOC, .channels = { [0] = { - .buf_size = CH_ISOC_BUF_DEP, + .cl = ISOC_TX_CL, .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[3].channels[0]. - buf_lock), }, [1] = { - .buf_size = CH_ISOC_BUF_DEP, + .cl = ISOC_RX_CL, .dbr_buf_head = CH_ISOC_DBR_BUF_OFFSET - + CH_ISOC_BUF_DEP, - .buf_lock = - __RW_LOCK_UNLOCKED(mlb_devinfo[3].channels[1]. - buf_lock), + + CH_ISOC_BUF_SZ, }, }, + .rx_rbuf = { + .unit_size = CH_ISOC_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[3].rx_rbuf.rb_lock), + }, + .tx_rbuf = { + .unit_size = CH_ISOC_BUF_SZ, + .rb_lock = + __RW_LOCK_UNLOCKED(mlb_devinfo[3].tx_rbuf.rb_lock), + }, + .cdt_buf_dep = CH_ISOC_CDT_BUF_DEP, + .adt_buf_dep = CH_ISOC_ADT_BUF_DEP, + .buf_size = CH_ISOC_BUF_SZ, .on = ATOMIC_INIT(0), .opencnt = ATOMIC_INIT(0), - .rd_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[3].rd_wq), - .wt_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[3].wt_wq), + .rx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[3].rx_wq), + .tx_wq = __WAIT_QUEUE_HEAD_INITIALIZER(mlb_devinfo[3].tx_wq), .event_lock = __SPIN_LOCK_UNLOCKED(mlb_devinfo[3].event_lock), + .isoc_blksz = CH_ISOC_BLK_SIZE_188, }, }; -static struct regulator *reg_nvcc; /* NVCC_MLB regulator */ -static struct clk *mlb_clk; -static struct clk *mlb_pll_clk; -static dev_t dev; -static struct class *mlb_class; /* device class */ -static struct device *class_dev; -static u32 mlb_base; /* mlb module base address */ -static u32 ahb0_irq, ahb1_irq, mlb_irq; +static u32 mlb_base; DEFINE_SPINLOCK(ctr_lock); #ifdef DEBUG - #define DUMP_REG(reg) pr_debug(#reg": 0x%08x\n", __raw_readl(mlb_base + reg)) static void mlb150_dev_dump_reg(void) @@ -561,6 +616,7 @@ static inline u8 mlb150_dev_dbr_read(u32 dbr_addr) if (0 == timeout) { spin_unlock_irqrestore(&ctr_lock, flags); return -ETIME; + } dbr_val = __raw_readl(mlb_base + REG_MDAT0) & 0x000000ff; @@ -736,11 +792,11 @@ static s32 mlb150_dev_cat_write(u32 ctr_offset, u32 ch, const u16 cat_val) { u16 ctr_val[8] = { 0 }; - if (unlikely(mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val))) + if (mlb150_dev_ctr_read(ctr_offset, (u32 *)ctr_val)) return -ETIME; ctr_val[ch % 8] = cat_val; - if (unlikely(mlb150_dev_ctr_write(ctr_offset, (u32 *)ctr_val))) + if (mlb150_dev_ctr_write(ctr_offset, (u32 *)ctr_val)) return -ETIME; return 0; @@ -823,7 +879,7 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) pr_debug("mxc_mlb150: CAT MLB Table"); for (i = BUF_CAT_MLB_OFFSET + (ch_start >> 3); - i < BUF_CAT_MLB_OFFSET + (ch_end >> 3) + 1; + i <= BUF_CAT_MLB_OFFSET + ((ch_end + 8) >> 3); ++i) { mlb150_dev_ctr_read(i, ctr_val); pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", @@ -832,7 +888,7 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) pr_debug("mxc_mlb150: CAT HBI Table"); for (i = BUF_CAT_HBI_OFFSET + (ch_start >> 3); - i < BUF_CAT_HBI_OFFSET + (ch_end >> 3) + 1; + i <= BUF_CAT_HBI_OFFSET + ((ch_end + 8) >> 3); ++i) { mlb150_dev_ctr_read(i, ctr_val); pr_debug("CTR 0x%02x: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", @@ -846,9 +902,22 @@ static void mlb150_dev_dump_ctr_tbl(u32 ch_start, u32 ch_end) */ static inline s32 mlb150_dev_enable_dma_irq(u32 enable) { + u32 ch_rx_mask = (1 << SYNC_RX_CL_AHB0) | (1 << CTRL_RX_CL_AHB0) + | (1 << ASYNC_RX_CL_AHB0) | (1 << ISOC_RX_CL_AHB0) + | (1 << SYNC_TX_CL_AHB0) | (1 << CTRL_TX_CL_AHB0) + | (1 << ASYNC_TX_CL_AHB0) | (1 << ISOC_TX_CL_AHB0); + u32 ch_tx_mask = (1 << (SYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (CTRL_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ASYNC_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ISOC_RX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (SYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (CTRL_TX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ASYNC_TX_CL_AHB1 - INT_AHB1_CH_START)) | + (1 << (ISOC_TX_CL_AHB1 - INT_AHB1_CH_START)); + if (enable) { - __raw_writel(0xffffffff, mlb_base + REG_ACMR0); - __raw_writel(0xffffffff, mlb_base + REG_ACMR1); + __raw_writel(ch_rx_mask, mlb_base + REG_ACMR0); + __raw_writel(ch_tx_mask, mlb_base + REG_ACMR1); } else { __raw_writel(0x0, mlb_base + REG_ACMR0); __raw_writel(0x0, mlb_base + REG_ACMR1); @@ -881,9 +950,7 @@ static s32 mlb150_dev_init_ir_amba_ahb(void) * and another interrupt for channels 32 - 63 on ahb_init[1] * ACTL.SMX = 1: singel interrupt all channels on ahb_init[0] * */ - /* - reg |= ACTL_SMX; - */ + reg &= ~ACTL_SMX; __raw_writel(reg, mlb_base + REG_ACTL); @@ -911,40 +978,40 @@ static inline s32 mlb150_dev_enable_ir_mlb(u32 enable) return 0; } -static inline int mlb150_enable_pll(void) +static inline int mlb150_enable_pll(struct mlb_data *drvdata) { u32 c0_val; __raw_writel(MLBPC1_VAL, - mlb_base + REG_MLBPC1); + drvdata->membase + REG_MLBPC1); - c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val = __raw_readl(drvdata->membase + REG_MLBC0); if (c0_val & MLBC0_MLBPEN) { c0_val &= ~MLBC0_MLBPEN; __raw_writel(c0_val, - mlb_base + REG_MLBC0); + drvdata->membase + REG_MLBC0); } - clk_enable(mlb_pll_clk); + clk_enable(drvdata->clk_mlb6p); c0_val |= (MLBC0_MLBPEN); - __raw_writel(c0_val, mlb_base + REG_MLBC0); + __raw_writel(c0_val, drvdata->membase + REG_MLBC0); return 0; } -static inline int mlb150_disable_pll(void) +static inline int mlb150_disable_pll(struct mlb_data *drvdata) { u32 c0_val; - clk_disable(mlb_pll_clk); + clk_disable(drvdata->clk_mlb6p); - c0_val = __raw_readl(mlb_base + REG_MLBC0); + c0_val = __raw_readl(drvdata->membase + REG_MLBC0); - __raw_writel(0x0, mlb_base + REG_MLBPC1); + __raw_writel(0x0, drvdata->membase + REG_MLBPC1); c0_val &= ~MLBC0_MLBPEN; - __raw_writel(c0_val, mlb_base + REG_MLBC0); + __raw_writel(c0_val, drvdata->membase + REG_MLBC0); return 0; } @@ -963,57 +1030,42 @@ static s32 mlb150_dev_reset_cdt(void) return 0; } -static s32 mlb150_dev_init_ch_cdt(u32 ch, enum MLB_CTYPE ctype, u32 ch_func) +static s32 mlb150_dev_init_ch_cdt(struct mlb_dev_info *pdevinfo, u32 ch, + enum MLB_CTYPE ctype, u32 ch_func) { u32 cdt_val[4] = { 0 }; /* a. Set the 14-bit base address (BA) */ pr_debug("mxc_mlb150: ctype: %d, ch: %d, dbr_buf_head: 0x%08x", - ctype, ch, mlb_devinfo[ctype].channels[ch_func].dbr_buf_head); - cdt_val[3] = (mlb_devinfo[ctype].channels[ch_func].dbr_buf_head) + ctype, ch, pdevinfo->channels[ch_func].dbr_buf_head); + cdt_val[3] = (pdevinfo->channels[ch_func].dbr_buf_head) << CDT_BA_SHIFT; /* b. Set the 12-bit or 13-bit buffer depth (BD) * BD = buffer depth in bytes - 1 */ - switch (ctype) { - case MLB_CTYPE_SYNC: - /* For synchronous channels: (BD + 1) = 4 * m * bpf */ - cdt_val[3] |= (CH_SYNC_BUF_DEP - 1) << CDT_BD_SHIFT; - break; - case MLB_CTYPE_CTRL: - /* For control channels: (BD + 1) >= max packet length (64) */ - /* BD */ - cdt_val[3] |= ((CH_CTRL_BUF_DEP - 1) << CDT_BD_SHIFT); - break; - case MLB_CTYPE_ASYNC: - /* For asynchronous channels: (BD + 1) >= max packet length - * 1024 for a MOST Data packet (MDP); - * 1536 for a MOST Ethernet Packet (MEP) */ - cdt_val[3] |= ((CH_ASYNC_BUF_DEP - 1) << CDT_BD_SHIFT); - break; - case MLB_CTYPE_ISOC: - /* For isochronous channels: (BD + 1) mod (BS + 1) = 0 */ - /* BS */ - cdt_val[1] |= (CH_ISOC_BLK_SIZE - 1); - /* BD */ - cdt_val[3] |= (CH_ISOC_BUF_DEP - 1) - << CDT_BD_SHIFT; - break; - default: - break; - } + /* For synchronous channels: (BD + 1) = 4 * m * bpf */ + /* For control channels: (BD + 1) >= max packet length (64) */ + /* For asynchronous channels: (BD + 1) >= max packet length + * 1024 for a MOST Data packet (MDP); + * 1536 for a MOST Ethernet Packet (MEP) */ + /* For isochronous channels: (BD + 1) mod (BS + 1) = 0 */ + /* BS */ + if (MLB_CTYPE_ISOC == ctype) + cdt_val[1] |= (pdevinfo->isoc_blksz - 1); + /* BD */ + cdt_val[3] |= (pdevinfo->cdt_buf_dep - 1) << CDT_BD_SHIFT; pr_debug("mxc_mlb150: Set CDT val of channel %d, type: %d: " "0x%08x 0x%08x 0x%08x 0x%08x\n", ch, ctype, cdt_val[3], cdt_val[2], cdt_val[1], cdt_val[0]); - if (unlikely(mlb150_dev_cdt_write(ch, cdt_val))) + if (mlb150_dev_cdt_write(ch, cdt_val)) return -ETIME; #ifdef DEBUG_CTR { u32 cdt_rd[4] = { 0 }; - if (likely(!mlb150_dev_cdt_read(ch, cdt_rd))) { + if (!mlb150_dev_cdt_read(ch, cdt_rd)) { pr_debug("mxc_mlb150: CDT val of channel %d: " "0x%08x 0x%08x 0x%08x 0x%08x\n", ch, cdt_rd[3], cdt_rd[2], cdt_rd[1], cdt_rd[0]); @@ -1038,14 +1090,15 @@ static s32 mlb150_dev_init_ch_cdt(u32 ch, enum MLB_CTYPE ctype, u32 ch_func) return 0; } -static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cat_mode, enum MLB_CTYPE ctype) +static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cl, + u32 cat_mode, enum MLB_CTYPE ctype) { u16 cat_val = 0; #ifdef DEBUG_CTR u16 cat_rd = 0; #endif - cat_val = CAT_CE | (ctype << CAT_CT_SHIFT) | ch; + cat_val = CAT_CE | (ctype << CAT_CT_SHIFT) | cl; if (cat_mode & CAT_MODE_OUTBOUND_DMA) cat_val |= CAT_RNW; @@ -1053,16 +1106,16 @@ static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cat_mode, enum MLB_CTYPE ctype) if (MLB_CTYPE_SYNC == ctype) cat_val |= CAT_MT; - pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n", - ch, ctype, cat_val); - switch (cat_mode) { case CAT_MODE_RX | CAT_MODE_INBOUND_DMA: case CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA: - if (unlikely(mlb150_dev_cat_mlb_write(ch, cat_val))) + pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n", + ch, ctype, cat_val); + + if (mlb150_dev_cat_mlb_write(ch, cat_val)) return -ETIME; #ifdef DEBUG_CTR - if (likely(!mlb150_dev_cat_mlb_read(ch, &cat_rd))) + if (!mlb150_dev_cat_mlb_read(ch, &cat_rd)) pr_debug("mxc_mlb150: CAT val of mlb channel %d: 0x%04x", ch, cat_rd); else { @@ -1074,15 +1127,18 @@ static s32 mlb150_dev_init_ch_cat(u32 ch, u32 cat_mode, enum MLB_CTYPE ctype) break; case CAT_MODE_TX | CAT_MODE_INBOUND_DMA: case CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA: - if (unlikely(mlb150_dev_cat_hbi_write(ch, cat_val))) + pr_debug("mxc_mlb150: set CAT val of channel %d, type: %d: 0x%04x\n", + cl, ctype, cat_val); + + if (mlb150_dev_cat_hbi_write(cl, cat_val)) return -ETIME; #ifdef DEBUG_CTR - if (likely(!mlb150_dev_cat_hbi_read(ch, &cat_rd))) + if (!mlb150_dev_cat_hbi_read(cl, &cat_rd)) pr_debug("mxc_mlb150: CAT val of hbi channel %d: 0x%04x", - ch, cat_rd); + cl, cat_rd); else { pr_debug("mxc_mlb150: Read CAT of hbi channel %d failed\n", - ch); + cl); return -EBADE; } #endif @@ -1121,28 +1177,31 @@ static s32 mlb150_dev_reset_cat(void) return 0; } -static s32 mlb150_dev_init_rfb(u32 rx_ch, u32 tx_ch, enum MLB_CTYPE ctype) +static s32 mlb150_dev_init_rfb(struct mlb_dev_info *pdevinfo, u32 rx_ch, + u32 tx_ch, enum MLB_CTYPE ctype) { + u32 rx_cl = pdevinfo->channels[RX_CHANNEL].cl; + u32 tx_cl = pdevinfo->channels[TX_CHANNEL].cl; /* Step 1, Initialize all bits of CAT to '0' */ mlb150_dev_reset_cat(); mlb150_dev_reset_cdt(); /* Step 2, Initialize logical channel */ /* Step 3, Program the CDT for channel N */ - mlb150_dev_init_ch_cdt(rx_ch, ctype, RX_CHANNEL); - mlb150_dev_init_ch_cdt(tx_ch, ctype, TX_CHANNEL); + mlb150_dev_init_ch_cdt(pdevinfo, rx_cl, ctype, RX_CHANNEL); + mlb150_dev_init_ch_cdt(pdevinfo, tx_cl, ctype, TX_CHANNEL); /* Step 4&5, Program the CAT for the inbound and outbound DMA */ - mlb150_dev_init_ch_cat(rx_ch, + mlb150_dev_init_ch_cat(rx_ch, rx_cl, CAT_MODE_RX | CAT_MODE_INBOUND_DMA, ctype); - mlb150_dev_init_ch_cat(rx_ch, + mlb150_dev_init_ch_cat(rx_ch, rx_cl, CAT_MODE_RX | CAT_MODE_OUTBOUND_DMA, ctype); - mlb150_dev_init_ch_cat(tx_ch, + mlb150_dev_init_ch_cat(tx_ch, tx_cl, CAT_MODE_TX | CAT_MODE_INBOUND_DMA, ctype); - mlb150_dev_init_ch_cat(tx_ch, + mlb150_dev_init_ch_cat(tx_ch, tx_cl, CAT_MODE_TX | CAT_MODE_OUTBOUND_DMA, ctype); @@ -1273,16 +1332,17 @@ static inline s32 mlb150_dev_set_ch_amba_ahb(u32 ch, enum MLB_CTYPE ctype, return 0; } -static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_channel_info *chinfo, +static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_dev_info *pdevinfo, + struct mlb_channel_info *chinfo, enum MLB_CTYPE ctype) { u32 ctr_val[4] = { 0 }; /* a. Set the 32-bit base address (BA1) */ - ctr_val[3] = chinfo->pong_phy_head; - ctr_val[2] = chinfo->ping_phy_head; - ctr_val[1] = (chinfo->buf_size - 1) << ADT_BD1_SHIFT; - ctr_val[1] |= (chinfo->buf_size - 1) << ADT_BD2_SHIFT; + ctr_val[3] = 0; + ctr_val[2] = 0; + ctr_val[1] = (pdevinfo->adt_buf_dep - 1) << ADT_BD1_SHIFT; + ctr_val[1] |= (pdevinfo->adt_buf_dep - 1) << ADT_BD2_SHIFT; if (MLB_CTYPE_ASYNC == ctype || MLB_CTYPE_CTRL == ctype) { ctr_val[1] |= ADT_PS1; @@ -1293,19 +1353,19 @@ static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_channel_info *chinfo, pr_debug("mxc_mlb150: Set ADT val of channel %d, ctype: %d: " "0x%08x 0x%08x 0x%08x 0x%08x\n", - chinfo->address, ctype, ctr_val[3], ctr_val[2], + chinfo->cl, ctype, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]); - if (unlikely(mlb150_dev_adt_write(chinfo->address, ctr_val))) + if (mlb150_dev_adt_write(chinfo->cl, ctr_val)) return -ETIME; #ifdef DEBUG_CTR { u32 ctr_rd[4] = { 0 }; - if (likely(!mlb150_dev_adt_read(chinfo->address, ctr_rd))) { + if (!mlb150_dev_adt_read(chinfo->cl, ctr_rd)) { pr_debug("mxc_mlb150: ADT val of channel %d: " "0x%08x 0x%08x 0x%08x 0x%08x\n", - chinfo->address, ctr_rd[3], ctr_rd[2], + chinfo->cl, ctr_rd[3], ctr_rd[2], ctr_rd[1], ctr_rd[0]); if (ctr_rd[3] == ctr_val[3] && ctr_rd[2] == ctr_val[2] && @@ -1319,7 +1379,7 @@ static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_channel_info *chinfo, } } else { pr_debug("mxc_mlb150: Read ADT val of channel %d failed\n", - chinfo->address); + chinfo->cl); return -EBADE; } } @@ -1328,17 +1388,20 @@ static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_channel_info *chinfo, return 0; } -static s32 mlb150_dev_init_amba_ahb(struct mlb_channel_info *rx_chinfo, - struct mlb_channel_info *tx_chinfo, enum MLB_CTYPE ctype) +static s32 mlb150_dev_init_amba_ahb(struct mlb_dev_info *pdevinfo, + enum MLB_CTYPE ctype) { + struct mlb_channel_info *tx_chinfo = &pdevinfo->channels[TX_CHANNEL]; + struct mlb_channel_info *rx_chinfo = &pdevinfo->channels[RX_CHANNEL]; + /* Step 1, Initialize all bits of the ADT to '0' */ mlb150_dev_reset_adt(); /* Step 2, Select a logic channel */ /* Step 3, Program the AMBA AHB block ping page for channel N */ /* Step 4, Program the AMBA AHB block pong page for channel N */ - mlb150_dev_init_ch_amba_ahb(rx_chinfo, ctype); - mlb150_dev_init_ch_amba_ahb(tx_chinfo, ctype); + mlb150_dev_init_ch_amba_ahb(pdevinfo, rx_chinfo, ctype); + mlb150_dev_init_ch_amba_ahb(pdevinfo, tx_chinfo, ctype); return 0; } @@ -1408,7 +1471,7 @@ static void mlb150_dev_init(void) mlb150_dev_enable_ir_mlb(1); } -static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 tx_ch) +static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 rx_cl, u32 tx_ch, u32 tx_cl) { u32 timeout = 10000; @@ -1419,7 +1482,7 @@ static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 tx_ch) || timeout--) __raw_writel(~MLBC1_CLKM, mlb_base + REG_MLBC1); - if (unlikely(0 == timeout)) + if (0 == timeout) return -ETIME; timeout = 10000; @@ -1428,16 +1491,16 @@ static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 tx_ch) || timeout--) ; - if (unlikely(0 == timeout)) + if (0 == timeout) return -ETIME; /* Unmute synchronous channel(s) */ - mlb150_dev_cat_mlb_write(rx_ch, CAT_CE | rx_ch); + mlb150_dev_cat_mlb_write(rx_ch, CAT_CE | rx_cl); mlb150_dev_cat_mlb_write(tx_ch, - CAT_CE | tx_ch | CAT_RNW); - mlb150_dev_cat_hbi_write(rx_ch, - CAT_CE | rx_ch | CAT_RNW); - mlb150_dev_cat_hbi_write(tx_ch, CAT_CE | tx_ch); + CAT_CE | tx_cl | CAT_RNW); + mlb150_dev_cat_hbi_write(rx_cl, + CAT_CE | rx_cl | CAT_RNW); + mlb150_dev_cat_hbi_write(tx_cl, CAT_CE | tx_cl); return 0; } @@ -1467,57 +1530,66 @@ static inline void mlb_start_tx(u32 ch, s32 ctype, u32 dne_sts, u32 buf_addr) /*! * Enable the MLB channel */ -static void mlb_channel_enable(int chan_dev_id, int on) +static void mlb_channel_enable(struct mlb_data *drvdata, + int chan_dev_id, int on) { - struct mlb_dev_info *pdevinfo = &mlb_devinfo[chan_dev_id]; + struct mlb_dev_info *pdevinfo = drvdata->devinfo; + struct mlb_channel_info *tx_chinfo = &pdevinfo->channels[TX_CHANNEL]; + struct mlb_channel_info *rx_chinfo = &pdevinfo->channels[RX_CHANNEL]; + u32 tx_ch = tx_chinfo->address; + u32 rx_ch = rx_chinfo->address; + u32 tx_cl = tx_chinfo->cl; + u32 rx_cl = rx_chinfo->cl; + /*! * setup the direction, enable, channel type, * mode select, channel address and mask buf start */ if (on) { u32 ctype = pdevinfo->channel_type; - struct mlb_channel_info *tx_chinfo = &_get_txchan(chan_dev_id); - struct mlb_channel_info *rx_chinfo = &_get_rxchan(chan_dev_id); - u32 tx_ch = tx_chinfo->address; - u32 rx_ch = rx_chinfo->address; mlb150_dev_enable_ctr_write(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff); - mlb150_dev_init_rfb(rx_ch, tx_ch, ctype); + mlb150_dev_init_rfb(pdevinfo, rx_ch, tx_ch, ctype); - mlb150_dev_init_amba_ahb(rx_chinfo, tx_chinfo, ctype); + mlb150_dev_init_amba_ahb(pdevinfo, ctype); +#ifdef DEBUG + mlb150_dev_dump_ctr_tbl(0, tx_chinfo->cl + 1); +#endif /* Synchronize and unmute synchrouous channel */ if (MLB_CTYPE_SYNC == ctype) - mlb150_dev_unmute_syn_ch(rx_ch, tx_ch); + mlb150_dev_unmute_syn_ch(rx_ch, rx_cl, tx_ch, tx_cl); mlb150_dev_enable_ctr_write(0x0, ADT_RDY1 | ADT_DNE1 | ADT_ERR1 | ADT_PS1 | - ADT_MEP1 | ADT_RDY2 | ADT_DNE2 | ADT_ERR2 | - ADT_PS2 | ADT_MEP2, + ADT_RDY2 | ADT_DNE2 | ADT_ERR2 | ADT_PS2, 0xffffffff, 0xffffffff); if (pdevinfo->fps >= CLK_2048FS) - mlb150_enable_pll(); + mlb150_enable_pll(drvdata); atomic_set(&pdevinfo->on, 1); #ifdef DEBUG mlb150_dev_dump_reg(); - mlb150_dev_dump_ctr_tbl(0, tx_chinfo->address + 1); + mlb150_dev_dump_ctr_tbl(0, tx_chinfo->cl + 1); #endif - mlb_start_rx(rx_ch, ctype, ADT_DNE2, - pdevinfo->rx_bufs.phy_addrs[0]); + /* Init RX ADT */ + mlb150_dev_pipo_start(&pdevinfo->rx_rbuf, rx_cl, + pdevinfo->rx_rbuf.phy_addrs[0]); } else { + mlb150_dev_pipo_stop(&pdevinfo->rx_rbuf, rx_cl); + mlb150_dev_enable_dma_irq(0); mlb150_dev_enable_ir_mlb(0); mlb150_dev_reset_cat(); - atomic_set(&mlb_devinfo[chan_dev_id].on, 0); + atomic_set(&pdevinfo->on, 0); - if (mlb_devinfo[chan_dev_id].fps >= CLK_2048FS) - mlb150_disable_pll(); + if (pdevinfo->fps >= CLK_2048FS) + mlb150_disable_pll(drvdata); } } @@ -1649,7 +1721,6 @@ static irqreturn_t mlb_isr(int irq, void *dev_id) { u32 rx_int_sts, tx_int_sts, ms0, ms1, tx_cis, rx_cis, ctype; - struct mlb_dev_info *pdev; int minor; u32 cdt_val[4] = { 0 }; @@ -1661,26 +1732,30 @@ static irqreturn_t mlb_isr(int irq, void *dev_id) (u32)ms0, (u32)ms1); for (minor = 0; minor < MLB_MINOR_DEVICES; minor++) { - pdev = &mlb_devinfo[minor]; + struct mlb_dev_info *pdevinfo = &mlb_devinfo[minor]; + u32 rx_mlb_ch = pdevinfo->channels[RX_CHANNEL].address; + u32 tx_mlb_ch = pdevinfo->channels[TX_CHANNEL].address; + u32 rx_mlb_cl = pdevinfo->channels[RX_CHANNEL].cl; + u32 tx_mlb_cl = pdevinfo->channels[TX_CHANNEL].cl; + tx_cis = rx_cis = 0; - ctype = pdev->channel_type; - rx_int_sts = (_get_rxchan(minor).address < 31) ? ms0 : ms1; - tx_int_sts = (_get_txchan(minor).address < 31) ? ms0 : ms1; + ctype = pdevinfo->channel_type; + rx_int_sts = (rx_mlb_ch < 31) ? ms0 : ms1; + tx_int_sts = (tx_mlb_ch < 31) ? ms0 : ms1; pr_debug("mxc_mlb150: channel interrupt: " - "tx: 0x%08x, rx: 0x%08x\n", - (u32)tx_int_sts, (u32)rx_int_sts); + "tx %d: 0x%08x, rx %d: 0x%08x\n", + tx_mlb_ch, (u32)tx_int_sts, rx_mlb_ch, (u32)rx_int_sts); /* Get tx channel interrupt status */ - if (tx_int_sts & (1 << (_get_txchan(minor).address % 32))) { - mlb150_dev_cdt_read(_get_txchan(minor).address, - cdt_val); - pr_debug("mxc_mlb150: cdt_val[3]: 0x%08x, " + if (tx_int_sts & (1 << (tx_mlb_ch % 32))) { + mlb150_dev_cdt_read(tx_mlb_cl, cdt_val); + pr_debug("mxc_mlb150: TX_CH: %d, cdt_val[3]: 0x%08x, " "cdt_val[2]: 0x%08x, " "cdt_val[1]: 0x%08x, " "cdt_val[0]: 0x%08x\n", - cdt_val[3], cdt_val[2], + tx_mlb_ch, cdt_val[3], cdt_val[2], cdt_val[1], cdt_val[0]); switch (ctype) { case MLB_CTYPE_SYNC: @@ -1714,14 +1789,18 @@ static irqreturn_t mlb_isr(int irq, void *dev_id) default: break; } - mlb150_dev_cdt_write(_get_txchan(minor).address, - cdt_val); + mlb150_dev_cdt_write(tx_mlb_ch, cdt_val); } /* Get rx channel interrupt status */ - if (rx_int_sts & (1 << (_get_rxchan(minor).address % 32))) { - mlb150_dev_cdt_read(_get_rxchan(minor).address, - cdt_val); + if (rx_int_sts & (1 << (rx_mlb_ch % 32))) { + mlb150_dev_cdt_read(rx_mlb_cl, cdt_val); + pr_debug("mxc_mlb150: RX_CH: %d, cdt_val[3]: 0x%08x, " + "cdt_val[2]: 0x%08x, " + "cdt_val[1]: 0x%08x, " + "cdt_val[0]: 0x%08x\n", + rx_mlb_ch, cdt_val[3], cdt_val[2], + cdt_val[1], cdt_val[0]); switch (ctype) { case MLB_CTYPE_SYNC: tx_cis = (cdt_val[2] & ~CDT_SYNC_RSTS_MASK) @@ -1747,17 +1826,16 @@ static irqreturn_t mlb_isr(int irq, void *dev_id) default: break; } - mlb150_dev_cdt_write(_get_rxchan(minor).address, - cdt_val); + mlb150_dev_cdt_write(rx_mlb_ch, cdt_val); } if (!tx_cis && !rx_cis) continue; /* fill exception event */ - spin_lock(&pdev->event_lock); - pdev->ex_event |= (rx_cis << 16) | tx_cis; - spin_unlock(&pdev->event_lock); + spin_lock(&pdevinfo->event_lock); + pdevinfo->ex_event |= (rx_cis << 16) | tx_cis; + spin_unlock(&pdevinfo->event_lock); } return IRQ_HANDLED; @@ -1767,64 +1845,70 @@ static int mxc_mlb150_open(struct inode *inode, struct file *filp) { int minor, ring_buf_size, buf_size, j, ret; void __iomem *buf_addr; - ulong phyaddr; - struct mxc_mlb_platform_data *plat_data; + ulong phy_addr; struct mlb_dev_info *pdevinfo = NULL; struct mlb_channel_info *pchinfo = NULL; - - plat_data = container_of(inode->i_cdev, struct mxc_mlb_platform_data, - cdev); - filp->private_data = plat_data; + struct mlb_data *drvdata; minor = MINOR(inode->i_rdev); - if (unlikely(minor < 0 || minor >= MLB_MINOR_DEVICES)) + if (minor < 0 || minor >= MLB_MINOR_DEVICES) { + pr_err("no device\n"); return -ENODEV; + } /* open for each channel device */ - if (unlikely(atomic_cmpxchg(&mlb_devinfo[minor].opencnt, 0, 1) != 0)) + if (atomic_cmpxchg(&mlb_devinfo[minor].opencnt, 0, 1) != 0) { + pr_err("busy\n"); return -EBUSY; + } + + /* initial MLB module */ + mlb150_dev_init(); pdevinfo = &mlb_devinfo[minor]; - pchinfo = &_get_txchan(minor); + pchinfo = &pdevinfo->channels[TX_CHANNEL]; - ring_buf_size = mlb150_ch_packet_buf_size[minor]; - buf_size = ring_buf_size * (TRANS_RING_NODES + 1) + PING_BUF_MAX_SIZE; - buf_addr = iram_alloc(buf_size, &phyaddr); - memset(buf_addr, 0, buf_size); - if (unlikely(buf_addr == NULL)) { + ring_buf_size = pdevinfo->buf_size; + buf_size = ring_buf_size * (TRANS_RING_NODES * 2 + 1); + buf_addr = iram_alloc(buf_size, &phy_addr); + if (buf_addr == NULL) { ret = -ENOMEM; - dev_err(plat_data->dev, "can not alloc rx buffers\n"); + pr_err("can not alloc rx buffers\n"); return ret; } + pdevinfo->rbuf_base_virt = buf_addr; + pdevinfo->rbuf_base_phy = phy_addr; + memset(buf_addr, 0, buf_size); - dev_dbg(plat_data->dev, "ch_type: %d, RX ring buf virt base: 0x%08x " - "phy base: 0x%08x\n", - pdevinfo->channel_type, (u32)buf_addr, (u32)phyaddr); - - for (j = 0; j < TRANS_RING_NODES + 1; - ++j, buf_addr += ring_buf_size, phyaddr += ring_buf_size) { - pdevinfo->rx_bufs.virt_bufs[j] = buf_addr; - pdevinfo->rx_bufs.phy_addrs[j] = phyaddr; - pdevinfo->rx_bufs.size = pchinfo->buf_size; + for (j = 0; j < (TRANS_RING_NODES + 1); + ++j, buf_addr += ring_buf_size, phy_addr += ring_buf_size) { + pdevinfo->rx_rbuf.virt_bufs[j] = buf_addr; + pdevinfo->rx_rbuf.phy_addrs[j] = phy_addr; + } + pdevinfo->rx_rbuf.unit_size = ring_buf_size; + pdevinfo->rx_rbuf.total_size = buf_size; + + buf_addr += ring_buf_size; + phy_addr += ring_buf_size; + for (j = 0; j < (TRANS_RING_NODES); + ++j, buf_addr += ring_buf_size, phy_addr += ring_buf_size) { + pdevinfo->tx_rbuf.virt_bufs[j] = buf_addr; + pdevinfo->tx_rbuf.phy_addrs[j] = phy_addr; } - /* set the virtual and physical buf head address */ - pchinfo->ping_buf_head = pchinfo->pong_buf_head = (u32)buf_addr; - pchinfo->ping_phy_head = pchinfo->pong_phy_head = phyaddr; - - pchinfo->buf_ptr = (u32)buf_addr; - pchinfo->buf_phy_addr = phyaddr; - - dev_dbg(plat_data->dev, "ctype: %d, tx phy_head: 0x%08x, " - "buf_head: 0x%08x\n", - pchinfo->address, - (u32)pchinfo->buf_phy_addr, - (u32)pchinfo->buf_ptr); + pdevinfo->tx_rbuf.unit_size = ring_buf_size; + pdevinfo->tx_rbuf.total_size = buf_size; /* reset the buffer read/write ptr */ - pdevinfo->rx_bufs.rpos = pdevinfo->rx_bufs.wpos = 0; + pdevinfo->rx_rbuf.head = pdevinfo->rx_rbuf.tail = 0; + pdevinfo->tx_rbuf.head = pdevinfo->tx_rbuf.tail = 0; pdevinfo->ex_event = 0; + pdevinfo->tx_ok = 0; + + drvdata = container_of(inode->i_cdev, struct mlb_data, cdev); + drvdata->devinfo = pdevinfo; + filp->private_data = drvdata; return 0; } @@ -1832,26 +1916,24 @@ static int mxc_mlb150_open(struct inode *inode, struct file *filp) static int mxc_mlb150_release(struct inode *inode, struct file *filp) { int minor; - u32 buf_size; + struct mlb_data *drvdata = filp->private_data; + struct mlb_dev_info *pdevinfo = drvdata->devinfo; + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf; minor = MINOR(inode->i_rdev); #ifdef DEBUG mlb150_dev_dump_reg(); - mlb150_dev_dump_ctr_tbl(0, _get_txchan(minor).address + 1); - mlb150_dev_dump_hex((const u8 *)mlb_devinfo[minor].rx_bufs.virt_bufs[0], - mlb_devinfo[minor].rx_bufs.size); + mlb150_dev_dump_ctr_tbl(0, pdevinfo->channels[TX_CHANNEL].cl + 1); #endif /* clear channel settings and info */ - mlb_channel_enable(minor, 0); + mlb_channel_enable(drvdata, minor, 0); - buf_size = mlb150_ch_packet_buf_size[minor] * - (TRANS_RING_NODES + 1) + PING_BUF_MAX_SIZE; - iram_free(mlb_devinfo[minor].rx_bufs.phy_addrs[0], buf_size); + iram_free(pdevinfo->rbuf_base_phy, rx_rbuf->total_size); /* decrease the open count */ - atomic_set(&mlb_devinfo[minor].opencnt, 0); + atomic_set(&pdevinfo->opencnt, 0); return 0; } @@ -1860,10 +1942,11 @@ static long mxc_mlb150_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { struct inode *inode = filp->f_dentry->d_inode; + struct mlb_data *drvdata = filp->private_data; + struct mlb_dev_info *pdevinfo = drvdata->devinfo; void __user *argp = (void __user *)arg; unsigned long flags, event; int minor; - struct mxc_mlb_platform_data *plat_data = filp->private_data; minor = MINOR(inode->i_rdev); @@ -1876,45 +1959,43 @@ static long mxc_mlb150_ioctl(struct file *filp, pr_err("mxc_mlb150: copy from user failed\n"); return -EFAULT; } - _get_txchan(minor).address = (caddr >> 16) & 0xFFFF; - _get_rxchan(minor).address = caddr & 0xFFFF; + pdevinfo->channels[TX_CHANNEL].address = + (caddr >> 16) & 0xFFFF; + pdevinfo->channels[RX_CHANNEL].address = caddr & 0xFFFF; pr_debug("mxc_mlb150: set ch addr, tx: %d, rx: %d\n", - _get_txchan(minor).address, - _get_rxchan(minor).address); + pdevinfo->channels[TX_CHANNEL].address, + pdevinfo->channels[RX_CHANNEL].address); break; } case MLB_CHAN_STARTUP: - if (unlikely(atomic_read(&mlb_devinfo[minor].on))) { - pr_debug("mxc_mlb150: channel areadly startup\n"); + if (atomic_read(&pdevinfo->on)) { + pr_debug("mxc_mlb150: channel alreadly startup\n"); break; } - pr_debug("mxc_mlb150: start channel\n"); - mlb_channel_enable(minor, 1); + mlb_channel_enable(drvdata, minor, 1); break; case MLB_CHAN_SHUTDOWN: - if (unlikely(atomic_read(&mlb_devinfo[minor].on) == 0)) { + if (atomic_read(&pdevinfo->on) == 0) { pr_debug("mxc_mlb150: channel areadly shutdown\n"); break; } - pr_debug("mxc_mlb150: shutdown channel\n"); - mlb_channel_enable(minor, 0); + mlb150_trans_complete_check(pdevinfo); + mlb_channel_enable(drvdata, minor, 0); break; case MLB_CHAN_GETEVENT: /* get and clear the ex_event */ - spin_lock_irqsave(&mlb_devinfo[minor].event_lock, flags); - event = mlb_devinfo[minor].ex_event; - mlb_devinfo[minor].ex_event = 0; - spin_unlock_irqrestore(&mlb_devinfo[minor].event_lock, flags); + spin_lock_irqsave(&pdevinfo->event_lock, flags); + event = pdevinfo->ex_event; + pdevinfo->ex_event = 0; + spin_unlock_irqrestore(&pdevinfo->event_lock, flags); - pr_debug("mxc_mlb150: get event\n"); if (event) { if (copy_to_user(argp, &event, sizeof(event))) { pr_err("mxc_mlb150: copy to user failed\n"); return -EFAULT; } - } else { - pr_debug("mxc_mlb150: no exception event now\n"); + } else return -EAGAIN; } break; @@ -1923,14 +2004,11 @@ static long mxc_mlb150_ioctl(struct file *filp, u32 fps, c0_val; /* get fps from user space */ - if (unlikely(copy_from_user(&fps, argp, sizeof(fps)))) { + if (copy_from_user(&fps, argp, sizeof(fps))) { pr_err("mxc_mlb150: copy from user failed\n"); return -EFAULT; } - if (plat_data->fps_sel) - plat_data->fps_sel(fps); - c0_val = __raw_readl(mlb_base + REG_MLBC0); c0_val &= ~MLBC0_MLBCLK_MASK; @@ -1939,25 +2017,32 @@ static long mxc_mlb150_ioctl(struct file *filp, case 256: case 512: case 1024: - mlb_devinfo[minor].fps = fps >> 9; + pdevinfo->fps = fps >> 9; c0_val &= ~MLBC0_MLBPEN; c0_val |= (fps >> 9) << MLBC0_MLBCLK_SHIFT; + + if (1024 == fps) { + /* Invert output clock phase + * in 1024 fps */ + __raw_writel(0x1, + mlb_base + REG_MLBPC2); + } break; case 2048: case 3072: case 4096: - mlb_devinfo[minor].fps = (fps >> 10) + 1; + pdevinfo->fps = (fps >> 10) + 1; c0_val |= ((fps >> 10) + 1) << MLBC0_MLBCLK_SHIFT; break; case 6144: - mlb_devinfo[minor].fps = fps >> 10; + pdevinfo->fps = fps >> 10; c0_val |= ((fps >> 10) + 1) << MLBC0_MLBCLK_SHIFT; break; case 8192: - mlb_devinfo[minor].fps = (fps >> 10) - 1; + pdevinfo->fps = (fps >> 10) - 1; c0_val |= ((fps >> 10) - 1) << MLBC0_MLBCLK_SHIFT; break; @@ -1999,8 +2084,8 @@ static long mxc_mlb150_ioctl(struct file *filp, u8 devaddr; /* get MLB device address from user space */ - if (unlikely(copy_from_user - (&devaddr, argp, sizeof(unsigned char)))) { + if (copy_from_user + (&devaddr, argp, sizeof(unsigned char))) { pr_err("mxc_mlb150: copy from user failed\n"); return -EFAULT; } @@ -2186,175 +2271,180 @@ static const struct file_operations mxc_mlb150_fops = { static int __devinit mxc_mlb150_probe(struct platform_device *pdev) { int ret, mlb_major, i; - struct mxc_mlb_platform_data *plat_data; + struct mlb_data *drvdata; struct resource *res; - void __iomem *base; + struct mxc_mlb_platform_data *plat_data; + plat_data = (struct mxc_mlb_platform_data *)pdev->dev.platform_data; plat_data->dev = &pdev->dev; + drvdata = kzalloc(sizeof(struct mlb_data), GFP_KERNEL); + if (!drvdata) { + dev_err(&pdev->dev, "can't allocate enough memory\n"); + return -ENOMEM; + } /** * Register MLB lld as four character devices */ - ret = alloc_chrdev_region(&dev, 0, MLB_MINOR_DEVICES, "mxc_mlb150"); - mlb_major = MAJOR(dev); - dev_dbg(plat_data->dev, "MLB device major: %d\n", mlb_major); - - if (unlikely(ret < 0)) { - dev_err(plat_data->dev, "can't get major %d\n", mlb_major); - goto err2; + ret = alloc_chrdev_region(&drvdata->firstdev, 0, + MLB_MINOR_DEVICES, "mxc_mlb150"); + mlb_major = MAJOR(drvdata->firstdev); + dev_dbg(&pdev->dev, "MLB device major: %d\n", mlb_major); + + if (ret < 0) { + dev_err(&pdev->dev, "can't get major %d\n", mlb_major); + goto err_reg; } - cdev_init(&plat_data->cdev, &mxc_mlb150_fops); - plat_data->cdev.owner = THIS_MODULE; + cdev_init(&drvdata->cdev, &mxc_mlb150_fops); + drvdata->cdev.owner = THIS_MODULE; - ret = cdev_add(&plat_data->cdev, dev, MLB_MINOR_DEVICES); - if (unlikely(ret)) { - dev_err(plat_data->dev, "can't add cdev\n"); - goto err2; + ret = cdev_add(&drvdata->cdev, drvdata->firstdev, MLB_MINOR_DEVICES); + if (ret) { + dev_err(&pdev->dev, "can't add cdev\n"); + goto err_reg; } /* create class and device for udev information */ - mlb_class = class_create(THIS_MODULE, "mlb150"); - if (unlikely(IS_ERR(mlb_class))) { - dev_err(plat_data->dev, "failed to create mlb150 class\n"); + drvdata->class = class_create(THIS_MODULE, "mlb150"); + if (IS_ERR(drvdata->class)) { + dev_err(&pdev->dev, "failed to create device class\n"); ret = -ENOMEM; - goto err2; + goto err_reg; } for (i = 0; i < MLB_MINOR_DEVICES; i++) { - class_dev = device_create(mlb_class, NULL, MKDEV(mlb_major, i), - NULL, mlb_devinfo[i].dev_name); - if (unlikely(IS_ERR(class_dev))) { - dev_err(plat_data->dev, "failed to create mlb150 %s" + struct device *class_dev; + + class_dev = device_create(drvdata->class, NULL, + MKDEV(mlb_major, i), + NULL, mlb_devinfo[i].dev_name); + if (IS_ERR(class_dev)) { + dev_err(&pdev->dev, "failed to create mlb150 %s" " class device\n", mlb_devinfo[i].dev_name); ret = -ENOMEM; - goto err1; + goto err_dev; } } - /* get irq line */ - /* AHB0 IRQ */ + /* get irq */ + /* ahb0 irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); if (unlikely(res == NULL)) { - dev_err(plat_data->dev, "No mlb150 ahb0 irq line provided\n"); - goto err0; + dev_err(&pdev->dev, "No ahb0 irq line provided\n"); + goto err_irq; } - - ahb0_irq = res->start; - dev_dbg(plat_data->dev, "ahb0_irq: %d\n", ahb0_irq); - if (request_irq(ahb0_irq, mlb_ahb_isr, 0, "mlb_ahb0", NULL)) { - dev_err(plat_data->dev, "failed to request irq\n"); - ret = -EBUSY; - goto err0; + drvdata->irq_ahb0 = res->start; + dev_dbg(&pdev->dev, "ahb0_irq: %d\n", drvdata->irq_ahb0); + if (request_irq(drvdata->irq_ahb0, mlb_ahb_isr, 0, "mlb_ahb0", NULL)) { + dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_ahb0); + goto err_irq; } - /* AHB1 IRQ */ + /* ahb1 irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 2); if (unlikely(res == NULL)) { - dev_err(plat_data->dev, "No mlb150 ahb0 irq line provided\n"); - goto err0; + dev_err(&pdev->dev, "No ahb1 irq line provided\n"); + goto err_irq; } - - ahb1_irq = res->start; - dev_dbg(plat_data->dev, "ahb1_irq: %d\n", ahb1_irq); - if (request_irq(ahb1_irq, mlb_ahb_isr, 0, "mlb_ahb1", NULL)) { - dev_err(plat_data->dev, "failed to request irq\n"); - ret = -EBUSY; - goto err0; + drvdata->irq_ahb1 = res->start; + dev_dbg(&pdev->dev, "ahb1_irq: %d\n", drvdata->irq_ahb1); + if (request_irq(drvdata->irq_ahb1, mlb_ahb_isr, 0, "mlb_ahb1", NULL)) { + dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_ahb1); + goto err_irq; } - /* MLB IRQ */ + /* mlb irq */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - dev_err(plat_data->dev, "No mlb150 irq line provided\n"); - goto err0; + if (unlikely(res == NULL)) { + dev_err(&pdev->dev, "No mlb irq line provided\n"); + goto err_irq; } - - mlb_irq = res->start; - dev_dbg(plat_data->dev, "mlb_irq: %d\n", mlb_irq); - if (request_irq(mlb_irq, mlb_isr, 0, "mlb", NULL)) { - dev_err(plat_data->dev, "failed to request irq\n"); - ret = -EBUSY; - goto err0; + drvdata->irq_mlb = res->start; + dev_dbg(&pdev->dev, "mlb_irq: %d\n", drvdata->irq_mlb); + if (request_irq(drvdata->irq_mlb, mlb_isr, 0, "mlb", NULL)) { + dev_err(&pdev->dev, "can't claim irq %d\n", drvdata->irq_mlb); + goto err_irq; } /* ioremap from phy mlb to kernel space */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(res == NULL)) { - dev_err(plat_data->dev, "No mlb150 base address provided\n"); - goto err0; + if (!res) { + dev_err(&pdev->dev, "can't get device resources\n"); + ret = -ENOENT; + goto err_unmap; } - - base = ioremap(res->start, res->end - res->start); - dev_dbg(plat_data->dev, "mapped mlb150 base address: 0x%08x\n", - (u32)base); - - if (unlikely(base == NULL)) { - dev_err(plat_data->dev, - "failed to do ioremap with mlb150 base\n"); - goto err0; + mlb_base = (u32)ioremap(res->start, res->end - res->start); + dev_dbg(&pdev->dev, "mapped base address: 0x%08x\n", (u32)mlb_base); + if (!mlb_base) { + dev_err(&pdev->dev, + "failed to get ioremap base\n"); + goto err_irq; } - mlb_base = (u32)base; - - dev_dbg(plat_data->dev, "mlb reg base: 0x%08x\n", mlb_base); + drvdata->membase = mlb_base; +#ifdef CONFIG_REGULATOR if (plat_data->reg_nvcc) { /* power on MLB */ - reg_nvcc = regulator_get(plat_data->dev, plat_data->reg_nvcc); - if (unlikely(!IS_ERR(reg_nvcc))) { + drvdata->nvcc = regulator_get(&pdev->dev, plat_data->reg_nvcc); + if (!IS_ERR(drvdata->nvcc)) { /* set MAX LDO6 for NVCC to 2.5V */ - regulator_set_voltage(reg_nvcc, 2500000, 2500000); - regulator_enable(reg_nvcc); + regulator_set_voltage(drvdata->nvcc, 2500000, 2500000); + regulator_enable(drvdata->nvcc); } } +#endif /* enable clock */ - if (likely(plat_data->mlb_clk)) { - mlb_clk = clk_get(plat_data->dev, plat_data->mlb_clk); - if (unlikely(IS_ERR(mlb_clk))) { + if (plat_data->mlb_clk) { + drvdata->clk_mlb3p = clk_get(&pdev->dev, plat_data->mlb_clk); + if (IS_ERR(drvdata->clk_mlb3p)) { dev_err(&pdev->dev, "unable to get mlb clock\n"); - ret = PTR_ERR(mlb_clk); - goto err0; + ret = PTR_ERR(drvdata->clk_mlb3p); + goto err_clk; } - clk_enable(mlb_clk); + clk_enable(drvdata->clk_mlb3p); } - if (likely(plat_data->mlb_pll_clk)) { - mlb_pll_clk = clk_get(plat_data->dev, plat_data->mlb_pll_clk); - if (unlikely(IS_ERR(mlb_pll_clk))) { + if (plat_data->mlb_pll_clk) { + drvdata->clk_mlb6p = clk_get(&pdev->dev, + plat_data->mlb_pll_clk); + if (IS_ERR(drvdata->clk_mlb6p)) { dev_err(&pdev->dev, "unable to get mlb pll clock\n"); - ret = PTR_ERR(mlb_pll_clk); - goto err0; + ret = PTR_ERR(drvdata->clk_mlb6p); + goto err_clk; } } - /* initial MLB module */ - mlb150_dev_init(); + platform_set_drvdata(pdev, drvdata); return 0; -err0: - if (likely(ahb0_irq)) { - free_irq(ahb0_irq, NULL); - ahb0_irq = 0; - } - if (likely(ahb1_irq)) { - free_irq(ahb1_irq, NULL); - ahb1_irq = 0; - } - if (likely(mlb_irq)) { - free_irq(mlb_irq, NULL); - mlb_irq = 0; - } -err1: +err_clk: + if (plat_data->mlb_clk) + clk_disable(drvdata->clk_mlb3p); + if (plat_data->mlb_pll_clk) + clk_disable(drvdata->clk_mlb6p); +err_irq: + if (drvdata->irq_ahb0) + free_irq(drvdata->irq_ahb0, NULL); + if (drvdata->irq_ahb1) + free_irq(drvdata->irq_ahb1, NULL); + if (drvdata->irq_mlb) + free_irq(drvdata->irq_mlb, NULL); +err_dev: for (--i; i >= 0; i--) - device_destroy(mlb_class, MKDEV(mlb_major, i)); + device_destroy(drvdata->class, MKDEV(mlb_major, i)); + + class_destroy(drvdata->class); +err_reg: + unregister_chrdev_region(drvdata->firstdev, MLB_MINOR_DEVICES); +err_unmap: + iounmap((void __iomem *)drvdata->membase); - class_destroy(mlb_class); -err2: - unregister_chrdev_region(dev, MLB_MINOR_DEVICES); + kfree(drvdata); return ret; } @@ -2363,6 +2453,7 @@ static int __devexit mxc_mlb150_remove(struct platform_device *pdev) { int i; struct mxc_mlb_platform_data *plat_data; + struct mlb_data *drvdata = platform_get_drvdata(pdev); plat_data = (struct mxc_mlb_platform_data *)pdev->dev.platform_data; @@ -2370,43 +2461,43 @@ static int __devexit mxc_mlb150_remove(struct platform_device *pdev) /* disable mlb clock */ if (plat_data->mlb_clk) { - clk_disable(mlb_clk); - clk_put(mlb_clk); + clk_disable(drvdata->clk_mlb3p); + clk_put(drvdata->clk_mlb3p); } - if (plat_data->mlb_pll_clk) - clk_put(mlb_pll_clk); + clk_put(drvdata->clk_mlb6p); /* disable mlb power */ - if (plat_data->reg_nvcc) { - regulator_disable(reg_nvcc); - regulator_put(reg_nvcc); +#ifdef CONFIG_REGULATOR + if (drvdata->nvcc) { + regulator_disable(drvdata->nvcc); + regulator_put(drvdata->nvcc); } +#endif /* inactive GPIO */ gpio_mlb_inactive(); /* iounmap */ - if (mlb_base) { - iounmap((void *)mlb_base); - mlb_base = 0; - } + iounmap((void __iomem *)drvdata->membase); - if (ahb0_irq) - free_irq(ahb0_irq, NULL); - if (ahb1_irq) - free_irq(ahb1_irq, NULL); - if (mlb_irq) - free_irq(mlb_irq, NULL); - ahb0_irq = ahb1_irq = mlb_irq = 0; + if (drvdata->irq_ahb0) + free_irq(drvdata->irq_ahb0, NULL); + if (drvdata->irq_ahb1) + free_irq(drvdata->irq_ahb1, NULL); + if (drvdata->irq_mlb) + free_irq(drvdata->irq_mlb, NULL); /* destroy mlb device class */ for (i = MLB_MINOR_DEVICES - 1; i >= 0; i--) - device_destroy(mlb_class, MKDEV(MAJOR(dev), i)); - class_destroy(mlb_class); + device_destroy(drvdata->class, + MKDEV(MAJOR(drvdata->firstdev), i)); + class_destroy(drvdata->class); /* Unregister the two MLB devices */ - unregister_chrdev_region(dev, MLB_MINOR_DEVICES); + unregister_chrdev_region(drvdata->firstdev, MLB_MINOR_DEVICES); + + kfree(drvdata); return 0; } @@ -2414,11 +2505,23 @@ static int __devexit mxc_mlb150_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int mxc_mlb150_suspend(struct platform_device *pdev, pm_message_t state) { + struct mlb_data *drvdata = platform_get_drvdata(pdev); + + mlb150_dev_exit(); + + clk_disable(drvdata->clk_mlb3p); + return 0; } static int mxc_mlb150_resume(struct platform_device *pdev) { + struct mlb_data *drvdata = platform_get_drvdata(pdev); + + mlb150_dev_init(); + + clk_enable(drvdata->clk_mlb6p); + return 0; } #else -- cgit v1.2.3 From f8f1b8124d552ec0320c4360b460ed2d74fab81d Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Fri, 12 Apr 2013 15:44:46 +0800 Subject: ENGR00258357-5: mlb: Use circle buf macros to replace old ringbuf mechanism Use circle buf to replace old ringbuf mechanism. Change to use circle buffer in read, write, rx isr and tx isr functions. In first design of MLB, it's using it's own mechanism to manage ring buffer, like in mxc_mlb.c. And then, I saw that kernel already had a serials of circ buffer macros which can be used to manage ring buffers. This patch is to use circle buffer macros to manage mlb internal ring buffers. For detail of circle buffers, you can refer to linux-2.6-imx/Documentation/circular-buffers.txt. Signed-off-by: Terry Lv --- drivers/mxc/mlb/mxc_mlb150.c | 571 +++++++++++++++++++++++++++---------------- include/linux/mxc_mlb.h | 7 +- 2 files changed, 371 insertions(+), 207 deletions(-) diff --git a/drivers/mxc/mlb/mxc_mlb150.c b/drivers/mxc/mlb/mxc_mlb150.c index 4fa3ff873e1f..a74a72bb029b 100755 --- a/drivers/mxc/mlb/mxc_mlb150.c +++ b/drivers/mxc/mlb/mxc_mlb150.c @@ -37,6 +37,7 @@ #include #include #include +#include #define DRIVER_NAME "mxc_mlb150" @@ -157,24 +158,30 @@ #define CAT_MODE_INBOUND_DMA (0x1 << 8) #define CAT_MODE_OUTBOUND_DMA (0x1 << 9) -#define CH_SYNC_BUF_DEP (128 * 4 * 4) -#define CH_CTRL_BUF_DEP (64) -#define CH_ASYNC_BUF_DEP (2048) -#define CH_ISOC_BLK_SIZE (196) -#define CH_ISOC_BLK_NUM (3) -#define CH_ISOC_BUF_DEP (CH_ISOC_BLK_SIZE * CH_ISOC_BLK_NUM) +#define CH_SYNC_DEFAULT_QUAD (1) +#define CH_SYNC_MAX_QUAD (15) +#define CH_SYNC_CDT_BUF_DEP (CH_SYNC_DEFAULT_QUAD * 4 * 4) +#define CH_SYNC_ADT_BUF_MULTI (4) +#define CH_SYNC_ADT_BUF_DEP (CH_SYNC_CDT_BUF_DEP * CH_SYNC_ADT_BUF_MULTI) +#define CH_SYNC_BUF_SZ (CH_SYNC_MAX_QUAD * 4 * 4 * CH_SYNC_ADT_BUF_MULTI) +#define CH_CTRL_CDT_BUF_DEP (64) +#define CH_CTRL_ADT_BUF_DEP (CH_CTRL_CDT_BUF_DEP) +#define CH_CTRL_BUF_SZ (CH_CTRL_ADT_BUF_DEP) +#define CH_ASYNC_CDT_BUF_DEP (2048) +#define CH_ASYNC_ADT_BUF_DEP (CH_ASYNC_CDT_BUF_DEP) +#define CH_ASYNC_BUF_SZ (CH_ASYNC_ADT_BUF_DEP) +#define CH_ISOC_BLK_SIZE_188 (188) +#define CH_ISOC_BLK_SIZE_196 (196) +#define CH_ISOC_BLK_SIZE (CH_ISOC_BLK_SIZE_188) +#define CH_ISOC_BLK_NUM (5) +#define CH_ISOC_CDT_BUF_DEP (CH_ISOC_BLK_SIZE * CH_ISOC_BLK_NUM) +#define CH_ISOC_ADT_BUF_DEP (CH_ISOC_CDT_BUF_DEP) +#define CH_ISOC_BUF_SZ (1024) #define CH_SYNC_DBR_BUF_OFFSET (0x0) -#define CH_CTRL_DBR_BUF_OFFSET (CH_SYNC_DBR_BUF_OFFSET + 2 * CH_SYNC_BUF_DEP) -#define CH_ASYNC_DBR_BUF_OFFSET (CH_CTRL_DBR_BUF_OFFSET + 2 * CH_CTRL_BUF_DEP) -#define CH_ISOC_DBR_BUF_OFFSET (CH_ASYNC_DBR_BUF_OFFSET + 2 * CH_ASYNC_BUF_DEP) - -static u32 mlb150_ch_packet_buf_size[4] = { - CH_SYNC_BUF_DEP, - CH_CTRL_BUF_DEP, - CH_ASYNC_BUF_DEP, - CH_ISOC_BUF_DEP -}; +#define CH_CTRL_DBR_BUF_OFFSET (CH_SYNC_DBR_BUF_OFFSET + 2 * (CH_SYNC_MAX_QUAD * 4 * 4)) +#define CH_ASYNC_DBR_BUF_OFFSET (CH_CTRL_DBR_BUF_OFFSET + 2 * CH_CTRL_CDT_BUF_DEP) +#define CH_ISOC_DBR_BUF_OFFSET (CH_ASYNC_DBR_BUF_OFFSET + 2 * CH_ASYNC_CDT_BUF_DEP) #define DBR_BUF_START 0x00000 @@ -1273,8 +1280,22 @@ static s32 mlb150_dev_reset_all_regs(void) return 0; } -static inline s32 mlb150_dev_set_ch_amba_ahb(u32 ch, enum MLB_CTYPE ctype, - u32 dne_sts, u32 buf_addr) +static inline s32 mlb150_dev_pipo_start(struct mlb_ringbuf *rbuf, + u32 ahb_ch, u32 buf_addr) +{ + u32 ctr_val[4] = { 0 }; + + ctr_val[1] |= ADT_RDY1; + ctr_val[2] = buf_addr; + + if (mlb150_dev_adt_write(ahb_ch, ctr_val)) + return -ETIME; + + return 0; +} + +static inline s32 mlb150_dev_pipo_next(u32 ahb_ch, enum MLB_CTYPE ctype, + u32 dne_sts, u32 buf_addr) { u32 ctr_val[4] = { 0 }; @@ -1294,42 +1315,25 @@ static inline s32 mlb150_dev_set_ch_amba_ahb(u32 ch, enum MLB_CTYPE ctype, ctr_val[2] = buf_addr; } -#ifdef DEBUG_ADT - pr_debug("mxc_mlb150: Set ADT val of channel %d, ctype: %d: " - "0x%08x 0x%08x 0x%08x 0x%08x\n", - ch, ctype, ctr_val[3], ctr_val[2], ctr_val[1], ctr_val[0]); -#endif - - if (unlikely(mlb150_dev_adt_write(ch, ctr_val))) + if (mlb150_dev_adt_write(ahb_ch, ctr_val)) return -ETIME; -#ifdef DEBUG_ADT_N - { - u32 ctr_rd[4] = { 0 }; - if (likely(!mlb150_dev_adt_read(ch, ctr_rd))) { - pr_debug("mxc_mlb150: ADT val of channel %d: " - "0x%08x 0x%08x 0x%08x 0x%08x\n", - ch, ctr_rd[3], ctr_rd[2], - ctr_rd[1], ctr_rd[0]); - if (ctr_rd[3] == ctr_val[3] && - ctr_rd[2] == ctr_val[2] && - ctr_rd[1] == ctr_val[1] && - ctr_rd[0] == ctr_val[0]) { - pr_debug("mxc_mlb150: set adt succeed!\n"); - return 0; - } else { - pr_debug("mxc_mlb150: set adt failed!\n"); - return -EBADE; - } - } else { - pr_debug("mxc_mlb150: Read ADT val of channel %d failed\n", - ch); - return -EBADE; - } - } -#endif + return 0; +} - return 0; +static inline s32 mlb150_dev_pipo_stop(struct mlb_ringbuf *rbuf, u32 ahb_ch) +{ + u32 ctr_val[4] = { 0 }; + unsigned long flags; + + write_lock_irqsave(&rbuf->rb_lock, flags); + rbuf->head = rbuf->tail = 0; + write_unlock_irqrestore(&rbuf->rb_lock, flags); + + if (mlb150_dev_adt_write(ahb_ch, ctr_val)) + return -ETIME; + + return 0; } static s32 mlb150_dev_init_ch_amba_ahb(struct mlb_dev_info *pdevinfo, @@ -1505,26 +1509,43 @@ static s32 mlb150_dev_unmute_syn_ch(u32 rx_ch, u32 rx_cl, u32 tx_ch, u32 tx_cl) return 0; } -/*! - * MLB receive start function - * - * load phy_head to next buf register to start next rx - * here use single-packet buffer, set start=end - */ -static inline void mlb_start_rx(u32 ch, s32 ctype, u32 dne_sts, u32 buf_addr) +/* In case the user calls channel shutdown, but rx or tx is not completed yet */ +static s32 mlb150_trans_complete_check(struct mlb_dev_info *pdevinfo) { - /* Set ADT for RX */ - mlb150_dev_set_ch_amba_ahb(ch, ctype, dne_sts, buf_addr); -} + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf; + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf; + s32 timeout = 1024; -/*! - * MLB transmit start function - * make sure aquiring the rw buf_lock, when calling this - */ -static inline void mlb_start_tx(u32 ch, s32 ctype, u32 dne_sts, u32 buf_addr) -{ - /* Set ADT for TX */ - mlb150_dev_set_ch_amba_ahb(ch, ctype, dne_sts, buf_addr); + while (timeout--) { + read_lock(&tx_rbuf->rb_lock); + if (!CIRC_CNT(tx_rbuf->head, tx_rbuf->tail, TRANS_RING_NODES)) { + read_unlock(&tx_rbuf->rb_lock); + break; + } else + read_unlock(&tx_rbuf->rb_lock); + } + + if (timeout <= 0) { + pr_debug("TX complete check timeout!\n"); + return -ETIME; + } + + timeout = 1024; + while (timeout--) { + read_lock(&rx_rbuf->rb_lock); + if (!CIRC_CNT(rx_rbuf->head, rx_rbuf->tail, TRANS_RING_NODES)) { + read_unlock(&rx_rbuf->rb_lock); + break; + } else + read_unlock(&rx_rbuf->rb_lock); + } + + if (timeout <= 0) { + pr_debug("RX complete check timeout!\n"); + return -ETIME; + } + + return 0; } /*! @@ -1596,123 +1617,134 @@ static void mlb_channel_enable(struct mlb_data *drvdata, /*! * MLB interrupt handler */ -static void mlb_tx_isr(int minor) -{ - struct mlb_dev_info *pdevinfo = &mlb_devinfo[minor]; - - pdevinfo->tx_busy = 0; - - wake_up_interruptible(&pdevinfo->wt_wq); -} - -static void mlb_rx_isr(int minor) +static void mlb_rx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo) { - struct mlb_dev_info *pdevinfo = &mlb_devinfo[minor]; - struct mlb_channel_info *pchinfo = &_get_rxchan(minor); - struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_bufs; - s32 wpos, rpos, adt_sts; - u32 rx_ring_buf = 0; - s32 ctype = pdevinfo->channel_type; - u32 ch_addr = pchinfo->address; + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf; + s32 head, tail, adt_sts; + unsigned long flags; + u32 rx_buf_ptr; #ifdef DEBUG_RX pr_debug("mxc_mlb150: mlb_rx_isr\n"); #endif - rpos = rx_rbuf->rpos; - wpos = rx_rbuf->wpos; + write_lock_irqsave(&rx_rbuf->rb_lock, flags); -#ifdef DEBUG_RX - pr_debug("adt_buf_ptr: 0x%08x\n", (u32)adt_buf_ptr); -#endif + head = (rx_rbuf->head + 1) & (TRANS_RING_NODES - 1); + tail = ACCESS_ONCE(rx_rbuf->tail); - /*! - * Copy packet from IRAM buf to ring buf. - * if the wpos++ == rpos, drop this packet - */ - if (((wpos + 1) % TRANS_RING_NODES) != rpos) { - rx_ring_buf = rx_rbuf->phy_addrs[(wpos + 1) % TRANS_RING_NODES]; -#ifdef DEBUG_RX - if (len > mlb150_ch_packet_buf_size[ctype]) - pr_debug("mxc_mlb150: packet overflow, " - "packet type: %d\n", ctype); -#endif + if (CIRC_SPACE(head, tail, TRANS_RING_NODES) >= 1) { + rx_buf_ptr = rx_rbuf->phy_addrs[head]; - /* update the ring wpos */ - rx_rbuf->wpos = (wpos + 1) % TRANS_RING_NODES; + /* commit the item before incrementing the head */ + smp_wmb(); - /* wake up the reader */ - wake_up_interruptible(&pdevinfo->rd_wq); + rx_rbuf->head = head; -#ifdef DEBUG_RX - pr_debug("recv package, len:%d, rx_rdpos: %d, rx_wtpos: %d\n", - len, rpos, pdevinfo->rx_bufs.wpos); -#endif - } else { - rx_ring_buf = pdevinfo->rx_bufs.phy_addrs[TRANS_RING_NODES]; + write_unlock_irqrestore(&rx_rbuf->rb_lock, flags); - pr_debug - ("drop package, due to no space, (%d,%d)\n", - rpos, pdevinfo->rx_bufs.wpos); + /* wake up the reader */ + wake_up_interruptible(&pdevinfo->rx_wq); + } else { + rx_buf_ptr = rx_rbuf->phy_addrs[TRANS_RING_NODES]; + write_unlock_irqrestore(&rx_rbuf->rb_lock, flags); + pr_debug("drop RX package, due to no space, (%d,%d)\n", + head, tail); } - adt_sts = mlb150_dev_get_adt_sts(ch_addr); - mlb_start_rx(ch_addr, ctype, adt_sts, rx_ring_buf); + adt_sts = mlb150_dev_get_adt_sts(ahb_ch); + /* Set ADT for RX */ + mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, rx_buf_ptr); +} + +static void mlb_tx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo) +{ + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf; + s32 head, tail, adt_sts; + u32 tx_buf_ptr; + unsigned long flags; + + write_lock_irqsave(&tx_rbuf->rb_lock, flags); + + head = ACCESS_ONCE(tx_rbuf->head); + tail = (tx_rbuf->tail + 1) & (TRANS_RING_NODES - 1); + smp_mb(); + tx_rbuf->tail = tail; + + /* check the current tx buffer is available or not */ + if (CIRC_CNT(head, tail, TRANS_RING_NODES) >= 1) { + /* read index before reading contents at that index */ + smp_read_barrier_depends(); + + tx_buf_ptr = tx_rbuf->phy_addrs[tail]; + + write_unlock_irqrestore(&tx_rbuf->rb_lock, flags); + + wake_up_interruptible(&pdevinfo->tx_wq); + + adt_sts = mlb150_dev_get_adt_sts(ahb_ch); + /* Set ADT for TX */ + mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, tx_buf_ptr); + } else + write_unlock_irqrestore(&tx_rbuf->rb_lock, flags); } static irqreturn_t mlb_ahb_isr(int irq, void *dev_id) { - u32 rx_int_sts, tx_int_sts, acsr0, - acsr1, rx_err, tx_err, hcer0, hcer1; - struct mlb_dev_info *pdev = NULL; - struct mlb_channel_info *ptxchinfo = NULL, *prxchinfo = NULL; - int minor; + u32 acsr0, hcer0; + u32 ch_mask = (1 << SYNC_RX_CL) | (1 << CTRL_RX_CL) + | (1 << ASYNC_RX_CL) | (1 << ISOC_RX_CL) + | (1 << SYNC_TX_CL) | (1 << CTRL_TX_CL) + | (1 << ASYNC_TX_CL) | (1 << ISOC_TX_CL); /* Step 5, Read the ACSRn registers to determine which channel or * channels are causing the interrupt */ acsr0 = __raw_readl(mlb_base + REG_ACSR0); - acsr1 = __raw_readl(mlb_base + REG_ACSR1); hcer0 = __raw_readl(mlb_base + REG_HCER0); - hcer1 = __raw_readl(mlb_base + REG_HCER1); /* Step 6, If ACTL.SCE = 1, write the result of step 5 back to ACSR0 * and ACSR1 to clear the interrupt */ - if (ACTL_SCE & __raw_readl(mlb_base + REG_ACTL)) { + /* We'll not set ACTL_SCE */ + /* + if (ACTL_SCE & __raw_readl(mlb_base + REG_ACTL)) __raw_writel(acsr0, mlb_base + REG_ACSR0); - __raw_writel(acsr1, mlb_base + REG_ACSR1); - } + */ - for (minor = 0; minor < MLB_MINOR_DEVICES; minor++) { - pdev = &mlb_devinfo[minor]; - prxchinfo = &_get_rxchan(minor); - ptxchinfo = &_get_txchan(minor); - - rx_int_sts = (prxchinfo->address < 31) ? acsr0 : acsr1; - tx_int_sts = (ptxchinfo->address < 31) ? acsr0 : acsr1; - rx_err = (prxchinfo->address < 31) ? hcer0 : hcer1; - tx_err = (ptxchinfo->address < 31) ? hcer0 : hcer1; - - /* get tx channel interrupt status */ - if (tx_int_sts & (1 << (ptxchinfo->address % 32))) { - if (!(tx_err & (1 << (ptxchinfo->address % 32)))) - mlb_tx_isr(minor); - else { - pr_debug("tx channel %d encountered an AHB error!\n", - ptxchinfo->address); - } - } + if (ch_mask & hcer0) + pr_err("CH encounters an AHB error: 0x%x\n", hcer0); - /* get rx channel interrupt status */ - if (rx_int_sts & (1 << (prxchinfo->address % 32))) { - if (!(rx_err & (1 << (prxchinfo->address % 32)))) - mlb_rx_isr(minor); - else { - pr_debug("rx channel %d encountered an AHB error!\n", - prxchinfo->address); - } - } - } + if ((1 << SYNC_RX_CL) & acsr0) + mlb_rx_isr(MLB_CTYPE_SYNC, SYNC_RX_CL, + &mlb_devinfo[MLB_CTYPE_SYNC]); + + if ((1 << CTRL_RX_CL) & acsr0) + mlb_rx_isr(MLB_CTYPE_CTRL, CTRL_RX_CL, + &mlb_devinfo[MLB_CTYPE_CTRL]); + + if ((1 << ASYNC_RX_CL) & acsr0) + mlb_rx_isr(MLB_CTYPE_ASYNC, ASYNC_RX_CL, + &mlb_devinfo[MLB_CTYPE_ASYNC]); + + if ((1 << ISOC_RX_CL) & acsr0) + mlb_rx_isr(MLB_CTYPE_ISOC, ISOC_RX_CL, + &mlb_devinfo[MLB_CTYPE_ISOC]); + + if ((1 << SYNC_TX_CL) & acsr0) + mlb_tx_isr(MLB_CTYPE_SYNC, SYNC_TX_CL, + &mlb_devinfo[MLB_CTYPE_SYNC]); + + if ((1 << CTRL_TX_CL) & acsr0) + mlb_tx_isr(MLB_CTYPE_CTRL, CTRL_TX_CL, + &mlb_devinfo[MLB_CTYPE_CTRL]); + + if ((1 << ASYNC_TX_CL) & acsr0) + mlb_tx_isr(MLB_CTYPE_ASYNC, ASYNC_TX_CL, + &mlb_devinfo[MLB_CTYPE_ASYNC]); + + if ((1 << ISOC_TX_CL) & acsr0) + mlb_tx_isr(MLB_CTYPE_ASYNC, ISOC_TX_CL, + &mlb_devinfo[MLB_CTYPE_ISOC]); return IRQ_HANDLED; } @@ -1997,6 +2029,37 @@ static long mxc_mlb150_ioctl(struct file *filp, } } else return -EAGAIN; + break; + case MLB_SET_ISOC_BLKSIZE_188: + pdevinfo->isoc_blksz = 188; + pdevinfo->cdt_buf_dep = pdevinfo->adt_buf_dep = + pdevinfo->isoc_blksz * CH_ISOC_BLK_NUM; + break; + case MLB_SET_ISOC_BLKSIZE_196: + pdevinfo->isoc_blksz = 196; + pdevinfo->cdt_buf_dep = pdevinfo->adt_buf_dep = + pdevinfo->isoc_blksz * CH_ISOC_BLK_NUM; + break; + case MLB_SET_SYNC_QUAD: + { + u32 quad; + + if (copy_from_user(&quad, argp, sizeof(quad))) { + pr_err("mxc_mlb150: get quad number " + "from user failed\n"); + return -EFAULT; + } + if (quad <= 0 || quad > 3) { + pr_err("mxc_mlb150: Invalid Quadlets!" + "Quadlets in Sync mode can " + "only be 1, 2, 3\n"); + return -EINVAL; + } + pdevinfo->sync_quad = quad; + /* Each quadlets is 4 bytes */ + pdevinfo->cdt_buf_dep = quad * 4 * 4; + pdevinfo->adt_buf_dep = + pdevinfo->cdt_buf_dep * CH_SYNC_ADT_BUF_MULTI; } break; case MLB_SET_FPS: @@ -2117,35 +2180,59 @@ static long mxc_mlb150_ioctl(struct file *filp, static ssize_t mxc_mlb150_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos) { - int minor, ret; - int size, rdpos; - struct mlb_ringbuf *rx_rbuf = NULL; - struct mlb_dev_info *pdevinfo = NULL; - -#ifdef DEBUG_RX - pr_debug("mxc_mlb150: mxc_mlb150_read\n"); -#endif - - minor = MINOR(filp->f_dentry->d_inode->i_rdev); + int size; + struct mlb_data *drvdata = filp->private_data; + struct mlb_dev_info *pdevinfo = drvdata->devinfo; + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf; + int head, tail; + unsigned long flags; - pdevinfo = &mlb_devinfo[minor]; + read_lock_irqsave(&rx_rbuf->rb_lock, flags); - rdpos = pdevinfo->rx_bufs.rpos; - rx_rbuf = &pdevinfo->rx_bufs; + head = ACCESS_ONCE(rx_rbuf->head); + tail = rx_rbuf->tail; /* check the current rx buffer is available or not */ - if (rdpos == rx_rbuf->wpos) { + if (0 == CIRC_CNT(head, tail, TRANS_RING_NODES)) { + read_unlock_irqrestore(&rx_rbuf->rb_lock, flags); + if (filp->f_flags & O_NONBLOCK) return -EAGAIN; - /* if !O_NONBLOCK, we wait for recv packet */ - ret = wait_event_interruptible(pdevinfo->rd_wq, - (rx_rbuf->wpos != rdpos)); - if (ret < 0) - return ret; + + do { + DEFINE_WAIT(__wait); + + for (;;) { + prepare_to_wait(&pdevinfo->rx_wq, + &__wait, TASK_INTERRUPTIBLE); + + read_lock_irqsave(&rx_rbuf->rb_lock, flags); + if (CIRC_CNT(rx_rbuf->head, rx_rbuf->tail, + TRANS_RING_NODES) > 0) { + read_unlock_irqrestore(&rx_rbuf->rb_lock, + flags); + break; + } + read_unlock_irqrestore(&rx_rbuf->rb_lock, + flags); + + if (!signal_pending(current)) { + schedule(); + continue; + } + return -ERESTARTSYS; + } + finish_wait(&pdevinfo->rx_wq, &__wait); + } while (0); + read_lock_irqsave(&rx_rbuf->rb_lock, flags); } + read_unlock_irqrestore(&rx_rbuf->rb_lock, flags); + + /* read index before reading contents at that index */ + smp_read_barrier_depends(); - size = mlb150_ch_packet_buf_size[minor]; - if (unlikely(size > count)) { + size = pdevinfo->adt_buf_dep; + if (size > count) { /* the user buffer is too small */ pr_warning ("mxc_mlb150: received data size is bigger than " @@ -2153,14 +2240,18 @@ static ssize_t mxc_mlb150_read(struct file *filp, char __user *buf, return -EINVAL; } - /* copy rx buffer data to user buffer */ - if (likely(copy_to_user(buf, rx_rbuf->virt_bufs[rdpos], size))) { + /* extract one item from the buffer */ + if (copy_to_user(buf, rx_rbuf->virt_bufs[tail], size)) { pr_err("mxc_mlb150: copy from user failed\n"); return -EFAULT; } - /* update the read ptr */ - rx_rbuf->rpos = (rdpos + 1) % TRANS_RING_NODES; + /* finish reading descriptor before incrementing tail */ + smp_mb(); + + write_lock_irqsave(&rx_rbuf->rb_lock, flags); + rx_rbuf->tail = (tail + 1) & (TRANS_RING_NODES - 1); + write_unlock_irqrestore(&rx_rbuf->rb_lock, flags); *f_pos = 0; @@ -2176,16 +2267,20 @@ static ssize_t mxc_mlb150_read(struct file *filp, char __user *buf, static ssize_t mxc_mlb150_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos) { - s32 minor = 0, ret = 0; + s32 ret = 0; struct mlb_channel_info *pchinfo = NULL; - struct mlb_dev_info *pdevinfo = NULL; - u32 adt_sts = 0; + struct mlb_data *drvdata = filp->private_data; + struct mlb_dev_info *pdevinfo = drvdata->devinfo; + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf; + int head, tail; + unsigned long flags; + /* minor = MINOR(filp->f_dentry->d_inode->i_rdev); - pchinfo = &_get_txchan(minor); - pdevinfo = &mlb_devinfo[minor]; + */ + pchinfo = &pdevinfo->channels[TX_CHANNEL]; - if (unlikely(count > pchinfo->buf_size)) { + if (count > pdevinfo->buf_size) { /* too many data to write */ pr_warning("mxc_mlb150: overflow write data\n"); return -EFBIG; @@ -2193,31 +2288,77 @@ static ssize_t mxc_mlb150_write(struct file *filp, const char __user *buf, *f_pos = 0; - /* check the current tx buffer is used or not */ - if (1 == pdevinfo->tx_busy) { + read_lock_irqsave(&tx_rbuf->rb_lock, flags); + + head = tx_rbuf->head; + tail = ACCESS_ONCE(tx_rbuf->tail); + + if (0 == CIRC_SPACE(head, tail, TRANS_RING_NODES)) { + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags); if (filp->f_flags & O_NONBLOCK) return -EAGAIN; + do { + DEFINE_WAIT(__wait); + + for (;;) { + prepare_to_wait(&pdevinfo->tx_wq, + &__wait, TASK_INTERRUPTIBLE); + + read_lock_irqsave(&tx_rbuf->rb_lock, flags); + if (CIRC_SPACE(tx_rbuf->head, tx_rbuf->tail, + TRANS_RING_NODES) > 0) { + read_unlock_irqrestore(&tx_rbuf->rb_lock, + flags); + break; + } + read_unlock_irqrestore(&tx_rbuf->rb_lock, + flags); - ret = wait_event_interruptible(pdevinfo->wt_wq, - 0 == pdevinfo->tx_busy); - - if (ret < 0) - goto out; + if (!signal_pending(current)) { + schedule(); + continue; + } + return -ERESTARTSYS; + } + finish_wait(&pdevinfo->tx_wq, &__wait); + } while (0); } - if (copy_from_user((void *)pchinfo->buf_ptr, buf, count)) { + if (copy_from_user((void *)tx_rbuf->virt_bufs[head], buf, count)) { + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags); pr_err("mxc_mlb: copy from user failed\n"); ret = -EFAULT; goto out; } - adt_sts = mlb150_dev_get_adt_sts(pchinfo->address); - pdevinfo->tx_busy = 1; - mlb_start_tx(pchinfo->address, pdevinfo->channel_type, - adt_sts, pchinfo->buf_phy_addr); + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags); + write_lock_irqsave(&tx_rbuf->rb_lock, flags); + smp_wmb(); + tx_rbuf->head = (head + 1) & (TRANS_RING_NODES - 1); + write_unlock_irqrestore(&tx_rbuf->rb_lock, flags); - ret = count; + read_lock_irqsave(&tx_rbuf->rb_lock, flags); + if (0 == CIRC_CNT(head, tail, TRANS_RING_NODES)) { + u32 tx_buf_ptr, ahb_ch; + s32 adt_sts; + u32 ctype = pdevinfo->channel_type; + + /* read index before reading contents at that index */ + smp_read_barrier_depends(); + + tx_buf_ptr = tx_rbuf->phy_addrs[tail]; + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags); + ahb_ch = pdevinfo->channels[TX_CHANNEL].cl; + adt_sts = mlb150_dev_get_adt_sts(ahb_ch); + + /* Set ADT for TX */ + mlb150_dev_pipo_next(ahb_ch, ctype, adt_sts, tx_buf_ptr); + } else { + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags); + } + + ret = count; out: return ret; } @@ -2227,23 +2368,41 @@ static unsigned int mxc_mlb150_poll(struct file *filp, { int minor; unsigned int ret = 0; - struct mlb_dev_info *pdevinfo = NULL; + struct mlb_data *drvdata = filp->private_data; + struct mlb_dev_info *pdevinfo = drvdata->devinfo; + struct mlb_ringbuf *tx_rbuf = &pdevinfo->tx_rbuf; + struct mlb_ringbuf *rx_rbuf = &pdevinfo->rx_rbuf; + int head, tail; + unsigned long flags; + minor = MINOR(filp->f_dentry->d_inode->i_rdev); - pdevinfo = &mlb_devinfo[minor]; + poll_wait(filp, &pdevinfo->rx_wq, wait); + poll_wait(filp, &pdevinfo->tx_wq, wait); - poll_wait(filp, &pdevinfo->rd_wq, wait); - poll_wait(filp, &pdevinfo->wt_wq, wait); + read_lock_irqsave(&tx_rbuf->rb_lock, flags); + + head = tx_rbuf->head; + tail = tx_rbuf->tail; /* check the tx buffer is avaiable or not */ - if (0 == pdevinfo->tx_busy) + if (CIRC_SPACE(head, tail, TRANS_RING_NODES) >= 1) ret |= POLLOUT | POLLWRNORM; + read_unlock_irqrestore(&tx_rbuf->rb_lock, flags); + + read_lock_irqsave(&rx_rbuf->rb_lock, flags); + + head = rx_rbuf->head; + tail = rx_rbuf->tail; + /* check the rx buffer filled or not */ - if (pdevinfo->rx_bufs.rpos != pdevinfo->rx_bufs.wpos) + if (CIRC_CNT(head, tail, TRANS_RING_NODES) >= 1) ret |= POLLIN | POLLRDNORM; + read_unlock_irqrestore(&rx_rbuf->rb_lock, flags); + /* check the exception event */ if (pdevinfo->ex_event) ret |= POLLIN | POLLRDNORM; diff --git a/include/linux/mxc_mlb.h b/include/linux/mxc_mlb.h index 7ac953c84dd3..3a63647b61b3 100644 --- a/include/linux/mxc_mlb.h +++ b/include/linux/mxc_mlb.h @@ -1,7 +1,7 @@ /* * mxc_mlb.h * - * Copyright 2008-2011 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2008-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -21,6 +21,7 @@ #define MLB_SET_FPS _IOW('S', 0x10, unsigned int) #define MLB_GET_VER _IOR('S', 0x11, unsigned long) #define MLB_SET_DEVADDR _IOR('S', 0x12, unsigned char) + /*! * set channel address for each logical channel * the MSB 16bits is for tx channel, the left LSB is for rx channel @@ -30,6 +31,10 @@ #define MLB_CHAN_SHUTDOWN _IO('S', 0x15) #define MLB_CHAN_GETEVENT _IOR('S', 0x16, unsigned long) +#define MLB_SET_ISOC_BLKSIZE_188 _IO('S', 0x17) +#define MLB_SET_ISOC_BLKSIZE_196 _IO('S', 0x18) +#define MLB_SET_SYNC_QUAD _IOW('S', 0x19, unsigned int) + /*! * MLB event define */ -- cgit v1.2.3 From 25af3594148e6ab16ad0d86b36cded7200c880d2 Mon Sep 17 00:00:00 2001 From: Huang Shijie Date: Fri, 12 Apr 2013 15:33:11 +0800 Subject: ENGR00258733 WEIM-NOR: mtd: cfi_cmdset_0002: Do not release the mutex lock The NOR may suffers a write-buffer timeout during the bonnie++/ubifs stress test. This patch is just a workaround to fix this issue. With this patch, the read/write/erase will do in the synchronous way. Signed-off-by: Huang Shijie --- drivers/mtd/chips/cfi_cmdset_0002.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index a35416cbdbb4..f3626b0d7b11 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -1040,17 +1040,13 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, #define UDELAY(map, chip, adr, usec) \ do { \ - mutex_unlock(&chip->mutex); \ cfi_udelay(usec); \ - mutex_lock(&chip->mutex); \ } while (0) #define INVALIDATE_CACHE_UDELAY(map, chip, adr, len, usec) \ do { \ - mutex_unlock(&chip->mutex); \ INVALIDATE_CACHED_RANGE(map, adr, len); \ cfi_udelay(usec); \ - mutex_lock(&chip->mutex); \ } while (0) #endif -- cgit v1.2.3 From 94108194acb45f6cc488c9ff4e8d561c113f6409 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 10 Oct 2011 23:43:53 +0200 Subject: can: dev: let can_get_echo_skb() return dlc of CAN frame can_get_echo_skb() is usually called in the TX complete handler. The stats->tx_packets and stats->tx_bytes should be updated there, too. This patch simplifies to figure out the size of the sent CAN frame. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev.c | 10 +++++++++- include/linux/can/dev.h | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index d0f8c7e67e7d..f0123ef7d89d 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -315,16 +315,24 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb); * is handled in the device driver. The driver must protect * access to priv->echo_skb, if necessary. */ -void can_get_echo_skb(struct net_device *dev, unsigned int idx) +unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx) { struct can_priv *priv = netdev_priv(dev); BUG_ON(idx >= priv->echo_skb_max); if (priv->echo_skb[idx]) { + struct sk_buff *skb = priv->echo_skb[idx]; + struct can_frame *cf = (struct can_frame *)skb->data; + u8 dlc = cf->can_dlc; + netif_rx(priv->echo_skb[idx]); priv->echo_skb[idx] = NULL; + + return dlc; } + + return 0; } EXPORT_SYMBOL_GPL(can_get_echo_skb); diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index cc0bb4961669..129dbee2c8d6 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -93,7 +93,7 @@ void can_bus_off(struct net_device *dev); void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, unsigned int idx); -void can_get_echo_skb(struct net_device *dev, unsigned int idx); +unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx); void can_free_echo_skb(struct net_device *dev, unsigned int idx); struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf); -- cgit v1.2.3 From 2bb0d0422f1bf18d4ecb1d8f3fd4bdefa0145d78 Mon Sep 17 00:00:00 2001 From: Reuben Dowle Date: Tue, 1 Nov 2011 11:18:03 +1300 Subject: can: flexcan: Fix CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK Currently the flexcan driver uses hardware local echo. This blindly echos all transmitted frames to all receiving sockets, regardless what CAN_RAW_RECV_OWN_MSGS and CAN_RAW_LOOPBACK are set to. This patch now submits transmitted frames to be echoed in the transmit complete interrupt, preserving the reference to the sending socket. This allows the can protocol to correctly handle the local echo. Further this patch moves tx_bytes statistic accounting into the tx_complete handler. Signed-off-by: Reuben Dowle [mkl: move tx_bytes accounting into tx_complete handler; cleanups] Signed-off-by: Marc Kleine-Budde --- drivers/net/can/flexcan.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 920b8a01f9cb..886905db1396 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -284,7 +284,6 @@ static int flexcan_get_berr_counter(const struct net_device *dev, static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) { const struct flexcan_priv *priv = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; struct flexcan_regs __iomem *regs = priv->base; struct can_frame *cf = (struct can_frame *)skb->data; u32 can_id; @@ -314,14 +313,11 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) writel(data, ®s->cantxfg[FLEXCAN_TX_BUF_ID].data[1]); } + can_put_echo_skb(skb, dev, 0); + writel(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); writel(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); - kfree_skb(skb); - - /* tx_packets is incremented in flexcan_irq */ - stats->tx_bytes += cf->can_dlc; - return NETDEV_TX_OK; } @@ -633,7 +629,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) /* transmission complete interrupt */ if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) { - /* tx_bytes is incremented in flexcan_start_xmit */ + stats->tx_bytes += can_get_echo_skb(dev, 0); stats->tx_packets++; writel((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); netif_wake_queue(dev); @@ -722,13 +718,14 @@ static int flexcan_chip_start(struct net_device *dev) * enable warning int * choose format C * enable self wakeup + * disable local echo * */ reg_mcr = readl(®s->mcr); reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_WAK_MSK | - FLEXCAN_MCR_SLF_WAK; + FLEXCAN_MCR_SLF_WAK | FLEXCAN_MCR_SRX_DIS; dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr); writel(reg_mcr, ®s->mcr); @@ -1008,7 +1005,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev) goto failed_map; } - dev = alloc_candev(sizeof(struct flexcan_priv), 0); + dev = alloc_candev(sizeof(struct flexcan_priv), 1); if (!dev) { err = -ENOMEM; goto failed_alloc; @@ -1016,7 +1013,7 @@ static int __devinit flexcan_probe(struct platform_device *pdev) dev->netdev_ops = &flexcan_netdev_ops; dev->irq = irq; - dev->flags |= IFF_ECHO; /* we support local echo in hardware */ + dev->flags |= IFF_ECHO; priv = netdev_priv(dev); priv->can.clock.freq = clk_get_rate(clk); -- cgit v1.2.3 From 4344b2db1a090e212b7c7aafcdcfca66316ce22a Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 12 Apr 2013 18:49:36 +0800 Subject: ENGR00258885 flexcan: fix errata ERR005641 that MB may fail to be sent This is an issue from IC errata ERR005641 which is described as follows: ---------------------------------------------------------- FlexCAN does not transmit a message that is enabled to be transmitted in a specific moment during the arbitration process. The following conditions are necessary to have the issue. - Only one MB is configured to be transmitted - The write which enables the MB to be transmitted (write on Control status word) happens during a specific clock during the arbitration process. After this arbitration process occurs, the bus goes to Idle state and no new message is received on bus. For example: 1) MB13 is deactivated on RxIntermission (write 0x0 on CODE field from Control Status word) - First write on CODE 2) Reconfigure the ID and data fields 3) Enable the MB13 to be transmitted on BusIdle (write 0xC on Code field) - Second write on code 4) CAN bus keeps in Idle state 5) No write on Control status from any MB happens. During the second write on code (step 3), the write must happen one clock before the current MB13 is to be scanned by arbitration process. In this case, it does not detect the new code (0xC) and no new arbitration is scheduled. The suggested workaround which is implemented in this patch is: The workaround consists of executing two extra steps: 6. Reserve the first valid mailbox as an inactive mailbox (CODE=0b1000). If RX FIFO is disabled, this mailbox must be MB0. Otherwise, the first valid mailbox can be found by using table "RX FIFO filters" on FlexCAN3 chapter. 7. Write twice INACTIVE code (0b1000) into the first valid mailbox. Note: The first mailbox cannot be used for reception or transmission process. ------------------------------------------------------------- Note: Although the currently flexcan driver does not have the step 1 to run, it's also possible to meet this issue in theory because we can not predict when the arbitration is scheduled. With a modified can-utils/canfdttest tool simulating Pingpong test, we were able to reproduce this issue after running a about one day. After applying this patch, we ran six days and did not see the issue happen again on two mx6q sabrelite boards. Signed-off-by: Dong Aisheng --- drivers/net/can/flexcan.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 886905db1396..d3b1342ca727 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -126,7 +126,8 @@ (FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE) /* FLEXCAN interrupt flag register (IFLAG) bits */ -#define FLEXCAN_TX_BUF_ID 8 +#define FLEXCAN_RESERVED_BUF_ID 8 +#define FLEXCAN_TX_BUF_ID 13 #define FLEXCAN_IFLAG_BUF(x) BIT(x) #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) @@ -318,6 +319,11 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) writel(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); writel(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + if (priv->version == FLEXCAN_VER_10_0_12) { + writel(0x0, ®s->cantxfg[FLEXCAN_RESERVED_BUF_ID].can_ctrl); + writel(0x0, ®s->cantxfg[FLEXCAN_RESERVED_BUF_ID].can_ctrl); + } + return NETDEV_TX_OK; } -- cgit v1.2.3 From 556681e28fda1c92eb2178306904a7df87f37449 Mon Sep 17 00:00:00 2001 From: Terry Lv Date: Tue, 16 Apr 2013 19:05:54 +0800 Subject: ENGR00259008: mlb: reduce iram usage amount in async mode In testing async mode on mx6q ard and mx6dl ard, driver always said "can not alloc rx buffer". Change async's ring buffer size from 2048 to 1536(MEP package size) and reduce the extra ring buffer for drop package, now the iram usage amount in async mode reduced from 34816 to 24576. Signed-off-by: Terry Lv --- drivers/mxc/mlb/mxc_mlb150.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/drivers/mxc/mlb/mxc_mlb150.c b/drivers/mxc/mlb/mxc_mlb150.c index a74a72bb029b..6b07d0f0a428 100755 --- a/drivers/mxc/mlb/mxc_mlb150.c +++ b/drivers/mxc/mlb/mxc_mlb150.c @@ -167,7 +167,9 @@ #define CH_CTRL_CDT_BUF_DEP (64) #define CH_CTRL_ADT_BUF_DEP (CH_CTRL_CDT_BUF_DEP) #define CH_CTRL_BUF_SZ (CH_CTRL_ADT_BUF_DEP) -#define CH_ASYNC_CDT_BUF_DEP (2048) +#define CH_ASYNC_MDP_PACKET_LEN (1024) +#define CH_ASYNC_MEP_PACKET_LEN (1536) +#define CH_ASYNC_CDT_BUF_DEP (CH_ASYNC_MEP_PACKET_LEN) #define CH_ASYNC_ADT_BUF_DEP (CH_ASYNC_CDT_BUF_DEP) #define CH_ASYNC_BUF_SZ (CH_ASYNC_ADT_BUF_DEP) #define CH_ISOC_BLK_SIZE_188 (188) @@ -264,18 +266,9 @@ #define TX_CHANNEL 0 #define RX_CHANNEL 1 -#define PING_BUF_MAX_SIZE (2 * 1024) -#define PONG_BUF_MAX_SIZE (2 * 1024) -/* max package data size */ -#define ASYNC_PACKET_SIZE 1024 -#define CTRL_PACKET_SIZE 64 #define TRANS_RING_NODES (1 << 3) -#define MLB_IRAM_SIZE (MLB_MINOR_DEVICES * (PING_BUF_MAX_SIZE + PONG_BUF_MAX_SIZE)) -#define _get_txchan(dev) mlb_devinfo[dev].channels[TX_CHANNEL] -#define _get_rxchan(dev) mlb_devinfo[dev].channels[RX_CHANNEL] - enum MLB_CTYPE { MLB_CTYPE_SYNC, MLB_CTYPE_CTRL, @@ -1646,7 +1639,7 @@ static void mlb_rx_isr(s32 ctype, u32 ahb_ch, struct mlb_dev_info *pdevinfo) /* wake up the reader */ wake_up_interruptible(&pdevinfo->rx_wq); } else { - rx_buf_ptr = rx_rbuf->phy_addrs[TRANS_RING_NODES]; + rx_buf_ptr = rx_rbuf->phy_addrs[head]; write_unlock_irqrestore(&rx_rbuf->rb_lock, flags); pr_debug("drop RX package, due to no space, (%d,%d)\n", head, tail); @@ -1902,11 +1895,11 @@ static int mxc_mlb150_open(struct inode *inode, struct file *filp) pchinfo = &pdevinfo->channels[TX_CHANNEL]; ring_buf_size = pdevinfo->buf_size; - buf_size = ring_buf_size * (TRANS_RING_NODES * 2 + 1); + buf_size = ring_buf_size * (TRANS_RING_NODES * 2); buf_addr = iram_alloc(buf_size, &phy_addr); if (buf_addr == NULL) { ret = -ENOMEM; - pr_err("can not alloc rx buffers\n"); + pr_err("can not alloc rx/tx buffers: %d\n", buf_size); return ret; } pdevinfo->rbuf_base_virt = buf_addr; -- cgit v1.2.3