summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpio-mmio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpio/gpio-mmio.c')
-rw-r--r--drivers/gpio/gpio-mmio.c131
1 files changed, 65 insertions, 66 deletions
diff --git a/drivers/gpio/gpio-mmio.c b/drivers/gpio/gpio-mmio.c
index 4841e4ebe7a6..cf878c2ea6bf 100644
--- a/drivers/gpio/gpio-mmio.c
+++ b/drivers/gpio/gpio-mmio.c
@@ -211,11 +211,12 @@ static int bgpio_get_multiple_be(struct gpio_chip *gc, unsigned long *mask,
return 0;
}
-static void bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
+static int bgpio_set_none(struct gpio_chip *gc, unsigned int gpio, int val)
{
+ return 0;
}
-static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+static int bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
unsigned long mask = bgpio_line2mask(gc, gpio);
unsigned long flags;
@@ -230,10 +231,12 @@ static void bgpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
gc->write_reg(gc->reg_dat, gc->bgpio_data);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+ return 0;
}
-static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
- int val)
+static int bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
+ int val)
{
unsigned long mask = bgpio_line2mask(gc, gpio);
@@ -241,9 +244,11 @@ static void bgpio_set_with_clear(struct gpio_chip *gc, unsigned int gpio,
gc->write_reg(gc->reg_set, mask);
else
gc->write_reg(gc->reg_clr, mask);
+
+ return 0;
}
-static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
+static int bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
{
unsigned long mask = bgpio_line2mask(gc, gpio);
unsigned long flags;
@@ -258,6 +263,8 @@ static void bgpio_set_set(struct gpio_chip *gc, unsigned int gpio, int val)
gc->write_reg(gc->reg_set, gc->bgpio_data);
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
+
+ return 0;
}
static void bgpio_multiple_get_masks(struct gpio_chip *gc,
@@ -298,21 +305,25 @@ static void bgpio_set_multiple_single_reg(struct gpio_chip *gc,
raw_spin_unlock_irqrestore(&gc->bgpio_lock, flags);
}
-static void bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
+static int bgpio_set_multiple(struct gpio_chip *gc, unsigned long *mask,
unsigned long *bits)
{
bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_dat);
+
+ return 0;
}
-static void bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
- unsigned long *bits)
+static int bgpio_set_multiple_set(struct gpio_chip *gc, unsigned long *mask,
+ unsigned long *bits)
{
bgpio_set_multiple_single_reg(gc, mask, bits, gc->reg_set);
+
+ return 0;
}
-static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
- unsigned long *mask,
- unsigned long *bits)
+static int bgpio_set_multiple_with_clear(struct gpio_chip *gc,
+ unsigned long *mask,
+ unsigned long *bits)
{
unsigned long set_mask, clear_mask;
@@ -322,6 +333,8 @@ static void bgpio_set_multiple_with_clear(struct gpio_chip *gc,
gc->write_reg(gc->reg_set, set_mask);
if (clear_mask)
gc->write_reg(gc->reg_clr, clear_mask);
+
+ return 0;
}
static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_out)
@@ -335,6 +348,11 @@ static int bgpio_dir_return(struct gpio_chip *gc, unsigned int gpio, bool dir_ou
return pinctrl_gpio_direction_input(gc, gpio);
}
+static int bgpio_dir_in_err(struct gpio_chip *gc, unsigned int gpio)
+{
+ return -EINVAL;
+}
+
static int bgpio_simple_dir_in(struct gpio_chip *gc, unsigned int gpio)
{
return bgpio_dir_return(gc, gpio, false);
@@ -349,7 +367,7 @@ static int bgpio_dir_out_err(struct gpio_chip *gc, unsigned int gpio,
static int bgpio_simple_dir_out(struct gpio_chip *gc, unsigned int gpio,
int val)
{
- gc->set(gc, gpio, val);
+ gc->set_rv(gc, gpio, val);
return bgpio_dir_return(gc, gpio, true);
}
@@ -414,14 +432,14 @@ static int bgpio_dir_out_dir_first(struct gpio_chip *gc, unsigned int gpio,
int val)
{
bgpio_dir_out(gc, gpio, val);
- gc->set(gc, gpio, val);
+ gc->set_rv(gc, gpio, val);
return bgpio_dir_return(gc, gpio, true);
}
static int bgpio_dir_out_val_first(struct gpio_chip *gc, unsigned int gpio,
int val)
{
- gc->set(gc, gpio, val);
+ gc->set_rv(gc, gpio, val);
bgpio_dir_out(gc, gpio, val);
return bgpio_dir_return(gc, gpio, true);
}
@@ -510,18 +528,18 @@ static int bgpio_setup_io(struct gpio_chip *gc,
if (set && clr) {
gc->reg_set = set;
gc->reg_clr = clr;
- gc->set = bgpio_set_with_clear;
- gc->set_multiple = bgpio_set_multiple_with_clear;
+ gc->set_rv = bgpio_set_with_clear;
+ gc->set_multiple_rv = bgpio_set_multiple_with_clear;
} else if (set && !clr) {
gc->reg_set = set;
- gc->set = bgpio_set_set;
- gc->set_multiple = bgpio_set_multiple_set;
+ gc->set_rv = bgpio_set_set;
+ gc->set_multiple_rv = bgpio_set_multiple_set;
} else if (flags & BGPIOF_NO_OUTPUT) {
- gc->set = bgpio_set_none;
- gc->set_multiple = NULL;
+ gc->set_rv = bgpio_set_none;
+ gc->set_multiple_rv = NULL;
} else {
- gc->set = bgpio_set;
- gc->set_multiple = bgpio_set_multiple;
+ gc->set_rv = bgpio_set;
+ gc->set_multiple_rv = bgpio_set_multiple;
}
if (!(flags & BGPIOF_UNREADABLE_REG_SET) &&
@@ -566,7 +584,11 @@ static int bgpio_setup_direction(struct gpio_chip *gc,
gc->direction_output = bgpio_dir_out_err;
else
gc->direction_output = bgpio_simple_dir_out;
- gc->direction_input = bgpio_simple_dir_in;
+
+ if (flags & BGPIOF_NO_INPUT)
+ gc->direction_input = bgpio_dir_in_err;
+ else
+ gc->direction_input = bgpio_simple_dir_in;
}
return 0;
@@ -654,7 +676,7 @@ int bgpio_init(struct gpio_chip *gc, struct device *dev,
}
gc->bgpio_data = gc->read_reg(gc->reg_dat);
- if (gc->set == bgpio_set_set &&
+ if (gc->set_rv == bgpio_set_set &&
!(flags & BGPIOF_UNREADABLE_REG_SET))
gc->bgpio_data = gc->read_reg(gc->reg_set);
@@ -712,28 +734,6 @@ static const struct of_device_id bgpio_of_match[] = {
};
MODULE_DEVICE_TABLE(of, bgpio_of_match);
-static struct bgpio_pdata *bgpio_parse_fw(struct device *dev, unsigned long *flags)
-{
- struct bgpio_pdata *pdata;
-
- if (!dev_fwnode(dev))
- return NULL;
-
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return ERR_PTR(-ENOMEM);
-
- pdata->base = -1;
-
- if (device_is_big_endian(dev))
- *flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
-
- if (device_property_read_bool(dev, "no-output"))
- *flags |= BGPIOF_NO_OUTPUT;
-
- return pdata;
-}
-
static int bgpio_pdev_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -745,18 +745,10 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
void __iomem *dirin;
unsigned long sz;
unsigned long flags = 0;
+ unsigned int base;
int err;
struct gpio_chip *gc;
- struct bgpio_pdata *pdata;
-
- pdata = bgpio_parse_fw(dev, &flags);
- if (IS_ERR(pdata))
- return PTR_ERR(pdata);
-
- if (!pdata) {
- pdata = dev_get_platdata(dev);
- flags = pdev->id_entry->driver_data;
- }
+ const char *label;
r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dat");
if (!r)
@@ -788,17 +780,27 @@ static int bgpio_pdev_probe(struct platform_device *pdev)
if (!gc)
return -ENOMEM;
+ if (device_is_big_endian(dev))
+ flags |= BGPIOF_BIG_ENDIAN_BYTE_ORDER;
+
+ if (device_property_read_bool(dev, "no-output"))
+ flags |= BGPIOF_NO_OUTPUT;
+
err = bgpio_init(gc, dev, sz, dat, set, clr, dirout, dirin, flags);
if (err)
return err;
- if (pdata) {
- if (pdata->label)
- gc->label = pdata->label;
- gc->base = pdata->base;
- if (pdata->ngpio > 0)
- gc->ngpio = pdata->ngpio;
- }
+ err = device_property_read_string(dev, "label", &label);
+ if (!err)
+ gc->label = label;
+
+ /*
+ * This property *must not* be used in device-tree sources, it's only
+ * meant to be passed to the driver from board files and MFD core.
+ */
+ err = device_property_read_u32(dev, "gpio-mmio,base", &base);
+ if (!err && base <= INT_MAX)
+ gc->base = base;
platform_set_drvdata(pdev, gc);
@@ -809,9 +811,6 @@ static const struct platform_device_id bgpio_id_table[] = {
{
.name = "basic-mmio-gpio",
.driver_data = 0,
- }, {
- .name = "basic-mmio-gpio-be",
- .driver_data = BGPIOF_BIG_ENDIAN,
},
{ }
};