diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dfu/dfu_mmc.c | 11 | ||||
-rw-r--r-- | drivers/gpio/mpc85xx_gpio.c | 37 | ||||
-rw-r--r-- | drivers/misc/cros_ec_sandbox.c | 11 | ||||
-rw-r--r-- | drivers/mmc/Kconfig | 11 | ||||
-rw-r--r-- | drivers/mmc/Makefile | 3 | ||||
-rw-r--r-- | drivers/mmc/dw_mmc.c | 33 | ||||
-rw-r--r-- | drivers/mmc/mmc-uclass.c | 146 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 371 | ||||
-rw-r--r-- | drivers/mmc/mmc_boot.c | 131 | ||||
-rw-r--r-- | drivers/mmc/mmc_legacy.c | 91 | ||||
-rw-r--r-- | drivers/mmc/mmc_private.h | 47 | ||||
-rw-r--r-- | drivers/mmc/msm_sdhci.c | 38 | ||||
-rw-r--r-- | drivers/mmc/rockchip_dw_mmc.c | 14 | ||||
-rw-r--r-- | drivers/mmc/sandbox_mmc.c | 17 | ||||
-rw-r--r-- | drivers/mmc/sdhci.c | 147 | ||||
-rw-r--r-- | drivers/net/designware.c | 10 | ||||
-rw-r--r-- | drivers/net/designware.h | 7 | ||||
-rw-r--r-- | drivers/net/phy/aquantia.c | 28 | ||||
-rw-r--r-- | drivers/net/rtl8169.c | 4 | ||||
-rw-r--r-- | drivers/pci/pci_tegra.c | 37 | ||||
-rw-r--r-- | drivers/video/rockchip/rk_hdmi.c | 2 | ||||
-rw-r--r-- | drivers/video/tegra.c | 333 |
22 files changed, 810 insertions, 719 deletions
diff --git a/drivers/dfu/dfu_mmc.c b/drivers/dfu/dfu_mmc.c index 78724e467b..926ccbd2ef 100644 --- a/drivers/dfu/dfu_mmc.c +++ b/drivers/dfu/dfu_mmc.c @@ -49,7 +49,7 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, } if (dfu->data.mmc.hw_partition >= 0) { - part_num_bkp = mmc->block_dev.hwpart; + part_num_bkp = mmc_get_blk_desc(mmc)->hwpart; ret = blk_select_hwpart_devnum(IF_TYPE_MMC, dfu->data.mmc.dev_num, dfu->data.mmc.hw_partition); @@ -62,12 +62,11 @@ static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu, dfu->data.mmc.dev_num, blk_start, blk_count, buf); switch (op) { case DFU_OP_READ: - n = mmc->block_dev.block_read(&mmc->block_dev, blk_start, - blk_count, buf); + n = blk_dread(mmc_get_blk_desc(mmc), blk_start, blk_count, buf); break; case DFU_OP_WRITE: - n = mmc->block_dev.block_write(&mmc->block_dev, blk_start, - blk_count, buf); + n = blk_dwrite(mmc_get_blk_desc(mmc), blk_start, blk_count, + buf); break; default: error("Operation not supported\n"); @@ -356,7 +355,7 @@ int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s) } else if (!strcmp(entity_type, "part")) { disk_partition_t partinfo; - struct blk_desc *blk_dev = &mmc->block_dev; + struct blk_desc *blk_dev = mmc_get_blk_desc(mmc); int mmcdev = second_arg; int mmcpart = third_arg; diff --git a/drivers/gpio/mpc85xx_gpio.c b/drivers/gpio/mpc85xx_gpio.c index 04773e2b31..3754a8215c 100644 --- a/drivers/gpio/mpc85xx_gpio.c +++ b/drivers/gpio/mpc85xx_gpio.c @@ -163,23 +163,41 @@ static int mpc85xx_gpio_get_function(struct udevice *dev, unsigned gpio) return dir ? GPIOF_OUTPUT : GPIOF_INPUT; } +#if CONFIG_IS_ENABLED(OF_CONTROL) static int mpc85xx_gpio_ofdata_to_platdata(struct udevice *dev) { - struct mpc85xx_gpio_data *data = dev_get_priv(dev); + struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev); fdt_addr_t addr; fdt_size_t size; addr = fdtdec_get_addr_size_auto_noparent(gd->fdt_blob, dev->of_offset, "reg", 0, &size); - data->addr = addr; - data->base = map_sysmem(CONFIG_SYS_IMMR + addr, size); + plat->addr = addr; + plat->size = size; + plat->ngpios = fdtdec_get_int(gd->fdt_blob, dev->of_offset, + "ngpios", 32); - if (!data->base) + return 0; +} +#endif + +static int mpc85xx_gpio_platdata_to_priv(struct udevice *dev) +{ + struct mpc85xx_gpio_data *priv = dev_get_priv(dev); + struct mpc85xx_gpio_plat *plat = dev_get_platdata(dev); + unsigned long size = plat->size; + + if (size == 0) + size = 0x100; + + priv->addr = plat->addr; + priv->base = map_sysmem(CONFIG_SYS_IMMR + plat->addr, size); + + if (!priv->base) return -ENOMEM; - data->gpio_count = fdtdec_get_int(gd->fdt_blob, dev->of_offset, - "ngpios", 32); - data->dat_shadow = 0; + priv->gpio_count = plat->ngpios; + priv->dat_shadow = 0; return 0; } @@ -190,6 +208,8 @@ static int mpc85xx_gpio_probe(struct udevice *dev) struct mpc85xx_gpio_data *data = dev_get_priv(dev); char name[32], *str; + mpc85xx_gpio_platdata_to_priv(dev); + snprintf(name, sizeof(name), "MPC@%lx_", data->addr); str = strdup(name); @@ -221,8 +241,11 @@ U_BOOT_DRIVER(gpio_mpc85xx) = { .name = "gpio_mpc85xx", .id = UCLASS_GPIO, .ops = &gpio_mpc85xx_ops, +#if CONFIG_IS_ENABLED(OF_CONTROL) .ofdata_to_platdata = mpc85xx_gpio_ofdata_to_platdata, + .platdata_auto_alloc_size = sizeof(struct mpc85xx_gpio_plat), .of_match = mpc85xx_gpio_ids, +#endif .probe = mpc85xx_gpio_probe, .priv_auto_alloc_size = sizeof(struct mpc85xx_gpio_data), }; diff --git a/drivers/misc/cros_ec_sandbox.c b/drivers/misc/cros_ec_sandbox.c index 98f19a68bf..c4fbca0d3a 100644 --- a/drivers/misc/cros_ec_sandbox.c +++ b/drivers/misc/cros_ec_sandbox.c @@ -517,6 +517,7 @@ int cros_ec_probe(struct udevice *dev) struct ec_state *ec = dev->priv; struct cros_ec_dev *cdev = dev->uclass_priv; const void *blob = gd->fdt_blob; + struct udevice *keyb_dev; int node; int err; @@ -525,7 +526,15 @@ int cros_ec_probe(struct udevice *dev) if (err) return err; - node = fdtdec_next_compatible(blob, 0, COMPAT_GOOGLE_CROS_EC_KEYB); + node = -1; + for (device_find_first_child(dev, &keyb_dev); + keyb_dev; + device_find_next_child(&keyb_dev)) { + if (device_get_uclass_id(keyb_dev) == UCLASS_KEYBOARD) { + node = keyb_dev->of_offset; + break; + } + } if (node < 0) { debug("%s: No cros_ec keyboard found\n", __func__); } else if (keyscan_read_fdt_matrix(ec, blob, node)) { diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c80efc39a7..79cf18f14f 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig @@ -16,9 +16,18 @@ config DM_MMC appear as block devices in U-Boot and can support filesystems such as EXT4 and FAT. +config DM_MMC_OPS + bool "Support MMC controller operations using Driver Model" + depends on DM_MMC + help + Driver model provides a means of supporting device operations. This + option moves MMC operations under the control of driver model. The + option will be removed as soon as all DM_MMC drivers use it, as it + will the only supported behaviour. + config MSM_SDHCI bool "Qualcomm SDHCI controller" - depends on DM_MMC + depends on DM_MMC && BLK && DM_MMC_OPS help Enables support for SDHCI 2.0 controller present on some Qualcomm Snapdragon devices. This device is compatible with eMMC v4.5 and diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 3da4817a18..b44a12e606 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -25,6 +25,9 @@ obj-$(CONFIG_FSL_ESDHC) += fsl_esdhc.o obj-$(CONFIG_FTSDC010) += ftsdc010_mci.o obj-$(CONFIG_FTSDC021) += ftsdc021_sdhci.o obj-$(CONFIG_GENERIC_MMC) += mmc.o +ifdef CONFIG_SUPPORT_EMMC_BOOT +obj-$(CONFIG_GENERIC_MMC) += mmc_boot.o +endif obj-$(CONFIG_GENERIC_ATMEL_MCI) += gen_atmel_mci.o obj-$(CONFIG_KONA_SDHCI) += kona_sdhci.o obj-$(CONFIG_MMC_SPI) += mmc_spi.o diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c index af6e04aa28..2cf7bae792 100644 --- a/drivers/mmc/dw_mmc.c +++ b/drivers/mmc/dw_mmc.c @@ -181,9 +181,16 @@ static int dwmci_set_transfer_mode(struct dwmci_host *host, return mode; } +#ifdef CONFIG_DM_MMC_OPS +int dwmci_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) { +#endif struct dwmci_host *host = mmc->priv; ALLOC_CACHE_ALIGN_BUFFER(struct dwmci_idmac, cur_idmac, data ? DIV_ROUND_UP(data->blocks, 8) : 0); @@ -373,8 +380,14 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq) return 0; } +#ifdef CONFIG_DM_MMC_OPS +int dwmci_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static void dwmci_set_ios(struct mmc *mmc) { +#endif struct dwmci_host *host = (struct dwmci_host *)mmc->priv; u32 ctype, regs; @@ -405,6 +418,9 @@ static void dwmci_set_ios(struct mmc *mmc) if (host->clksel) host->clksel(host); +#ifdef CONFIG_DM_MMC_OPS + return 0; +#endif } static int dwmci_init(struct mmc *mmc) @@ -448,17 +464,34 @@ static int dwmci_init(struct mmc *mmc) return 0; } +#ifdef CONFIG_DM_MMC_OPS +int dwmci_probe(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return dwmci_init(mmc); +} + +const struct dm_mmc_ops dm_dwmci_ops = { + .send_cmd = dwmci_send_cmd, + .set_ios = dwmci_set_ios, +}; + +#else static const struct mmc_ops dwmci_ops = { .send_cmd = dwmci_send_cmd, .set_ios = dwmci_set_ios, .init = dwmci_init, }; +#endif void dwmci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, uint caps, u32 max_clk, u32 min_clk) { cfg->name = name; +#ifndef CONFIG_DM_MMC_OPS cfg->ops = &dwmci_ops; +#endif cfg->f_min = min_clk; cfg->f_max = max_clk; diff --git a/drivers/mmc/mmc-uclass.c b/drivers/mmc/mmc-uclass.c index 1b967d982b..38ced4102e 100644 --- a/drivers/mmc/mmc-uclass.c +++ b/drivers/mmc/mmc-uclass.c @@ -8,8 +8,76 @@ #include <common.h> #include <mmc.h> #include <dm.h> +#include <dm/device-internal.h> #include <dm/lists.h> #include <dm/root.h> +#include "mmc_private.h" + +#ifdef CONFIG_DM_MMC_OPS +int dm_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + struct dm_mmc_ops *ops = mmc_get_ops(dev); + int ret; + + mmmc_trace_before_send(mmc, cmd); + if (ops->send_cmd) + ret = ops->send_cmd(dev, cmd, data); + else + ret = -ENOSYS; + mmmc_trace_after_send(mmc, cmd, ret); + + return ret; +} + +int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +{ + return dm_mmc_send_cmd(mmc->dev, cmd, data); +} + +int dm_mmc_set_ios(struct udevice *dev) +{ + struct dm_mmc_ops *ops = mmc_get_ops(dev); + + if (!ops->set_ios) + return -ENOSYS; + return ops->set_ios(dev); +} + +int mmc_set_ios(struct mmc *mmc) +{ + return dm_mmc_set_ios(mmc->dev); +} + +int dm_mmc_get_wp(struct udevice *dev) +{ + struct dm_mmc_ops *ops = mmc_get_ops(dev); + + if (!ops->get_wp) + return -ENOSYS; + return ops->get_wp(dev); +} + +int mmc_getwp(struct mmc *mmc) +{ + return dm_mmc_get_wp(mmc->dev); +} + +int dm_mmc_get_cd(struct udevice *dev) +{ + struct dm_mmc_ops *ops = mmc_get_ops(dev); + + if (!ops->get_cd) + return -ENOSYS; + return ops->get_cd(dev); +} + +int mmc_getcd(struct mmc *mmc) +{ + return dm_mmc_get_cd(mmc->dev); +} +#endif struct mmc *mmc_get_mmc_dev(struct udevice *dev) { @@ -125,6 +193,84 @@ void print_mmc_devices(char separator) #else void print_mmc_devices(char separator) { } #endif + +int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) +{ + struct blk_desc *bdesc; + struct udevice *bdev; + int ret; + + ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512, + 0, &bdev); + if (ret) { + debug("Cannot create block device\n"); + return ret; + } + bdesc = dev_get_uclass_platdata(bdev); + mmc->cfg = cfg; + mmc->priv = dev; + + /* the following chunk was from mmc_register() */ + + /* Setup dsr related values */ + mmc->dsr_imp = 0; + mmc->dsr = 0xffffffff; + /* Setup the universal parts of the block interface just once */ + bdesc->removable = 1; + + /* setup initial part type */ + bdesc->part_type = cfg->part_type; + mmc->dev = dev; + + return 0; +} + +int mmc_unbind(struct udevice *dev) +{ + struct udevice *bdev; + + device_find_first_child(dev, &bdev); + if (bdev) { + device_remove(bdev); + device_unbind(bdev); + } + + return 0; +} + +static int mmc_select_hwpart(struct udevice *bdev, int hwpart) +{ + struct udevice *mmc_dev = dev_get_parent(bdev); + struct mmc *mmc = mmc_get_mmc_dev(mmc_dev); + struct blk_desc *desc = dev_get_uclass_platdata(bdev); + int ret; + + if (desc->hwpart == hwpart) + return 0; + + if (mmc->part_config == MMCPART_NOAVAILABLE) + return -EMEDIUMTYPE; + + ret = mmc_switch_part(mmc, hwpart); + if (ret) + return ret; + + return 0; +} + +static const struct blk_ops mmc_blk_ops = { + .read = mmc_bread, +#ifndef CONFIG_SPL_BUILD + .write = mmc_bwrite, +#endif + .select_hwpart = mmc_select_hwpart, +}; + +U_BOOT_DRIVER(mmc_blk) = { + .name = "mmc_blk", + .id = UCLASS_BLK, + .ops = &mmc_blk_ops, +}; #endif /* CONFIG_BLK */ U_BOOT_DRIVER(mmc) = { diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index aabfc711e5..f8e5f7a608 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -21,6 +21,7 @@ #include <div64.h> #include "mmc_private.h" +#ifndef CONFIG_DM_MMC_OPS __weak int board_mmc_getwp(struct mmc *mmc) { return -1; @@ -46,18 +47,20 @@ __weak int board_mmc_getcd(struct mmc *mmc) { return -1; } +#endif -int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +#ifdef CONFIG_MMC_TRACE +void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd) { - int ret; + printf("CMD_SEND:%d\n", cmd->cmdidx); + printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg); +} -#ifdef CONFIG_MMC_TRACE +void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret) +{ int i; u8 *ptr; - printf("CMD_SEND:%d\n", cmd->cmdidx); - printf("\t\tARG\t\t\t 0x%08X\n", cmd->cmdarg); - ret = mmc->cfg->ops->send_cmd(mmc, cmd, data); if (ret) { printf("\t\tRET\t\t\t %d\n", ret); } else { @@ -103,19 +106,34 @@ int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) break; } } -#else - ret = mmc->cfg->ops->send_cmd(mmc, cmd, data); +} + +void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd) +{ + int status; + + status = (cmd->response[0] & MMC_STATUS_CURR_STATE) >> 9; + printf("CURR STATE:%d\n", status); +} #endif + +#ifndef CONFIG_DM_MMC_OPS +int mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data) +{ + int ret; + + mmmc_trace_before_send(mmc, cmd); + ret = mmc->cfg->ops->send_cmd(mmc, cmd, data); + mmmc_trace_after_send(mmc, cmd, ret); + return ret; } +#endif int mmc_send_status(struct mmc *mmc, int timeout) { struct mmc_cmd cmd; int err, retries = 5; -#ifdef CONFIG_MMC_TRACE - int status; -#endif cmd.cmdidx = MMC_CMD_SEND_STATUS; cmd.resp_type = MMC_RSP_R1; @@ -145,10 +163,7 @@ int mmc_send_status(struct mmc *mmc, int timeout) udelay(1000); } -#ifdef CONFIG_MMC_TRACE - status = (cmd.response[0] & MMC_STATUS_CURR_STATE) >> 9; - printf("CURR STATE:%d\n", status); -#endif + mmc_trace_state(mmc, &cmd); if (timeout <= 0) { #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("Timeout waiting card ready\n"); @@ -215,11 +230,10 @@ static int mmc_read_blocks(struct mmc *mmc, void *dst, lbaint_t start, } #ifdef CONFIG_BLK -static ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, - void *dst) +ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, void *dst) #else -static ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, - lbaint_t blkcnt, void *dst) +ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, + void *dst) #endif { #ifdef CONFIG_BLK @@ -464,8 +478,7 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd) return err; } - -static int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) +int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) { struct mmc_cmd cmd; int timeout = 1000; @@ -566,7 +579,7 @@ static int mmc_set_capacity(struct mmc *mmc, int part_num) return 0; } -static int mmc_switch_part(struct mmc *mmc, unsigned int part_num) +int mmc_switch_part(struct mmc *mmc, unsigned int part_num) { int ret; @@ -586,49 +599,6 @@ static int mmc_switch_part(struct mmc *mmc, unsigned int part_num) return ret; } -#ifdef CONFIG_BLK -static int mmc_select_hwpart(struct udevice *bdev, int hwpart) -{ - struct udevice *mmc_dev = dev_get_parent(bdev); - struct mmc *mmc = mmc_get_mmc_dev(mmc_dev); - struct blk_desc *desc = dev_get_uclass_platdata(bdev); - int ret; - - if (desc->hwpart == hwpart) - return 0; - - if (mmc->part_config == MMCPART_NOAVAILABLE) - return -EMEDIUMTYPE; - - ret = mmc_switch_part(mmc, hwpart); - if (ret) - return ret; - - return 0; -} -#else -static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart) -{ - struct mmc *mmc = find_mmc_device(desc->devnum); - int ret; - - if (!mmc) - return -ENODEV; - - if (mmc->block_dev.hwpart == hwpart) - return 0; - - if (mmc->part_config == MMCPART_NOAVAILABLE) - return -EMEDIUMTYPE; - - ret = mmc_switch_part(mmc, hwpart); - if (ret) - return ret; - - return 0; -} -#endif - int mmc_hwpart_config(struct mmc *mmc, const struct mmc_hwpart_conf *conf, enum mmc_hwpart_conf_mode mode) @@ -823,6 +793,7 @@ int mmc_hwpart_config(struct mmc *mmc, return 0; } +#ifndef CONFIG_DM_MMC_OPS int mmc_getcd(struct mmc *mmc) { int cd; @@ -838,6 +809,7 @@ int mmc_getcd(struct mmc *mmc) return cd; } +#endif static int sd_switch(struct mmc *mmc, int mode, int group, u8 value, u8 *resp) { @@ -1001,11 +973,13 @@ static const u8 multipliers[] = { 80, }; +#ifndef CONFIG_DM_MMC_OPS static void mmc_set_ios(struct mmc *mmc) { if (mmc->cfg->ops->set_ios) mmc->cfg->ops->set_ios(mmc); } +#endif void mmc_set_clock(struct mmc *mmc, uint clock) { @@ -1532,115 +1506,6 @@ static int mmc_send_if_cond(struct mmc *mmc) return 0; } -#ifdef CONFIG_BLK -int mmc_bind(struct udevice *dev, struct mmc *mmc, const struct mmc_config *cfg) -{ - struct blk_desc *bdesc; - struct udevice *bdev; - int ret; - - ret = blk_create_devicef(dev, "mmc_blk", "blk", IF_TYPE_MMC, -1, 512, - 0, &bdev); - if (ret) { - debug("Cannot create block device\n"); - return ret; - } - bdesc = dev_get_uclass_platdata(bdev); - mmc->cfg = cfg; - mmc->priv = dev; - - /* the following chunk was from mmc_register() */ - - /* Setup dsr related values */ - mmc->dsr_imp = 0; - mmc->dsr = 0xffffffff; - /* Setup the universal parts of the block interface just once */ - bdesc->removable = 1; - - /* setup initial part type */ - bdesc->part_type = cfg->part_type; - mmc->dev = dev; - - return 0; -} - -int mmc_unbind(struct udevice *dev) -{ - struct udevice *bdev; - - device_find_first_child(dev, &bdev); - if (bdev) { - device_remove(bdev); - device_unbind(bdev); - } - - return 0; -} - -#else -struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) -{ - struct blk_desc *bdesc; - struct mmc *mmc; - - /* quick validation */ - if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL || - cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0) - return NULL; - - mmc = calloc(1, sizeof(*mmc)); - if (mmc == NULL) - return NULL; - - mmc->cfg = cfg; - mmc->priv = priv; - - /* the following chunk was mmc_register() */ - - /* Setup dsr related values */ - mmc->dsr_imp = 0; - mmc->dsr = 0xffffffff; - /* Setup the universal parts of the block interface just once */ - bdesc = mmc_get_blk_desc(mmc); - bdesc->if_type = IF_TYPE_MMC; - bdesc->removable = 1; - bdesc->devnum = mmc_get_next_devnum(); - bdesc->block_read = mmc_bread; - bdesc->block_write = mmc_bwrite; - bdesc->block_erase = mmc_berase; - - /* setup initial part type */ - bdesc->part_type = mmc->cfg->part_type; - mmc_list_add(mmc); - - return mmc; -} - -void mmc_destroy(struct mmc *mmc) -{ - /* only freeing memory for now */ - free(mmc); -} -#endif - -#ifndef CONFIG_BLK -static int mmc_get_dev(int dev, struct blk_desc **descp) -{ - struct mmc *mmc = find_mmc_device(dev); - int ret; - - if (!mmc) - return -ENODEV; - ret = mmc_init(mmc); - if (ret) - return ret; - - *descp = &mmc->block_dev; - - return 0; -} -#endif - /* board-specific MMC power initializations. */ __weak void board_mmc_power_init(void) { @@ -1648,10 +1513,15 @@ __weak void board_mmc_power_init(void) int mmc_start_init(struct mmc *mmc) { + bool no_card; int err; /* we pretend there's no card when init is NULL */ - if (mmc_getcd(mmc) == 0 || mmc->cfg->ops->init == NULL) { + no_card = mmc_getcd(mmc) == 0; +#ifndef CONFIG_DM_MMC_OPS + no_card = no_card || (mmc->cfg->ops->init == NULL); +#endif + if (no_card) { mmc->has_init = 0; #if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_SPL_LIBCOMMON_SUPPORT) printf("MMC: no card present\n"); @@ -1667,12 +1537,14 @@ int mmc_start_init(struct mmc *mmc) #endif board_mmc_power_init(); +#ifdef CONFIG_DM_MMC_OPS + /* The device has already been probed ready for use */ +#else /* made sure it's not NULL earlier */ err = mmc->cfg->ops->init(mmc); - if (err) return err; - +#endif mmc->ddr_mode = 0; mmc_set_bus_width(mmc, 1); mmc_set_clock(mmc, 1); @@ -1839,148 +1711,3 @@ int mmc_initialize(bd_t *bis) mmc_do_preinit(); return 0; } - -#ifdef CONFIG_SUPPORT_EMMC_BOOT -/* - * This function changes the size of boot partition and the size of rpmb - * partition present on EMMC devices. - * - * Input Parameters: - * struct *mmc: pointer for the mmc device strcuture - * bootsize: size of boot partition - * rpmbsize: size of rpmb partition - * - * Returns 0 on success. - */ - -int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, - unsigned long rpmbsize) -{ - int err; - struct mmc_cmd cmd; - - /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */ - cmd.cmdidx = MMC_CMD_RES_MAN; - cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = MMC_CMD62_ARG1; - - err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error1 = %d\n", err); - return err; - } - - /* Boot partition changing mode */ - cmd.cmdidx = MMC_CMD_RES_MAN; - cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = MMC_CMD62_ARG2; - - err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error2 = %d\n", err); - return err; - } - /* boot partition size is multiple of 128KB */ - bootsize = (bootsize * 1024) / 128; - - /* Arg: boot partition size */ - cmd.cmdidx = MMC_CMD_RES_MAN; - cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = bootsize; - - err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error3 = %d\n", err); - return err; - } - /* RPMB partition size is multiple of 128KB */ - rpmbsize = (rpmbsize * 1024) / 128; - /* Arg: RPMB partition size */ - cmd.cmdidx = MMC_CMD_RES_MAN; - cmd.resp_type = MMC_RSP_R1b; - cmd.cmdarg = rpmbsize; - - err = mmc_send_cmd(mmc, &cmd, NULL); - if (err) { - debug("mmc_boot_partition_size_change: Error4 = %d\n", err); - return err; - } - return 0; -} - -/* - * 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_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode) -{ - int err; - - 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)); - - if (err) - return err; - return 0; -} - -/* - * 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; - - 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)); - - if (err) - return err; - return 0; -} - -/* - * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value - * for enable. Note that this is a write-once field for non-zero values. - * - * Returns 0 on success. - */ -int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) -{ - return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION, - enable); -} -#endif - -#ifdef CONFIG_BLK -static const struct blk_ops mmc_blk_ops = { - .read = mmc_bread, - .write = mmc_bwrite, - .select_hwpart = mmc_select_hwpart, -}; - -U_BOOT_DRIVER(mmc_blk) = { - .name = "mmc_blk", - .id = UCLASS_BLK, - .ops = &mmc_blk_ops, -}; -#else -U_BOOT_LEGACY_BLK(mmc) = { - .if_typename = "mmc", - .if_type = IF_TYPE_MMC, - .max_devs = -1, - .get_dev = mmc_get_dev, - .select_hwpart = mmc_select_hwpartp, -}; -#endif diff --git a/drivers/mmc/mmc_boot.c b/drivers/mmc/mmc_boot.c new file mode 100644 index 0000000000..756a9824e3 --- /dev/null +++ b/drivers/mmc/mmc_boot.c @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2016 Google, Inc + * Written by Amar <amarendra.xt@samsung.com> + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <mmc.h> +#include "mmc_private.h" + +/* + * This function changes the size of boot partition and the size of rpmb + * partition present on EMMC devices. + * + * Input Parameters: + * struct *mmc: pointer for the mmc device strcuture + * bootsize: size of boot partition + * rpmbsize: size of rpmb partition + * + * Returns 0 on success. + */ + +int mmc_boot_partition_size_change(struct mmc *mmc, unsigned long bootsize, + unsigned long rpmbsize) +{ + int err; + struct mmc_cmd cmd; + + /* Only use this command for raw EMMC moviNAND. Enter backdoor mode */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = MMC_CMD62_ARG1; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error1 = %d\n", err); + return err; + } + + /* Boot partition changing mode */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = MMC_CMD62_ARG2; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error2 = %d\n", err); + return err; + } + /* boot partition size is multiple of 128KB */ + bootsize = (bootsize * 1024) / 128; + + /* Arg: boot partition size */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = bootsize; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error3 = %d\n", err); + return err; + } + /* RPMB partition size is multiple of 128KB */ + rpmbsize = (rpmbsize * 1024) / 128; + /* Arg: RPMB partition size */ + cmd.cmdidx = MMC_CMD_RES_MAN; + cmd.resp_type = MMC_RSP_R1b; + cmd.cmdarg = rpmbsize; + + err = mmc_send_cmd(mmc, &cmd, NULL); + if (err) { + debug("mmc_boot_partition_size_change: Error4 = %d\n", err); + return err; + } + return 0; +} + +/* + * 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_set_boot_bus_width(struct mmc *mmc, u8 width, u8 reset, u8 mode) +{ + int err; + + 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)); + + if (err) + return err; + return 0; +} + +/* + * 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; + + 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)); + + if (err) + return err; + return 0; +} + +/* + * Modify EXT_CSD[162] which is RST_n_FUNCTION based on the given value + * for enable. Note that this is a write-once field for non-zero values. + * + * Returns 0 on success. + */ +int mmc_set_rst_n_function(struct mmc *mmc, u8 enable) +{ + return mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_RST_N_FUNCTION, + enable); +} diff --git a/drivers/mmc/mmc_legacy.c b/drivers/mmc/mmc_legacy.c index 3ec649f2b8..040728b45d 100644 --- a/drivers/mmc/mmc_legacy.c +++ b/drivers/mmc/mmc_legacy.c @@ -6,7 +6,9 @@ */ #include <common.h> +#include <malloc.h> #include <mmc.h> +#include "mmc_private.h" static struct list_head mmc_devices; static int cur_dev_num = -1; @@ -106,3 +108,92 @@ void print_mmc_devices(char separator) #else void print_mmc_devices(char separator) { } #endif + +struct mmc *mmc_create(const struct mmc_config *cfg, void *priv) +{ + struct blk_desc *bdesc; + struct mmc *mmc; + + /* quick validation */ + if (cfg == NULL || cfg->ops == NULL || cfg->ops->send_cmd == NULL || + cfg->f_min == 0 || cfg->f_max == 0 || cfg->b_max == 0) + return NULL; + + mmc = calloc(1, sizeof(*mmc)); + if (mmc == NULL) + return NULL; + + mmc->cfg = cfg; + mmc->priv = priv; + + /* the following chunk was mmc_register() */ + + /* Setup dsr related values */ + mmc->dsr_imp = 0; + mmc->dsr = 0xffffffff; + /* Setup the universal parts of the block interface just once */ + bdesc = mmc_get_blk_desc(mmc); + bdesc->if_type = IF_TYPE_MMC; + bdesc->removable = 1; + bdesc->devnum = mmc_get_next_devnum(); + bdesc->block_read = mmc_bread; + bdesc->block_write = mmc_bwrite; + bdesc->block_erase = mmc_berase; + + /* setup initial part type */ + bdesc->part_type = mmc->cfg->part_type; + mmc_list_add(mmc); + + return mmc; +} + +void mmc_destroy(struct mmc *mmc) +{ + /* only freeing memory for now */ + free(mmc); +} + +static int mmc_select_hwpartp(struct blk_desc *desc, int hwpart) +{ + struct mmc *mmc = find_mmc_device(desc->devnum); + int ret; + + if (!mmc) + return -ENODEV; + + if (mmc->block_dev.hwpart == hwpart) + return 0; + + if (mmc->part_config == MMCPART_NOAVAILABLE) + return -EMEDIUMTYPE; + + ret = mmc_switch_part(mmc, hwpart); + if (ret) + return ret; + + return 0; +} + +static int mmc_get_dev(int dev, struct blk_desc **descp) +{ + struct mmc *mmc = find_mmc_device(dev); + int ret; + + if (!mmc) + return -ENODEV; + ret = mmc_init(mmc); + if (ret) + return ret; + + *descp = &mmc->block_dev; + + return 0; +} + +U_BOOT_LEGACY_BLK(mmc) = { + .if_typename = "mmc", + .if_type = IF_TYPE_MMC, + .max_devs = -1, + .get_dev = mmc_get_dev, + .select_hwpart = mmc_select_hwpartp, +}; diff --git a/drivers/mmc/mmc_private.h b/drivers/mmc/mmc_private.h index 9f0d5c2384..49ec022a9e 100644 --- a/drivers/mmc/mmc_private.h +++ b/drivers/mmc/mmc_private.h @@ -20,6 +20,14 @@ extern int mmc_set_blocklen(struct mmc *mmc, int len); void mmc_adapter_card_type_ident(void); #endif +#ifdef CONFIG_BLK +ulong mmc_bread(struct udevice *dev, lbaint_t start, lbaint_t blkcnt, + void *dst); +#else +ulong mmc_bread(struct blk_desc *block_dev, lbaint_t start, lbaint_t blkcnt, + void *dst); +#endif + #ifndef CONFIG_SPL_BUILD unsigned long mmc_berase(struct blk_desc *block_dev, lbaint_t start, @@ -65,6 +73,25 @@ static inline ulong mmc_bwrite(struct blk_desc *block_dev, lbaint_t start, #endif /* CONFIG_SPL_BUILD */ +#ifdef CONFIG_MMC_TRACE +void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd); +void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, int ret); +void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd); +#else +static inline void mmmc_trace_before_send(struct mmc *mmc, struct mmc_cmd *cmd) +{ +} + +static inline void mmmc_trace_after_send(struct mmc *mmc, struct mmc_cmd *cmd, + int ret) +{ +} + +static inline void mmc_trace_state(struct mmc *mmc, struct mmc_cmd *cmd) +{ +} +#endif + /** * mmc_get_next_devnum() - Get the next available MMC device number * @@ -89,4 +116,24 @@ void mmc_list_init(void); */ void mmc_list_add(struct mmc *mmc); +/** + * mmc_switch_part() - Switch to a new MMC hardware partition + * + * @mmc: MMC device + * @part_num: Hardware partition number + * @return 0 if OK, -ve on error + */ +int mmc_switch_part(struct mmc *mmc, unsigned int part_num); + +/** + * mmc_switch() - Issue and MMC switch mode command + * + * @mmc: MMC device + * @set: Unused + * @index: Cmdarg index + * @value: Cmdarg value + * @return 0 if OK, -ve on error + */ +int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value); + #endif /* _MMC_PRIVATE_H_ */ diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 64bbf0cd25..70a8d96eee 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -36,6 +36,11 @@ /* Non standard (?) SDHCI register */ #define SDHCI_VENDOR_SPEC_CAPABILITIES0 0x11c +struct msm_sdhc_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + struct msm_sdhc { struct sdhci_host host; void *base; @@ -81,9 +86,12 @@ static int msm_sdc_clk_init(struct udevice *dev) static int msm_sdc_probe(struct udevice *dev) { + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct msm_sdhc_plat *plat = dev_get_platdata(dev); struct msm_sdhc *prv = dev_get_priv(dev); struct sdhci_host *host = &prv->host; u32 core_version, core_minor, core_major; + u32 caps; int ret; host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_BROKEN_R1B; @@ -127,7 +135,7 @@ static int msm_sdc_probe(struct udevice *dev) * controller versions and must be explicitly enabled. */ if (core_major >= 1 && core_minor != 0x11 && core_minor != 0x12) { - u32 caps = readl(host->ioaddr + SDHCI_CAPABILITIES); + caps = readl(host->ioaddr + SDHCI_CAPABILITIES); caps |= SDHCI_CAN_VDD_300 | SDHCI_CAN_DO_8BIT; writel(caps, host->ioaddr + SDHCI_VENDOR_SPEC_CAPABILITIES0); } @@ -135,8 +143,17 @@ static int msm_sdc_probe(struct udevice *dev) /* Set host controller version */ host->version = sdhci_readw(host, SDHCI_HOST_VERSION); - /* automatically detect max and min speed */ - return add_sdhci(host, 0, 0); + caps = sdhci_readl(host, SDHCI_CAPABILITIES); + ret = sdhci_setup_cfg(&plat->cfg, dev->name, host->bus_width, + caps, 0, 0, host->version, host->quirks, 0); + host->mmc = &plat->mmc; + if (ret) + return ret; + host->mmc->priv = &prv->host; + host->mmc->dev = dev; + upriv->mmc = host->mmc; + + return sdhci_probe(dev); } static int msm_sdc_remove(struct udevice *dev) @@ -171,6 +188,18 @@ static int msm_ofdata_to_platdata(struct udevice *dev) return 0; } +static int msm_sdc_bind(struct udevice *dev) +{ + struct msm_sdhc_plat *plat = dev_get_platdata(dev); + int ret; + + ret = sdhci_bind(dev, &plat->mmc, &plat->cfg); + if (ret) + return ret; + + return 0; +} + static const struct udevice_id msm_mmc_ids[] = { { .compatible = "qcom,sdhci-msm-v4" }, { } @@ -181,7 +210,10 @@ U_BOOT_DRIVER(msm_sdc_drv) = { .id = UCLASS_MMC, .of_match = msm_mmc_ids, .ofdata_to_platdata = msm_ofdata_to_platdata, + .ops = &sdhci_ops, + .bind = msm_sdc_bind, .probe = msm_sdc_probe, .remove = msm_sdc_remove, .priv_auto_alloc_size = sizeof(struct msm_sdhc), + .platdata_auto_alloc_size = sizeof(struct msm_sdhc_plat), }; diff --git a/drivers/mmc/rockchip_dw_mmc.c b/drivers/mmc/rockchip_dw_mmc.c index d41d60ce35..691a51557d 100644 --- a/drivers/mmc/rockchip_dw_mmc.c +++ b/drivers/mmc/rockchip_dw_mmc.c @@ -66,9 +66,7 @@ static int rockchip_dwmmc_ofdata_to_platdata(struct udevice *dev) static int rockchip_dwmmc_probe(struct udevice *dev) { -#ifdef CONFIG_BLK struct rockchip_mmc_plat *plat = dev_get_platdata(dev); -#endif struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); struct rockchip_dwmmc_priv *priv = dev_get_priv(dev); struct dwmci_host *host = &priv->host; @@ -106,33 +104,24 @@ static int rockchip_dwmmc_probe(struct udevice *dev) return ret; } #endif -#ifdef CONFIG_BLK dwmci_setup_cfg(&plat->cfg, dev->name, host->buswidth, host->caps, minmax[1], minmax[0]); host->mmc = &plat->mmc; -#else - ret = add_dwmci(host, minmax[1], minmax[0]); - if (ret) - return ret; - -#endif host->mmc->priv = &priv->host; host->mmc->dev = dev; upriv->mmc = host->mmc; - return 0; + return dwmci_probe(dev); } static int rockchip_dwmmc_bind(struct udevice *dev) { -#ifdef CONFIG_BLK struct rockchip_mmc_plat *plat = dev_get_platdata(dev); int ret; ret = dwmci_bind(dev, &plat->mmc, &plat->cfg); if (ret) return ret; -#endif return 0; } @@ -147,6 +136,7 @@ U_BOOT_DRIVER(rockchip_dwmmc_drv) = { .id = UCLASS_MMC, .of_match = rockchip_dwmmc_ids, .ofdata_to_platdata = rockchip_dwmmc_ofdata_to_platdata, + .ops = &dm_dwmci_ops, .bind = rockchip_dwmmc_bind, .probe = rockchip_dwmmc_probe, .priv_auto_alloc_size = sizeof(struct rockchip_dwmmc_priv), diff --git a/drivers/mmc/sandbox_mmc.c b/drivers/mmc/sandbox_mmc.c index 7da059c43c..5f1333b748 100644 --- a/drivers/mmc/sandbox_mmc.c +++ b/drivers/mmc/sandbox_mmc.c @@ -25,7 +25,7 @@ struct sandbox_mmc_plat { * This emulate an SD card version 2. Single-block reads result in zero data. * Multiple-block reads return a test string. */ -static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, +static int sandbox_mmc_send_cmd(struct udevice *dev, struct mmc_cmd *cmd, struct mmc_data *data) { switch (cmd->cmdidx) { @@ -85,25 +85,20 @@ static int sandbox_mmc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, return 0; } -static void sandbox_mmc_set_ios(struct mmc *mmc) -{ -} - -static int sandbox_mmc_init(struct mmc *mmc) +static int sandbox_mmc_set_ios(struct udevice *dev) { return 0; } -static int sandbox_mmc_getcd(struct mmc *mmc) +static int sandbox_mmc_get_cd(struct udevice *dev) { return 1; } -static const struct mmc_ops sandbox_mmc_ops = { +static const struct dm_mmc_ops sandbox_mmc_ops = { .send_cmd = sandbox_mmc_send_cmd, .set_ios = sandbox_mmc_set_ios, - .init = sandbox_mmc_init, - .getcd = sandbox_mmc_getcd, + .get_cd = sandbox_mmc_get_cd, }; int sandbox_mmc_probe(struct udevice *dev) @@ -120,7 +115,6 @@ int sandbox_mmc_bind(struct udevice *dev) int ret; cfg->name = dev->name; - cfg->ops = &sandbox_mmc_ops; cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS | MMC_MODE_8BIT; cfg->voltages = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34; cfg->f_min = 1000000; @@ -150,6 +144,7 @@ U_BOOT_DRIVER(mmc_sandbox) = { .name = "mmc_sandbox", .id = UCLASS_MMC, .of_match = sandbox_mmc_ids, + .ops = &sandbox_mmc_ops, .bind = sandbox_mmc_bind, .unbind = sandbox_mmc_unbind, .probe = sandbox_mmc_probe, diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 604f18dcc9..de8d8ea70c 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c @@ -9,6 +9,7 @@ */ #include <common.h> +#include <errno.h> #include <malloc.h> #include <mmc.h> #include <sdhci.h> @@ -129,9 +130,17 @@ static int sdhci_transfer_data(struct sdhci_host *host, struct mmc_data *data, #define CONFIG_SDHCI_CMD_DEFAULT_TIMEOUT 100 #define SDHCI_READ_STATUS_TIMEOUT 1000 +#ifdef CONFIG_DM_MMC_OPS +static int sdhci_send_command(struct udevice *dev, struct mmc_cmd *cmd, + struct mmc_data *data) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + +#else static int sdhci_send_command(struct mmc *mmc, struct mmc_cmd *cmd, - struct mmc_data *data) + struct mmc_data *data) { +#endif struct sdhci_host *host = mmc->priv; unsigned int stat = 0; int ret = 0; @@ -389,8 +398,14 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL); } +#ifdef CONFIG_DM_MMC_OPS +static int sdhci_set_ios(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); +#else static void sdhci_set_ios(struct mmc *mmc) { +#endif u32 ctrl; struct sdhci_host *host = mmc->priv; @@ -426,6 +441,9 @@ static void sdhci_set_ios(struct mmc *mmc) ctrl &= ~SDHCI_CTRL_HISPD; sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); +#ifdef CONFIG_DM_MMC_OPS + return 0; +#endif } static int sdhci_init(struct mmc *mmc) @@ -472,80 +490,110 @@ static int sdhci_init(struct mmc *mmc) return 0; } +#ifdef CONFIG_DM_MMC_OPS +int sdhci_probe(struct udevice *dev) +{ + struct mmc *mmc = mmc_get_mmc_dev(dev); + + return sdhci_init(mmc); +} +const struct dm_mmc_ops sdhci_ops = { + .send_cmd = sdhci_send_command, + .set_ios = sdhci_set_ios, +}; +#else static const struct mmc_ops sdhci_ops = { .send_cmd = sdhci_send_command, .set_ios = sdhci_set_ios, .init = sdhci_init, }; +#endif -int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) +int sdhci_setup_cfg(struct mmc_config *cfg, const char *name, int buswidth, + uint caps, u32 max_clk, u32 min_clk, uint version, + uint quirks, uint host_caps) { - unsigned int caps; - - host->cfg.name = host->name; - host->cfg.ops = &sdhci_ops; - - caps = sdhci_readl(host, SDHCI_CAPABILITIES); -#ifdef CONFIG_MMC_SDMA - if (!(caps & SDHCI_CAN_DO_SDMA)) { - printf("%s: Your controller doesn't support SDMA!!\n", - __func__); - return -1; - } + cfg->name = name; +#ifndef CONFIG_DM_MMC_OPS + cfg->ops = &sdhci_ops; #endif - if (max_clk) - host->cfg.f_max = max_clk; + cfg->f_max = max_clk; else { - if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) - host->cfg.f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) - >> SDHCI_CLOCK_BASE_SHIFT; + if (version >= SDHCI_SPEC_300) + cfg->f_max = (caps & SDHCI_CLOCK_V3_BASE_MASK) >> + SDHCI_CLOCK_BASE_SHIFT; else - host->cfg.f_max = (caps & SDHCI_CLOCK_BASE_MASK) - >> SDHCI_CLOCK_BASE_SHIFT; - host->cfg.f_max *= 1000000; - } - if (host->cfg.f_max == 0) { - printf("%s: Hardware doesn't specify base clock frequency\n", - __func__); - return -1; + cfg->f_max = (caps & SDHCI_CLOCK_BASE_MASK) >> + SDHCI_CLOCK_BASE_SHIFT; + cfg->f_max *= 1000000; } + if (cfg->f_max == 0) + return -EINVAL; if (min_clk) - host->cfg.f_min = min_clk; + cfg->f_min = min_clk; else { - if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) - host->cfg.f_min = host->cfg.f_max / - SDHCI_MAX_DIV_SPEC_300; + if (version >= SDHCI_SPEC_300) + cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_300; else - host->cfg.f_min = host->cfg.f_max / - SDHCI_MAX_DIV_SPEC_200; + cfg->f_min = cfg->f_max / SDHCI_MAX_DIV_SPEC_200; } - - host->cfg.voltages = 0; + cfg->voltages = 0; if (caps & SDHCI_CAN_VDD_330) - host->cfg.voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; + cfg->voltages |= MMC_VDD_32_33 | MMC_VDD_33_34; if (caps & SDHCI_CAN_VDD_300) - host->cfg.voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; + cfg->voltages |= MMC_VDD_29_30 | MMC_VDD_30_31; if (caps & SDHCI_CAN_VDD_180) - host->cfg.voltages |= MMC_VDD_165_195; + cfg->voltages |= MMC_VDD_165_195; - if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE) - host->cfg.voltages |= host->voltages; - - host->cfg.host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT; - if (SDHCI_GET_VERSION(host) >= SDHCI_SPEC_300) { + cfg->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_4BIT; + if (version >= SDHCI_SPEC_300) { if (caps & SDHCI_CAN_DO_8BIT) - host->cfg.host_caps |= MMC_MODE_8BIT; + cfg->host_caps |= MMC_MODE_8BIT; } - if (host->quirks & SDHCI_QUIRK_NO_HISPD_BIT) - host->cfg.host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz); + if (quirks & SDHCI_QUIRK_NO_HISPD_BIT) + cfg->host_caps &= ~(MMC_MODE_HS | MMC_MODE_HS_52MHz); - if (host->host_caps) - host->cfg.host_caps |= host->host_caps; + if (host_caps) + cfg->host_caps |= host_caps; - host->cfg.b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + cfg->b_max = CONFIG_SYS_MMC_MAX_BLK_COUNT; + + return 0; +} + +#ifdef CONFIG_BLK +int sdhci_bind(struct udevice *dev, struct mmc *mmc, struct mmc_config *cfg) +{ + return mmc_bind(dev, mmc, cfg); +} +#else +int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) +{ + unsigned int caps; + + caps = sdhci_readl(host, SDHCI_CAPABILITIES); +#ifdef CONFIG_MMC_SDMA + if (!(caps & SDHCI_CAN_DO_SDMA)) { + printf("%s: Your controller doesn't support SDMA!!\n", + __func__); + return -1; + } +#endif + + if (sdhci_setup_cfg(&host->cfg, host->name, host->bus_width, caps, + max_clk, min_clk, SDHCI_GET_VERSION(host), + host->quirks, host->host_caps)) { + printf("%s: Hardware doesn't specify base clock frequency\n", + __func__); + return -EINVAL; + } + + if (host->quirks & SDHCI_QUIRK_BROKEN_VOLTAGE) + host->cfg.voltages |= host->voltages; sdhci_reset(host, SDHCI_RESET_ALL); @@ -557,3 +605,4 @@ int add_sdhci(struct sdhci_host *host, u32 max_clk, u32 min_clk) return 0; } +#endif diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 8858f0768a..8ba72e30b1 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -80,7 +80,7 @@ static int dw_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, return ret; } -#if CONFIG_DM_ETH +#if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_GPIO) static int dw_mdio_reset(struct mii_dev *bus) { struct udevice *dev = bus->priv; @@ -126,7 +126,7 @@ static int dw_mdio_init(const char *name, void *priv) bus->read = dw_mdio_read; bus->write = dw_mdio_write; snprintf(bus->name, sizeof(bus->name), "%s", name); -#ifdef CONFIG_DM_ETH +#if defined(CONFIG_DM_ETH) && defined(CONFIG_DM_GPIO) bus->reset = dw_mdio_reset; #endif @@ -690,11 +690,15 @@ static const struct eth_ops designware_eth_ops = { static int designware_eth_ofdata_to_platdata(struct udevice *dev) { struct dw_eth_pdata *dw_pdata = dev_get_platdata(dev); +#ifdef CONFIG_DM_GPIO struct dw_eth_dev *priv = dev_get_priv(dev); +#endif struct eth_pdata *pdata = &dw_pdata->eth_pdata; const char *phy_mode; const fdt32_t *cell; +#ifdef CONFIG_DM_GPIO int reset_flags = GPIOD_IS_OUT; +#endif int ret = 0; pdata->iobase = dev_get_addr(dev); @@ -712,6 +716,7 @@ static int designware_eth_ofdata_to_platdata(struct udevice *dev) if (cell) pdata->max_speed = fdt32_to_cpu(*cell); +#ifdef CONFIG_DM_GPIO if (fdtdec_get_bool(gd->fdt_blob, dev->of_offset, "snps,reset-active-low")) reset_flags |= GPIOD_ACTIVE_LOW; @@ -724,6 +729,7 @@ static int designware_eth_ofdata_to_platdata(struct udevice *dev) } else if (ret == -ENOENT) { ret = 0; } +#endif return ret; } diff --git a/drivers/net/designware.h b/drivers/net/designware.h index 51ba769cfb..d345c5b0c3 100644 --- a/drivers/net/designware.h +++ b/drivers/net/designware.h @@ -8,7 +8,9 @@ #ifndef _DW_ETH_H #define _DW_ETH_H -#include <asm/gpio.h> +#ifdef CONFIG_DM_GPIO +#include <asm-generic/gpio.h> +#endif #define CONFIG_TX_DESCR_NUM 16 #define CONFIG_RX_DESCR_NUM 16 @@ -234,7 +236,10 @@ struct dw_eth_dev { #ifndef CONFIG_DM_ETH struct eth_device *dev; #endif +#ifdef CONFIG_DM_GPIO struct gpio_desc reset_gpio; +#endif + struct phy_device *phydev; struct mii_dev *bus; }; diff --git a/drivers/net/phy/aquantia.c b/drivers/net/phy/aquantia.c index f90c2ae3bb..ad12f6d61f 100644 --- a/drivers/net/phy/aquantia.c +++ b/drivers/net/phy/aquantia.c @@ -147,6 +147,32 @@ struct phy_driver aqr105_driver = { .shutdown = &gen10g_shutdown, }; +struct phy_driver aqr106_driver = { + .name = "Aquantia AQR106", + .uid = 0x3a1b4d0, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS| + MDIO_MMD_PHYXS | MDIO_MMD_AN | + MDIO_MMD_VEND1), + .config = &aquantia_config, + .startup = &aquantia_startup, + .shutdown = &gen10g_shutdown, +}; + +struct phy_driver aqr107_driver = { + .name = "Aquantia AQR107", + .uid = 0x3a1b4e0, + .mask = 0xfffffff0, + .features = PHY_10G_FEATURES, + .mmds = (MDIO_MMD_PMAPMD | MDIO_MMD_PCS| + MDIO_MMD_PHYXS | MDIO_MMD_AN | + MDIO_MMD_VEND1), + .config = &aquantia_config, + .startup = &aquantia_startup, + .shutdown = &gen10g_shutdown, +}; + struct phy_driver aqr405_driver = { .name = "Aquantia AQR405", .uid = 0x3a1b4b2, @@ -165,6 +191,8 @@ int phy_aquantia_init(void) phy_register(&aq1202_driver); phy_register(&aq2104_driver); phy_register(&aqr105_driver); + phy_register(&aqr106_driver); + phy_register(&aqr107_driver); phy_register(&aqr405_driver); return 0; diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c index 843b083f8f..1cc0b40935 100644 --- a/drivers/net/rtl8169.c +++ b/drivers/net/rtl8169.c @@ -666,12 +666,12 @@ static int rtl_send_common(pci_dev_t dev, unsigned long dev_iobase, puts("tx timeout/error\n"); printf("%s elapsed time : %lu\n", __func__, currticks()-stime); #endif - ret = 0; + ret = -ETIMEDOUT; } else { #ifdef DEBUG_RTL8169_TX puts("tx done\n"); #endif - ret = length; + ret = 0; } /* Delay to make net console (nc) work properly */ udelay(20); diff --git a/drivers/pci/pci_tegra.c b/drivers/pci/pci_tegra.c index c5b04daffa..352cdef56a 100644 --- a/drivers/pci/pci_tegra.c +++ b/drivers/pci/pci_tegra.c @@ -154,15 +154,6 @@ DECLARE_GLOBAL_DATA_PTR; #define PADS_REFCLK_CFG_PREDI_SHIFT 8 /* 11:8 */ #define PADS_REFCLK_CFG_DRVI_SHIFT 12 /* 15:12 */ -/* Default value provided by HW engineering is 0xfa5c */ -#define PADS_REFCLK_CFG_VALUE \ - ( \ - (0x17 << PADS_REFCLK_CFG_TERM_SHIFT) | \ - (0 << PADS_REFCLK_CFG_E_TERM_SHIFT) | \ - (0xa << PADS_REFCLK_CFG_PREDI_SHIFT) | \ - (0xf << PADS_REFCLK_CFG_DRVI_SHIFT) \ - ) - #define RP_VEND_XP 0x00000F00 #define RP_VEND_XP_DL_UP (1 << 30) @@ -198,6 +189,8 @@ struct tegra_pcie_soc { unsigned int num_ports; unsigned long pads_pll_ctl; unsigned long tx_ref_sel; + u32 pads_refclk_cfg0; + u32 pads_refclk_cfg1; bool has_pex_clkreq_en; bool has_pex_bias_ctrl; bool has_cml_clk; @@ -627,13 +620,6 @@ static int tegra_pcie_phy_enable(struct tegra_pcie *pcie) value |= PADS_PLL_CTL_RST_B4SM; pads_writel(pcie, value, soc->pads_pll_ctl); - /* configure the reference clock driver */ - value = PADS_REFCLK_CFG_VALUE | (PADS_REFCLK_CFG_VALUE << 16); - pads_writel(pcie, value, PADS_REFCLK_CFG0); - - if (soc->num_ports > 2) - pads_writel(pcie, PADS_REFCLK_CFG_VALUE, PADS_REFCLK_CFG1); - /* wait for the PLL to lock */ err = tegra_pcie_pll_wait(pcie, 500); if (err < 0) { @@ -827,20 +813,21 @@ static void tegra_pcie_port_reset(struct tegra_pcie_port *port) static void tegra_pcie_port_enable(struct tegra_pcie_port *port) { - const struct tegra_pcie_soc *soc = port->pcie->soc; + struct tegra_pcie *pcie = port->pcie; + const struct tegra_pcie_soc *soc = pcie->soc; unsigned long ctrl = tegra_pcie_port_get_pex_ctrl(port); unsigned long value; /* enable reference clock */ - value = afi_readl(port->pcie, ctrl); + value = afi_readl(pcie, ctrl); value |= AFI_PEX_CTRL_REFCLK_EN; - if (port->pcie->soc->has_pex_clkreq_en) + if (pcie->soc->has_pex_clkreq_en) value |= AFI_PEX_CTRL_CLKREQ_EN; value |= AFI_PEX_CTRL_OVERRIDE_EN; - afi_writel(port->pcie, value, ctrl); + afi_writel(pcie, value, ctrl); tegra_pcie_port_reset(port); @@ -849,6 +836,11 @@ static void tegra_pcie_port_enable(struct tegra_pcie_port *port) value |= RP_VEND_CTL2_PCA_ENABLE; rp_writel(port, value, RP_VEND_CTL2); } + + /* configure the reference clock driver */ + pads_writel(pcie, soc->pads_refclk_cfg0, PADS_REFCLK_CFG0); + if (soc->num_ports > 2) + pads_writel(pcie, soc->pads_refclk_cfg1, PADS_REFCLK_CFG1); } static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port) @@ -943,6 +935,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 2, .pads_pll_ctl = PADS_PLL_CTL_TEGRA20, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_DIV10, + .pads_refclk_cfg0 = 0xfa5cfa5c, .has_pex_clkreq_en = false, .has_pex_bias_ctrl = false, .has_cml_clk = false, @@ -952,6 +945,8 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 3, .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0xfa5cfa5c, + .pads_refclk_cfg1 = 0xfa5cfa5c, .has_pex_clkreq_en = true, .has_pex_bias_ctrl = true, .has_cml_clk = true, @@ -961,6 +956,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 2, .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0x44ac44ac, .has_pex_clkreq_en = true, .has_pex_bias_ctrl = true, .has_cml_clk = true, @@ -970,6 +966,7 @@ static const struct tegra_pcie_soc pci_tegra_soc[] = { .num_ports = 2, .pads_pll_ctl = PADS_PLL_CTL_TEGRA30, .tx_ref_sel = PADS_PLL_CTL_TXCLKREF_BUF_EN, + .pads_refclk_cfg0 = 0x90b890b8, .has_pex_clkreq_en = true, .has_pex_bias_ctrl = true, .has_cml_clk = true, diff --git a/drivers/video/rockchip/rk_hdmi.c b/drivers/video/rockchip/rk_hdmi.c index 8dd2c87090..7976c5e263 100644 --- a/drivers/video/rockchip/rk_hdmi.c +++ b/drivers/video/rockchip/rk_hdmi.c @@ -666,7 +666,7 @@ static int hdmi_wait_for_hpd(struct rk3288_hdmi *regs) if (hdmi_get_plug_in_status(regs)) return 0; udelay(100); - } while (get_timer(start) < 30000); + } while (get_timer(start) < 300); return -1; } diff --git a/drivers/video/tegra.c b/drivers/video/tegra.c index c01809e89e..217f05f9e2 100644 --- a/drivers/video/tegra.c +++ b/drivers/video/tegra.c @@ -6,6 +6,7 @@ #include <common.h> #include <dm.h> #include <fdtdec.h> +#include <panel.h> #include <pwm.h> #include <video.h> #include <asm/system.h> @@ -21,70 +22,16 @@ DECLARE_GLOBAL_DATA_PTR; -/* These are the stages we go throuh in enabling the LCD */ -enum stage_t { - STAGE_START, - STAGE_PANEL_VDD, - STAGE_LVDS, - STAGE_BACKLIGHT_VDD, - STAGE_PWM, - STAGE_BACKLIGHT_EN, - STAGE_DONE, -}; - -#define FDT_LCD_TIMINGS 4 - -enum { - FDT_LCD_TIMING_REF_TO_SYNC, - FDT_LCD_TIMING_SYNC_WIDTH, - FDT_LCD_TIMING_BACK_PORCH, - FDT_LCD_TIMING_FRONT_PORCH, - - FDT_LCD_TIMING_COUNT, -}; - -enum lcd_cache_t { - FDT_LCD_CACHE_OFF = 0, - FDT_LCD_CACHE_WRITE_THROUGH = 1 << 0, - FDT_LCD_CACHE_WRITE_BACK = 1 << 1, - FDT_LCD_CACHE_FLUSH = 1 << 2, - FDT_LCD_CACHE_WRITE_BACK_FLUSH = FDT_LCD_CACHE_WRITE_BACK | - FDT_LCD_CACHE_FLUSH, -}; - /* Information about the display controller */ struct tegra_lcd_priv { - enum stage_t stage; /* Current stage we are at */ - unsigned long timer_next; /* Time we can move onto next stage */ int width; /* width in pixels */ int height; /* height in pixels */ - - /* - * log2 of number of bpp, in general, unless it bpp is 24 in which - * case this field holds 24 also! This is a U-Boot thing. - */ - int log2_bpp; + enum video_log2_bpp log2_bpp; /* colour depth */ + struct display_timing timing; + struct udevice *panel; struct disp_ctlr *disp; /* Display controller to use */ fdt_addr_t frame_buffer; /* Address of frame buffer */ unsigned pixel_clock; /* Pixel clock in Hz */ - uint horiz_timing[FDT_LCD_TIMING_COUNT]; /* Horizontal timing */ - uint vert_timing[FDT_LCD_TIMING_COUNT]; /* Vertical timing */ - struct udevice *pwm; - int pwm_channel; /* PWM channel to use for backlight */ - enum lcd_cache_t cache_type; - - struct gpio_desc backlight_en; /* GPIO for backlight enable */ - struct gpio_desc lvds_shutdown; /* GPIO for lvds shutdown */ - struct gpio_desc backlight_vdd; /* GPIO for backlight vdd */ - struct gpio_desc panel_vdd; /* GPIO for panel vdd */ - /* - * Panel required timings - * Timing 1: delay between panel_vdd-rise and data-rise - * Timing 2: delay between data-rise and backlight_vdd-rise - * Timing 3: delay between backlight_vdd and pwm-rise - * Timing 4: delay between pwm-rise and backlight_en-rise - */ - uint panel_timings[FDT_LCD_TIMINGS]; }; enum { @@ -150,26 +97,23 @@ static void update_window(struct dc_ctlr *dc, struct disp_ctl_win *win) writel(val, &dc->cmd.state_ctrl); } -static void write_pair(struct tegra_lcd_priv *priv, int item, u32 *reg) -{ - writel(priv->horiz_timing[item] | - (priv->vert_timing[item] << 16), reg); -} - static int update_display_mode(struct dc_disp_reg *disp, struct tegra_lcd_priv *priv) { + struct display_timing *dt = &priv->timing; unsigned long val; unsigned long rate; unsigned long div; writel(0x0, &disp->disp_timing_opt); - write_pair(priv, FDT_LCD_TIMING_REF_TO_SYNC, &disp->ref_to_sync); - write_pair(priv, FDT_LCD_TIMING_SYNC_WIDTH, &disp->sync_width); - write_pair(priv, FDT_LCD_TIMING_BACK_PORCH, &disp->back_porch); - write_pair(priv, FDT_LCD_TIMING_FRONT_PORCH, &disp->front_porch); - writel(priv->width | (priv->height << 16), &disp->disp_active); + writel(1 | 1 << 16, &disp->ref_to_sync); + writel(dt->hsync_len.typ | dt->vsync_len.typ << 16, &disp->sync_width); + writel(dt->hback_porch.typ | dt->vback_porch.typ << 16, + &disp->back_porch); + writel((dt->hfront_porch.typ - 1) | (dt->vfront_porch.typ - 1) << 16, + &disp->front_porch); + writel(dt->hactive.typ | (dt->vactive.typ << 16), &disp->disp_active); val = DE_SELECT_ACTIVE << DE_SELECT_SHIFT; val |= DE_CONTROL_NORMAL << DE_CONTROL_SHIFT; @@ -287,12 +231,11 @@ static int setup_window(struct disp_ctl_win *win, win->stride = priv->width * (1 << priv->log2_bpp) / 8; debug("%s: depth = %d\n", __func__, priv->log2_bpp); switch (priv->log2_bpp) { - case 5: - case 24: + case VIDEO_BPP32: win->fmt = COLOR_DEPTH_R8G8B8A8; win->bpp = 32; break; - case 4: + case VIDEO_BPP16: win->fmt = COLOR_DEPTH_B5G6R5; win->bpp = 16; break; @@ -305,18 +248,6 @@ static int setup_window(struct disp_ctl_win *win, return 0; } -static void debug_timing(const char *name, unsigned int timing[]) -{ -#ifdef DEBUG - int i; - - debug("%s timing: ", name); - for (i = 0; i < FDT_LCD_TIMING_COUNT; i++) - debug("%d ", timing[i]); - debug("\n"); -#endif -} - /** * Register a new display based on device tree configuration. * @@ -363,137 +294,35 @@ static int tegra_display_probe(const void *blob, struct tegra_lcd_priv *priv, return 0; } -/** - * Handle the next stage of device init - */ -static int handle_stage(const void *blob, struct tegra_lcd_priv *priv) -{ - debug("%s: stage %d\n", __func__, priv->stage); - - /* do the things for this stage */ - switch (priv->stage) { - case STAGE_START: - /* - * It is possible that the FDT has requested that the LCD be - * disabled. We currently don't support this. It would require - * changes to U-Boot LCD subsystem to have LCD support - * compiled in but not used. An easier option might be to - * still have a frame buffer, but leave the backlight off and - * remove all mention of lcd in the stdout environment - * variable. - */ - - funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); - break; - case STAGE_PANEL_VDD: - if (dm_gpio_is_valid(&priv->panel_vdd)) - dm_gpio_set_value(&priv->panel_vdd, 1); - break; - case STAGE_LVDS: - if (dm_gpio_is_valid(&priv->lvds_shutdown)) - dm_gpio_set_value(&priv->lvds_shutdown, 1); - break; - case STAGE_BACKLIGHT_VDD: - if (dm_gpio_is_valid(&priv->backlight_vdd)) - dm_gpio_set_value(&priv->backlight_vdd, 1); - break; - case STAGE_PWM: - /* Enable PWM at 15/16 high, 32768 Hz with divider 1 */ - pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); - pinmux_tristate_disable(PMUX_PINGRP_GPU); - - pwm_set_config(priv->pwm, priv->pwm_channel, 0xdf, 0xff); - pwm_set_enable(priv->pwm, priv->pwm_channel, true); - break; - case STAGE_BACKLIGHT_EN: - if (dm_gpio_is_valid(&priv->backlight_en)) - dm_gpio_set_value(&priv->backlight_en, 1); - break; - case STAGE_DONE: - break; - } - - /* set up timer for next stage */ - priv->timer_next = timer_get_us(); - if (priv->stage < FDT_LCD_TIMINGS) - priv->timer_next += priv->panel_timings[priv->stage] * 1000; - - /* move to next stage */ - priv->stage++; - return 0; -} - -/** - * Perform the next stage of the LCD init if it is time to do so. - * - * LCD init can be time-consuming because of the number of delays we need - * while waiting for the backlight power supply, etc. This function can - * be called at various times during U-Boot operation to advance the - * initialization of the LCD to the next stage if sufficient time has - * passed since the last stage. It keeps track of what stage it is up to - * and the time that it is permitted to move to the next stage. - * - * The final call should have wait=1 to complete the init. - * - * @param blob fdt blob containing LCD information - * @param wait 1 to wait until all init is complete, and then return - * 0 to return immediately, potentially doing nothing if it is - * not yet time for the next init. - */ -static int tegra_lcd_check_next_stage(const void *blob, - struct tegra_lcd_priv *priv, int wait) -{ - if (priv->stage == STAGE_DONE) - return 0; - - do { - /* wait if we need to */ - debug("%s: stage %d\n", __func__, priv->stage); - if (priv->stage != STAGE_START) { - int delay = priv->timer_next - timer_get_us(); - - if (delay > 0) { - if (wait) - udelay(delay); - else - return 0; - } - } - - if (handle_stage(blob, priv)) - return -1; - } while (wait && priv->stage != STAGE_DONE); - if (priv->stage == STAGE_DONE) - debug("%s: LCD init complete\n", __func__); - - return 0; -} - static int tegra_lcd_probe(struct udevice *dev) { struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); struct video_priv *uc_priv = dev_get_uclass_priv(dev); struct tegra_lcd_priv *priv = dev_get_priv(dev); const void *blob = gd->fdt_blob; - int type = DCACHE_OFF; + int ret; /* Initialize the Tegra display controller */ + funcmux_select(PERIPH_ID_DISP1, FUNCMUX_DEFAULT); if (tegra_display_probe(blob, priv, (void *)plat->base)) { printf("%s: Failed to probe display driver\n", __func__); return -1; } - tegra_lcd_check_next_stage(blob, priv, 1); + pinmux_set_func(PMUX_PINGRP_GPU, PMUX_FUNC_PWM); + pinmux_tristate_disable(PMUX_PINGRP_GPU); + + ret = panel_enable_backlight(priv->panel); + if (ret) { + debug("%s: Cannot enable backlight, ret=%d\n", __func__, ret); + return ret; + } - /* Set up the LCD caching as requested */ - if (priv->cache_type & FDT_LCD_CACHE_WRITE_THROUGH) - type = DCACHE_WRITETHROUGH; - else if (priv->cache_type & FDT_LCD_CACHE_WRITE_BACK) - type = DCACHE_WRITEBACK; - mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size, type); + mmu_set_region_dcache_behaviour(priv->frame_buffer, plat->size, + DCACHE_WRITETHROUGH); /* Enable flushing after LCD writes if requested */ - video_set_flush_dcache(dev, priv->cache_type & FDT_LCD_CACHE_FLUSH); + video_set_flush_dcache(dev, true); uc_priv->xsize = priv->width; uc_priv->ysize = priv->height; @@ -507,13 +336,11 @@ static int tegra_lcd_probe(struct udevice *dev) static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) { struct tegra_lcd_priv *priv = dev_get_priv(dev); - struct fdtdec_phandle_args args; const void *blob = gd->fdt_blob; + struct display_timing *timing; int node = dev->of_offset; - int front, back, ref; int panel_node; int rgb; - int bpp, bit; int ret; priv->disp = (struct disp_ctlr *)dev_get_addr(dev); @@ -523,96 +350,40 @@ static int tegra_lcd_ofdata_to_platdata(struct udevice *dev) } rgb = fdt_subnode_offset(blob, node, "rgb"); - - panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); - if (panel_node < 0) { - debug("%s: Cannot find panel information\n", __func__); + if (rgb < 0) { + debug("%s: Cannot find rgb subnode for '%s' (ret=%d)\n", + __func__, dev->name, rgb); return -EINVAL; } - priv->width = fdtdec_get_int(blob, panel_node, "xres", -1); - priv->height = fdtdec_get_int(blob, panel_node, "yres", -1); - priv->pixel_clock = fdtdec_get_int(blob, panel_node, "clock", 0); - if (!priv->pixel_clock || priv->width == -1 || priv->height == -1) { - debug("%s: Pixel parameters missing\n", __func__); - return -EINVAL; - } - - back = fdtdec_get_int(blob, panel_node, "left-margin", -1); - front = fdtdec_get_int(blob, panel_node, "right-margin", -1); - ref = fdtdec_get_int(blob, panel_node, "hsync-len", -1); - if ((back | front | ref) == -1) { - debug("%s: Horizontal parameters missing\n", __func__); - return -EINVAL; - } - - /* Use a ref-to-sync of 1 always, and take this from the front porch */ - priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; - priv->horiz_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; - priv->horiz_timing[FDT_LCD_TIMING_BACK_PORCH] = back; - priv->horiz_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - - priv->horiz_timing[FDT_LCD_TIMING_REF_TO_SYNC]; - debug_timing("horiz", priv->horiz_timing); - - back = fdtdec_get_int(blob, panel_node, "upper-margin", -1); - front = fdtdec_get_int(blob, panel_node, "lower-margin", -1); - ref = fdtdec_get_int(blob, panel_node, "vsync-len", -1); - if ((back | front | ref) == -1) { - debug("%s: Vertical parameters missing\n", __func__); - return -EINVAL; - } - - priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC] = 1; - priv->vert_timing[FDT_LCD_TIMING_SYNC_WIDTH] = ref; - priv->vert_timing[FDT_LCD_TIMING_BACK_PORCH] = back; - priv->vert_timing[FDT_LCD_TIMING_FRONT_PORCH] = front - - priv->vert_timing[FDT_LCD_TIMING_REF_TO_SYNC]; - debug_timing("vert", priv->vert_timing); - - bpp = fdtdec_get_int(blob, panel_node, "nvidia,bits-per-pixel", -1); - bit = ffs(bpp) - 1; - if (bpp == (1 << bit)) - priv->log2_bpp = bit; - else - priv->log2_bpp = bpp; - if (bpp == -1) { - debug("%s: Pixel bpp parameters missing\n", __func__); + ret = fdtdec_decode_display_timing(blob, rgb, 0, &priv->timing); + if (ret) { + debug("%s: Cannot read display timing for '%s' (ret=%d)\n", + __func__, dev->name, ret); return -EINVAL; } + timing = &priv->timing; + priv->width = timing->hactive.typ; + priv->height = timing->vactive.typ; + priv->pixel_clock = timing->pixelclock.typ; + priv->log2_bpp = VIDEO_BPP16; - if (fdtdec_parse_phandle_with_args(blob, panel_node, "nvidia,pwm", - "#pwm-cells", 0, 0, &args)) { - debug("%s: Unable to decode PWM\n", __func__); + /* + * Sadly the panel phandle is in an rgb subnode so we cannot use + * uclass_get_device_by_phandle(). + */ + panel_node = fdtdec_lookup_phandle(blob, rgb, "nvidia,panel"); + if (panel_node < 0) { + debug("%s: Cannot find panel information\n", __func__); return -EINVAL; } - - ret = uclass_get_device_by_of_offset(UCLASS_PWM, args.node, &priv->pwm); + ret = uclass_get_device_by_of_offset(UCLASS_PANEL, panel_node, + &priv->panel); if (ret) { - debug("%s: Unable to find PWM\n", __func__); - return -EINVAL; + debug("%s: Cannot find panel for '%s' (ret=%d)\n", __func__, + dev->name, ret); + return ret; } - priv->pwm_channel = args.args[0]; - - priv->cache_type = fdtdec_get_int(blob, panel_node, "nvidia,cache-type", - FDT_LCD_CACHE_WRITE_BACK_FLUSH); - - /* These GPIOs are all optional */ - gpio_request_by_name_nodev(blob, panel_node, - "nvidia,backlight-enable-gpios", 0, - &priv->backlight_en, GPIOD_IS_OUT); - gpio_request_by_name_nodev(blob, panel_node, - "nvidia,lvds-shutdown-gpios", 0, - &priv->lvds_shutdown, GPIOD_IS_OUT); - gpio_request_by_name_nodev(blob, panel_node, - "nvidia,backlight-vdd-gpios", 0, - &priv->backlight_vdd, GPIOD_IS_OUT); - gpio_request_by_name_nodev(blob, panel_node, - "nvidia,panel-vdd-gpios", 0, - &priv->panel_vdd, GPIOD_IS_OUT); - - if (fdtdec_get_int_array(blob, panel_node, "nvidia,panel-timings", - priv->panel_timings, FDT_LCD_TIMINGS)) - return -EINVAL; return 0; } |