Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  dat_v1.c   Sprache: C

 
// SPDX-License-Identifier: BSD-3-Clause
/*
 * Copyright (c) 2020, MIPI Alliance, Inc.
 *
 * Author: Nicolas Pitre <npitre@baylibre.com>
 */


#include <linux/bitfield.h>
#include <linux/bitmap.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/i3c/master.h>
#include <linux/io.h>

#include "hci.h"
#include "dat.h"


/*
 * Device Address Table Structure
 */


#define DAT_1_AUTOCMD_HDR_CODE  W1_MASK(58, 51)
#define DAT_1_AUTOCMD_MODE  W1_MASK(50, 48)
#define DAT_1_AUTOCMD_VALUE  W1_MASK(47, 40)
#define DAT_1_AUTOCMD_MASK  W1_MASK(39, 32)
/* DAT_0_I2C_DEVICE W0_BIT_(31) */
#define DAT_0_DEV_NACK_RETRY_CNT W0_MASK(30, 29)
#define DAT_0_RING_ID   W0_MASK(28, 26)
#define DAT_0_DYNADDR_PARITY  W0_BIT_(23)
#define DAT_0_DYNAMIC_ADDRESS  W0_MASK(22, 16)
#define DAT_0_TS   W0_BIT_(15)
#define DAT_0_MR_REJECT   W0_BIT_(14)
/* DAT_0_SIR_REJECT W0_BIT_(13) */
/* DAT_0_IBI_PAYLOAD W0_BIT_(12) */
#define DAT_0_STATIC_ADDRESS  W0_MASK(6, 0)

#define dat_w0_read(i)  readl(hci->DAT_regs + (i) * 8)
#define dat_w1_read(i)  readl(hci->DAT_regs + (i) * 8 + 4)
#define dat_w0_write(i, v) writel(v, hci->DAT_regs + (i) * 8)
#define dat_w1_write(i, v) writel(v, hci->DAT_regs + (i) * 8 + 4)

static int hci_dat_v1_init(struct i3c_hci *hci)
{
 unsigned int dat_idx;

 if (!hci->DAT_regs) {
  dev_err(&hci->master.dev,
   "only DAT in register space is supported at the moment\n");
  return -EOPNOTSUPP;
 }
 if (hci->DAT_entry_size != 8) {
  dev_err(&hci->master.dev,
   "only 8-bytes DAT entries are supported at the moment\n");
  return -EOPNOTSUPP;
 }

 if (!hci->DAT_data) {
  /* use a bitmap for faster free slot search */
  hci->DAT_data = bitmap_zalloc(hci->DAT_entries, GFP_KERNEL);
  if (!hci->DAT_data)
   return -ENOMEM;

  /* clear them */
  for (dat_idx = 0; dat_idx < hci->DAT_entries; dat_idx++) {
   dat_w0_write(dat_idx, 0);
   dat_w1_write(dat_idx, 0);
  }
 }

 return 0;
}

static void hci_dat_v1_cleanup(struct i3c_hci *hci)
{
 bitmap_free(hci->DAT_data);
 hci->DAT_data = NULL;
}

static int hci_dat_v1_alloc_entry(struct i3c_hci *hci)
{
 unsigned int dat_idx;
 int ret;

 if (!hci->DAT_data) {
  ret = hci_dat_v1_init(hci);
  if (ret)
   return ret;
 }
 dat_idx = find_first_zero_bit(hci->DAT_data, hci->DAT_entries);
 if (dat_idx >= hci->DAT_entries)
  return -ENOENT;
 __set_bit(dat_idx, hci->DAT_data);

 /* default flags */
 dat_w0_write(dat_idx, DAT_0_SIR_REJECT | DAT_0_MR_REJECT);

 return dat_idx;
}

static void hci_dat_v1_free_entry(struct i3c_hci *hci, unsigned int dat_idx)
{
 dat_w0_write(dat_idx, 0);
 dat_w1_write(dat_idx, 0);
 if (hci->DAT_data)
  __clear_bit(dat_idx, hci->DAT_data);
}

static void hci_dat_v1_set_dynamic_addr(struct i3c_hci *hci,
     unsigned int dat_idx, u8 address)
{
 u32 dat_w0;

 dat_w0 = dat_w0_read(dat_idx);
 dat_w0 &= ~(DAT_0_DYNAMIC_ADDRESS | DAT_0_DYNADDR_PARITY);
 dat_w0 |= FIELD_PREP(DAT_0_DYNAMIC_ADDRESS, address) |
    (parity8(address) ? 0 : DAT_0_DYNADDR_PARITY);
 dat_w0_write(dat_idx, dat_w0);
}

static void hci_dat_v1_set_static_addr(struct i3c_hci *hci,
           unsigned int dat_idx, u8 address)
{
 u32 dat_w0;

 dat_w0 = dat_w0_read(dat_idx);
 dat_w0 &= ~DAT_0_STATIC_ADDRESS;
 dat_w0 |= FIELD_PREP(DAT_0_STATIC_ADDRESS, address);
 dat_w0_write(dat_idx, dat_w0);
}

static void hci_dat_v1_set_flags(struct i3c_hci *hci, unsigned int dat_idx,
     u32 w0_flags, u32 w1_flags)
{
 u32 dat_w0, dat_w1;

 dat_w0 = dat_w0_read(dat_idx);
 dat_w1 = dat_w1_read(dat_idx);
 dat_w0 |= w0_flags;
 dat_w1 |= w1_flags;
 dat_w0_write(dat_idx, dat_w0);
 dat_w1_write(dat_idx, dat_w1);
}

static void hci_dat_v1_clear_flags(struct i3c_hci *hci, unsigned int dat_idx,
       u32 w0_flags, u32 w1_flags)
{
 u32 dat_w0, dat_w1;

 dat_w0 = dat_w0_read(dat_idx);
 dat_w1 = dat_w1_read(dat_idx);
 dat_w0 &= ~w0_flags;
 dat_w1 &= ~w1_flags;
 dat_w0_write(dat_idx, dat_w0);
 dat_w1_write(dat_idx, dat_w1);
}

static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr)
{
 unsigned int dat_idx;
 u32 dat_w0;

 for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) {
  dat_w0 = dat_w0_read(dat_idx);
  if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr)
   return dat_idx;
 }

 return -ENODEV;
}

const struct hci_dat_ops mipi_i3c_hci_dat_v1 = {
 .init   = hci_dat_v1_init,
 .cleanup  = hci_dat_v1_cleanup,
 .alloc_entry  = hci_dat_v1_alloc_entry,
 .free_entry  = hci_dat_v1_free_entry,
 .set_dynamic_addr = hci_dat_v1_set_dynamic_addr,
 .set_static_addr = hci_dat_v1_set_static_addr,
 .set_flags  = hci_dat_v1_set_flags,
 .clear_flags  = hci_dat_v1_clear_flags,
 .get_index  = hci_dat_v1_get_index,
};

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

¤ Dauer der Verarbeitung: 0.11 Sekunden  (vorverarbeitet)  ¤

*© 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge