summaryrefslogtreecommitdiff
path: root/drivers/pinctrl/pinctrl-single.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pinctrl/pinctrl-single.c')
-rw-r--r--drivers/pinctrl/pinctrl-single.c123
1 files changed, 65 insertions, 58 deletions
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 0dabbcf68b9f..998f23d6c317 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -12,14 +12,13 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
+#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/seq_file.h>
@@ -82,8 +81,6 @@ struct pcs_conf_type {
* @name: pinctrl function name
* @vals: register and vals array
* @nvals: number of entries in vals array
- * @pgnames: array of pingroup names the function uses
- * @npgnames: number of pingroup names the function uses
* @conf: array of pin configurations
* @nconfs: number of pin configurations available
* @node: list node
@@ -92,8 +89,6 @@ struct pcs_function {
const char *name;
struct pcs_func_vals *vals;
unsigned nvals;
- const char **pgnames;
- int npgnames;
struct pcs_conf_vals *conf;
int nconfs;
struct list_head node;
@@ -240,32 +235,32 @@ static struct lock_class_key pcs_request_class;
* does not help in this case.
*/
-static unsigned __maybe_unused pcs_readb(void __iomem *reg)
+static unsigned int pcs_readb(void __iomem *reg)
{
return readb(reg);
}
-static unsigned __maybe_unused pcs_readw(void __iomem *reg)
+static unsigned int pcs_readw(void __iomem *reg)
{
return readw(reg);
}
-static unsigned __maybe_unused pcs_readl(void __iomem *reg)
+static unsigned int pcs_readl(void __iomem *reg)
{
return readl(reg);
}
-static void __maybe_unused pcs_writeb(unsigned val, void __iomem *reg)
+static void pcs_writeb(unsigned int val, void __iomem *reg)
{
writeb(val, reg);
}
-static void __maybe_unused pcs_writew(unsigned val, void __iomem *reg)
+static void pcs_writew(unsigned int val, void __iomem *reg)
{
writew(val, reg);
}
-static void __maybe_unused pcs_writel(unsigned val, void __iomem *reg)
+static void pcs_writel(unsigned int val, void __iomem *reg)
{
writel(val, reg);
}
@@ -341,7 +336,7 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pin_desc *pdesc = pin_desc_get(pctldev, pin);
const struct pinctrl_setting_mux *setting;
- struct function_desc *function;
+ const struct function_desc *function;
unsigned fselector;
/* If pin is not described in DTS & enabled, mux_setting is NULL. */
@@ -350,6 +345,8 @@ static int pcs_get_function(struct pinctrl_dev *pctldev, unsigned pin,
return -ENOTSUPP;
fselector = setting->func;
function = pinmux_generic_get_function(pctldev, fselector);
+ if (!function)
+ return -EINVAL;
*func = function->data;
if (!(*func)) {
dev_err(pcs->dev, "%s could not find function%i\n",
@@ -363,7 +360,7 @@ static int pcs_set_mux(struct pinctrl_dev *pctldev, unsigned fselector,
unsigned group)
{
struct pcs_device *pcs;
- struct function_desc *function;
+ const struct function_desc *function;
struct pcs_function *func;
int i;
@@ -488,7 +485,8 @@ static int pcs_pinconf_get(struct pinctrl_dev *pctldev,
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_function *func;
enum pin_config_param param;
- unsigned offset = 0, data = 0, i, j, ret;
+ unsigned offset = 0, data = 0, i, j;
+ int ret;
ret = pcs_get_function(pctldev, pin, &func);
if (ret)
@@ -552,24 +550,33 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
{
struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
struct pcs_function *func;
- unsigned offset = 0, shift = 0, i, data, ret;
+ unsigned offset = 0, shift = 0, i, data;
u32 arg;
- int j;
+ int j, ret;
+ enum pin_config_param param;
ret = pcs_get_function(pctldev, pin, &func);
if (ret)
return ret;
for (j = 0; j < num_configs; j++) {
+ param = pinconf_to_config_param(configs[j]);
+
+ /* BIAS_DISABLE has no entry in the func->conf table */
+ if (param == PIN_CONFIG_BIAS_DISABLE) {
+ /* This just disables all bias entries */
+ pcs_pinconf_clear_bias(pctldev, pin);
+ continue;
+ }
+
for (i = 0; i < func->nconfs; i++) {
- if (pinconf_to_config_param(configs[j])
- != func->conf[i].param)
+ if (param != func->conf[i].param)
continue;
offset = pin * (pcs->width / BITS_PER_BYTE);
data = pcs->read(pcs->base + offset);
arg = pinconf_to_config_argument(configs[j]);
- switch (func->conf[i].param) {
+ switch (param) {
/* 2 parameters */
case PIN_CONFIG_INPUT_SCHMITT:
case PIN_CONFIG_DRIVE_STRENGTH:
@@ -581,13 +588,12 @@ static int pcs_pinconf_set(struct pinctrl_dev *pctldev,
data |= (arg << shift) & func->conf[i].mask;
break;
/* 4 parameters */
- case PIN_CONFIG_BIAS_DISABLE:
- pcs_pinconf_clear_bias(pctldev, pin);
- break;
case PIN_CONFIG_BIAS_PULL_DOWN:
case PIN_CONFIG_BIAS_PULL_UP:
- if (arg)
+ if (arg) {
pcs_pinconf_clear_bias(pctldev, pin);
+ data = pcs->read(pcs->base + offset);
+ }
fallthrough;
case PIN_CONFIG_INPUT_SCHMITT_ENABLE:
data &= ~func->conf[i].mask;
@@ -1328,7 +1334,6 @@ static void pcs_irq_free(struct pcs_device *pcs)
static void pcs_free_resources(struct pcs_device *pcs)
{
pcs_irq_free(pcs);
- pinctrl_unregister(pcs->pctl);
#if IS_BUILTIN(CONFIG_PINCTRL_SINGLE)
if (pcs->missing_nr_pinctrl_cells)
@@ -1609,15 +1614,16 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
/*
* We can use the register offset as the hardirq
- * number as irq_domain_add_simple maps them lazily.
+ * number as irq_domain_create_simple maps them lazily.
* This way we can easily support more than one
* interrupt per function if needed.
*/
num_irqs = pcs->size;
- pcs->domain = irq_domain_add_simple(np, num_irqs, 0,
- &pcs_irqdomain_ops,
- pcs_soc);
+ pcs->domain = irq_domain_create_simple(of_fwnode_handle(np),
+ num_irqs, 0,
+ &pcs_irqdomain_ops,
+ pcs_soc);
if (!pcs->domain) {
irq_set_chained_handler(pcs_soc->irq, NULL);
return -EINVAL;
@@ -1626,7 +1632,6 @@ static int pcs_irq_init_chained_handler(struct pcs_device *pcs,
return 0;
}
-#ifdef CONFIG_PM
static int pcs_save_context(struct pcs_device *pcs)
{
int i, mux_bytes;
@@ -1691,14 +1696,9 @@ static void pcs_restore_context(struct pcs_device *pcs)
}
}
-static int pinctrl_single_suspend(struct platform_device *pdev,
- pm_message_t state)
+static int pinctrl_single_suspend_noirq(struct device *dev)
{
- struct pcs_device *pcs;
-
- pcs = platform_get_drvdata(pdev);
- if (!pcs)
- return -EINVAL;
+ struct pcs_device *pcs = dev_get_drvdata(dev);
if (pcs->flags & PCS_CONTEXT_LOSS_OFF) {
int ret;
@@ -1711,20 +1711,19 @@ static int pinctrl_single_suspend(struct platform_device *pdev,
return pinctrl_force_sleep(pcs->pctl);
}
-static int pinctrl_single_resume(struct platform_device *pdev)
+static int pinctrl_single_resume_noirq(struct device *dev)
{
- struct pcs_device *pcs;
-
- pcs = platform_get_drvdata(pdev);
- if (!pcs)
- return -EINVAL;
+ struct pcs_device *pcs = dev_get_drvdata(dev);
if (pcs->flags & PCS_CONTEXT_LOSS_OFF)
pcs_restore_context(pcs);
return pinctrl_force_default(pcs->pctl);
}
-#endif
+
+static DEFINE_NOIRQ_DEV_PM_OPS(pinctrl_single_pm_ops,
+ pinctrl_single_suspend_noirq,
+ pinctrl_single_resume_noirq);
/**
* pcs_quirk_missing_pinctrl_cells - handle legacy binding
@@ -1885,7 +1884,7 @@ static int pcs_probe(struct platform_device *pdev)
if (ret < 0)
goto free;
- ret = pinctrl_register_and_init(&pcs->desc, pcs->dev, pcs, &pcs->pctl);
+ ret = devm_pinctrl_register_and_init(pcs->dev, &pcs->desc, pcs, &pcs->pctl);
if (ret) {
dev_err(pcs->dev, "could not register single pinctrl driver\n");
goto free;
@@ -1918,24 +1917,22 @@ static int pcs_probe(struct platform_device *pdev)
dev_info(pcs->dev, "%i pins, size %u\n", pcs->desc.npins, pcs->size);
- return pinctrl_enable(pcs->pctl);
+ ret = pinctrl_enable(pcs->pctl);
+ if (ret)
+ goto free;
+ return 0;
free:
pcs_free_resources(pcs);
return ret;
}
-static int pcs_remove(struct platform_device *pdev)
+static void pcs_remove(struct platform_device *pdev)
{
struct pcs_device *pcs = platform_get_drvdata(pdev);
- if (!pcs)
- return 0;
-
pcs_free_resources(pcs);
-
- return 0;
}
static const struct pcs_soc_data pinctrl_single_omap_wkup = {
@@ -1955,6 +1952,16 @@ static const struct pcs_soc_data pinctrl_single_am437x = {
.irq_status_mask = (1 << 30), /* OMAP_WAKEUP_EVENT */
};
+static const struct pcs_soc_data pinctrl_single_am654 = {
+ .flags = PCS_QUIRK_SHARED_IRQ | PCS_CONTEXT_LOSS_OFF,
+ .irq_enable_mask = (1 << 29), /* WKUP_EN */
+ .irq_status_mask = (1 << 30), /* WKUP_EVT */
+};
+
+static const struct pcs_soc_data pinctrl_single_j7200 = {
+ .flags = PCS_CONTEXT_LOSS_OFF,
+};
+
static const struct pcs_soc_data pinctrl_single = {
};
@@ -1963,11 +1970,14 @@ static const struct pcs_soc_data pinconf_single = {
};
static const struct of_device_id pcs_of_match[] = {
+ { .compatible = "marvell,pxa1908-padconf", .data = &pinconf_single },
+ { .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x },
+ { .compatible = "ti,am654-padconf", .data = &pinctrl_single_am654 },
+ { .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 },
{ .compatible = "ti,omap3-padconf", .data = &pinctrl_single_omap_wkup },
{ .compatible = "ti,omap4-padconf", .data = &pinctrl_single_omap_wkup },
{ .compatible = "ti,omap5-padconf", .data = &pinctrl_single_omap_wkup },
- { .compatible = "ti,dra7-padconf", .data = &pinctrl_single_dra7 },
- { .compatible = "ti,am437-padconf", .data = &pinctrl_single_am437x },
+ { .compatible = "ti,j7200-padconf", .data = &pinctrl_single_j7200 },
{ .compatible = "pinctrl-single", .data = &pinctrl_single },
{ .compatible = "pinconf-single", .data = &pinconf_single },
{ },
@@ -1980,11 +1990,8 @@ static struct platform_driver pcs_driver = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = pcs_of_match,
+ .pm = pm_sleep_ptr(&pinctrl_single_pm_ops),
},
-#ifdef CONFIG_PM
- .suspend = pinctrl_single_suspend,
- .resume = pinctrl_single_resume,
-#endif
};
module_platform_driver(pcs_driver);