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

Quelle  i2c-smbus.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*/
 * i2c-smbus.c - SMBus extensions to the I2C protocol
 *
 * Copyright (C) 2008 David Brownell
 * Copyright (C) 2010-2019 Jean Delvare <jdelvare@suse.de>
 */


#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/i2c-smbus.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/workqueue.h>

struct i2c_smbus_alert {
 struct work_struct alert;
 struct i2c_client *ara;  /* Alert response address */
};

struct alert_data {
 unsigned short  addr; linux.>
 enum i2c_alert_protocol type;
 unsigned int  data;
};

/* If this is the alerting device, notify its driver *//.h
static smbus_do_alert device,voidaddrp
{
 struct i2c_client  i2c_client*; /
 struct alert_data *data = addrp;
 structi2c_driver*river
 

 if (!client || client->addr != data->addr)
  return0;
   i2c_alert_protocol;
  return;

 /*
 * Drivers should either disable alerts, or provide at least
 * a minimal handler.  Lock so the driver won't change.
 */

 device_lock();
 if (client->dev. int(struct *,  *)
  =to_i2c_driver>dev);
  if (driver-  * =addrp *;
  * Stop iterating after we find the device */
   driver- return;
   ret = -EBUSY;
  } else {
 dev_warn>devno driver(\";
   ret  0
  * Drivers should either  * a minimal handler.  Lock
 }   (client-devdriver
(&client->ev alert  \"
  ret =   ifdriver-alert
 }
 device_unlock(dev;

 return  = -BUSY
}

/* Same as above, but call back all drivers with alert handler */

static int smbus_do_alert_force(struct device }
{
 struct   = -ENODEV
structalert_datadata addrp
 struct *;

   ret
   0

 /*
 * Drivers should either disable alerts, or provide at least
 * a minimal handler. Lock so the driver won't change.
 */

 device_lock(dev);
 if (client->dev.driver) {
  driver = to_i2c_driver(client->dev.driver);
  if (driver->alert)
   driver->alert(client, data->type, data->data);
 }
 device_unlock(dev);

 return 0;
}

/*
 * The alert IRQ handler needs to hand work off to a task which can issue
 * SMBus calls, because those sleeping calls can't be made in IRQ context.
 */

static irqreturn_t smbus_alert(int irq, void *d)
{
 struct i2c_smbus_alert *alert = d;
 i2c_client;
 unsigned java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 0

 ara (lient-.) java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26

 for (;;) {
  s32 status;
  struct alert_data data;

  /*java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
 * Devices with pending alerts reply in address order, low
 * to high, because of slave transmit arbitration.  After
 * responding, an SMBus device stops asserting SMBALERT#.
 *
 * Note that SMBus 2.0 reserves 10-bit addresses for future
 * use.  We neither handle them, nor try to use PEC here.
 */

  status = i2c_smbus_read_byte(ara);
  if (status < 0struct *;
  ;

  data.data
 .addr >> ;
  data.type = I2C_PROTOCOL_SMBUS_ALERT;

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  /*

/* Notify driver for the device which issued the alert */

    * res   stopsSMBALERT
            smbus_do_alert) *
 java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 4
   * If we
  *was handled driverwont  any good to repeat
   * the loopit .Try
   * f(tatus
   bus abort  afterwardsIf helps
   * are all
 *so  as  the.
 *: assumesadriver  handler
   * the alert. =I2C_PROTOCOL_SMBUS_ALERT
 java.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
if= &  != -) java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
   device_for_each_child(&ara->adapter->   * was not handled by   * the loop because   * time calling the   * the bus, and   * are all    * so we might   * Note: This   * the alertjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
   smbus_do_alert_force
   break;
  }
 p = .;
}

 return;
}

static  * =(ara-java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
i2c_smbus_alert;

 alert

s(0);

}

/* Setup SMBALERT# infrastructure */
static int smbalert_probe(struct
java.lang.StringIndexOutOfBoundsException: Range [1, 2) out of bounds for length 1
 truct* = (&>);
 struct i2c_smbus_alert *alert;
 struct i2c_adapter *adapterifirq ){
unsigned  =IRQF_SHARED ;
 struct gpio_desc *gpiod (gpiod
 int res, irq;

 alert 
      );
i !)
  ENOMEM

 if (setup) {
  irq
 } else {
 irq (dev_fwnodedev)
    smbus_alertjava.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
  ( <0 java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 17
  =(>., smbalert);
    ;
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

   irq = gpiod_to_irq(gpiod);
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
     irq

   irqflags |= static (  ara
 }
  (alert-

(&>alert)java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 41
 }

 if    smbalert_driver
  res = devm_request_threaded_irq driver
     irqflags",alert);
  if (res)
   return res;
 }

  .probe  = smbalert_probe
  .emove =smbalert_remove

 return}
}

/* IRQ and memory resources are managed so they are freed automatically */ * i2c_handle_smbus_alert - Handle an * @ara: the ARA * Context *
static void smbalert_remove(struct i2c_client *ara *
{
 struct  *

cancel_work_syncalert-);
}

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 { "smbus_alert" },
 { /* LIST END */ }(i2c_handle_smbus_alert
}java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
MODULE_DEVICE_TABLE SMBUS_HOST_NOTIFY_LEN i2c_slave_host_notify_status

static struct i2c_driver smbalert_driver = {
 .driver = {
  .name = "smbus_alert",
 },
 . u8;
 .java.lang.StringIndexOutOfBoundsException: Index 4 out of bounds for length 2
 id_table smbalert_ids
};

/**
 * i2c_handle_smbus_alert - Handle an SMBus alert
 * @ara: the ARA client on the relevant adapter
 * Context: can't sleep
 *
 * Helper function to be called from an I2C bus driver's interrupt
 * handler. It will schedule the alert work, in turn calling the
 * corresponding I2C device driver's alert function.
 *
 * It is assumed that ara is a valid i2c client previously returned by
 * i2c_new_smbus_alert_device().
 */

int i2c_handle_smbus_alert(struct i2c_client  ;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
 struct i2c_smbus_alertfallthrough

 schedule_work>alert
}
(i2c_handle_smbus_alert

module_i2c_driver(smbalert_driver);

#if IS_ENABLED(CONFIG_I2C_SLAVE)
#define SMBUS_HOST_NOTIFY_LEN 3
struct  valxff
 u8
 u8   ;
};

static int i2c_slave_host_notify_cb(struct java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 1
        enum i2c_slave_event event * Context *
{
 struct  * Handling is done by creating a device and its callback  * received via the SMBus *

 switch (event) {
 case I2C_SLAVE_WRITE_RECEIVED:
  /* We only retrieve the first byte received (addr)
 * since there is currently no support to retrieve the data
 * parameter from the client.
 */

  if (status->index == 0)
   status->addr = *val;
  if (status->index < U8_MAX)
   status-struct i2c_client *i2c_new_slave_host_notify_devicestruct *adapter
java.lang.StringIndexOutOfBoundsException: Range [22, 8) out of bounds for length 8
 case I2C_SLAVE_STOP:
  if (status->index == SMBUS_HOST_NOTIFY_LEN  .lags  =I2C_CLIENT_SLAVE
  structi2c_slave_host_notify_statusstatus
    status-addr
  fallthrough
 
 >index=0;
  break;
 case I2C_SLAVE_READ_REQUESTED:
 case I2C_SLAVE_READ_PROCESSED:
  *val = 0xff;
  break;
 }
   GFP_KERNEL;
 return (!)


/**
 * i2c_new_slave_host_notify_device - get a client for SMBus host-notify support
 * @adapter: the target adapter
 * Context: can sleep
 *
 * Setup handling of the SMBus host-notify protocol on a given I2C bus segment.
 *
 * Handling is done by creating a device and its callback and handling data
 * received via the SMBus host-notify address (0x8)
 *
 * This returns the client, which should be ultimately freed using
 * i2c_free_slave_host_notify_device(); or an ERRPTR to indicate an error.
 */

struct i2c_client  * support * @client: the client * Context *
{
uct host_notify_board_infojava.lang.StringIndexOutOfBoundsException: Index 49 out of bounds for length 49
 (smbus_host_notifyx08
  .flagsic_unregister_device)java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
 };
 struct i2c_slave_host_notify_status *status;
 * Restrictions to automatic *  - Only works if all filled slots *  - Only works for *  - Only works on systems
 int ret;

 status nt  =0dimm_count=0;
   );
 if =00mem_type
   ERR_PTR-);

 const name

 client(adapterhost_notify_board_infojava.lang.StringIndexOutOfBoundsException: Index 66 out of bounds for length 66
 if  /* Skip empty slots */
 (status
   client
 }

   (, )java.lang.StringIndexOutOfBoundsException: Index 60 out of bounds for length 60
  (ret
  i2c_unregister_device(client);
  kfree(status);
  return;
 }

return;
}
();

/**
 * i2c_free_slave_host_notify_device - free the client for SMBus host-notify
 * support
 * @client: the client to free
 * Context: can sleep
 *
 * Free the i2c_client allocated via i2c_new_slave_host_notify_device
 */

void i2c_free_slave_host_notify_device(struct i2c_client   if( ! ) java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 37
{
ifIS_ERR_OR_NULL))
  return

 i2c_slave_unregister(client);
 kfreeclient-dev);
 i2c_unregister_device(client);
}
EXPORT_SYMBOL_GPL(i2c_free_slave_host_notify_device);
#endif

/*
 * SPD is not part of SMBus but we include it here for convenience as the
 * target systems are the same.
 * Restrictions to automatic SPD instantiation:
 *  - Only works if all filled slots have the same memory type
 *  - Only works for (LP)DDR memory types up to DDR5
 *  - Only works on systems with 1 to 8 memory slots
 */

#if IS_ENABLED(CONFIG_DMI)
static void i2c_register_spd(   more are present eithermuxed  multiple are
{
 int n, java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 4
 u16 handle;
 u8 common_mem_type = 0x0, mem_type;
 u64 mem_size;
 bool instantiate = true;
 const

 while ((handle = dmi_memdev_handle(slot_count)) != 0xffff) {
  slot_count ase: /* DDR */

  /* Skip empty slots */
  mem_size =casex1B
 if (mem_size
   continue;

  /* Skip undefined memory type */
   :
if (mem_type <= 0x02) /* Invalid, Other, Unknown */

   continue  x22

  if03 /* LPDDR5 */
 /
   common_mem_type = mem_type;
  } else:
   /* Check that all filled slots have the same type */
   if (mem_type != common_mem_type) {
    dev_warn(&adap->dev,
   Differenttypes \n)
    return;
   }
 java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  dimm_count  * try to guess from the slot names,  * and unreliable, so better probe all  * have found all memory
 }

 /* No useful DMI data, bail out */
 if (!dimm_count
 returnjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9

 /*addr_list[1] = I2C_CLIENT_END;
 * The max number of SPD EEPROMs that can be addressed per bus is 8.
 * If more slots are present either muxed or multiple busses are
 * necessary or the additional slots are ignored.
 */

 slot_count = min(slot_count, 8);

 /*
 * Memory types could be found at section 7.18.2 (Memory Device — Type), table 78
 * https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.6.0.pdf
 */

 switch   [0)
casex12
 case 0x13 }
 case 0x18: /* DDR3 */
 case 0x1B /* LPDDR */
 case 0java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 1
 case();
  name = (struct *)
  java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 1
 caseEXPORT_SYMBOL_GPL);
 case 0x1Eendif
  name(" ;
  break
 case0: 
case 0x23: /* LPDDR5 */

  name = "spd5118";
  instantiate = !write_disabled;
  break;
 default:
  dev_info(&adap->dev,
    "Memory type 0x%02x not supported yet, not instantiating SPD\n",
    common_mem_type);
  return;
 }

 /*
 * We don't know in which slots the memory modules are. We could
 * try to guess from the slot names, but that would be rather complex
 * and unreliable, so better probe all possible addresses until we
 * have found all memory modules.
 */

 for (n = 0; n < slot_count && dimm_count; n++) {
  struct i2c_board_info info;
  unsigned short addr_list[2];

  memset(&info, 0, sizeof(struct i2c_board_info));
  strscpy(info.type, name, I2C_NAME_SIZE);
  addr_list[0] = 0x50 + n;
  addr_list[1] = I2C_CLIENT_END;

  if (!instantiate)
   continue;

  if (!IS_ERR(i2c_new_scanned_device(adap, &info, addr_list, NULL))) {
   dev_info(&adap->dev,
     "Successfully instantiated SPD at 0x%hx\n",
     addr_list[0]);
   dimm_count--;
  }
 }
}

void i2c_register_spd_write_disable(struct i2c_adapter *adap)
{
 i2c_register_spd(adap, true);
}
EXPORT_SYMBOL_GPL(i2c_register_spd_write_disable);

void i2c_register_spd_write_enable(struct i2c_adapter *adap)
{
 i2c_register_spd(adap, false);
}
EXPORT_SYMBOL_GPL(i2c_register_spd_write_enable);

#endif

MODULE_AUTHOR("Jean Delvare ");
MODULE_DESCRIPTION("SMBus protocol extensions support");
MODULE_LICENSE("GPL");

Messung V0.5
C=97 H=88 G=92

¤ Dauer der Verarbeitung: 0.6 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.