linux/drivers/macintosh/windfarm_max6690_sensor.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Windfarm PowerMac thermal control.  MAX6690 sensor.
   4 *
   5 * Copyright (C) 2005 Paul Mackerras, IBM Corp. <paulus@samba.org>
   6 */
   7#include <linux/types.h>
   8#include <linux/errno.h>
   9#include <linux/kernel.h>
  10#include <linux/init.h>
  11#include <linux/slab.h>
  12#include <linux/i2c.h>
  13#include <asm/prom.h>
  14#include <asm/pmac_low_i2c.h>
  15
  16#include "windfarm.h"
  17
  18#define VERSION "1.0"
  19
  20/* This currently only exports the external temperature sensor,
  21   since that's all the control loops need. */
  22
  23/* Some MAX6690 register numbers */
  24#define MAX6690_INTERNAL_TEMP   0
  25#define MAX6690_EXTERNAL_TEMP   1
  26
  27struct wf_6690_sensor {
  28        struct i2c_client       *i2c;
  29        struct wf_sensor        sens;
  30};
  31
  32#define wf_to_6690(x)   container_of((x), struct wf_6690_sensor, sens)
  33
  34static int wf_max6690_get(struct wf_sensor *sr, s32 *value)
  35{
  36        struct wf_6690_sensor *max = wf_to_6690(sr);
  37        s32 data;
  38
  39        if (max->i2c == NULL)
  40                return -ENODEV;
  41
  42        /* chip gets initialized by firmware */
  43        data = i2c_smbus_read_byte_data(max->i2c, MAX6690_EXTERNAL_TEMP);
  44        if (data < 0)
  45                return data;
  46        *value = data << 16;
  47        return 0;
  48}
  49
  50static void wf_max6690_release(struct wf_sensor *sr)
  51{
  52        struct wf_6690_sensor *max = wf_to_6690(sr);
  53
  54        kfree(max);
  55}
  56
  57static const struct wf_sensor_ops wf_max6690_ops = {
  58        .get_value      = wf_max6690_get,
  59        .release        = wf_max6690_release,
  60        .owner          = THIS_MODULE,
  61};
  62
  63static int wf_max6690_probe(struct i2c_client *client,
  64                            const struct i2c_device_id *id)
  65{
  66        const char *name, *loc;
  67        struct wf_6690_sensor *max;
  68        int rc;
  69
  70        loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
  71        if (!loc) {
  72                dev_warn(&client->dev, "Missing hwsensor-location property!\n");
  73                return -ENXIO;
  74        }
  75
  76        /*
  77         * We only expose the external temperature register for
  78         * now as this is all we need for our control loops
  79         */
  80        if (!strcmp(loc, "BACKSIDE") || !strcmp(loc, "SYS CTRLR AMBIENT"))
  81                name = "backside-temp";
  82        else if (!strcmp(loc, "NB Ambient"))
  83                name = "north-bridge-temp";
  84        else if (!strcmp(loc, "GPU Ambient"))
  85                name = "gpu-temp";
  86        else
  87                return -ENXIO;
  88
  89        max = kzalloc(sizeof(struct wf_6690_sensor), GFP_KERNEL);
  90        if (max == NULL) {
  91                printk(KERN_ERR "windfarm: Couldn't create MAX6690 sensor: "
  92                       "no memory\n");
  93                return -ENOMEM;
  94        }
  95
  96        max->i2c = client;
  97        max->sens.name = name;
  98        max->sens.ops = &wf_max6690_ops;
  99        i2c_set_clientdata(client, max);
 100
 101        rc = wf_register_sensor(&max->sens);
 102        if (rc)
 103                kfree(max);
 104        return rc;
 105}
 106
 107static int wf_max6690_remove(struct i2c_client *client)
 108{
 109        struct wf_6690_sensor *max = i2c_get_clientdata(client);
 110
 111        max->i2c = NULL;
 112        wf_unregister_sensor(&max->sens);
 113
 114        return 0;
 115}
 116
 117static const struct i2c_device_id wf_max6690_id[] = {
 118        { "MAC,max6690", 0 },
 119        { }
 120};
 121MODULE_DEVICE_TABLE(i2c, wf_max6690_id);
 122
 123static const struct of_device_id wf_max6690_of_id[] = {
 124        { .compatible = "max6690", },
 125        { }
 126};
 127MODULE_DEVICE_TABLE(of, wf_max6690_of_id);
 128
 129static struct i2c_driver wf_max6690_driver = {
 130        .driver = {
 131                .name           = "wf_max6690",
 132                .of_match_table = wf_max6690_of_id,
 133        },
 134        .probe          = wf_max6690_probe,
 135        .remove         = wf_max6690_remove,
 136        .id_table       = wf_max6690_id,
 137};
 138
 139module_i2c_driver(wf_max6690_driver);
 140
 141MODULE_AUTHOR("Paul Mackerras <paulus@samba.org>");
 142MODULE_DESCRIPTION("MAX6690 sensor objects for PowerMac thermal control");
 143MODULE_LICENSE("GPL");
 144