linux/drivers/fsi/fsi-core.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * FSI core driver
 *
 * Copyright (C) IBM Corporation 2016
 *
 * TODO:
 *  - Rework topology
 *  - s/chip_id/chip_loc
 *  - s/cfam/chip (cfam_id -> chip_id etc...)
 */

#include <linux/crc4.h>
#include <linux/device.h>
#include <linux/fsi.h>
#include <linux/idr.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/bitops.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/uaccess.h>

#include "fsi-master.h"
#include "fsi-slave.h"

#define CREATE_TRACE_POINTS
#include <trace/events/fsi.h>

#define FSI_SLAVE_CONF_NEXT_MASK
#define FSI_SLAVE_CONF_SLOTS_MASK
#define FSI_SLAVE_CONF_SLOTS_SHIFT
#define FSI_SLAVE_CONF_VERSION_MASK
#define FSI_SLAVE_CONF_VERSION_SHIFT
#define FSI_SLAVE_CONF_TYPE_MASK
#define FSI_SLAVE_CONF_TYPE_SHIFT
#define FSI_SLAVE_CONF_CRC_SHIFT
#define FSI_SLAVE_CONF_CRC_MASK
#define FSI_SLAVE_CONF_DATA_BITS

#define FSI_PEEK_BASE

static const int engine_page_size =;

#define FSI_SLAVE_BASE

/*
 * FSI slave engine control register offsets
 */
#define FSI_SMODE
#define FSI_SISC
#define FSI_SSTAT
#define FSI_SLBUS
#define FSI_LLMODE

/*
 * SMODE fields
 */
#define FSI_SMODE_WSC
#define FSI_SMODE_ECRC
#define FSI_SMODE_SID_SHIFT
#define FSI_SMODE_SID_MASK
#define FSI_SMODE_ED_SHIFT
#define FSI_SMODE_ED_MASK
#define FSI_SMODE_SD_SHIFT
#define FSI_SMODE_SD_MASK
#define FSI_SMODE_LBCRR_SHIFT
#define FSI_SMODE_LBCRR_MASK

/*
 * SLBUS fields
 */
#define FSI_SLBUS_FORCE

/*
 * LLMODE fields
 */
#define FSI_LLMODE_ASYNC

#define FSI_SLAVE_SIZE_23b

static DEFINE_IDA(master_ida);

static const int slave_retries =;
static int discard_errors;

static dev_t fsi_base_dev;
static DEFINE_IDA(fsi_minor_ida);
#define FSI_CHAR_MAX_DEVICES

/* Legacy /dev numbering: 4 devices per chip, 16 chips */
#define FSI_CHAR_LEGACY_TOP

static int fsi_master_read(struct fsi_master *master, int link,
		uint8_t slave_id, uint32_t addr, void *val, size_t size);
static int fsi_master_write(struct fsi_master *master, int link,
		uint8_t slave_id, uint32_t addr, const void *val, size_t size);
static int fsi_master_break(struct fsi_master *master, int link);

/*
 * fsi_device_read() / fsi_device_write() / fsi_device_peek()
 *
 * FSI endpoint-device support
 *
 * Read / write / peek accessors for a client
 *
 * Parameters:
 * dev:  Structure passed to FSI client device drivers on probe().
 * addr: FSI address of given device.  Client should pass in its base address
 *       plus desired offset to access its register space.
 * val:  For read/peek this is the value read at the specified address. For
 *       write this is value to write to the specified address.
 *       The data in val must be FSI bus endian (big endian).
 * size: Size in bytes of the operation.  Sizes supported are 1, 2 and 4 bytes.
 *       Addresses must be aligned on size boundaries or an error will result.
 */
int fsi_device_read(struct fsi_device *dev, uint32_t addr, void *val,
		size_t size)
{}
EXPORT_SYMBOL_GPL();

