aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pinctrl/pinctrl-samsung.c117
-rw-r--r--drivers/pinctrl/pinctrl-samsung.h11
2 files changed, 79 insertions, 49 deletions
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c
index e1ef5d28094d..0a38368edcd3 100644
--- a/drivers/pinctrl/pinctrl-samsung.c
+++ b/drivers/pinctrl/pinctrl-samsung.c
@@ -48,6 +48,11 @@ struct pin_config {
48 48
49static unsigned int pin_base = 0; 49static unsigned int pin_base = 0;
50 50
51static inline struct samsung_pin_bank *gc_to_pin_bank(struct gpio_chip *gc)
52{
53 return container_of(gc, struct samsung_pin_bank, gpio_chip);
54}
55
51/* check if the selector is a valid pin group selector */ 56/* check if the selector is a valid pin group selector */
52static int samsung_get_group_count(struct pinctrl_dev *pctldev) 57static int samsung_get_group_count(struct pinctrl_dev *pctldev)
53{ 58{
@@ -333,9 +338,12 @@ static int samsung_pinmux_gpio_set_direction(struct pinctrl_dev *pctldev,
333 void __iomem *reg; 338 void __iomem *reg;
334 u32 data, pin_offset, mask, shift; 339 u32 data, pin_offset, mask, shift;
335 340
341 bank = gc_to_pin_bank(range->gc);
336 drvdata = pinctrl_dev_get_drvdata(pctldev); 342 drvdata = pinctrl_dev_get_drvdata(pctldev);
337 343
338 pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, &bank); 344 pin_offset = offset - bank->pin_base;
345 reg = drvdata->virt_base + bank->pctl_offset;
346
339 mask = (1 << bank->func_width) - 1; 347 mask = (1 << bank->func_width) - 1;
340 shift = pin_offset * bank->func_width; 348 shift = pin_offset * bank->func_width;
341 349
@@ -469,17 +477,16 @@ static struct pinconf_ops samsung_pinconf_ops = {
469/* gpiolib gpio_set callback function */ 477/* gpiolib gpio_set callback function */
470static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value) 478static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
471{ 479{
480 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
472 void __iomem *reg; 481 void __iomem *reg;
473 u32 pin_offset, data; 482 u32 data;
474 struct samsung_pinctrl_drv_data *drvdata;
475 483
476 drvdata = dev_get_drvdata(gc->dev); 484 reg = bank->drvdata->virt_base + bank->pctl_offset;
477 485
478 pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, NULL);
479 data = readl(reg + DAT_REG); 486 data = readl(reg + DAT_REG);
480 data &= ~(1 << pin_offset); 487 data &= ~(1 << offset);
481 if (value) 488 if (value)
482 data |= 1 << pin_offset; 489 data |= 1 << offset;
483 writel(data, reg + DAT_REG); 490 writel(data, reg + DAT_REG);
484} 491}
485 492
@@ -487,14 +494,13 @@ static void samsung_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
487static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset) 494static int samsung_gpio_get(struct gpio_chip *gc, unsigned offset)
488{ 495{
489 void __iomem *reg; 496 void __iomem *reg;
490 u32 pin_offset, data; 497 u32 data;
491 struct samsung_pinctrl_drv_data *drvdata; 498 struct samsung_pin_bank *bank = gc_to_pin_bank(gc);
492 499
493 drvdata = dev_get_drvdata(gc->dev); 500 reg = bank->drvdata->virt_base + bank->pctl_offset;
494 501
495 pin_to_reg_bank(drvdata, offset, &reg, &pin_offset, NULL);
496 data = readl(reg + DAT_REG); 502 data = readl(reg + DAT_REG);
497 data >>= pin_offset; 503 data >>= offset;
498 data &= 1; 504 data &= 1;
499 return data; 505 return data;
500} 506}
@@ -724,12 +730,16 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,
724 return -EINVAL; 730 return -EINVAL;
725 } 731 }
726 732
727 drvdata->grange.name = "samsung-pctrl-gpio-range"; 733 for (bank = 0; bank < drvdata->ctrl->nr_banks; ++bank) {
728 drvdata->grange.id = 0; 734 pin_bank = &drvdata->ctrl->pin_banks[bank];
729 drvdata->grange.base = drvdata->ctrl->base; 735 pin_bank->grange.name = pin_bank->name;
730 drvdata->grange.npins = drvdata->ctrl->nr_pins; 736 pin_bank->grange.id = bank;
731 drvdata->grange.gc = drvdata->gc; 737 pin_bank->grange.pin_base = pin_bank->pin_base;
732 pinctrl_add_gpio_range(drvdata->pctl_dev, &drvdata->grange); 738 pin_bank->grange.base = pin_bank->gpio_chip.base;
739 pin_bank->grange.npins = pin_bank->gpio_chip.ngpio;
740 pin_bank->grange.gc = &pin_bank->gpio_chip;
741 pinctrl_add_gpio_range(drvdata->pctl_dev, &pin_bank->grange);
742 }
733 743
734 ret = samsung_pinctrl_parse_dt(pdev, drvdata); 744 ret = samsung_pinctrl_parse_dt(pdev, drvdata);
735 if (ret) { 745 if (ret) {
@@ -740,49 +750,68 @@ static int __init samsung_pinctrl_register(struct platform_device *pdev,
740 return 0; 750 return 0;
741} 751}
742 752
753static const struct gpio_chip samsung_gpiolib_chip = {
754 .set = samsung_gpio_set,
755 .get = samsung_gpio_get,
756 .direction_input = samsung_gpio_direction_input,
757 .direction_output = samsung_gpio_direction_output,
758 .owner = THIS_MODULE,
759};
760
743/* register the gpiolib interface with the gpiolib subsystem */ 761/* register the gpiolib interface with the gpiolib subsystem */
744static int __init samsung_gpiolib_register(struct platform_device *pdev, 762static int __init samsung_gpiolib_register(struct platform_device *pdev,
745 struct samsung_pinctrl_drv_data *drvdata) 763 struct samsung_pinctrl_drv_data *drvdata)
746{ 764{
765 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
766 struct samsung_pin_bank *bank = ctrl->pin_banks;
747 struct gpio_chip *gc; 767 struct gpio_chip *gc;
748 int ret; 768 int ret;
769 int i;
749 770
750 gc = devm_kzalloc(&pdev->dev, sizeof(*gc), GFP_KERNEL); 771 for (i = 0; i < ctrl->nr_banks; ++i, ++bank) {
751 if (!gc) { 772 bank->gpio_chip = samsung_gpiolib_chip;
752 dev_err(&pdev->dev, "mem alloc for gpio_chip failed\n"); 773
753 return -ENOMEM; 774 gc = &bank->gpio_chip;
754 } 775 gc->base = ctrl->base + bank->pin_base;
755 776 gc->ngpio = bank->nr_pins;
756 drvdata->gc = gc; 777 gc->dev = &pdev->dev;
757 gc->base = drvdata->ctrl->base; 778 gc->of_node = bank->of_node;
758 gc->ngpio = drvdata->ctrl->nr_pins; 779 gc->label = bank->name;
759 gc->dev = &pdev->dev; 780
760 gc->set = samsung_gpio_set; 781 ret = gpiochip_add(gc);
761 gc->get = samsung_gpio_get; 782 if (ret) {
762 gc->direction_input = samsung_gpio_direction_input; 783 dev_err(&pdev->dev, "failed to register gpio_chip %s, error code: %d\n",
763 gc->direction_output = samsung_gpio_direction_output; 784 gc->label, ret);
764 gc->label = drvdata->ctrl->label; 785 goto fail;
765 gc->owner = THIS_MODULE; 786 }
766 ret = gpiochip_add(gc);
767 if (ret) {
768 dev_err(&pdev->dev, "failed to register gpio_chip %s, error "
769 "code: %d\n", gc->label, ret);
770 return ret;
771 } 787 }
772 788
773 return 0; 789 return 0;
790
791fail:
792 for (--i, --bank; i >= 0; --i, --bank)
793 if (gpiochip_remove(&bank->gpio_chip))
794 dev_err(&pdev->dev, "gpio chip %s remove failed\n",
795 bank->gpio_chip.label);
796 return ret;
774} 797}
775 798
776/* unregister the gpiolib interface with the gpiolib subsystem */ 799/* unregister the gpiolib interface with the gpiolib subsystem */
777static int __init samsung_gpiolib_unregister(struct platform_device *pdev, 800static int __init samsung_gpiolib_unregister(struct platform_device *pdev,
778 struct samsung_pinctrl_drv_data *drvdata) 801 struct samsung_pinctrl_drv_data *drvdata)
779{ 802{
780 int ret = gpiochip_remove(drvdata->gc); 803 struct samsung_pin_ctrl *ctrl = drvdata->ctrl;
781 if (ret) { 804 struct samsung_pin_bank *bank = ctrl->pin_banks;
805 int ret = 0;
806 int i;
807
808 for (i = 0; !ret && i < ctrl->nr_banks; ++i, ++bank)
809 ret = gpiochip_remove(&bank->gpio_chip);
810
811 if (ret)
782 dev_err(&pdev->dev, "gpio chip remove failed\n"); 812 dev_err(&pdev->dev, "gpio chip remove failed\n");
783 return ret; 813
784 } 814 return ret;
785 return 0;
786} 815}
787 816
788static const struct of_device_id samsung_pinctrl_dt_match[]; 817static const struct of_device_id samsung_pinctrl_dt_match[];
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h
index e56be22302cd..dac40ffd5e67 100644
--- a/drivers/pinctrl/pinctrl-samsung.h
+++ b/drivers/pinctrl/pinctrl-samsung.h
@@ -23,6 +23,8 @@
23#include <linux/pinctrl/consumer.h> 23#include <linux/pinctrl/consumer.h>
24#include <linux/pinctrl/machine.h> 24#include <linux/pinctrl/machine.h>
25 25
26#include <linux/gpio.h>
27
26/* register offsets within a pin bank */ 28/* register offsets within a pin bank */
27#define DAT_REG 0x4 29#define DAT_REG 0x4
28#define PUD_REG 0x8 30#define PUD_REG 0x8
@@ -113,6 +115,8 @@ struct samsung_pinctrl_drv_data;
113 * @of_node: OF node of the bank. 115 * @of_node: OF node of the bank.
114 * @drvdata: link to controller driver data 116 * @drvdata: link to controller driver data
115 * @irq_domain: IRQ domain of the bank. 117 * @irq_domain: IRQ domain of the bank.
118 * @gpio_chip: GPIO chip of the bank.
119 * @grange: linux gpio pin range supported by this bank.
116 */ 120 */
117struct samsung_pin_bank { 121struct samsung_pin_bank {
118 u32 pctl_offset; 122 u32 pctl_offset;
@@ -129,6 +133,8 @@ struct samsung_pin_bank {
129 struct device_node *of_node; 133 struct device_node *of_node;
130 struct samsung_pinctrl_drv_data *drvdata; 134 struct samsung_pinctrl_drv_data *drvdata;
131 struct irq_domain *irq_domain; 135 struct irq_domain *irq_domain;
136 struct gpio_chip gpio_chip;
137 struct pinctrl_gpio_range grange;
132}; 138};
133 139
134/** 140/**
@@ -186,8 +192,6 @@ struct samsung_pin_ctrl {
186 * @nr_groups: number of such pin groups. 192 * @nr_groups: number of such pin groups.
187 * @pmx_functions: list of pin functions available to the driver. 193 * @pmx_functions: list of pin functions available to the driver.
188 * @nr_function: number of such pin functions. 194 * @nr_function: number of such pin functions.
189 * @gc: gpio_chip instance registered with gpiolib.
190 * @grange: linux gpio pin range supported by this controller.
191 */ 195 */
192struct samsung_pinctrl_drv_data { 196struct samsung_pinctrl_drv_data {
193 void __iomem *virt_base; 197 void __iomem *virt_base;
@@ -204,9 +208,6 @@ struct samsung_pinctrl_drv_data {
204 unsigned int nr_functions; 208 unsigned int nr_functions;
205 209
206 struct irq_domain *wkup_irqd; 210 struct irq_domain *wkup_irqd;
207
208 struct gpio_chip *gc;
209 struct pinctrl_gpio_range grange;
210}; 211};
211 212
212/** 213/**