diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/core/of_access.c | 18 | ||||
-rw-r--r-- | drivers/core/read.c | 8 | ||||
-rw-r--r-- | drivers/i2c/i2c-uclass.c | 54 | ||||
-rw-r--r-- | drivers/i2c/muxes/i2c-mux-uclass.c | 29 | ||||
-rw-r--r-- | drivers/pci/pcie_dw_mvebu.c | 4 | ||||
-rw-r--r-- | drivers/timer/tsc_timer.c | 55 |
6 files changed, 161 insertions, 7 deletions
diff --git a/drivers/core/of_access.c b/drivers/core/of_access.c index 14c020a687..945b81448c 100644 --- a/drivers/core/of_access.c +++ b/drivers/core/of_access.c @@ -812,6 +812,24 @@ int of_alias_get_id(const struct device_node *np, const char *stem) return id; } +int of_alias_get_highest_id(const char *stem) +{ + struct alias_prop *app; + int id = -1; + + mutex_lock(&of_mutex); + list_for_each_entry(app, &aliases_lookup, link) { + if (strcmp(app->stem, stem) != 0) + continue; + + if (app->id > id) + id = app->id; + } + mutex_unlock(&of_mutex); + + return id; +} + struct device_node *of_get_stdout(void) { return of_stdout; diff --git a/drivers/core/read.c b/drivers/core/read.c index 3c46b3674e..6bda077a34 100644 --- a/drivers/core/read.c +++ b/drivers/core/read.c @@ -264,3 +264,11 @@ u64 dev_translate_address(struct udevice *dev, const fdt32_t *in_addr) { return ofnode_translate_address(dev_ofnode(dev), in_addr); } + +int dev_read_alias_highest_id(const char *stem) +{ + if (of_live_active()) + return of_alias_get_highest_id(stem); + + return fdtdec_get_alias_highest_id(gd->fdt_blob, stem); +} diff --git a/drivers/i2c/i2c-uclass.c b/drivers/i2c/i2c-uclass.c index 975318e5f2..49e23a0a4b 100644 --- a/drivers/i2c/i2c-uclass.c +++ b/drivers/i2c/i2c-uclass.c @@ -619,13 +619,61 @@ static int i2c_child_post_bind(struct udevice *dev) #endif } +struct i2c_priv { + int max_id; +}; + +static int i2c_post_bind(struct udevice *dev) +{ + struct uclass *class = dev->uclass; + struct i2c_priv *priv = class->priv; + int ret = 0; + + /* Just for sure */ + if (!priv) + return -ENOMEM; + + debug("%s: %s, req_seq=%d\n", __func__, dev->name, dev->req_seq); + + /* if there is no alias ID, use the first free */ + if (dev->req_seq == -1) + dev->req_seq = ++priv->max_id; + + debug("%s: %s, new req_seq=%d\n", __func__, dev->name, dev->req_seq); + +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + ret = dm_scan_fdt_dev(dev); +#endif + return ret; +} + +int i2c_uclass_init(struct uclass *class) +{ + struct i2c_priv *priv = class->priv; + + /* Just for sure */ + if (!priv) + return -ENOMEM; + + /* Get the last allocated alias. */ +#if CONFIG_IS_ENABLED(OF_CONTROL) + priv->max_id = dev_read_alias_highest_id("i2c"); +#else + priv->max_id = -1; +#endif + + debug("%s: highest alias id is %d\n", __func__, priv->max_id); + + return 0; +} + UCLASS_DRIVER(i2c) = { .id = UCLASS_I2C, .name = "i2c", .flags = DM_UC_FLAG_SEQ_ALIAS, -#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) - .post_bind = dm_scan_fdt_dev, -#endif + .post_bind = i2c_post_bind, + .init = i2c_uclass_init, + .priv_auto_alloc_size = sizeof(struct i2c_priv), .post_probe = i2c_post_probe, .per_device_auto_alloc_size = sizeof(struct dm_i2c_bus), .per_child_platdata_auto_alloc_size = sizeof(struct dm_i2c_chip), diff --git a/drivers/i2c/muxes/i2c-mux-uclass.c b/drivers/i2c/muxes/i2c-mux-uclass.c index a680ee1762..8b1149997a 100644 --- a/drivers/i2c/muxes/i2c-mux-uclass.c +++ b/drivers/i2c/muxes/i2c-mux-uclass.c @@ -59,11 +59,34 @@ static int i2c_mux_post_bind(struct udevice *mux) dev_for_each_subnode(node, mux) { struct udevice *dev; const char *name; + const char *arrow = "->"; + char *full_name; + int parent_name_len, arrow_len, mux_name_len, name_len; name = ofnode_get_name(node); - ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv", name, - node, &dev); - debug(" - bind ret=%d, %s\n", ret, dev ? dev->name : NULL); + + /* Calculate lenghts of strings */ + parent_name_len = strlen(mux->parent->name); + arrow_len = strlen(arrow); + mux_name_len = strlen(mux->name); + name_len = strlen(name); + + full_name = calloc(1, parent_name_len + arrow_len + + mux_name_len + arrow_len + name_len + 1); + if (!full_name) + return -ENOMEM; + + /* Compose bus name */ + strcat(full_name, mux->parent->name); + strcat(full_name, arrow); + strcat(full_name, mux->name); + strcat(full_name, arrow); + strcat(full_name, name); + + ret = device_bind_driver_to_node(mux, "i2c_mux_bus_drv", + full_name, node, &dev); + debug(" - bind ret=%d, %s, req_seq %d\n", ret, + dev ? dev->name : NULL, dev->req_seq); if (ret) return ret; } diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c index 8081005c27..95fb41966f 100644 --- a/drivers/pci/pcie_dw_mvebu.c +++ b/drivers/pci/pcie_dw_mvebu.c @@ -489,7 +489,9 @@ static int pcie_dw_mvebu_probe(struct udevice *dev) * using this GPIO. */ if (dm_gpio_is_valid(&reset_gpio)) { - dm_gpio_set_value(&reset_gpio, 1); + dm_gpio_set_value(&reset_gpio, 1); /* assert */ + mdelay(200); + dm_gpio_set_value(&reset_gpio, 0); /* de-assert */ mdelay(200); } #else diff --git a/drivers/timer/tsc_timer.c b/drivers/timer/tsc_timer.c index ba940ebf1c..919caba8a1 100644 --- a/drivers/timer/tsc_timer.c +++ b/drivers/timer/tsc_timer.c @@ -19,8 +19,59 @@ #define MAX_NUM_FREQS 9 +#define INTEL_FAM6_SKYLAKE_MOBILE 0x4E +#define INTEL_FAM6_ATOM_GOLDMONT 0x5C /* Apollo Lake */ +#define INTEL_FAM6_SKYLAKE_DESKTOP 0x5E +#define INTEL_FAM6_ATOM_GOLDMONT_X 0x5F /* Denverton */ +#define INTEL_FAM6_KABYLAKE_MOBILE 0x8E +#define INTEL_FAM6_KABYLAKE_DESKTOP 0x9E + DECLARE_GLOBAL_DATA_PTR; +/* + * native_calibrate_tsc + * Determine TSC frequency via CPUID, else return 0. + */ +static unsigned long native_calibrate_tsc(void) +{ + struct cpuid_result tsc_info; + unsigned int crystal_freq; + + if (gd->arch.x86_vendor != X86_VENDOR_INTEL) + return 0; + + if (cpuid_eax(0) < 0x15) + return 0; + + tsc_info = cpuid(0x15); + + if (tsc_info.ebx == 0 || tsc_info.eax == 0) + return 0; + + crystal_freq = tsc_info.ecx / 1000; + + if (!crystal_freq) { + switch (gd->arch.x86_model) { + case INTEL_FAM6_SKYLAKE_MOBILE: + case INTEL_FAM6_SKYLAKE_DESKTOP: + case INTEL_FAM6_KABYLAKE_MOBILE: + case INTEL_FAM6_KABYLAKE_DESKTOP: + crystal_freq = 24000; /* 24.0 MHz */ + break; + case INTEL_FAM6_ATOM_GOLDMONT_X: + crystal_freq = 25000; /* 25.0 MHz */ + break; + case INTEL_FAM6_ATOM_GOLDMONT: + crystal_freq = 19200; /* 19.2 MHz */ + break; + default: + return 0; + } + } + + return (crystal_freq * tsc_info.ebx / tsc_info.eax) / 1000; +} + static unsigned long cpu_mhz_from_cpuid(void) { if (gd->arch.x86_vendor != X86_VENDOR_INTEL) @@ -350,6 +401,10 @@ static void tsc_timer_ensure_setup(bool early) if (!gd->arch.clock_rate) { unsigned long fast_calibrate; + fast_calibrate = native_calibrate_tsc(); + if (fast_calibrate) + goto done; + fast_calibrate = cpu_mhz_from_cpuid(); if (fast_calibrate) goto done; |