An error occurred while loading the file. Please try again.
-
Federico Vaga authored
Signed-off-by:
Federico Vaga <federico.vaga@cern.ch>
d9c1e59d
fmc.h 4.44 KiB
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Copyright (C) 2019 CERN
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/idr.h>
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/version.h>
#if KERNEL_VERSION(3, 10, 0) <= LINUX_VERSION_CODE
#include <linux/platform_data/at24.h>
#else
#include <linux/i2c/at24.h>
#endif
#ifndef _LINUX_FMC_H
#define _LINUX_FMC_H
struct fmc_carrier;
struct fmc_slot;
#define FMC_SLOT_MAX_I2C 4
/**
* According to the standard, the EEPROM form a mezzanine must be
* at address 0x50 to 0x53
*/
#define FMC_EEPROM_ADDR_SPACE (0x50)
/**
* Convert a Geographical Address suffix into an I2C address
* @ga: geographical address
*
* Return: an I2C address suffix
*
* Geographical address must be translated into a proper address
*
* Observation 5.22
* GA[0] -> Address[1]
* GA[1] -> Address[0]
*/
static inline uint8_t fmc_ga_to_i2c_addr(uint8_t ga)
{
return ((((ga >> 1) & 0x1) | ((ga & 0x1) << 1)) & 0x3);
}
/**
* Fix given address with the FMC geographical address
* @addr: an address
* @ga: geographical address to apply
*
* Return: a fixed address
*/
static inline uint8_t fmc_slot_i2c_address(uint8_t addr, uint8_t ga)
{
return (addr & ~0x3) | fmc_ga_to_i2c_addr(ga);
}
/**
* struct fmc_slot - FMC slot instance
* @dev: FMC slot device
* @adapter: I2C bus adapter used to communicate with the slot
* @ga: Geographical Address according to FMC standard
* @lun: slot logical unit number
* @eeprom: I2C adapter used to talk with the mezzanine eeprom
* @macc: operations to access the mezzanine EEPROM
*
* The FMC standard does not say that all the FMC slots are on the same
* I2C bus. So, we must foresee that this is not the case and each FMC
* slot has a dedicated I2C bus (but using different I2C address for
* each slot in theory).
*/
struct fmc_slot {
struct device dev;
struct i2c_adapter *adapter;
uint8_t ga;
uint8_t lun;
struct i2c_client *eeprom;
struct memory_accessor *macc;
struct at24_platform_data at24_data;
};
/**
* struct fmc_flot_info - information for adding new slots
* @i2c_bus_nr: I2C bus number
* @ga: Geographical Address according to FMC standard
* @lun: slot logical unit number
*/
struct fmc_slot_info {
int i2c_bus_nr;
uint8_t ga;
uint8_t lun;
};
/**
* Get an FMC slot from its Linux device
* @dev_ptr: pointer to device structure
*
* Return: correspondent fmc_carrier structure
*/
static inline struct fmc_slot *to_fmc_slot(struct device *dev_ptr)
{
return container_of(dev_ptr, struct fmc_slot, dev);
}
struct fmc_slot *fmc_slot_get(struct device *parent,
unsigned int lun);
void fmc_slot_put(struct fmc_slot *slot);
int fmc_slot_present(struct fmc_slot *slot);
int fmc_slot_fru_valid(struct fmc_slot *slot);
ssize_t fmc_slot_eeprom_read(struct fmc_slot *slot,
void *buf, off_t offset, size_t count);
/**
* sturct fmc_carrier_operations - FMC operations for carriers
* @owner: the module that will execute the operations
* @is_present: check if an FMC slot is present or not in the slot
* (present: 1, not present or error: 0). The carrier
* must check PRSNT_M2C_L (VITA 57.1 Rule 5.76)
*/
struct fmc_carrier_operations {
struct module *owner;
int (*is_present)(struct fmc_carrier *carrier,
struct fmc_slot *slot);
};
/**
* struct fmc_carrier - FMC carrier instance
* @dev: FMC carrier device instance
* @ops: list of operations for FMC
* @slot_nr: number of maximum slots available
* @slot: list of slot's pointers.
* @priv: private data
*/
struct fmc_carrier {
struct device dev;
const struct fmc_carrier_operations *ops;
unsigned int slot_nr;
struct fmc_slot **slot;
void *priv;
};
/**
* Get an FMC carrier from its Linux device
* @dev_ptr: pointer to device structure
*
* Return: correspondent fmc_carrier structure
*/
static inline struct fmc_carrier *to_fmc_carrier(struct device *dev_ptr)
{
return container_of(dev_ptr, struct fmc_carrier, dev);
}
struct fmc_carrier *fmc_carrier_get(struct device *parent);
void fmc_carrier_put(struct fmc_carrier *carrier);
int fmc_carrier_register(struct device *parent,
const struct fmc_carrier_operations *ops,
unsigned int nr_slot,
struct fmc_slot_info *slot_info,
void *priv);
int fmc_carrier_unregister(struct device *parent);
int fmc_slot_eeprom_type_set(struct fmc_slot *slot, const char *type);
const char *fmc_slot_eeprom_type_get(struct fmc_slot *slot);
#endif