[PATCH linux 4/4] drivers/fsi: Add FSI link buildup function

Joel Stanley joel at jms.id.au
Mon Aug 1 17:58:57 AEST 2016


On Fri, Jul 29, 2016 at 3:44 AM,  <christopher.lee.bostic at gmail.com> wrote:
> From: Chris Bostic <cbostic at us.ibm.com>
>
> Start the link buildup.  This begins the process of creating data structures
> that represent the physical connections on FSI links - part of scan process.

I had a brief read of this one and have made some comments below. a
1000 line diff is still quite long. Comments below.

Checkpatch:

 total: 11 errors, 14 warnings, 1188 lines checked

>
> Signed-off-by: Chris Bostic <cbostic at us.ibm.com>
> ---
>  drivers/fsi/Makefile     |   2 +-
>  drivers/fsi/build.c      | 124 +++++++++++++++
>  drivers/fsi/fsi.h        |  28 ++++
>  drivers/fsi/fsidefines.h |  43 +++--
>  drivers/fsi/fsiinit.c    |  34 ++++
>  drivers/fsi/fsiinit.h    |  12 ++
>  drivers/fsi/fsilink.h    | 102 ++++++++++++
>  drivers/fsi/fsimaster.c  | 223 +++++++++++++++++++++++++-
>  drivers/fsi/fsimaster.h  |   8 +-
>  drivers/fsi/fsislave.h   | 403 +++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/fsi/ldm.c        |  28 ++++
>  drivers/fsi/readwrite.c  |  48 ++++++
>  12 files changed, 1037 insertions(+), 18 deletions(-)
>  create mode 100644 drivers/fsi/build.c
>  create mode 100644 drivers/fsi/fsilink.h
>  create mode 100644 drivers/fsi/fsislave.h
>  create mode 100644 drivers/fsi/ldm.c
>  create mode 100644 drivers/fsi/readwrite.c
>
> diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
> index 9800c15..2445cee 100644
> --- a/drivers/fsi/Makefile
> +++ b/drivers/fsi/Makefile
> @@ -2,4 +2,4 @@
>  # Makefile for the FSI bus specific drivers.
>  #
>
> -obj-y          += fsiinit.o fsimaster.o
> +obj-y          += fsiinit.o fsimaster.o build.o readwrite.o ldm.o
> diff --git a/drivers/fsi/build.c b/drivers/fsi/build.c
> new file mode 100644
> index 0000000..0045222
> --- /dev/null
> +++ b/drivers/fsi/build.c
> @@ -0,0 +1,124 @@
> +/*
> + * FSI Link Build up
> + *
> + * 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 <asm/io.h>
> +#include "fsi.h"
> +#include "fsidefines.h"
> +#include "fsimaster.h"
> +#include "fsicfam.h"
> +#include "fsilink.h"
> +
> +static void link_release(struct device *devp)
> +{
> +}
> +
> +/*
> + * Allocate an FSI link structure and initialize it
> + */
> +static struct fsilink *link_alloc(void)
> +{
> +       struct fsilink *link = fsi_calloc(sizeof * link, GFP_KERNEL);

This function is unnecessary. Perform the allocation in the calling function.

We normally put brackets around a sizeof.

> +
> +       return link;
> +}
> +
> +/*
> + * Create a FSI link struct and assign it to the FSI tree
> + */
> +static struct fsilink *link_add(struct fsimaster *p, int no)
> +{
> +       int rc = -ENOMEM;
> +       struct fsilink *lp;
> +       int id = 0;
> +
> +       id = fsi_mtype_2break_id(p->type);
> +
> +       if (!(lp = link_alloc()))
> +               goto bad;

lp = fsi_calloc(sizeof(*link), GFP_KERNEL);
if (!lp)
   return -ENOMEM

> +
> +       dev_set_name(&lp->fsidev.dev, "link-%d", no);
> +       lp->id3_addr = fsim_cfam2pa(p, no, id);
> +       lp->master = p;
> +       lp->linkno = no;
> +       lp->fsidev.map.paddr = fsim_cfam2pa(p, no, 0);
> +       lp->fsidev.map.addr = lp->id3_addr;
> +       lp->fsidev.map.cmtype = p->type;
> +       lp->fsidev.id.engine_type = FSI_ENGID_LINK;
> +       lp->fsidev.map.kb = fsim_linksz(p) / FSI_ENGINE_SIZE;
> +       lp->fsidev.irq_start = FSI_IRQ_OFFSET + no
> +                               * (FSI_MAX_CASCADE * FSI_MAX_ENGINES);
> +       lp->fsidev.irq_range = FSI_MAX_CASCADE * FSI_MAX_ENGINES;
> +       if (!p->fsidev)
> +               lp->fsidev.dev.parent = 0;
> +       else
> +               lp->fsidev.dev.parent = &p->fsidev->dev;
> +       lp->fsidev.dev.release = link_release;
> +
> +       /* stub */
> +bad:
> +       return lp ? : ERR_PTR(rc);
> +}
> +
> +static void linkbuild2(struct fsimaster *p, struct fsilink *lp)
> +{
> +}
> +
> +/*
> + * Return number of CFAMs discovered. If something fails during the build up
> + * process return error reason
> + */
> +static int linkbuild1(struct fsimaster *p, int no)

Perhaps fsi_linkbuild_first?

> +{
> +       int i, rc = 0;
> +       struct fsilink *lp = link_add(p, no);
> +
> +       if (IS_ERR(lp))
> +               return PTR_ERR(lp);
> +
> +       /* stub */
> +
> +       linkbuild2(p, lp);
> +       if ((i = lp->cascade) == 0) {
> +
> +               /* stub */
> +
> +               rc = -EIO;
> +       } else {
> +
> +               /* stub */
> +       }
> +
> +       return rc;
> +}
> +
> +/*
> + * Build up a link.  Returns number of CFAMs discovered.
> + */
> +int fsi_linkbuild(struct fsimaster *p, int no)
> +{
> +       int rc;
> +       u32 menp[2];
> +
> +       if ((rc = fsim_r_menp(p, menp)))

I've got no idea what r_menp is. m normally means master, en is en,
and p is pointer? Perhaps make this names a bit more descriptive

> +               goto bad;

rc = fsim....
if (rc)
   goto bad;

Same for the others below.

> +       if ((menp[no / BITS_PER_LONG] & mask32(no % BITS_PER_LONG))) {

Ahh, mask32 is doing IBM bit ordering. We have macros for this but
they live in arch/powerpc.

> +               return -EEXIST;  /* Already running */
> +       }
> +       if ((rc = fsim_enable_link(p, no)))
> +               goto bad;
> +       if ((rc = linkbuild1(p, no)) < 0)
> +               fsim_disable_link(p, no);
> +bad:
> +       return rc;
> +}
> diff --git a/drivers/fsi/fsi.h b/drivers/fsi/fsi.h
> index e17a419..26420da 100644
> --- a/drivers/fsi/fsi.h
> +++ b/drivers/fsi/fsi.h
> @@ -15,10 +15,38 @@
>
>  #include <linux/device.h>
>
> +/*
> + * Engine ID's
> + */
> +#define FSI_ENGID_LINK         0xff    /* Link Identifier */
> +
> +/* Engine ID as it appears in the CFAM configuration table */
> +struct fsi_engine_id {
> +       unsigned char match_flags;
> +       unsigned char engine_type;
> +       unsigned char engine_version;
> +       unsigned char engine_vendor;

u8?

> +};
> +
> +struct fsi_iaddr {
> +       u32 addr;                       /* Virtual address */
> +       u32 paddr;                      /* Physical address */
> +       unsigned char cmtype;           /* Master type */
> +       unsigned char eng;              /* Engine # on CFAM */
> +       unsigned short kb;              /* # kb device uses */
> +       unsigned short kb_off;          /* offset from beginning of CFAM */

u8?

> +};
> +
>  struct fsidevice {
> +       struct fsi_iaddr map;           /* Address info */
> +       struct fsi_engine_id id;        /* Engine type/version */
>         unsigned long irq_start;        /* IRQ Number */
> +       unsigned short irq_range;       /* Number of IRQs */
>         struct fsidevice *parent;       /* Parent of this device */
>         struct device dev;              /* LDM entry for bus */
>  };
>
> +int fsidev_register(struct fsidevice *, struct device_attribute **);
> +int fsidev_register_nolock(struct fsidevice *, struct device_attribute **);
> +
>  #endif /* DRIVERS_FSI_H */
> diff --git a/drivers/fsi/fsidefines.h b/drivers/fsi/fsidefines.h
> index bf72ec438..da6c268 100644
> --- a/drivers/fsi/fsidefines.h
> +++ b/drivers/fsi/fsidefines.h
> @@ -50,14 +50,22 @@
>  #define        FSI_PA16_SHIFT          16              /* For 16 bit pa conversions */
>
>  /* FSI Events */
> -#define FSI_EVT_PLUG           5               /* Link hot plug add detected */
> -#define FSIDD_BUILD            9               /* In build up phase */
> -#define FSIDD_PROBE            10              /* In probe phase */

