drivers/fsi: Implement slave initialisation
Implement fsi_slave_init: if we can read a chip ID, create fsi_slave devices and register with the driver core. Includes changes from Christopher Bostic <cbostic@linux.vnet.ibm.com>. Signed-off-by: Jeremy Kerr <jk@ozlabs.org> Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com> Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
2609528211
commit
2b545cd8e1
|
@ -6,6 +6,7 @@ menu "FSI support"
|
|||
|
||||
config FSI
|
||||
tristate "FSI support"
|
||||
select CRC4
|
||||
---help---
|
||||
FSI - the FRU Support Interface - is a simple bus for low-level
|
||||
access to POWER-based hardware.
|
||||
|
|
|
@ -13,13 +13,17 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
#include <linux/crc4.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fsi.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "fsi-master.h"
|
||||
|
||||
#define FSI_SLAVE_SIZE_23b 0x800000
|
||||
|
||||
static DEFINE_IDA(master_ida);
|
||||
|
||||
struct fsi_slave {
|
||||
|
@ -90,11 +94,70 @@ static int fsi_slave_write(struct fsi_slave *slave, uint32_t addr,
|
|||
addr, val, size);
|
||||
}
|
||||
|
||||
static void fsi_slave_release(struct device *dev)
|
||||
{
|
||||
struct fsi_slave *slave = to_fsi_slave(dev);
|
||||
|
||||
kfree(slave);
|
||||
}
|
||||
|
||||
static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
|
||||
{
|
||||
/* todo: initialise slave device, perform engine scan */
|
||||
struct fsi_slave *slave;
|
||||
uint32_t chip_id;
|
||||
uint8_t crc;
|
||||
int rc;
|
||||
|
||||
return -ENODEV;
|
||||
/* Currently, we only support single slaves on a link, and use the
|
||||
* full 23-bit address range
|
||||
*/
|
||||
if (id != 0)
|
||||
return -EINVAL;
|
||||
|
||||
rc = fsi_master_read(master, link, id, 0, &chip_id, sizeof(chip_id));
|
||||
if (rc) {
|
||||
dev_dbg(&master->dev, "can't read slave %02x:%02x %d\n",
|
||||
link, id, rc);
|
||||
return -ENODEV;
|
||||
}
|
||||
chip_id = be32_to_cpu(chip_id);
|
||||
|
||||
crc = crc4(0, chip_id, 32);
|
||||
if (crc) {
|
||||
dev_warn(&master->dev, "slave %02x:%02x invalid chip id CRC!\n",
|
||||
link, id);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_info(&master->dev, "fsi: found chip %08x at %02x:%02x:%02x\n",
|
||||
chip_id, master->idx, link, id);
|
||||
|
||||
/* We can communicate with a slave; create the slave device and
|
||||
* register.
|
||||
*/
|
||||
slave = kzalloc(sizeof(*slave), GFP_KERNEL);
|
||||
if (!slave)
|
||||
return -ENOMEM;
|
||||
|
||||
slave->master = master;
|
||||
slave->dev.parent = &master->dev;
|
||||
slave->dev.release = fsi_slave_release;
|
||||
slave->link = link;
|
||||
slave->id = id;
|
||||
slave->size = FSI_SLAVE_SIZE_23b;
|
||||
|
||||
dev_set_name(&slave->dev, "slave@%02x:%02x", link, id);
|
||||
rc = device_register(&slave->dev);
|
||||
if (rc < 0) {
|
||||
dev_warn(&master->dev, "failed to create slave device: %d\n",
|
||||
rc);
|
||||
put_device(&slave->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* todo: perform engine scan */
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* FSI master support */
|
||||
|
|
Loading…
Reference in New Issue