diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/Kconfig | 11 | ||||
-rw-r--r-- | drivers/of/Makefile | 2 | ||||
-rw-r--r-- | drivers/of/address.c | 32 | ||||
-rw-r--r-- | drivers/of/fdt.c | 16 | ||||
-rw-r--r-- | drivers/of/of_batterydata.c | 453 | ||||
-rw-r--r-- | drivers/of/of_reserved_mem.c | 4 | ||||
-rw-r--r-- | drivers/of/of_slimbus.c | 90 | ||||
-rw-r--r-- | drivers/of/platform.c | 6 |
8 files changed, 602 insertions, 12 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index e2a48415d969..60efdd584d15 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -102,6 +102,12 @@ config OF_RESERVED_MEM config OF_RESOLVE bool +config OF_SLIMBUS + def_tristate SLIMBUS + depends on SLIMBUS + help + OpenFirmware SLIMBUS accessors + config OF_OVERLAY bool "Device Tree overlays" select OF_DYNAMIC @@ -112,4 +118,9 @@ config OF_OVERLAY While this option is selected automatically when needed, you can enable it manually to improve device tree unit test coverage. +config OF_BATTERYDATA + def_bool y + help + OpenFirmware BatteryData accessors + endif # OF diff --git a/drivers/of/Makefile b/drivers/of/Makefile index 156c072b3117..025229bd2d9f 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -14,5 +14,7 @@ obj-$(CONFIG_OF_MTD) += of_mtd.o obj-$(CONFIG_OF_RESERVED_MEM) += of_reserved_mem.o obj-$(CONFIG_OF_RESOLVE) += resolver.o obj-$(CONFIG_OF_OVERLAY) += overlay.o +obj-$(CONFIG_OF_SLIMBUS) += of_slimbus.o +obj-$(CONFIG_OF_BATTERYDATA) += of_batterydata.o obj-$(CONFIG_OF_UNITTEST) += unittest-data/ diff --git a/drivers/of/address.c b/drivers/of/address.c index 9582c5703b3c..ec5eb17ae283 100644 --- a/drivers/of/address.c +++ b/drivers/of/address.c @@ -788,6 +788,22 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address) #endif } +const __be32 *of_get_address_by_name(struct device_node *dev, const char *name, + u64 *size, unsigned int *flags) +{ + int index; + if (!name) + return NULL; + + /* Try to read "reg-names" property and get the index by name */ + index = of_property_match_string(dev, "reg-names", name); + if (index < 0) + return NULL; + + return of_get_address(dev, index, size, flags); +} +EXPORT_SYMBOL(of_get_address_by_name); + static int __of_address_to_resource(struct device_node *dev, const __be32 *addrp, u64 size, unsigned int flags, const char *name, struct resource *r) @@ -1026,3 +1042,19 @@ bool of_dma_is_coherent(struct device_node *np) return false; } EXPORT_SYMBOL_GPL(of_dma_is_coherent); + +void __iomem *of_iomap_by_name(struct device_node *np, const char *name) +{ + int index; + + if (!name) + return NULL; + + /* Try to read "reg-names" property and get the index by name */ + index = of_property_match_string(np, "reg-names", name); + if (index < 0) + return NULL; + + return of_iomap(np, index); +} +EXPORT_SYMBOL(of_iomap_by_name); diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index c6d196188bc9..0438512f4d69 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -496,7 +496,7 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, if (size && early_init_dt_reserve_memory_arch(base, size, nomap) == 0) - pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", + pr_info("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", uname, &base, (unsigned long)size / SZ_1M); else pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", @@ -804,14 +804,13 @@ static inline void early_init_dt_check_for_initrd(unsigned long node) #endif /* CONFIG_BLK_DEV_INITRD */ #ifdef CONFIG_SERIAL_EARLYCON -extern struct of_device_id __earlycon_of_table[]; static int __init early_init_dt_scan_chosen_serial(void) { int offset; const char *p; int l; - const struct of_device_id *match = __earlycon_of_table; + const struct earlycon_id *match; const void *fdt = initial_boot_params; offset = fdt_path_offset(fdt, "/chosen"); @@ -834,19 +833,20 @@ static int __init early_init_dt_scan_chosen_serial(void) if (offset < 0) return -ENODEV; - while (match->compatible[0]) { + for (match = __earlycon_table; match < __earlycon_table_end; match++) { u64 addr; - if (fdt_node_check_compatible(fdt, offset, match->compatible)) { - match++; + if (!match->compatible[0]) + continue; + + if (fdt_node_check_compatible(fdt, offset, match->compatible)) continue; - } addr = fdt_translate_address(fdt, offset); if (addr == OF_BAD_ADDR) return -ENXIO; - of_setup_earlycon(addr, match->data); + of_setup_earlycon(addr, match->setup); return 0; } return -ENODEV; diff --git a/drivers/of/of_batterydata.c b/drivers/of/of_batterydata.c new file mode 100644 index 000000000000..4410f270f557 --- /dev/null +++ b/drivers/of/of_batterydata.c @@ -0,0 +1,453 @@ +/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) "%s: " fmt, __func__ + +#include <linux/err.h> +#include <linux/of.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/types.h> +#include <linux/batterydata-lib.h> +#include <linux/power_supply.h> + +static int of_batterydata_read_lut(const struct device_node *np, + int max_cols, int max_rows, int *ncols, int *nrows, + int *col_legend_data, int *row_legend_data, + int *lut_data) +{ + struct property *prop; + const __be32 *data; + int cols, rows, size, i, j, *out_values; + + prop = of_find_property(np, "qcom,lut-col-legend", NULL); + if (!prop) { + pr_err("%s: No col legend found\n", np->name); + return -EINVAL; + } else if (!prop->value) { + pr_err("%s: No col legend value found, np->name\n", np->name); + return -ENODATA; + } else if (prop->length > max_cols * sizeof(int)) { + pr_err("%s: Too many columns\n", np->name); + return -EINVAL; + } + + cols = prop->length/sizeof(int); + *ncols = cols; + data = prop->value; + for (i = 0; i < cols; i++) + *col_legend_data++ = be32_to_cpup(data++); + + prop = of_find_property(np, "qcom,lut-row-legend", NULL); + if (!prop || row_legend_data == NULL) { + /* single row lut */ + rows = 1; + } else if (!prop->value) { + pr_err("%s: No row legend value found\n", np->name); + return -ENODATA; + } else if (prop->length > max_rows * sizeof(int)) { + pr_err("%s: Too many rows\n", np->name); + return -EINVAL; + } else { + rows = prop->length/sizeof(int); + *nrows = rows; + data = prop->value; + for (i = 0; i < rows; i++) + *row_legend_data++ = be32_to_cpup(data++); + } + + prop = of_find_property(np, "qcom,lut-data", NULL); + if (!prop) { + pr_err("prop 'qcom,lut-data' not found\n"); + return -EINVAL; + } + data = prop->value; + size = prop->length/sizeof(int); + if (size != cols * rows) { + pr_err("%s: data size mismatch, %dx%d != %d\n", + np->name, cols, rows, size); + return -EINVAL; + } + for (i = 0; i < rows; i++) { + out_values = lut_data + (max_cols * i); + for (j = 0; j < cols; j++) { + *out_values++ = be32_to_cpup(data++); + pr_debug("Value = %d\n", *(out_values-1)); + } + } + + return 0; +} + +static int of_batterydata_read_sf_lut(struct device_node *data_node, + const char *name, struct sf_lut *lut) +{ + struct device_node *node = of_find_node_by_name(data_node, name); + int rc; + + if (!lut) { + pr_debug("No lut provided, skipping\n"); + return 0; + } else if (!node) { + pr_err("Couldn't find %s node.\n", name); + return -EINVAL; + } + + rc = of_batterydata_read_lut(node, PC_CC_COLS, PC_CC_ROWS, + &lut->cols, &lut->rows, lut->row_entries, + lut->percent, *lut->sf); + if (rc) { + pr_err("Failed to read %s node.\n", name); + return rc; + } + + return 0; +} + +static int of_batterydata_read_pc_temp_ocv_lut(struct device_node *data_node, + const char *name, struct pc_temp_ocv_lut *lut) +{ + struct device_node *node = of_find_node_by_name(data_node, name); + int rc; + + if (!lut) { + pr_debug("No lut provided, skipping\n"); + return 0; + } else if (!node) { + pr_err("Couldn't find %s node.\n", name); + return -EINVAL; + } + rc = of_batterydata_read_lut(node, PC_TEMP_COLS, PC_TEMP_ROWS, + &lut->cols, &lut->rows, lut->temp, lut->percent, + *lut->ocv); + if (rc) { + pr_err("Failed to read %s node.\n", name); + return rc; + } + + return 0; +} + +static int of_batterydata_read_ibat_temp_acc_lut(struct device_node *data_node, + const char *name, struct ibat_temp_acc_lut *lut) +{ + struct device_node *node = of_find_node_by_name(data_node, name); + int rc; + + if (!lut) { + pr_debug("No lut provided, skipping\n"); + return 0; + } else if (!node) { + pr_debug("Couldn't find %s node.\n", name); + return 0; + } + rc = of_batterydata_read_lut(node, ACC_TEMP_COLS, ACC_IBAT_ROWS, + &lut->cols, &lut->rows, lut->temp, lut->ibat, + *lut->acc); + if (rc) { + pr_err("Failed to read %s node.\n", name); + return rc; + } + + return 0; +} + +static int of_batterydata_read_single_row_lut(struct device_node *data_node, + const char *name, struct single_row_lut *lut) +{ + struct device_node *node = of_find_node_by_name(data_node, name); + int rc; + + if (!lut) { + pr_debug("No lut provided, skipping\n"); + return 0; + } else if (!node) { + pr_err("Couldn't find %s node.\n", name); + return -EINVAL; + } + + rc = of_batterydata_read_lut(node, MAX_SINGLE_LUT_COLS, 1, + &lut->cols, NULL, lut->x, NULL, lut->y); + if (rc) { + pr_err("Failed to read %s node.\n", name); + return rc; + } + + return 0; +} + +static int of_batterydata_read_batt_id_kohm(const struct device_node *np, + const char *propname, struct batt_ids *batt_ids) +{ + struct property *prop; + const __be32 *data; + int num, i, *id_kohm = batt_ids->kohm; + + prop = of_find_property(np, "qcom,batt-id-kohm", NULL); + if (!prop) { + pr_err("%s: No battery id resistor found\n", np->name); + return -EINVAL; + } else if (!prop->value) { + pr_err("%s: No battery id resistor value found, np->name\n", + np->name); + return -ENODATA; + } else if (prop->length > MAX_BATT_ID_NUM * sizeof(__be32)) { + pr_err("%s: Too many battery id resistors\n", np->name); + return -EINVAL; + } + + num = prop->length/sizeof(__be32); + batt_ids->num = num; + data = prop->value; + for (i = 0; i < num; i++) + *id_kohm++ = be32_to_cpup(data++); + + return 0; +} + +#define OF_PROP_READ(property, qpnp_dt_property, node, rc, optional) \ +do { \ + if (rc) \ + break; \ + rc = of_property_read_u32(node, "qcom," qpnp_dt_property, \ + &property); \ + \ + if ((rc == -EINVAL) && optional) { \ + property = -EINVAL; \ + rc = 0; \ + } else if (rc) { \ + pr_err("Error reading " #qpnp_dt_property \ + " property rc = %d\n", rc); \ + } \ +} while (0) + +static int of_batterydata_load_battery_data(struct device_node *node, + int best_id_kohm, + struct bms_battery_data *batt_data) +{ + int rc; + + rc = of_batterydata_read_single_row_lut(node, "qcom,fcc-temp-lut", + batt_data->fcc_temp_lut); + if (rc) + return rc; + + rc = of_batterydata_read_pc_temp_ocv_lut(node, + "qcom,pc-temp-ocv-lut", + batt_data->pc_temp_ocv_lut); + if (rc) + return rc; + + rc = of_batterydata_read_sf_lut(node, "qcom,rbatt-sf-lut", + batt_data->rbatt_sf_lut); + if (rc) + return rc; + + rc = of_batterydata_read_ibat_temp_acc_lut(node, "qcom,ibat-acc-lut", + batt_data->ibat_acc_lut); + if (rc) + return rc; + + rc = of_property_read_string(node, "qcom,battery-type", + &batt_data->battery_type); + if (rc) { + pr_err("Error reading qcom,battery-type property rc=%d\n", rc); + batt_data->battery_type = NULL; + return rc; + } + + OF_PROP_READ(batt_data->fcc, "fcc-mah", node, rc, false); + OF_PROP_READ(batt_data->default_rbatt_mohm, + "default-rbatt-mohm", node, rc, false); + OF_PROP_READ(batt_data->rbatt_capacitive_mohm, + "rbatt-capacitive-mohm", node, rc, false); + OF_PROP_READ(batt_data->flat_ocv_threshold_uv, + "flat-ocv-threshold-uv", node, rc, true); + OF_PROP_READ(batt_data->max_voltage_uv, + "max-voltage-uv", node, rc, true); + OF_PROP_READ(batt_data->cutoff_uv, "v-cutoff-uv", node, rc, true); + OF_PROP_READ(batt_data->iterm_ua, "chg-term-ua", node, rc, true); + OF_PROP_READ(batt_data->fastchg_current_ma, + "fastchg-current-ma", node, rc, true); + OF_PROP_READ(batt_data->fg_cc_cv_threshold_mv, + "fg-cc-cv-threshold-mv", node, rc, true); + + batt_data->batt_id_kohm = best_id_kohm; + + return rc; +} + +static int64_t of_batterydata_convert_battery_id_kohm(int batt_id_uv, + int rpull_up, int vadc_vdd) +{ + int64_t resistor_value_kohm, denom; + + if (batt_id_uv == 0) { + /* vadc not correct or batt id line grounded, report 0 kohms */ + return 0; + } + /* calculate the battery id resistance reported via ADC */ + denom = div64_s64(vadc_vdd * 1000000LL, batt_id_uv) - 1000000LL; + + if (denom == 0) { + /* batt id connector might be open, return 0 kohms */ + return 0; + } + resistor_value_kohm = div64_s64(rpull_up * 1000000LL + denom/2, denom); + + pr_debug("batt id voltage = %d, resistor value = %lld\n", + batt_id_uv, resistor_value_kohm); + + return resistor_value_kohm; +} + +struct device_node *of_batterydata_get_best_profile( + const struct device_node *batterydata_container_node, + int batt_id_kohm, const char *batt_type) +{ + struct batt_ids batt_ids; + struct device_node *node, *best_node = NULL; + const char *battery_type = NULL; + int delta = 0, best_delta = 0, best_id_kohm = 0, id_range_pct, + i = 0, rc = 0, limit = 0; + bool in_range = false; + + /* read battery id range percentage for best profile */ + rc = of_property_read_u32(batterydata_container_node, + "qcom,batt-id-range-pct", &id_range_pct); + + if (rc) { + if (rc == -EINVAL) { + id_range_pct = 0; + } else { + pr_err("failed to read battery id range\n"); + return ERR_PTR(-ENXIO); + } + } + + /* + * Find the battery data with a battery id resistor closest to this one + */ + for_each_child_of_node(batterydata_container_node, node) { + if (batt_type != NULL) { + rc = of_property_read_string(node, "qcom,battery-type", + &battery_type); + if (!rc && strcmp(battery_type, batt_type) == 0) { + best_node = node; + best_id_kohm = batt_id_kohm; + break; + } + } else { + rc = of_batterydata_read_batt_id_kohm(node, + "qcom,batt-id-kohm", + &batt_ids); + if (rc) + continue; + for (i = 0; i < batt_ids.num; i++) { + delta = abs(batt_ids.kohm[i] - batt_id_kohm); + limit = (batt_ids.kohm[i] * id_range_pct) / 100; + in_range = (delta <= limit); + /* + * Check if the delta is the lowest one + * and also if the limits are in range + * before selecting the best node. + */ + if ((delta < best_delta || !best_node) + && in_range) { + best_node = node; + best_delta = delta; + best_id_kohm = batt_ids.kohm[i]; + } + } + } + } + + if (best_node == NULL) { + pr_err("No battery data found\n"); + return best_node; + } + + /* check that profile id is in range of the measured batt_id */ + if (abs(best_id_kohm - batt_id_kohm) > + ((best_id_kohm * id_range_pct) / 100)) { + pr_err("out of range: profile id %d batt id %d pct %d", + best_id_kohm, batt_id_kohm, id_range_pct); + return NULL; + } + + rc = of_property_read_string(best_node, "qcom,battery-type", + &battery_type); + if (!rc) + pr_info("%s found\n", battery_type); + else + pr_info("%s found\n", best_node->name); + + return best_node; +} + +int of_batterydata_read_data(struct device_node *batterydata_container_node, + struct bms_battery_data *batt_data, + int batt_id_uv) +{ + struct device_node *node, *best_node; + struct batt_ids batt_ids; + const char *battery_type = NULL; + int delta, best_delta, batt_id_kohm, rpull_up_kohm, + vadc_vdd_uv, best_id_kohm, i, rc = 0; + + node = batterydata_container_node; + OF_PROP_READ(rpull_up_kohm, "rpull-up-kohm", node, rc, false); + OF_PROP_READ(vadc_vdd_uv, "vref-batt-therm", node, rc, false); + if (rc) + return rc; + + batt_id_kohm = of_batterydata_convert_battery_id_kohm(batt_id_uv, + rpull_up_kohm, vadc_vdd_uv); + best_node = NULL; + best_delta = 0; + best_id_kohm = 0; + + /* + * Find the battery data with a battery id resistor closest to this one + */ + for_each_child_of_node(batterydata_container_node, node) { + rc = of_batterydata_read_batt_id_kohm(node, + "qcom,batt-id-kohm", + &batt_ids); + if (rc) + continue; + for (i = 0; i < batt_ids.num; i++) { + delta = abs(batt_ids.kohm[i] - batt_id_kohm); + if (delta < best_delta || !best_node) { + best_node = node; + best_delta = delta; + best_id_kohm = batt_ids.kohm[i]; + } + } + } + + if (best_node == NULL) { + pr_err("No battery data found\n"); + return -ENODATA; + } + rc = of_property_read_string(best_node, "qcom,battery-type", + &battery_type); + if (!rc) + pr_info("%s loaded\n", battery_type); + else + pr_info("%s loaded\n", best_node->name); + + return of_batterydata_load_battery_data(best_node, + best_id_kohm, batt_data); +} + +MODULE_LICENSE("GPL v2"); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index ed01c0172e4a..cffd4d31d3c1 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -149,7 +149,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ret = early_init_dt_alloc_reserved_memory_arch(size, align, start, end, nomap, &base); if (ret == 0) { - pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", + pr_info("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", uname, &base, (unsigned long)size / SZ_1M); break; @@ -161,7 +161,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ret = early_init_dt_alloc_reserved_memory_arch(size, align, 0, 0, nomap, &base); if (ret == 0) - pr_debug("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", + pr_info("Reserved memory: allocated memory for '%s' node: base %pa, size %ld MiB\n", uname, &base, (unsigned long)size / SZ_1M); } diff --git a/drivers/of/of_slimbus.c b/drivers/of/of_slimbus.c new file mode 100644 index 000000000000..234a5eb77db0 --- /dev/null +++ b/drivers/of/of_slimbus.c @@ -0,0 +1,90 @@ +/* Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/* OF helpers for SLIMbus */ +#include <linux/slimbus/slimbus.h> +#include <linux/irq.h> +#include <linux/slab.h> +#include <linux/of.h> +#include <linux/of_irq.h> +#include <linux/of_slimbus.h> + +int of_register_slim_devices(struct slim_controller *ctrl) +{ + struct device_node *node; + struct slim_boardinfo *binfo = NULL; + struct slim_boardinfo *temp; + int n = 0; + int ret = 0; + + if (!ctrl->dev.of_node) + return -EINVAL; + + for_each_child_of_node(ctrl->dev.of_node, node) { + struct property *prop; + struct slim_device *slim; + char *name; + prop = of_find_property(node, "elemental-addr", NULL); + if (!prop || prop->length != 6) { + dev_err(&ctrl->dev, "of_slim: invalid E-addr"); + continue; + } + name = kzalloc(SLIMBUS_NAME_SIZE, GFP_KERNEL); + if (!name) { + dev_err(&ctrl->dev, "of_slim: out of memory"); + ret = -ENOMEM; + goto of_slim_err; + } + if (of_modalias_node(node, name, SLIMBUS_NAME_SIZE) < 0) { + dev_err(&ctrl->dev, "of_slim: modalias failure on %s\n", + node->full_name); + kfree(name); + continue; + } + slim = kzalloc(sizeof(struct slim_device), GFP_KERNEL); + if (!slim) { + dev_err(&ctrl->dev, "of_slim: out of memory"); + ret = -ENOMEM; + kfree(name); + goto of_slim_err; + } + memcpy(slim->e_addr, prop->value, 6); + + temp = krealloc(binfo, (n + 1) * sizeof(struct slim_boardinfo), + GFP_KERNEL); + if (!temp) { + dev_err(&ctrl->dev, "out of memory"); + kfree(name); + kfree(slim); + ret = -ENOMEM; + goto of_slim_err; + } + binfo = temp; + + slim->dev.of_node = of_node_get(node); + slim->name = (const char *)name; + binfo[n].bus_num = ctrl->nr; + binfo[n].slim_slave = slim; + n++; + } + ret = slim_register_board_info(binfo, n); + if (!ret) + goto of_slim_ret; +of_slim_err: + while (n-- > 0) { + kfree(binfo[n].slim_slave->name); + kfree(binfo[n].slim_slave); + } +of_slim_ret: + kfree(binfo); + return ret; +} diff --git a/drivers/of/platform.c b/drivers/of/platform.c index af98343614d8..2924c8141f16 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -21,6 +21,7 @@ #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/of_platform.h> +#include <linux/of_reserved_mem.h> #include <linux/platform_device.h> const struct of_device_id of_default_bus_match_table[] = { @@ -139,7 +140,7 @@ struct platform_device *of_device_alloc(struct device_node *np, } dev->dev.of_node = of_node_get(np); - dev->dev.parent = parent ? : &platform_bus; + dev->dev.parent = parent; if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); @@ -185,6 +186,7 @@ static struct platform_device *of_platform_device_create_pdata( dev->dev.platform_data = platform_data; of_dma_configure(&dev->dev, dev->dev.of_node); of_msi_configure(&dev->dev, dev->dev.of_node); + of_reserved_mem_device_init(&dev->dev); if (of_device_add(dev) != 0) { of_dma_deconfigure(&dev->dev); @@ -241,7 +243,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node, /* setup generic device info */ dev->dev.of_node = of_node_get(node); - dev->dev.parent = parent ? : &platform_bus; + dev->dev.parent = parent; dev->dev.platform_data = platform_data; if (bus_id) dev_set_name(&dev->dev, "%s", bus_id); |