We should add these once and not re-write the code in later patches.

> +#define FSI_EVT_LBUSLOST       1               /* Local bus loss detected */
> +#define FSI_EVT_LBUSRECV       2               /* Local bus gain detected */
> +#define FSI_EVT_IRQLOOP                3               /* IRQ loop detected */
> +#define FSI_EVT_LINKCHG                4               /* Link state change */
> +#define FSI_EVT_UNPLUG         5               /* Hot plug IRQ unplug */
> +#define FSI_EVT_PLUG           6               /* Hot plug IRQ plug */
> +#define FSI_EVT_CFAMADD                7               /* CFAM buildup via sysfs */
> +#define FSI_EVT_CFAMDELETE     8               /* CFAM removal via sysfs */
> +#define FSI_EVT_CFAMDEAD       9               /* CFAM init failed */
> +#define FSIDD_BUILD            10              /* In build up phase */
> +#define FSIDD_PROBE            11              /* In probe phase */
>
>  /*
>   * Return FSI physical address without type information (last 2 bits)
>   */
> -static inline phys_addr_t fsi_panot(phys_addr_t pa)
> +static inline u32 fsi_panot(u32 pa)

As above; correct in the patch where you add the code instead of
modifying it later in the series. Same for the rest of the
modificaitons ot this file.
>  {
>         return pa & ~FSI_MBIT_MASK;
>  }
> @@ -65,7 +73,7 @@ static inline phys_addr_t fsi_panot(phys_addr_t pa)
>  /*
>   * Return type of FSI master this physical address belongs to
>   */
> -static inline int fsi_pa2mtype(phys_addr_t pa)
> +static inline int fsi_pa2mtype(u32 pa)
>  {
>         return pa & FSI_MBIT_MASK;
>  }
> @@ -73,7 +81,7 @@ static inline int fsi_pa2mtype(phys_addr_t pa)
>  /*
>   * Add type of FSI master to physical address
>   */
> -static inline phys_addr_t fsi_mtype2pa(phys_addr_t pa, unsigned char type)
> +static inline u32 fsi_mtype2pa(u32 pa, unsigned char type)
>  {
>         return fsi_panot(pa) | (type & FSI_MBIT_MASK);
>  }
> @@ -81,15 +89,15 @@ static inline phys_addr_t fsi_mtype2pa(phys_addr_t pa, unsigned char type)
>  /*
>   * Extract link number from physical address
>   */
> -static inline int fsi_pa2link(phys_addr_t addr)
> +static inline int fsi_pa2link(u32 pa)
>  {
> -       return (addr >> FSI_LINK_SHIFT) & (FSI_LINK_MASK >> FSI_LINK_SHIFT);
> +       return (pa >> FSI_LINK_SHIFT) & (FSI_LINK_MASK >> FSI_LINK_SHIFT);
>  }
>
>  /*
>   * Extract cfam number from physical address
>   */
> -static inline int fsi_pa2cfam(phys_addr_t addr)
> +static inline int fsi_pa2cfam(u32 pa)
>  {
>          /* Stub */
>         return 0;
> @@ -127,4 +135,21 @@ void fsi_exit_fileio(dev_t);
>  int fsibus_init(void);
>  void fsibus_exit(void);
>
> +/*
> + * I/O access and wrappers
> + */
> +int fsi_readw_int2(u32, u32 *);
> +int fsi_writew_int2(u32, u32);
> +int fsi_writew_int(u32, u32);
> +int fsi_readw_int(u32, u32 *);
> +int fsi_writew_int(u32, u32);
> +
> +/*
> + * Memory allocation
> + */
> +void fsi_cfree(void *, size_t);
> +void *fsi_calloc(size_t, int);
> +void fsi_showmemstat(void);
> +void fsi_ioused(void);
> +
>  #endif /* DRIVERS_FSIDEFINES_H */
> diff --git a/drivers/fsi/fsiinit.c b/drivers/fsi/fsiinit.c
> index 3330d8b..4b17837 100644
> --- a/drivers/fsi/fsiinit.c
> +++ b/drivers/fsi/fsiinit.c
> @@ -14,8 +14,11 @@
>  #include <linux/init.h>
>  #include <linux/module.h>
>  #include <linux/kdev_t.h>
> +#include <linux/io.h>
> +#include <linux/slab.h>
>  #include "fsiinit.h"
>  #include "fsimaster.h"
> +#include "fsidefines.h"
>
>  MODULE_AUTHOR("Christopher Bostic cbostic at us.ibm.com");
>  MODULE_DESCRIPTION("FSI master device driver");
> @@ -26,6 +29,8 @@ MODULE_DESCRIPTION("FSI master device driver");
>  #define        FSIDD_VER(x)    FSIDD_TOSTR(x)
>
>  struct primaster prim;
> +static unsigned long malloc_cnt, free_cnt;
> +
>  EXPORT_SYMBOL(prim);
>
>  struct fsidd fsidd = {         /* FSI device driver structure definition */
> @@ -34,6 +39,35 @@ struct fsidd fsidd = {               /* FSI device driver structure definition */
>         .major = MKDEV(FSIDD_MAJOR, 0),
>  };
>
> +void *fsi_calloc(size_t size, int flags)
> +{
> +       void *p;
> +
> +       malloc_cnt += size;
> +       p = kzalloc(size, flags);

No. We don't want to do this in our driver.

> +
> +       return p;
> +}
> +EXPORT_SYMBOL(fsi_calloc);

Why are we exporting this?

> +
> +void fsi_cfree(void *p, size_t size)
> +{
> +       free_cnt += size;

Nor this.

> +       kfree(p);
> +}
> +
> +void fsi_showmemstat(void)
> +{
> +}
> +
> +void fsi_ioused(void)
> +{
> +}
> +
> +void fsi_lock_mutex(enum fsi_mutex_fkt fkt)

fkt?

> +{
> +}
> +
>  static int fsi_start(void)
>  {
>         int rc = 0;
> diff --git a/drivers/fsi/fsiinit.h b/drivers/fsi/fsiinit.h
> index 059187f..a63d443 100644
> --- a/drivers/fsi/fsiinit.h
> +++ b/drivers/fsi/fsiinit.h
> @@ -40,4 +40,16 @@ struct fsidd {                               /* FSI Main structure */
>
>  #define to_fsidd_prim(a)       container_of(a, struct fsidd, pri_master)
>
> +enum fsi_mutex_fkt {
> +       LOCK_BUILD = 1,
> +       LOCK_ACTIVATE = 2,
> +       LOCK_DEACTIVATE = 3,
> +       LOCK_MUXCHANGE = 4,
> +       LOCK_FSIUNREG = 5,
> +       LOCK_FSIREG = 6
> +};
> +
> +void fsi_lock_mutex(enum fsi_mutex_fkt);
> +void fsi_unlock_mutex(enum fsi_mutex_fkt);
> +
>  #endif /* DRIVERS_FSIINIT_H */
> diff --git a/drivers/fsi/fsilink.h b/drivers/fsi/fsilink.h
> new file mode 100644
> index 0000000..9c575c7
> --- /dev/null
> +++ b/drivers/fsi/fsilink.h
> @@ -0,0 +1,102 @@
> +/*
> + * FSI link 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_FSILINK_H
> +#define DRIVERS_FSILINK_H
> +
> +#include <linux/types.h>
> +#include <linux/kobject.h>
> +#include <linux/device.h>
> +
> +#include "fsi.h"
> +#include "fsidefines.h"
> +
> +/*
> + * Extended FSI error counting and thresholding. Count the FSI errors with
> + * time they occured.
> + */
> +#define        FSI_MAX_PE      6               /* Max # of FSI port errors */
> +#define        FSI_MAX_ME      11              /* Max # of FSI master errors */
> +#define        FSI_MAX_SE      10              /* Max # of FSI slave V3 errors */
> +#define        FSI_MAX_SEV2    6               /* Max # of FSI slave V2 errors */
> +
> +struct fsi_ecnt {                      /* Structure for counting errors */
> +       unsigned short cnt;             /* Counter */
> +       struct timeval seen_1st;        /* First occurance */
> +       struct timeval seen_last;       /* Last occurance */
> +};
> +
> +struct fsi_eport {                     /* Port error statistics */
> +       unsigned short pec[FSI_MAX_PE]; /* Port errors counter per type */
> +       unsigned short pcrc_cnt;        /* Recovered CRC counter port */
> +};
> +
> +struct fsi_eslv {                      /* Slave error statistics */
> +       unsigned short sec[FSI_MAX_SE]; /* Slave errors counter per type  */
> +       unsigned short scrc_cnt;        /* Recovered CRC counter slave */
> +};
> +
> +struct fsi_emaster {                   /* Master error statistics */
> +       unsigned short mec[FSI_MAX_ME]; /* Master errors counter per type */
> +       unsigned short mcrc_cnt;        /* Recovered CRC counter master */
> +};
> +
> +struct fsi_elink {                     /* Link error statistics */
> +       struct fsi_emaster master;      /* Master errors */
> +       struct fsi_eport port;          /* Port errors */
> +       struct fsi_eslv slv[FSI_MAX_CASCADE];   /* Slave errors */
> +       struct fsi_ecnt breaked;        /* BREAK command sent */
> +};
> +
> +enum fsilink_state {                   /* Bit mask for error states */
> +       fsilink_lost = 1,               /* Link already schedule for removal */
> +       fsilink_up = 2,                 /* Link up & running */
> +       fsilink_going = 3               /* Link removal in progress */
> +};
> +
> +struct fsilink {                       /* Information per link */
> +       unsigned long magic;            /* Magic number */
> +       unsigned long strno;            /* Structure version number */
> +       unsigned char speedset;         /* Link speed set (0 or 1) */
> +       unsigned char cascade;          /* Length of cascade */
> +       unsigned char top_cfam;         /* # CFAM found on initial scan */
> +       unsigned char linkno;           /* Number of this link */
> +       unsigned long state;            /* Bit mask for error states */
> +       struct fsicfam *cfams[FSI_MAX_CASCADE]; /* CFAMs per link */
> +       struct fsidevice fsidev;
> +       u32 id3_addr;                   /* CFAM id3 page */
> +       struct fsimaster *master;       /* Ptr to controlling fsi master */
> +       struct fsi_elink error;         /* Errors on this link */
> +};
> +
> +#define FSILINK_ATTR(_name, _mode, _show, _store)      \
> +struct device_attribute fsilink_attr_##_name = {       \
> +       .attr = {                                       \
> +               .name = __stringify(_name),             \
> +               .mode = _mode,                          \
> +       },                                              \
> +       .show   = _show,                                \
> +       .store  = _store                                \
> +}
> +
> +/*
> + * Pointer conversion from fsidevice member to fsilink.
> + */
> +#define        to_fsilink(x)   container_of((x), struct fsilink, fsidev)
> +
> +unsigned char fsilink_get_top_cfam(struct fsilink *);
> +unsigned char fsilink_get_linkno(struct fsilink *);
> +unsigned long fsilink_get_state(struct fsilink *);
> +struct fsicfam * fsilink_get_cfam(struct fsilink *, int);
> +struct device * fsilink_get_device(struct fsilink *);
> +
> +#endif /* DRIVERS_FSILINK_H */
> diff --git a/drivers/fsi/fsimaster.c b/drivers/fsi/fsimaster.c
> index 0827f0b..59af679 100644
> --- a/drivers/fsi/fsimaster.c
> +++ b/drivers/fsi/fsimaster.c
> @@ -19,6 +19,7 @@
>  #include "fsiinit.h"
>  #include "fsimaster.h"
>  #include "fsicfam.h"
> +#include "fsislave.h"
>
>  extern struct primaster prim;
>
> @@ -37,11 +38,6 @@ static int fsi_nextbit(u32 *new, int words)
>         return -1;
>  }
>
> -u32 fsim_cfam2pa(struct fsimaster *p, int link, int cfam)
> -{
> -       return 0;
> -}
> -
>  static int hpinfo_alloc(struct fsimaster *p)
>  {
>         return 0;
> @@ -186,6 +182,9 @@ static int fsimaster_init(struct fsimaster *p)
>         return rc;
>  }
>
> +/*
> + * Retrieve the first master in the chain
> + */
>  struct fsimaster * fsim_get_top_master(struct fsimaster *p)
>  {
>         struct fsimaster *parent = NULL;
> @@ -199,10 +198,194 @@ struct fsimaster * fsim_get_top_master(struct fsimaster *p)
>  }
>
>  /*
> + * Get the address window of a link/CFAM
> + */
> +unsigned long fsim_cfamsz(struct fsimaster *p)
> +{
> +       return p->cfam_size;
> +}
> +
> +unsigned long fsim_linksz(struct fsimaster *p)
> +{
> +       return FSI_MAX_CASCADE * fsim_cfamsz(p);
> +}
> +
> +/*
> + * Convert link number to a physical address
> + */
> +u32 fsim_link2pa(struct fsimaster *p, int link)
> +{
> +       unsigned long offset;
> +
> +       offset = link * fsim_linksz(p);
> +       return p->membase + offset;
> +}
> +
> +/*
> + * Convert a link and CFAM number to a physical address
> + */
> +u32 fsim_cfam2pa(struct fsimaster *p, int link, int cfam)
> +{
> +       unsigned long offset;
> +
> +       offset = link * fsim_linksz(p) + cfam * fsim_cfamsz(p);
> +       return p->membase + offset;
> +}
> +
> +int fsim_pa2irq(struct fsimaster *p, u32 pa)
> +{
> +       return 0;
> +}
> +
> +int fsi_pa2irq(u32 pa)
> +{
> +       return 0;
> +}
> +
> +/*
> + * FSI master register access utilities

What do they all mean?

> + */
> +int fsim_r_mmode_nl(struct fsimaster *p, u32 *value)
> +{
> +       return (*p->read_f)(p->mp, FSI_N_MMODE, value);
> +}
> +
> +int fsim_r_mmode(struct fsimaster *p, u32 *value)
> +{
> +       return 0;
> +}
> +
> +int fsim_w_mmode(struct fsimaster *p, u32 value)
> +{
> +       return 0;
> +}
> +
> +int fsim_r_menp_nl(struct fsimaster *p, u32 *menp)
> +{
> +       return 0;
> +}
> +
> +int fsim_r_menp(struct fsimaster *p, u32 *menp)
> +{
> +       return 0;
> +}
> +
> +int fsim_w_menp(struct fsimaster *p, u32 *menp, int on_off)
> +{
> +       return 0;
> +}
> +
> +int fsim_disable_link(struct fsimaster *p, int link)
> +{
> +       return 0;
> +}
> +
> +int fsim_enable_link(struct fsimaster *p, int link)
> +{
> +       return 0;
> +}
> +
> +/*
> + * Send out a BREAK command and see if anything responds.  Part of the
> + * FSI device scan process.
> + */
> +static int ping_cfam(struct fsimaster *p, struct hp_info *hp, const int count)
> +{
> +       int i = 0, rc = -EIO;
> +       u32 value, pa;
> +       int id = fsi_mtype_2break_id(p->type);
> +
> +       pa = fsim_cfam2pa(p, hp->linkno, id);
> +
> +       if (fsim_enable_link(p, hp->linkno)) {
> +               goto out;
> +       }
> +       if (fsi_sendbreak(p, pa, hp->linkno)) {
> +               goto out;
> +       }
> +       while (i++ < count) {
> +               if ((rc = fsi_readw_int(pa + FSI_SLAVE0_OFFSET + FSI_SMODE,
> +                                       &value)) == 0) {
> +                       break;
> +               }
> +               udelay(FSI_CFAM_PING_DELAY);
> +       }
> +out:
> +       if (fsim_disable_link(p, hp->linkno) && rc == 0) {
> +               rc = -EIO;
> +       }
> +
> +       return rc;
> +}
> +
> +/*
> + * Probe for CFAMs
> + */
> +static int probe_link(struct fsimaster *p, struct hp_info *hp)
> +{
> +       int rc = 0;
> +       struct fsidd *dd = to_fsidd_prim(fsim_get_top_master(p));
> +
> +       hp->tries++;
> +       rc = ping_cfam(p, hp, FSI_MAX_CASCADE - 1);
> +       if (rc == 0) {
> +               atomic_set(&hp->state, FSI_LINK_INBUILD);
> +               set_bit(FSIDD_BUILD, &dd->state);
> +               set_bit(hp->linkno, p->hotp.building);
> +               clear_bit(hp->linkno, p->hotp.probing);
> +               rc = 1;
> +       } else if (hp->tries > FSI_MAX_PING_ATTEMPTS) {
> +               atomic_set(&hp->state, FSI_LINK_DEAD);
> +               clear_bit(hp->linkno, p->hotp.probing);
> +       }
> +
> +       return rc;
> +}
> +
> +/*
>   * Work queue function to probe for links
>   */
>  static void probe_wq(struct work_struct *nix)
>  {
> +       struct fsimaster *p = to_fsimaster_probe(nix);
> +       struct fsidd *dd = to_fsidd_prim(fsim_get_top_master(p));
> +       int i, cnt = 0;
> +
> +       for (i = 0; i < p->maxlinks; ++i) {
> +               if (test_bit(i, p->hotp.probing)) {
> +                       cnt += probe_link(p, p->hotp.plug[i]);
> +               }
> +       }
> +       if (cnt)
> +               queue_work(dd->hotp_wq, &p->hotp.buildwrk);
> +}
> +
> +/*
> + * Called from worker in process/task context.
> + */
> +static int build(struct fsimaster *p, struct hp_info *hp)
> +{
> +       int rc;
> +
> +       rc = fsi_linkbuild(p, hp->linkno);
> +       atomic_set(&hp->state, rc ? FSI_LINK_RUNNING : FSI_LINK_DEAD);
> +       if( test_and_clear_bit(FSI_LINK_WAITFOR, &hp->state_w))
> +               complete_all(&hp->done);
> +
> +       return rc;
> +}
> +
> +static int remove(struct fsimaster *p, struct hp_info *hp)
> +{
> +       return 0;
> +}
> +
> +/*
> + * Actual link build function.  Called in process context.
> + */
> +static void build_link(struct fsimaster *p, struct hp_info *hp)
> +{
> +       hp->ec = (hp->cmd == FSI_EVT_CFAMADD) ? build(p, hp) : remove(p, hp);
>  }
>
>  /*
> @@ -210,6 +393,36 @@ static void probe_wq(struct work_struct *nix)
>   */
>  static void build_wq(struct work_struct *nix)
>  {
> +       struct fsimaster *p = to_fsimaster_build(nix);
> +       struct fsidd *dd = to_fsidd_prim(fsim_get_top_master(p));
> +       int i;
> +
> +       set_bit(FSIDD_BUILD, &dd->state);
> +again:
> +       fsi_lock_mutex(LOCK_BUILD);
> +       for (i = 0; i < p->maxlinks; ++i) {
> +               if (test_and_clear_bit(i % BITS_PER_LONG,
> +                                       &p->hotp.building[i / BITS_PER_LONG]))
> +                       build_link(p, p->hotp.plug[i]);
> +       }
> +
> +       /* stub */
> +
> +       /*
> +        * Make sure all bits are cleared before leaving.
> +        * This worker runs in process context.  While running, an FSI error
> +        * interrupt can occur and schedule a link for removal.
> +        * If we are past this new bit in our loop above, the link is not
> +        * removed.  iterate on non zero.
> +        */
> +       if (p->hotp.building[0] || p->hotp.building[1])
> +               goto again;
> +
> +       /*
> +        * If the same described above happens here, we are toast again.
> +        * So another periodic check is done on plugmgr()
> +        */
> +       clear_bit(FSIDD_BUILD, &dd->state);
>  }
>
>  static int fsimaster_reset(struct fsimaster *p)
> diff --git a/drivers/fsi/fsimaster.h b/drivers/fsi/fsimaster.h
> index 40f4f4c..5474a72 100644
> --- a/drivers/fsi/fsimaster.h
> +++ b/drivers/fsi/fsimaster.h
> @@ -20,6 +20,7 @@
>  #define FSI_MAX_PING_ATTEMPTS  12
>  #define        FSI_DFLT_PLUG_CHECK     100
>  #define FSI_DFLT_IPOLL_CHECK   800
> +#define FSI_CFAM_PING_DELAY    20      /* in uS */
>
>  /* Link states */
>  #define FSI_LINK_FREE          1       /* Nothing plugged */
> @@ -536,6 +537,7 @@ struct hp_info {                    /* Hot plug information */
>         struct completion done;         /* Link build done */
>         unsigned short tries;           /* # of tries before probing */
>         unsigned char linkno;           /* Link # */
> +       unsigned char cmd;              /* State add/delete */
>         atomic_t state;                 /* State of this entry */
>         int ec;                         /* Error code */
>         unsigned long state_w;          /* Wait state */
> @@ -616,7 +618,7 @@ void fsi_linklost(struct fsimaster *, int);
>  /*
>   * Master commands
>   */
> -int fsi_sendbreak(struct fsimaster *, void *, int, int);
> +int fsi_sendbreak(struct fsimaster *, u32, int);
>  struct fsimaster * fsim_get_top_master(struct fsimaster *);
>  #define FSI_TRACE_ERRORS 1
>
> @@ -662,8 +664,8 @@ unsigned long fsim_cfamsz(struct fsimaster *);
>  /*
>   * Helper utilities for IRQ number calculations.
>   */
> -int fsim_pa2irq(struct fsimaster *, phys_addr_t);
> -int fsi_pa2irq(phys_addr_t);
> +int fsim_pa2irq(struct fsimaster *, u32);
> +int fsi_pa2irq(u32);
>
>  /*
>   * Functions for link reference
> diff --git a/drivers/fsi/fsislave.h b/drivers/fsi/fsislave.h
> new file mode 100644
> index 0000000..d39384b
> --- /dev/null
> +++ b/drivers/fsi/fsislave.h
> @@ -0,0 +1,403 @@
> +/*
> + * FSI slave 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_FSISLAVE_H
> +#define        DRIVERS_FSISLAVE_H
> +
> +/*
> + * Define read address for peek engine refering to side/series/node-id/frame-id
> + */
> +#define FSI_PEEK_IDADDR        0xc
> +
> +#define FSI_SLV_CFAM_OFFSET 0x800
> +
> +/*
> + * Defines for address locations of certain register in FSI Slave. All register
> + * names start with FSI_S for slave register. Some registers have the
> + * same address but different meanings for read and write access.
> + */
> +#define        FSI_SMODE       0x0     /* R/W: Slave mode register */
> +#define        FSI_SDMA        0x4     /* R/W: DMA control register */
> +#define        FSI_SISC        0x8     /* Read: read Interrupt condition register */
> +#define        FSI_SCISC       0x8     /* Write: Clear Interrupt condition register */
> +#define        FSI_SISM        0xC     /* R/W: Interrupt mask register */
> +#define        FSI_SISS        0x10    /* Read: Interrupt status register */
> +#define        FSI_SSISM       0x10    /* Write: Set interrupt mask */
> +#define        FSI_SSTAT       0x14    /* Read: Read slave status register */
> +#define        FSI_SCISM       0x14    /* Write: Clear interrupt mask */
> +#define        FSI_SI1M        0x18    /* R/W: Interrupt 1 mask register */
> +#define        FSI_SI1S        0x1C    /* Read: Read Interrupt 1 status register */
> +#define        FSI_SSI1M       0x1C    /* Write: Set Interrupt 1 mask register */
> +#define        FSI_SIC         0x20    /* Read: Read engine interrupt condition reg */
> +#define        FSI_SCI1M       0x20    /* Write: Clear Interrupt 1 mask register */
> +#define        FSI_SI2M        0x24    /* R/W: Interrupt 2 mask register */
> +#define        FSI_SI2S        0x28    /* Read: Read Interrupt 2 status register */
> +#define        FSI_SSI2M       0x28    /* Write: Set Interrupt 2 mask register */
> +#define        FSI_SCMDT       0x2C    /* Read: Command trace register */
> +#define        FSI_SCI2M       0x2C    /* Write: Clear Interrupt 2 mask register */
> +#define        FSI_SDATAT      0x30    /* Read: Data trace register */
> +#define        FSI_SLBUS       0x30    /* Write: local bus address commands */
> +#define        FSI_SLASTD      0x34    /* Read: Last data send register */
> +#define        FSI_SRES        0x34    /* Write: Reset command register */
> +#define        FSI_SMBL        0x38    /* R/W: Mailbox register left port */
> +#define        FSI_SOML        0x3C    /* Read: Mailbox old data register left port */
> +#define        FSI_SSMBL       0x3C    /* Write: Set Mailbox bits register left port */
> +#define        FSI_SNML        0x40    /* Read: Mailbox new data register left port */
> +#define        FSI_SCMBL       0x40    /* Write: Clear mailbox bits left port */
> +#define FSI_SMBR       0x44    /* R/W: Mailbox register right port */
> +#define FSI_SOMR       0x48    /* Read: Mailbox old data register right port */
> +#define FSI_SSMBR      0x48    /* Write: Set Mailbox bits register right port*/
> +#define FSI_SNMR       0x4c    /* Read: Mailbox new data register right port */
> +#define FSI_SCMBR      0x4c    /* Write: Clear mailbox bits right port */
> +
> +/* Same as above except Word offsets into the FSI slave engine */
> +#define FSI_N_SISC     0x2     /* Read: read Interrupt condition register */
> +#define FSI_N_SSTAT    0x5     /* Read: Slave Status register */
> +#define FSI_N_SCMDT    0xB     /* Read: Command trace register */
> +#define FSI_N_SDATAT   0xC     /* Read: Data trace register */
> +#define FSI_N_SLASTD   0xD     /* Read: Last data send register */
> +
> +/* Next registers are only valid for FSI slave version 3 */
> +#define FSI_SRSIC      0x50    /* Read slave remote slave IRQ condition */
> +#define FSI_SCRSIC     0x50    /* Write: Clear Slave remote slave IRQ cond */
> +#define FSI_SRSIM      0x54    /* R/W: Slave remote slave IRQ mask */
> +#define FSI_SRSIS      0x58    /* Read: Slave remote slave IRQ status */
> +
> +/* Next registers are only valid for FSI slave version 4 */
> +/* cmFSI */
> +#define FSI_ScRSIC0    0x50    /* Read / Write: to clear cmFSI remote */
> +/* slave IRQ condition ports 0-3 */
> +#define FSI_ScRSIC4    0x54    /* Read / Write: to clear cmFSI remote */
> +/* slave IRQ condition ports 4-7 */
> +#define FSI_ScRSIM0    0x58    /* R/W: cmFSI remote slave IRQ mask */
> +/* ports 0-3 */
> +#define FSI_ScRSIM4    0x5C    /* R/W: cmFSI remote slave IRQ mask */
> +/* ports 4-7 */
> +#define FSI_ScRSIS0    0x60    /* Read: cmFSI remote slave IRQ status */
> +/* ports 0-3 */
> +#define FSI_ScRSIS4    0x64    /* Read: cMFSI remote slave IRQ status */
> +/* ports 4-7 */
> +/* hFSI */
> +#define FSI_SRSIC0     0x68    /* Read / Write: to clear hFSI remote */
> +/* slave IRQ condition ports 0-3 */
> +#define FSI_SRSIC4     0x6C    /* Read / Write: to clear hFSI remote */
> +/* slave IRQ condition ports 4-7 */
> +#define FSI_SRSIM0     0x70    /* R/W: hFSI remote slave IRQ mask */
> +/* ports 0-3 */
> +#define FSI_SRSIM4     0x74    /* R/W: hFSI remote slave IRQ mask */
> +/* ports 4-7 */
> +#define FSI_SRSIS0     0x78    /* Read: hFSI remote slave IRQ status */
> +/* ports 0-3 */
> +#define FSI_SRSIS4     0x7C    /* Read: hFSI remote slave IRQ status */
> +/* ports 4-7 */
> +
> +#define FSI_SRSIM_SID3_SHIFT   6
> +
> +/* Slave ID 3 on interrupt level 1 for all sub/hub links */
> +#define SRSIM_ID3_IRPT1_MASK   0x02020202
> +#define SRSIM_MAGIC            SRSIM_ID3_IRPT1_MASK
> +
> +struct fsi_sreg {              /* FSI slave register definition */
> +       u32 smode;              /* 0x0: Mode register */
> +       u32 sdma;               /* 0x4: DMA control register */
> +       u32 sisc;               /* 0x8: Slave interrupt condition register */
> +       u32 sism;               /* 0xc: Slave interrupt mask register */
> +       u32 siss;               /* 0x10: Slave interrupt status register */
> +       u32 sstat;              /* 0x14: Slave status register */
> +       u32 si1m;               /* 0x18: interrupt 1 mask register */
> +       u32 si1s;               /* 0x1c: interrupt 1 status register */
> +       u32 sic;                /* 0x20: engine interrupt condition register */
> +       u32 si2m;               /* 0x24: interrupt 2 mask register */
> +       u32 si2s;               /* 0x28: interrupt 2 status register */
> +       u32 scmdt;              /* 0x2c: read command trace register */
> +       u32 sdatat;             /* 0x30: read data trace register */
> +       u32 slastd;             /* 0x34: read last FSI data register */
> +       u32 smbl;               /* 0x38: mail box to left port register */
> +       u32 soml;               /* 0x3c: old mail left port register */
> +       u32 snml;               /* 0x40: new mail left port register */
> +       u32 smbr;               /* 0x44: mail box to right port register */
> +       u32 somr;               /* 0x48: old mail right port register */
> +       u32 snmr;               /* 0x4c: new mail right port register */
> +       u32 srsic0;             /* 0x50: slave remote slave IRQ cond. 0-3 */
> +       u32 srsic4;             /* 0x54: slave remote slave IRQ cond. 4-7 */
> +       u32 srsim0;             /* 0x58: slave remote slave IRQ mask 0-3 */
> +       u32 srsim4;             /* 0x5C: slave remote slave IRQ mask 4-7 */
> +       u32 srsis0;             /* 0x60: slave remote slave IRQ stat 0-3 */
> +       u32 srsis4;             /* 0x64: slave remote slave IRQ stat 4-7 */
> +};
> +
> +/*
> + * FSI slave mode register
> + */
> +#define        FSI_SMODE_WSC           0x80000000      /* Warm start completed */
> +#define        FSI_SMODE_EAP           0x40000000      /* Enable auxiliary port */
> +#define        FSI_SMODE_ECRC          0x20000000      /* Enable CRC checking by hw */
> +#define        FSI_SMODE_SID_SHIFT     24              /* Slave identifier shift */
> +#define        FSI_SMODE_SID_MASK      3               /* Slave identifier mask */
> +#define        FSI_SMODE_ED_SHIFT      20              /* Echo delay cycles shift */
> +#define        FSI_SMODE_ED_MASK       0xf             /* Echo delay cycles mask */
> +#define        FSI_SMODE_SD_SHIFT      16              /* Send delay cycles shift */
> +#define        FSI_SMODE_SD_MASK       0xf             /* Send delay cycles mask */
> +#define        FSI_SMODE_LBCRR_SHIFT   8               /* Local bus clk rate shift */
> +#define        FSI_SMODE_LBCRR_MASK    0xf             /* Local bus clk rate mask */
> +#define        FSI_SMODE_BDL_SHIFT     4               /* Briefing data left shift */
> +#define        FSI_SMODE_BDL_MASK      0xf             /* Briefing data mask */
> +#define        FSI_SMODE_BDR_SHIFT     0               /* Briefing data right shift */
> +#define        FSI_SMODE_BDR_MASK      0xf             /* Briefing data mask */
> +#define        FSI_SMODE_RSV_MASK      0xe3ff0fff      /* Mask for used bit clr rsvd */
> +
> +/* FSI slave local bus echo delay */
> +static inline u32 fsi_smode_echodly(int x)
> +{
> +       return (x & FSI_SMODE_ED_MASK) << FSI_SMODE_ED_SHIFT;
> +}
> +
> +/* FSI slave local bus send delay */
> +static inline u32 fsi_smode_senddly(int x)
> +{
> +       return (x & FSI_SMODE_SD_MASK) << FSI_SMODE_SD_SHIFT;
> +}
> +
> +/* FSI slave local bus clock rate ratio */
> +static inline int fsi_smode_extlbcrr(u32 x)
> +{
> +       return (x >> FSI_SMODE_LBCRR_SHIFT) & FSI_SMODE_LBCRR_MASK;
> +}
> +
> +/* FSI slave local bus clock rate ratio */
> +static inline u32 fsi_smode_lbcrr(int x)
> +{
> +       return (x & FSI_SMODE_LBCRR_MASK) << FSI_SMODE_LBCRR_SHIFT;
> +}
> +
> +/* FSI slave identifier setting */
> +static inline u32 fsi_smode_sid(int x)
> +{
> +       return (x & FSI_SMODE_SID_MASK) << FSI_SMODE_SID_SHIFT;
> +}
> +
> +/* FSI slave briefing data right port */
> +static inline u32 fsi_smode_bdr(int x)
> +{
> +       return (x & FSI_SMODE_BDR_MASK) << FSI_SMODE_BDR_SHIFT;
> +}
> +
> +static inline int fsi_smode_extbdr(u32 x)
> +{
> +       return (x >> FSI_SMODE_BDR_SHIFT) & FSI_SMODE_BDR_MASK;
> +}
> +
> +/* FSI slave briefing data left port */
> +static inline u32 fsi_smode_bdl(int x)
> +{
> +       return (x & FSI_SMODE_BDL_MASK) << FSI_SMODE_BDL_SHIFT;
> +}
> +
> +static inline int fsi_smode_extbdl(u32 x)
> +{
> +       return (x >> FSI_SMODE_BDL_SHIFT) & FSI_SMODE_BDL_MASK;
> +}
> +
> +/* FSI slave echo delay */
> +static inline u32 fsi_smode_ed(int x)
> +{
> +       return (x & FSI_SMODE_ED_MASK) << FSI_SMODE_ED_SHIFT;
> +}
> +
> +static inline int fsi_smode_exted(u32 x)
> +{
> +       return (x >> FSI_SMODE_ED_SHIFT) & FSI_SMODE_ED_MASK;
> +}
> +
> +/* FSI slave send delay */
> +static inline u32 fsi_smode_sd(int x)
> +{
> +       return (x & FSI_SMODE_SD_MASK) << FSI_SMODE_SD_SHIFT;
> +}
> +
> +static inline int fsi_smode_extsd(u32 x)
> +{
> +       return (x >> FSI_SMODE_SD_SHIFT) & FSI_SMODE_SD_MASK;
> +}
> +
> +/*
> + * FSI slave interrupt register: interrupt conditions, status and mask
> + */
> +#define        FSI_SSI_CRCE            0x80000000      /* FSI CRC error */
> +#define        FSI_SSI_PROTE           0x40000000      /* FSI protocol error */
> +#define        FSI_SSI_LBPE            0x20000000      /* FSI local bus parity error */
> +#define        FSI_SSI_LBPROTE         0x10000000      /* FSI local bus protocol err */
> +#define        FSI_SSI_LBAE            0x08000000      /* FSI local bus access error */
> +#define        FSI_SSI_LBOE            0x04000000      /* FSI local bus owner error */
> +#define        FSI_SSI_LBOC            0x02000000      /* FSI local bus owner change */
> +#define        FSI_SSI_HPE             0x01000000      /* Hot plug event */
> +#define        FSI_SSI_MRL             0x00800000      /* Mail received left port */
> +#define        FSI_SSI_MDL             0x00400000      /* Mail send left port */
> +#define        FSI_SSI_WSL             0x00200000      /* Warm start flag left port */
> +#define        FSI_SSI_LBRL            0x00100000      /* Local bus requ left port */
> +#define        FSI_SSI_MRR             0x00080000      /* Mail received right port */
> +#define        FSI_SSI_MDR             0x00040000      /* Mail delivered right port */
> +#define        FSI_SSI_WSR             0x00020000      /* Warm start flag right port */
> +#define        FSI_SSI_LBRR            0x00010000      /* Local bus req right port */
> +#define        FSI_SSI_CMEL            0x00008000      /* Clocks monitor event left */
> +#define        FSI_SSI_CMER            0x00004000      /* Clocks monitor event right */
> +#define        FSI_SSI_OPB_FNC         0x00001000      /* OPB Fenced (cMFSI & hMFSI) */
> +#define        FSI_SSI_OBP_PA          0x00000800      /* OPB Parity (cMFSI) */
> +#define        FSI_SSI_OBP_PR          0x00000400      /* OPB Protocol (cMFSI) */
> +#define        FSI_SSI_OBP_TO          0x00000200      /* OPB Timeout (cMFSI) */
> +#define        FSI_SSI_OBP_EA          0x00000100      /* OPB ErrorAck (cMFSI) */
> +#define        FSI_SSI_OBP_IA          0x00002000      /* OPB Invalid Address (cMFSI)*/
> +#define        FSI_SSI_CMFSI_AME       0x00000080      /* CMFSI any-master-error */
> +#define        FSI_SSI_CMFSI_APE       0x00000040      /* CMFSI any-port-error */
> +#define        FSI_SSI_CMFSI_HPE       0x00000020      /* CMFSI Hot plug event */
> +#define        FSI_SSI_CMFSI_CRPA      0x00000010      /* CMFSI Contr reg parity err */
> +#define        FSI_SSI_ANY_IRQ         0xffffc000      /* Valid bits */
> +#define        FSI_SSI_ANY_IRQ3        (FSI_SSI_CMFSI_AME | FSI_SSI_CMFSI_APE \
> +                               | FSI_SSI_CMFSI_HPE | FSI_SSI_CMFSI_CRPA)
> +                                               /* Valid bits (cMFSI) */
> +#define        FSI_SSI_ANY_ERROR       0xfc000000      /* Valid error bits */
> +#define        FSI_SSI_ANY_ERROR3      (FSI_SSI_OBP_PA \
> +                               | FSI_SSI_OBP_PR | FSI_SSI_OBP_TO \
> +                               | FSI_SSI_OBP_EA | FSI_SSI_OBP_IA)
> +                                               /* Valid error bits (cMFSI) */
> +#define        FSI_SSI_ERR_MASK        0x3f            /* Any error bits mask */
> +#define        FSI_SSI_ERR_SHFT        26              /* Any error bits shift */
> +#define        FSI_SISC_CRCE           0               /* Slave CRC error bit */
> +#define        FSI_SISC_PE             1               /* Slave protocol error bit */
> +#define        FSI_SISC_LBPE           2               /* Slave lcl bus parity err */
> +#define        FSI_SISC_LBPROTOE       3               /* Slave lcl bus prot err */
> +#define        FSI_SISC_LBAE           4               /* Slave access error bit */
> +#define        FSI_SISC_LBOE           5               /* Slave lcl bus owner err */
> +#define        FSI_SISC_OPBPA          20              /* Slave OPB parity error */
> +#define        FSI_SISC_OPBPR          21              /* Slave OPB protocol error */
> +#define        FSI_SISC_OPBTO          22              /* Slave OPB timeout error */
> +#define        FSI_SISC_OPBEA          23              /* Slave OPB ack error */
> +#define        FSI_SISC_CM_ERRS        0x000000f0      /* CMP8 sourced errors */
> +#define        FSI_SISC_HM_ERRS        0x0000000f      /* HMP8 sourced errors */
> +
> +/* FSI slave error interrupt */
> +static inline int fsi_sisc_iserror(u32 x)
> +{
> +       return x & (FSI_SSI_ANY_ERROR3 | FSI_SSI_ANY_ERROR);
> +}
> +
> +/*
> + * FSI slave interrupt mask register: interrupt conditions, status and mask
> + */
> +#define        FSI_SSI_ENG0            0x80000000      /* FSI slave */
> +#define        FSI_SSI_ENG_MBX         0x400           /* FSI IOU Mailbox */
> +#define        FSI_SSI_ENG_ANY         0x7fffffff      /* FSI engine 1..31 */
> +#define        FSI_SSI_ENG_NOLBUS      (FSI_SSI_ENG0 | FSI_SSI_ENG_MBX)
> +                                               /* Engines without local bus */
> +/*
> + * FSI slave status register SSTAT
> + */
> +#define        FSI_SSTAT_AE            0x80000000      /* Any error bit */
> +#define        FSI_SSTAT_IDD           0x40000000      /* CFAM ID dirty at PON lvl) */
> +#define        FSI_SSTAT_LSW           0x40000000      /* Left side warm start flag */
> +#define        FSI_SSTAT_RSW           0x10000000      /* Rt side warm start flag */
> +#define        FSI_SSTAT_MDL           0x08000000      /* Mail delivered left side */
> +#define        FSI_SSTAT_MDR           0x04000000      /* Mail delivered right side */
> +#define        FSI_SSTAT_MRL           0x02000000      /* Mail received left side */
> +#define        FSI_SSTAT_MRR           0x01000000      /* Mail received right side */
> +#define        FSI_SSTAT_BDL_SHIFT     20              /* Brief data left side shft */
> +#define        FSI_SSTAT_BDL_MASK      0xf             /* Brief data left side mask */
> +#define        FSI_SSTAT_BDR_SHIFT     16              /* Brief data rt side shift */
> +#define        FSI_SSTAT_BDR_MASK      0xf             /* Brief data rt side mask */
> +#define        FSI_SSTAT_LSLBR         0x8000          /* Left side local bus req */
> +#define        FSI_SSTAT_RSLBR         0x4000          /* Right side local bus req */
> +#define        FSI_SSTAT_TSLBR         0x2000          /* This side local bus req */
> +#define        FSI_SSTAT_BLBA          0x1000          /* Block C-side lcl bus acc */
> +#define        FSI_SSTAT_LBO_SHIFT     10              /* Local bus owner shift */
> +#define        FSI_SSTAT_LBO_MASK      3               /* Local bus owner mask */
> +#define        FSI_SSTAT_TSF_SHIFT     8               /* This side A=01 B=10 C=11 */
> +#define        FSI_SSTAT_TSF_MASK      3               /* This side flag mask */
> +#define        FSI_SSTAT_CAL           0x00000080      /* Clocks active left port */
> +#define        FSI_SSTAT_CAR           0x00000040      /* Clocks active right port */
> +#define        FSI_SSTAT_APIL          0x00000020      /* Aux port input level */
> +#define        FSI_SSTAT_APRL          0x00000010      /* Aux port reference level */
> +#define        FSI_SSTAT_CRC_SHIFT     0               /* CRC error counter */
> +#define        FSI_SSTAT_CRC_MASK      0xf             /* CRC mask */
> +#define        FSI_SSTAT_SIDE_NONE     0               /* Unknown Side */
> +#define        FSI_SSTAT_SIDE_A        1               /* A-Side */
> +#define        FSI_SSTAT_SIDE_B        2               /* B-Side */
> +#define        FSI_SSTAT_SIDE_C        3               /* C-Side */
> +
> +/* FSI status local bus request */
> +static inline int fsi_sstat_tsf(u32 x)
> +{
> +       return (x >> FSI_SSTAT_TSF_SHIFT) & FSI_SSTAT_TSF_MASK;
> +}
> +
> +/* FSI status get local bus owner */
> +static inline int fsi_sstat_lbo(u32 x)
> +{
> +       return (x >> FSI_SSTAT_LBO_SHIFT) & FSI_SSTAT_LBO_MASK;
> +}
> +
> +/* FSI status get right side briefing data */
> +static inline int fsi_sstat_bdr(u32 x)
> +{
> +       return (x >> FSI_SSTAT_BDR_SHIFT) & FSI_SSTAT_BDR_MASK;
> +}
> +
> +/* FSI status get left side briefing data */
> +static inline int fsi_sstat_bdl(u32 x)
> +{
> +       return (x >> FSI_SSTAT_BDL_SHIFT) & FSI_SSTAT_BDL_MASK;
> +}
> +
> +/* FSI status get CRC counter */
> +static inline int fsi_sstat_crc(u32 x)
> +{
> +       return (x >> FSI_SSTAT_CRC_SHIFT) & FSI_SSTAT_CRC_MASK;
> +}
> +
> +/*
> + * FSI slave local bus access register SLBUS
> + */
> +#define        FSI_SLBUS_FLBO          0x80000000      /* Force local bus ownership */
> +#define        FSI_SLBUS_RLBA          0x40000000      /* Request local bus access */
> +#define        FSI_SLBUS_RLBO_SHIFT    28              /* Release local bus shift */
> +#define        FSI_SLBUS_RLBO_MASK     3               /* Release local bus mask */
> +#define        FSI_SLBUS_RLBR          0x08000000      /* Reset local bus req */
> +#define        FSI_SLBUS_BLBA_SHIFT    16              /* Block local bus acc shift */
> +#define        FSI_SLBUS_BLBA_MASK     0xff            /* Block local bus acc mask */
> +#define        FSI_SLBUS_BLBA          0xff            /* Block local bus acc */
> +#define        FSI_SLBUS_UBLBA         0xec            /* Unblock local bus access */
> +#define        FSI_SLBUS_RESERVE_MASK  0xf8ff0000      /* Mask off reserved bits */
> +
> +/* Release local bus */
> +static inline u32 fsi_slbus_rlbo(int side)
> +{
> +       return (side & FSI_SLBUS_RLBO_MASK) << FSI_SLBUS_RLBO_SHIFT;
> +}
> +
> +/* Block local bus access */
> +static inline u32 fsi_slbus_blba(int side)
> +{
> +       return (side & FSI_SLBUS_BLBA_MASK) << FSI_SLBUS_BLBA_SHIFT;
> +}
> +
> +/* FSI Slave Error Reset Register SRES */
> +#define        FSI_SRES_RFS            0x80000000      /* Reset FSI slave */
> +#define        FSI_SRES_REFS           0x40000000      /* Reset Errors FSI slave */
> +#define        FSI_SRES_RLBE           0x20000000      /* Reset Local bus engs slave */
> +#define        FSI_SRES_RESERVE_MASK   0x1fffffff      /* Mask off reserved bits */
> +
> +int slave_readreg(struct fsimaster *, void *, u32 *, u32);
> +int slave_writereg(struct fsimaster *, void *, u32, u32);
> +int slave_irqclear(struct fsimaster *, void *, u32, u32);
> +int p8_cfam_fixup(struct fsicfam *, int);
> +unsigned long xmp8_srsim_mask(int);
> +
> +#endif /* DRIVERS_FSISLAVE_H */
> diff --git a/drivers/fsi/ldm.c b/drivers/fsi/ldm.c
> new file mode 100644
> index 0000000..254a95ea
> --- /dev/null
> +++ b/drivers/fsi/ldm.c
> @@ -0,0 +1,28 @@
> +/*
> + * FSI interface to the LDM
> + *
> + * 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 "fsi.h"
> +#include "fsidefines.h"
> +
> +/*
> + * Register a FSI device with the Linux device model
> + */
> +int fsidev_register_nolock(struct fsidevice *p, struct device_attribute **ap)
> +{
> +       return 0;
> +}
> +
> +int fsidev_register(struct fsidevice *p, struct device_attribute **ap)
> +{
> +       return 0;
> +}
> +EXPORT_SYMBOL(fsidev_register);
> diff --git a/drivers/fsi/readwrite.c b/drivers/fsi/readwrite.c
> new file mode 100644
> index 0000000..3c7f0c5
> --- /dev/null
> +++ b/drivers/fsi/readwrite.c
> @@ -0,0 +1,48 @@
> +/*
> + * FSI I/O accesses
> + *
> + * 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 "fsi.h"
> +#include "fsidefines.h"
> +#include "fsimaster.h"
> +
> +/*
> + * Send out a BREAK command on a given link - Resets the logic of any slaves
> + * present
> + */
> +int fsi_sendbreak(struct fsimaster *p, u32 pa, int linkno)
> +{
> +       return 0;
> +}
> +
> +/*
> + * Read/write functions to be used only by the FSI driver itself.  FSI clients
> + * will use separate interfaces
> + */
> +int fsi_readw_int2(u32 pa, u32 *value)
> +{
> +       return 0;
> +}
> +
> +int fsi_writew_int2(u32 pa, u32 value)
> +{
> +       return 0;
> +}
> +
> +int fsi_readw_int(u32 pa, u32 *value)
> +{
> +       return 0;
> +}
> +
> +int fsi_writew_int(u32 pa, u32 value)
> +{
> +       return 0;
> +}
> --
> 1.8.2.2
>


More information about the openbmc mailing list