diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 01:34:22 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-02-22 01:34:22 +0100 |
commit | 5ab356626f3cf97f00280f17a52e4b5b4a13e038 (patch) | |
tree | 6a2d8598a264b8bc1e563edaf35dc37fff26556e /drivers/pinctrl/samsung/pinctrl-samsung.c | |
parent | Merge tag 'extable-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/gi... (diff) | |
parent | pinctrl: samsung: Fix return value check in samsung_pinctrl_get_soc_data() (diff) | |
download | linux-5ab356626f3cf97f00280f17a52e4b5b4a13e038.tar.xz linux-5ab356626f3cf97f00280f17a52e4b5b4a13e038.zip |
Merge tag 'pinctrl-v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl
Pull pin control updates from Linus Walleij:
"Pin control bulk changes for the v4.11 kernel cycle.
Core changes:
- Switch the generic pin config argument from 16 to 24 bits, only use
8 bits for the configuration type. We might need to encode more
information about a certain setting than we need to encode
different generic settings.
- Add a cross-talk API to the pin control GPIO back-end, utilizing
pinctrl_gpio_set_config() from GPIO drivers that want to set up a
certain pin configuration in the back-end.
This also includes the .set_config() refactoring of the GPIO chips,
so that they pass a generic configuration for things like
debouncing and single ended (typically open drain). This change has
also been merged in an immutable branch to the GPIO tree.
- Take hogs with a delayed work, so that we finalize probing a pin
controller before trying to get any hogs.
- For pin controllers putting all group and function definitions into
the device tree, we now have generic code to deal with this and it
is used in two drivers so far.
- Simplifications of the pin request conflict check.
- Make dt_free_map() optional.
Updates to drivers:
- pinctrl-single now use the generic helpers to generate dynamic
group and function tables from the device tree.
- Texas Instruments IOdelay configuration driver add-on to
pinctrl-single.
- i.MX: use radix trees to store groups and functions, use the new
generic group and function helpers to manage them.
- Intel: add support for hardware debouncing and 1K pull-down. New
subdriver for the Gemini Lake SoC.
- Renesas SH-PFC: drive strength and bias support, CAN bus muxing,
MSIOF, SDHI, HSCIF for r8a7796. Gyro-ADC supporton r8a7791.
- Aspeed: use syscon cross-dependencies to set up related bits in the
LPC host controller and display controller.
- Aspeed: finalize G4 and G5 support. Fix mux configuration on GPIOs.
Add banks Y, Z, AA, AB and AC.
- AMD: support additional GPIO.
- STM32: set this controller to strict muxing mode. STM32H743 MCU
support.
- Allwinner sunxi: deep simplifications on how to support subvariants
of SoCs without adding to much SoC-specific data for each
subvariant, especially for sun5i variants. New driver for V3s SoCs.
New driver for the H5 SoC. Support A31/A31s variants with the new
variant framework.
- Mvebu: simplifications to use a MMIO and regmap abstraction. New
subdrivers for the 98DX3236, 98DX5241 SoCs.
- Samsung Exynos: delete Exynos4415 support. Add crosstalk to the SoC
driver to access regmaps. Add infrastructure for pin-bank retention
control. Clean out the pin retention control from
arch/arm/mach-exynos and arch/arm/mach-s5p and put it properly in
the Samsung pin control driver(s).
- Meson: add HDMI HPD/DDC pins. Add pwm_ao_b pin.
- Qualcomm: use raw spinlock variants: this makes the qualcomm driver
realtime-safe"
* tag 'pinctrl-v4.11-1' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: (111 commits)
pinctrl: samsung: Fix return value check in samsung_pinctrl_get_soc_data()
pinctrl: intel: unlock on error in intel_config_set_pull()
pinctrl: berlin: make bool drivers explicitly non-modular
pinctrl: spear: make bool drivers explicitly non-modular
pinctrl: mvebu: make bool drivers explicitly non-modular
pinctrl: sunxi: make sun5i explicitly non-modular
pinctrl: sunxi: Remove stray printk call in sun5i driver's probe function
pinctrl: samsung: mark PM functions as __maybe_unused
pinctrl: sunxi: Remove redundant A31s pinctrl driver
pinctrl: sunxi: Support A31/A31s with pinctrl variants
pinctrl: Amend bindings for STM32 pinctrl
pinctrl: Add STM32 pinctrl driver DT bindings
pinctrl: stm32: Add STM32H743 MCU support
include: dt-bindings: Add STM32H7 pinctrl DT defines
gpio: aspeed: Remove dependence on GPIOF_* macros
pinctrl: stm32: fix bad location of gpiochip_lock_as_irq
drivers: pinctrl: add driver for Allwinner H5 SoC
pinctrl: intel: Add Intel Gemini Lake pin controller support
pinctrl: intel: Add support for 1k additional pull-down
pinctrl: intel: Add support for hardware debouncer
...
Diffstat (limited to 'drivers/pinctrl/samsung/pinctrl-samsung.c')
-rw-r--r-- | drivers/pinctrl/samsung/pinctrl-samsung.c | 132 |
1 files changed, 40 insertions, 92 deletions
diff --git a/drivers/pinctrl/samsung/pinctrl-samsung.c b/drivers/pinctrl/samsung/pinctrl-samsung.c index 41e62391c33c..f9ddba7decc1 100644 --- a/drivers/pinctrl/samsung/pinctrl-samsung.c +++ b/drivers/pinctrl/samsung/pinctrl-samsung.c @@ -27,8 +27,8 @@ #include <linux/err.h> #include <linux/gpio.h> #include <linux/irqdomain.h> +#include <linux/of_device.h> #include <linux/spinlock.h> -#include <linux/syscore_ops.h> #include "../core.h" #include "pinctrl-samsung.h" @@ -48,9 +48,6 @@ static struct pin_config { { "samsung,pin-val", PINCFG_TYPE_DAT }, }; -/* Global list of devices (struct samsung_pinctrl_drv_data) */ -static LIST_HEAD(drvdata_list); - static unsigned int pin_base; static int samsung_get_group_count(struct pinctrl_dev *pctldev) @@ -93,10 +90,8 @@ static int reserve_map(struct device *dev, struct pinctrl_map **map, return 0; new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL); - if (!new_map) { - dev_err(dev, "krealloc(map) failed\n"); + if (!new_map) return -ENOMEM; - } memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map)); @@ -133,10 +128,8 @@ static int add_map_configs(struct device *dev, struct pinctrl_map **map, dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs), GFP_KERNEL); - if (!dup_configs) { - dev_err(dev, "kmemdup(configs) failed\n"); + if (!dup_configs) return -ENOMEM; - } (*map)[*num_maps].type = PIN_MAP_TYPE_CONFIGS_GROUP; (*map)[*num_maps].data.configs.group_or_pin = group; @@ -156,10 +149,8 @@ static int add_config(struct device *dev, unsigned long **configs, new_configs = krealloc(*configs, sizeof(*new_configs) * new_num, GFP_KERNEL); - if (!new_configs) { - dev_err(dev, "krealloc(configs) failed\n"); + if (!new_configs) return -ENOMEM; - } new_configs[old_num] = config; @@ -356,7 +347,7 @@ static void pin_to_reg_bank(struct samsung_pinctrl_drv_data *drvdata, /* enable or disable a pinmux function */ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, - unsigned group, bool enable) + unsigned group) { struct samsung_pinctrl_drv_data *drvdata; const struct samsung_pin_bank_type *type; @@ -386,8 +377,7 @@ static void samsung_pinmux_setup(struct pinctrl_dev *pctldev, unsigned selector, data = readl(reg + type->reg_offset[PINCFG_TYPE_FUNC]); data &= ~(mask << shift); - if (enable) - data |= func->val << shift; + data |= func->val << shift; writel(data, reg + type->reg_offset[PINCFG_TYPE_FUNC]); spin_unlock_irqrestore(&bank->slock, flags); @@ -398,7 +388,7 @@ static int samsung_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned selector, unsigned group) { - samsung_pinmux_setup(pctldev, selector, group, true); + samsung_pinmux_setup(pctldev, selector, group); return 0; } @@ -756,10 +746,8 @@ static struct samsung_pmx_func *samsung_pinctrl_create_functions( functions = devm_kzalloc(dev, func_cnt * sizeof(*functions), GFP_KERNEL); - if (!functions) { - dev_err(dev, "failed to allocate memory for function list\n"); - return ERR_PTR(-EINVAL); - } + if (!functions) + return ERR_PTR(-ENOMEM); func = functions; /* @@ -850,10 +838,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev, pindesc = devm_kzalloc(&pdev->dev, sizeof(*pindesc) * drvdata->nr_pins, GFP_KERNEL); - if (!pindesc) { - dev_err(&pdev->dev, "mem alloc for pin descriptors failed\n"); + if (!pindesc) return -ENOMEM; - } ctrldesc->pins = pindesc; ctrldesc->npins = drvdata->nr_pins; @@ -867,10 +853,8 @@ static int samsung_pinctrl_register(struct platform_device *pdev, */ pin_names = devm_kzalloc(&pdev->dev, sizeof(char) * PIN_NAME_LENGTH * drvdata->nr_pins, GFP_KERNEL); - if (!pin_names) { - dev_err(&pdev->dev, "mem alloc for pin names failed\n"); + if (!pin_names) return -ENOMEM; - } /* for each pin, the name of the pin is pin-bank name + pin number */ for (bank = 0; bank < drvdata->nr_banks; bank++) { @@ -968,15 +952,12 @@ static int samsung_gpiolib_unregister(struct platform_device *pdev, return 0; } -static const struct of_device_id samsung_pinctrl_dt_match[]; - /* retrieve the soc specific data */ static const struct samsung_pin_ctrl * samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, struct platform_device *pdev) { int id; - const struct of_device_id *match; struct device_node *node = pdev->dev.of_node; struct device_node *np; const struct samsung_pin_bank_data *bdata; @@ -991,8 +972,8 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, dev_err(&pdev->dev, "failed to get alias id\n"); return ERR_PTR(-ENOENT); } - match = of_match_node(samsung_pinctrl_dt_match, node); - ctrl = (struct samsung_pin_ctrl *)match->data + id; + ctrl = of_device_get_match_data(&pdev->dev); + ctrl += id; d->suspend = ctrl->suspend; d->resume = ctrl->resume; @@ -1007,10 +988,9 @@ samsung_pinctrl_get_soc_data(struct samsung_pinctrl_drv_data *d, for (i = 0; i < ctrl->nr_ext_resources + 1; i++) { res = platform_get_resource(pdev, IORESOURCE_MEM, i); - virt_base[i] = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); + virt_base[i] = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(virt_base[i])) - return ERR_PTR(-EIO); + return ERR_CAST(virt_base[i]); } bank = d->pin_banks; @@ -1075,6 +1055,13 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) if (res) drvdata->irq = res->start; + if (ctrl->retention_data) { + drvdata->retention_ctrl = ctrl->retention_data->init(drvdata, + ctrl->retention_data); + if (IS_ERR(drvdata->retention_ctrl)) + return PTR_ERR(drvdata->retention_ctrl); + } + ret = samsung_gpiolib_register(pdev, drvdata); if (ret) return ret; @@ -1092,22 +1079,17 @@ static int samsung_pinctrl_probe(struct platform_device *pdev) platform_set_drvdata(pdev, drvdata); - /* Add to the global list */ - list_add_tail(&drvdata->node, &drvdata_list); - return 0; } -#ifdef CONFIG_PM - /** - * samsung_pinctrl_suspend_dev - save pinctrl state for suspend for a device + * samsung_pinctrl_suspend - save pinctrl state for suspend * * Save data for all banks handled by this device. */ -static void samsung_pinctrl_suspend_dev( - struct samsung_pinctrl_drv_data *drvdata) +static int __maybe_unused samsung_pinctrl_suspend(struct device *dev) { + struct samsung_pinctrl_drv_data *drvdata = dev_get_drvdata(dev); int i; for (i = 0; i < drvdata->nr_banks; i++) { @@ -1141,18 +1123,23 @@ static void samsung_pinctrl_suspend_dev( if (drvdata->suspend) drvdata->suspend(drvdata); + if (drvdata->retention_ctrl && drvdata->retention_ctrl->enable) + drvdata->retention_ctrl->enable(drvdata); + + return 0; } /** - * samsung_pinctrl_resume_dev - restore pinctrl state from suspend for a device + * samsung_pinctrl_resume - restore pinctrl state from suspend * * Restore one of the banks that was saved during suspend. * * We don't bother doing anything complicated to avoid glitching lines since * we're called before pad retention is turned off. */ -static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) +static int __maybe_unused samsung_pinctrl_resume(struct device *dev) { + struct samsung_pinctrl_drv_data *drvdata = dev_get_drvdata(dev); int i; if (drvdata->resume) @@ -1188,48 +1175,13 @@ static void samsung_pinctrl_resume_dev(struct samsung_pinctrl_drv_data *drvdata) if (widths[type]) writel(bank->pm_save[type], reg + offs[type]); } -} - -/** - * samsung_pinctrl_suspend - save pinctrl state for suspend - * - * Save data for all banks across all devices. - */ -static int samsung_pinctrl_suspend(void) -{ - struct samsung_pinctrl_drv_data *drvdata; - list_for_each_entry(drvdata, &drvdata_list, node) { - samsung_pinctrl_suspend_dev(drvdata); - } + if (drvdata->retention_ctrl && drvdata->retention_ctrl->disable) + drvdata->retention_ctrl->disable(drvdata); return 0; } -/** - * samsung_pinctrl_resume - restore pinctrl state for suspend - * - * Restore data for all banks across all devices. - */ -static void samsung_pinctrl_resume(void) -{ - struct samsung_pinctrl_drv_data *drvdata; - - list_for_each_entry_reverse(drvdata, &drvdata_list, node) { - samsung_pinctrl_resume_dev(drvdata); - } -} - -#else -#define samsung_pinctrl_suspend NULL -#define samsung_pinctrl_resume NULL -#endif - -static struct syscore_ops samsung_pinctrl_syscore_ops = { - .suspend = samsung_pinctrl_suspend, - .resume = samsung_pinctrl_resume, -}; - static const struct of_device_id samsung_pinctrl_dt_match[] = { #ifdef CONFIG_PINCTRL_EXYNOS { .compatible = "samsung,exynos3250-pinctrl", @@ -1238,8 +1190,6 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { .data = (void *)exynos4210_pin_ctrl }, { .compatible = "samsung,exynos4x12-pinctrl", .data = (void *)exynos4x12_pin_ctrl }, - { .compatible = "samsung,exynos4415-pinctrl", - .data = (void *)exynos4415_pin_ctrl }, { .compatible = "samsung,exynos5250-pinctrl", .data = (void *)exynos5250_pin_ctrl }, { .compatible = "samsung,exynos5260-pinctrl", @@ -1273,25 +1223,23 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { }; MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); +static const struct dev_pm_ops samsung_pinctrl_pm_ops = { + SET_LATE_SYSTEM_SLEEP_PM_OPS(samsung_pinctrl_suspend, + samsung_pinctrl_resume) +}; + static struct platform_driver samsung_pinctrl_driver = { .probe = samsung_pinctrl_probe, .driver = { .name = "samsung-pinctrl", .of_match_table = samsung_pinctrl_dt_match, .suppress_bind_attrs = true, + .pm = &samsung_pinctrl_pm_ops, }, }; static int __init samsung_pinctrl_drv_register(void) { - /* - * Register syscore ops for save/restore of registers across suspend. - * It's important to ensure that this driver is running at an earlier - * initcall level than any arch-specific init calls that install syscore - * ops that turn off pad retention (like exynos_pm_resume). - */ - register_syscore_ops(&samsung_pinctrl_syscore_ops); - return platform_driver_register(&samsung_pinctrl_driver); } postcore_initcall(samsung_pinctrl_drv_register); |