int fsi_device_write(struct fsi_device *dev, uint32_t addr, const void *val,
		size_t size)
{}
EXPORT_SYMBOL_GPL();

int fsi_device_peek(struct fsi_device *dev, void *val)
{}

static void fsi_device_release(struct device *_device)
{}

static struct fsi_device *fsi_create_device(struct fsi_slave *slave)
{}

/* FSI slave support */
static int fsi_slave_calc_addr(struct fsi_slave *slave, uint32_t *addrp,
		uint8_t *idp)
{}

static int fsi_slave_report_and_clear_errors(struct fsi_slave *slave)
{}

/* Encode slave local bus echo delay */
static inline uint32_t fsi_smode_echodly(int x)
{}

/* Encode slave local bus send delay */
static inline uint32_t fsi_smode_senddly(int x)
{}

/* Encode slave local bus clock rate ratio */
static inline uint32_t fsi_smode_lbcrr(int x)
{}

/* Encode slave ID */
static inline uint32_t fsi_smode_sid(int x)
{}

static uint32_t fsi_slave_smode(int id, u8 t_senddly, u8 t_echodly)
{}

static int fsi_slave_set_smode(struct fsi_slave *slave)
{}

static int fsi_slave_handle_error(struct fsi_slave *slave, bool write,
				  uint32_t addr, size_t size)
{}

int fsi_slave_read(struct fsi_slave *slave, uint32_t addr,
			void *val, size_t size)
{}
EXPORT_SYMBOL_GPL();

int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
			const void *val, size_t size)
{}
EXPORT_SYMBOL_GPL();

int fsi_slave_claim_range(struct fsi_slave *slave,
			  uint32_t addr, uint32_t size)
{}
EXPORT_SYMBOL_GPL();

void fsi_slave_release_range(struct fsi_slave *slave,
			     uint32_t addr, uint32_t size)
{}
EXPORT_SYMBOL_GPL();

static bool fsi_device_node_matches(struct device *dev, struct device_node *np,
		uint32_t addr, uint32_t size)
{}

/* Find a matching node for the slave engine at @address, using @size bytes
 * of space. Returns NULL if not found, or a matching node with refcount
 * already incremented.
 */
static struct device_node *fsi_device_find_of_node(struct fsi_device *dev)
{}

static int fsi_slave_scan(struct fsi_slave *slave)
{}

static unsigned long aligned_access_size(size_t offset, size_t count)
{}

static ssize_t fsi_slave_sysfs_raw_read(struct file *file,
		struct kobject *kobj, struct bin_attribute *attr, char *buf,
		loff_t off, size_t count)
{}

static ssize_t fsi_slave_sysfs_raw_write(struct file *file,
		struct kobject *kobj, struct bin_attribute *attr,
		char *buf, loff_t off, size_t count)
{}

static const struct bin_attribute fsi_slave_raw_attr =;

static void fsi_slave_release(struct device *dev)
{}

static bool fsi_slave_node_matches(struct device_node *np,
		int link, uint8_t id)
{}

/* Find a matching node for the slave at (link, id). Returns NULL if none
 * found, or a matching node with refcount already incremented.
 */
static struct device_node *fsi_slave_find_of_node(struct fsi_master *master,
		int link, uint8_t id)
{}

static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count,
			 loff_t *offset)
{}

static ssize_t cfam_write(struct file *filep, const char __user *buf,
			  size_t count, loff_t *offset)
{}

static loff_t cfam_llseek(struct file *file, loff_t offset, int whence)
{}

static int cfam_open(struct inode *inode, struct file *file)
{}

static const struct file_operations cfam_fops =;

static ssize_t send_term_store(struct device *dev,
			       struct device_attribute *attr,
			       const char *buf, size_t count)
{}

static DEVICE_ATTR_WO(send_term);

static ssize_t slave_send_echo_show(struct device *dev,
				    struct device_attribute *attr,
				    char *buf)
{}

