linux/drivers/hwmon/atxp1.c
<<
>>
Prefs
   1/*
   2 * atxp1.c - kernel module for setting CPU VID and general purpose
   3 *           I/Os using the Attansic ATXP1 chip.
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * The ATXP1 can reside on I2C addresses 0x37 or 0x4e. The chip is
  16 * not auto-detected by the driver and must be instantiated explicitly.
  17 * See Documentation/i2c/instantiating-devices for more information.
  18 */
  19
  20#include <linux/kernel.h>
  21#include <linux/init.h>
  22#include <linux/module.h>
  23#include <linux/jiffies.h>
  24#include <linux/i2c.h>
  25#include <linux/hwmon.h>
  26#include <linux/hwmon-vid.h>
  27#include <linux/err.h>
  28#include <linux/mutex.h>
  29#include <linux/sysfs.h>
  30#include <linux/slab.h>
  31
  32MODULE_LICENSE("GPL");
  33MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
  34MODULE_VERSION("0.6.3");
  35MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
  36
  37#define ATXP1_VID       0x00
  38#define ATXP1_CVID      0x01
  39#define ATXP1_GPIO1     0x06
  40#define ATXP1_GPIO2     0x0a
  41#define ATXP1_VIDENA    0x20
  42#define ATXP1_VIDMASK   0x1f
  43#define ATXP1_GPIO1MASK 0x0f
  44
  45struct atxp1_data {
  46        struct i2c_client *client;
  47        struct mutex update_lock;
  48        unsigned long last_updated;
  49        u8 valid;
  50        struct {
  51                u8 vid;         /* VID output register */
  52                u8 cpu_vid; /* VID input from CPU */
  53                u8 gpio1;   /* General purpose I/O register 1 */
  54                u8 gpio2;   /* General purpose I/O register 2 */
  55        } reg;
  56        u8 vrm;                 /* Detected CPU VRM */
  57};
  58
  59static struct atxp1_data *atxp1_update_device(struct device *dev)
  60{
  61        struct atxp1_data *data = dev_get_drvdata(dev);
  62        struct i2c_client *client = data->client;
  63
  64        mutex_lock(&data->update_lock);
  65
  66        if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
  67
  68                /* Update local register data */
  69                data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID);
  70                data->reg.cpu_vid = i2c_smbus_read_byte_data(client,
  71                                                             ATXP1_CVID);
  72                data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1);
  73                data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2);
  74
  75                data->valid = 1;
  76        }
  77
  78        mutex_unlock(&data->update_lock);
  79
  80        return data;
  81}
  82
  83/* sys file functions for cpu0_vid */
  84static ssize_t atxp1_showvcore(struct device *dev,
  85                               struct device_attribute *attr, char *buf)
  86{
  87        int size;
  88        struct atxp1_data *data;
  89
  90        data = atxp1_update_device(dev);
  91
  92        size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK,
  93                                                 data->vrm));
  94
  95        return size;
  96}
  97
  98static ssize_t atxp1_storevcore(struct device *dev,
  99                                struct device_attribute *attr,
 100                                const char *buf, size_t count)
 101{
 102        struct atxp1_data *data = atxp1_update_device(dev);
 103        struct i2c_client *client = data->client;
 104        int vid, cvid;
 105        unsigned long vcore;
 106        int err;
 107
 108        err = kstrtoul(buf, 10, &vcore);
 109        if (err)
 110                return err;
 111
 112        vcore /= 25;
 113        vcore *= 25;
 114
 115        /* Calculate VID */
 116        vid = vid_to_reg(vcore, data->vrm);
 117        if (vid < 0) {
 118                dev_err(dev, "VID calculation failed.\n");
 119                return vid;
 120        }
 121
 122        /*
 123         * If output enabled, use control register value.
 124         * Otherwise original CPU VID
 125         */
 126        if (data->reg.vid & ATXP1_VIDENA)
 127                cvid = data->reg.vid & ATXP1_VIDMASK;
 128        else
 129                cvid = data->reg.cpu_vid;
 130
 131        /* Nothing changed, aborting */
 132        if (vid == cvid)
 133                return count;
 134
 135        dev_dbg(dev, "Setting VCore to %d mV (0x%02x)\n", (int)vcore, vid);
 136
 137        /* Write every 25 mV step to increase stability */
 138        if (cvid > vid) {
 139                for (; cvid >= vid; cvid--)
 140                        i2c_smbus_write_byte_data(client,
 141                                                ATXP1_VID, cvid | ATXP1_VIDENA);
 142        } else {
 143                for (; cvid <= vid; cvid++)
 144                        i2c_smbus_write_byte_data(client,
 145                                                ATXP1_VID, cvid | ATXP1_VIDENA);
 146        }
 147
 148        data->valid = 0;
 149
 150        return count;
 151}
 152
 153/*
 154 * CPU core reference voltage
 155 * unit: millivolt
 156 */
 157static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore,
 158                   atxp1_storevcore);
 159
 160/* sys file functions for GPIO1 */
 161static ssize_t atxp1_showgpio1(struct device *dev,
 162                               struct device_attribute *attr, char *buf)
 163{
 164        int size;
 165        struct atxp1_data *data;
 166
 167        data = atxp1_update_device(dev);
 168
 169        size = sprintf(buf, "0x%02x\n", data->reg.gpio1 & ATXP1_GPIO1MASK);
 170
 171        return size;
 172}
 173
 174static ssize_t atxp1_storegpio1(struct device *dev,
 175                                struct device_attribute *attr, const char *buf,
 176                                size_t count)
 177{
 178        struct atxp1_data *data = atxp1_update_device(dev);
 179        struct i2c_client *client = data->client;
 180        unsigned long value;
 181        int err;
 182
 183        err = kstrtoul(buf, 16, &value);
 184        if (err)
 185                return err;
 186
 187        value &= ATXP1_GPIO1MASK;
 188
 189        if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) {
 190                dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value);
 191
 192                i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
 193
 194                data->valid = 0;
 195        }
 196
 197        return count;
 198}
 199
 200/*
 201 * GPIO1 data register
 202 * unit: Four bit as hex (e.g. 0x0f)
 203 */
 204static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1);
 205
 206/* sys file functions for GPIO2 */
 207static ssize_t atxp1_showgpio2(struct device *dev,
 208                               struct device_attribute *attr, char *buf)
 209{
 210        int size;
 211        struct atxp1_data *data;
 212
 213        data = atxp1_update_device(dev);
 214
 215        size = sprintf(buf, "0x%02x\n", data->reg.gpio2);
 216
 217        return size;
 218}
 219
 220static ssize_t atxp1_storegpio2(struct device *dev,
 221                                struct device_attribute *attr,
 222                                const char *buf, size_t count)
 223{
 224        struct atxp1_data *data = atxp1_update_device(dev);
 225        struct i2c_client *client = data->client;
 226        unsigned long value;
 227        int err;
 228
 229        err = kstrtoul(buf, 16, &value);
 230        if (err)
 231                return err;
 232        value &= 0xff;
 233
 234        if (value != data->reg.gpio2) {
 235                dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value);
 236
 237                i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
 238
 239                data->valid = 0;
 240        }
 241
 242        return count;
 243}
 244
 245/*
 246 * GPIO2 data register
 247 * unit: Eight bit as hex (e.g. 0xff)
 248 */
 249static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
 250
 251static struct attribute *atxp1_attrs[] = {
 252        &dev_attr_gpio1.attr,
 253        &dev_attr_gpio2.attr,
 254        &dev_attr_cpu0_vid.attr,
 255        NULL
 256};
 257ATTRIBUTE_GROUPS(atxp1);
 258
 259static int atxp1_probe(struct i2c_client *client,
 260                       const struct i2c_device_id *id)
 261{
 262        struct device *dev = &client->dev;
 263        struct atxp1_data *data;
 264        struct device *hwmon_dev;
 265
 266        data = devm_kzalloc(dev, sizeof(struct atxp1_data), GFP_KERNEL);
 267        if (!data)
 268                return -ENOMEM;
 269
 270        /* Get VRM */
 271        data->vrm = vid_which_vrm();
 272        if (data->vrm != 90 && data->vrm != 91) {
 273                dev_err(dev, "atxp1: Not supporting VRM %d.%d\n",
 274                        data->vrm / 10, data->vrm % 10);
 275                return -ENODEV;
 276        }
 277
 278        data->client = client;
 279        mutex_init(&data->update_lock);
 280
 281        hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
 282                                                           data,
 283                                                           atxp1_groups);
 284        if (IS_ERR(hwmon_dev))
 285                return PTR_ERR(hwmon_dev);
 286
 287        dev_info(dev, "Using VRM: %d.%d\n", data->vrm / 10, data->vrm % 10);
 288
 289        return 0;
 290};
 291
 292static const struct i2c_device_id atxp1_id[] = {
 293        { "atxp1", 0 },
 294        { }
 295};
 296MODULE_DEVICE_TABLE(i2c, atxp1_id);
 297
 298static struct i2c_driver atxp1_driver = {
 299        .class          = I2C_CLASS_HWMON,
 300        .driver = {
 301                .name   = "atxp1",
 302        },
 303        .probe          = atxp1_probe,
 304        .id_table       = atxp1_id,
 305};
 306
 307module_i2c_driver(atxp1_driver);
 308