183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck/* 283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller 383f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * and Digital Power Monitor 483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * 583f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * Copyright (c) 2011 Ericsson AB. 683f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * 783f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * This program is free software; you can redistribute it and/or modify 883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * it under the terms of the GNU General Public License as published by 983f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * the Free Software Foundation; either version 2 of the License, or 1083f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * (at your option) any later version. 1183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * 1283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * This program is distributed in the hope that it will be useful, 1383f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of 1483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1583f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck * GNU General Public License for more details. 1683f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck */ 1783f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 1883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include <linux/kernel.h> 1983f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include <linux/module.h> 2083f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include <linux/init.h> 2183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include <linux/err.h> 2283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include <linux/slab.h> 2383f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include <linux/i2c.h> 2483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#include "pmbus.h" 2583f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 26927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeckenum chips { adm1075, adm1275, adm1276 }; 275cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck 28c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck#define ADM1275_PEAK_IOUT 0xd0 29c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck#define ADM1275_PEAK_VIN 0xd1 30c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck#define ADM1275_PEAK_VOUT 0xd2 3183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#define ADM1275_PMON_CONFIG 0xd4 3283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 3383f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#define ADM1275_VIN_VOUT_SELECT (1 << 6) 3483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck#define ADM1275_VRANGE (1 << 5) 35927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_IRANGE_50 (1 << 4) 36927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_IRANGE_25 (1 << 3) 37927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4)) 3883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 39c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck#define ADM1275_IOUT_WARN2_LIMIT 0xd7 40c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck#define ADM1275_DEVICE_CONFIG 0xd8 41c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 42c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck#define ADM1275_IOUT_WARN2_SELECT (1 << 4) 43c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 445cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck#define ADM1276_PEAK_PIN 0xda 455cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck 46c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0) 47c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 48927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_READ_VAUX 0xdd 49927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_VAUX_OV_WARN_LIMIT 0xde 50927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf 51927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_VAUX_STATUS 0xf6 52927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck 53927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_VAUX_OV_WARN (1<<7) 54927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck#define ADM1075_VAUX_UV_WARN (1<<6) 55927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck 56c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeckstruct adm1275_data { 575cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck int id; 58c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck bool have_oc_fault; 59c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck struct pmbus_driver_info info; 60c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck}; 61c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 62c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck#define to_adm1275_data(x) container_of(x, struct adm1275_data, info) 63c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 64c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeckstatic int adm1275_read_word_data(struct i2c_client *client, int page, int reg) 65c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck{ 66c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 67c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 685cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck int ret = 0; 69c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 70c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck if (page) 71c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck return -ENXIO; 72c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 73c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck switch (reg) { 74c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck case PMBUS_IOUT_UC_FAULT_LIMIT: 75c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck if (data->have_oc_fault) { 76c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = -ENXIO; 77c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 78c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck } 79c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 80c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 81c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck case PMBUS_IOUT_OC_FAULT_LIMIT: 82c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck if (!data->have_oc_fault) { 83c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = -ENXIO; 84c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 85c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck } 86c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 87c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 88927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case PMBUS_VOUT_OV_WARN_LIMIT: 89927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id != adm1075) { 90927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = -ENODATA; 91927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 92927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck } 93927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = pmbus_read_word_data(client, 0, 94927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ADM1075_VAUX_OV_WARN_LIMIT); 95927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 96927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case PMBUS_VOUT_UV_WARN_LIMIT: 97927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id != adm1075) { 98927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = -ENODATA; 99927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 100927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck } 101927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = pmbus_read_word_data(client, 0, 102927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ADM1075_VAUX_UV_WARN_LIMIT); 103927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 104927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case PMBUS_READ_VOUT: 105927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id != adm1075) { 106927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = -ENODATA; 107927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 108927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck } 109927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); 110927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 111c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_READ_IOUT_MAX: 112c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); 113c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 114c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_READ_VOUT_MAX: 115c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT); 116c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 117c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_READ_VIN_MAX: 118c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); 119c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 1205cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck case PMBUS_VIRT_READ_PIN_MAX: 121927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id == adm1275) { 1225cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck ret = -ENXIO; 1235cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck break; 1245cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck } 1255cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); 1265cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck break; 127c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 128c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 129c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 1305cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck break; 1315cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck case PMBUS_VIRT_RESET_PIN_HISTORY: 132927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id == adm1275) 1335cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck ret = -ENXIO; 134c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 135c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck default: 136c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = -ENODATA; 137c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 138c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck } 139c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck return ret; 140c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck} 141c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 142c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeckstatic int adm1275_write_word_data(struct i2c_client *client, int page, int reg, 143c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck u16 word) 144c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck{ 145c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck int ret; 146c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 147c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck if (page) 148c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck return -ENXIO; 149c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 150c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck switch (reg) { 151c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck case PMBUS_IOUT_UC_FAULT_LIMIT: 152c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck case PMBUS_IOUT_OC_FAULT_LIMIT: 153c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT, 154c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck word); 155c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 156c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_RESET_IOUT_HISTORY: 157c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); 158c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 159c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_RESET_VOUT_HISTORY: 160c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); 161c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 162c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck case PMBUS_VIRT_RESET_VIN_HISTORY: 163c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); 164c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 1655cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck case PMBUS_VIRT_RESET_PIN_HISTORY: 1665cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); 1675cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck break; 168c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck default: 169c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck ret = -ENODATA; 170c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck break; 171c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck } 172c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck return ret; 173c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck} 174c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 175c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeckstatic int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) 176c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck{ 177c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 178c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck const struct adm1275_data *data = to_adm1275_data(info); 179c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck int mfr_status, ret; 180c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 181da8e48ab483e1f54c1099bed91bfd2c302bc7ddfGuenter Roeck if (page > 0) 182c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck return -ENXIO; 183c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 184c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck switch (reg) { 185c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck case PMBUS_STATUS_IOUT: 186c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); 187c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck if (ret < 0) 188c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 189c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck mfr_status = pmbus_read_byte_data(client, page, 190c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck PMBUS_STATUS_MFR_SPECIFIC); 191c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck if (mfr_status < 0) { 192c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = mfr_status; 193c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 194c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck } 195c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { 196c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret |= data->have_oc_fault ? 197c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; 198c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck } 199c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 200927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case PMBUS_STATUS_VOUT: 201927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id != adm1075) { 202927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = -ENODATA; 203927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 204927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck } 205927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret = 0; 206927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck mfr_status = pmbus_read_byte_data(client, 0, 207927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ADM1075_VAUX_STATUS); 208927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (mfr_status & ADM1075_VAUX_OV_WARN) 209927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret |= PB_VOLTAGE_OV_WARNING; 210927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (mfr_status & ADM1075_VAUX_UV_WARN) 211927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck ret |= PB_VOLTAGE_UV_WARNING; 212927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 213c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck default: 214c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck ret = -ENODATA; 215c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck break; 216c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck } 217c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck return ret; 218c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck} 219c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 22087102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeckstatic const struct i2c_device_id adm1275_id[] = { 221927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck { "adm1075", adm1075 }, 22287102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck { "adm1275", adm1275 }, 22387102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck { "adm1276", adm1276 }, 22487102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck { } 22587102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck}; 22687102808d03948c825c3bdc48316e48f6422fd7eGuenter RoeckMODULE_DEVICE_TABLE(i2c, adm1275_id); 22787102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck 22883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeckstatic int adm1275_probe(struct i2c_client *client, 22983f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck const struct i2c_device_id *id) 23083f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck{ 23187102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; 232c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck int config, device_config; 2333b33ca41227a54a78446fb0d7a6fdb9862f563dbGuenter Roeck int ret; 23483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck struct pmbus_driver_info *info; 235c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck struct adm1275_data *data; 23687102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck const struct i2c_device_id *mid; 23783f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 23883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck if (!i2c_check_functionality(client->adapter, 23987102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck I2C_FUNC_SMBUS_READ_BYTE_DATA 24087102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck | I2C_FUNC_SMBUS_BLOCK_DATA)) 24183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck return -ENODEV; 24283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 24387102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer); 24487102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (ret < 0) { 24587102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck dev_err(&client->dev, "Failed to read Manufacturer ID\n"); 24687102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return ret; 24787102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck } 24887102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (ret != 3 || strncmp(block_buffer, "ADI", 3)) { 24987102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck dev_err(&client->dev, "Unsupported Manufacturer ID\n"); 25087102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return -ENODEV; 25187102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck } 25283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 25387102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer); 25487102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (ret < 0) { 25587102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck dev_err(&client->dev, "Failed to read Manufacturer Model\n"); 25687102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return ret; 25787102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck } 25887102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck for (mid = adm1275_id; mid->name[0]; mid++) { 25987102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) 26087102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck break; 26187102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck } 26287102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (!mid->name[0]) { 26387102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck dev_err(&client->dev, "Unsupported device\n"); 26487102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return -ENODEV; 2653b33ca41227a54a78446fb0d7a6fdb9862f563dbGuenter Roeck } 26683f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 26787102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (id->driver_data != mid->driver_data) 26887102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck dev_notice(&client->dev, 26987102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck "Device mismatch: Configured %s, detected %s\n", 27087102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck id->name, mid->name); 27187102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck 27287102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); 27387102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (config < 0) 27487102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return config; 27587102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck 276c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); 27787102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (device_config < 0) 27887102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return device_config; 27987102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck 2808b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck data = devm_kzalloc(&client->dev, sizeof(struct adm1275_data), 2818b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck GFP_KERNEL); 28287102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck if (!data) 28387102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck return -ENOMEM; 28487102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck 28587102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck data->id = mid->driver_data; 286c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 287c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck info = &data->info; 288c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 28983f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->pages = 1; 2901061d8518f8bde548a03a5ff77dbe9a4202ad826Guenter Roeck info->format[PSC_VOLTAGE_IN] = direct; 2911061d8518f8bde548a03a5ff77dbe9a4202ad826Guenter Roeck info->format[PSC_VOLTAGE_OUT] = direct; 2921061d8518f8bde548a03a5ff77dbe9a4202ad826Guenter Roeck info->format[PSC_CURRENT_OUT] = direct; 2937e97bbba62754ea86e191b99c6978476198ecb99Guenter Roeck info->m[PSC_CURRENT_OUT] = 807; 29483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->b[PSC_CURRENT_OUT] = 20475; 29583f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->R[PSC_CURRENT_OUT] = -1; 29683f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; 29783f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 298c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck info->read_word_data = adm1275_read_word_data; 299c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck info->read_byte_data = adm1275_read_byte_data; 300c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck info->write_word_data = adm1275_write_word_data; 301c576e30cd0c9814b3b45772d46924d796f538deeGuenter Roeck 302927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (data->id == adm1075) { 303927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_VOLTAGE_IN] = 27169; 304927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->b[PSC_VOLTAGE_IN] = 0; 305927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->R[PSC_VOLTAGE_IN] = -1; 306927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_VOLTAGE_OUT] = 27169; 307927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->b[PSC_VOLTAGE_OUT] = 0; 308927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->R[PSC_VOLTAGE_OUT] = -1; 309927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck } else if (config & ADM1275_VRANGE) { 3107e97bbba62754ea86e191b99c6978476198ecb99Guenter Roeck info->m[PSC_VOLTAGE_IN] = 19199; 31183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->b[PSC_VOLTAGE_IN] = 0; 31283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->R[PSC_VOLTAGE_IN] = -2; 3137e97bbba62754ea86e191b99c6978476198ecb99Guenter Roeck info->m[PSC_VOLTAGE_OUT] = 19199; 31483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->b[PSC_VOLTAGE_OUT] = 0; 31583f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->R[PSC_VOLTAGE_OUT] = -2; 31683f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck } else { 3177e97bbba62754ea86e191b99c6978476198ecb99Guenter Roeck info->m[PSC_VOLTAGE_IN] = 6720; 31883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->b[PSC_VOLTAGE_IN] = 0; 31983f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->R[PSC_VOLTAGE_IN] = -1; 3207e97bbba62754ea86e191b99c6978476198ecb99Guenter Roeck info->m[PSC_VOLTAGE_OUT] = 6720; 32183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->b[PSC_VOLTAGE_OUT] = 0; 32283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck info->R[PSC_VOLTAGE_OUT] = -1; 32383f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck } 32483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 325c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck if (device_config & ADM1275_IOUT_WARN2_SELECT) 326c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck data->have_oc_fault = true; 327c5e6763667ffc94eaad4634841cb1b7ecd951fb7Guenter Roeck 32887102808d03948c825c3bdc48316e48f6422fd7eGuenter Roeck switch (data->id) { 329927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case adm1075: 330927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->format[PSC_POWER] = direct; 331927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->b[PSC_POWER] = 0; 332927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->R[PSC_POWER] = -1; 333927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck switch (config & ADM1075_IRANGE_MASK) { 334927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case ADM1075_IRANGE_25: 335927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_POWER] = 8549; 336927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_CURRENT_OUT] = 806; 337927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 338927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck case ADM1075_IRANGE_50: 339927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_POWER] = 4279; 340927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_CURRENT_OUT] = 404; 341927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 342927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck default: 343927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck dev_err(&client->dev, "Invalid input current range"); 344927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_POWER] = 0; 345927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->m[PSC_CURRENT_OUT] = 0; 346927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 347927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck } 348927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 349927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck | PMBUS_HAVE_STATUS_INPUT; 350927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 351927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck info->func[0] |= 352927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 353927112696654f4c96a85aa8a494866cbc6ccfbe6Guenter Roeck break; 3545cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck case adm1275: 3555cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 3565cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->func[0] |= 3575cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 3585cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck else 3595cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->func[0] |= 3605cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; 3615cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck break; 3625cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck case adm1276: 3635cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->format[PSC_POWER] = direct; 3645cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 3655cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck | PMBUS_HAVE_STATUS_INPUT; 3665cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck if (config & ADM1275_VIN_VOUT_SELECT) 3675cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->func[0] |= 3685cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 3695cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck if (config & ADM1275_VRANGE) { 3705cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->m[PSC_POWER] = 6043; 3715cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->b[PSC_POWER] = 0; 3725cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->R[PSC_POWER] = -2; 3735cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck } else { 3745cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->m[PSC_POWER] = 2115; 3755cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->b[PSC_POWER] = 0; 3765cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck info->R[PSC_POWER] = -1; 3775cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck } 3785cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck break; 3795cf231a346fb80d7945aa46e90186a068a3a001bGuenter Roeck } 38083f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 3818b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck return pmbus_do_probe(client, id, info); 38283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck} 38383f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 38483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeckstatic struct i2c_driver adm1275_driver = { 38583f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck .driver = { 38683f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck .name = "adm1275", 38783f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck }, 38883f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck .probe = adm1275_probe, 389dd285ad7373bf5d21cceacb3b7a5eb8b72d37085Guenter Roeck .remove = pmbus_do_remove, 39083f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck .id_table = adm1275_id, 39183f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck}; 39283f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 393f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(adm1275_driver); 39483f7649c52871d4b0799c209c364374b682fa4a8Guenter Roeck 39583f7649c52871d4b0799c209c364374b682fa4a8Guenter RoeckMODULE_AUTHOR("Guenter Roeck"); 3965cf231a346fb80d7945aa46e90186a068a3a001bGuenter RoeckMODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles"); 39783f7649c52871d4b0799c209c364374b682fa4a8Guenter RoeckMODULE_LICENSE("GPL"); 398