Commit da4085d5 authored by Federico Vaga's avatar Federico Vaga

sw:drv: move spec-core-fpga device register where it belongs

The SPEC is made of its PCI bridge (GN4124) and a set of FPGA
devices that enables some carrier feature. The first one is handled
by the Linux pci_dev, the second set of devices have a commond parent
that I am moving into the spec-core-fpga.c file so that all FPGA related
code is in one place
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 292e1bd7
...@@ -490,14 +490,14 @@ static void spec_fpga_app_exit(struct spec_dev *spec) ...@@ -490,14 +490,14 @@ static void spec_fpga_app_exit(struct spec_dev *spec)
static bool spec_fpga_is_valid(struct spec_dev *spec) static bool spec_fpga_is_valid(struct spec_dev *spec)
{ {
if ((spec->meta->bom & SPEC_META_BOM_END_MASK) != SPEC_META_BOM_LE) { if ((spec->meta->bom & SPEC_META_BOM_END_MASK) != SPEC_META_BOM_LE) {
dev_err(spec->dev.parent, dev_err(&spec->pdev->dev,
"Expected Little Endian devices BOM: 0x%x\n", "Expected Little Endian devices BOM: 0x%x\n",
spec->meta->bom); spec->meta->bom);
return false; return false;
} }
if ((spec->meta->bom & SPEC_META_BOM_VER_MASK) != 0) { if ((spec->meta->bom & SPEC_META_BOM_VER_MASK) != 0) {
dev_err(spec->dev.parent, dev_err(&spec->pdev->dev,
"Unknow Metadata specification version BOM: 0x%x\n", "Unknow Metadata specification version BOM: 0x%x\n",
spec->meta->bom); spec->meta->bom);
return false; return false;
...@@ -505,14 +505,14 @@ static bool spec_fpga_is_valid(struct spec_dev *spec) ...@@ -505,14 +505,14 @@ static bool spec_fpga_is_valid(struct spec_dev *spec)
if (spec->meta->vendor != SPEC_META_VENDOR_ID || if (spec->meta->vendor != SPEC_META_VENDOR_ID ||
spec->meta->device != SPEC_META_DEVICE_ID) { spec->meta->device != SPEC_META_DEVICE_ID) {
dev_err(spec->dev.parent, dev_err(&spec->pdev->dev,
"Unknow vendor/device ID: %08x:%08x\n", "Unknow vendor/device ID: %08x:%08x\n",
spec->meta->vendor, spec->meta->device); spec->meta->vendor, spec->meta->device);
return false; return false;
} }
if (spec->meta->version != SPEC_META_VERSION_1_4) { if (spec->meta->version != SPEC_META_VERSION_1_4) {
dev_err(spec->dev.parent, dev_err(&spec->pdev->dev,
"Unknow version: %08x\n", spec->meta->version); "Unknow version: %08x\n", spec->meta->version);
return false; return false;
} }
...@@ -521,6 +521,22 @@ static bool spec_fpga_is_valid(struct spec_dev *spec) ...@@ -521,6 +521,22 @@ static bool spec_fpga_is_valid(struct spec_dev *spec)
} }
static void spec_release(struct device *dev)
{
}
static int spec_uevent(struct device *dev, struct kobj_uevent_env *env)
{
return 0;
}
static const struct device_type spec_dev_type = {
.name = "spec",
.release = spec_release,
.uevent = spec_uevent,
};
/** /**
* Initialize carrier devices on FPGA * Initialize carrier devices on FPGA
*/ */
...@@ -534,6 +550,22 @@ int spec_fpga_init(struct spec_dev *spec) ...@@ -534,6 +550,22 @@ int spec_fpga_init(struct spec_dev *spec)
if (!spec_fpga_is_valid(spec)) if (!spec_fpga_is_valid(spec))
return -EINVAL; return -EINVAL;
memset(&spec->dev, 0, sizeof(spec->dev));
spec->dev.parent = &spec->pdev->dev;
spec->dev.driver = spec->pdev->dev.driver;
spec->dev.type = &spec_dev_type;
err = dev_set_name(&spec->dev, "spec-%s", dev_name(&spec->pdev->dev));
if (err)
goto err_name;
err = device_register(&spec->dev);
if (err) {
dev_err(&spec->pdev->dev, "Failed to register '%s'\n",
dev_name(&spec->dev));
goto err_dev;
}
err = spec_fpga_therm_init(spec); err = spec_fpga_therm_init(spec);
if (err) if (err)
goto err_therm; goto err_therm;
...@@ -542,7 +574,7 @@ int spec_fpga_init(struct spec_dev *spec) ...@@ -542,7 +574,7 @@ int spec_fpga_init(struct spec_dev *spec)
goto err_vic; goto err_vic;
err = spec_fpga_devices_init(spec); err = spec_fpga_devices_init(spec);
if (err) if (err)
goto err_dev; goto err_devs;
err = spec_fmc_init(spec); err = spec_fmc_init(spec);
if (err) if (err)
goto err_fmc; goto err_fmc;
...@@ -556,11 +588,14 @@ err_app: ...@@ -556,11 +588,14 @@ err_app:
spec_fmc_exit(spec); spec_fmc_exit(spec);
err_fmc: err_fmc:
spec_fpga_devices_exit(spec); spec_fpga_devices_exit(spec);
err_dev: err_devs:
spec_fpga_vic_exit(spec); spec_fpga_vic_exit(spec);
err_vic: err_vic:
spec_fpga_therm_exit(spec); spec_fpga_therm_exit(spec);
err_therm: err_therm:
device_unregister(&spec->dev);
err_dev:
err_name:
return err; return err;
} }
...@@ -571,6 +606,7 @@ int spec_fpga_exit(struct spec_dev *spec) ...@@ -571,6 +606,7 @@ int spec_fpga_exit(struct spec_dev *spec)
spec_fpga_devices_exit(spec); spec_fpga_devices_exit(spec);
spec_fpga_vic_exit(spec); spec_fpga_vic_exit(spec);
spec_fpga_therm_exit(spec); spec_fpga_therm_exit(spec);
device_unregister(&spec->dev);
return 0; return 0;
} }
...@@ -92,12 +92,10 @@ static const struct mfd_cell spec_mfd_devs[] = { ...@@ -92,12 +92,10 @@ static const struct mfd_cell spec_mfd_devs[] = {
*/ */
static const char *spec_fw_name_init_get(struct spec_dev *spec) static const char *spec_fw_name_init_get(struct spec_dev *spec)
{ {
struct pci_dev *pdev = to_pci_dev(spec->dev.parent);
if (strlen(spec_fw_name) > 0) if (strlen(spec_fw_name) > 0)
return spec_fw_name; return spec_fw_name;
switch (pdev->device) { switch (spec->pdev->device) {
case PCI_DEVICE_ID_SPEC_45T: case PCI_DEVICE_ID_SPEC_45T:
return spec_fw_name_45t; return spec_fw_name_45t;
case PCI_DEVICE_ID_SPEC_100T: case PCI_DEVICE_ID_SPEC_100T:
...@@ -123,7 +121,7 @@ int spec_fw_load(struct spec_dev *spec, const char *name) ...@@ -123,7 +121,7 @@ int spec_fw_load(struct spec_dev *spec, const char *name)
err = spec_fpga_exit(spec); err = spec_fpga_exit(spec);
if (err) { if (err) {
dev_err(&spec->dev, dev_err(&spec->pdev->dev,
"Cannot remove FPGA device instances. Try to remove them manually and to reload this device instance\n"); "Cannot remove FPGA device instances. Try to remove them manually and to reload this device instance\n");
return err; return err;
} }
...@@ -140,7 +138,7 @@ int spec_fw_load(struct spec_dev *spec, const char *name) ...@@ -140,7 +138,7 @@ int spec_fw_load(struct spec_dev *spec, const char *name)
err = spec_fpga_init(spec); err = spec_fpga_init(spec);
if (err) if (err)
dev_warn(&spec->dev, "FPGA incorrectly programmed\n"); dev_warn(&spec->pdev->dev, "FPGA incorrectly programmed\n");
out: out:
spec_gpio_fpga_select_set(spec, sel); spec_gpio_fpga_select_set(spec, sel);
...@@ -149,22 +147,12 @@ out: ...@@ -149,22 +147,12 @@ out:
return err; return err;
} }
static void spec_release(struct device *dev)
{
}
static int spec_uevent(struct device *dev, struct kobj_uevent_env *env)
{
return 0;
}
static ssize_t bootselect_store(struct device *dev, static ssize_t bootselect_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct spec_dev *spec = to_spec_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct spec_dev *spec = pci_get_drvdata(pdev);
enum spec_fpga_select sel; enum spec_fpga_select sel;
if (strncmp("fpga-flash", buf, 8) == 0) { if (strncmp("fpga-flash", buf, 8) == 0) {
...@@ -190,7 +178,8 @@ static ssize_t bootselect_show(struct device *dev, ...@@ -190,7 +178,8 @@ static ssize_t bootselect_show(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
char *buf) char *buf)
{ {
struct spec_dev *spec = to_spec_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct spec_dev *spec = pci_get_drvdata(pdev);
enum spec_fpga_select sel; enum spec_fpga_select sel;
sel = spec_gpio_fpga_select_get(spec); sel = spec_gpio_fpga_select_get(spec);
...@@ -216,7 +205,8 @@ static ssize_t load_golden_fpga_store(struct device *dev, ...@@ -216,7 +205,8 @@ static ssize_t load_golden_fpga_store(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct spec_dev *spec = to_spec_dev(dev); struct pci_dev *pdev = to_pci_dev(dev);
struct spec_dev *spec = pci_get_drvdata(pdev);
int err; int err;
err = spec_fw_load(spec, spec_fw_name_init_get(spec)); err = spec_fw_load(spec, spec_fw_name_init_get(spec));
...@@ -225,29 +215,17 @@ static ssize_t load_golden_fpga_store(struct device *dev, ...@@ -225,29 +215,17 @@ static ssize_t load_golden_fpga_store(struct device *dev,
} }
static DEVICE_ATTR_WO(load_golden_fpga); static DEVICE_ATTR_WO(load_golden_fpga);
static struct attribute *spec_type_attrs[] = { static struct attribute *gn412x_fpga_attrs[] = {
&dev_attr_load_golden_fpga.attr, &dev_attr_load_golden_fpga.attr,
&dev_attr_bootselect.attr, &dev_attr_bootselect.attr,
NULL, NULL,
}; };
static const struct attribute_group spec_type_group = { static const struct attribute_group gn412x_fpga_group = {
.attrs = spec_type_attrs, .name = "fpga-options",
.attrs = gn412x_fpga_attrs,
}; };
static const struct attribute_group *spec_type_groups[] = {
&spec_type_group,
NULL,
};
static const struct device_type spec_dev_type = {
.name = "spec",
.release = spec_release,
.uevent = spec_uevent,
.groups = spec_type_groups,
};
static int spec_probe(struct pci_dev *pdev, static int spec_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
...@@ -260,11 +238,11 @@ static int spec_probe(struct pci_dev *pdev, ...@@ -260,11 +238,11 @@ static int spec_probe(struct pci_dev *pdev,
mutex_init(&spec->mtx); mutex_init(&spec->mtx);
pci_set_drvdata(pdev, spec); pci_set_drvdata(pdev, spec);
spec->pdev = pdev;
err = pci_enable_device(pdev); err = pci_enable_device(pdev);
if (err) { if (err) {
dev_err(spec->dev.parent, dev_err(&pdev->dev, "Failed to enable PCI device (%d)\n",
"Failed to enable PCI device (%d)\n",
err); err);
goto err_enable; goto err_enable;
} }
...@@ -285,7 +263,7 @@ static int spec_probe(struct pci_dev *pdev, ...@@ -285,7 +263,7 @@ static int spec_probe(struct pci_dev *pdev,
} }
} }
if (err) { if (err) {
dev_err(spec->dev.parent, "Failed to remap memory (%d)\n", dev_err(&pdev->dev, "Failed to remap memory (%d)\n",
err); err);
goto err_remap; goto err_remap;
} }
...@@ -295,35 +273,25 @@ static int spec_probe(struct pci_dev *pdev, ...@@ -295,35 +273,25 @@ static int spec_probe(struct pci_dev *pdev,
ARRAY_SIZE(spec_mfd_devs), ARRAY_SIZE(spec_mfd_devs),
&pdev->resource[4], pdev->irq, NULL); &pdev->resource[4], pdev->irq, NULL);
if (err) { if (err) {
dev_err(&spec->dev, "Failed to add MFD devices (%d)\n", err); dev_err(&spec->pdev->dev, "Failed to add MFD devices (%d)\n",
err);
goto err_mfd; goto err_mfd;
} }
spec->dev.parent = &pdev->dev;
spec->dev.type = &spec_dev_type;
err = dev_set_name(&spec->dev, "spec-%s", dev_name(&pdev->dev));
if (err)
goto err_name;
err = device_register(&spec->dev);
if (err) {
dev_err(spec->dev.parent, "Failed to register '%s'\n",
dev_name(&spec->dev));
goto err_dev;
}
/* This virtual device is assciated with this driver */
spec->dev.driver = pdev->dev.driver;
err = spec_gpio_init(spec); err = spec_gpio_init(spec);
if (err) { if (err) {
dev_err(&spec->dev, "Failed to get GPIOs (%d)\n", err); dev_err(&pdev->dev, "Failed to get GPIOs (%d)\n", err);
goto err_sgpio; goto err_sgpio;
} }
err = sysfs_create_group(&pdev->dev.kobj, &gn412x_fpga_group);
if (err)
goto err_sysfs;
mutex_lock(&spec->mtx); mutex_lock(&spec->mtx);
err = spec_fpga_init(spec); err = spec_fpga_init(spec);
if (err) if (err)
dev_warn(&spec->dev, dev_warn(&pdev->dev,
"FPGA incorrectly programmed or empty (%d)\n", err); "FPGA incorrectly programmed or empty (%d)\n", err);
mutex_unlock(&spec->mtx); mutex_unlock(&spec->mtx);
...@@ -331,10 +299,9 @@ static int spec_probe(struct pci_dev *pdev, ...@@ -331,10 +299,9 @@ static int spec_probe(struct pci_dev *pdev,
return 0; return 0;
err_sysfs:
spec_gpio_exit(spec);
err_sgpio: err_sgpio:
device_unregister(&spec->dev);
err_dev:
err_name:
mfd_remove_devices(&pdev->dev); mfd_remove_devices(&pdev->dev);
err_mfd: err_mfd:
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
...@@ -356,8 +323,8 @@ static void spec_remove(struct pci_dev *pdev) ...@@ -356,8 +323,8 @@ static void spec_remove(struct pci_dev *pdev)
spec_dbg_exit(spec); spec_dbg_exit(spec);
spec_fpga_exit(spec); spec_fpga_exit(spec);
sysfs_remove_group(&pdev->dev.kobj, &gn412x_fpga_group);
spec_gpio_exit(spec); spec_gpio_exit(spec);
device_unregister(&spec->dev);
mfd_remove_devices(&pdev->dev); mfd_remove_devices(&pdev->dev);
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
......
...@@ -15,9 +15,9 @@ static int spec_irq_dbg_info(struct seq_file *s, void *offset) ...@@ -15,9 +15,9 @@ static int spec_irq_dbg_info(struct seq_file *s, void *offset)
{ {
struct spec_dev *spec = s->private; struct spec_dev *spec = s->private;
seq_printf(s, "'%s':\n", dev_name(spec->dev.parent)); seq_printf(s, "'%s':\n", dev_name(&spec->pdev->dev));
seq_printf(s, " redirect: %d\n", to_pci_dev(spec->dev.parent)->irq); seq_printf(s, " redirect: %d\n", to_pci_dev(&spec->pdev->dev)->irq);
seq_puts(s, " irq-mapping:\n"); seq_puts(s, " irq-mapping:\n");
seq_puts(s, " - hardware: 8\n"); seq_puts(s, " - hardware: 8\n");
seq_printf(s, " linux: %d\n", seq_printf(s, " linux: %d\n",
...@@ -75,7 +75,7 @@ static int spec_dbg_meta(struct seq_file *s, void *offset) ...@@ -75,7 +75,7 @@ static int spec_dbg_meta(struct seq_file *s, void *offset)
{ {
struct spec_dev *spec = s->private; struct spec_dev *spec = s->private;
seq_printf(s, "'%s':\n", dev_name(spec->dev.parent)); seq_printf(s, "'%s':\n", dev_name(&spec->pdev->dev));
seq_puts(s, "Metadata:\n"); seq_puts(s, "Metadata:\n");
seq_printf(s, " - Vendor: 0x%08x\n", spec->meta->vendor); seq_printf(s, " - Vendor: 0x%08x\n", spec->meta->vendor);
seq_printf(s, " - Device: 0x%08x\n", spec->meta->device); seq_printf(s, " - Device: 0x%08x\n", spec->meta->device);
...@@ -119,7 +119,7 @@ static const struct file_operations spec_dbg_meta_ops = { ...@@ -119,7 +119,7 @@ static const struct file_operations spec_dbg_meta_ops = {
*/ */
int spec_dbg_init(struct spec_dev *spec) int spec_dbg_init(struct spec_dev *spec)
{ {
spec->dbg_dir = debugfs_create_dir(dev_name(&spec->dev), NULL); spec->dbg_dir = debugfs_create_dir(dev_name(&spec->pdev->dev), NULL);
if (IS_ERR_OR_NULL(spec->dbg_dir)) { if (IS_ERR_OR_NULL(spec->dbg_dir)) {
dev_err(&spec->dev, dev_err(&spec->dev,
"Cannot create debugfs directory (%ld)\n", "Cannot create debugfs directory (%ld)\n",
......
...@@ -78,7 +78,7 @@ int spec_gpio_init(struct spec_dev *spec) ...@@ -78,7 +78,7 @@ int spec_gpio_init(struct spec_dev *spec)
struct gpiod_lookup_table *lookup; struct gpiod_lookup_table *lookup;
int err = 0; int err = 0;
lookup = devm_kzalloc(spec->dev.parent, lookup = devm_kzalloc(&spec->pdev->dev,
spec_gpiod_table_size(), spec_gpiod_table_size(),
GFP_KERNEL); GFP_KERNEL);
if (!lookup) { if (!lookup) {
...@@ -88,7 +88,7 @@ int spec_gpio_init(struct spec_dev *spec) ...@@ -88,7 +88,7 @@ int spec_gpio_init(struct spec_dev *spec)
memcpy(lookup, &spec_gpiod_table, spec_gpiod_table_size()); memcpy(lookup, &spec_gpiod_table, spec_gpiod_table_size());
lookup->dev_id = kstrdup(dev_name(spec->dev.parent), GFP_KERNEL); lookup->dev_id = kstrdup(dev_name(&spec->pdev->dev), GFP_KERNEL);
if (!lookup->dev_id) if (!lookup->dev_id)
goto err_dup; goto err_dup;
...@@ -97,14 +97,14 @@ int spec_gpio_init(struct spec_dev *spec) ...@@ -97,14 +97,14 @@ int spec_gpio_init(struct spec_dev *spec)
if (err) if (err)
goto err_lookup; goto err_lookup;
gpiod = gpiod_get_index(spec->dev.parent, "bootsel", 0, GPIOD_OUT_HIGH); gpiod = gpiod_get_index(&spec->pdev->dev, "bootsel", 0, GPIOD_OUT_HIGH);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
err = PTR_ERR(gpiod); err = PTR_ERR(gpiod);
goto err_sel0; goto err_sel0;
} }
spec->gpiod[GN4124_GPIO_BOOTSEL0] = gpiod; spec->gpiod[GN4124_GPIO_BOOTSEL0] = gpiod;
gpiod = gpiod_get_index(spec->dev.parent, "bootsel", 1, GPIOD_OUT_HIGH); gpiod = gpiod_get_index(&spec->pdev->dev, "bootsel", 1, GPIOD_OUT_HIGH);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
err = PTR_ERR(gpiod); err = PTR_ERR(gpiod);
goto err_sel1; goto err_sel1;
...@@ -120,14 +120,14 @@ int spec_gpio_init(struct spec_dev *spec) ...@@ -120,14 +120,14 @@ int spec_gpio_init(struct spec_dev *spec)
goto err_out1; goto err_out1;
gpiod = gpiod_get_index(spec->dev.parent, "irq", 0, GPIOD_IN); gpiod = gpiod_get_index(&spec->pdev->dev, "irq", 0, GPIOD_IN);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
err = PTR_ERR(gpiod); err = PTR_ERR(gpiod);
goto err_irq0; goto err_irq0;
} }
spec->gpiod[GN4124_GPIO_IRQ0] = gpiod; spec->gpiod[GN4124_GPIO_IRQ0] = gpiod;
gpiod = gpiod_get_index(spec->dev.parent, "irq", 1, GPIOD_IN); gpiod = gpiod_get_index(&spec->pdev->dev, "irq", 1, GPIOD_IN);
if (IS_ERR(gpiod)) { if (IS_ERR(gpiod)) {
err = PTR_ERR(gpiod); err = PTR_ERR(gpiod);
goto err_irq1; goto err_irq1;
...@@ -160,7 +160,7 @@ err_sel0: ...@@ -160,7 +160,7 @@ err_sel0:
err_lookup: err_lookup:
kfree(lookup->dev_id); kfree(lookup->dev_id);
err_dup: err_dup:
devm_kfree(spec->dev.parent, lookup); devm_kfree(&spec->pdev->dev, lookup);
spec->gpiod_table = NULL; spec->gpiod_table = NULL;
err_alloc: err_alloc:
......
...@@ -110,6 +110,7 @@ struct spec_meta_id { ...@@ -110,6 +110,7 @@ struct spec_meta_id {
* @i2c_adapter: the I2C master device to be used * @i2c_adapter: the I2C master device to be used
*/ */
struct spec_dev { struct spec_dev {
struct pci_dev *pdev;
struct device dev; struct device dev;
DECLARE_BITMAP(flags, SPEC_FLAG_BITS); DECLARE_BITMAP(flags, SPEC_FLAG_BITS);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment