Commit cd9de065 authored by Federico Vaga's avatar Federico Vaga

sw:drv: split GPIO initialization in smaller functions

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 391b25f8
...@@ -269,19 +269,14 @@ static inline size_t spec_gpiod_table_size(void) ...@@ -269,19 +269,14 @@ static inline size_t spec_gpiod_table_size(void)
(sizeof(struct gpiod_lookup) * 9); (sizeof(struct gpiod_lookup) * 9);
} }
static int spec_gpio_init(struct spec_gn412x *spec_gn412x) static int spec_gpio_init_table(struct spec_gn412x *spec_gn412x)
{ {
struct gpio_desc *gpiod;
struct gpiod_lookup_table *lookup; struct gpiod_lookup_table *lookup;
int err = 0; int err = 0;
lookup = devm_kzalloc(&spec_gn412x->pdev->dev, lookup = kzalloc(spec_gpiod_table_size(), GFP_KERNEL);
spec_gpiod_table_size(), if (!lookup)
GFP_KERNEL); return -ENOMEM;
if (!lookup) {
err = -ENOMEM;
goto err_alloc;
}
memcpy(lookup, &spec_gpiod_table, spec_gpiod_table_size()); memcpy(lookup, &spec_gpiod_table, spec_gpiod_table_size());
...@@ -294,12 +289,48 @@ static int spec_gpio_init(struct spec_gn412x *spec_gn412x) ...@@ -294,12 +289,48 @@ static int spec_gpio_init(struct spec_gn412x *spec_gn412x)
if (err) if (err)
goto err_lookup; goto err_lookup;
return 0;
err_lookup:
kfree(lookup->dev_id);
err_dup:
kfree(lookup);
return err;
}
static void spec_gpio_exit_table(struct spec_gn412x *spec_gn412x)
{
struct gpiod_lookup_table *lookup = spec_gn412x->gpiod_table;
gpiod_remove_lookup_table(spec_gn412x->gpiod_table);
kfree(lookup->dev_id);
kfree(lookup);
spec_gn412x->gpiod_table = NULL;
}
/**
* Configure bootsel GPIOs
*
* Note: Because of a BUG in RedHat kernel 3.10 we re-set direction
*/
static int spec_gpio_init_bootsel(struct spec_gn412x *spec_gn412x)
{
struct gpio_desc *gpiod;
int err;
gpiod = gpiod_get_index(&spec_gn412x->pdev->dev, "bootsel", 0, gpiod = gpiod_get_index(&spec_gn412x->pdev->dev, "bootsel", 0,
GPIOD_OUT_HIGH); 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;
} }
err = gpiod_direction_output(gpiod, 1);
if (err) {
gpiod_put(gpiod);
goto err_out0;
}
spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0] = gpiod; spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0] = gpiod;
gpiod = gpiod_get_index(&spec_gn412x->pdev->dev, "bootsel", 1, gpiod = gpiod_get_index(&spec_gn412x->pdev->dev, "bootsel", 1,
...@@ -308,74 +339,115 @@ static int spec_gpio_init(struct spec_gn412x *spec_gn412x) ...@@ -308,74 +339,115 @@ static int spec_gpio_init(struct spec_gn412x *spec_gn412x)
err = PTR_ERR(gpiod); err = PTR_ERR(gpiod);
goto err_sel1; goto err_sel1;
} }
err = gpiod_direction_output(gpiod, 1);
if (err) {
gpiod_put(gpiod);
goto err_out1;
}
spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1] = gpiod; spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1] = gpiod;
/* Because of a BUG in RedHat kernel 3.10 we re-set direction */ return 0;
err = gpiod_direction_output(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0],
1);
if (err)
goto err_out0;
err = gpiod_direction_output(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1],
1);
if (err)
goto err_out1;
err_out1:
err_sel1:
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0]);
spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0] = NULL;
err_out0:
err_sel0:
return err;
}
static void spec_gpio_exit_bootsel(struct spec_gn412x *spec_gn412x)
{
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1]);
spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1] = NULL;
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0]);
spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0] = NULL;
}
/**
* Configure IRQ GPIOs
*
* Note: Because of a BUG in RedHat kernel 3.10 we re-set direction
*/
static int spec_gpio_init_irq(struct spec_gn412x *spec_gn412x)
{
struct gpio_desc *gpiod;
int err;
gpiod = gpiod_get_index(&spec_gn412x->pdev->dev, "irq", 0, GPIOD_IN); gpiod = gpiod_get_index(&spec_gn412x->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_sel0;
}
err = gpiod_direction_input(gpiod);
if (err) {
gpiod_put(gpiod);
goto err_out0;
} }
spec_gn412x->gpiod[GN4124_GPIO_IRQ0] = gpiod; spec_gn412x->gpiod[GN4124_GPIO_IRQ0] = gpiod;
gpiod = gpiod_get_index(&spec_gn412x->pdev->dev, "irq", 1, GPIOD_IN); gpiod = gpiod_get_index(&spec_gn412x->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_sel1;
}
err = gpiod_direction_input(gpiod);
if (err) {
gpiod_put(gpiod);
goto err_out1;
} }
spec_gn412x->gpiod[GN4124_GPIO_IRQ1] = gpiod; spec_gn412x->gpiod[GN4124_GPIO_IRQ1] = gpiod;
/* Because of a BUG in RedHat kernel 3.10 we re-set direction */
err = gpiod_direction_input(spec_gn412x->gpiod[GN4124_GPIO_IRQ0]);
if (err)
goto err_in0;
err = gpiod_direction_input(spec_gn412x->gpiod[GN4124_GPIO_IRQ1]);
if (err)
goto err_in1;
return 0; return 0;
err_in1:
err_in0:
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ1]);
err_irq1:
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ0]);
err_irq0:
err_out1: err_out1:
err_out0:
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1]);
err_sel1: err_sel1:
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0]); gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ0]);
spec_gn412x->gpiod[GN4124_GPIO_IRQ0] = NULL;
err_out0:
err_sel0: err_sel0:
gpiod_remove_lookup_table(spec_gn412x->gpiod_table);
err_lookup:
kfree(lookup->dev_id);
err_dup:
devm_kfree(&spec_gn412x->pdev->dev, lookup);
spec_gn412x->gpiod_table = NULL;
err_alloc:
return err; return err;
} }
static void spec_gpio_exit(struct spec_gn412x *spec_gn412x) static void spec_gpio_exit_irq(struct spec_gn412x *spec_gn412x)
{ {
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ1]); gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ1]);
spec_gn412x->gpiod[GN4124_GPIO_IRQ1] = NULL;
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ0]); gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_IRQ0]);
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL1]); spec_gn412x->gpiod[GN4124_GPIO_IRQ0] = NULL;
gpiod_put(spec_gn412x->gpiod[GN4124_GPIO_BOOTSEL0]); }
gpiod_remove_lookup_table(spec_gn412x->gpiod_table);
kfree(spec_gn412x->gpiod_table->dev_id); static int spec_gpio_init(struct spec_gn412x *spec_gn412x)
{
int err;
err = spec_gpio_init_table(spec_gn412x);
if (err)
return err;
err = spec_gpio_init_bootsel(spec_gn412x);
if (err)
goto err_bootsel;
err = spec_gpio_init_irq(spec_gn412x);
if (err)
goto err_irq;
return 0;
err_irq:
spec_gpio_exit_bootsel(spec_gn412x);
err_bootsel:
spec_gpio_exit_table(spec_gn412x);
return err;
}
static void spec_gpio_exit(struct spec_gn412x *spec_gn412x)
{
spec_gpio_exit_irq(spec_gn412x);
spec_gpio_exit_bootsel(spec_gn412x);
spec_gpio_exit_table(spec_gn412x);
} }
/* SPEC sub-devices */ /* SPEC sub-devices */
...@@ -581,7 +653,7 @@ static int spec_probe(struct pci_dev *pdev, ...@@ -581,7 +653,7 @@ static int spec_probe(struct pci_dev *pdev,
const struct pci_device_id *id) const struct pci_device_id *id)
{ {
struct spec_gn412x *spec_gn412x; struct spec_gn412x *spec_gn412x;
int err; int err = 0;
spec_gn412x = kzalloc(sizeof(*spec_gn412x), GFP_KERNEL); spec_gn412x = kzalloc(sizeof(*spec_gn412x), GFP_KERNEL);
if (!spec_gn412x) if (!spec_gn412x)
......
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