diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-04 20:22:09 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-04 20:22:09 +0300 |
commit | 88a99886c26fec8bf662e7b6bc080431a8660326 (patch) | |
tree | 615b9a9a959ab093f6d8d0dd94d3bbc5299fc4c6 /drivers/pinctrl/nomadik | |
parent | 8d2faea672606827c2018143ec7d88c760f2d6de (diff) | |
parent | 1ab36387ea4face01aac3560b396b1e2ce07c4ff (diff) | |
download | linux-88a99886c26fec8bf662e7b6bc080431a8660326.tar.xz |
Merge tag 'pinctrl-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij:
"This is the bulk of pin control changes for the v4.3 development
cycle.
Like with GPIO it's a lot of stuff. If my subsystems are any sign of
the overall tempo of the kernel v4.3 will be a gigantic diff.
[ It looks like 4.3 is calmer than 4.2 in most other subsystems, but
we'll see - Linus ]
Core changes:
- It is possible configure groups in debugfs.
- Consolidation of chained IRQ handler install/remove replacing all
call sites where irq_set_handler_data() and
irq_set_chained_handler() were done in succession with a combined
call to irq_set_chained_handler_and_data(). This series was
created by Thomas Gleixner after the problem was observed by
Russell King.
- Tglx also made another series of patches switching
__irq_set_handler_locked() for irq_set_handler_locked() which is
way cleaner.
- Tglx also wrote a good bunch of patches to make use of
irq_desc_get_xxx() accessors and avoid looking up irq_descs from
IRQ numbers. The goal is to get rid of the irq number from the
handlers in the IRQ flow which is nice.
Driver feature enhancements:
- Power management support for the SiRF SoC Atlas 7.
- Power down support for the Qualcomm driver.
- Intel Cherryview and Baytrail: switch drivers to use raw spinlocks
in IRQ handlers to play nice with the realtime patch set.
- Rework and new modes handling for Qualcomm SPMI-MPP.
- Pinconf power source config for SH PFC.
New drivers and subdrivers:
- A new driver for Conexant Digicolor CX92755.
- A new driver for UniPhier PH1-LD4, PH1-Pro4, PH1-sLD8, PH1-Pro5,
ProXtream2 and PH1-LD6b SoC pin control support.
- Reverse-egineered the S/PDIF settings for the Allwinner sun4i
driver.
- Support for Qualcomm Technologies QDF2xxx ARM64 SoCs
- A new Freescale i.mx6ul subdriver.
Cleanup:
- Remove platform data support in a number of SH PFC subdrivers"
* tag 'pinctrl-v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (95 commits)
pinctrl: at91: fix null pointer dereference
pinctrl: mediatek: Implement wake handler and suspend resume
pinctrl: mediatek: Fix multiple registration issue.
pinctrl: sh-pfc: r8a7794: add USB pin groups
pinctrl: at91: Use generic irq_{request,release}_resources()
pinctrl: cherryview: Use raw_spinlock for locking
pinctrl: baytrail: Use raw_spinlock for locking
pinctrl: imx6ul: Remove .owner field
pinctrl: zynq: Fix typos in smc0_nand_grp and smc0_nor_grp
pinctrl: sh-pfc: Implement pinconf power-source param for voltage switching
clk: rockchip: add pclk_pd_pmu to the list of rk3288 critical clocks
pinctrl: sun4i: add spdif to pin description.
pinctrl: atlas7: clear ugly branch statements for pull and drivestrength
pinctrl: baytrail: Serialize all register access
pinctrl: baytrail: Drop FSF mailing address
pinctrl: rockchip: only enable gpio clock when it setting
pinctrl/mediatek: fix spelling mistake in dev_err error message
pinctrl: cherryview: Serialize all register access
pinctrl: UniPhier: PH1-Pro5: add I2C ch6 pin-mux setting
pinctrl: nomadik: reflect current input value
...
Diffstat (limited to 'drivers/pinctrl/nomadik')
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c | 21 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c | 24 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c | 30 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik.c | 241 | ||||
-rw-r--r-- | drivers/pinctrl/nomadik/pinctrl-nomadik.h | 4 |
5 files changed, 147 insertions, 173 deletions
diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c index c74840729648..8392083514fb 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8500.c @@ -355,25 +355,6 @@ static const struct pinctrl_pin_desc nmk_db8500_pins[] = { PINCTRL_PIN(DB8500_PIN_AC27, "GPIO267_AC27"), }; -#define DB8500_GPIO_RANGE(a, b, c) { .name = "DB8500", .id = a, .base = b, \ - .pin_base = b, .npins = c } - -/* - * This matches the 32-pin gpio chips registered by the GPIO portion. This - * cannot be const since we assign the struct gpio_chip * pointer at runtime. - */ -static struct pinctrl_gpio_range nmk_db8500_ranges[] = { - DB8500_GPIO_RANGE(0, 0, 32), - DB8500_GPIO_RANGE(1, 32, 5), - DB8500_GPIO_RANGE(2, 64, 32), - DB8500_GPIO_RANGE(3, 96, 2), - DB8500_GPIO_RANGE(4, 128, 32), - DB8500_GPIO_RANGE(5, 160, 12), - DB8500_GPIO_RANGE(6, 192, 32), - DB8500_GPIO_RANGE(7, 224, 7), - DB8500_GPIO_RANGE(8, 256, 12), -}; - /* * Read the pin group names like this: * u0_a_1 = first groups of pins for uart0 on alt function a @@ -1238,8 +1219,6 @@ static const u16 db8500_prcm_gpiocr_regs[] = { }; static const struct nmk_pinctrl_soc_data nmk_db8500_soc = { - .gpio_ranges = nmk_db8500_ranges, - .gpio_num_ranges = ARRAY_SIZE(nmk_db8500_ranges), .pins = nmk_db8500_pins, .npins = ARRAY_SIZE(nmk_db8500_pins), .functions = nmk_db8500_functions, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c index d7ba5443bae0..2860eafd1b42 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-db8540.c @@ -341,28 +341,6 @@ static const struct pinctrl_pin_desc nmk_db8540_pins[] = { PINCTRL_PIN(DB8540_PIN_D17, "GPIO267_D17"), }; -#define DB8540_GPIO_RANGE(a, b, c) { .name = "db8540", .id = a, .base = b, \ - .pin_base = b, .npins = c } - -/* - * This matches the 32-pin gpio chips registered by the GPIO portion. This - * cannot be const since we assign the struct gpio_chip * pointer at runtime. - */ -static struct pinctrl_gpio_range nmk_db8540_ranges[] = { - DB8540_GPIO_RANGE(0, 0, 18), - DB8540_GPIO_RANGE(0, 22, 7), - DB8540_GPIO_RANGE(1, 33, 6), - DB8540_GPIO_RANGE(2, 64, 4), - DB8540_GPIO_RANGE(2, 70, 18), - DB8540_GPIO_RANGE(3, 116, 12), - DB8540_GPIO_RANGE(4, 128, 32), - DB8540_GPIO_RANGE(5, 160, 9), - DB8540_GPIO_RANGE(6, 192, 23), - DB8540_GPIO_RANGE(6, 219, 5), - DB8540_GPIO_RANGE(7, 224, 9), - DB8540_GPIO_RANGE(8, 256, 12), -}; - /* * Read the pin group names like this: * u0_a_1 = first groups of pins for uart0 on alt function a @@ -1247,8 +1225,6 @@ static const u16 db8540_prcm_gpiocr_regs[] = { }; static const struct nmk_pinctrl_soc_data nmk_db8540_soc = { - .gpio_ranges = nmk_db8540_ranges, - .gpio_num_ranges = ARRAY_SIZE(nmk_db8540_ranges), .pins = nmk_db8540_pins, .npins = ARRAY_SIZE(nmk_db8540_pins), .functions = nmk_db8540_functions, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c index 2cd71470f270..587b222f12f3 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik-stn8815.c @@ -264,20 +264,6 @@ static const struct pinctrl_pin_desc nmk_stn8815_pins[] = { PINCTRL_PIN(STN8815_PIN_J22, "GPIO123_J22"), }; -#define STN8815_GPIO_RANGE(a, b, c) { .name = "STN8815", .id = a, .base = b, \ - .pin_base = b, .npins = c } - -/* - * This matches the 32-pin gpio chips registered by the GPIO portion. This - * cannot be const since we assign the struct gpio_chip * pointer at runtime. - */ -static struct pinctrl_gpio_range nmk_stn8815_ranges[] = { - STN8815_GPIO_RANGE(0, 0, 32), - STN8815_GPIO_RANGE(1, 32, 32), - STN8815_GPIO_RANGE(2, 64, 32), - STN8815_GPIO_RANGE(3, 96, 28), -}; - /* * Read the pin group names like this: * u0_a_1 = first groups of pins for uart0 on alt function a @@ -285,9 +271,11 @@ static struct pinctrl_gpio_range nmk_stn8815_ranges[] = { */ /* Altfunction A */ -static const unsigned u0_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5, - STN8815_PIN_C5, STN8815_PIN_A4, STN8815_PIN_B5, STN8815_PIN_D6, - STN8815_PIN_C6, STN8815_PIN_B6 }; +static const unsigned u0txrx_a_1_pins[] = { STN8815_PIN_B4, STN8815_PIN_D5 }; +static const unsigned u0ctsrts_a_1_pins[] = { STN8815_PIN_C5, STN8815_PIN_B6 }; +/* Modem pins: DCD, DSR, RI, DTR */ +static const unsigned u0modem_a_1_pins[] = { STN8815_PIN_A4, STN8815_PIN_B5, + STN8815_PIN_D6, STN8815_PIN_C6 }; static const unsigned mmcsd_a_1_pins[] = { STN8815_PIN_B10, STN8815_PIN_A10, STN8815_PIN_C11, STN8815_PIN_B11, STN8815_PIN_A11, STN8815_PIN_C12, STN8815_PIN_B12, STN8815_PIN_A12, STN8815_PIN_C13, STN8815_PIN_C15 }; @@ -304,7 +292,9 @@ static const unsigned i2cusb_b_1_pins[] = { STN8815_PIN_C21, STN8815_PIN_C20 }; .npins = ARRAY_SIZE(a##_pins), .altsetting = b } static const struct nmk_pingroup nmk_stn8815_groups[] = { - STN8815_PIN_GROUP(u0_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(u0txrx_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(u0ctsrts_a_1, NMK_GPIO_ALT_A), + STN8815_PIN_GROUP(u0modem_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(mmcsd_a_1, NMK_GPIO_ALT_A), STN8815_PIN_GROUP(mmcsd_b_1, NMK_GPIO_ALT_B), STN8815_PIN_GROUP(u1_a_1, NMK_GPIO_ALT_A), @@ -318,7 +308,7 @@ static const struct nmk_pingroup nmk_stn8815_groups[] = { #define STN8815_FUNC_GROUPS(a, b...) \ static const char * const a##_groups[] = { b }; -STN8815_FUNC_GROUPS(u0, "u0_a_1"); +STN8815_FUNC_GROUPS(u0, "u0txrx_a_1", "u0ctsrts_a_1", "u0modem_a_1"); STN8815_FUNC_GROUPS(mmcsd, "mmcsd_a_1", "mmcsd_b_1"); STN8815_FUNC_GROUPS(u1, "u1_a_1", "u1_b_1"); STN8815_FUNC_GROUPS(i2c1, "i2c1_a_1"); @@ -342,8 +332,6 @@ static const struct nmk_function nmk_stn8815_functions[] = { }; static const struct nmk_pinctrl_soc_data nmk_stn8815_soc = { - .gpio_ranges = nmk_stn8815_ranges, - .gpio_num_ranges = ARRAY_SIZE(nmk_stn8815_ranges), .pins = nmk_stn8815_pins, .npins = ARRAY_SIZE(nmk_stn8815_pins), .functions = nmk_stn8815_functions, diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.c b/drivers/pinctrl/nomadik/pinctrl-nomadik.c index 809d88445db5..352ede13a9e9 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.c +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.c @@ -203,6 +203,7 @@ typedef unsigned long pin_cfg_t; #define GPIO_BLOCK_SHIFT 5 #define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) +#define NMK_MAX_BANKS DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP) /* Register in the logic block */ #define NMK_GPIO_DAT 0x00 @@ -282,8 +283,7 @@ struct nmk_pinctrl { void __iomem *prcm_base; }; -static struct nmk_gpio_chip * -nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)]; +static struct nmk_gpio_chip *nmk_gpio_chips[NMK_MAX_BANKS]; static DEFINE_SPINLOCK(nmk_gpio_slpm_lock); @@ -843,10 +843,9 @@ static void nmk_gpio_irq_shutdown(struct irq_data *d) clk_disable(nmk_chip->clk); } -static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc, - u32 status) +static void __nmk_gpio_irq_handler(struct irq_desc *desc, u32 status) { - struct irq_chip *host_chip = irq_get_chip(irq); + struct irq_chip *host_chip = irq_desc_get_chip(desc); struct gpio_chip *chip = irq_desc_get_handler_data(desc); chained_irq_enter(host_chip, desc); @@ -871,17 +870,16 @@ static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc) status = readl(nmk_chip->addr + NMK_GPIO_IS); clk_disable(nmk_chip->clk); - __nmk_gpio_irq_handler(irq, desc, status); + __nmk_gpio_irq_handler(desc, status); } -static void nmk_gpio_latent_irq_handler(unsigned int irq, - struct irq_desc *desc) +static void nmk_gpio_latent_irq_handler(unsigned int irq, struct irq_desc *desc) { struct gpio_chip *chip = irq_desc_get_handler_data(desc); struct nmk_gpio_chip *nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); u32 status = nmk_chip->get_latent_status(nmk_chip->bank); - __nmk_gpio_irq_handler(irq, desc, status); + __nmk_gpio_irq_handler(desc, status); } /* I/O Functions */ @@ -1012,6 +1010,7 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, int irq = gpio_to_irq(gpio); struct irq_desc *desc = irq_to_desc(irq); int pullidx = 0; + int val; if (pull) pullidx = data_out ? 1 : 2; @@ -1021,6 +1020,10 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, label ?: "(none)", pulls[pullidx], (mode < 0) ? "unknown" : modes[mode]); + + val = nmk_gpio_get_input(chip, offset); + seq_printf(s, " VAL %d", val); + /* * This races with request_irq(), set_irq_type(), * and set_irq_wake() ... but those are "rare". @@ -1162,29 +1165,90 @@ void nmk_gpio_read_pull(int gpio_bank, u32 *pull_up) } } +/* + * We will allocate memory for the state container using devm* allocators + * binding to the first device reaching this point, it doesn't matter if + * it is the pin controller or GPIO driver. However we need to use the right + * platform device when looking up resources so pay attention to pdev. + */ +static struct nmk_gpio_chip *nmk_gpio_populate_chip(struct device_node *np, + struct platform_device *pdev) +{ + struct nmk_gpio_chip *nmk_chip; + struct platform_device *gpio_pdev; + struct gpio_chip *chip; + struct resource *res; + struct clk *clk; + void __iomem *base; + u32 id; + + gpio_pdev = of_find_device_by_node(np); + if (!gpio_pdev) { + pr_err("populate \"%s\": device not found\n", np->name); + return ERR_PTR(-ENODEV); + } + if (of_property_read_u32(np, "gpio-bank", &id)) { + dev_err(&pdev->dev, "populate: gpio-bank property not found\n"); + return ERR_PTR(-EINVAL); + } + + /* Already populated? */ + nmk_chip = nmk_gpio_chips[id]; + if (nmk_chip) + return nmk_chip; + + nmk_chip = devm_kzalloc(&pdev->dev, sizeof(*nmk_chip), GFP_KERNEL); + if (!nmk_chip) + return ERR_PTR(-ENOMEM); + + nmk_chip->bank = id; + chip = &nmk_chip->chip; + chip->base = id * NMK_GPIO_PER_CHIP; + chip->ngpio = NMK_GPIO_PER_CHIP; + chip->label = dev_name(&gpio_pdev->dev); + chip->dev = &gpio_pdev->dev; + + res = platform_get_resource(gpio_pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return base; + nmk_chip->addr = base; + + clk = clk_get(&gpio_pdev->dev, NULL); + if (IS_ERR(clk)) + return (void *) clk; + clk_prepare(clk); + nmk_chip->clk = clk; + + BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); + nmk_gpio_chips[id] = nmk_chip; + return nmk_chip; +} + static int nmk_gpio_probe(struct platform_device *dev) { struct device_node *np = dev->dev.of_node; struct nmk_gpio_chip *nmk_chip; struct gpio_chip *chip; struct irq_chip *irqchip; - struct resource *res; - struct clk *clk; int latent_irq; bool supports_sleepmode; - void __iomem *base; int irq; int ret; + nmk_chip = nmk_gpio_populate_chip(np, dev); + if (IS_ERR(nmk_chip)) { + dev_err(&dev->dev, "could not populate nmk chip struct\n"); + return PTR_ERR(nmk_chip); + } + if (of_get_property(np, "st,supports-sleepmode", NULL)) supports_sleepmode = true; else supports_sleepmode = false; - if (of_property_read_u32(np, "gpio-bank", &dev->id)) { - dev_err(&dev->dev, "gpio-bank property not found\n"); - return -EINVAL; - } + /* Correct platform device ID */ + dev->id = nmk_chip->bank; irq = platform_get_irq(dev, 0); if (irq < 0) @@ -1193,27 +1257,10 @@ static int nmk_gpio_probe(struct platform_device *dev) /* It's OK for this IRQ not to be present */ latent_irq = platform_get_irq(dev, 1); - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(&dev->dev, res); - if (IS_ERR(base)) - return PTR_ERR(base); - - clk = devm_clk_get(&dev->dev, NULL); - if (IS_ERR(clk)) - return PTR_ERR(clk); - clk_prepare(clk); - - nmk_chip = devm_kzalloc(&dev->dev, sizeof(*nmk_chip), GFP_KERNEL); - if (!nmk_chip) - return -ENOMEM; - /* * The virt address in nmk_chip->addr is in the nomadik register space, * so we can simply convert the resource address, without remapping */ - nmk_chip->bank = dev->id; - nmk_chip->clk = clk; - nmk_chip->addr = base; nmk_chip->parent_irq = irq; nmk_chip->latent_parent_irq = latent_irq; nmk_chip->sleepmode = supports_sleepmode; @@ -1228,10 +1275,6 @@ static int nmk_gpio_probe(struct platform_device *dev) chip->set = nmk_gpio_set_output; chip->dbg_show = nmk_gpio_dbg_show; chip->can_sleep = false; - chip->base = dev->id * NMK_GPIO_PER_CHIP; - chip->ngpio = NMK_GPIO_PER_CHIP; - chip->label = dev_name(&dev->dev); - chip->dev = &dev->dev; chip->owner = THIS_MODULE; irqchip = &nmk_chip->irqchip; @@ -1253,14 +1296,10 @@ static int nmk_gpio_probe(struct platform_device *dev) clk_disable(nmk_chip->clk); chip->of_node = np; - ret = gpiochip_add(&nmk_chip->chip); + ret = gpiochip_add(chip); if (ret) return ret; - BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips)); - - nmk_gpio_chips[nmk_chip->bank] = nmk_chip; - platform_set_drvdata(dev, nmk_chip); /* @@ -1320,35 +1359,40 @@ static int nmk_get_group_pins(struct pinctrl_dev *pctldev, unsigned selector, return 0; } -static struct pinctrl_gpio_range * -nmk_match_gpio_range(struct pinctrl_dev *pctldev, unsigned offset) +static struct nmk_gpio_chip *find_nmk_gpio_from_pin(unsigned pin) { - struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); int i; + struct nmk_gpio_chip *nmk_gpio; - for (i = 0; i < npct->soc->gpio_num_ranges; i++) { - struct pinctrl_gpio_range *range; - - range = &npct->soc->gpio_ranges[i]; - if (offset >= range->pin_base && - offset <= (range->pin_base + range->npins - 1)) - return range; + for(i = 0; i < NMK_MAX_BANKS; i++) { + nmk_gpio = nmk_gpio_chips[i]; + if (!nmk_gpio) + continue; + if (pin >= nmk_gpio->chip.base && + pin < nmk_gpio->chip.base + nmk_gpio->chip.ngpio) + return nmk_gpio; } return NULL; } +static struct gpio_chip *find_gc_from_pin(unsigned pin) +{ + struct nmk_gpio_chip *nmk_gpio = find_nmk_gpio_from_pin(pin); + + if (nmk_gpio) + return &nmk_gpio->chip; + return NULL; +} + static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, unsigned offset) { - struct pinctrl_gpio_range *range; - struct gpio_chip *chip; + struct gpio_chip *chip = find_gc_from_pin(offset); - range = nmk_match_gpio_range(pctldev, offset); - if (!range || !range->gc) { + if (!chip) { seq_printf(s, "invalid pin offset"); return; } - chip = range->gc; nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); } @@ -1693,25 +1737,16 @@ static int nmk_pmx_set(struct pinctrl_dev *pctldev, unsigned function, } for (i = 0; i < g->npins; i++) { - struct pinctrl_gpio_range *range; struct nmk_gpio_chip *nmk_chip; - struct gpio_chip *chip; unsigned bit; - range = nmk_match_gpio_range(pctldev, g->pins[i]); - if (!range) { + nmk_chip = find_nmk_gpio_from_pin(g->pins[i]); + if (!nmk_chip) { dev_err(npct->dev, "invalid pin offset %d in group %s at index %d\n", g->pins[i], g->name, i); goto out_glitch; } - if (!range->gc) { - dev_err(npct->dev, "GPIO chip missing in range for pin offset %d in group %s at index %d\n", - g->pins[i], g->name, i); - goto out_glitch; - } - chip = range->gc; - nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); dev_dbg(npct->dev, "setting pin %d to altsetting %d\n", g->pins[i], g->altsetting); clk_enable(nmk_chip->clk); @@ -1827,25 +1862,17 @@ static int nmk_pin_config_set(struct pinctrl_dev *pctldev, unsigned pin, }; struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); struct nmk_gpio_chip *nmk_chip; - struct pinctrl_gpio_range *range; - struct gpio_chip *chip; unsigned bit; pin_cfg_t cfg; int pull, slpm, output, val, i; bool lowemi, gpiomode, sleep; - range = nmk_match_gpio_range(pctldev, pin); - if (!range) { - dev_err(npct->dev, "invalid pin offset %d\n", pin); - return -EINVAL; - } - if (!range->gc) { - dev_err(npct->dev, "GPIO chip missing in range for pin %d\n", - pin); + nmk_chip = find_nmk_gpio_from_pin(pin); + if (!nmk_chip) { + dev_err(npct->dev, + "invalid pin offset %d\n", pin); return -EINVAL; } - chip = range->gc; - nmk_chip = container_of(chip, struct nmk_gpio_chip, chip); for (i = 0; i < num_configs; i++) { /* @@ -1997,6 +2024,31 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) if (version == PINCTRL_NMK_DB8540) nmk_pinctrl_db8540_init(&npct->soc); + /* + * Since we depend on the GPIO chips to provide clock and register base + * for the pin control operations, make sure that we have these + * populated before we continue. Follow the phandles to instantiate + * them. The GPIO portion of the actual hardware may be probed before + * or after this point: it shouldn't matter as the APIs are orthogonal. + */ + for (i = 0; i < NMK_MAX_BANKS; i++) { + struct device_node *gpio_np; + struct nmk_gpio_chip *nmk_chip; + + gpio_np = of_parse_phandle(np, "nomadik-gpio-chips", i); + if (gpio_np) { + dev_info(&pdev->dev, + "populate NMK GPIO %d \"%s\"\n", + i, gpio_np->name); + nmk_chip = nmk_gpio_populate_chip(gpio_np, pdev); + if (IS_ERR(nmk_chip)) + dev_err(&pdev->dev, + "could not populate nmk chip struct " + "- continue anyway\n"); + of_node_put(gpio_np); + } + } + prcm_np = of_parse_phandle(np, "prcm", 0); if (prcm_np) npct->prcm_base = of_iomap(prcm_np, 0); @@ -2011,19 +2063,6 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) } } - /* - * We need all the GPIO drivers to probe FIRST, or we will not be able - * to obtain references to the struct gpio_chip * for them, and we - * need this to proceed. - */ - for (i = 0; i < npct->soc->gpio_num_ranges; i++) { - if (!nmk_gpio_chips[npct->soc->gpio_ranges[i].id]) { - dev_warn(&pdev->dev, "GPIO chip %d not registered yet\n", i); - return -EPROBE_DEFER; - } - npct->soc->gpio_ranges[i].gc = &nmk_gpio_chips[npct->soc->gpio_ranges[i].id]->chip; - } - nmk_pinctrl_desc.pins = npct->soc->pins; nmk_pinctrl_desc.npins = npct->soc->npins; npct->dev = &pdev->dev; @@ -2034,10 +2073,6 @@ static int nmk_pinctrl_probe(struct platform_device *pdev) return PTR_ERR(npct->pctl); } - /* We will handle a range of GPIO pins */ - for (i = 0; i < npct->soc->gpio_num_ranges; i++) - pinctrl_add_gpio_range(npct->pctl, &npct->soc->gpio_ranges[i]); - platform_set_drvdata(pdev, npct); dev_info(&pdev->dev, "initialized Nomadik pin control driver\n"); @@ -2072,15 +2107,15 @@ static struct platform_driver nmk_pinctrl_driver = { static int __init nmk_gpio_init(void) { - int ret; + return platform_driver_register(&nmk_gpio_driver); +} +subsys_initcall(nmk_gpio_init); - ret = platform_driver_register(&nmk_gpio_driver); - if (ret) - return ret; +static int __init nmk_pinctrl_init(void) +{ return platform_driver_register(&nmk_pinctrl_driver); } - -core_initcall(nmk_gpio_init); +core_initcall(nmk_pinctrl_init); MODULE_AUTHOR("Prafulla WADASKAR and Alessandro Rubini"); MODULE_DESCRIPTION("Nomadik GPIO Driver"); diff --git a/drivers/pinctrl/nomadik/pinctrl-nomadik.h b/drivers/pinctrl/nomadik/pinctrl-nomadik.h index d8215f1e70c7..30bba2a75a58 100644 --- a/drivers/pinctrl/nomadik/pinctrl-nomadik.h +++ b/drivers/pinctrl/nomadik/pinctrl-nomadik.h @@ -121,8 +121,6 @@ struct nmk_pingroup { /** * struct nmk_pinctrl_soc_data - Nomadik pin controller per-SoC configuration - * @gpio_ranges: An array of GPIO ranges for this SoC - * @gpio_num_ranges: The number of GPIO ranges for this SoC * @pins: An array describing all pins the pin controller affects. * All pins which are also GPIOs must be listed first within the * array, and be numbered identically to the GPIO controller's @@ -137,8 +135,6 @@ struct nmk_pingroup { * @prcm_gpiocr_registers: The array of PRCM GPIOCR registers on this SoC */ struct nmk_pinctrl_soc_data { - struct pinctrl_gpio_range *gpio_ranges; - unsigned gpio_num_ranges; const struct pinctrl_pin_desc *pins; unsigned npins; const struct nmk_function *functions; |