Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Windfarm PowerMac thermal control.  MAX6690 sensor.
0004  *
0005  * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
0006  */
0007 #include <linux/types.h>
0008 #include <linux/errno.h>
0009 #include <linux/kernel.h>
0010 #include <linux/init.h>
0011 #include <linux/slab.h>
0012 #include <linux/i2c.h>
0013 
0014 #include <asm/pmac_low_i2c.h>
0015 
0016 #include "windfarm.h"
0017 
0018 #define VERSION "1.0"
0019 
0020 /* This currently only exports the external temperature sensor,
0021    since that's all the control loops need. */
0022 
0023 /* Some MAX6690 register numbers */
0024 #define MAX6690_INTERNAL_TEMP   0
0025 #define MAX6690_EXTERNAL_TEMP   1
0026 
0027 struct wf_6690_sensor {
0028     struct i2c_client   *i2c;
0029     struct wf_sensor    sens;
0030 };
0031 
0032 #define wf_to_6690(x)   container_of((x), struct wf_6690_sensor, sens)
0033 
0034 static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
0035 {
0036     struct wf_6690_sensor *max = wf_to_6690(sr);
0037     s32 data;
0038 
0039     if (max->i2c == NULL)
0040         return -ENODEV;
0041 
0042     /* chip gets initialized by firmware */
0043     data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP);
0044     if (data < 0)
0045         return data;
0046     *value = data << 16;
0047     return 0;
0048 }
0049 
0050 static void wf_max6690_release(struct wf_sensor *sr)
0051 {
0052     struct wf_6690_sensor *max = wf_to_6690(sr);
0053 
0054     kfree(max);
0055 }
0056 
0057 static const struct wf_sensor_ops wf_max6690_ops = {
0058     .get_value  = wf_max6690_get,
0059     .release    = wf_max6690_release,
0060     .owner      = THIS_MODULE,
0061 };
0062 
0063 static int wf_max6690_probe(struct i2c_client *client,
0064                 const struct i2c_device_id *id)
0065 {
0066     const char *name, *loc;
0067     struct wf_6690_sensor *max;
0068     int rc;
0069 
0070     loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
0071     if (!loc) {
0072         dev_warn(&client->dev, "Missing hwsensor-location property!\n");
0073         return -ENXIO;
0074     }
0075 
0076     /*
0077      * We only expose the external temperature register for
0078      * now as this is all we need for our control loops
0079      */
0080     if (!strcmp(loc, "BACKSIDE") || !strcmp(loc, "SYS CTRLR AMBIENT"))
0081         name = "backside-temp";
0082     else if (!strcmp(loc, "NB Ambient"))
0083         name = "north-bridge-temp";
0084     else if (!strcmp(loc, "GPU Ambient"))
0085         name = "gpu-temp";
0086     else
0087         return -ENXIO;
0088 
0089     max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
0090     if (max == NULL) {
0091         printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
0092                "no memory\n");
0093         return -ENOMEM;
0094     }
0095 
0096     max->i2c = client;
0097     max->sens.name = name;
0098     max->sens.ops = &wf_max6690_ops;
0099     i2c_set_clientdata(client, max);
0100 
0101     rc = wf_register_sensor(&max->sens);
0102     if (rc)
0103         kfree(max);
0104     return rc;
0105 }
0106 
0107 static int wf_max6690_remove(struct i2c_client *client)
0108 {
0109     struct wf_6690_sensor *max = i2c_get_clientdata(client);
0110 
0111     max->i2c = NULL;
0112     wf_unregister_sensor(&max->sens);
0113 
0114     return 0;
0115 }
0116 
0117 static const struct i2c_device_id wf_max6690_id[] = {
0118     { "MAC,max6690", 0 },
0119     { }
0120 };
0121 MODULE_DEVICE_TABLE(i2c, wf_max6690_id);
0122 
0123 static const struct of_device_id wf_max6690_of_id[] = {
0124     { .compatible = "max6690", },
0125     { }
0126 };
0127 MODULE_DEVICE_TABLE(of, wf_max6690_of_id);
0128 
0129 static struct i2c_driver wf_max6690_driver = {
0130     .driver = {
0131         .name       = "wf_max6690",
0132         .of_match_table = wf_max6690_of_id,
0133     },
0134     .probe      = wf_max6690_probe,
0135     .remove     = wf_max6690_remove,
0136     .id_table   = wf_max6690_id,
0137 };
0138 
0139 module_i2c_driver(wf_max6690_driver);
0140 
0141 MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
0142 MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
0143 MODULE_LICENSE("GPL");