root/drivers/macintosh/windfarm_lm75_sensor.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wf_lm75_get
  2. wf_lm75_release
  3. wf_lm75_probe
  4. wf_lm75_remove

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Windfarm PowerMac thermal control. LM75 sensor
   4  *
   5  * (c) Copyright 2005 Benjamin Herrenschmidt, IBM Corp.
   6  *                    <benh@kernel.crashing.org>
   7  */
   8 
   9 #include <linux/types.h>
  10 #include <linux/errno.h>
  11 #include <linux/kernel.h>
  12 #include <linux/delay.h>
  13 #include <linux/slab.h>
  14 #include <linux/init.h>
  15 #include <linux/wait.h>
  16 #include <linux/i2c.h>
  17 #include <linux/of_device.h>
  18 #include <asm/prom.h>
  19 #include <asm/machdep.h>
  20 #include <asm/io.h>
  21 #include <asm/sections.h>
  22 #include <asm/pmac_low_i2c.h>
  23 
  24 #include "windfarm.h"
  25 
  26 #define VERSION "1.0"
  27 
  28 #undef DEBUG
  29 
  30 #ifdef DEBUG
  31 #define DBG(args...)    printk(args)
  32 #else
  33 #define DBG(args...)    do { } while(0)
  34 #endif
  35 
  36 struct wf_lm75_sensor {
  37         int                     ds1775 : 1;
  38         int                     inited : 1;
  39         struct i2c_client       *i2c;
  40         struct wf_sensor        sens;
  41 };
  42 #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
  43 
  44 static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
  45 {
  46         struct wf_lm75_sensor *lm = wf_to_lm75(sr);
  47         s32 data;
  48 
  49         if (lm->i2c == NULL)
  50                 return -ENODEV;
  51 
  52         /* Init chip if necessary */
  53         if (!lm->inited) {
  54                 u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1);
  55 
  56                 DBG("wf_lm75: Initializing %s, cfg was: %02x\n",
  57                     sr->name, cfg);
  58 
  59                 /* clear shutdown bit, keep other settings as left by
  60                  * the firmware for now
  61                  */
  62                 cfg_new = cfg & ~0x01;
  63                 i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new);
  64                 lm->inited = 1;
  65 
  66                 /* If we just powered it up, let's wait 200 ms */
  67                 msleep(200);
  68         }
  69 
  70         /* Read temperature register */
  71         data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0));
  72         data <<= 8;
  73         *value = data;
  74 
  75         return 0;
  76 }
  77 
  78 static void wf_lm75_release(struct wf_sensor *sr)
  79 {
  80         struct wf_lm75_sensor *lm = wf_to_lm75(sr);
  81 
  82         kfree(lm);
  83 }
  84 
  85 static const struct wf_sensor_ops wf_lm75_ops = {
  86         .get_value      = wf_lm75_get,
  87         .release        = wf_lm75_release,
  88         .owner          = THIS_MODULE,
  89 };
  90 
  91 static int wf_lm75_probe(struct i2c_client *client,
  92                          const struct i2c_device_id *id)
  93 {       
  94         struct wf_lm75_sensor *lm;
  95         int rc, ds1775;
  96         const char *name, *loc;
  97 
  98         if (id)
  99                 ds1775 = id->driver_data;
 100         else
 101                 ds1775 = !!of_device_get_match_data(&client->dev);
 102 
 103         DBG("wf_lm75: creating  %s device at address 0x%02x\n",
 104             ds1775 ? "ds1775" : "lm75", client->addr);
 105 
 106         loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
 107         if (!loc) {
 108                 dev_warn(&client->dev, "Missing hwsensor-location property!\n");
 109                 return -ENXIO;
 110         }
 111 
 112         /* Usual rant about sensor names not beeing very consistent in
 113          * the device-tree, oh well ...
 114          * Add more entries below as you deal with more setups
 115          */
 116         if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
 117                 name = "hd-temp";
 118         else if (!strcmp(loc, "Incoming Air Temp"))
 119                 name = "incoming-air-temp";
 120         else if (!strcmp(loc, "ODD Temp"))
 121                 name = "optical-drive-temp";
 122         else if (!strcmp(loc, "HD Temp"))
 123                 name = "hard-drive-temp";
 124         else if (!strcmp(loc, "PCI SLOTS"))
 125                 name = "slots-temp";
 126         else if (!strcmp(loc, "CPU A INLET"))
 127                 name = "cpu-inlet-temp-0";
 128         else if (!strcmp(loc, "CPU B INLET"))
 129                 name = "cpu-inlet-temp-1";
 130         else
 131                 return -ENXIO;
 132         
 133 
 134         lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
 135         if (lm == NULL)
 136                 return -ENODEV;
 137 
 138         lm->inited = 0;
 139         lm->ds1775 = ds1775;
 140         lm->i2c = client;
 141         lm->sens.name = name;
 142         lm->sens.ops = &wf_lm75_ops;
 143         i2c_set_clientdata(client, lm);
 144 
 145         rc = wf_register_sensor(&lm->sens);
 146         if (rc)
 147                 kfree(lm);
 148         return rc;
 149 }
 150 
 151 static int wf_lm75_remove(struct i2c_client *client)
 152 {
 153         struct wf_lm75_sensor *lm = i2c_get_clientdata(client);
 154 
 155         DBG("wf_lm75: i2c detatch called for %s\n", lm->sens.name);
 156 
 157         /* Mark client detached */
 158         lm->i2c = NULL;
 159 
 160         /* release sensor */
 161         wf_unregister_sensor(&lm->sens);
 162 
 163         return 0;
 164 }
 165 
 166 static const struct i2c_device_id wf_lm75_id[] = {
 167         { "MAC,lm75", 0 },
 168         { "MAC,ds1775", 1 },
 169         { }
 170 };
 171 MODULE_DEVICE_TABLE(i2c, wf_lm75_id);
 172 
 173 static const struct of_device_id wf_lm75_of_id[] = {
 174         { .compatible = "lm75", .data = (void *)0},
 175         { .compatible = "ds1775", .data = (void *)1 },
 176         { }
 177 };
 178 MODULE_DEVICE_TABLE(of, wf_lm75_of_id);
 179 
 180 static struct i2c_driver wf_lm75_driver = {
 181         .driver = {
 182                 .name   = "wf_lm75",
 183                 .of_match_table = wf_lm75_of_id,
 184         },
 185         .probe          = wf_lm75_probe,
 186         .remove         = wf_lm75_remove,
 187         .id_table       = wf_lm75_id,
 188 };
 189 
 190 module_i2c_driver(wf_lm75_driver);
 191 
 192 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
 193 MODULE_DESCRIPTION("LM75 sensor objects for PowerMacs thermal control");
 194 MODULE_LICENSE("GPL");
 195 

/* [<][>][^][v][top][bottom][index][help] */