diff options
Diffstat (limited to 'drivers')
28 files changed, 764 insertions, 750 deletions
diff --git a/drivers/fpga/zynqpl.c b/drivers/fpga/zynqpl.c index 1effbad..15900c9 100644 --- a/drivers/fpga/zynqpl.c +++ b/drivers/fpga/zynqpl.c @@ -187,6 +187,16 @@ int zynq_load(Xilinx_desc *desc, const void *buf, size_t bsize) if ((u32)buf != ALIGN((u32)buf, ARCH_DMA_MINALIGN)) { u32 *new_buf = (u32 *)ALIGN((u32)buf, ARCH_DMA_MINALIGN); + /* + * This might be dangerous but permits to flash if + * ARCH_DMA_MINALIGN is greater than header size + */ + if (new_buf > buf_start) { + debug("%s: Aligned buffer is after buffer start\n", + __func__); + new_buf -= ARCH_DMA_MINALIGN; + } + printf("%s: Align buffer at %x to %x(swap %d)\n", __func__, (u32)buf_start, (u32)new_buf, swap); diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index 4cec5aa..d45c15c 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -237,7 +237,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) * host->bus_hz should be set from user. */ if (host->get_mmc_clk) - sclk = host->get_mmc_clk(host->dev_index); + sclk = host->get_mmc_clk(host); else if (host->bus_hz) sclk = host->bus_hz; else { diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c index b3e5c5e..de8cdcc 100644 --- a/drivers/mmc/exynos_dw_mmc.c +++ b/drivers/mmc/exynos_dw_mmc.c @@ -29,9 +29,22 @@ static void exynos_dwmci_clksel(struct dwmci_host *host) dwmci_writel(host, DWMCI_CLKSEL, host->clksel_val); } -unsigned int exynos_dwmci_get_clk(int dev_index) +unsigned int exynos_dwmci_get_clk(struct dwmci_host *host) { - return get_mmc_clk(dev_index); + unsigned long sclk; + int8_t clk_div; + + /* + * Since SDCLKIN is divided inside controller by the DIVRATIO + * value set in the CLKSEL register, we need to use the same output + * clock value to calculate the CLKDIV value. + * as per user manual:cclk_in = SDCLKIN / (DIVRATIO + 1) + */ + clk_div = ((dwmci_readl(host, DWMCI_CLKSEL) >> DWMCI_DIVRATIO_BIT) + & DWMCI_DIVRATIO_MASK) + 1; + sclk = get_mmc_clk(host->dev_index); + + return sclk / clk_div; } static void exynos_dwmci_board_init(struct dwmci_host *host) diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index c6a1c23..8ab0bc9 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -430,7 +430,7 @@ int mmc_complete_op_cond(struct mmc *mmc) mmc->ocr = cmd.response[0]; mmc->high_capacity = ((mmc->ocr & OCR_HCS) == OCR_HCS); - mmc->rca = 0; + mmc->rca = 1; return 0; } @@ -1442,67 +1442,44 @@ int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, } /* - * This function shall form and send the commands to open / close the - * boot partition specified by user. - * - * Input Parameters: - * ack: 0x0 - No boot acknowledge sent (default) - * 0x1 - Boot acknowledge sent during boot operation - * part_num: User selects boot data that will be sent to master - * 0x0 - Device not boot enabled (default) - * 0x1 - Boot partition 1 enabled for boot - * 0x2 - Boot partition 2 enabled for boot - * access: User selects partitions to access - * 0x0 : No access to boot partition (default) - * 0x1 : R/W boot partition 1 - * 0x2 : R/W boot partition 2 - * 0x3 : R/W Replay Protected Memory Block (RPMB) + * Modify EXT_CSD[177] which is BOOT_BUS_WIDTH + * based on the passed in values for BOOT_BUS_WIDTH, RESET_BOOT_BUS_WIDTH + * and BOOT_MODE. * * Returns 0 on success. */ -int mmc_boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access) +int mmc_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode) { int err; - struct mmc_cmd cmd; - /* Boot ack enable, boot partition enable , boot partition access */ - cmd.cmdidx = MMC_CMD_SWITCH; - cmd.resp_type = MMC_RSP_R1b; - - cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_PART_CONF << 16) | - ((EXT_CSD_BOOT_ACK(ack) | - EXT_CSD_BOOT_PART_NUM(part_num) | - EXT_CSD_PARTITION_ACCESS(access)) << 8); + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_BUS_WIDTH, + EXT_CSD_BOOT_BUS_WIDTH_MODE(mode) | + EXT_CSD_BOOT_BUS_WIDTH_RESET(reset) | + EXT_CSD_BOOT_BUS_WIDTH_WIDTH(width)); - err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - if (access) { - debug("mmc boot partition#%d open fail:Error1 = %d\n", - part_num, err); - } else { - debug("mmc boot partition#%d close fail:Error = %d\n", - part_num, err); - } + if (err) return err; - } + return 0; +} - if (access) { - /* 4bit transfer mode at booting time. */ - cmd.cmdidx = MMC_CMD_SWITCH; - cmd.resp_type = MMC_RSP_R1b; +/* + * Modify EXT_CSD[179] which is PARTITION_CONFIG (formerly BOOT_CONFIG) + * based on the passed in values for BOOT_ACK, BOOT_PARTITION_ENABLE and + * PARTITION_ACCESS. + * + * Returns 0 on success. + */ +int mmc_set_part_conf(struct mmc *mmc, u8 ack, u8 part_num, u8 access) +{ + int err; - cmd.cmdarg = (MMC_SWITCH_MODE_WRITE_BYTE << 24) | - (EXT_CSD_BOOT_BUS_WIDTH << 16) | - ((1 << 0) << 8); + err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_PART_CONF, + EXT_CSD_BOOT_ACK(ack) | + EXT_CSD_BOOT_PART_NUM(part_num) | + EXT_CSD_PARTITION_ACCESS(access)); - err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc boot partition#%d open fail:Error2 = %d\n", - part_num, err); - return err; - } - } + if (err) + return err; return 0; } #endif diff --git a/drivers/mmc/zynq_sdhci.c b/drivers/mmc/zynq_sdhci.c index 610bef5..72a272f 100644 --- a/drivers/mmc/zynq_sdhci.c +++ b/drivers/mmc/zynq_sdhci.c @@ -23,7 +23,8 @@ int zynq_sdhci_init(u32 regbase) host->name = "zynq_sdhci"; host->ioaddr = (void *)regbase; - host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD; + host->quirks = SDHCI_QUIRK_NO_CD | SDHCI_QUIRK_WAIT_SEND_CMD | + SDHCI_QUIRK_BROKEN_R1B; host->version = sdhci_readw(host, SDHCI_HOST_VERSION); host->host_caps = MMC_MODE_HC; diff --git a/drivers/mtd/nand/fsl_ifc_nand.c b/drivers/mtd/nand/fsl_ifc_nand.c index 1808a7f..be5a16a 100644 --- a/drivers/mtd/nand/fsl_ifc_nand.c +++ b/drivers/mtd/nand/fsl_ifc_nand.c @@ -230,8 +230,8 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob) ctrl->page = page_addr; /* Program ROW0/COL0 */ - out_be32(&ifc->ifc_nand.row0, page_addr); - out_be32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column); + ifc_out32(&ifc->ifc_nand.row0, page_addr); + ifc_out32(&ifc->ifc_nand.col0, (oob ? IFC_NAND_COL_MS : 0) | column); buf_num = page_addr & priv->bufnum_mask; @@ -294,23 +294,23 @@ static int fsl_ifc_run_command(struct mtd_info *mtd) int i; /* set the chip select for NAND Transaction */ - out_be32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand); + ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand); /* start read/write seq */ - out_be32(&ifc->ifc_nand.nandseq_strt, - IFC_NAND_SEQ_STRT_FIR_STRT); + ifc_out32(&ifc->ifc_nand.nandseq_strt, + IFC_NAND_SEQ_STRT_FIR_STRT); /* wait for NAND Machine complete flag or timeout */ end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks(); while (end_tick > get_ticks()) { - ctrl->status = in_be32(&ifc->ifc_nand.nand_evter_stat); + ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat); if (ctrl->status & IFC_NAND_EVTER_STAT_OPC) break; } - out_be32(&ifc->ifc_nand.nand_evter_stat, ctrl->status); + ifc_out32(&ifc->ifc_nand.nand_evter_stat, ctrl->status); if (ctrl->status & IFC_NAND_EVTER_STAT_FTOER) printf("%s: Flash Time Out Error\n", __func__); @@ -324,7 +324,7 @@ static int fsl_ifc_run_command(struct mtd_info *mtd) int sector_end = sector + chip->ecc.steps - 1; for (i = sector / 4; i <= sector_end / 4; i++) - eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]); + eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]); for (i = sector; i <= sector_end; i++) { errors = check_read_ecc(mtd, ctrl, eccstat, i); @@ -364,30 +364,30 @@ static void fsl_ifc_do_read(struct nand_chip *chip, /* Program FIR/IFC_NAND_FCR0 for Small/Large page */ if (mtd->writesize > 512) { - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | - (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fir1, 0x0); - - out_be32(&ifc->ifc_nand.nand_fcr0, - (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | - (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | + (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP4_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0); + + ifc_out32(&ifc->ifc_nand.nand_fcr0, + (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | + (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT)); } else { - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_RBCD << IFC_NAND_FIR0_OP3_SHIFT)); if (oob) - out_be32(&ifc->ifc_nand.nand_fcr0, - NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + NAND_CMD_READOOB << IFC_NAND_FCR0_CMD0_SHIFT); else - out_be32(&ifc->ifc_nand.nand_fcr0, - NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT); } } @@ -408,7 +408,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, switch (command) { /* READ0 read the entire buffer to use hardware ECC. */ case NAND_CMD_READ0: { - out_be32(&ifc->ifc_nand.nand_fbcr, 0); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 0); set_addr(mtd, 0, page_addr, 0); ctrl->read_bytes = mtd->writesize + mtd->oobsize; @@ -424,7 +424,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, /* READOOB reads only the OOB because no ECC is performed. */ case NAND_CMD_READOOB: - out_be32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column); + ifc_out32(&ifc->ifc_nand.nand_fbcr, mtd->oobsize - column); set_addr(mtd, column, page_addr, 1); ctrl->read_bytes = mtd->writesize + mtd->oobsize; @@ -441,19 +441,19 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, if (command == NAND_CMD_PARAM) timing = IFC_FIR_OP_RBCD; - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | - (timing << IFC_NAND_FIR0_OP2_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fcr0, - command << IFC_NAND_FCR0_CMD0_SHIFT); - out_be32(&ifc->ifc_nand.row3, column); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | + (timing << IFC_NAND_FIR0_OP2_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + command << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.row3, column); /* * although currently it's 8 bytes for READID, we always read * the maximum 256 bytes(for PARAM) */ - out_be32(&ifc->ifc_nand.nand_fbcr, 256); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 256); ctrl->read_bytes = 256; set_addr(mtd, 0, 0, 0); @@ -468,16 +468,16 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, /* ERASE2 uses the block and page address from ERASE1 */ case NAND_CMD_ERASE2: - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP2_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fcr0, - (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) | - (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + (NAND_CMD_ERASE1 << IFC_NAND_FCR0_CMD0_SHIFT) | + (NAND_CMD_ERASE2 << IFC_NAND_FCR0_CMD1_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fbcr, 0); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 0); ctrl->read_bytes = 0; fsl_ifc_run_command(mtd); return; @@ -494,17 +494,18 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD1_SHIFT) | (NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD2_SHIFT); - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP3_SHIFT) | - (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fir1, - (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) | - (IFC_FIR_OP_RDSTAT << + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_WBCD << + IFC_NAND_FIR0_OP3_SHIFT) | + (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP4_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir1, + (IFC_FIR_OP_CW1 << IFC_NAND_FIR1_OP5_SHIFT) | + (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR1_OP6_SHIFT) | - (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT)); + (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP7_SHIFT)); } else { nand_fcr0 = ((NAND_CMD_PAGEPROG << IFC_NAND_FCR0_CMD1_SHIFT) | @@ -513,18 +514,18 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, (NAND_CMD_STATUS << IFC_NAND_FCR0_CMD3_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) | - (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fir1, - (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) | - (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) | - (IFC_FIR_OP_RDSTAT << + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CMD2 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP3_SHIFT) | + (IFC_FIR_OP_WBCD << IFC_NAND_FIR0_OP4_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir1, + (IFC_FIR_OP_CMD1 << IFC_NAND_FIR1_OP5_SHIFT) | + (IFC_FIR_OP_CW3 << IFC_NAND_FIR1_OP6_SHIFT) | + (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR1_OP7_SHIFT) | - (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT)); + (IFC_FIR_OP_NOP << IFC_NAND_FIR1_OP8_SHIFT)); if (column >= mtd->writesize) nand_fcr0 |= @@ -539,7 +540,7 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, column -= mtd->writesize; ctrl->oob = 1; } - out_be32(&ifc->ifc_nand.nand_fcr0, nand_fcr0); + ifc_out32(&ifc->ifc_nand.nand_fcr0, nand_fcr0); set_addr(mtd, column, page_addr, ctrl->oob); return; } @@ -547,21 +548,21 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, /* PAGEPROG reuses all of the setup from SEQIN and adds the length */ case NAND_CMD_PAGEPROG: if (ctrl->oob) - out_be32(&ifc->ifc_nand.nand_fbcr, - ctrl->index - ctrl->column); + ifc_out32(&ifc->ifc_nand.nand_fbcr, + ctrl->index - ctrl->column); else - out_be32(&ifc->ifc_nand.nand_fbcr, 0); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 0); fsl_ifc_run_command(mtd); return; case NAND_CMD_STATUS: - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fcr0, - NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT); - out_be32(&ifc->ifc_nand.nand_fbcr, 1); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP1_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + NAND_CMD_STATUS << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 1); set_addr(mtd, 0, 0, 0); ctrl->read_bytes = 1; @@ -572,10 +573,10 @@ static void fsl_ifc_cmdfunc(struct mtd_info *mtd, unsigned int command, return; case NAND_CMD_RESET: - out_be32(&ifc->ifc_nand.nand_fir0, - IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT); - out_be32(&ifc->ifc_nand.nand_fcr0, - NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fir0, + IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + NAND_CMD_RESET << IFC_NAND_FCR0_CMD0_SHIFT); fsl_ifc_run_command(mtd); return; @@ -647,8 +648,8 @@ static uint8_t fsl_ifc_read_byte16(struct mtd_info *mtd) * next byte. */ if (ctrl->index < ctrl->read_bytes) { - data = in_be16((uint16_t *)&ctrl-> - addr[ctrl->index]); + data = ifc_in16((uint16_t *)&ctrl-> + addr[ctrl->index]); ctrl->index += 2; return (uint8_t)data; } @@ -727,12 +728,12 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) return NAND_STATUS_FAIL; /* Use READ_STATUS command, but wait for the device to be ready */ - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS << - IFC_NAND_FCR0_CMD0_SHIFT); - out_be32(&ifc->ifc_nand.nand_fbcr, 1); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_RDSTAT << IFC_NAND_FIR0_OP1_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fcr0, NAND_CMD_STATUS << + IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 1); set_addr(mtd, 0, 0, 0); ctrl->read_bytes = 1; @@ -741,7 +742,7 @@ static int fsl_ifc_wait(struct mtd_info *mtd, struct nand_chip *chip) if (ctrl->status != IFC_NAND_EVTER_STAT_OPC) return NAND_STATUS_FAIL; - nand_fsr = in_be32(&ifc->ifc_nand.nand_fsr); + nand_fsr = ifc_in32(&ifc->ifc_nand.nand_fsr); /* Chip sometimes reporting write protect even when it's not */ nand_fsr = nand_fsr | NAND_STATUS_WP; @@ -784,17 +785,17 @@ static void fsl_ifc_ctrl_init(void) ifc_ctrl->regs = IFC_BASE_ADDR; /* clear event registers */ - out_be32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U); - out_be32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U); + ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_stat, ~0U); + ifc_out32(&ifc_ctrl->regs->ifc_nand.pgrdcmpl_evt_stat, ~0U); /* Enable error and event for any detected errors */ - out_be32(&ifc_ctrl->regs->ifc_nand.nand_evter_en, - IFC_NAND_EVTER_EN_OPC_EN | - IFC_NAND_EVTER_EN_PGRDCMPL_EN | - IFC_NAND_EVTER_EN_FTOER_EN | - IFC_NAND_EVTER_EN_WPER_EN); + ifc_out32(&ifc_ctrl->regs->ifc_nand.nand_evter_en, + IFC_NAND_EVTER_EN_OPC_EN | + IFC_NAND_EVTER_EN_PGRDCMPL_EN | + IFC_NAND_EVTER_EN_FTOER_EN | + IFC_NAND_EVTER_EN_WPER_EN); - out_be32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0); + ifc_out32(&ifc_ctrl->regs->ifc_nand.ncfgr, 0x0); } static void fsl_ifc_select_chip(struct mtd_info *mtd, int chip) @@ -810,50 +811,50 @@ static void fsl_ifc_sram_init(void) cs = ifc_ctrl->cs_nand >> IFC_NAND_CSEL_SHIFT; /* Save CSOR and CSOR_ext */ - csor = in_be32(&ifc_ctrl->regs->csor_cs[cs].csor); - csor_ext = in_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext); + csor = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor); + csor_ext = ifc_in32(&ifc_ctrl->regs->csor_cs[cs].csor_ext); /* chage PageSize 8K and SpareSize 1K*/ csor_8k = (csor & ~(CSOR_NAND_PGS_MASK)) | 0x0018C000; - out_be32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k); - out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400); + ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor_8k); + ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, 0x0000400); /* READID */ - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fcr0, - NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); - out_be32(&ifc->ifc_nand.row3, 0x0); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_UA << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RB << IFC_NAND_FIR0_OP2_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fcr0, + NAND_CMD_READID << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.row3, 0x0); - out_be32(&ifc->ifc_nand.nand_fbcr, 0x0); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 0x0); /* Program ROW0/COL0 */ - out_be32(&ifc->ifc_nand.row0, 0x0); - out_be32(&ifc->ifc_nand.col0, 0x0); + ifc_out32(&ifc->ifc_nand.row0, 0x0); + ifc_out32(&ifc->ifc_nand.col0, 0x0); /* set the chip select for NAND Transaction */ - out_be32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand); + ifc_out32(&ifc->ifc_nand.nand_csel, ifc_ctrl->cs_nand); /* start read seq */ - out_be32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT); + ifc_out32(&ifc->ifc_nand.nandseq_strt, IFC_NAND_SEQ_STRT_FIR_STRT); /* wait for NAND Machine complete flag or timeout */ end_tick = usec2ticks(IFC_TIMEOUT_MSECS * 1000) + get_ticks(); while (end_tick > get_ticks()) { - ifc_ctrl->status = in_be32(&ifc->ifc_nand.nand_evter_stat); + ifc_ctrl->status = ifc_in32(&ifc->ifc_nand.nand_evter_stat); if (ifc_ctrl->status & IFC_NAND_EVTER_STAT_OPC) break; } - out_be32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status); + ifc_out32(&ifc->ifc_nand.nand_evter_stat, ifc_ctrl->status); /* Restore CSOR and CSOR_ext */ - out_be32(&ifc_ctrl->regs->csor_cs[cs].csor, csor); - out_be32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext); + ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor, csor); + ifc_out32(&ifc_ctrl->regs->csor_cs[cs].csor_ext, csor_ext); } static int fsl_ifc_chip_init(int devnum, u8 *addr) @@ -883,8 +884,8 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr) for (priv->bank = 0; priv->bank < MAX_BANKS; priv->bank++) { phys_addr_t phys_addr = virt_to_phys(addr); - cspr = in_be32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr); - csor = in_be32(&ifc_ctrl->regs->csor_cs[priv->bank].csor); + cspr = ifc_in32(&ifc_ctrl->regs->cspr_cs[priv->bank].cspr); + csor = ifc_in32(&ifc_ctrl->regs->csor_cs[priv->bank].csor); if ((cspr & CSPR_V) && (cspr & CSPR_MSEL) == CSPR_MSEL_NAND && (cspr & CSPR_BA) == CSPR_PHYS_ADDR(phys_addr)) { @@ -1004,7 +1005,7 @@ static int fsl_ifc_chip_init(int devnum, u8 *addr) nand->ecc.mode = NAND_ECC_SOFT; } - ver = in_be32(&ifc_ctrl->regs->ifc_rev); + ver = ifc_in32(&ifc_ctrl->regs->ifc_rev); if (ver == FSL_IFC_V1_1_0) fsl_ifc_sram_init(); diff --git a/drivers/mtd/nand/fsl_ifc_spl.c b/drivers/mtd/nand/fsl_ifc_spl.c index 6b43496..2f82f7c 100644 --- a/drivers/mtd/nand/fsl_ifc_spl.c +++ b/drivers/mtd/nand/fsl_ifc_spl.c @@ -60,7 +60,7 @@ static inline void nand_wait(uchar *buf, int bufnum, int page_size) bufnum_end = bufnum + bufperpage - 1; do { - status = in_be32(&ifc->ifc_nand.nand_evter_stat); + status = ifc_in32(&ifc->ifc_nand.nand_evter_stat); } while (!(status & IFC_NAND_EVTER_STAT_OPC)); if (status & IFC_NAND_EVTER_STAT_FTOER) { @@ -70,14 +70,14 @@ static inline void nand_wait(uchar *buf, int bufnum, int page_size) } for (i = bufnum / 4; i <= bufnum_end / 4; i++) - eccstat[i] = in_be32(&ifc->ifc_nand.nand_eccstat[i]); + eccstat[i] = ifc_in32(&ifc->ifc_nand.nand_eccstat[i]); for (i = bufnum; i <= bufnum_end; i++) { if (check_read_ecc(buf, eccstat, i, page_size)) break; } - out_be32(&ifc->ifc_nand.nand_evter_stat, status); + ifc_out32(&ifc->ifc_nand.nand_evter_stat, status); } static inline int bad_block(uchar *marker, int port_size) @@ -140,38 +140,38 @@ static int nand_load(uint32_t offs, unsigned int uboot_size, void *vdst) blk_size = pages_per_blk * page_size; /* Open Full SRAM mapping for spare are access */ - out_be32(&ifc->ifc_nand.ncfgr, 0x0); + ifc_out32(&ifc->ifc_nand.ncfgr, 0x0); /* Clear Boot events */ - out_be32(&ifc->ifc_nand.nand_evter_stat, 0xffffffff); + ifc_out32(&ifc->ifc_nand.nand_evter_stat, 0xffffffff); /* Program FIR/FCR for Large/Small page */ if (page_size > 512) { - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | - (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP4_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fir1, 0x0); - - out_be32(&ifc->ifc_nand.nand_fcr0, - (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | - (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_CMD1 << IFC_NAND_FIR0_OP3_SHIFT) | + (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP4_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0); + + ifc_out32(&ifc->ifc_nand.nand_fcr0, + (NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT) | + (NAND_CMD_READSTART << IFC_NAND_FCR0_CMD1_SHIFT)); } else { - out_be32(&ifc->ifc_nand.nand_fir0, - (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | - (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | - (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | - (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP3_SHIFT)); - out_be32(&ifc->ifc_nand.nand_fir1, 0x0); - - out_be32(&ifc->ifc_nand.nand_fcr0, - NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT); + ifc_out32(&ifc->ifc_nand.nand_fir0, + (IFC_FIR_OP_CW0 << IFC_NAND_FIR0_OP0_SHIFT) | + (IFC_FIR_OP_CA0 << IFC_NAND_FIR0_OP1_SHIFT) | + (IFC_FIR_OP_RA0 << IFC_NAND_FIR0_OP2_SHIFT) | + (IFC_FIR_OP_BTRD << IFC_NAND_FIR0_OP3_SHIFT)); + ifc_out32(&ifc->ifc_nand.nand_fir1, 0x0); + + ifc_out32(&ifc->ifc_nand.nand_fcr0, + NAND_CMD_READ0 << IFC_NAND_FCR0_CMD0_SHIFT); } /* Program FBCR = 0 for full page read */ - out_be32(&ifc->ifc_nand.nand_fbcr, 0); + ifc_out32(&ifc->ifc_nand.nand_fbcr, 0); /* Read and copy u-boot on SDRAM from NAND device, In parallel * check for Bad block if found skip it and read continue to @@ -184,11 +184,11 @@ static int nand_load(uint32_t offs, unsigned int uboot_size, void *vdst) bufnum = pg_no & bufnum_mask; sram_addr = bufnum * page_size * 2; - out_be32(&ifc->ifc_nand.row0, pg_no); - out_be32(&ifc->ifc_nand.col0, 0); + ifc_out32(&ifc->ifc_nand.row0, pg_no); + ifc_out32(&ifc->ifc_nand.col0, 0); /* start read */ - out_be32(&ifc->ifc_nand.nandseq_strt, - IFC_NAND_SEQ_STRT_FIR_STRT); + ifc_out32(&ifc->ifc_nand.nandseq_strt, + IFC_NAND_SEQ_STRT_FIR_STRT); /* wait for read to complete */ nand_wait(&buf[sram_addr], bufnum, page_size); diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 0ffd59d..42e208c 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -259,6 +259,8 @@ static int bfin_miiphy_init(struct eth_device *dev, int *opmode) *opmode = 0; bfin_write_EMAC_MMC_CTL(RSTC | CROLL); + bfin_write_EMAC_VLAN1(EMAC_VLANX_DEF_VAL); + bfin_write_EMAC_VLAN2(EMAC_VLANX_DEF_VAL); /* Initialize the TX DMA channel registers */ bfin_write_DMA2_X_COUNT(0); diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 22155b4..c45593b 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -17,7 +17,75 @@ #include <asm/io.h> #include "designware.h" -static int configure_phy(struct eth_device *dev); +#if !defined(CONFIG_PHYLIB) +# error "DesignWare Ether MAC requires PHYLIB - missing CONFIG_PHYLIB" +#endif + +static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) +{ + struct eth_mac_regs *mac_p = bus->priv; + ulong start; + u16 miiaddr; + int timeout = CONFIG_MDIO_TIMEOUT; + + miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | + ((reg << MIIREGSHIFT) & MII_REGMSK); + + writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); + + start = get_timer(0); + while (get_timer(start) < timeout) { + if (!(readl(&mac_p->miiaddr) & MII_BUSY)) + return readl(&mac_p->miidata); + udelay(10); + }; + + return -1; +} + +static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 val) +{ + struct eth_mac_regs *mac_p = bus->priv; + ulong start; + u16 miiaddr; + int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; + + 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_timer(0); + while (get_timer(start) < timeout) { + if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { + ret = 0; + break; + } + udelay(10); + }; + + return ret; +} + +static int dw_mdio_init(char *name, struct eth_mac_regs *mac_regs_p) +{ + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate MDIO bus\n"); + return -1; + } + + bus->read = dw_mdio_read; + bus->write = dw_mdio_write; + sprintf(bus->name, name); + + bus->priv = (void *)mac_regs_p; + + return mdio_register(bus); +} static void tx_descs_init(struct eth_device *dev) { @@ -51,7 +119,13 @@ static void tx_descs_init(struct eth_device *dev) /* Correcting the last pointer of the chain */ desc_p->dmamac_next = &desc_table_p[0]; + /* Flush all Tx buffer descriptors at once */ + flush_dcache_range((unsigned int)priv->tx_mac_descrtable, + (unsigned int)priv->tx_mac_descrtable + + sizeof(priv->tx_mac_descrtable)); + writel((ulong)&desc_table_p[0], &dma_p->txdesclistaddr); + priv->tx_currdescnum = 0; } static void rx_descs_init(struct eth_device *dev) @@ -63,6 +137,15 @@ static void rx_descs_init(struct eth_device *dev) struct dmamacdescr *desc_p; u32 idx; + /* Before passing buffers to GMAC we need to make sure zeros + * written there right after "priv" structure allocation were + * flushed into RAM. + * Otherwise there's a chance to get some of them flushed in RAM when + * GMAC is already pushing data to RAM via DMA. This way incoming from + * GMAC data will be corrupted. */ + flush_dcache_range((unsigned int)rxbuffs, (unsigned int)rxbuffs + + RX_TOTAL_BUFSIZE); + for (idx = 0; idx < CONFIG_RX_DESCR_NUM; idx++) { desc_p = &desc_table_p[idx]; desc_p->dmamac_addr = &rxbuffs[idx * CONFIG_ETH_BUFSIZE]; @@ -78,56 +161,68 @@ static void rx_descs_init(struct eth_device *dev) /* Correcting the last pointer of the chain */ desc_p->dmamac_next = &desc_table_p[0]; + /* Flush all Rx buffer descriptors at once */ + flush_dcache_range((unsigned int)priv->rx_mac_descrtable, + (unsigned int)priv->rx_mac_descrtable + + sizeof(priv->rx_mac_descrtable)); + writel((ulong)&desc_table_p[0], &dma_p->rxdesclistaddr); + priv->rx_currdescnum = 0; } -static void descs_init(struct eth_device *dev) +static int dw_write_hwaddr(struct eth_device *dev) { - tx_descs_init(dev); - rx_descs_init(dev); + struct dw_eth_dev *priv = dev->priv; + struct eth_mac_regs *mac_p = priv->mac_regs_p; + u32 macid_lo, macid_hi; + u8 *mac_id = &dev->enetaddr[0]; + + macid_lo = mac_id[0] + (mac_id[1] << 8) + (mac_id[2] << 16) + + (mac_id[3] << 24); + macid_hi = mac_id[4] + (mac_id[5] << 8); + + writel(macid_hi, &mac_p->macaddr0hi); + writel(macid_lo, &mac_p->macaddr0lo); + + return 0; } -static int mac_reset(struct eth_device *dev) +static void dw_adjust_link(struct eth_mac_regs *mac_p, + struct phy_device *phydev) { - 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 = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN; - ulong start; - int timeout = CONFIG_MACRESET_TIMEOUT; + if (!phydev->link) { + printf("%s: No link.\n", phydev->dev->name); + return; + } - writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); + if (phydev->speed != 1000) + conf |= MII_PORTSELECT; - if (priv->interface != PHY_INTERFACE_MODE_RGMII) - writel(MII_PORTSELECT, &mac_p->conf); + if (phydev->speed == 100) + conf |= FES_100; - start = get_timer(0); - while (get_timer(start) < timeout) { - if (!(readl(&dma_p->busmode) & DMAMAC_SRST)) - return 0; + if (phydev->duplex) + conf |= FULLDPLXMODE; - /* Try again after 10usec */ - udelay(10); - }; + writel(conf, &mac_p->conf); - return -1; + printf("Speed: %d, %s duplex%s\n", phydev->speed, + (phydev->duplex) ? "full" : "half", + (phydev->port == PORT_FIBRE) ? ", fiber mode" : ""); } -static int dw_write_hwaddr(struct eth_device *dev) +static void dw_eth_halt(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; struct eth_mac_regs *mac_p = priv->mac_regs_p; - u32 macid_lo, macid_hi; - u8 *mac_id = &dev->enetaddr[0]; - - macid_lo = mac_id[0] + (mac_id[1] << 8) + \ - (mac_id[2] << 16) + (mac_id[3] << 24); - macid_hi = mac_id[4] + (mac_id[5] << 8); + struct eth_dma_regs *dma_p = priv->dma_regs_p; - writel(macid_hi, &mac_p->macaddr0hi); - writel(macid_lo, &mac_p->macaddr0lo); + writel(readl(&mac_p->conf) & ~(RXENABLE | TXENABLE), &mac_p->conf); + writel(readl(&dma_p->opmode) & ~(RXSTART | TXSTART), &dma_p->opmode); - return 0; + phy_shutdown(priv->phydev); } static int dw_eth_init(struct eth_device *dev, bd_t *bis) @@ -135,55 +230,43 @@ static int dw_eth_init(struct eth_device *dev, bd_t *bis) 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; + unsigned int start; - if (priv->phy_configured != 1) - configure_phy(dev); + writel(readl(&dma_p->busmode) | DMAMAC_SRST, &dma_p->busmode); - /* Print link status only once */ - if (!priv->link_printed) { - printf("ENET Speed is %d Mbps - %s duplex connection\n", - priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL"); - priv->link_printed = 1; - } + start = get_timer(0); + while (readl(&dma_p->busmode) & DMAMAC_SRST) { + if (get_timer(start) >= CONFIG_MACRESET_TIMEOUT) + return -1; - /* Reset ethernet hardware */ - if (mac_reset(dev) < 0) - return -1; + mdelay(100); + }; - /* Resore the HW MAC address as it has been lost during MAC reset */ + /* Soft reset above clears HW address registers. + * So we have to set it here once again */ dw_write_hwaddr(dev); - writel(FIXEDBURST | PRIORXTX_41 | BURST_16, - &dma_p->busmode); - - writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD | - TXSECONDFRAME, &dma_p->opmode); + rx_descs_init(dev); + tx_descs_init(dev); - conf = FRAMEBURSTENABLE | DISABLERXOWN; + writel(FIXEDBURST | PRIORXTX_41 | BURST_16, &dma_p->busmode); - if (priv->speed != 1000) - conf |= MII_PORTSELECT; + writel(readl(&dma_p->opmode) | FLUSHTXFIFO | STOREFORWARD, + &dma_p->opmode); - if ((priv->interface != PHY_INTERFACE_MODE_MII) && - (priv->interface != PHY_INTERFACE_MODE_GMII)) { + writel(readl(&dma_p->opmode) | RXSTART | TXSTART, &dma_p->opmode); - if (priv->speed == 100) - conf |= FES_100; + /* Start up the PHY */ + if (phy_startup(priv->phydev)) { + printf("Could not initialize PHY %s\n", + priv->phydev->dev->name); + return -1; } - if (priv->duplex == FULL) - conf |= FULLDPLXMODE; - - writel(conf, &mac_p->conf); - - descs_init(dev); + dw_adjust_link(mac_p, priv->phydev); - /* - * 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); + if (!priv->phydev->link) + return -1; writel(readl(&mac_p->conf) | RXENABLE | TXENABLE, &mac_p->conf); @@ -197,6 +280,11 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length) u32 desc_num = priv->tx_currdescnum; struct dmamacdescr *desc_p = &priv->tx_mac_descrtable[desc_num]; + /* Invalidate only "status" field for the following check */ + invalidate_dcache_range((unsigned long)&desc_p->txrx_status, + (unsigned long)&desc_p->txrx_status + + sizeof(desc_p->txrx_status)); + /* Check if the descriptor is owned by CPU */ if (desc_p->txrx_status & DESC_TXSTS_OWNBYDMA) { printf("CPU not owner of tx frame\n"); @@ -205,6 +293,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length) memcpy((void *)desc_p->dmamac_addr, packet, length); + /* Flush data to be sent */ + flush_dcache_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + length); + #if defined(CONFIG_DW_ALTDESCRIPTOR) desc_p->txrx_status |= DESC_TXSTS_TXFIRST | DESC_TXSTS_TXLAST; desc_p->dmamac_cntl |= (length << DESC_TXCTRL_SIZE1SHFT) & \ @@ -220,6 +312,10 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length) desc_p->txrx_status = DESC_TXSTS_OWNBYDMA; #endif + /* Flush modified buffer descriptor */ + flush_dcache_range((unsigned long)desc_p, + (unsigned long)desc_p + sizeof(struct dmamacdescr)); + /* Test the wrap-around condition. */ if (++desc_num >= CONFIG_TX_DESCR_NUM) desc_num = 0; @@ -235,18 +331,28 @@ static int dw_eth_send(struct eth_device *dev, void *packet, int length) static int dw_eth_recv(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; - u32 desc_num = priv->rx_currdescnum; + u32 status, desc_num = priv->rx_currdescnum; struct dmamacdescr *desc_p = &priv->rx_mac_descrtable[desc_num]; - - u32 status = desc_p->txrx_status; int length = 0; + /* Invalidate entire buffer descriptor */ + invalidate_dcache_range((unsigned long)desc_p, + (unsigned long)desc_p + + sizeof(struct dmamacdescr)); + + status = desc_p->txrx_status; + /* Check if the owner is the CPU */ if (!(status & DESC_RXSTS_OWNBYDMA)) { length = (status & DESC_RXSTS_FRMLENMSK) >> \ DESC_RXSTS_FRMLENSHFT; + /* Invalidate received data */ + invalidate_dcache_range((unsigned long)desc_p->dmamac_addr, + (unsigned long)desc_p->dmamac_addr + + length); + NetReceive(desc_p->dmamac_addr, length); /* @@ -255,6 +361,11 @@ static int dw_eth_recv(struct eth_device *dev) */ desc_p->txrx_status |= DESC_RXSTS_OWNBYDMA; + /* Flush only status field - others weren't changed */ + flush_dcache_range((unsigned long)&desc_p->txrx_status, + (unsigned long)&desc_p->txrx_status + + sizeof(desc_p->txrx_status)); + /* Test the wrap-around condition. */ if (++desc_num >= CONFIG_RX_DESCR_NUM) desc_num = 0; @@ -265,251 +376,30 @@ static int dw_eth_recv(struct eth_device *dev) return length; } -static void dw_eth_halt(struct eth_device *dev) -{ - struct dw_eth_dev *priv = dev->priv; - - mac_reset(dev); - priv->tx_currdescnum = priv->rx_currdescnum = 0; -} - -static int eth_mdio_read(struct eth_device *dev, u8 addr, u8 reg, u16 *val) -{ - struct dw_eth_dev *priv = dev->priv; - struct eth_mac_regs *mac_p = priv->mac_regs_p; - ulong start; - u32 miiaddr; - int timeout = CONFIG_MDIO_TIMEOUT; - - miiaddr = ((addr << MIIADDRSHIFT) & MII_ADDRMSK) | \ - ((reg << MIIREGSHIFT) & MII_REGMSK); - - writel(miiaddr | MII_CLKRANGE_150_250M | MII_BUSY, &mac_p->miiaddr); - - start = get_timer(0); - while (get_timer(start) < timeout) { - if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { - *val = readl(&mac_p->miidata); - return 0; - } - - /* Try again after 10usec */ - udelay(10); - }; - - return -1; -} - -static int eth_mdio_write(struct eth_device *dev, u8 addr, u8 reg, u16 val) +static int dw_phy_init(struct eth_device *dev) { struct dw_eth_dev *priv = dev->priv; - struct eth_mac_regs *mac_p = priv->mac_regs_p; - ulong start; - u32 miiaddr; - int ret = -1, timeout = CONFIG_MDIO_TIMEOUT; - u16 value; - - 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_timer(0); - while (get_timer(start) < timeout) { - if (!(readl(&mac_p->miiaddr) & MII_BUSY)) { - ret = 0; - break; - } + struct phy_device *phydev; + int mask = 0xffffffff; - /* Try again after 10usec */ - udelay(10); - }; - - /* Needed as a fix for ST-Phy */ - eth_mdio_read(dev, addr, reg, &value); - - return ret; -} - -#if defined(CONFIG_DW_SEARCH_PHY) -static int find_phy(struct eth_device *dev) -{ - int phy_addr = 0; - u16 ctrl, oldctrl; - - do { - eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); - oldctrl = ctrl & BMCR_ANENABLE; - - ctrl ^= BMCR_ANENABLE; - eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl); - eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); - ctrl &= BMCR_ANENABLE; - - if (ctrl == oldctrl) { - phy_addr++; - } else { - ctrl ^= BMCR_ANENABLE; - eth_mdio_write(dev, phy_addr, MII_BMCR, ctrl); - - return phy_addr; - } - } while (phy_addr < 32); - - return -1; -} +#ifdef CONFIG_PHY_ADDR + mask = 1 << CONFIG_PHY_ADDR; #endif -static int dw_reset_phy(struct eth_device *dev) -{ - struct dw_eth_dev *priv = dev->priv; - u16 ctrl; - ulong start; - int timeout = CONFIG_PHYRESET_TIMEOUT; - u32 phy_addr = priv->address; - - eth_mdio_write(dev, phy_addr, MII_BMCR, BMCR_RESET); - - start = get_timer(0); - while (get_timer(start) < timeout) { - eth_mdio_read(dev, phy_addr, MII_BMCR, &ctrl); - if (!(ctrl & BMCR_RESET)) - break; - - /* Try again after 10usec */ - udelay(10); - }; - - if (get_timer(start) >= CONFIG_PHYRESET_TIMEOUT) + phydev = phy_find_by_mask(priv->bus, mask, priv->interface); + if (!phydev) return -1; -#ifdef CONFIG_PHY_RESET_DELAY - udelay(CONFIG_PHY_RESET_DELAY); -#endif - return 0; -} + phydev->supported &= PHY_GBIT_FEATURES; + phydev->advertising = phydev->supported; -/* - * Add weak default function for board specific PHY configuration - */ -int __weak designware_board_phy_init(struct eth_device *dev, int phy_addr, - int (*mii_write)(struct eth_device *, u8, u8, u16), - int dw_reset_phy(struct eth_device *)) -{ - return 0; -} - -static int configure_phy(struct eth_device *dev) -{ - struct dw_eth_dev *priv = dev->priv; - int phy_addr; - u16 bmcr; -#if defined(CONFIG_DW_AUTONEG) - u16 bmsr; - u32 timeout; - ulong start; -#endif - -#if defined(CONFIG_DW_SEARCH_PHY) - phy_addr = find_phy(dev); - if (phy_addr >= 0) - priv->address = phy_addr; - else - return -1; -#else - phy_addr = priv->address; -#endif - - /* - * Some boards need board specific PHY initialization. This is - * after the main driver init code but before the auto negotiation - * is run. - */ - if (designware_board_phy_init(dev, phy_addr, - eth_mdio_write, dw_reset_phy) < 0) - return -1; - - if (dw_reset_phy(dev) < 0) - return -1; - -#if defined(CONFIG_DW_AUTONEG) - /* Set Auto-Neg Advertisement capabilities to 10/100 half/full */ - eth_mdio_write(dev, phy_addr, MII_ADVERTISE, 0x1E1); - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; -#else - bmcr = BMCR_SPEED100 | BMCR_FULLDPLX; - -#if defined(CONFIG_DW_SPEED10M) - bmcr &= ~BMCR_SPEED100; -#endif -#if defined(CONFIG_DW_DUPLEXHALF) - bmcr &= ~BMCR_FULLDPLX; -#endif -#endif - if (eth_mdio_write(dev, phy_addr, MII_BMCR, bmcr) < 0) - return -1; - - /* Read the phy status register and populate priv structure */ -#if defined(CONFIG_DW_AUTONEG) - timeout = CONFIG_AUTONEG_TIMEOUT; - start = get_timer(0); - puts("Waiting for PHY auto negotiation to complete"); - while (get_timer(start) < timeout) { - eth_mdio_read(dev, phy_addr, MII_BMSR, &bmsr); - if (bmsr & BMSR_ANEGCOMPLETE) { - priv->phy_configured = 1; - break; - } + priv->phydev = phydev; + phy_config(phydev); - /* Print dot all 1s to show progress */ - if ((get_timer(start) % 1000) == 0) - putc('.'); - - /* Try again after 1msec */ - udelay(1000); - }; - - if (!(bmsr & BMSR_ANEGCOMPLETE)) - puts(" TIMEOUT!\n"); - else - puts(" done\n"); -#else - priv->phy_configured = 1; -#endif - - priv->speed = miiphy_speed(dev->name, phy_addr); - priv->duplex = miiphy_duplex(dev->name, phy_addr); - - return 0; -} - -#if defined(CONFIG_MII) -static int dw_mii_read(const char *devname, u8 addr, u8 reg, u16 *val) -{ - struct eth_device *dev; - - dev = eth_get_dev_by_name(devname); - if (dev) - eth_mdio_read(dev, addr, reg, val); - - return 0; -} - -static int dw_mii_write(const char *devname, u8 addr, u8 reg, u16 val) -{ - struct eth_device *dev; - - dev = eth_get_dev_by_name(devname); - if (dev) - eth_mdio_write(dev, addr, reg, val); - - return 0; + return 1; } -#endif -int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface) +int designware_initialize(ulong base_addr, u32 interface) { struct eth_device *dev; struct dw_eth_dev *priv; @@ -531,19 +421,14 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface) memset(dev, 0, sizeof(struct eth_device)); memset(priv, 0, sizeof(struct dw_eth_dev)); - sprintf(dev->name, "mii%d", id); + sprintf(dev->name, "dwmac.%lx", base_addr); dev->iobase = (int)base_addr; dev->priv = priv; - eth_getenv_enetaddr_by_index("eth", id, &dev->enetaddr[0]); - priv->dev = dev; priv->mac_regs_p = (struct eth_mac_regs *)base_addr; priv->dma_regs_p = (struct eth_dma_regs *)(base_addr + DW_DMA_BASE_OFFSET); - priv->address = phy_addr; - priv->phy_configured = 0; - priv->interface = interface; dev->init = dw_eth_init; dev->send = dw_eth_send; @@ -553,8 +438,10 @@ int designware_initialize(u32 id, ulong base_addr, u32 phy_addr, u32 interface) eth_register(dev); -#if defined(CONFIG_MII) - miiphy_register(dev->name, dw_mii_read, dw_mii_write); -#endif - return 1; + priv->interface = interface; + + dw_mdio_init(dev->name, priv->mac_regs_p); + priv->bus = miiphy_get_dev_by_name(dev->name); + + return dw_phy_init(dev); } diff --git a/drivers/net/designware.h b/drivers/net/designware.h index 5440c92..afeacce 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -16,8 +16,6 @@ #define CONFIG_MACRESET_TIMEOUT (3 * CONFIG_SYS_HZ) #define CONFIG_MDIO_TIMEOUT (3 * CONFIG_SYS_HZ) -#define CONFIG_PHYRESET_TIMEOUT (3 * CONFIG_SYS_HZ) -#define CONFIG_AUTONEG_TIMEOUT (5 * CONFIG_SYS_HZ) struct eth_mac_regs { u32 conf; /* 0x00 */ @@ -217,14 +215,9 @@ struct dmamacdescr { #endif struct dw_eth_dev { - u32 address; u32 interface; - u32 speed; - u32 duplex; u32 tx_currdescnum; u32 rx_currdescnum; - u32 phy_configured; - u32 link_printed; struct dmamacdescr tx_mac_descrtable[CONFIG_TX_DESCR_NUM]; struct dmamacdescr rx_mac_descrtable[CONFIG_RX_DESCR_NUM]; @@ -236,15 +229,8 @@ struct dw_eth_dev { struct eth_dma_regs *dma_regs_p; struct eth_device *dev; + struct phy_device *phydev; + struct mii_dev *bus; }; -/* 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 - #endif diff --git a/drivers/net/fm/t1040.c b/drivers/net/fm/t1040.c index 83cf081..bcc871d 100644 --- a/drivers/net/fm/t1040.c +++ b/drivers/net/fm/t1040.c @@ -12,5 +12,61 @@ phy_interface_t fman_port_enet_if(enum fm_port port) { + ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR); + u32 rcwsr13 = in_be32(&gur->rcwsr[13]); + + /* handle RGMII first */ + if ((port == FM1_DTSEC2) && + ((rcwsr13 & FSL_CORENET_RCWSR13_MAC2_GMII_SEL) == + FSL_CORENET_RCWSR13_MAC2_GMII_SEL_ENET_PORT)) { + if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == + FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_RGMII) + return PHY_INTERFACE_MODE_RGMII; + else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == + FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_MII) + return PHY_INTERFACE_MODE_MII; + else + return PHY_INTERFACE_MODE_NONE; + } + + if ((port == FM1_DTSEC4) && + ((rcwsr13 & FSL_CORENET_RCWSR13_MAC2_GMII_SEL) == + FSL_CORENET_RCWSR13_MAC2_GMII_SEL_L2_SWITCH)) { + if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == + FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_RGMII) + return PHY_INTERFACE_MODE_RGMII; + else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC1) == + FSL_CORENET_RCWSR13_EC1_FM1_DTSEC4_MII) + return PHY_INTERFACE_MODE_MII; + else + return PHY_INTERFACE_MODE_NONE; + } + + if (port == FM1_DTSEC5) { + if ((rcwsr13 & FSL_CORENET_RCWSR13_EC2) == + FSL_CORENET_RCWSR13_EC2_FM1_DTSEC5_RGMII) + return PHY_INTERFACE_MODE_RGMII; + else if ((rcwsr13 & FSL_CORENET_RCWSR13_EC2) == + FSL_CORENET_RCWSR13_EC2_FM1_DTSEC5_MII) + return PHY_INTERFACE_MODE_MII; + else + return PHY_INTERFACE_MODE_NONE; + } + + switch (port) { + case FM1_DTSEC1: + case FM1_DTSEC2: + if (is_serdes_configured(QSGMII_SW1_A + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_QSGMII; + case FM1_DTSEC3: + case FM1_DTSEC4: + case FM1_DTSEC5: + if (is_serdes_configured(SGMII_FM1_DTSEC1 + port - FM1_DTSEC1)) + return PHY_INTERFACE_MODE_SGMII; + break; + default: + return PHY_INTERFACE_MODE_NONE; + } + return PHY_INTERFACE_MODE_NONE; } diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index bb5044b..262b67b 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -261,6 +261,10 @@ static int setup_phy(struct eth_device *dev) phydev->dev->name); return 0; } + if (!phydev->link) { + printf("%s: No link.\n", phydev->dev->name); + return 0; + } switch (phydev->speed) { case 1000: diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 6a017a8..381bca4 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -339,6 +339,11 @@ static int zynq_gem_init(struct eth_device *dev, bd_t * bis) phy_config(phydev); phy_startup(phydev); + if (!phydev->link) { + printf("%s: No link.\n", phydev->dev->name); + return -1; + } + switch (phydev->speed) { case SPEED_1000: writel(ZYNQ_GEM_NWCFG_INIT | ZYNQ_GEM_NWCFG_SPEED1000, diff --git a/drivers/pci/fsl_pci_init.c b/drivers/pci/fsl_pci_init.c index 2085cd6..6317fb1 100644 --- a/drivers/pci/fsl_pci_init.c +++ b/drivers/pci/fsl_pci_init.c @@ -510,8 +510,8 @@ void fsl_pci_init(struct pci_controller *hose, struct fsl_pci_info *pci_info) /* Print the negotiated PCIe link width */ pci_hose_read_config_word(hose, dev, pci_lsr, &temp16); - printf("x%d, regs @ 0x%lx\n", (temp16 & 0x3f0 ) >> 4, - pci_info->regs); + printf("x%d gen%d, regs @ 0x%lx\n", (temp16 & 0x3f0) >> 4, + (temp16 & 0xf), pci_info->regs); hose->current_busno++; /* Start scan with secondary */ pciauto_prescan_setup_bridge(hose, dev, hose->current_busno); diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 6b4cade..5eb4601 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_ZYNQ_SERIAL) += serial_zynq.o obj-$(CONFIG_BFIN_SERIAL) += serial_bfin.o obj-$(CONFIG_FSL_LPUART) += serial_lpuart.o obj-$(CONFIG_MXS_AUART) += mxs_auart.o +obj-$(CONFIG_ARC_SERIAL) += serial_arc.o ifndef CONFIG_SPL_BUILD obj-$(CONFIG_USB_TTY) += usbtty.o diff --git a/drivers/serial/opencores_yanu.c b/drivers/serial/opencores_yanu.c index 8de2eca..d4ed60c 100644 --- a/drivers/serial/opencores_yanu.c +++ b/drivers/serial/opencores_yanu.c @@ -8,6 +8,7 @@ #include <watchdog.h> #include <asm/io.h> #include <nios2-yanu.h> +#include <serial.h> DECLARE_GLOBAL_DATA_PTR; @@ -17,62 +18,34 @@ DECLARE_GLOBAL_DATA_PTR; static yanu_uart_t *uart = (yanu_uart_t *)CONFIG_SYS_NIOS_CONSOLE; -#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) - -/* Everything's already setup for fixed-baud PTF assignment*/ - static void oc_serial_setbrg(void) { int n, k; const unsigned max_uns = 0xFFFFFFFF; unsigned best_n, best_m, baud; + unsigned baudrate; - /* compute best N and M couple */ - best_n = YANU_MAX_PRESCALER_N; - for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) { - if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >= - (unsigned)CONFIG_BAUDRATE) { - best_n = n; - break; - } - } - for (k = 0;; k++) { - if ((unsigned)CONFIG_BAUDRATE <= (max_uns >> (15+n-k))) - break; - } - best_m = - ((unsigned)CONFIG_BAUDRATE * (1 << (15 + n - k))) / - ((unsigned)CONFIG_SYS_CLK_FREQ >> k); - - baud = best_m + best_n * YANU_BAUDE; - writel(baud, &uart->baud); - - return; -} - +#if defined(CONFIG_SYS_NIOS_FIXEDBAUD) + /* Everything's already setup for fixed-baud PTF assignment */ + baudrate = CONFIG_BAUDRATE; #else - -static void oc_serial_setbrg(void) -{ - int n, k; - const unsigned max_uns = 0xFFFFFFFF; - unsigned best_n, best_m, baud; - + baudrate = gd->baudrate; +#endif /* compute best N and M couple */ best_n = YANU_MAX_PRESCALER_N; for (n = YANU_MAX_PRESCALER_N; n >= 0; n--) { if ((unsigned)CONFIG_SYS_CLK_FREQ / (1 << (n + 4)) >= - gd->baudrate) { + baudrate) { best_n = n; break; } } for (k = 0;; k++) { - if (gd->baudrate <= (max_uns >> (15+n-k))) + if (baudrate <= (max_uns >> (15+n-k))) break; } best_m = - (gd->baudrate * (1 << (15 + n - k))) / + (baudrate * (1 << (15 + n - k))) / ((unsigned)CONFIG_SYS_CLK_FREQ >> k); baud = best_m + best_n * YANU_BAUDE; @@ -81,9 +54,6 @@ static void oc_serial_setbrg(void) return; } - -#endif /* CONFIG_SYS_NIOS_FIXEDBAUD */ - static int oc_serial_init(void) { unsigned action,control; @@ -154,7 +124,7 @@ static int oc_serial_tstc(void) ((1 << YANU_RFIFO_CHARS_N) - 1)) > 0); } -statoc int oc_serial_getc(void) +static int oc_serial_getc(void) { while (serial_tstc() == 0) WATCHDOG_RESET (); diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c index df2b84a..05cb369 100644 --- a/drivers/serial/serial.c +++ b/drivers/serial/serial.c @@ -160,6 +160,7 @@ serial_initfunc(sa1100_serial_initialize); serial_initfunc(sh_serial_initialize); serial_initfunc(arm_dcc_initialize); serial_initfunc(mxs_auart_initialize); +serial_initfunc(arc_serial_initialize); /** * serial_register() - Register serial driver with serial driver core @@ -253,6 +254,7 @@ void serial_initialize(void) sh_serial_initialize(); arm_dcc_initialize(); mxs_auart_initialize(); + arc_serial_initialize(); serial_assign(default_serial_console()->name); } diff --git a/drivers/serial/serial_arc.c b/drivers/serial/serial_arc.c new file mode 100644 index 0000000..e63d25d --- /dev/null +++ b/drivers/serial/serial_arc.c @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2013 Synopsys, Inc. (www.synopsys.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <common.h> +#include <serial.h> + +DECLARE_GLOBAL_DATA_PTR; + +struct arc_serial_regs { + unsigned int id0; + unsigned int id1; + unsigned int id2; + unsigned int id3; + unsigned int data; + unsigned int status; + unsigned int baudl; + unsigned int baudh; +}; + +/* Bit definitions of STATUS register */ +#define UART_RXEMPTY (1 << 5) +#define UART_OVERFLOW_ERR (1 << 1) +#define UART_TXEMPTY (1 << 7) + +struct arc_serial_regs *regs; + +static void arc_serial_setbrg(void) +{ + int arc_console_baud; + + if (!gd->baudrate) + gd->baudrate = CONFIG_BAUDRATE; + + arc_console_baud = gd->cpu_clk / (gd->baudrate * 4) - 1; + writel(arc_console_baud & 0xff, ®s->baudl); + writel((arc_console_baud & 0xff00) >> 8, ®s->baudh); +} + +static int arc_serial_init(void) +{ + regs = (struct arc_serial_regs *)CONFIG_ARC_UART_BASE; + serial_setbrg(); + return 0; +} + +static void arc_serial_putc(const char c) +{ + if (c == '\n') + arc_serial_putc('\r'); + + while (!(readl(®s->status) & UART_TXEMPTY)) + ; + + writel(c, ®s->data); +} + +static int arc_serial_tstc(void) +{ + return !(readl(®s->status) & UART_RXEMPTY); +} + +static int arc_serial_getc(void) +{ + while (!arc_serial_tstc()) + ; + + /* Check for overflow errors */ + if (readl(®s->status) & UART_OVERFLOW_ERR) + return 0; + + return readl(®s->data) & 0xFF; +} + +static void arc_serial_puts(const char *s) +{ + while (*s) + arc_serial_putc(*s++); +} + +static struct serial_device arc_serial_drv = { + .name = "arc_serial", + .start = arc_serial_init, + .stop = NULL, + .setbrg = arc_serial_setbrg, + .putc = arc_serial_putc, + .puts = arc_serial_puts, + .getc = arc_serial_getc, + .tstc = arc_serial_tstc, +}; + +void arc_serial_initialize(void) +{ + serial_register(&arc_serial_drv); +} + +__weak struct serial_device *default_serial_console(void) +{ + return &arc_serial_drv; +} diff --git a/drivers/serial/serial_xuartlite.c b/drivers/serial/serial_xuartlite.c index e613994..988438e 100644 --- a/drivers/serial/serial_xuartlite.c +++ b/drivers/serial/serial_xuartlite.c @@ -18,10 +18,14 @@ #define SR_RX_FIFO_VALID_DATA 0x01 /* data in receive FIFO */ #define SR_RX_FIFO_FULL 0x02 /* receive FIFO full */ +#define ULITE_CONTROL_RST_TX 0x01 +#define ULITE_CONTROL_RST_RX 0x02 + struct uartlite { unsigned int rx_fifo; unsigned int tx_fifo; unsigned int status; + unsigned int control; }; static struct uartlite *userial_ports[4] = { @@ -75,8 +79,16 @@ static int uartlite_serial_tstc(const int port) static int uartlite_serial_init(const int port) { - if (userial_ports[port]) + struct uartlite *regs = userial_ports[port]; + + if (regs) { + out_be32(®s->control, 0); + out_be32(®s->control, + ULITE_CONTROL_RST_RX | ULITE_CONTROL_RST_TX); + in_be32(®s->control); return 0; + } + return -1; } diff --git a/drivers/serial/usbtty.h b/drivers/serial/usbtty.h index 819dec6..21a3ef4 100644 --- a/drivers/serial/usbtty.h +++ b/drivers/serial/usbtty.h @@ -20,8 +20,8 @@ #include <usb/pxa27x_udc.h> #elif defined(CONFIG_DW_UDC) #include <usb/designware_udc.h> -#elif defined(CONFIG_MV_UDC) -#include <usb/mv_udc.h> +#elif defined(CONFIG_CI_UDC) +#include <usb/ci_udc.h> #endif #include <usb/udc.h> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index f13b172..804a2bd 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -21,7 +21,7 @@ endif ifdef CONFIG_USB_ETHER obj-y += ether.o obj-$(CONFIG_USB_ETH_RNDIS) += rndis.o -obj-$(CONFIG_MV_UDC) += mv_udc.o +obj-$(CONFIG_CI_UDC) += ci_udc.o obj-$(CONFIG_CPU_PXA25X) += pxa25x_udc.o else # Devices not related to the new gadget layer depend on CONFIG_USB_DEVICE diff --git a/drivers/usb/gadget/mv_udc.c b/drivers/usb/gadget/ci_udc.c index da41738..14b1e9b 100644 --- a/drivers/usb/gadget/mv_udc.c +++ b/drivers/usb/gadget/ci_udc.c @@ -20,9 +20,9 @@ #include <linux/types.h> #include <linux/usb/ch9.h> #include <linux/usb/gadget.h> -#include <usb/mv_udc.h> +#include <usb/ci_udc.h> #include "../host/ehci.h" -#include "mv_udc.h" +#include "ci_udc.h" /* * Check if the system has too long cachelines. If the cachelines are @@ -70,85 +70,85 @@ static struct usb_endpoint_descriptor ep0_in_desc = { .bmAttributes = USB_ENDPOINT_XFER_CONTROL, }; -static int mv_pullup(struct usb_gadget *gadget, int is_on); -static int mv_ep_enable(struct usb_ep *ep, +static int ci_pullup(struct usb_gadget *gadget, int is_on); +static int ci_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc); -static int mv_ep_disable(struct usb_ep *ep); -static int mv_ep_queue(struct usb_ep *ep, +static int ci_ep_disable(struct usb_ep *ep); +static int ci_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags); static struct usb_request * -mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); -static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req); +ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags); +static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req); -static struct usb_gadget_ops mv_udc_ops = { - .pullup = mv_pullup, +static struct usb_gadget_ops ci_udc_ops = { + .pullup = ci_pullup, }; -static struct usb_ep_ops mv_ep_ops = { - .enable = mv_ep_enable, - .disable = mv_ep_disable, - .queue = mv_ep_queue, - .alloc_request = mv_ep_alloc_request, - .free_request = mv_ep_free_request, +static struct usb_ep_ops ci_ep_ops = { + .enable = ci_ep_enable, + .disable = ci_ep_disable, + .queue = ci_ep_queue, + .alloc_request = ci_ep_alloc_request, + .free_request = ci_ep_free_request, }; /* Init values for USB endpoints. */ -static const struct usb_ep mv_ep_init[2] = { +static const struct usb_ep ci_ep_init[2] = { [0] = { /* EP 0 */ .maxpacket = 64, .name = "ep0", - .ops = &mv_ep_ops, + .ops = &ci_ep_ops, }, [1] = { /* EP 1..n */ .maxpacket = 512, .name = "ep-", - .ops = &mv_ep_ops, + .ops = &ci_ep_ops, }, }; -static struct mv_drv controller = { +static struct ci_drv controller = { .gadget = { - .name = "mv_udc", - .ops = &mv_udc_ops, + .name = "ci_udc", + .ops = &ci_udc_ops, .is_dualspeed = 1, }, }; /** - * mv_get_qh() - return queue head for endpoint + * ci_get_qh() - return queue head for endpoint * @ep_num: Endpoint number * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) * * This function returns the QH associated with particular endpoint * and it's direction. */ -static struct ept_queue_head *mv_get_qh(int ep_num, int dir_in) +static struct ept_queue_head *ci_get_qh(int ep_num, int dir_in) { return &controller.epts[(ep_num * 2) + dir_in]; } /** - * mv_get_qtd() - return queue item for endpoint + * ci_get_qtd() - return queue item for endpoint * @ep_num: Endpoint number * @dir_in: Direction of the endpoint (IN = 1, OUT = 0) * * This function returns the QH associated with particular endpoint * and it's direction. */ -static struct ept_queue_item *mv_get_qtd(int ep_num, int dir_in) +static struct ept_queue_item *ci_get_qtd(int ep_num, int dir_in) { return controller.items[(ep_num * 2) + dir_in]; } /** - * mv_flush_qh - flush cache over queue head + * ci_flush_qh - flush cache over queue head * @ep_num: Endpoint number * * This function flushes cache over QH for particular endpoint. */ -static void mv_flush_qh(int ep_num) +static void ci_flush_qh(int ep_num) { - struct ept_queue_head *head = mv_get_qh(ep_num, 0); + struct ept_queue_head *head = ci_get_qh(ep_num, 0); const uint32_t start = (uint32_t)head; const uint32_t end = start + 2 * sizeof(*head); @@ -156,14 +156,14 @@ static void mv_flush_qh(int ep_num) } /** - * mv_invalidate_qh - invalidate cache over queue head + * ci_invalidate_qh - invalidate cache over queue head * @ep_num: Endpoint number * * This function invalidates cache over QH for particular endpoint. */ -static void mv_invalidate_qh(int ep_num) +static void ci_invalidate_qh(int ep_num) { - struct ept_queue_head *head = mv_get_qh(ep_num, 0); + struct ept_queue_head *head = ci_get_qh(ep_num, 0); uint32_t start = (uint32_t)head; uint32_t end = start + 2 * sizeof(*head); @@ -171,14 +171,14 @@ static void mv_invalidate_qh(int ep_num) } /** - * mv_flush_qtd - flush cache over queue item + * ci_flush_qtd - flush cache over queue item * @ep_num: Endpoint number * * This function flushes cache over qTD pair for particular endpoint. */ -static void mv_flush_qtd(int ep_num) +static void ci_flush_qtd(int ep_num) { - struct ept_queue_item *item = mv_get_qtd(ep_num, 0); + struct ept_queue_item *item = ci_get_qtd(ep_num, 0); const uint32_t start = (uint32_t)item; const uint32_t end_raw = start + 2 * sizeof(*item); const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN); @@ -187,14 +187,14 @@ static void mv_flush_qtd(int ep_num) } /** - * mv_invalidate_qtd - invalidate cache over queue item + * ci_invalidate_qtd - invalidate cache over queue item * @ep_num: Endpoint number * * This function invalidates cache over qTD pair for particular endpoint. */ -static void mv_invalidate_qtd(int ep_num) +static void ci_invalidate_qtd(int ep_num) { - struct ept_queue_item *item = mv_get_qtd(ep_num, 0); + struct ept_queue_item *item = ci_get_qtd(ep_num, 0); const uint32_t start = (uint32_t)item; const uint32_t end_raw = start + 2 * sizeof(*item); const uint32_t end = roundup(end_raw, ARCH_DMA_MINALIGN); @@ -203,20 +203,20 @@ static void mv_invalidate_qtd(int ep_num) } static struct usb_request * -mv_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) +ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags) { - struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); - return &mv_ep->req; + struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); + return &ci_ep->req; } -static void mv_ep_free_request(struct usb_ep *ep, struct usb_request *_req) +static void ci_ep_free_request(struct usb_ep *ep, struct usb_request *_req) { return; } static void ep_enable(int num, int in, int maxpacket) { - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; unsigned n; n = readl(&udc->epctrl[num]); @@ -226,22 +226,22 @@ static void ep_enable(int num, int in, int maxpacket) n |= (CTRL_RXE | CTRL_RXR | CTRL_RXT_BULK); if (num != 0) { - struct ept_queue_head *head = mv_get_qh(num, in); + struct ept_queue_head *head = ci_get_qh(num, in); head->config = CONFIG_MAX_PKT(maxpacket) | CONFIG_ZLT; - mv_flush_qh(num); + ci_flush_qh(num); } writel(n, &udc->epctrl[num]); } -static int mv_ep_enable(struct usb_ep *ep, +static int ci_ep_enable(struct usb_ep *ep, const struct usb_endpoint_descriptor *desc) { - struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); + struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); int num, in; num = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; in = (desc->bEndpointAddress & USB_DIR_IN) != 0; - mv_ep->desc = desc; + ci_ep->desc = desc; if (num) { int max = get_unaligned_le16(&desc->wMaxPacketSize); @@ -259,15 +259,15 @@ static int mv_ep_enable(struct usb_ep *ep, return 0; } -static int mv_ep_disable(struct usb_ep *ep) +static int ci_ep_disable(struct usb_ep *ep) { - struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); + struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); - mv_ep->desc = NULL; + ci_ep->desc = NULL; return 0; } -static int mv_bounce(struct mv_ep *ep, int in) +static int ci_bounce(struct ci_ep *ep, int in) { uint32_t addr = (uint32_t)ep->req.buf; uint32_t ba; @@ -306,7 +306,7 @@ flush: return 0; } -static void mv_debounce(struct mv_ep *ep, int in) +static void ci_debounce(struct ci_ep *ep, int in) { uint32_t addr = (uint32_t)ep->req.buf; uint32_t ba = (uint32_t)ep->b_buf; @@ -328,36 +328,36 @@ free: free(ep->b_buf); } -static int mv_ep_queue(struct usb_ep *ep, +static int ci_ep_queue(struct usb_ep *ep, struct usb_request *req, gfp_t gfp_flags) { - struct mv_ep *mv_ep = container_of(ep, struct mv_ep, ep); - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_ep *ci_ep = container_of(ep, struct ci_ep, ep); + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; struct ept_queue_item *item; struct ept_queue_head *head; int bit, num, len, in, ret; - num = mv_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; - in = (mv_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; - item = mv_get_qtd(num, in); - head = mv_get_qh(num, in); + num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0; + item = ci_get_qtd(num, in); + head = ci_get_qh(num, in); len = req->length; - ret = mv_bounce(mv_ep, in); + ret = ci_bounce(ci_ep, in); if (ret) return ret; item->next = TERMINATE; item->info = INFO_BYTES(len) | INFO_IOC | INFO_ACTIVE; - item->page0 = (uint32_t)mv_ep->b_buf; - item->page1 = ((uint32_t)mv_ep->b_buf & 0xfffff000) + 0x1000; - mv_flush_qtd(num); + item->page0 = (uint32_t)ci_ep->b_buf; + item->page1 = ((uint32_t)ci_ep->b_buf & 0xfffff000) + 0x1000; + ci_flush_qtd(num); head->next = (unsigned) item; head->info = 0; DBG("ept%d %s queue len %x, buffer %p\n", - num, in ? "in" : "out", len, mv_ep->b_buf); - mv_flush_qh(num); + num, in ? "in" : "out", len, ci_ep->b_buf); + ci_flush_qh(num); if (in) bit = EPT_TX(num); @@ -369,7 +369,7 @@ static int mv_ep_queue(struct usb_ep *ep, return 0; } -static void handle_ep_complete(struct mv_ep *ep) +static void handle_ep_complete(struct ci_ep *ep) { struct ept_queue_item *item; int num, in, len; @@ -377,8 +377,8 @@ static void handle_ep_complete(struct mv_ep *ep) in = (ep->desc->bEndpointAddress & USB_DIR_IN) != 0; if (num == 0) ep->desc = &ep0_out_desc; - item = mv_get_qtd(num, in); - mv_invalidate_qtd(num); + item = ci_get_qtd(num, in); + ci_invalidate_qtd(num); if (item->info & 0xff) printf("EP%d/%s FAIL info=%x pg0=%x\n", @@ -386,7 +386,7 @@ static void handle_ep_complete(struct mv_ep *ep) len = (item->info >> 16) & 0x7fff; ep->req.length -= len; - mv_debounce(ep, in); + ci_debounce(ep, in); DBG("ept%d %s complete %x\n", num, in ? "in" : "out", len); @@ -403,15 +403,15 @@ static void handle_ep_complete(struct mv_ep *ep) static void handle_setup(void) { struct usb_request *req = &controller.ep[0].req; - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; struct ept_queue_head *head; struct usb_ctrlrequest r; int status = 0; int num, in, _num, _in, i; char *buf; - head = mv_get_qh(0, 0); /* EP0 OUT */ + head = ci_get_qh(0, 0); /* EP0 OUT */ - mv_invalidate_qh(0); + ci_invalidate_qh(0); memcpy(&r, head->setup_data, sizeof(struct usb_ctrlrequest)); writel(EPT_RX(0), &udc->epstat); DBG("handle setup %s, %x, %x index %x value %x\n", reqname(r.bRequest), @@ -425,7 +425,7 @@ static void handle_setup(void) if ((r.wValue == 0) && (r.wLength == 0)) { req->length = 0; for (i = 0; i < NUM_ENDPOINTS; i++) { - struct mv_ep *ep = &controller.ep[i]; + struct ci_ep *ep = &controller.ep[i]; if (!ep->desc) continue; @@ -478,7 +478,7 @@ static void stop_activity(void) { int i, num, in; struct ept_queue_head *head; - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; writel(readl(&udc->epcomp), &udc->epcomp); writel(readl(&udc->epstat), &udc->epstat); writel(0xffffffff, &udc->epflush); @@ -492,16 +492,16 @@ static void stop_activity(void) & USB_ENDPOINT_NUMBER_MASK; in = (controller.ep[i].desc->bEndpointAddress & USB_DIR_IN) != 0; - head = mv_get_qh(num, in); + head = ci_get_qh(num, in); head->info = INFO_ACTIVE; - mv_flush_qh(num); + ci_flush_qh(num); } } } void udc_irq(void) { - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; unsigned n = readl(&udc->usbsts); writel(n, &udc->usbsts); int bit, i, num, in; @@ -563,7 +563,7 @@ void udc_irq(void) int usb_gadget_handle_interrupts(void) { u32 value; - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; value = readl(&udc->usbsts); if (value) @@ -572,9 +572,9 @@ int usb_gadget_handle_interrupts(void) return value; } -static int mv_pullup(struct usb_gadget *gadget, int is_on) +static int ci_pullup(struct usb_gadget *gadget, int is_on) { - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; if (is_on) { /* RESET */ writel(USBCMD_ITC(MICRO_8FRAME) | USBCMD_RST, &udc->usbcmd); @@ -602,7 +602,7 @@ static int mv_pullup(struct usb_gadget *gadget, int is_on) void udc_disconnect(void) { - struct mv_udc *udc = (struct mv_udc *)controller.ctrl->hcor; + struct ci_udc *udc = (struct ci_udc *)controller.ctrl->hcor; /* disable pullup */ stop_activity(); writel(USBCMD_FS2, &udc->usbcmd); @@ -611,7 +611,7 @@ void udc_disconnect(void) controller.driver->disconnect(&controller.gadget); } -static int mvudc_probe(void) +static int ci_udc_probe(void) { struct ept_queue_head *head; uint8_t *imem; @@ -673,23 +673,23 @@ static int mvudc_probe(void) controller.items[i] = (struct ept_queue_item *)imem; if (i & 1) { - mv_flush_qh(i - 1); - mv_flush_qtd(i - 1); + ci_flush_qh(i - 1); + ci_flush_qtd(i - 1); } } INIT_LIST_HEAD(&controller.gadget.ep_list); /* Init EP 0 */ - memcpy(&controller.ep[0].ep, &mv_ep_init[0], sizeof(*mv_ep_init)); + memcpy(&controller.ep[0].ep, &ci_ep_init[0], sizeof(*ci_ep_init)); controller.ep[0].desc = &ep0_in_desc; controller.gadget.ep0 = &controller.ep[0].ep; INIT_LIST_HEAD(&controller.gadget.ep0->ep_list); /* Init EP 1..n */ for (i = 1; i < NUM_ENDPOINTS; i++) { - memcpy(&controller.ep[i].ep, &mv_ep_init[1], - sizeof(*mv_ep_init)); + memcpy(&controller.ep[i].ep, &ci_ep_init[1], + sizeof(*ci_ep_init)); list_add_tail(&controller.ep[i].ep.ep_list, &controller.gadget.ep_list); } @@ -699,7 +699,7 @@ static int mvudc_probe(void) int usb_gadget_register_driver(struct usb_gadget_driver *driver) { - struct mv_udc *udc; + struct ci_udc *udc; int ret; if (!driver) @@ -713,9 +713,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) if (ret) return ret; - ret = mvudc_probe(); + ret = ci_udc_probe(); if (!ret) { - udc = (struct mv_udc *)controller.ctrl->hcor; + udc = (struct ci_udc *)controller.ctrl->hcor; /* select ULPI phy */ writel(PTS(PTS_ENABLE) | PFSC, &udc->portsc); diff --git a/drivers/usb/gadget/mv_udc.h b/drivers/usb/gadget/ci_udc.h index c7d8b33..42f6ef4 100644 --- a/drivers/usb/gadget/mv_udc.h +++ b/drivers/usb/gadget/ci_udc.h @@ -3,12 +3,12 @@ * * Licensed under the GPL-2 or later. */ -#ifndef __GADGET__MV_UDC_H__ -#define __GADGET__MV_UDC_H__ +#ifndef __GADGET__CI_UDC_H__ +#define __GADGET__CI_UDC_H__ #define NUM_ENDPOINTS 6 -struct mv_udc { +struct ci_udc { #define MICRO_8FRAME 0x8 #define USBCMD_ITC(x) ((((x) > 0xff) ? 0xff : x) << 16) #define USBCMD_FS2 (1 << 15) @@ -48,7 +48,7 @@ struct mv_udc { u32 epctrl[16]; /* 0x1c0 */ }; -struct mv_ep { +struct ci_ep { struct usb_ep ep; struct list_head queue; const struct usb_endpoint_descriptor *desc; @@ -59,14 +59,14 @@ struct mv_ep { uint8_t b_fast[64] __aligned(ARCH_DMA_MINALIGN); }; -struct mv_drv { +struct ci_drv { struct usb_gadget gadget; struct usb_gadget_driver *driver; struct ehci_ctrl *ctrl; struct ept_queue_head *epts; struct ept_queue_item *items[2 * NUM_ENDPOINTS]; uint8_t *items_mem; - struct mv_ep ep[NUM_ENDPOINTS]; + struct ci_ep ep[NUM_ENDPOINTS]; }; struct ept_queue_head { diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index b1fe8bd..f896169 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -2515,7 +2515,7 @@ static struct fsg_common *fsg_common_init(struct fsg_common *common, buffhds_first_it: bh->inreq_busy = 0; bh->outreq_busy = 0; - bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); + bh->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, FSG_BUFLEN); if (unlikely(!bh->buf)) { rc = -ENOMEM; goto error_release; @@ -2622,7 +2622,7 @@ usb_copy_descriptors(struct usb_descriptor_header **src) bytes += (*tmp)->bLength; bytes += (n_desc + 1) * sizeof(*tmp); - mem = kmalloc(bytes, GFP_KERNEL); + mem = memalign(CONFIG_SYS_CACHELINE_SIZE, bytes); if (!mem) return NULL; diff --git a/drivers/usb/gadget/f_thor.c b/drivers/usb/gadget/f_thor.c index c4c9909..f5c0224 100644 --- a/drivers/usb/gadget/f_thor.c +++ b/drivers/usb/gadget/f_thor.c @@ -614,7 +614,7 @@ static struct usb_request *thor_start_ep(struct usb_ep *ep) { struct usb_request *req; - req = alloc_ep_req(ep, ep->maxpacket); + req = alloc_ep_req(ep, THOR_PACKET_SIZE); debug("%s: ep:%p req:%p\n", __func__, ep, req); if (!req) @@ -623,8 +623,6 @@ static struct usb_request *thor_start_ep(struct usb_ep *ep) memset(req->buf, 0, req->length); req->complete = thor_rx_tx_complete; - memset(req->buf, 0x55, req->length); - return req; } diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index aa54b85..cc94771 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -144,10 +144,10 @@ #define gadget_is_m66592(g) 0 #endif -#ifdef CONFIG_MV_UDC -#define gadget_is_mv(g) (!strcmp("mv_udc", (g)->name)) +#ifdef CONFIG_CI_UDC +#define gadget_is_ci(g) (!strcmp("ci_udc", (g)->name)) #else -#define gadget_is_mv(g) 0 +#define gadget_is_ci(g) 0 #endif #ifdef CONFIG_USB_GADGET_FOTG210 @@ -219,7 +219,7 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x19; else if (gadget_is_m66592(gadget)) return 0x20; - else if (gadget_is_mv(gadget)) + else if (gadget_is_ci(gadget)) return 0x21; else if (gadget_is_fotg210(gadget)) return 0x22; diff --git a/drivers/usb/gadget/s3c_udc_otg.c b/drivers/usb/gadget/s3c_udc_otg.c index ba17a04..63d4487 100644 --- a/drivers/usb/gadget/s3c_udc_otg.c +++ b/drivers/usb/gadget/s3c_udc_otg.c @@ -843,7 +843,7 @@ static struct s3c_udc memory = { int s3c_udc_probe(struct s3c_plat_otg_data *pdata) { struct s3c_udc *dev = &memory; - int retval = 0, i; + int retval = 0; debug("%s: %p\n", __func__, pdata); @@ -864,16 +864,15 @@ int s3c_udc_probe(struct s3c_plat_otg_data *pdata) the_controller = dev; - for (i = 0; i < S3C_MAX_ENDPOINTS+1; i++) { - dev->dma_buf[i] = memalign(CONFIG_SYS_CACHELINE_SIZE, - DMA_BUFFER_SIZE); - dev->dma_addr[i] = (dma_addr_t) dev->dma_buf[i]; - invalidate_dcache_range((unsigned long) dev->dma_buf[i], - (unsigned long) (dev->dma_buf[i] - + DMA_BUFFER_SIZE)); + usb_ctrl = memalign(CONFIG_SYS_CACHELINE_SIZE, + ROUND(sizeof(struct usb_ctrlrequest), + CONFIG_SYS_CACHELINE_SIZE)); + if (!usb_ctrl) { + error("No memory available for UDC!\n"); + return -ENOMEM; } - usb_ctrl = dev->dma_buf[0]; - usb_ctrl_dma_addr = dev->dma_addr[0]; + + usb_ctrl_dma_addr = (dma_addr_t) usb_ctrl; udc_reinit(dev); diff --git a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c index 1cbf8f6..06dfeed 100644 --- a/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c +++ b/drivers/usb/gadget/s3c_udc_otg_xfer_dma.c @@ -29,10 +29,6 @@ static inline void s3c_udc_ep0_zlp(struct s3c_udc *dev) { u32 ep_ctrl; - flush_dcache_range((unsigned long) usb_ctrl_dma_addr, - (unsigned long) usb_ctrl_dma_addr - + DMA_BUFFER_SIZE); - writel(usb_ctrl_dma_addr, ®->in_endp[EP0_CON].diepdma); writel(DIEPT_SIZ_PKT_CNT(1), ®->in_endp[EP0_CON].dieptsiz); @@ -52,10 +48,6 @@ void s3c_udc_pre_setup(void) debug_cond(DEBUG_IN_EP, "%s : Prepare Setup packets.\n", __func__); - invalidate_dcache_range((unsigned long) usb_ctrl_dma_addr, - (unsigned long) usb_ctrl_dma_addr - + DMA_BUFFER_SIZE); - writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), ®->out_endp[EP0_CON].doeptsiz); writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); @@ -82,10 +74,6 @@ static inline void s3c_ep0_complete_out(void) debug_cond(DEBUG_IN_EP, "%s : Prepare Complete Out packet.\n", __func__); - invalidate_dcache_range((unsigned long) usb_ctrl_dma_addr, - (unsigned long) usb_ctrl_dma_addr - + DMA_BUFFER_SIZE); - writel(DOEPT_SIZ_PKT_CNT(1) | sizeof(struct usb_ctrlrequest), ®->out_endp[EP0_CON].doeptsiz); writel(usb_ctrl_dma_addr, ®->out_endp[EP0_CON].doepdma); @@ -109,27 +97,20 @@ static int setdma_rx(struct s3c_ep *ep, struct s3c_request *req) u32 ep_num = ep_index(ep); buf = req->req.buf + req->req.actual; - - length = min(req->req.length - req->req.actual, (int)ep->ep.maxpacket); + length = min(req->req.length - req->req.actual, + ep_num ? DMA_BUFFER_SIZE : ep->ep.maxpacket); ep->len = length; ep->dma_buf = buf; - invalidate_dcache_range((unsigned long) ep->dev->dma_buf[ep_num], - (unsigned long) ep->dev->dma_buf[ep_num] - + ROUND(ep->ep.maxpacket, - CONFIG_SYS_CACHELINE_SIZE)); - - if (length == 0) + if (ep_num == EP0_CON || length == 0) pktcnt = 1; else pktcnt = (length - 1)/(ep->ep.maxpacket) + 1; - pktcnt = 1; ctrl = readl(®->out_endp[ep_num].doepctl); - writel(the_controller->dma_addr[ep_index(ep)+1], - ®->out_endp[ep_num].doepdma); + writel((unsigned int) ep->dma_buf, ®->out_endp[ep_num].doepdma); writel(DOEPT_SIZ_PKT_CNT(pktcnt) | DOEPT_SIZ_XFER_SIZE(length), ®->out_endp[ep_num].doeptsiz); writel(DEPCTL_EPENA|DEPCTL_CNAK|ctrl, ®->out_endp[ep_num].doepctl); @@ -152,7 +133,6 @@ int setdma_tx(struct s3c_ep *ep, struct s3c_request *req) u32 *buf, ctrl = 0; u32 length, pktcnt; u32 ep_num = ep_index(ep); - u32 *p = the_controller->dma_buf[ep_index(ep)+1]; buf = req->req.buf + req->req.actual; length = req->req.length - req->req.actual; @@ -162,10 +142,10 @@ int setdma_tx(struct s3c_ep *ep, struct s3c_request *req) ep->len = length; ep->dma_buf = buf; - memcpy(p, ep->dma_buf, length); - flush_dcache_range((unsigned long) p , - (unsigned long) p + DMA_BUFFER_SIZE); + flush_dcache_range((unsigned long) ep->dma_buf, + (unsigned long) ep->dma_buf + + ROUND(ep->len, CONFIG_SYS_CACHELINE_SIZE)); if (length == 0) pktcnt = 1; @@ -178,8 +158,7 @@ int setdma_tx(struct s3c_ep *ep, struct s3c_request *req) while (readl(®->grstctl) & TX_FIFO_FLUSH) ; - writel(the_controller->dma_addr[ep_index(ep)+1], - ®->in_endp[ep_num].diepdma); + writel((unsigned long) ep->dma_buf, ®->in_endp[ep_num].diepdma); writel(DIEPT_SIZ_PKT_CNT(pktcnt) | DIEPT_SIZ_XFER_SIZE(length), ®->in_endp[ep_num].dieptsiz); @@ -212,7 +191,6 @@ static void complete_rx(struct s3c_udc *dev, u8 ep_num) struct s3c_ep *ep = &dev->ep[ep_num]; struct s3c_request *req = NULL; u32 ep_tsr = 0, xfer_size = 0, is_short = 0; - u32 *p = the_controller->dma_buf[ep_index(ep)+1]; if (list_empty(&ep->queue)) { debug_cond(DEBUG_OUT_EP != 0, @@ -232,10 +210,23 @@ static void complete_rx(struct s3c_udc *dev, u8 ep_num) xfer_size = ep->len - xfer_size; - invalidate_dcache_range((unsigned long) p, - (unsigned long) p + DMA_BUFFER_SIZE); - - memcpy(ep->dma_buf, p, ep->len); + /* + * NOTE: + * + * Please be careful with proper buffer allocation for USB request, + * which needs to be aligned to CONFIG_SYS_CACHELINE_SIZE, not only + * with starting address, but also its size shall be a cache line + * multiplication. + * + * This will prevent from corruption of data allocated immediatelly + * before or after the buffer. + * + * For armv7, the cache_v7.c provides proper code to emit "ERROR" + * message to warn users. + */ + invalidate_dcache_range((unsigned long) ep->dma_buf, + (unsigned long) ep->dma_buf + + ROUND(xfer_size, CONFIG_SYS_CACHELINE_SIZE)); req->req.actual += min(xfer_size, req->req.length - req->req.actual); is_short = (xfer_size < ep->ep.maxpacket); @@ -729,19 +720,14 @@ static int write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req) int s3c_fifo_read(struct s3c_ep *ep, u32 *cp, int max) { - u32 bytes; - - bytes = sizeof(struct usb_ctrlrequest); - - invalidate_dcache_range((unsigned long) ep->dev->dma_buf[ep_index(ep)], - (unsigned long) ep->dev->dma_buf[ep_index(ep)] - + DMA_BUFFER_SIZE); + invalidate_dcache_range((unsigned long)cp, (unsigned long)cp + + ROUND(max, CONFIG_SYS_CACHELINE_SIZE)); debug_cond(DEBUG_EP0 != 0, - "%s: bytes=%d, ep_index=%d %p\n", __func__, - bytes, ep_index(ep), ep->dev->dma_buf[ep_index(ep)]); + "%s: bytes=%d, ep_index=%d 0x%p\n", __func__, + max, ep_index(ep), cp); - return bytes; + return max; } /** @@ -873,14 +859,12 @@ static int s3c_ep0_write(struct s3c_udc *dev) return 1; } -u16 g_status; - int s3c_udc_get_status(struct s3c_udc *dev, struct usb_ctrlrequest *crq) { u8 ep_num = crq->wIndex & 0x7F; + u16 g_status = 0; u32 ep_ctrl; - u32 *p = the_controller->dma_buf[1]; debug_cond(DEBUG_SETUP != 0, "%s: *** USB_REQ_GET_STATUS\n", __func__); @@ -918,12 +902,13 @@ int s3c_udc_get_status(struct s3c_udc *dev, return 1; } - memcpy(p, &g_status, sizeof(g_status)); + memcpy(usb_ctrl, &g_status, sizeof(g_status)); - flush_dcache_range((unsigned long) p, - (unsigned long) p + DMA_BUFFER_SIZE); + flush_dcache_range((unsigned long) usb_ctrl, + (unsigned long) usb_ctrl + + ROUND(sizeof(g_status), CONFIG_SYS_CACHELINE_SIZE)); - writel(the_controller->dma_addr[1], ®->in_endp[EP0_CON].diepdma); + writel(usb_ctrl_dma_addr, ®->in_endp[EP0_CON].diepdma); writel(DIEPT_SIZ_PKT_CNT(1) | DIEPT_SIZ_XFER_SIZE(2), ®->in_endp[EP0_CON].dieptsiz); |