diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c index bfa1eab91f4142cecb3bdd1ce4c4ec1b8e9a9698..22ef8a1abe0835cc7d0143c9456b984794c10113 100644 --- a/arch/arm/mach-nomadik/board-nhk8815.c +++ b/arch/arm/mach-nomadik/board-nhk8815.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -32,9 +33,7 @@ #include #include -#include #include -#include #include #include diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c index b617eaed0ce58695ac709b460ac29b8ac2d4b1d6..1273931303fb81599201ae0f70c1c71f503b9eda 100644 --- a/arch/arm/mach-nomadik/cpu-8815.c +++ b/arch/arm/mach-nomadik/cpu-8815.c @@ -26,8 +26,8 @@ #include #include #include +#include -#include #include #include #include diff --git a/arch/arm/mach-nomadik/i2c-8815nhk.c b/arch/arm/mach-nomadik/i2c-8815nhk.c index 6d14454d46094fc4bdd00c66cabff3a0abb800f9..0c2f6628299aa6bc2a7c95b567ff56344dd7df87 100644 --- a/arch/arm/mach-nomadik/i2c-8815nhk.c +++ b/arch/arm/mach-nomadik/i2c-8815nhk.c @@ -4,8 +4,7 @@ #include #include #include -#include -#include +#include /* * There are two busses in the 8815NHK. diff --git a/arch/arm/mach-ux500/board-mop500-audio.c b/arch/arm/mach-ux500/board-mop500-audio.c index 070629a95625a9b7f3a5bfd0921d419a779966fc..33631c9f121802d447ecd38fa7f6bee4af955e18 100644 --- a/arch/arm/mach-ux500/board-mop500-audio.c +++ b/arch/arm/mach-ux500/board-mop500-audio.c @@ -7,9 +7,8 @@ #include #include #include +#include -#include -#include #include #include diff --git a/arch/arm/mach-ux500/board-mop500-pins.c b/arch/arm/mach-ux500/board-mop500-pins.c index a267c6d30e374f19c491244ad23fd93b07aa85d1..c34d4efd0d5c46987775b47c1393349760d60c27 100644 --- a/arch/arm/mach-ux500/board-mop500-pins.c +++ b/arch/arm/mach-ux500/board-mop500-pins.c @@ -9,10 +9,9 @@ #include #include #include +#include #include -#include -#include #include diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c index 416d436111f29bbc64c267f104ab2838cf3db0ac..0a3dd601a400c4cddeba32a945d2461bde52797a 100644 --- a/arch/arm/mach-ux500/board-mop500.c +++ b/arch/arm/mach-ux500/board-mop500.c @@ -37,13 +37,13 @@ #include #include #include +#include #include #include #include #include -#include #include #include diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c index bcdfe6b1d4534e72dc952cfa989a98ac57d84b70..113d9c47a8428ffebf8d40e6e2e762de61f80640 100644 --- a/arch/arm/mach-ux500/cpu-db8500.c +++ b/arch/arm/mach-ux500/cpu-db8500.c @@ -17,14 +17,14 @@ #include #include #include +#include +#include #include #include -#include #include #include #include -#include #include #include "devices-db8500.h" @@ -158,7 +158,7 @@ static void __init db8500_add_gpios(struct device *parent) dbx500_add_gpios(parent, ARRAY_AND_SIZE(db8500_gpio_base), IRQ_DB8500_GPIO0, &pdata); - dbx500_add_pinctrl(parent, "pinctrl-db8500"); + dbx500_add_pinctrl(parent, "pinctrl-db8500", U8500_PRCMU_BASE); } static int usb_db8500_rx_dma_cfg[] = { diff --git a/arch/arm/mach-ux500/devices-common.c b/arch/arm/mach-ux500/devices-common.c index dfdd4a54668dfb4c85dfdb9a703f714b40a69bdc..692a77a1c1536eb045b714559b17d0e68aac78de 100644 --- a/arch/arm/mach-ux500/devices-common.c +++ b/arch/arm/mach-ux500/devices-common.c @@ -11,8 +11,7 @@ #include #include #include - -#include +#include #include diff --git a/arch/arm/mach-ux500/devices-common.h b/arch/arm/mach-ux500/devices-common.h index 7fbf0ba336e1bba5e5f92cd2a0945ec411e5c5e6..96fa4ac89e2ecbee38e672dd8858679c7e09134c 100644 --- a/arch/arm/mach-ux500/devices-common.h +++ b/arch/arm/mach-ux500/devices-common.h @@ -129,12 +129,18 @@ void dbx500_add_gpios(struct device *parent, resource_size_t *base, int num, int irq, struct nmk_gpio_platform_data *pdata); static inline void -dbx500_add_pinctrl(struct device *parent, const char *name) +dbx500_add_pinctrl(struct device *parent, const char *name, + resource_size_t base) { + struct resource res[] = { + DEFINE_RES_MEM(base, SZ_8K), + }; struct platform_device_info pdevinfo = { .parent = parent, .name = name, .id = -1, + .res = res, + .num_res = ARRAY_SIZE(res), }; platform_device_register_full(&pdevinfo); diff --git a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h b/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h deleted file mode 100644 index c08a54d9d8897dd686462787d8d205206e00da84..0000000000000000000000000000000000000000 --- a/arch/arm/plat-nomadik/include/plat/gpio-nomadik.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Structures and registers for GPIO access in the Nomadik SoC - * - * Copyright (C) 2008 STMicroelectronics - * Author: Prafulla WADASKAR - * Copyright (C) 2009 Alessandro Rubini - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef __PLAT_NOMADIK_GPIO -#define __PLAT_NOMADIK_GPIO - -/* - * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving - * the "gpio" namespace for generic and cross-machine functions - */ - -/* Register in the logic block */ -#define NMK_GPIO_DAT 0x00 -#define NMK_GPIO_DATS 0x04 -#define NMK_GPIO_DATC 0x08 -#define NMK_GPIO_PDIS 0x0c -#define NMK_GPIO_DIR 0x10 -#define NMK_GPIO_DIRS 0x14 -#define NMK_GPIO_DIRC 0x18 -#define NMK_GPIO_SLPC 0x1c -#define NMK_GPIO_AFSLA 0x20 -#define NMK_GPIO_AFSLB 0x24 -#define NMK_GPIO_LOWEMI 0x28 - -#define NMK_GPIO_RIMSC 0x40 -#define NMK_GPIO_FIMSC 0x44 -#define NMK_GPIO_IS 0x48 -#define NMK_GPIO_IC 0x4c -#define NMK_GPIO_RWIMSC 0x50 -#define NMK_GPIO_FWIMSC 0x54 -#define NMK_GPIO_WKS 0x58 - -/* Alternate functions: function C is set in hw by setting both A and B */ -#define NMK_GPIO_ALT_GPIO 0 -#define NMK_GPIO_ALT_A 1 -#define NMK_GPIO_ALT_B 2 -#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) - -#define NMK_GPIO_ALT_CX_SHIFT 2 -#define NMK_GPIO_ALT_C1 ((1< /* Since we request GPIOs from ourself */ #include -/* - * For the U8500 archs, use the PRCMU register interface, for the older - * Nomadik, provide some stubs. The functions using these will only be - * called on the U8500 series. - */ -#ifdef CONFIG_ARCH_U8500 -#include -#else -static inline u32 prcmu_read(unsigned int reg) { - return 0; -} -static inline void prcmu_write(unsigned int reg, u32 value) {} -static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} -#endif +#include #include -#include -#include - #include "pinctrl-nomadik.h" /* @@ -60,8 +44,6 @@ static inline void prcmu_write_masked(unsigned int reg, u32 mask, u32 value) {} * Symbols in this file are called "nmk_gpio" for "nomadik gpio" */ -#define NMK_GPIO_PER_CHIP 32 - struct nmk_gpio_chip { struct gpio_chip chip; struct irq_domain *domain; @@ -86,10 +68,18 @@ struct nmk_gpio_chip { u32 lowemi; }; +/** + * struct nmk_pinctrl - state container for the Nomadik pin controller + * @dev: containing device pointer + * @pctl: corresponding pin controller device + * @soc: SoC data for this specific chip + * @prcm_base: PRCM register range virtual base + */ struct nmk_pinctrl { struct device *dev; struct pinctrl_dev *pctl; const struct nmk_pinctrl_soc_data *soc; + void __iomem *prcm_base; }; static struct nmk_gpio_chip * @@ -251,6 +241,15 @@ nmk_gpio_disable_lazy_irq(struct nmk_gpio_chip *nmk_chip, unsigned offset) dev_dbg(nmk_chip->chip.dev, "%d: clearing interrupt mask\n", gpio); } +static void nmk_write_masked(void __iomem *reg, u32 mask, u32 value) +{ + u32 val; + + val = readl(reg); + val = ((val & ~mask) | (value & mask)); + writel(val, reg); +} + static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, unsigned offset, unsigned alt_num) { @@ -289,8 +288,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, if (pin_desc->altcx[i].used == true) { reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; bit = pin_desc->altcx[i].control_bit; - if (prcmu_read(reg) & BIT(bit)) { - prcmu_write_masked(reg, BIT(bit), 0); + if (readl(npct->prcm_base + reg) & BIT(bit)) { + nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0); dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n", offset, i+1); @@ -318,8 +317,8 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, if (pin_desc->altcx[i].used == true) { reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; bit = pin_desc->altcx[i].control_bit; - if (prcmu_read(reg) & BIT(bit)) { - prcmu_write_masked(reg, BIT(bit), 0); + if (readl(npct->prcm_base + reg) & BIT(bit)) { + nmk_write_masked(npct->prcm_base + reg, BIT(bit), 0); dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been disabled\n", offset, i+1); @@ -331,7 +330,7 @@ static void nmk_prcm_altcx_set_mode(struct nmk_pinctrl *npct, bit = pin_desc->altcx[alt_index].control_bit; dev_dbg(npct->dev, "PRCM GPIOCR: pin %i: alternate-C%i has been selected\n", offset, alt_index+1); - prcmu_write_masked(reg, BIT(bit), BIT(bit)); + nmk_write_masked(npct->prcm_base + reg, BIT(bit), BIT(bit)); } static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset, @@ -536,7 +535,7 @@ static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep) * and its sleep mode based on the specified configuration. The @cfg is * usually one of the SoC specific macros defined in mach/-pins.h. These * are constructed using, and can be further enhanced with, the macros in - * plat/pincfg.h. + * * * If a pin's mode is set to GPIO, it is configured as an input to avoid * side-effects. The gpio can be manipulated later using standard GPIO API @@ -675,6 +674,35 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) } EXPORT_SYMBOL(nmk_gpio_set_mode); +static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) +{ + int i; + u16 reg; + u8 bit; + struct nmk_pinctrl *npct = pinctrl_dev_get_drvdata(pctldev); + const struct prcm_gpiocr_altcx_pin_desc *pin_desc; + const u16 *gpiocr_regs; + + for (i = 0; i < npct->soc->npins_altcx; i++) { + if (npct->soc->altcx_pins[i].pin == gpio) + break; + } + if (i == npct->soc->npins_altcx) + return NMK_GPIO_ALT_C; + + pin_desc = npct->soc->altcx_pins + i; + gpiocr_regs = npct->soc->prcm_gpiocr_registers; + for (i = 0; i < PRCM_IDX_GPIOCR_ALTC_MAX; i++) { + if (pin_desc->altcx[i].used == true) { + reg = gpiocr_regs[pin_desc->altcx[i].reg_index]; + bit = pin_desc->altcx[i].control_bit; + if (readl(npct->prcm_base + reg) & BIT(bit)) + return NMK_GPIO_ALT_C+i+1; + } + } + return NMK_GPIO_ALT_C; +} + int nmk_gpio_get_mode(int gpio) { struct nmk_gpio_chip *nmk_chip; @@ -1063,8 +1091,9 @@ static int nmk_gpio_to_irq(struct gpio_chip *chip, unsigned offset) #include -static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip, - unsigned offset, unsigned gpio) +static void nmk_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, struct gpio_chip *chip, + unsigned offset, unsigned gpio) { const char *label = gpiochip_is_requested(chip, offset); struct nmk_gpio_chip *nmk_chip = @@ -1078,12 +1107,18 @@ static void nmk_gpio_dbg_show_one(struct seq_file *s, struct gpio_chip *chip, [NMK_GPIO_ALT_A] = "altA", [NMK_GPIO_ALT_B] = "altB", [NMK_GPIO_ALT_C] = "altC", + [NMK_GPIO_ALT_C+1] = "altC1", + [NMK_GPIO_ALT_C+2] = "altC2", + [NMK_GPIO_ALT_C+3] = "altC3", + [NMK_GPIO_ALT_C+4] = "altC4", }; clk_enable(nmk_chip->clk); is_out = !!(readl(nmk_chip->addr + NMK_GPIO_DIR) & bit); pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit); mode = nmk_gpio_get_mode(gpio); + if ((mode == NMK_GPIO_ALT_C) && pctldev) + mode = nmk_prcm_gpiocr_get_mode(pctldev, gpio); seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s", gpio, label ?: "(none)", @@ -1127,13 +1162,14 @@ static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip) unsigned gpio = chip->base; for (i = 0; i < chip->ngpio; i++, gpio++) { - nmk_gpio_dbg_show_one(s, chip, i, gpio); + nmk_gpio_dbg_show_one(s, NULL, chip, i, gpio); seq_printf(s, "\n"); } } #else static inline void nmk_gpio_dbg_show_one(struct seq_file *s, + struct pinctrl_dev *pctldev, struct gpio_chip *chip, unsigned offset, unsigned gpio) { @@ -1464,7 +1500,7 @@ static void nmk_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s, return; } chip = range->gc; - nmk_gpio_dbg_show_one(s, chip, offset - chip->base, offset); + nmk_gpio_dbg_show_one(s, pctldev, chip, offset - chip->base, offset); } static struct pinctrl_ops nmk_pinctrl_ops = { @@ -1818,6 +1854,7 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) const struct platform_device_id *platid = platform_get_device_id(pdev); struct device_node *np = pdev->dev.of_node; struct nmk_pinctrl *npct; + struct resource *res; unsigned int version = 0; int i; @@ -1839,22 +1876,37 @@ static int __devinit nmk_pinctrl_probe(struct platform_device *pdev) if (version == PINCTRL_NMK_DB8540) nmk_pinctrl_db8540_init(&npct->soc); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res) { + npct->prcm_base = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!npct->prcm_base) { + dev_err(&pdev->dev, + "failed to ioremap PRCM registers\n"); + return -ENOMEM; + } + } else { + dev_info(&pdev->dev, + "No PRCM base, assume no ALT-Cx control is available\n"); + } + /* * 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[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[i]->chip; + 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; + npct->pctl = pinctrl_register(&nmk_pinctrl_desc, &pdev->dev, npct); if (!npct->pctl) { dev_err(&pdev->dev, "could not register Nomadik pinctrl driver\n"); @@ -1889,6 +1941,7 @@ static const struct platform_device_id nmk_pinctrl_id[] = { { "pinctrl-stn8815", PINCTRL_NMK_STN8815 }, { "pinctrl-db8500", PINCTRL_NMK_DB8500 }, { "pinctrl-db8540", PINCTRL_NMK_DB8540 }, + { } }; static struct platform_driver nmk_pinctrl_driver = { diff --git a/drivers/pinctrl/pinctrl-nomadik.h b/drivers/pinctrl/pinctrl-nomadik.h index eef316e979a02a1156c8ede6ca10c3b039e5d7fc..bcd4191e10ea8ced278c469799d521e4a82dee65 100644 --- a/drivers/pinctrl/pinctrl-nomadik.h +++ b/drivers/pinctrl/pinctrl-nomadik.h @@ -1,7 +1,7 @@ #ifndef PINCTRL_PINCTRL_NOMADIK_H #define PINCTRL_PINCTRL_NOMADIK_H -#include +#include /* Package definitions */ #define PINCTRL_NMK_STN8815 0 diff --git a/arch/arm/plat-nomadik/include/plat/pincfg.h b/include/linux/platform_data/pinctrl-nomadik.h similarity index 66% rename from arch/arm/plat-nomadik/include/plat/pincfg.h rename to include/linux/platform_data/pinctrl-nomadik.h index 3b8ec60af351500a5cbcb80c970b8026c7d8477d..f73b2f0c55b77f6fc61605f6315563494d6692fc 100644 --- a/arch/arm/plat-nomadik/include/plat/pincfg.h +++ b/include/linux/platform_data/pinctrl-nomadik.h @@ -1,16 +1,17 @@ /* - * Copyright (C) ST-Ericsson SA 2010 + * Structures and registers for GPIO access in the Nomadik SoC * - * License terms: GNU General Public License, version 2 - * Author: Rabin Vincent for ST-Ericsson + * Copyright (C) 2008 STMicroelectronics + * Author: Prafulla WADASKAR + * Copyright (C) 2009 Alessandro Rubini * - * Based on arch/arm/mach-pxa/include/mach/mfp.h: - * Copyright (C) 2007 Marvell International Ltd. - * eric miao + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ -#ifndef __PLAT_PINCFG_H -#define __PLAT_PINCFG_H +#ifndef __PLAT_NOMADIK_GPIO +#define __PLAT_NOMADIK_GPIO /* * pin configurations are represented by 32-bit integers: @@ -166,8 +167,100 @@ typedef unsigned long pin_cfg_t; (PIN_CFG_DEFAULT |\ (PIN_NUM(num) | PIN_##alt | PIN_OUTPUT_##val)) +/* + * "nmk_gpio" and "NMK_GPIO" stand for "Nomadik GPIO", leaving + * the "gpio" namespace for generic and cross-machine functions + */ + +#define GPIO_BLOCK_SHIFT 5 +#define NMK_GPIO_PER_CHIP (1 << GPIO_BLOCK_SHIFT) + +/* Register in the logic block */ +#define NMK_GPIO_DAT 0x00 +#define NMK_GPIO_DATS 0x04 +#define NMK_GPIO_DATC 0x08 +#define NMK_GPIO_PDIS 0x0c +#define NMK_GPIO_DIR 0x10 +#define NMK_GPIO_DIRS 0x14 +#define NMK_GPIO_DIRC 0x18 +#define NMK_GPIO_SLPC 0x1c +#define NMK_GPIO_AFSLA 0x20 +#define NMK_GPIO_AFSLB 0x24 +#define NMK_GPIO_LOWEMI 0x28 + +#define NMK_GPIO_RIMSC 0x40 +#define NMK_GPIO_FIMSC 0x44 +#define NMK_GPIO_IS 0x48 +#define NMK_GPIO_IC 0x4c +#define NMK_GPIO_RWIMSC 0x50 +#define NMK_GPIO_FWIMSC 0x54 +#define NMK_GPIO_WKS 0x58 +/* These appear in DB8540 and later ASICs */ +#define NMK_GPIO_EDGELEVEL 0x5C +#define NMK_GPIO_LEVEL 0x60 + +/* Alternate functions: function C is set in hw by setting both A and B */ +#define NMK_GPIO_ALT_GPIO 0 +#define NMK_GPIO_ALT_A 1 +#define NMK_GPIO_ALT_B 2 +#define NMK_GPIO_ALT_C (NMK_GPIO_ALT_A | NMK_GPIO_ALT_B) + +#define NMK_GPIO_ALT_CX_SHIFT 2 +#define NMK_GPIO_ALT_C1 ((1<