Merge branches 'pm-cpuidle', 'pm-sleep' and 'pm-domains'
[linux-2.6-microblaze.git] / drivers / i2c / i2c-core-base.c
index f213623..5a97e4a 100644 (file)
@@ -76,6 +76,27 @@ void i2c_transfer_trace_unreg(void)
        static_branch_dec(&i2c_trace_msg_key);
 }
 
+const char *i2c_freq_mode_string(u32 bus_freq_hz)
+{
+       switch (bus_freq_hz) {
+       case I2C_MAX_STANDARD_MODE_FREQ:
+               return "Standard Mode (100 kHz)";
+       case I2C_MAX_FAST_MODE_FREQ:
+               return "Fast Mode (400 kHz)";
+       case I2C_MAX_FAST_MODE_PLUS_FREQ:
+               return "Fast Mode Plus (1.0 MHz)";
+       case I2C_MAX_TURBO_MODE_FREQ:
+               return "Turbo Mode (1.4 MHz)";
+       case I2C_MAX_HIGH_SPEED_MODE_FREQ:
+               return "High Speed Mode (3.4 MHz)";
+       case I2C_MAX_ULTRA_FAST_MODE_FREQ:
+               return "Ultra Fast Mode (5.0 MHz)";
+       default:
+               return "Unknown Mode";
+       }
+}
+EXPORT_SYMBOL_GPL(i2c_freq_mode_string);
+
 const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id,
                                                const struct i2c_client *client)
 {
@@ -249,7 +270,7 @@ EXPORT_SYMBOL_GPL(i2c_generic_scl_recovery);
 int i2c_recover_bus(struct i2c_adapter *adap)
 {
        if (!adap->bus_recovery_info)
-               return -EOPNOTSUPP;
+               return -EBUSY;
 
        dev_dbg(&adap->dev, "Trying i2c bus recovery\n");
        return adap->bus_recovery_info->recover_bus(adap);
@@ -519,6 +540,13 @@ static int i2c_device_probe(struct device *dev)
        if (status)
                goto err_clear_wakeup_irq;
 
+       client->devres_group_id = devres_open_group(&client->dev, NULL,
+                                                   GFP_KERNEL);
+       if (!client->devres_group_id) {
+               status = -ENOMEM;
+               goto err_detach_pm_domain;
+       }
+
        /*
         * When there are no more users of probe(),
         * rename probe_new to probe.
@@ -531,11 +559,21 @@ static int i2c_device_probe(struct device *dev)
        else
                status = -EINVAL;
 
+       /*
+        * Note that we are not closing the devres group opened above so
+        * even resources that were attached to the device after probe is
+        * run are released when i2c_device_remove() is executed. This is
+        * needed as some drivers would allocate additional resources,
+        * for example when updating firmware.
+        */
+
        if (status)
-               goto err_detach_pm_domain;
+               goto err_release_driver_resources;
 
        return 0;
 
+err_release_driver_resources:
+       devres_release_group(&client->dev, client->devres_group_id);
 err_detach_pm_domain:
        dev_pm_domain_detach(&client->dev, true);
 err_clear_wakeup_irq:
@@ -564,6 +602,8 @@ static int i2c_device_remove(struct device *dev)
                        dev_warn(dev, "remove failed (%pe), will be ignored\n", ERR_PTR(status));
        }
 
+       devres_release_group(&client->dev, client->devres_group_id);
+
        dev_pm_domain_detach(&client->dev, true);
 
        dev_pm_clear_wake_irq(&client->dev);
@@ -612,7 +652,7 @@ modalias_show(struct device *dev, struct device_attribute *attr, char *buf)
        if (len != -ENODEV)
                return len;
 
-       len = acpi_device_modalias(dev, buf, PAGE_SIZE -1);
+       len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
        if (len != -ENODEV)
                return len;
 
@@ -910,11 +950,11 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
 
        i2c_dev_set_name(adap, client, info);
 
-       if (info->properties) {
-               status = device_add_properties(&client->dev, info->properties);
+       if (info->swnode) {
+               status = device_add_software_node(&client->dev, info->swnode);
                if (status) {
                        dev_err(&adap->dev,
-                               "Failed to add properties to client %s: %d\n",
+                               "Failed to add software node to client %s: %d\n",
                                client->name, status);
                        goto out_err_put_of_node;
                }
@@ -922,16 +962,15 @@ i2c_new_client_device(struct i2c_adapter *adap, struct i2c_board_info const *inf
 
        status = device_register(&client->dev);
        if (status)
-               goto out_free_props;
+               goto out_remove_swnode;
 
        dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n",
                client->name, dev_name(&client->dev));
 
        return client;
 
-out_free_props:
-       if (info->properties)
-               device_remove_properties(&client->dev);
+out_remove_swnode:
+       device_remove_software_node(&client->dev);
 out_err_put_of_node:
        of_node_put(info->of_node);
 out_err:
@@ -961,6 +1000,7 @@ void i2c_unregister_device(struct i2c_client *client)
 
        if (ACPI_COMPANION(&client->dev))
                acpi_device_clear_enumerated(ACPI_COMPANION(&client->dev));
+       device_remove_software_node(&client->dev);
        device_unregister(&client->dev);
 }
 EXPORT_SYMBOL_GPL(i2c_unregister_device);
@@ -1017,15 +1057,9 @@ struct i2c_client *i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address
 }
 EXPORT_SYMBOL_GPL(i2c_new_dummy_device);
 
-struct i2c_dummy_devres {
-       struct i2c_client *client;
-};
-
-static void devm_i2c_release_dummy(struct device *dev, void *res)
+static void devm_i2c_release_dummy(void *client)
 {
-       struct i2c_dummy_devres *this = res;
-
-       i2c_unregister_device(this->client);
+       i2c_unregister_device(client);
 }
 
 /**
@@ -1042,20 +1076,16 @@ struct i2c_client *devm_i2c_new_dummy_device(struct device *dev,
                                             struct i2c_adapter *adapter,
                                             u16 address)
 {
-       struct i2c_dummy_devres *dr;
        struct i2c_client *client;
-
-       dr = devres_alloc(devm_i2c_release_dummy, sizeof(*dr), GFP_KERNEL);
-       if (!dr)
-               return ERR_PTR(-ENOMEM);
+       int ret;
 
        client = i2c_new_dummy_device(adapter, address);
-       if (IS_ERR(client)) {
-               devres_free(dr);
-       } else {
-               dr->client = client;
-               devres_add(dev, dr);
-       }
+       if (IS_ERR(client))
+               return client;
+
+       ret = devm_add_action_or_reset(dev, devm_i2c_release_dummy, client);
+       if (ret)
+               return ERR_PTR(ret);
 
        return client;
 }
@@ -1704,6 +1734,32 @@ void i2c_del_adapter(struct i2c_adapter *adap)
 }
 EXPORT_SYMBOL(i2c_del_adapter);
 
+static void devm_i2c_del_adapter(void *adapter)
+{
+       i2c_del_adapter(adapter);
+}
+
+/**
+ * devm_i2c_add_adapter - device-managed variant of i2c_add_adapter()
+ * @dev: managing device for adding this I2C adapter
+ * @adapter: the adapter to add
+ * Context: can sleep
+ *
+ * Add adapter with dynamic bus number, same with i2c_add_adapter()
+ * but the adapter will be auto deleted on driver detach.
+ */
+int devm_i2c_add_adapter(struct device *dev, struct i2c_adapter *adapter)
+{
+       int ret;
+
+       ret = i2c_add_adapter(adapter);
+       if (ret)
+               return ret;
+
+       return devm_add_action_or_reset(dev, devm_i2c_del_adapter, adapter);
+}
+EXPORT_SYMBOL_GPL(devm_i2c_add_adapter);
+
 static void i2c_parse_timing(struct device *dev, char *prop_name, u32 *cur_val_p,
                            u32 def_val, bool use_def)
 {