diff options
| author | Tom Rini <[email protected]> | 2022-01-17 11:24:43 -0500 |
|---|---|---|
| committer | Tom Rini <[email protected]> | 2022-01-17 11:24:43 -0500 |
| commit | 4e81f3be340072ad2c0aac093677333702f14f22 (patch) | |
| tree | 447e16a695d5e55d52cf4687495a35fda48dacd6 /drivers | |
| parent | 6d2ebcd7be3e7f9cc81011ddb97540c81a301701 (diff) | |
| parent | 609983e981a0a7f053ee6f9f6cd2772226a33000 (diff) | |
Merge branch '2022-01-15-TI-platform-updates'
- Let am335x_evm use the CPSW or PRUSS ethernet.
- Implement timer_get_boot_us in the omap timer driver
- gpmc bitflip, QSPI clock calculation on am437x, da8xx_gpio bugfixes
- Assorted K3 updates
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/dma/ti/k3-udma.c | 21 | ||||
| -rw-r--r-- | drivers/gpio/da8xx_gpio.c | 8 | ||||
| -rw-r--r-- | drivers/mtd/nand/raw/omap_gpmc.c | 45 | ||||
| -rw-r--r-- | drivers/net/ti/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/net/ti/am65-cpsw-nuss.c | 77 | ||||
| -rw-r--r-- | drivers/spi/ti_qspi.c | 3 | ||||
| -rw-r--r-- | drivers/timer/omap-timer.c | 21 |
7 files changed, 127 insertions, 50 deletions
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 411edef3a76..86603d43f14 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -165,7 +165,6 @@ struct udma_dev { unsigned long *rchan_map; unsigned long *rflow_map; unsigned long *rflow_map_reserved; - unsigned long *rflow_in_use; unsigned long *tflow_map; struct udma_bchan *bchans; @@ -1448,15 +1447,11 @@ static int bcdma_setup_resources(struct udma_dev *ud) sizeof(unsigned long), GFP_KERNEL); ud->rchans = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rchans), GFP_KERNEL); - /* BCDMA do not really have flows, but the driver expect it */ - ud->rflow_in_use = devm_kcalloc(dev, BITS_TO_LONGS(ud->rchan_cnt), - sizeof(unsigned long), - GFP_KERNEL); ud->rflows = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rflows), GFP_KERNEL); if (!ud->bchan_map || !ud->tchan_map || !ud->rchan_map || - !ud->rflow_in_use || !ud->bchans || !ud->tchans || !ud->rchans || + !ud->bchans || !ud->tchans || !ud->rchans || !ud->rflows) return -ENOMEM; @@ -1535,16 +1530,16 @@ static int pktdma_setup_resources(struct udma_dev *ud) sizeof(unsigned long), GFP_KERNEL); ud->rchans = devm_kcalloc(dev, ud->rchan_cnt, sizeof(*ud->rchans), GFP_KERNEL); - ud->rflow_in_use = devm_kcalloc(dev, BITS_TO_LONGS(ud->rflow_cnt), - sizeof(unsigned long), - GFP_KERNEL); + ud->rflow_map = devm_kcalloc(dev, BITS_TO_LONGS(ud->rflow_cnt), + sizeof(unsigned long), + GFP_KERNEL); ud->rflows = devm_kcalloc(dev, ud->rflow_cnt, sizeof(*ud->rflows), GFP_KERNEL); ud->tflow_map = devm_kmalloc_array(dev, BITS_TO_LONGS(ud->tflow_cnt), sizeof(unsigned long), GFP_KERNEL); if (!ud->tchan_map || !ud->rchan_map || !ud->tflow_map || !ud->tchans || - !ud->rchans || !ud->rflows || !ud->rflow_in_use) + !ud->rchans || !ud->rflows || !ud->rflow_map) return -ENOMEM; /* Get resource ranges from tisci */ @@ -1592,12 +1587,12 @@ static int pktdma_setup_resources(struct udma_dev *ud) rm_res = tisci_rm->rm_ranges[RM_RANGE_RFLOW]; if (IS_ERR(rm_res)) { /* all rflows are assigned exclusively to Linux */ - bitmap_zero(ud->rflow_in_use, ud->rflow_cnt); + bitmap_zero(ud->rflow_map, ud->rflow_cnt); } else { - bitmap_fill(ud->rflow_in_use, ud->rflow_cnt); + bitmap_fill(ud->rflow_map, ud->rflow_cnt); for (i = 0; i < rm_res->sets; i++) { rm_desc = &rm_res->desc[i]; - bitmap_clear(ud->rflow_in_use, rm_desc->start, + bitmap_clear(ud->rflow_map, rm_desc->start, rm_desc->num); dev_dbg(dev, "ti-sci-res: rflow: %d:%d\n", rm_desc->start, rm_desc->num); diff --git a/drivers/gpio/da8xx_gpio.c b/drivers/gpio/da8xx_gpio.c index d106e9846df..b310f2dbf65 100644 --- a/drivers/gpio/da8xx_gpio.c +++ b/drivers/gpio/da8xx_gpio.c @@ -545,12 +545,20 @@ static int davinci_gpio_of_to_plat(struct udevice *dev) { struct davinci_gpio_plat *plat = dev_get_plat(dev); fdt_addr_t addr; + char name[18], *str; addr = dev_read_addr(dev); if (addr == FDT_ADDR_T_NONE) return -EINVAL; plat->base = addr; + + sprintf(name, "gpio@%4x_", (unsigned int)plat->base); + str = strdup(name); + if (!str) + return -ENOMEM; + plat->port_name = str; + return 0; } diff --git a/drivers/mtd/nand/raw/omap_gpmc.c b/drivers/mtd/nand/raw/omap_gpmc.c index 530574898ce..107447f9df4 100644 --- a/drivers/mtd/nand/raw/omap_gpmc.c +++ b/drivers/mtd/nand/raw/omap_gpmc.c @@ -507,19 +507,45 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, /* check calculated ecc */ for (i = 0; i < ecc->bytes && !ecc_flag; i++) { if (calc_ecc[i] != 0x00) - ecc_flag = 1; + goto not_ecc_match; } - if (!ecc_flag) - return 0; + return 0; +not_ecc_match: - /* check for whether its a erased-page */ - ecc_flag = 0; - for (i = 0; i < ecc->bytes && !ecc_flag; i++) { + /* check for whether it's an erased-page */ + for (i = 0; i < ecc->bytes; i++) { if (read_ecc[i] != 0xff) - ecc_flag = 1; + goto not_erased; + } + for (i = 0; i < SECTOR_BYTES; i++) { + if (dat[i] != 0xff) + goto not_erased; + } + return 0; +not_erased: + + /* + * Check for whether it's an erased page with a correctable + * number of bitflips. Erased pages have all 1's in the data, + * so we just compute the number of 0 bits in the data and + * see if it's under the correction threshold. + * + * NOTE: The check for a perfect erased page above is faster for + * the more common case, even though it's logically redundant. + */ + for (i = 0; i < ecc->bytes; i++) + error_count += hweight8(~read_ecc[i]); + + for (i = 0; i < SECTOR_BYTES; i++) + error_count += hweight8(~dat[i]); + + if (error_count <= ecc->strength) { + memset(read_ecc, 0xFF, ecc->bytes); + memset(dat, 0xFF, SECTOR_BYTES); + debug("nand: %u bit-flip(s) corrected in erased page\n", + error_count); + return error_count; } - if (!ecc_flag) - return 0; /* * while reading ECC result we read it in big endian. @@ -539,6 +565,7 @@ static int omap_correct_data_bch(struct mtd_info *mtd, uint8_t *dat, } /* use elm module to check for errors */ elm_config(bch_type); + error_count = 0; err = elm_check_error(calc_ecc, bch_type, &error_count, error_loc); if (err) return err; diff --git a/drivers/net/ti/Kconfig b/drivers/net/ti/Kconfig index f2dbbd0128d..59c96d862dd 100644 --- a/drivers/net/ti/Kconfig +++ b/drivers/net/ti/Kconfig @@ -28,6 +28,8 @@ config DRIVER_TI_KEYSTONE_NET config TI_AM65_CPSW_NUSS bool "TI K3 AM65x MCU CPSW Nuss Ethernet controller driver" depends on ARCH_K3 + imply MISC_INIT_R + imply MISC select PHYLIB help This driver supports TI K3 MCU CPSW Nuss Ethernet controller diff --git a/drivers/net/ti/am65-cpsw-nuss.c b/drivers/net/ti/am65-cpsw-nuss.c index 3ab6a30828c..6ae69b51c79 100644 --- a/drivers/net/ti/am65-cpsw-nuss.c +++ b/drivers/net/ti/am65-cpsw-nuss.c @@ -597,7 +597,7 @@ static int am65_cpsw_phy_init(struct udevice *dev) return ret; } -static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np) +static int am65_cpsw_ofdata_parse_phy(struct udevice *dev) { struct eth_pdata *pdata = dev_get_plat(dev); struct am65_cpsw_priv *priv = dev_get_priv(dev); @@ -605,7 +605,9 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np) const char *phy_mode; int ret = 0; - phy_mode = ofnode_read_string(port_np, "phy-mode"); + dev_read_u32(dev, "reg", &priv->port_id); + + phy_mode = dev_read_string(dev, "phy-mode"); if (phy_mode) { pdata->phy_interface = phy_get_interface_by_name(phy_mode); @@ -617,13 +619,13 @@ static int am65_cpsw_ofdata_parse_phy(struct udevice *dev, ofnode port_np) } } - ofnode_read_u32(port_np, "max-speed", (u32 *)&pdata->max_speed); + dev_read_u32(dev, "max-speed", (u32 *)&pdata->max_speed); if (pdata->max_speed) dev_err(dev, "Port %u speed froced to %uMbit\n", priv->port_id, pdata->max_speed); priv->has_phy = true; - ret = ofnode_parse_phandle_with_args(port_np, "phy-handle", + ret = ofnode_parse_phandle_with_args(dev_ofnode(dev), "phy-handle", NULL, 0, 0, &out_args); if (ret) { dev_err(dev, "can't parse phy-handle port %u (%d)\n", @@ -646,21 +648,46 @@ out: return ret; } -static int am65_cpsw_probe_cpsw(struct udevice *dev) +static int am65_cpsw_port_probe(struct udevice *dev) { struct am65_cpsw_priv *priv = dev_get_priv(dev); struct eth_pdata *pdata = dev_get_plat(dev); struct am65_cpsw_common *cpsw_common; - ofnode ports_np, node; - int ret, i; + char portname[15]; + int ret; priv->dev = dev; - cpsw_common = calloc(1, sizeof(*priv->cpsw_common)); - if (!cpsw_common) - return -ENOMEM; + cpsw_common = dev_get_priv(dev->parent); priv->cpsw_common = cpsw_common; + sprintf(portname, "%s%s", dev->parent->name, dev->name); + device_set_name(dev, portname); + + ret = am65_cpsw_ofdata_parse_phy(dev); + if (ret) + goto out; + + am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id); + + ret = am65_cpsw_mdio_init(dev); + if (ret) + goto out; + + ret = am65_cpsw_phy_init(dev); + if (ret) + goto out; +out: + return ret; +} + +static int am65_cpsw_probe_nuss(struct udevice *dev) +{ + struct am65_cpsw_common *cpsw_common = dev_get_priv(dev); + ofnode ports_np, node; + int ret, i; + struct udevice *port_dev; + cpsw_common->dev = dev; cpsw_common->ss_base = dev_read_addr(dev); if (cpsw_common->ss_base == FDT_ADDR_T_NONE) @@ -723,10 +750,9 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev) if (disabled) continue; - priv->port_id = port_id; - ret = am65_cpsw_ofdata_parse_phy(dev, node); + ret = device_bind_driver_to_node(dev, "am65_cpsw_nuss_port", ofnode_get_name(node), node, &port_dev); if (ret) - goto out; + printf("SCREEEM\n"); } for (i = 0; i < AM65_CPSW_CPSWNU_MAX_PORTS; i++) { @@ -756,16 +782,6 @@ static int am65_cpsw_probe_cpsw(struct udevice *dev) dev_read_u32_default(dev, "bus_freq", AM65_CPSW_MDIO_BUS_FREQ_DEF); - am65_cpsw_gmii_sel_k3(priv, pdata->phy_interface, priv->port_id); - - ret = am65_cpsw_mdio_init(dev); - if (ret) - goto out; - - ret = am65_cpsw_phy_init(dev); - if (ret) - goto out; - dev_info(dev, "K3 CPSW: nuss_ver: 0x%08X cpsw_ver: 0x%08X ale_ver: 0x%08X Ports:%u mdio_freq:%u\n", readl(cpsw_common->ss_base), readl(cpsw_common->cpsw_base), @@ -786,11 +802,18 @@ static const struct udevice_id am65_cpsw_nuss_ids[] = { { } }; -U_BOOT_DRIVER(am65_cpsw_nuss_slave) = { - .name = "am65_cpsw_nuss_slave", - .id = UCLASS_ETH, +U_BOOT_DRIVER(am65_cpsw_nuss) = { + .name = "am65_cpsw_nuss", + .id = UCLASS_MISC, .of_match = am65_cpsw_nuss_ids, - .probe = am65_cpsw_probe_cpsw, + .probe = am65_cpsw_probe_nuss, + .priv_auto = sizeof(struct am65_cpsw_common), +}; + +U_BOOT_DRIVER(am65_cpsw_nuss_port) = { + .name = "am65_cpsw_nuss_port", + .id = UCLASS_ETH, + .probe = am65_cpsw_port_probe, .ops = &am65_cpsw_ops, .priv_auto = sizeof(struct am65_cpsw_priv), .plat_auto = sizeof(struct eth_pdata), diff --git a/drivers/spi/ti_qspi.c b/drivers/spi/ti_qspi.c index c542f40c7df..99acb108823 100644 --- a/drivers/spi/ti_qspi.c +++ b/drivers/spi/ti_qspi.c @@ -30,7 +30,8 @@ DECLARE_GLOBAL_DATA_PTR; /* ti qpsi register bit masks */ #define QSPI_TIMEOUT 2000000 -#define QSPI_FCLK 192000000 +/* AM4372: QSPI gets SPI_GCLK from PRCM unit as PER_CLKOUTM2 divided by 4. */ +#define QSPI_FCLK (192000000 / 4) #define QSPI_DRA7XX_FCLK 76800000 #define QSPI_WLEN_MAX_BITS 128 #define QSPI_WLEN_MAX_BYTES (QSPI_WLEN_MAX_BITS >> 3) diff --git a/drivers/timer/omap-timer.c b/drivers/timer/omap-timer.c index 721e385fd15..25a6108fef2 100644 --- a/drivers/timer/omap-timer.c +++ b/drivers/timer/omap-timer.c @@ -83,6 +83,27 @@ static int omap_timer_of_to_plat(struct udevice *dev) return 0; } +#if CONFIG_IS_ENABLED(BOOTSTAGE) +ulong timer_get_boot_us(void) +{ + u64 ticks = 0; + u32 rate = 1; + u64 us; + int ret; + + ret = dm_timer_init(); + if (!ret) { + /* The timer is available */ + rate = timer_get_rate(gd->timer); + timer_get_count(gd->timer, &ticks); + } else { + return 0; + } + + us = (ticks * 1000) / rate; + return us; +} +#endif static const struct timer_ops omap_timer_ops = { .get_count = omap_timer_get_count, |
