213 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hardware monitoring driver for ucd9200 series Digital PWM System Controllers4 *5 * Copyright (C) 2011 Ericsson AB.6 */7 8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/init.h>12#include <linux/err.h>13#include <linux/slab.h>14#include <linux/i2c.h>15#include <linux/pmbus.h>16#include "pmbus.h"17 18#define UCD9200_PHASE_INFO 0xd219#define UCD9200_DEVICE_ID 0xfd20 21enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246,22 ucd9248 };23 24static const struct i2c_device_id ucd9200_id[] = {25 {"ucd9200", ucd9200},26 {"ucd9220", ucd9220},27 {"ucd9222", ucd9222},28 {"ucd9224", ucd9224},29 {"ucd9240", ucd9240},30 {"ucd9244", ucd9244},31 {"ucd9246", ucd9246},32 {"ucd9248", ucd9248},33 {}34};35MODULE_DEVICE_TABLE(i2c, ucd9200_id);36 37static const struct of_device_id __maybe_unused ucd9200_of_match[] = {38 {39 .compatible = "ti,cd9200",40 .data = (void *)ucd920041 },42 {43 .compatible = "ti,cd9220",44 .data = (void *)ucd922045 },46 {47 .compatible = "ti,cd9222",48 .data = (void *)ucd922249 },50 {51 .compatible = "ti,cd9224",52 .data = (void *)ucd922453 },54 {55 .compatible = "ti,cd9240",56 .data = (void *)ucd924057 },58 {59 .compatible = "ti,cd9244",60 .data = (void *)ucd924461 },62 {63 .compatible = "ti,cd9246",64 .data = (void *)ucd924665 },66 {67 .compatible = "ti,cd9248",68 .data = (void *)ucd924869 },70 { },71};72MODULE_DEVICE_TABLE(of, ucd9200_of_match);73 74static int ucd9200_probe(struct i2c_client *client)75{76 u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];77 struct pmbus_driver_info *info;78 const struct i2c_device_id *mid;79 enum chips chip;80 int i, j, ret;81 82 if (!i2c_check_functionality(client->adapter,83 I2C_FUNC_SMBUS_BYTE_DATA |84 I2C_FUNC_SMBUS_BLOCK_DATA))85 return -ENODEV;86 87 ret = i2c_smbus_read_block_data(client, UCD9200_DEVICE_ID,88 block_buffer);89 if (ret < 0) {90 dev_err(&client->dev, "Failed to read device ID\n");91 return ret;92 }93 block_buffer[ret] = '\0';94 dev_info(&client->dev, "Device ID %s\n", block_buffer);95 96 for (mid = ucd9200_id; mid->name[0]; mid++) {97 if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))98 break;99 }100 if (!mid->name[0]) {101 dev_err(&client->dev, "Unsupported device\n");102 return -ENODEV;103 }104 105 if (client->dev.of_node)106 chip = (uintptr_t)of_device_get_match_data(&client->dev);107 else108 chip = mid->driver_data;109 110 if (chip != ucd9200 && strcmp(client->name, mid->name) != 0)111 dev_notice(&client->dev,112 "Device mismatch: Configured %s, detected %s\n",113 client->name, mid->name);114 115 info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),116 GFP_KERNEL);117 if (!info)118 return -ENOMEM;119 120 ret = i2c_smbus_read_block_data(client, UCD9200_PHASE_INFO,121 block_buffer);122 if (ret < 0) {123 dev_err(&client->dev, "Failed to read phase information\n");124 return ret;125 }126 127 /*128 * Calculate number of configured pages (rails) from PHASE_INFO129 * register.130 * Rails have to be sequential, so we can abort after finding131 * the first unconfigured rail.132 */133 info->pages = 0;134 for (i = 0; i < ret; i++) {135 if (!block_buffer[i])136 break;137 info->pages++;138 }139 if (!info->pages) {140 dev_err(&client->dev, "No rails configured\n");141 return -ENODEV;142 }143 dev_info(&client->dev, "%d rails configured\n", info->pages);144 145 /*146 * Set PHASE registers on all pages to 0xff to ensure that phase147 * specific commands will apply to all phases of a given page (rail).148 * This only affects the READ_IOUT and READ_TEMPERATURE2 registers.149 * READ_IOUT will return the sum of currents of all phases of a rail,150 * and READ_TEMPERATURE2 will return the maximum temperature detected151 * for the phases of the rail.152 */153 for (i = 0; i < info->pages; i++) {154 /*155 * Setting PAGE & PHASE fails once in a while for no obvious156 * reason, so we need to retry a couple of times.157 */158 for (j = 0; j < 3; j++) {159 ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);160 if (ret < 0)161 continue;162 ret = i2c_smbus_write_byte_data(client, PMBUS_PHASE,163 0xff);164 if (ret < 0)165 continue;166 break;167 }168 if (ret < 0) {169 dev_err(&client->dev,170 "Failed to initialize PHASE registers\n");171 return ret;172 }173 }174 if (info->pages > 1)175 i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);176 177 info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |178 PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |179 PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |180 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |181 PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP |182 PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;183 184 for (i = 1; i < info->pages; i++)185 info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |186 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |187 PMBUS_HAVE_POUT |188 PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;189 190 /* ucd9240 supports a single fan */191 if (mid->driver_data == ucd9240)192 info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12;193 194 return pmbus_do_probe(client, info);195}196 197/* This is the driver that will be inserted */198static struct i2c_driver ucd9200_driver = {199 .driver = {200 .name = "ucd9200",201 .of_match_table = of_match_ptr(ucd9200_of_match),202 },203 .probe = ucd9200_probe,204 .id_table = ucd9200_id,205};206 207module_i2c_driver(ucd9200_driver);208 209MODULE_AUTHOR("Guenter Roeck");210MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x");211MODULE_LICENSE("GPL");212MODULE_IMPORT_NS(PMBUS);213