static ssize_t slave_send_echo_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(send_echo_delays, 0600,
		   slave_send_echo_show, slave_send_echo_store);

static ssize_t chip_id_show(struct device *dev,
			    struct device_attribute *attr,
			    char *buf)
{}

static DEVICE_ATTR_RO(chip_id);

static ssize_t cfam_id_show(struct device *dev,
			    struct device_attribute *attr,
			    char *buf)
{}

static DEVICE_ATTR_RO(cfam_id);

static struct attribute *cfam_attr[] =;

static const struct attribute_group cfam_attr_group =;

static const struct attribute_group *cfam_attr_groups[] =;

static char *cfam_devnode(const struct device *dev, umode_t *mode,
			  kuid_t *uid, kgid_t *gid)
{}

static const struct device_type cfam_type =;

static char *fsi_cdev_devnode(const struct device *dev, umode_t *mode,
			      kuid_t *uid, kgid_t *gid)
{}

const struct device_type fsi_cdev_type =;
EXPORT_SYMBOL_GPL();

/* Backward compatible /dev/ numbering in "old style" mode */
static int fsi_adjust_index(int index)
{}

static int __fsi_get_new_minor(struct fsi_slave *slave, enum fsi_dev_type type,
			       dev_t *out_dev, int *out_index)
{}

static const char *const fsi_dev_type_names[] =;

int fsi_get_new_minor(struct fsi_device *fdev, enum fsi_dev_type type,
		      dev_t *out_dev, int *out_index)
{}
EXPORT_SYMBOL_GPL();

void fsi_free_minor(dev_t dev)
{}
EXPORT_SYMBOL_GPL();

static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
{}

/* FSI master support */
static int fsi_check_access(uint32_t addr, size_t size)
{}

static int fsi_master_read(struct fsi_master *master, int link,
		uint8_t slave_id, uint32_t addr, void *val, size_t size)
{}

static int fsi_master_write(struct fsi_master *master, int link,
		uint8_t slave_id, uint32_t addr, const void *val, size_t size)
{}

static int fsi_master_link_disable(struct fsi_master *master, int link)
{}

static int fsi_master_link_enable(struct fsi_master *master, int link)
{}

/*
 * Issue a break command on this link
 */
static int fsi_master_break(struct fsi_master *master, int link)
{}

static int fsi_master_scan(struct fsi_master *master)
{}

static int fsi_slave_remove_device(struct device *dev, void *arg)
{}

static int fsi_master_remove_slave(struct device *dev, void *arg)
{}

static void fsi_master_unscan(struct fsi_master *master)
{}

int fsi_master_rescan(struct fsi_master *master)
{}
EXPORT_SYMBOL_GPL();

static ssize_t master_rescan_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(rescan, 0200, NULL, master_rescan_store);

static ssize_t master_break_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{}

static DEVICE_ATTR(break, 0200, NULL, master_break_store);

static struct attribute *master_attrs[] =;

ATTRIBUTE_GROUPS();

static struct class fsi_master_class =;

int fsi_master_register(struct fsi_master *master)
{}
EXPORT_SYMBOL_GPL();

void fsi_master_unregister(struct fsi_master *master)
{}
EXPORT_SYMBOL_GPL();

/* FSI core & Linux bus type definitions */

static int fsi_bus_match(struct device *dev, const struct device_driver *drv)
{}

int fsi_driver_register(struct fsi_driver *fsi_drv)
{}
EXPORT_SYMBOL_GPL();

void fsi_driver_unregister(struct fsi_driver *fsi_drv)
{}
EXPORT_SYMBOL_GPL();

struct bus_type fsi_bus_type =;
EXPORT_SYMBOL_GPL();

static int __init fsi_init(void)
{}
postcore_initcall(fsi_init);

static void fsi_exit(void)
{}
module_exit(fsi_exit);
module_param(discard_errors, int, 0664);
MODULE_LICENSE();
MODULE_PARM_DESC();