[PATCH linux v5 2/7] drivers/fsi: Add FSI Master Functionality and Initialization
Christopher Bostic
christopher.lee.bostic at gmail.com
Thu Sep 22 04:38:13 AEST 2016
On Wed, Sep 7, 2016 at 7:09 PM, Joel Stanley <joel at jms.id.au> wrote:
> On Thu, Aug 25, 2016 at 5:24 AM, <christopher.lee.bostic at gmail.com> wrote:
>> From: Chris Bostic <cbostic at us.ibm.com>
>>
>> Define the FSI master control register set and its accessors.
>> Initialize the primary FSI master.
>>
>> Signed-off-by: Chris Bostic <cbostic at us.ibm.com>
>> ---
>
> I recall reading this patch in the past. No changelog?
Had the changes specific to this patch in 0001, will move those to 0002.
>
>> drivers/fsi/Makefile | 2 +-
>> drivers/fsi/fsi.h | 32 +++
>> drivers/fsi/fsi_private.h | 97 +++++++
>> drivers/fsi/fsicfam.h | 46 ++++
>> drivers/fsi/fsiinit.c | 22 ++
>> drivers/fsi/fsiinit.h | 2 +
>> drivers/fsi/fsimaster.c | 242 +++++++++++++++++
>> drivers/fsi/fsimaster.h | 655 ++++++++++++++++++++++++++++++++++++++++++++++
>> 8 files changed, 1097 insertions(+), 1 deletion(-)
>> create mode 100644 drivers/fsi/fsi.h
>> create mode 100644 drivers/fsi/fsi_private.h
>> create mode 100644 drivers/fsi/fsicfam.h
>> create mode 100644 drivers/fsi/fsimaster.c
>> create mode 100644 drivers/fsi/fsimaster.h
>>
>> diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
>> index f547c08..9800c15 100644
>> --- a/drivers/fsi/Makefile
>> +++ b/drivers/fsi/Ma
>> + * Determine the link address to send the break command to
>> + * This is master dependent
>> + */
>> +static inline int fsi_mtype_2break_id(u8 mtype)
>> +{
>> + return FSI_MAX_CASCADE - 1;
>> +}
>> +
>> +/*
>> + * Build a mask where bit index 'x' is set (numbering from left to right.
>> + * Bit 0 is MSB and bit 31 is LSM.
>> + */
>> +static inline unsigned long mask32(int x)
>> +{
>> + return 1 << (BITS_PER_LONG - x - 1);
>
> Is this masking in IBM bit ordering?
>
> We should pull the macros (or at least copy them) from arch/powerpc so
> we can use them here.
Will do, should be easy
>
>> +}
>> +
>> +/*
>> + * Various function prototypes
>> + */
>> +int slv_install(void);
>> +void slv_uninstall(void);
>> +
>> +void fsi_exit_fileio(dev_t);
>> +
>> +int fsibus_init(void);
>> +void fsibus_exit(void);
>> +
>> +#endif /* DRIVERS_FSI_PRIVATE_H */
>> diff --git a/drivers/fsi/fsicfam.h b/drivers/fsi/fsicfam.h
>> new file mode 100644
>> index 0000000..dde7036
>> --- /dev/null
>> +++ b/drivers/fsi/fsicfam.h
>> @@ -0,0 +1,46 @@
>> +/*
>> + * FSI CFAM structure definitions and defines
>> + *
>> + * Copyright 2016 IBM Corp.
>> + *
>> + * Christopher Bostic <cbostic at us.ibm.com>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version
>> + * 2 of the License, or (at your option) any later version.
>> + */
>> +#ifndef DRIVERS_FSICFAM_H
>> +#define DRIVERS_FSICFAM_H
>> +
>> +#include "fsi.h"
>> +#include "fsi_private.h"
>> +
>> +#define FSI_MAX_ENGINES 32 /* Max # of engines per CFAM */
>> +
>> +struct fsicfam { /* CFAM internal structure */
>> + struct fsidevice *engines[FSI_MAX_ENGINES]; /* CFAM engine data */
>> + u32 cfgtab[FSI_MAX_ENGINES]; /* Configuration word */
>> + u16 chipid; /* CFAM chip type (IOU, CFAM-S, etc) */
>> + u8 id; /* CFAM Id */
>> + bool has_submaster; /* CFAM with cascaded or hub masters */
>> + bool has_mux; /* CFAM with multiplexer */
>> + u8 ec_maj; /* Major EC Level */
>> + u8 ec_min; /* Minor EC Level or version number */
>> + u16 pages; /* # Mapped pages */
>> + u8 no_eng; /* Number of engines[] */
>> + struct fsidevice fsidev; /* LDM entry */
>> + struct fsidevice hpdone; /* Dummy engine to signal completion */
>> + unsigned long eng_build; /* True during engine activate */
>> + struct fsimaster *master; /* pointer to parent master */
>> +};
>> +
>> +#define to_fsicfam(x) container_of((x), struct fsicfam, fsidev)
>
> Make this a function.
Will change.
>
>> +
>> +/*
>> + * CFAM specific function prototypes.
>> + */
>> +int fsi_cfamirq_request(int, struct fsicfam *);
>> +void fsi_cfamirq_free(struct fsicfam *);
>> +
>> +#endif /* DRIVERS_FSICFAM_H */
>> diff --git a/drivers/fsi/fsiinit.c b/drivers/fsi/fsiinit.c
>> index 767c0c3..c589294 100644
>> --- a/drivers/fsi/fsiinit.c
>> +++ b/drivers/fsi/fsiinit.c
>> @@ -13,7 +13,9 @@
>>
>> #include <linux/init.h>
>> #include <linux/module.h>
>> +#include <linux/kdev_t.h>
>> #include "fsiinit.h"
>> +#include "fsimaster.h"
>>
>> MODULE_AUTHOR("Christopher Bostic cbostic at us.ibm.com");
>> MODULE_DESCRIPTION("FSI master device driver");
>> @@ -26,6 +28,7 @@ MODULE_DESCRIPTION("FSI master device driver");
>> struct fsidd fsidd = { /* FSI device driver structure definition */
>> .magic = FSI_DD_MAGIC,
>> .strno = FSI_DD_STRNO,
>> + .major = MKDEV(FSIDD_MAJOR, 0),
>> };
>>
>> static int fsi_start(void)
>> @@ -33,6 +36,25 @@ static int fsi_start(void)
>> int rc = 0;
>>
>> dev_dbg(&fsidd.dev, "FSI DD v:%d installation ok\n", FSIDD_VERNO);
>> +
>> + init_waitqueue_head(&fsidd.error_wq);
>> + init_waitqueue_head(&fsidd.lbus_wq);
>> + init_waitqueue_head(&fsidd.irq_wq);
>> + init_waitqueue_head(&fsidd.link_wq);
>> +
>> + /*
>> + * Initialize the the master
>> + */
>> + if (!fsimaster_build_init(&fsidd.pri_master, FSI_PRIM, 0)) {
>> + rc = PTR_ERR(0);
>
> ???
>
>> + goto err;
>> + }
>> + fsimaster_start(&fsidd.pri_master);
>> + dev_dbg(&fsidd.dev, "FSI DD v%d installation ok\n", FSIDD_VERNO);
>> + return rc;
>> +
>> +err:
>> + dev_dbg(&fsidd.dev, "FSI DD v:%d installation failed\n", FSIDD_VERNO);
>> return rc;
>
> Your formatting is broken.
How is it broken? Not sure what '???' means.
>
>> }
>>
>> diff --git a/drivers/fsi/fsiinit.h b/drivers/fsi/fsiinit.h
>> index 93662533..10ddfc0 100644
>> --- a/drivers/fsi/fsiinit.h
>> +++ b/drivers/fsi/fsiinit.h
>> @@ -19,6 +19,7 @@
>> #include <linux/device.h>
>> #include <linux/workqueue.h>
>> #include <linux/hrtimer.h>
>> +#include "fsimaster.h"
>>
>> #define FSI_DD_MAGIC 0x64644632 /* ddF2 */
>> #define FSI_DD_STRNO 0x1 /* Structure version number */
>> @@ -34,6 +35,7 @@ struct fsidd { /* FSI Main structure */
>> wait_queue_head_t link_wq; /* Wait queue for link changes */
>> unsigned long state; /* State driver is in */
>> struct device dev; /* Anchor point in /sys/kernel */
>> + struct fsimaster pri_master; /* Primary FSI master */
>> };
>>
>> #define to_fsidd_prim(a) container_of(a, struct fsidd, pri_master)
>> diff --git a/drivers/fsi/fsimaster.c b/drivers/fsi/fsimaster.c
>> new file mode 100644
>> index 0000000..b5d16db
>> --- /dev/null
>> +++ b/drivers/fsi/fsimaster.c
>> @@ -0,0 +1,242 @@
>> +/*
>> + * FSI Master Control
>> + *
>> + * Copyright 2016 IBM Corp.
>> + *
>> + * Christopher Bostic <cbostic at us.ibm.com>
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * as published by the Free Software Foundation; either version
>> + * 2 of the License, or (at your option) any later version.
>> + */
>> +
>> +#include <linux/err.h>
>> +#include <linux/delay.h>
>> +#include <linux/ktime.h>
>> +#include <linux/io.h>
>> +#include "fsi.h"
>> +#include "fsiinit.h"
>> +#include "fsimaster.h"
>> +#include "fsicfam.h"
>> +
>> +static int hpinfo_alloc(struct fsimaster *master)
>> +{
>> + return 0;
>> +}
>> +
>> +static inline unsigned int fsimid(struct fsimaster *master)
>> +{
>> + return master->myid;
>> +}
>> +
>> +static void primaster_exit(struct fsimaster *master)
>> +{
>> + if (master->dcr_alloc) {
>> + master->base = NULL;
>> + master->dcr_alloc = false;
>> + }
>> +}
>> +
>> +/*
>> + * Read/write functions to access primary FSI master registers
>> + * Note that this master is virtual as we don't yet have any
>> + * real FSI masters implemented in hardware
>
> "virtual"? What's the purpose of this code?
For implementations without a real hardware FSI master such as soft
FSI there is a 'virtual' master in memory where registers are just u32
variables in a data structure. Will add comments to make this clear.
>
>> + */
>> +static u32 virt_master_readreg(struct fsi_mreg *mbase, int regnm)
>> +{
>> + u32 *base = (u32 *)mbase;
>> +
>> + return *(base + regnm);
>> +}
>> +
>> +static void virt_master_readreg2(struct fsi_mreg *mbase, int regnm, u64 *dest)
>> +{
>> + u32 *base = (u32 *)mbase;
>> +
>> + memcpy(dest, base + regnm, sizeof(u64));
>> +}
>> +
>> +static void virt_master_readreg4(struct fsi_mreg *mbase, int regnm, u32 *dest)
>> +{
>> + u32 *base = (u32 *)mbase;
>> +
>> + memcpy(dest, base + regnm, 4 * sizeof(u32));
>> +}
>>
More information about the openbmc
mailing list