diff options
Diffstat (limited to 'drivers')
43 files changed, 1170 insertions, 272 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 037b0d47d9..883b0e7bc9 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -15,7 +15,7 @@ source "drivers/mfd/Kconfig" source "drivers/led/Kconfig" source "drivers/eeprom/Kconfig" source "drivers/input/Kconfig" - +source "drivers/watchdog/Kconfig" source "drivers/pwm/Kconfig" source "drivers/dma/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index f40b321d3b..ea3263f615 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -16,3 +16,4 @@ obj-y += eeprom/ obj-$(CONFIG_PWM) += pwm/ obj-y += input/ obj-y += dma/ +obj-y += watchdog/ diff --git a/drivers/ata/disk_ata_drive.c b/drivers/ata/disk_ata_drive.c index 4602af3c0d..d5c583790c 100644 --- a/drivers/ata/disk_ata_drive.c +++ b/drivers/ata/disk_ata_drive.c @@ -231,7 +231,7 @@ static void __maybe_unused ata_dump_id(uint16_t *id) */ static void ata_fix_endianess(uint16_t *buf, unsigned wds) { -#if __BYTE_ORDER == __BIG_ENDIAN +#ifdef __BIG_ENDIAN unsigned u; for (u = 0; u < wds; u++) diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 81cedca1db..6cd428681f 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -241,15 +241,15 @@ static struct resource *dev_get_resource(struct device_d *dev, int num) return NULL; } -void __iomem *dev_get_mem_region(struct device_d *dev, int num) +void *dev_get_mem_region(struct device_d *dev, int num) { struct resource *res; res = dev_get_resource(dev, num); if (!res) - return res; + return NULL; - return (void __force __iomem *)res->start; + return (void __force *)res->start; } EXPORT_SYMBOL(dev_get_mem_region); @@ -261,7 +261,7 @@ void __iomem *dev_request_mem_region(struct device_d *dev, int num) if (!res) return NULL; - res = request_iomem_region(dev_name(dev), res->start, res->size); + res = request_iomem_region(dev_name(dev), res->start, res->end); if (!res) return NULL; @@ -339,7 +339,7 @@ static int do_devinfo_subtree(struct device_d *dev, int depth) list_for_each_entry(cdev, &dev->cdevs, devices_list) { for (i = 0; i < depth + 1; i++) printf(" "); - printf("`---- 0x%08lx-0x%08lx: /dev/%s\n", + printf("`---- 0x%08llx-0x%08llx: /dev/%s\n", cdev->offset, cdev->offset + cdev->size - 1, cdev->name); @@ -392,7 +392,7 @@ static int do_devinfo(int argc, char *argv[]) printf("name : %s\n", res->name); printf("start : " PRINTF_CONVERSION_RESOURCE "\nsize : " PRINTF_CONVERSION_RESOURCE "\n", - res->start, res->size); + res->start, resource_size(res)); } printf("driver: %s\n\n", dev->driver ? diff --git a/drivers/base/resource.c b/drivers/base/resource.c index 347b2f01f0..988d27ea93 100644 --- a/drivers/base/resource.c +++ b/drivers/base/resource.c @@ -47,7 +47,7 @@ struct device_d *add_generic_device(const char* devname, int id, const char *res if (resname) res[0].name = xstrdup(resname); res[0].start = start; - res[0].size = size; + res[0].end = start + size - 1; res[0].flags = flags; return add_generic_device_res(devname, id, res, 1, pdata); @@ -94,10 +94,10 @@ struct device_d *add_dm9000_device(int id, resource_size_t base, } res[0].start = base; - res[0].size = size; + res[0].end = base + size - 1; res[0].flags = IORESOURCE_MEM | flags; res[1].start = data; - res[1].size = size; + res[1].end = data + size - 1; res[1].flags = IORESOURCE_MEM | flags; return add_generic_device_res("dm9000", id, res, 2, pdata); @@ -113,10 +113,10 @@ struct device_d *add_usb_ehci_device(int id, resource_size_t hccr, res = xzalloc(sizeof(struct resource) * 2); res[0].start = hccr; - res[0].size = 0x40; + res[0].end = hccr + 0x10 - 1; res[0].flags = IORESOURCE_MEM; res[1].start = hcor; - res[1].size = 0xc0; + res[1].end = hcor + 0xc0 - 1; res[1].flags = IORESOURCE_MEM; return add_generic_device_res("ehci", id, res, 2, pdata); @@ -146,10 +146,10 @@ struct device_d *add_ks8851_device(int id, resource_size_t addr, res = xzalloc(sizeof(struct resource) * 2); res[0].start = addr; - res[0].size = size; + res[0].end = addr + size - 1; res[0].flags = IORESOURCE_MEM | flags; res[1].start = addr_cmd; - res[1].size = size; + res[1].end = addr_cmd + size - 1; res[1].flags = IORESOURCE_MEM | flags; return add_generic_device_res("ks8851_mll", id, res, 2, pdata); diff --git a/drivers/eeprom/at25.c b/drivers/eeprom/at25.c index 8a979d53a1..03d191eb90 100644 --- a/drivers/eeprom/at25.c +++ b/drivers/eeprom/at25.c @@ -67,7 +67,7 @@ struct at25_data { static ssize_t at25_ee_read(struct cdev *cdev, void *buf, size_t count, - ulong offset, + loff_t offset, ulong flags) { u8 command[EE_MAXADDRLEN + 1]; @@ -117,7 +117,7 @@ static ssize_t at25_ee_read(struct cdev *cdev, */ status = spi_sync(at25->spi, &m); dev_dbg(at25->cdev.dev, - "read %d bytes at %lu --> %d\n", + "read %d bytes at %llu --> %d\n", count, offset, (int) status); return status ? status : count; @@ -126,7 +126,7 @@ static ssize_t at25_ee_read(struct cdev *cdev, static ssize_t at25_ee_write(struct cdev *cdev, const void *buf, size_t count, - ulong off, + loff_t off, ulong flags) { ssize_t status = 0; @@ -232,7 +232,7 @@ static ssize_t at25_ee_write(struct cdev *cdev, return written ? written : status; } -static off_t at25_ee_lseek(struct cdev *cdev, off_t off) +static loff_t at25_ee_lseek(struct cdev *cdev, loff_t off) { return off; } diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index ae3c805997..585cab9e54 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -70,7 +70,7 @@ struct fsl_esdhc { struct fsl_esdhc_host { struct mci_host mci; - struct fsl_esdhc *regs; + struct fsl_esdhc __iomem *regs; u32 no_snoop; unsigned long cur_clock; struct device_d *dev; @@ -81,7 +81,7 @@ struct fsl_esdhc_host { #define SDHCI_CMD_ABORTCMD (0xC0 << 16) /* Return the XFERTYP flags for a given command and data packet */ -u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) +static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data) { u32 xfertyp = 0; @@ -185,7 +185,7 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data) static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc *regs = host->regs; + struct fsl_esdhc __iomem *regs = host->regs; #ifndef CONFIG_MCI_IMX_ESDHC_PIO u32 wml_value; @@ -237,7 +237,7 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) u32 xfertyp, mixctrl; u32 irqstat; struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc *regs = host->regs; + struct fsl_esdhc __iomem *regs = host->regs; int ret; esdhc_write32(®s->irqstat, -1); @@ -353,11 +353,11 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data) return 0; } -void set_sysctl(struct mci_host *mci, u32 clock) +static void set_sysctl(struct mci_host *mci, u32 clock) { int div, pre_div; struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc *regs = host->regs; + struct fsl_esdhc __iomem *regs = host->regs; int sdhc_clk = imx_get_mmcclk(); u32 clk; @@ -400,7 +400,7 @@ void set_sysctl(struct mci_host *mci, u32 clock) static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc *regs = host->regs; + struct fsl_esdhc __iomem *regs = host->regs; /* Set the clock speed */ set_sysctl(mci, ios->clock); @@ -425,7 +425,7 @@ static void esdhc_set_ios(struct mci_host *mci, struct mci_ios *ios) static int esdhc_card_detect(struct fsl_esdhc_host *host) { - struct fsl_esdhc *regs = host->regs; + struct fsl_esdhc __iomem *regs = host->regs; struct esdhc_platform_data *pdata = host->dev->platform_data; int ret; @@ -451,7 +451,7 @@ static int esdhc_card_detect(struct fsl_esdhc_host *host) static int esdhc_init(struct mci_host *mci, struct device_d *dev) { struct fsl_esdhc_host *host = to_fsl_esdhc(mci); - struct fsl_esdhc *regs = host->regs; + struct fsl_esdhc __iomem *regs = host->regs; int timeout = 1000; int ret = 0; @@ -493,7 +493,7 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev) return ret; } -static int esdhc_reset(struct fsl_esdhc *regs) +static int esdhc_reset(struct fsl_esdhc __iomem *regs) { uint64_t start; diff --git a/drivers/mci/imx-esdhc.h b/drivers/mci/imx-esdhc.h index 19fed5aebf..7d5ed85dfd 100644 --- a/drivers/mci/imx-esdhc.h +++ b/drivers/mci/imx-esdhc.h @@ -39,7 +39,6 @@ #define SYSCTL_PEREN 0x00000004 #define SYSCTL_HCKEN 0x00000002 #define SYSCTL_IPGEN 0x00000001 -#define SYSCTL_RSTA 0x01000000 #define IRQSTAT 0x0002e030 #define IRQSTAT_DMAE (0x10000000) diff --git a/drivers/mfd/lp3972.c b/drivers/mfd/lp3972.c index 98266990dc..0f3093bd15 100644 --- a/drivers/mfd/lp3972.c +++ b/drivers/mfd/lp3972.c @@ -58,7 +58,7 @@ static u32 lp_read_reg(struct lp_priv *lp, int reg) return buf; } -static ssize_t lp_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t lp_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) { struct lp_priv *priv = to_lp_priv(cdev); int i = count; diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c index f9477a3540..2934e9d9bd 100644 --- a/drivers/mfd/mc13xxx.c +++ b/drivers/mfd/mc13xxx.c @@ -160,7 +160,7 @@ int mc13xxx_set_bits(struct mc13xxx *mc13xxx, u8 reg, u32 mask, u32 val) } EXPORT_SYMBOL(mc13xxx_set_bits); -static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) { struct mc13xxx *priv = to_mc13xxx(cdev); u32 *buf = _buf; @@ -181,7 +181,7 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset return count; } -static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) { struct mc13xxx *mc13xxx = to_mc13xxx(cdev); const u32 *buf = _buf; diff --git a/drivers/mfd/mc34704.c b/drivers/mfd/mc34704.c index a2171b35d1..20c01e2be6 100644 --- a/drivers/mfd/mc34704.c +++ b/drivers/mfd/mc34704.c @@ -65,7 +65,7 @@ int mc34704_reg_write(struct mc34704 *mc34704, u8 reg, u8 val) EXPORT_SYMBOL(mc34704_reg_write) static ssize_t mc34704_read(struct cdev *cdev, void *_buf, size_t count, - ulong offset, ulong flags) + loff_t offset, ulong flags) { struct mc34704 *priv = to_mc34704(cdev); u8 *buf = _buf; @@ -85,7 +85,7 @@ static ssize_t mc34704_read(struct cdev *cdev, void *_buf, size_t count, } static ssize_t mc34704_write(struct cdev *cdev, const void *_buf, size_t count, - ulong offset, ulong flags) + loff_t offset, ulong flags) { struct mc34704 *mc34704 = to_mc34704(cdev); const u8 *buf = _buf; diff --git a/drivers/mfd/mc34708.c b/drivers/mfd/mc34708.c index e7f40c02b7..02c58a997d 100644 --- a/drivers/mfd/mc34708.c +++ b/drivers/mfd/mc34708.c @@ -163,7 +163,8 @@ int mc34708_set_bits(struct mc34708 *mc34708, enum mc34708_reg reg, u32 mask, u3 } EXPORT_SYMBOL(mc34708_set_bits); -static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, + loff_t offset, ulong flags) { struct mc34708 *priv = to_mc34708(cdev); u32 *buf = _buf; @@ -184,7 +185,8 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset return count; } -static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, + loff_t offset, ulong flags) { struct mc34708 *mc34708 = to_mc34708(cdev); const u32 *buf = _buf; diff --git a/drivers/mfd/mc9sdz60.c b/drivers/mfd/mc9sdz60.c index db208ec2db..0cd5007e1c 100644 --- a/drivers/mfd/mc9sdz60.c +++ b/drivers/mfd/mc9sdz60.c @@ -78,7 +78,7 @@ int mc9sdz60_set_bits(struct mc9sdz60 *mc9sdz60, enum mc9sdz60_reg reg, u8 mask, } EXPORT_SYMBOL(mc9sdz60_set_bits); -static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) { struct mc9sdz60 *mc9sdz60 = to_mc9sdz60(cdev); u8 *buf = _buf; @@ -97,7 +97,7 @@ static ssize_t mc_read(struct cdev *cdev, void *_buf, size_t count, ulong offset return count; } -static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t mc_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) { struct mc9sdz60 *mc9sdz60 = to_mc9sdz60(cdev); const u8 *buf = _buf; diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c index cb2c03dfca..20bde2cf89 100644 --- a/drivers/mfd/twl-core.c +++ b/drivers/mfd/twl-core.c @@ -112,7 +112,7 @@ int twlcore_set_bits(struct twlcore *twlcore, u16 reg, u8 mask, u8 val) EXPORT_SYMBOL(twlcore_set_bits); static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count, - ulong offset, ulong flags) + loff_t offset, ulong flags) { struct twlcore *priv = to_twlcore(cdev); u8 *buf = _buf; @@ -131,7 +131,7 @@ static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count, } static ssize_t twl_write(struct cdev *cdev, const void *_buf, size_t count, - ulong offset, ulong flags) + loff_t offset, ulong flags) { struct twlcore *twlcore = to_twlcore(cdev); const u8 *buf = _buf; diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index 87dcba6801..5510439a87 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -31,11 +31,12 @@ static LIST_HEAD(mtd_register_hooks); static ssize_t mtd_read(struct cdev *cdev, void* buf, size_t count, - ulong offset, ulong flags) + loff_t _offset, ulong flags) { struct mtd_info *mtd = cdev->priv; size_t retlen; int ret; + unsigned long offset = _offset; debug("mtd_read: 0x%08lx 0x%08x\n", offset, count); @@ -64,13 +65,14 @@ static int all_ff(const void *buf, int len) } static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count, - ulong offset, ulong flags) + loff_t _offset, ulong flags) { struct mtd_info *mtd = cdev->priv; size_t retlen, now; int ret = 0; void *wrbuf = NULL; size_t count = _count; + unsigned long offset = _offset; if (NOTALIGNED(offset)) { printf("offset 0x%0lx not page aligned\n", offset); @@ -123,16 +125,17 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) struct mtd_ecc_stats *ecc = buf; #endif struct region_info_user *reg = buf; + loff_t *offset = buf; switch (request) { case MEMGETBADBLOCK: - dev_dbg(cdev->dev, "MEMGETBADBLOCK: 0x%08lx\n", (off_t)buf); - ret = mtd->block_isbad(mtd, (off_t)buf); + dev_dbg(cdev->dev, "MEMGETBADBLOCK: 0x%08llx\n", *offset); + ret = mtd->block_isbad(mtd, *offset); break; #ifdef CONFIG_MTD_WRITE case MEMSETBADBLOCK: - dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08lx\n", (off_t)buf); - ret = mtd->block_markbad(mtd, (off_t)buf); + dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08llx\n", *offset); + ret = mtd->block_markbad(mtd, *offset); break; #endif case MEMGETINFO: @@ -156,9 +159,10 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) #endif case MEMGETREGIONINFO: if (cdev->mtd) { + unsigned long size = cdev->size; reg->offset = cdev->offset; reg->erasesize = cdev->mtd->erasesize; - reg->numblocks = cdev->size/reg->erasesize; + reg->numblocks = size / reg->erasesize; reg->regionindex = cdev->mtd->index; } break; @@ -170,7 +174,7 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf) } #ifdef CONFIG_MTD_WRITE -static ssize_t mtd_erase(struct cdev *cdev, size_t count, unsigned long offset) +static ssize_t mtd_erase(struct cdev *cdev, size_t count, loff_t offset) { struct mtd_info *mtd = cdev->priv; struct erase_info erase; diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c index be656a4d33..e4dd1a00c8 100644 --- a/drivers/mtd/mtdoob.c +++ b/drivers/mtd/mtdoob.c @@ -38,11 +38,12 @@ static struct mtd_info *to_mtd(struct cdev *cdev) } static ssize_t mtd_read_oob(struct cdev *cdev, void *buf, size_t count, - ulong offset, ulong flags) + loff_t _offset, ulong flags) { struct mtd_info *mtd = to_mtd(cdev); struct mtd_oob_ops ops; int ret; + unsigned long offset = _offset; if (count < mtd->oobsize) return -EINVAL; diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c index 7abe2351a5..24f7358098 100644 --- a/drivers/mtd/mtdraw.c +++ b/drivers/mtd/mtdraw.c @@ -116,12 +116,13 @@ err: } static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count, - ulong offset, ulong flags) + loff_t _offset, ulong flags) { struct mtd_info *mtd = to_mtd(cdev); ssize_t retlen = 0, ret = 1, toread; ulong numpage; int skip; + unsigned long offset = _offset; numpage = offset / (mtd->writesize + mtd->oobsize); skip = offset % (mtd->writesize + mtd->oobsize); @@ -167,13 +168,14 @@ static void mtdraw_fillbuf(struct mtdraw *mtdraw, const void *src, int nbbytes) } static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, - ulong offset, ulong flags) + loff_t _offset, ulong flags) { struct mtdraw *mtdraw = to_mtdraw(cdev); struct mtd_info *mtd = to_mtd(cdev); int bsz = mtd->writesize + mtd->oobsize; ulong numpage; size_t retlen = 0, tofill; + unsigned long offset = _offset; int ret = 0; if (mtdraw->write_fill && @@ -220,10 +222,11 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, } } -static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, ulong offset) +static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset) { struct mtd_info *mtd = to_mtd(cdev); struct erase_info erase; + unsigned long offset = _offset; int ret; offset = offset / (mtd->writesize + mtd->oobsize) * mtd->writesize; diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c index bd30438958..d27274924a 100644 --- a/drivers/mtd/nand/nand-bb.c +++ b/drivers/mtd/nand/nand-bb.c @@ -42,9 +42,9 @@ struct nand_bb { struct mtd_info_user info; - size_t raw_size; - size_t size; - off_t offset; + loff_t raw_size; + loff_t size; + loff_t offset; unsigned long flags; void *writebuf; @@ -54,7 +54,7 @@ struct nand_bb { }; static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count, - unsigned long offset, ulong flags) + loff_t offset, ulong flags) { struct nand_bb *bb = cdev->priv; struct cdev *parent = bb->cdev_parent; @@ -63,18 +63,18 @@ static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count, debug("%s %d %d\n", __func__, offset, count); while(count) { - ret = cdev_ioctl(parent, MEMGETBADBLOCK, (void *)bb->offset); + ret = cdev_ioctl(parent, MEMGETBADBLOCK, &bb->offset); if (ret < 0) return ret; if (ret) { - printf("skipping bad block at 0x%08lx\n", bb->offset); + printf("skipping bad block at 0x%08llx\n", bb->offset); bb->offset += bb->info.erasesize; continue; } now = min(count, (size_t)(bb->info.erasesize - - (bb->offset % bb->info.erasesize))); + ((size_t)bb->offset % bb->info.erasesize))); ret = cdev_read(parent, buf, now, bb->offset, 0); if (ret < 0) return ret; @@ -96,10 +96,10 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count) int ret, now; struct cdev *parent = bb->cdev_parent; void *buf = bb->writebuf; - int cur_ofs = bb->offset & ~(BB_WRITEBUF_SIZE - 1); + off_t cur_ofs = bb->offset & ~(BB_WRITEBUF_SIZE - 1); while (count) { - ret = cdev_ioctl(parent, MEMGETBADBLOCK, (void *)cur_ofs); + ret = cdev_ioctl(parent, MEMGETBADBLOCK, &cur_ofs); if (ret < 0) return ret; @@ -123,12 +123,12 @@ static int nand_bb_write_buf(struct nand_bb *bb, size_t count) } static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count, - unsigned long offset, ulong flags) + loff_t offset, ulong flags) { struct nand_bb *bb = cdev->priv; int bytes = count, now, wroffs, ret; - debug("%s offset: 0x%08x count: 0x%08x\n", __func__, offset, count); + debug("%s offset: 0x%08llx count: 0x%08x\n", __func__, offset, count); while (count) { wroffs = bb->offset % BB_WRITEBUF_SIZE; @@ -152,7 +152,7 @@ static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count, return bytes; } -static int nand_bb_erase(struct cdev *cdev, size_t count, unsigned long offset) +static int nand_bb_erase(struct cdev *cdev, size_t count, loff_t offset) { struct nand_bb *bb = cdev->priv; @@ -197,11 +197,11 @@ static int nand_bb_close(struct cdev *cdev) static int nand_bb_calc_size(struct nand_bb *bb) { - ulong pos = 0; + loff_t pos = 0; int ret; while (pos < bb->raw_size) { - ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, (void *)pos); + ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, &pos); if (ret < 0) return ret; if (!ret) @@ -213,7 +213,7 @@ static int nand_bb_calc_size(struct nand_bb *bb) return 0; } -static off_t nand_bb_lseek(struct cdev *cdev, off_t __offset) +static loff_t nand_bb_lseek(struct cdev *cdev, loff_t __offset) { struct nand_bb *bb = cdev->priv; unsigned long raw_pos = 0; diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 95bef1f9e0..c99b64db21 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -12,7 +12,7 @@ struct ubi_volume_cdev_priv { }; static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size, - unsigned long offset, unsigned long flags) + loff_t offset, unsigned long flags) { struct ubi_volume_cdev_priv *priv = cdev->priv; struct ubi_volume *vol = priv->vol; @@ -23,7 +23,7 @@ static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size, loff_t offp = offset; int usable_leb_size = vol->usable_leb_size; - printf("%s: %d @ 0x%08lx\n", __func__, size, offset); + printf("%s: %d @ 0x%08llx\n", __func__, size, offset); len = size > usable_leb_size ? usable_leb_size : size; @@ -56,7 +56,7 @@ static ssize_t ubi_volume_cdev_read(struct cdev *cdev, void *buf, size_t size, } static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf, - size_t size, unsigned long offset, unsigned long flags) + size_t size, loff_t offset, unsigned long flags) { struct ubi_volume_cdev_priv *priv = cdev->priv; struct ubi_volume *vol = priv->vol; @@ -121,7 +121,7 @@ static int ubi_volume_cdev_close(struct cdev *cdev) return 0; } -static off_t ubi_volume_cdev_lseek(struct cdev *cdev, off_t ofs) +static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs) { struct ubi_volume_cdev_priv *priv = cdev->priv; diff --git a/drivers/mtd/ubi/ubi-barebox.h b/drivers/mtd/ubi/ubi-barebox.h index d23228f648..72f29a61e7 100644 --- a/drivers/mtd/ubi/ubi-barebox.h +++ b/drivers/mtd/ubi/ubi-barebox.h @@ -135,7 +135,6 @@ struct kmem_cache { int i; }; #define GFP_KERNEL 0 #define GFP_NOFS 1 -#define __user #define __init #define __exit diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 172cc39080..749ea6a9c0 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -13,6 +13,9 @@ config HAS_AT91_ETHER config HAS_NETX_ETHER bool +config HAS_DESIGNWARE_ETH + bool + config ARCH_HAS_FEC_IMX bool @@ -108,6 +111,19 @@ config DRIVER_NET_KS8851_MLL This option enables support for the Micrel KS8851 MLL ethernet chip. +config DRIVER_NET_DESIGNWARE + bool "Designware Universal MAC ethernet driver" + select MIIDEV + depends on HAS_DESIGNWARE_ETH + help + This option enables support for the Synopsys + Designware Core Univesal MAC 10M/100M/1G ethernet IP. + +config DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR + bool + depends on DRIVER_NET_DESIGNWARE + default n + source "drivers/net/usb/Kconfig" endmenu diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 34dbee9e13..29727b7d5b 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -13,3 +13,4 @@ obj-$(CONFIG_MIIDEV) += miidev.o obj-$(CONFIG_NET_USB) += usb/ obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o obj-$(CONFIG_DRIVER_NET_KS8851_MLL) += ks8851_mll.o +obj-$(CONFIG_DRIVER_NET_DESIGNWARE) += designware.o diff --git a/drivers/net/designware.c b/drivers/net/designware.c new file mode 100644 index 0000000000..379b4e39a5 --- /dev/null +++ b/drivers/net/designware.c @@ -0,0 +1,436 @@ +/* + * (C) Copyright 2010 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Designware ethernet IP driver for u-boot + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <net.h> +#include <miidev.h> +#include <asm/mmu.h> +#include <net/designware.h> +#include "designware.h" + + +struct dw_eth_dev { + struct eth_device netdev; + struct mii_device miidev; + + void (*fix_mac_speed)(int speed); + u8 macaddr[6]; + u32 tx_currdescnum; + u32 rx_currdescnum; + + struct dmamacdescr *tx_mac_descrtable; + struct dmamacdescr *rx_mac_descrtable; + + u8 *txbuffs; + u8 *rxbuffs; + + struct eth_mac_regs *mac_regs_p; + struct eth_dma_regs *dma_regs_p; +}; + +/* Speed specific definitions */ +#define SPEED_10M 1 +#define SPEED_100M 2 +#define SPEED_1000M 3 + +/* Duplex mode specific definitions */ +#define HALF_DUPLEX 1 +#define FULL_DUPLEX 2 + + +static int dwc_ether_mii_read(struct mii_device *dev, int addr, int reg) +{ + struct dw_eth_dev *priv = dev->edev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + u64 start; + u32 miiaddr; + + miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ + ((reg << MIIREGSHIFT) & MII_REGMSK); + + writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); + + start = get_time_ns(); + while (readl(&mac_p->miiaddr) & MII_BUSY) { + if (is_timeout(start, 10 * MSECOND)) { + dev_err(&priv->netdev.dev, "MDIO timeout\n"); + return -EIO; + } + } + return readl(&mac_p->miidata) & 0xffff; +} + +static int dwc_ether_mii_write(struct mii_device *dev, int addr, int reg, int val) +{ + struct dw_eth_dev *priv = dev->edev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + u64 start; + u32 miiaddr; + + writel(val, &mac_p->miidata); + miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ + ((reg << MIIREGSHIFT) & MII_REGMSK) | MII_WRITE; + + writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); + + start = get_time_ns(); + while (readl(&mac_p->miiaddr) & MII_BUSY) { + if (is_timeout(start, 10 * MSECOND)) { + dev_err(&priv->netdev.dev, "MDIO timeout\n"); + return -EIO; + } + } + + /* Needed as a fix for ST-Phy */ + dwc_ether_mii_read(dev, addr, reg); + return 0; +} + + +static int mac_reset(struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + struct eth_dma_regs *dma_p = priv->dma_regs_p; + u64 start; + + writel(DMAMAC_SRST, &dma_p->busmode); + writel(MII_PORTSELECT, &mac_p->conf); + + start = get_time_ns(); + while (readl(&dma_p->busmode) & DMAMAC_SRST) { + if (is_timeout(start, 10 * MSECOND)) { + dev_err(&priv->netdev.dev, "MAC reset timeout\n"); + return -EIO; + } + } + return 0; +} + +static void tx_descs_init(struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_dma_regs *dma_p = priv->dma_regs_p; + struct dmamacdescr *desc_table_p = &priv->tx_mac_descrtable[0]; + char *txbuffs = &priv->txbuffs[0]; + struct dmamacdescr *desc_p; + u32 idx; + + for (idx = 0; idx < CONFIG_TX_DESCR_NUM; idx++) { + desc_p = &desc_table_p[idx]; + desc_p->dmamac_addr = &txbuffs[idx * CONFIG_ETH_BUFSIZE]; + desc_p->dmamac_next = &desc_table_p[idx + 1]; + +#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) + desc_p->txrx_status &= ~(DESC_TXSTS_TXINT | DESC_TXSTS_TXLAST | + DESC_TXSTS_TXFIRST | DESC_TXSTS_TXCRCDIS | \ + DESC_TXSTS_TXCHECKINSCTRL | \ + DESC_TXSTS_TXRINGEND | DESC_TXSTS_TXPADDIS); + + desc_p->txrx_status |= DESC_TXSTS_TXCHAIN; + desc_p->dmamac_cntl = 0; + desc_p->txrx_status &= ~(DESC_TXSTS_MSK | DESC_TXSTS_OWNBYDMA); +#else + desc_p->dmamac_cntl = DESC_TXCTRL_TXCHAIN; + desc_p->txrx_status = 0; +#endif + } + + /* Correcting the last pointer of the chain */ + desc_p->dmamac_next = &desc_table_p[0]; + + writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); +} + +static void rx_descs_init(struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_dma_regs *dma_p = priv->dma_regs_p; + struct dmamacdescr *desc_table_p = &priv->rx_mac_descrtable[0]; + char *rxbuffs = &priv->rxbuffs[0]; + struct dmamacdescr *desc_p; + u32 idx; + + for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { + desc_p = &desc_table_p[idx]; + desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE]; + desc_p->dmamac_next = &desc_table_p[idx + 1]; + + desc_p->dmamac_cntl = + (MAC_MAX_FRAME_SZ & DESC_RXCTRL_SIZE1MASK) | \ + DESC_RXCTRL_RXCHAIN; + + dma_inv_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + CONFIG_ETH_BUFSIZE); + desc_p->txrx_status = DESC_RXSTS_OWNBYDMA; + } + + /* Correcting the last pointer of the chain */ + desc_p->dmamac_next = &desc_table_p[0]; + + writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); +} + +static void descs_init(struct eth_device *dev) +{ + tx_descs_init(dev); + rx_descs_init(dev); +} + +static int dwc_ether_init(struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + struct eth_dma_regs *dma_p = priv->dma_regs_p; + + if (mac_reset(dev) < 0) + return -1; + + /* HW MAC address is lost during MAC reset */ + dev->set_ethaddr(dev, priv->macaddr); + + writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode); + writel(FLUSHTXFIFO | readl(&dma_p->opmode), &dma_p->opmode); + writel(STOREFORWARD | TXSECONDFRAME, &dma_p->opmode); + writel(FRAMEBURSTENABLE | DISABLERXOWN, &mac_p->conf); + return 0; +} + +static int dwc_ether_open(struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + struct eth_dma_regs *dma_p = priv->dma_regs_p; + u32 conf; + int link, speed; + + miidev_wait_aneg(&priv->miidev); + miidev_print_status(&priv->miidev); + link = miidev_get_status(&priv->miidev); + + if (priv->fix_mac_speed) { + speed = link & MIIDEV_STATUS_IS_1000MBIT ? 1000 : + (link & MIIDEV_STATUS_IS_100MBIT ? 100 : 10); + priv->fix_mac_speed(speed); + } + + conf = readl(&mac_p->conf); + if (link & MIIDEV_STATUS_IS_FULL_DUPLEX) + conf |= FULLDPLXMODE; + else + conf &= ~FULLDPLXMODE; + if (link & MIIDEV_STATUS_IS_1000MBIT) + conf &= ~MII_PORTSELECT; + else + conf |= MII_PORTSELECT; + writel(conf, &mac_p->conf); + + descs_init(dev); + + /* + * Start/Enable xfer at dma as well as mac level + */ + writel(readl(&dma_p->opmode) | RXSTART, &dma_p->opmode); + writel(readl(&dma_p->opmode) | TXSTART, &dma_p->opmode); + writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf); + return 0; +} + +static int dwc_ether_send(struct eth_device *dev, void *packet, int length) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_dma_regs *dma_p = priv->dma_regs_p; + u32 desc_num = priv->tx_currdescnum; + struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num]; + + /* Check if the descriptor is owned by CPU */ + if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) { + dev_err(&dev->dev, "CPU not owner of tx frame\n"); + return -1; + } + + memcpy((void *)desc_p->dmamac_addr, packet, length); + dma_flush_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + length); + +#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) + desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST; + desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \ + DESC_TXCTRL_SIZE1MASK; + + desc_p->txrx_status &= ~(DESC_TXSTS_MSK); + desc_p->txrx_status |= DESC_TXSTS_OWNBYDMA; +#else + desc_p->dmamac_cntl |= ((length << DESC_TXCTRL_SIZE1SHFT) & \ + DESC_TXCTRL_SIZE1MASK) | DESC_TXCTRL_TXLAST | \ + DESC_TXCTRL_TXFIRST; + + desc_p->txrx_status = DESC_TXSTS_OWNBYDMA; +#endif + + /* Test the wrap-around condition. */ + if (++desc_num >= CONFIG_TX_DESCR_NUM) + desc_num = 0; + + priv->tx_currdescnum = desc_num; + + /* Start the transmission */ + writel(POLL_DATA, &dma_p->txpolldemand); + return 0; +} + +static int dwc_ether_rx(struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + u32 desc_num = priv->rx_currdescnum; + struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; + + u32 status = desc_p->txrx_status; + int length = 0; + + /* Check if the owner is the CPU */ + if (status & DESC_RXSTS_OWNBYDMA) + return 0; + + length = (status & DESC_RXSTS_FRMLENMSK) >> \ + DESC_RXSTS_FRMLENSHFT; + + net_receive(desc_p->dmamac_addr, length); + + /* + * Make the current descriptor valid again and go to + * the next one + */ + dma_inv_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + length); + desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; + + /* Test the wrap-around condition. */ + if (++desc_num >= CONFIG_RX_DESCR_NUM) + desc_num = 0; + + priv->rx_currdescnum = desc_num; + + return length; +} + +static void dwc_ether_halt (struct eth_device *dev) +{ + struct dw_eth_dev *priv = dev->priv; + + mac_reset(dev); + priv->tx_currdescnum = priv->rx_currdescnum = 0; +} + +static int dwc_ether_get_ethaddr(struct eth_device *dev, u8 adr[6]) +{ + /* we have no EEPROM */ + return -1; +} + +static int dwc_ether_set_ethaddr(struct eth_device *dev, u8 adr[6]) +{ + struct dw_eth_dev *priv = dev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + u32 macid_lo, macid_hi; + + macid_lo = adr[0] + (adr[1] << 8) + \ + (adr[2] << 16) + (adr[3] << 24); + macid_hi = adr[4] + (adr[5] << 8); + writel(macid_hi, &mac_p->macaddr0hi); + writel(macid_lo, &mac_p->macaddr0lo); + memcpy(priv->macaddr, adr, 6); + return 0; +} + +static int dwc_ether_probe(struct device_d *dev) +{ + struct dw_eth_dev *priv; + struct eth_device *edev; + struct mii_device *miidev; + void __iomem *base; + struct dwc_ether_platform_data *pdata = dev->platform_data; + + if (!pdata) { + printf("dwc_ether: no platform_data\n"); + return -ENODEV; + } + + priv = xzalloc(sizeof(struct dw_eth_dev)); + + base = dev_request_mem_region(dev, 0); + priv->mac_regs_p = base; + dev_info(dev, "MAC version %08x\n", readl(&priv->mac_regs_p->version)); + priv->dma_regs_p = base + DW_DMA_BASE_OFFSET; + priv->tx_mac_descrtable = dma_alloc_coherent( + CONFIG_TX_DESCR_NUM * sizeof(struct dmamacdescr)); + priv->rx_mac_descrtable = dma_alloc_coherent( + CONFIG_RX_DESCR_NUM * sizeof(struct dmamacdescr)); + priv->txbuffs = malloc(TX_TOTAL_BUFSIZE); + priv->rxbuffs = malloc(RX_TOTAL_BUFSIZE); + priv->fix_mac_speed = pdata->fix_mac_speed; + + edev = &priv->netdev; + miidev = &priv->miidev; + edev->priv = priv; + + edev->init = dwc_ether_init; + edev->open = dwc_ether_open; + edev->send = dwc_ether_send; + edev->recv = dwc_ether_rx; + edev->halt = dwc_ether_halt; + edev->get_ethaddr = dwc_ether_get_ethaddr; + edev->set_ethaddr = dwc_ether_set_ethaddr; + + miidev->address = pdata->phy_addr; + miidev->read = dwc_ether_mii_read; + miidev->write = dwc_ether_mii_write; + miidev->edev = edev; + + mii_register(miidev); + eth_register(edev); + return 0; +} + +static void dwc_ether_remove(struct device_d *dev) +{ +} + +static struct driver_d dwc_ether_driver = { + .name = "designware_eth", + .probe = dwc_ether_probe, + .remove = dwc_ether_remove, +}; + +static int dwc_ether_driver_init(void) +{ + register_driver(&dwc_ether_driver); + return 0; +} +device_initcall(dwc_ether_driver_init); diff --git a/drivers/net/designware.h b/drivers/net/designware.h new file mode 100644 index 0000000000..db2ead48aa --- /dev/null +++ b/drivers/net/designware.h @@ -0,0 +1,230 @@ +/* + * (C) Copyright 2010 + * Vipin Kumar, ST Micoelectronics, vipin.kumar@st.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __DESIGNWARE_ETH_H +#define __DESIGNWARE_ETH_H + +#define CONFIG_TX_DESCR_NUM 16 +#define CONFIG_RX_DESCR_NUM 16 +#define CONFIG_ETH_BUFSIZE 2048 +#define TX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_TX_DESCR_NUM) +#define RX_TOTAL_BUFSIZE (CONFIG_ETH_BUFSIZE * CONFIG_RX_DESCR_NUM) + +struct eth_mac_regs { + u32 conf; /* 0x00 */ + u32 framefilt; /* 0x04 */ + u32 hashtablehigh; /* 0x08 */ + u32 hashtablelow; /* 0x0c */ + u32 miiaddr; /* 0x10 */ + u32 miidata; /* 0x14 */ + u32 flowcontrol; /* 0x18 */ + u32 vlantag; /* 0x1c */ + u32 version; /* 0x20 */ + u8 reserved_1[20]; + u32 intreg; /* 0x38 */ + u32 intmask; /* 0x3c */ + u32 macaddr0hi; /* 0x40 */ + u32 macaddr0lo; /* 0x44 */ +}; + +/* MAC configuration register definitions */ +#define FRAMEBURSTENABLE (1 << 21) +#define MII_PORTSELECT (1 << 15) +#define FES_100 (1 << 14) +#define DISABLERXOWN (1 << 13) +#define FULLDPLXMODE (1 << 11) +#define RXENABLE (1 << 2) +#define TXENABLE (1 << 3) + +/* MII address register definitions */ +#define MII_BUSY (1 << 0) +#define MII_WRITE (1 << 1) +#define MII_CLKRANGE_60_100M (0) +#define MII_CLKRANGE_100_150M (0x4) +#define MII_CLKRANGE_20_35M (0x8) +#define MII_CLKRANGE_35_60M (0xC) +#define MII_CLKRANGE_150_250M (0x10) +#define MII_CLKRANGE_250_300M (0x14) + +#define MIIADDRSHIFT (11) +#define MIIREGSHIFT (6) +#define MII_REGMSK (0x1F << 6) +#define MII_ADDRMSK (0x1F << 11) + + +struct eth_dma_regs { + u32 busmode; /* 0x00 */ + u32 txpolldemand; /* 0x04 */ + u32 rxpolldemand; /* 0x08 */ + u32 rxdesclistaddr; /* 0x0c */ + u32 txdesclistaddr; /* 0x10 */ + u32 status; /* 0x14 */ + u32 opmode; /* 0x18 */ + u32 intenable; /* 0x1c */ + u8 reserved[40]; + u32 currhosttxdesc; /* 0x48 */ + u32 currhostrxdesc; /* 0x4c */ + u32 currhosttxbuffaddr; /* 0x50 */ + u32 currhostrxbuffaddr; /* 0x54 */ +}; + +#define DW_DMA_BASE_OFFSET (0x1000) + +/* Bus mode register definitions */ +#define FIXEDBURST (1 << 16) +#define PRIORXTX_41 (3 << 14) +#define PRIORXTX_31 (2 << 14) +#define PRIORXTX_21 (1 << 14) +#define PRIORXTX_11 (0 << 14) +#define BURST_1 (1 << 8) +#define BURST_2 (2 << 8) +#define BURST_4 (4 << 8) +#define BURST_8 (8 << 8) +#define BURST_16 (16 << 8) +#define BURST_32 (32 << 8) +#define RXHIGHPRIO (1 << 1) +#define DMAMAC_SRST (1 << 0) + +/* Poll demand definitions */ +#define POLL_DATA (0xFFFFFFFF) + +/* Operation mode definitions */ +#define STOREFORWARD (1 << 21) +#define FLUSHTXFIFO (1 << 20) +#define TXSTART (1 << 13) +#define TXSECONDFRAME (1 << 2) +#define RXSTART (1 << 1) + +/* Descriptior related definitions */ +#define MAC_MAX_FRAME_SZ (1600) + +struct dmamacdescr { + u32 txrx_status; + u32 dmamac_cntl; + void *dmamac_addr; + struct dmamacdescr *dmamac_next; +}; + +/* + * txrx_status definitions + */ + +/* tx status bits definitions */ +#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) + +#define DESC_TXSTS_OWNBYDMA (1 << 31) +#define DESC_TXSTS_TXINT (1 << 30) +#define DESC_TXSTS_TXLAST (1 << 29) +#define DESC_TXSTS_TXFIRST (1 << 28) +#define DESC_TXSTS_TXCRCDIS (1 << 27) + +#define DESC_TXSTS_TXPADDIS (1 << 26) +#define DESC_TXSTS_TXCHECKINSCTRL (3 << 22) +#define DESC_TXSTS_TXRINGEND (1 << 21) +#define DESC_TXSTS_TXCHAIN (1 << 20) +#define DESC_TXSTS_MSK (0x1FFFF << 0) + +#else + +#define DESC_TXSTS_OWNBYDMA (1 << 31) +#define DESC_TXSTS_MSK (0x1FFFF << 0) + +#endif + +/* rx status bits definitions */ +#define DESC_RXSTS_OWNBYDMA (1 << 31) +#define DESC_RXSTS_DAFILTERFAIL (1 << 30) +#define DESC_RXSTS_FRMLENMSK (0x3FFF << 16) +#define DESC_RXSTS_FRMLENSHFT (16) + +#define DESC_RXSTS_ERROR (1 << 15) +#define DESC_RXSTS_RXTRUNCATED (1 << 14) +#define DESC_RXSTS_SAFILTERFAIL (1 << 13) +#define DESC_RXSTS_RXIPC_GIANTFRAME (1 << 12) +#define DESC_RXSTS_RXDAMAGED (1 << 11) +#define DESC_RXSTS_RXVLANTAG (1 << 10) +#define DESC_RXSTS_RXFIRST (1 << 9) +#define DESC_RXSTS_RXLAST (1 << 8) +#define DESC_RXSTS_RXIPC_GIANT (1 << 7) +#define DESC_RXSTS_RXCOLLISION (1 << 6) +#define DESC_RXSTS_RXFRAMEETHER (1 << 5) +#define DESC_RXSTS_RXWATCHDOG (1 << 4) +#define DESC_RXSTS_RXMIIERROR (1 << 3) +#define DESC_RXSTS_RXDRIBBLING (1 << 2) +#define DESC_RXSTS_RXCRC (1 << 1) + +/* + * dmamac_cntl definitions + */ + +/* tx control bits definitions */ +#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) + +#define DESC_TXCTRL_SIZE1MASK (0x1FFF << 0) +#define DESC_TXCTRL_SIZE1SHFT (0) +#define DESC_TXCTRL_SIZE2MASK (0x1FFF << 16) +#define DESC_TXCTRL_SIZE2SHFT (16) + +#else + +#define DESC_TXCTRL_TXINT (1 << 31) +#define DESC_TXCTRL_TXLAST (1 << 30) +#define DESC_TXCTRL_TXFIRST (1 << 29) +#define DESC_TXCTRL_TXCHECKINSCTRL (3 << 27) +#define DESC_TXCTRL_TXCRCDIS (1 << 26) +#define DESC_TXCTRL_TXRINGEND (1 << 25) +#define DESC_TXCTRL_TXCHAIN (1 << 24) + +#define DESC_TXCTRL_SIZE1MASK (0x7FF << 0) +#define DESC_TXCTRL_SIZE1SHFT (0) +#define DESC_TXCTRL_SIZE2MASK (0x7FF << 11) +#define DESC_TXCTRL_SIZE2SHFT (11) + +#endif + +/* rx control bits definitions */ +#if defined(CONFIG_DRIVER_NET_DESIGNWARE_ALTDESCRIPTOR) + +#define DESC_RXCTRL_RXINTDIS (1 << 31) +#define DESC_RXCTRL_RXRINGEND (1 << 15) +#define DESC_RXCTRL_RXCHAIN (1 << 14) + +#define DESC_RXCTRL_SIZE1MASK (0x1FFF << 0) +#define DESC_RXCTRL_SIZE1SHFT (0) +#define DESC_RXCTRL_SIZE2MASK (0x1FFF << 16) +#define DESC_RXCTRL_SIZE2SHFT (16) + +#else + +#define DESC_RXCTRL_RXINTDIS (1 << 31) +#define DESC_RXCTRL_RXRINGEND (1 << 25) +#define DESC_RXCTRL_RXCHAIN (1 << 24) + +#define DESC_RXCTRL_SIZE1MASK (0x7FF << 0) +#define DESC_RXCTRL_SIZE1SHFT (0) +#define DESC_RXCTRL_SIZE2MASK (0x7FF << 11) +#define DESC_RXCTRL_SIZE2SHFT (11) + +#endif + +#endif diff --git a/drivers/net/miidev.c b/drivers/net/miidev.c index f47fc9e65b..b49944bbfe 100644 --- a/drivers/net/miidev.c +++ b/drivers/net/miidev.c @@ -123,7 +123,7 @@ int miidev_wait_aneg(struct mii_device *mdev) int miidev_get_status(struct mii_device *mdev) { - int ret, status; + int ret, status, adv, lpa; ret = mii_read(mdev, mdev->address, MII_BMSR); if (ret < 0) @@ -136,13 +136,31 @@ int miidev_get_status(struct mii_device *mdev) goto err_out; if (ret & BMCR_ANENABLE) { - ret = mii_read(mdev, mdev->address, MII_LPA); - if (ret < 0) + if (mdev->capabilities & MIIDEV_CAPABLE_1000M) { + lpa = mii_read(mdev, mdev->address, MII_STAT1000); + if (lpa < 0) + goto err_out; + adv = mii_read(mdev, mdev->address, MII_CTRL1000); + if (adv < 0) + goto err_out; + lpa &= adv << 2; + if (lpa & (LPA_1000FULL | LPA_1000HALF)) { + if (lpa & LPA_1000FULL) + status |= MIIDEV_STATUS_IS_FULL_DUPLEX; + status |= MIIDEV_STATUS_IS_1000MBIT; + return status; + } + } + lpa = mii_read(mdev, mdev->address, MII_LPA); + if (lpa < 0) goto err_out; - - status |= ret & LPA_DUPLEX ? MIIDEV_STATUS_IS_FULL_DUPLEX : 0; - status |= ret & LPA_100 ? MIIDEV_STATUS_IS_100MBIT : - MIIDEV_STATUS_IS_10MBIT; + adv = mii_read(mdev, mdev->address, MII_ADVERTISE); + if (adv < 0) + goto err_out; + lpa &= adv; + status |= lpa & LPA_DUPLEX ? MIIDEV_STATUS_IS_FULL_DUPLEX : 0; + status |= lpa & LPA_100 ? MIIDEV_STATUS_IS_100MBIT : + MIIDEV_STATUS_IS_10MBIT; } else { status |= ret & BMCR_FULLDPLX ? MIIDEV_STATUS_IS_FULL_DUPLEX : 0; status |= ret & BMCR_SPEED100 ? MIIDEV_STATUS_IS_100MBIT : @@ -170,8 +188,8 @@ int miidev_print_status(struct mii_device *mdev) return status; duplex = status & MIIDEV_STATUS_IS_FULL_DUPLEX ? "Full" : "Half"; - speed = status & MIIDEV_STATUS_IS_100MBIT ? 100 : 10; - + speed = status & MIIDEV_STATUS_IS_1000MBIT ? 1000 : + (status & MIIDEV_STATUS_IS_100MBIT ? 100 : 10); printf("%s: Link is %s", mdev->cdev.name, status & MIIDEV_STATUS_IS_UP ? "up" : "down"); @@ -180,33 +198,33 @@ int miidev_print_status(struct mii_device *mdev) return 0; } -static ssize_t miidev_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t miidev_read(struct cdev *cdev, void *_buf, size_t count, loff_t offset, ulong flags) { int i = count; uint16_t *buf = _buf; struct mii_device *mdev = cdev->priv; - while (i > 1) { - *buf = mii_read(mdev, mdev->address, offset); + while (i > 0) { + *buf = mii_read(mdev, mdev->address, offset / 2); buf++; i -= 2; - offset++; + offset += 2; } return count; } -static ssize_t miidev_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags) +static ssize_t miidev_write(struct cdev *cdev, const void *_buf, size_t count, loff_t offset, ulong flags) { int i = count; const uint16_t *buf = _buf; struct mii_device *mdev = cdev->priv; - while (i > 1) { - mii_write(mdev, mdev->address, offset, *buf); + while (i > 0) { + mii_write(mdev, mdev->address, offset / 2, *buf); buf++; i -= 2; - offset++; + offset += 2; } return count; @@ -221,7 +239,27 @@ static struct file_operations miidev_ops = { static int miidev_probe(struct device_d *dev) { struct mii_device *mdev = dev->priv; + int val; + int caps = 0; + val = mii_read(mdev, mdev->address, MII_PHYSID1); + if (val < 0 || val == 0xffff) + goto err_out; + val = mii_read(mdev, mdev->address, MII_PHYSID2); + if (val < 0 || val == 0xffff) + goto err_out; + val = mii_read(mdev, mdev->address, MII_BMSR); + if (val < 0) + goto err_out; + if (val & BMSR_ESTATEN) { + val = mii_read(mdev, mdev->address, MII_ESTATUS); + if (val < 0) + goto err_out; + if (val & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) + caps = MIIDEV_CAPABLE_1000M; + } + + mdev->capabilities = caps; mdev->cdev.name = asprintf("phy%d", dev->id); mdev->cdev.size = 64; mdev->cdev.ops = &miidev_ops; @@ -230,6 +268,10 @@ static int miidev_probe(struct device_d *dev) devfs_create(&mdev->cdev); list_add_tail(&mdev->list, &miidev_list); return 0; + +err_out: + dev_err(dev, "cannot read PHY registers (addr %d)\n", mdev->address); + return -ENODEV; } static void miidev_remove(struct device_d *dev) diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 800c1886ce..7dddbbcc38 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -691,7 +691,7 @@ static int smc911x_probe(struct device_d *dev) struct smc911x_priv *priv; uint32_t val; int i; - void *base; + void __iomem *base; base = dev_request_mem_region(dev, 0); diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c index 654e6470c1..16885c0af9 100644 --- a/drivers/nor/cfi_flash.c +++ b/drivers/nor/cfi_flash.c @@ -82,9 +82,9 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c) return; } -#if __BYTE_ORDER == __BIG_ENDIAN +#ifdef __BIG_ENDIAN *cword = (*cword << 8) | c; -#else +#elif defined __LITTLE_ENDIAN if (bankwidth_is_2(info)) *cword = (*cword >> 8) | (u16)c << 8; @@ -92,6 +92,8 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c) *cword = (*cword >> 8) | (u32)c << 24; else if (bankwidth_is_8(info)) *cword = (*cword >> 8) | (u64)c << 56; +#else +#error "could not determine byte order" #endif } @@ -167,7 +169,7 @@ static void flash_printqry (struct cfi_qry *qry) uchar flash_read_uchar (struct flash_info *info, uint offset) { uchar *cp = flash_make_addr(info, 0, offset); -#if __BYTE_ORDER == __LITTLE_ENDIAN +#if defined __LITTLE_ENDIAN return flash_read8(cp); #else return flash_read8(cp + info->portwidth - 1); @@ -195,7 +197,7 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o debug ("addr[%x] = 0x%x\n", x, flash_read8(addr + x)); } #endif -#if __BYTE_ORDER == __LITTLE_ENDIAN +#if defined __LITTLE_ENDIAN retval = ((flash_read8(addr) << 16) | (flash_read8(addr + info->portwidth) << 24) | (flash_read8(addr + 2 * info->portwidth)) | @@ -456,7 +458,7 @@ flash_sect_t find_sector (struct flash_info *info, ulong addr) return sector; } -static int __cfi_erase(struct cdev *cdev, size_t count, unsigned long offset, +static int __cfi_erase(struct cdev *cdev, size_t count, loff_t offset, int verbose) { struct flash_info *finfo = (struct flash_info *)cdev->priv; @@ -491,7 +493,7 @@ out: return ret; } -static int cfi_erase(struct cdev *cdev, size_t count, unsigned long offset) +static int cfi_erase(struct cdev *cdev, size_t count, loff_t offset) { return __cfi_erase(cdev, count, offset, 1); } @@ -628,7 +630,7 @@ static int flash_real_protect (struct flash_info *info, long sector, int prot) return retcode; } -static int cfi_protect(struct cdev *cdev, size_t count, unsigned long offset, int prot) +static int cfi_protect(struct cdev *cdev, size_t count, loff_t offset, int prot) { struct flash_info *finfo = (struct flash_info *)cdev->priv; unsigned long start, end; @@ -651,7 +653,7 @@ out: return ret; } -static ssize_t cfi_write(struct cdev *cdev, const void *buf, size_t count, unsigned long offset, ulong flags) +static ssize_t cfi_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, ulong flags) { struct flash_info *finfo = (struct flash_info *)cdev->priv; int ret; diff --git a/drivers/nor/m25p80.c b/drivers/nor/m25p80.c index 77669c2808..14402270bc 100644 --- a/drivers/nor/m25p80.c +++ b/drivers/nor/m25p80.c @@ -194,13 +194,14 @@ static int erase_sector(struct m25p *flash, u32 offset) * Erase an address range on the flash chip. The address range may extend * one or more erase sectors. Return an error is there is a problem erasing. */ -static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offset) +static ssize_t m25p80_erase(struct cdev *cdev, size_t count, loff_t offset) { struct m25p *flash = cdev->priv; u32 addr, len; u32 start_sector; u32 end_sector; u32 progress = 0; + int eraseshift = ffs(flash->erasesize) - 1; dev_dbg(&flash->spi->dev, "%s %s 0x%llx, len %lld\n", __func__, "at", (long long)offset, (long long)count); @@ -212,8 +213,8 @@ static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offse addr = offset; len = count; - start_sector = offset / flash->erasesize; - end_sector = (offset + count - 1) / flash->erasesize; + start_sector = offset >> eraseshift; + end_sector = (offset + count - 1) >> eraseshift; init_progression_bar(end_sector - start_sector + 1); /* whole-chip erase? */ @@ -250,7 +251,8 @@ static ssize_t m25p80_erase(struct cdev *cdev, size_t count, unsigned long offse return 0; } -ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags) +ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, + ulong flags) { struct m25p *flash = cdev->priv; struct spi_transfer t[2]; @@ -302,7 +304,8 @@ ssize_t m25p80_read(struct cdev *cdev, void *buf, size_t count, ulong offset, ul return retlen; } -ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) +ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, + loff_t offset, ulong flags) { struct m25p *flash = cdev->priv; struct spi_transfer t[2]; @@ -381,7 +384,8 @@ ssize_t m25p80_write(struct cdev *cdev, const void *buf, size_t count, ulong off return retlen; } #ifdef CONFIG_MTD_SST25L -ssize_t sst_write(struct cdev *cdev, const void *buf, size_t count, ulong offset, ulong flags) +ssize_t sst_write(struct cdev *cdev, const void *buf, size_t count, loff_t offset, + ulong flags) { struct m25p *flash = cdev->priv; struct spi_transfer t[2]; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index bd2938d2b7..a5075d5436 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -52,6 +52,7 @@ #include <asm/byteorder.h> #include <xfuncs.h> #include <init.h> +#include <dma.h> #include <usb/usb.h> @@ -67,7 +68,6 @@ static int dev_index; static int asynch_allowed; -static struct devrequest setup_packet; static int usb_hub_probe(struct usb_device *dev, int ifnum); static int hub_port_reset(struct usb_device *dev, int port, @@ -80,8 +80,8 @@ static void print_usb_device(struct usb_device *dev) { printf("Bus %03d Device %03d: ID %04x:%04x %s\n", dev->host->busnum, dev->devnum, - dev->descriptor.idVendor, - dev->descriptor.idProduct, + dev->descriptor->idVendor, + dev->descriptor->idProduct, dev->prod); } @@ -299,12 +299,14 @@ static int usb_new_device(struct usb_device *dev) { int addr, err; int tmp; - unsigned char tmpbuf[USB_BUFSIZ]; + void *buf; struct usb_device_descriptor *desc; int port = -1; struct usb_device *parent = dev->parent; unsigned short portstatus; + buf = dma_alloc(USB_BUFSIZ); + /* We still haven't set the Address yet */ addr = dev->devnum; dev->devnum = 0; @@ -322,8 +324,8 @@ static int usb_new_device(struct usb_device *dev) * the maxpacket size is 8 or 16 the device may be waiting to transmit * some more, or keeps on retransmitting the 8 byte header. */ - desc = (struct usb_device_descriptor *)tmpbuf; - dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ + desc = buf; + dev->descriptor->bMaxPacketSize0 = 64; /* Start off at 64 bytes */ /* Default to 64 byte max packet size */ dev->maxpacketsize = PACKET_SIZE_64; dev->epmaxpacketin[0] = 64; @@ -332,10 +334,10 @@ static int usb_new_device(struct usb_device *dev) err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); if (err < 0) { USB_PRINTF("%s: usb_get_descriptor() failed with %d\n", __func__, err); - return 1; + goto err_out; } - dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; + dev->descriptor->bMaxPacketSize0 = desc->bMaxPacketSize0; /* find the port number we're at */ if (parent) { @@ -349,20 +351,21 @@ static int usb_new_device(struct usb_device *dev) } if (port < 0) { printf("%s: cannot locate device's port.\n", __func__); - return 1; + err = -ENODEV; + goto err_out; } /* reset the port for the second time */ err = hub_port_reset(dev->parent, port, &portstatus); if (err < 0) { printf("\n Couldn't reset port %i\n", port); - return 1; + goto err_out; } } - dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; - dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; - switch (dev->descriptor.bMaxPacketSize0) { + dev->epmaxpacketin[0] = dev->descriptor->bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor->bMaxPacketSize0; + switch (dev->descriptor->bMaxPacketSize0) { case 8: dev->maxpacketsize = PACKET_SIZE_8; break; @@ -383,15 +386,15 @@ static int usb_new_device(struct usb_device *dev) if (err < 0) { printf("\n USB device not accepting new address " \ "(error=%lX)\n", dev->status); - return 1; + goto err_out; } wait_ms(10); /* Let the SET_ADDRESS settle */ - tmp = sizeof(dev->descriptor); + tmp = sizeof(*dev->descriptor); err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, - &dev->descriptor, sizeof(dev->descriptor)); + dev->descriptor, sizeof(*dev->descriptor)); if (err < tmp) { if (err < 0) printf("unable to get device descriptor (error=%d)\n", @@ -399,37 +402,37 @@ static int usb_new_device(struct usb_device *dev) else printf("USB device descriptor short read " \ "(expected %i, got %i)\n", tmp, err); - return 1; + goto err_out; } /* correct le values */ - le16_to_cpus(&dev->descriptor.bcdUSB); - le16_to_cpus(&dev->descriptor.idVendor); - le16_to_cpus(&dev->descriptor.idProduct); - le16_to_cpus(&dev->descriptor.bcdDevice); + le16_to_cpus(&dev->descriptor->bcdUSB); + le16_to_cpus(&dev->descriptor->idVendor); + le16_to_cpus(&dev->descriptor->idProduct); + le16_to_cpus(&dev->descriptor->bcdDevice); /* only support for one config for now */ - usb_get_configuration_no(dev, &tmpbuf[0], 0); - usb_parse_config(dev, &tmpbuf[0], 0); + usb_get_configuration_no(dev, buf, 0); + usb_parse_config(dev, buf, 0); usb_set_maxpacket(dev); /* we set the default configuration here */ if (usb_set_configuration(dev, dev->config.bConfigurationValue)) { printf("failed to set default configuration " \ "len %d, status %lX\n", dev->act_len, dev->status); - return -1; + goto err_out; } USB_PRINTF("new device: Mfr=%d, Product=%d, SerialNumber=%d\n", - dev->descriptor.iManufacturer, dev->descriptor.iProduct, - dev->descriptor.iSerialNumber); + dev->descriptor->iManufacturer, dev->descriptor->iProduct, + dev->descriptor->iSerialNumber); memset(dev->mf, 0, sizeof(dev->mf)); memset(dev->prod, 0, sizeof(dev->prod)); memset(dev->serial, 0, sizeof(dev->serial)); - if (dev->descriptor.iManufacturer) - usb_string(dev, dev->descriptor.iManufacturer, + if (dev->descriptor->iManufacturer) + usb_string(dev, dev->descriptor->iManufacturer, dev->mf, sizeof(dev->mf)); - if (dev->descriptor.iProduct) - usb_string(dev, dev->descriptor.iProduct, + if (dev->descriptor->iProduct) + usb_string(dev, dev->descriptor->iProduct, dev->prod, sizeof(dev->prod)); - if (dev->descriptor.iSerialNumber) - usb_string(dev, dev->descriptor.iSerialNumber, + if (dev->descriptor->iSerialNumber) + usb_string(dev, dev->descriptor->iSerialNumber, dev->serial, sizeof(dev->serial)); /* now prode if the device is a hub */ usb_hub_probe(dev, 0); @@ -441,7 +444,11 @@ static int usb_new_device(struct usb_device *dev) register_device(&dev->dev); list_add_tail(&dev->list, &usb_device_list); - return 0; + err = 0; + +err_out: + dma_free(buf); + return err; } static struct usb_device *usb_alloc_new_device(void) @@ -454,6 +461,8 @@ static struct usb_device *usb_alloc_new_device(void) usbdev->devnum = dev_index + 1; usbdev->maxchild = 0; usbdev->dev.bus = &usb_bus_type; + usbdev->setup_packet = dma_alloc(sizeof(*usbdev->setup_packet)); + usbdev->descriptor = dma_alloc(sizeof(*usbdev->descriptor)); dev_index++; @@ -471,6 +480,8 @@ void usb_rescan(void) unregister_device(&dev->dev); if (dev->hub) free(dev->hub); + dma_free(dev->setup_packet); + dma_free(dev->descriptor); free(dev); } @@ -532,6 +543,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, { struct usb_host *host = dev->host; int ret; + struct devrequest *setup_packet = dev->setup_packet; if ((timeout == 0) && (!asynch_allowed)) { /* request for a asynch control pipe is not allowed */ @@ -539,17 +551,18 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, } /* set setup command */ - setup_packet.requesttype = requesttype; - setup_packet.request = request; - setup_packet.value = cpu_to_le16(value); - setup_packet.index = cpu_to_le16(index); - setup_packet.length = cpu_to_le16(size); + setup_packet->requesttype = requesttype; + setup_packet->request = request; + setup_packet->value = cpu_to_le16(value); + setup_packet->index = cpu_to_le16(index); + setup_packet->length = cpu_to_le16(size); USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \ "value 0x%X index 0x%X length 0x%X\n", request, requesttype, value, index, size); dev->status = USB_ST_NOT_PROC; /*not yet processed */ - ret = host->submit_control_msg(dev, pipe, data, size, &setup_packet, timeout); + ret = host->submit_control_msg(dev, pipe, data, size, setup_packet, + timeout); if (ret) return ret; @@ -1284,11 +1297,11 @@ int usb_driver_register(struct usb_driver *drv) static int usb_match_device(struct usb_device *dev, const struct usb_device_id *id) { if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && - id->idVendor != le16_to_cpu(dev->descriptor.idVendor)) + id->idVendor != le16_to_cpu(dev->descriptor->idVendor)) return 0; if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) && - id->idProduct != le16_to_cpu(dev->descriptor.idProduct)) + id->idProduct != le16_to_cpu(dev->descriptor->idProduct)) return 0; return 1; @@ -1311,7 +1324,7 @@ static int usb_match_one_id(struct usb_device *usbdev, /* The interface class, subclass, and protocol should never be * checked for a match if the device class is Vendor Specific, * unless the match record specifies the Vendor ID. */ - if (usbdev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && + if (usbdev->descriptor->bDeviceClass == USB_CLASS_VENDOR_SPEC && !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && (id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO)) return 0; @@ -1371,7 +1384,8 @@ static int usb_match(struct device_d *dev, struct driver_d *drv) struct usb_driver *usbdrv = container_of(dev->driver, struct usb_driver, driver); const struct usb_device_id *id; - debug("matching: 0x%04x 0x%04x\n", usbdev->descriptor.idVendor, usbdev->descriptor.idProduct); + debug("matching: 0x%04x 0x%04x\n", usbdev->descriptor->idVendor, + usbdev->descriptor->idProduct); id = usb_match_id(usbdev, usbdrv->id_table); if (id) { diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index fd70e623a6..44e58d7de0 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -22,6 +22,7 @@ #include <common.h> #include <errno.h> +#include <dma.h> #include <usb/composite.h> #include <asm/byteorder.h> @@ -867,7 +868,7 @@ composite_unbind(struct usb_gadget *gadget) composite->unbind(cdev); if (cdev->req) { - kfree(cdev->req->buf); + dma_free(cdev->req->buf); usb_ep_free_request(gadget->ep0, cdev->req); } kfree(cdev); @@ -911,7 +912,7 @@ static int __init composite_bind(struct usb_gadget *gadget) cdev->req = usb_ep_alloc_request(gadget->ep0); if (!cdev->req) goto fail; - cdev->req->buf = malloc(USB_BUFSIZ); + cdev->req->buf = dma_alloc(USB_BUFSIZ); if (!cdev->req->buf) goto fail; cdev->req->complete = composite_setup_complete; diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c index f26c1e43d0..e205c65f32 100644 --- a/drivers/usb/gadget/dfu.c +++ b/drivers/usb/gadget/dfu.c @@ -40,6 +40,7 @@ * - make 'dnstate' attached to 'struct usb_device_instance' */ +#include <dma.h> #include <asm/byteorder.h> #include <usb/composite.h> #include <linux/types.h> @@ -183,7 +184,7 @@ dfu_unbind(struct usb_configuration *c, struct usb_function *f) if (gadget_is_dualspeed(c->cdev->gadget)) free(f->hs_descriptors); - free(dfu->dnreq->buf); + dma_free(dfu->dnreq->buf); usb_ep_free_request(c->cdev->gadget->ep0, dfu->dnreq); free(dfu); } @@ -602,7 +603,7 @@ static int dfu_bind_config(struct usb_configuration *c) dfu->dnreq = usb_ep_alloc_request(c->cdev->gadget->ep0); if (!dfu->dnreq) printf("usb_ep_alloc_request failed\n"); - dfu->dnreq->buf = xmalloc(CONFIG_USBD_DFU_XFER_SIZE); + dfu->dnreq->buf = dma_alloc(CONFIG_USBD_DFU_XFER_SIZE); dfu->dnreq->complete = dn_complete; dfu->dnreq->zero = 0; diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 5b64ec2011..5537a0eb97 100644 --- a/drivers/usb/gadget/fsl_udc.c +++ b/drivers/usb/gadget/fsl_udc.c @@ -1,5 +1,6 @@ #include <common.h> #include <errno.h> +#include <dma.h> #include <init.h> #include <clock.h> #include <usb/ch9.h> @@ -8,7 +9,6 @@ #include <io.h> #include <poller.h> #include <asm/byteorder.h> -#include <asm/mmu.h> /* ### define USB registers here */ @@ -519,7 +519,7 @@ static void dump_msg(const char *label, const u8 * buf, unsigned int length) * 2 + ((windex & USB_DIR_IN) ? 1 : 0)) #define get_pipe_by_ep(EP) (ep_index(EP) * 2 + ep_is_in(EP)) -static struct usb_dr_device *dr_regs; +static struct usb_dr_device __iomem *dr_regs; static struct fsl_udc *udc_controller = NULL; static const struct usb_endpoint_descriptor @@ -2109,7 +2109,8 @@ static int struct_udc_setup(struct fsl_udc *udc, udc->status_req = container_of(fsl_alloc_request(NULL), struct fsl_req, req); /* allocate a small amount of memory to get valid address */ - udc->status_req->req.buf = xmalloc(8); + udc->status_req->req.buf = dma_alloc(8); + udc->status_req->req.length = 8; udc->resume_state = USB_STATE_NOTATTACHED; udc->usb_state = USB_STATE_POWERED; udc->ep0_dir = 0; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index a2473a9141..c2f48ce428 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -120,63 +120,6 @@ static struct descriptor { #define ehci_is_TDI() (ehci->flags & EHCI_HAS_TT) -#ifdef CONFIG_MMU -/* - * Routines to handle (flush/invalidate) the dcache for the QH and qTD - * structures and data buffers. This is needed on platforms using this - * EHCI support with dcache enabled. - */ -static void flush_invalidate(void *addr, int size, int flush) -{ - if (flush) { - dma_flush_range((unsigned long)addr, (unsigned long)(addr + size)); - } else { - dma_inv_range((unsigned long)addr, (unsigned long)(addr + size)); - } -} - -static void cache_qtd(struct qTD *qtd, int flush) -{ - u32 *ptr = (u32 *)qtd->qt_buffer[0]; - int len = (qtd->qt_token & 0x7fff0000) >> 16; - - if (ptr && len) - flush_invalidate(ptr, len, flush); -} - -static void cache_qh(struct ehci_priv *ehci, int flush) -{ - int i; - - flush_invalidate(ehci->qh_list, sizeof(struct QH) * NUM_QH, flush); - flush_invalidate(ehci->td, sizeof(struct qTD) * NUM_TD, flush); - - for (i = 0; i < NUM_TD; i ++) - cache_qtd(&ehci->td[i], flush); -} - -static inline void ehci_flush_dcache(struct ehci_priv *ehci) -{ - cache_qh(ehci, 1); -} - -static inline void ehci_invalidate_dcache(struct ehci_priv *ehci) -{ - cache_qh(ehci, 0); -} -#else /* CONFIG_MMU */ -/* - * - */ -static inline void ehci_flush_dcache(struct ehci_priv *ehci) -{ -} - -static inline void ehci_invalidate_dcache(struct ehci_priv *ehci) -{ -} -#endif /* CONFIG_MMU */ - static int handshake(uint32_t *ptr, uint32_t mask, uint32_t done, int usec) { uint32_t result; @@ -231,6 +174,9 @@ static int ehci_td_buffer(struct qTD *td, void *buf, size_t sz) int idx; addr = (uint32_t) buf; + td->qtd_dma = addr; + td->length = sz; + idx = 0; while (idx < 5) { td->qt_buffer[idx] = cpu_to_hc32(addr); @@ -264,7 +210,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t endpt, token, usbsts; uint32_t c, toggle; uint32_t cmd; - int ret = 0; + int ret = 0, i; uint64_t start, timeout_val; debug("dev=%p, pipe=%lx, buffer=%p, length=%d, req=%p\n", dev, pipe, @@ -296,11 +242,11 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, (dev->portnr << 23) | (dev->parent->devnum << 16) | (0 << 8) | (0 << 0); qh->qh_endpt2 = cpu_to_hc32(endpt); - qh->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - qh->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + qh->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); + qh->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); td = NULL; - tdp = &qh->qh_overlay.qt_next; + tdp = &qh->qt_next; toggle = usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe)); @@ -363,7 +309,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci->qh_list->qh_link = cpu_to_hc32((uint32_t) qh | QH_LINK_TYPE_QH); /* Flush dcache */ - ehci_flush_dcache(ehci); + if (IS_ENABLED(CONFIG_MMU)) { + for (i = 0; i < NUM_TD; i ++) { + struct qTD *qtd = &ehci->td[i]; + if (!qtd->qtd_dma) + continue; + dma_flush_range(qtd->qtd_dma, qtd->qtd_dma + qtd->length); + } + } usbsts = ehci_readl(&ehci->hcor->or_usbsts); ehci_writel(&ehci->hcor->or_usbsts, (usbsts & 0x3f)); @@ -384,8 +337,6 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, start = get_time_ns(); vtd = td; do { - /* Invalidate dcache */ - ehci_invalidate_dcache(ehci); token = hc32_to_cpu(vtd->qt_token); if (is_timeout(start, timeout_val)) { /* Disable async schedule. */ @@ -394,11 +345,20 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci_writel(&ehci->hcor->or_usbcmd, cmd); ret = handshake(&ehci->hcor->or_usbsts, STD_ASS, 0, 100 * 1000); - ehci_writel(&qh->qh_overlay.qt_token, 0); + ehci_writel(&qh->qt_token, 0); return -ETIMEDOUT; } } while (token & 0x80); + if (IS_ENABLED(CONFIG_MMU)) { + for (i = 0; i < NUM_TD; i ++) { + struct qTD *qtd = &ehci->td[i]; + if (!qtd->qtd_dma) + continue; + dma_inv_range(qtd->qtd_dma, qtd->qtd_dma + qtd->length); + } + } + /* Disable async schedule. */ cmd = ehci_readl(&ehci->hcor->or_usbcmd); cmd &= ~CMD_ASE; @@ -413,7 +373,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH); - token = hc32_to_cpu(qh->qh_overlay.qt_token); + token = hc32_to_cpu(qh->qt_token); if (!(token & 0x80)) { debug("TOKEN=0x%08x\n", token); switch (token & 0xfc) { @@ -451,10 +411,10 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, fail: printf("fail1\n"); - td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); + td = (void *)hc32_to_cpu(qh->qt_next); while (td != (void *)QT_NEXT_TERMINATE) { - qh->qh_overlay.qt_next = td->qt_next; - td = (void *)hc32_to_cpu(qh->qh_overlay.qt_next); + qh->qt_next = td->qt_next; + td = (void *)hc32_to_cpu(qh->qt_next); } return -1; } @@ -770,9 +730,9 @@ static int ehci_init(struct usb_host *host) ehci->qh_list->qh_link = cpu_to_hc32((uint32_t)ehci->qh_list | QH_LINK_TYPE_QH); ehci->qh_list->qh_endpt1 = cpu_to_hc32((1 << 15) | (USB_SPEED_HIGH << 12)); ehci->qh_list->qh_curtd = cpu_to_hc32(QT_NEXT_TERMINATE); - ehci->qh_list->qh_overlay.qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); - ehci->qh_list->qh_overlay.qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); - ehci->qh_list->qh_overlay.qt_token = cpu_to_hc32(0x40); + ehci->qh_list->qt_next = cpu_to_hc32(QT_NEXT_TERMINATE); + ehci->qh_list->qt_altnext = cpu_to_hc32(QT_NEXT_TERMINATE); + ehci->qh_list->qt_token = cpu_to_hc32(0x40); /* Set async. queue head pointer. */ ehci_writel(&ehci->hcor->or_asynclistaddr, (uint32_t)ehci->qh_list); @@ -878,8 +838,8 @@ static int ehci_probe(struct device_d *dev) ehci->hccr = dev_request_mem_region(dev, 0); ehci->hcor = dev_request_mem_region(dev, 1); - ehci->qh_list = xmemalign(32, sizeof(struct QH) * NUM_QH); - ehci->td = xmemalign(32, sizeof(struct qTD) * NUM_TD); + ehci->qh_list = dma_alloc_coherent(sizeof(struct QH) * NUM_TD); + ehci->td = dma_alloc_coherent(sizeof(struct qTD) * NUM_TD); host->init = ehci_init; host->submit_int_msg = submit_int_msg; diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index eac93db01c..b127b95bbe 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -166,7 +166,9 @@ struct qTD { uint32_t qt_altnext; uint32_t qt_token; uint32_t qt_buffer[5]; -}; + unsigned long qtd_dma; + size_t length; +} __attribute__ ((aligned (32))); /* Queue Head (QH). */ struct QH { @@ -179,7 +181,11 @@ struct QH { uint32_t qh_endpt1; uint32_t qh_endpt2; uint32_t qh_curtd; - struct qTD qh_overlay; + /* qtd overlay (hardware parts of a struct qTD) */ + uint32_t qt_next; + uint32_t qt_altnext; + uint32_t qt_token; + uint32_t qt_buffer[5]; /* * Add dummy fill value to make the size of this struct * aligned to 32 bytes diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 2ce7c6ecc5..b3e9909df0 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -64,7 +64,7 @@ static int at91_ohci_probe(struct device_d *dev) writel(0, ®s->control); add_generic_device("ohci", DEVICE_ID_DYNAMIC, NULL, dev->resource[0].start, - dev->resource[0].size, IORESOURCE_MEM, NULL); + resource_size(&dev->resource[0]), IORESOURCE_MEM, NULL); return 0; } diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 05e4094386..f10d827615 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -415,7 +415,7 @@ static void ohci_dump(struct ohci *controller, int verbose) /* get a transfer request */ -int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) +static int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) { struct ed *ed; int i, size = 0; @@ -498,7 +498,7 @@ int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) static inline int sohci_return_job(struct ohci *hc, struct urb_priv *urb) { #ifdef ENBALE_PIPE_INTERRUPT - struct ohci_regs *regs = hc->regs; + struct ohci_regs __iomem *regs = hc->regs; #endif switch (usb_pipetype(urb->pipe)) { @@ -848,7 +848,7 @@ static void td_fill(struct ohci *ohci, unsigned int info, } #endif if (!len) - data = 0; + data = NULL; td->hwINFO = m32_swap(info); td->hwCBP = virt_to_phys((void *)m32_swap((unsigned long)data)); @@ -894,7 +894,7 @@ static void td_submit_job(struct usb_device *dev, unsigned long pipe, if (data_len) data = buffer; else - data = 0; + data = NULL; switch (usb_pipetype(pipe)) { case PIPE_BULK: @@ -1214,32 +1214,6 @@ static inline void wr_rh_portstat(struct ohci *ohci, int wIndex, __u32 value) writel(value, &ohci->regs->roothub.portstatus[wIndex-1]); } -/* request to virtual root hub */ - -int rh_check_port_status(struct ohci *controller) -{ - __u32 temp, ndp, i; - int res; - - res = -1; - temp = roothub_a(controller); - ndp = (temp & RH_A_NDP); -#ifdef CONFIG_AT91C_PQFP_UHPBUG - ndp = (ndp == 2) ? 1 : 0; -#endif - for (i = 0; i < ndp; i++) { - temp = roothub_portstatus(controller, i); - /* check for a device disconnect */ - if (((temp & (RH_PS_PESC | RH_PS_CSC)) == - (RH_PS_PESC | RH_PS_CSC)) && - ((temp & RH_PS_CCS) == 0)) { - res = i; - break; - } - } - return res; -} - static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *cmd) { @@ -1502,7 +1476,7 @@ static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, /* common code for handling submit messages - used for all but root hub */ /* accesses. */ -int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, +static int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, struct devrequest *setup, int interval, int timeout) { @@ -1721,7 +1695,7 @@ static int hc_start(struct ohci *ohci) static int hc_interrupt(struct ohci *ohci) { - struct ohci_regs *regs = ohci->regs; + struct ohci_regs __iomem *regs = ohci->regs; int ints; int stat = 0; @@ -1840,7 +1814,7 @@ static int ohci_probe(struct device_d *dev) usb_register_host(host); - ohci->regs = (void *)dev->resource[0].start; + ohci->regs = dev_request_mem_region(dev, 0); return 0; } diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h index 913296319e..9c9b8375ce 100644 --- a/drivers/usb/host/ohci.h +++ b/drivers/usb/host/ohci.h @@ -408,7 +408,7 @@ struct ohci { int disabled; /* e.g. got a UE, we're hung */ unsigned long flags; /* for HC bugs */ - struct ohci_regs *regs; /* OHCI controller's memory */ + struct ohci_regs __iomem *regs; /* OHCI controller's memory */ int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ struct ed *ed_rm_list[2]; /* lists of all endpoints to be removed */ diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index e7a5972750..68170b65c0 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -26,6 +26,7 @@ #include <clock.h> #include <scsi.h> #include <errno.h> +#include <dma.h> #undef USB_STOR_DEBUG @@ -65,8 +66,8 @@ int usb_stor_Bulk_clear_endpt_stall(struct us_data *us, unsigned int pipe) /* Determine what the maximum LUN supported is */ int usb_stor_Bulk_max_lun(struct us_data *us) { - int len; - unsigned char iobuf[1]; + int len, ret = 0; + unsigned char *iobuf = dma_alloc(1); /* issue the command */ iobuf[0] = 0; @@ -81,7 +82,9 @@ int usb_stor_Bulk_max_lun(struct us_data *us) /* if we have a successful request, return the result */ if (len > 0) - return (int)iobuf[0]; + ret = iobuf[0]; + + dma_free(iobuf); /* * Some devices don't like GetMaxLUN. They may STALL the control @@ -90,7 +93,7 @@ int usb_stor_Bulk_max_lun(struct us_data *us) * ways. In these cases the best approach is to use the default * value: only one LUN. */ - return 0; + return ret; } int usb_stor_Bulk_transport(ccb *srb, struct us_data *us) diff --git a/drivers/video/fb.c b/drivers/video/fb.c index 0be465f892..d885570b24 100644 --- a/drivers/video/fb.c +++ b/drivers/video/fb.c @@ -86,7 +86,7 @@ static int fb_setup_mode(struct device_d *dev, struct param_d *param, if (!ret) { dev->resource[0].start = (resource_size_t)info->screen_base; info->cdev.size = info->xres * info->yres * (info->bits_per_pixel >> 3); - dev->resource[0].size = info->cdev.size; + dev->resource[0].end = info->cdev.size - 1; dev_param_set_generic(dev, param, val); } else info->cdev.size = 0; @@ -116,7 +116,7 @@ int register_framebuffer(struct fb_info *info) info->cdev.priv = info; dev->resource = xzalloc(sizeof(struct resource)); dev->resource[0].start = (resource_size_t)info->screen_base; - dev->resource[0].size = info->cdev.size; + dev->resource[0].end = info->cdev.size - 1; dev->resource[0].flags = IORESOURCE_MEM; dev->num_resources = 1; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig new file mode 100644 index 0000000000..8fdc7a5aa8 --- /dev/null +++ b/drivers/watchdog/Kconfig @@ -0,0 +1,15 @@ +menuconfig WATCHDOG + bool "Watchdog support " + help + Many platforms support a watchdog to keep track of a working machine. + This framework provides routines to handle these watchdogs. + +if WATCHDOG + +config WATCHDOG_MXS28 + bool "i.MX28" + depends on ARCH_IMX28 + help + Add support for watchdog management for the i.MX28 SoC. + +endif diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile new file mode 100644 index 0000000000..b29103b6cc --- /dev/null +++ b/drivers/watchdog/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_WATCHDOG) += wd_core.o +obj-$(CONFIG_WATCHDOG_MXS28) += im28wd.o diff --git a/drivers/watchdog/im28wd.c b/drivers/watchdog/im28wd.c new file mode 100644 index 0000000000..b016910ec9 --- /dev/null +++ b/drivers/watchdog/im28wd.c @@ -0,0 +1,124 @@ +/* + * (c) 2012 Juergen Beisert <kernel@pengutronix.de> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Note: this driver works for the i.MX28 SoC. It might work for the + * i.MX23 Soc as well, but is not tested yet. + */ + +#include <common.h> +#include <init.h> +#include <io.h> +#include <errno.h> +#include <malloc.h> +#include <watchdog.h> + +#define MXS_RTC_CTRL 0x0 +#define MXS_RTC_SET_ADDR 0x4 +#define MXS_RTC_CLR_ADDR 0x8 +# define MXS_RTC_CTRL_WATCHDOGEN (1 << 4) + +#define MXS_RTC_STAT 0x10 +# define MXS_RTC_STAT_WD_PRESENT (1 << 29) + +#define MXS_RTC_WATCHDOG 0x50 + +#define MXS_RTC_PERSISTENT0 0x60 +/* dubious meaning from inside the SoC's firmware ROM */ +# define MXS_RTC_PERSISTENT0_EXT_RST (1 << 21) +/* dubious meaning from inside the SoC's firmware ROM */ +# define MXS_RTC_PERSISTENT0_THM_RST (1 << 20) + +#define MXS_RTC_PERSISTENT1 0x70 +/* dubious meaning from inside the SoC's firmware ROM */ +# define MXS_RTC_PERSISTENT1_FORCE_UPDATER (1 << 31) + +#define MXS_RTC_DEBUG 0xc0 + +#define WDOG_TICK_RATE 1000 /* the watchdog uses a 1 kHz clock rate */ + +struct imx28_wd { + struct watchdog wd; + void __iomem *regs; +}; + +#define to_imx28_wd(h) container_of(h, struct imx28_wd, wd) + +static int imx28_watchdog_set_timeout(struct watchdog *wd, unsigned timeout) +{ + struct imx28_wd *pwd = (struct imx28_wd *)to_imx28_wd(wd); + void __iomem *base; + + if (timeout > (ULONG_MAX / WDOG_TICK_RATE)) + return -EINVAL; + + if (timeout) { + writel(timeout * WDOG_TICK_RATE, pwd->regs + MXS_RTC_WATCHDOG); + base = pwd->regs + MXS_RTC_SET_ADDR; + } else { + base = pwd->regs + MXS_RTC_CLR_ADDR; + } + writel(MXS_RTC_CTRL_WATCHDOGEN, base + MXS_RTC_CTRL); + writel(MXS_RTC_PERSISTENT1_FORCE_UPDATER, base + MXS_RTC_PERSISTENT1); + + return 0; +} + +static int imx28_wd_probe(struct device_d *dev) +{ + struct imx28_wd *priv; + int rc; + + priv = xzalloc(sizeof(struct imx28_wd)); + priv->regs = dev_request_mem_region(dev, 0); + priv->wd.set_timeout = imx28_watchdog_set_timeout; + + if (!(readl(priv->regs + MXS_RTC_STAT) & MXS_RTC_STAT_WD_PRESENT)) { + rc = -ENODEV; + goto on_error; + } + + /* disable the debug feature to ensure a working WD */ + writel(0x00000000, priv->regs + MXS_RTC_DEBUG); + + rc = watchdog_register(&priv->wd); + if (rc != 0) + goto on_error; + + dev->priv = priv; + return 0; + +on_error: + free(priv); + return rc; +} + +static void imx28_wd_remove(struct device_d *dev) +{ + struct imx28_wd *priv= dev->priv; + watchdog_deregister(&priv->wd); + free(priv); +} + +static struct driver_d imx28_wd_driver = { + .name = "im28wd", + .probe = imx28_wd_probe, + .remove = imx28_wd_remove, +}; + +static int imx28_wd_init(void) +{ + register_driver(&imx28_wd_driver); + return 0; +} + +device_initcall(imx28_wd_init); diff --git a/drivers/watchdog/wd_core.c b/drivers/watchdog/wd_core.c new file mode 100644 index 0000000000..3d0cfc635d --- /dev/null +++ b/drivers/watchdog/wd_core.c @@ -0,0 +1,57 @@ +/* + * (c) 2012 Juergen Beisert <kernel@pengutronix.de> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <command.h> +#include <errno.h> +#include <linux/ctype.h> +#include <watchdog.h> + +/* + * Note: this simple framework supports one watchdog only. + */ +static struct watchdog *watchdog; + +int watchdog_register(struct watchdog *wd) +{ + if (watchdog != NULL) + return -EBUSY; + + watchdog = wd; + return 0; +} +EXPORT_SYMBOL(watchdog_register); + +int watchdog_deregister(struct watchdog *wd) +{ + if (watchdog == NULL || wd != watchdog) + return -ENODEV; + + watchdog = NULL; + return 0; +} +EXPORT_SYMBOL(watchdog_deregister); + +/* + * start, stop or retrigger the watchdog + * timeout in [seconds]. timeout of '0' will disable the watchdog (if possible) + */ +int watchdog_set_timeout(unsigned timeout) +{ + if (watchdog == NULL) + return -ENODEV; + + return watchdog->set_timeout(watchdog, timeout); +} +EXPORT_SYMBOL(watchdog_set_timeout); |