Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/drivers/hwmon/pmbus/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  pim4328.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Hardware monitoring driver for PIM4006, PIM4328 and PIM4820
 *
 * Copyright (c) 2021 Flextronics International Sweden AB
 */


#include <linux/err.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/pmbus.h>
#include <linux/slab.h>
#include "pmbus.h"

enum chips { pim4006, pim4328, pim4820 };

struct pim4328_data {
 enum chips id;
 struct pmbus_driver_info info;
};

#define to_pim4328_data(x)  container_of(x, struct pim4328_data, info)

/* PIM4006 and PIM4328 */
#define PIM4328_MFR_READ_VINA  0xd3
#define PIM4328_MFR_READ_VINB  0xd4

/* PIM4006 */
#define PIM4328_MFR_READ_IINA  0xd6
#define PIM4328_MFR_READ_IINB  0xd7
#define PIM4328_MFR_FET_CHECKSTATUS 0xd9

/* PIM4328 */
#define PIM4328_MFR_STATUS_BITS  0xd5

/* PIM4820 */
#define PIM4328_MFR_READ_STATUS  0xd0

static const struct i2c_device_id pim4328_id[] = {
 {"bmr455", pim4328},
 {"pim4006", pim4006},
 {"pim4106", pim4006},
 {"pim4206", pim4006},
 {"pim4306", pim4006},
 {"pim4328", pim4328},
 {"pim4406", pim4006},
 {"pim4820", pim4820},
 {}
};
MODULE_DEVICE_TABLE(i2c, pim4328_id);

static int pim4328_read_word_data(struct i2c_client *client, int page,
      int phase, int reg)
{
 int ret;

 if (page > 0)
  return -ENXIO;

 if (phase == 0xff)
  return -ENODATA;

 switch (reg) {
 case PMBUS_READ_VIN:
  ret = pmbus_read_word_data(client, page, phase,
        phase == 0 ? PIM4328_MFR_READ_VINA
            : PIM4328_MFR_READ_VINB);
  break;
 case PMBUS_READ_IIN:
  ret = pmbus_read_word_data(client, page, phase,
        phase == 0 ? PIM4328_MFR_READ_IINA
            : PIM4328_MFR_READ_IINB);
  break;
 default:
  ret = -ENODATA;
 }

 return ret;
}

static int pim4328_read_byte_data(struct i2c_client *client, int page, int reg)
{
 const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
 struct pim4328_data *data = to_pim4328_data(info);
 int ret, status;

 if (page > 0)
  return -ENXIO;

 switch (reg) {
 case PMBUS_STATUS_BYTE:
  ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE);
  if (ret < 0)
   return ret;
  if (data->id == pim4006) {
   status = pmbus_read_word_data(client, page, 0xff,
            PIM4328_MFR_FET_CHECKSTATUS);
   if (status < 0)
    return status;
   if (status & 0x0630) /* Input UV */
    ret |= PB_STATUS_VIN_UV;
  } else if (data->id == pim4328) {
   status = pmbus_read_byte_data(client, page,
            PIM4328_MFR_STATUS_BITS);
   if (status < 0)
    return status;
   if (status & 0x04) /* Input UV */
    ret |= PB_STATUS_VIN_UV;
   if (status & 0x40) /* Output UV */
    ret |= PB_STATUS_NONE_ABOVE;
  } else if (data->id == pim4820) {
   status = pmbus_read_byte_data(client, page,
            PIM4328_MFR_READ_STATUS);
   if (status < 0)
    return status;
   if (status & 0x05) /* Input OV or OC */
    ret |= PB_STATUS_NONE_ABOVE;
   if (status & 0x1a) /* Input UV */
    ret |= PB_STATUS_VIN_UV;
   if (status & 0x40) /* OT */
    ret |= PB_STATUS_TEMPERATURE;
  }
  break;
 default:
  ret = -ENODATA;
 }

 return ret;
}

static int pim4328_probe(struct i2c_client *client)
{
 int status;
 u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
 const struct i2c_device_id *mid;
 struct pim4328_data *data;
 struct pmbus_driver_info *info;
 struct pmbus_platform_data *pdata;
 struct device *dev = &client->dev;

 if (!i2c_check_functionality(client->adapter,
         I2C_FUNC_SMBUS_READ_BYTE_DATA
         | I2C_FUNC_SMBUS_BLOCK_DATA))
  return -ENODEV;

 data = devm_kzalloc(&client->dev, sizeof(struct pim4328_data),
       GFP_KERNEL);
 if (!data)
  return -ENOMEM;

 status = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, device_id);
 if (status < 0) {
  dev_err(&client->dev, "Failed to read Manufacturer Model\n");
  return status;
 }
 for (mid = pim4328_id; mid->name[0]; mid++) {
  if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
   break;
 }
 if (!mid->name[0]) {
  dev_err(&client->dev, "Unsupported device\n");
  return -ENODEV;
 }

 if (strcmp(client->name, mid->name))
  dev_notice(&client->dev,
      "Device mismatch: Configured %s, detected %s\n",
      client->name, mid->name);

 data->id = mid->driver_data;
 info = &data->info;
 info->pages = 1;
 info->read_byte_data = pim4328_read_byte_data;
 info->read_word_data = pim4328_read_word_data;

 pdata = devm_kzalloc(dev, sizeof(struct pmbus_platform_data),
        GFP_KERNEL);
 if (!pdata)
  return -ENOMEM;
 dev->platform_data = pdata;
 pdata->flags = PMBUS_NO_CAPABILITY | PMBUS_NO_WRITE_PROTECT;

 switch (data->id) {
 case pim4006:
  info->phases[0] = 2;
  info->func[0] = PMBUS_PHASE_VIRTUAL | PMBUS_HAVE_VIN
   | PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT;
  info->pfunc[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN;
  info->pfunc[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN;
  break;
 case pim4328:
  info->phases[0] = 2;
  info->func[0] = PMBUS_PHASE_VIRTUAL
   | PMBUS_HAVE_VCAP | PMBUS_HAVE_VIN
   | PMBUS_HAVE_TEMP | PMBUS_HAVE_IOUT;
  info->pfunc[0] = PMBUS_HAVE_VIN;
  info->pfunc[1] = PMBUS_HAVE_VIN;
  info->format[PSC_VOLTAGE_IN] = direct;
  info->format[PSC_TEMPERATURE] = direct;
  info->format[PSC_CURRENT_OUT] = direct;
  pdata->flags |= PMBUS_USE_COEFFICIENTS_CMD;
  break;
 case pim4820:
  info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_TEMP
   | PMBUS_HAVE_IIN;
  info->format[PSC_VOLTAGE_IN] = direct;
  info->format[PSC_TEMPERATURE] = direct;
  info->format[PSC_CURRENT_IN] = direct;
  pdata->flags |= PMBUS_USE_COEFFICIENTS_CMD;
  break;
 default:
  return -ENODEV;
 }

 return pmbus_do_probe(client, info);
}

static struct i2c_driver pim4328_driver = {
 .driver = {
     .name = "pim4328",
     },
 .probe = pim4328_probe,
 .id_table = pim4328_id,
};

module_i2c_driver(pim4328_driver);

MODULE_AUTHOR("Erik Rosen ");
MODULE_DESCRIPTION("PMBus driver for PIM4006, PIM4328, PIM4820 power interface modules");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("PMBUS");

Messung V0.5
C=96 H=95 G=95

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.