// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2013, Sony Mobile Communications AB.
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pinctrl/machine.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/pinctrl/pinconf.h>
#include <linux/pinctrl/pinconf-generic.h>
#include <linux/slab.h>
#include <linux/gpio/driver.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h>
#include <linux/reboot.h>
#include <linux/pm.h>
#include <linux/log2.h>
#include <linux/qcom_scm.h>
#include <linux/soc/qcom/irq.h>
#include "../core.h"
#include "../pinconf.h"
#include "pinctrl-msm.h"
#include "../pinctrl-utils.h"
#define MAX_NR_GPIO 300
#define MAX_NR_TILES 4
#define PS_HOLD_OFFSET 0x820
/**
* struct msm_pinctrl - state for a pinctrl-msm device
* @dev: device handle.
* @pctrl: pinctrl handle.
* @chip: gpiochip handle.
* @desc: pin controller descriptor
* @restart_nb: restart notifier block.
* @irq: parent irq for the TLMM irq_chip.
* @intr_target_use_scm: route irq to application cpu using scm calls
* @lock: Spinlock to protect register resources as well
* as msm_pinctrl data structures.
* @enabled_irqs: Bitmap of currently enabled irqs.
* @dual_edge_irqs: Bitmap of irqs that need sw emulated dual edge
* detection.
* @skip_wake_irqs: Skip IRQs that are handled by wakeup interrupt controller
* @disabled_for_mux: These IRQs were disabled because we muxed away.
* @soc: Reference to soc_data of platform specific data.
* @regs: Base addresses for the TLMM tiles.
* @phys_base: Physical base address
*/
struct msm_pinctrl {
struct device *dev;
struct pinctrl_dev *pctrl;
struct gpio_chip chip;
struct pinctrl_desc desc;
struct notifier_block restart_nb;
int irq;
bool intr_target_use_scm;
raw_spinlock_t lock;
DECLARE_BITMAP(dual_edge_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(enabled_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(skip_wake_irqs, MAX_NR_GPIO);
DECLARE_BITMAP(disabled_for_mux, MAX_NR_GPIO);
const struct msm_pinctrl_soc_data *soc;
void __iomem *regs[MAX_NR_TILES];
u32 phys_base[MAX_NR_TILES];
};
#define MSM_ACCESSOR(name) \
static u32 msm_readl_##name(struct msm_pinctrl *pctrl, \
const struct msm_pingroup *g) \
{ \
return readl(pctrl->regs[g->tile] + g->name##_reg); \
} \
static void msm_writel_##name(u32 val, struct msm_pinctrl *pctrl, \
const struct msm_pingroup *g) \
{ \
writel(val, pctrl->regs[g->tile] + g->name##_reg); \
}
MSM_ACCESSOR(ctl)
MSM_ACCESSOR(io)
MSM_ACCESSOR(intr_cfg)
MSM_ACCESSOR(intr_status)
MSM_ACCESSOR(intr_target)
static void msm_ack_intr_status(struct msm_pinctrl *pctrl,
const struct msm_pingroup *g)
{
u32 val = g->intr_ack_high ? BIT(g->intr_status_bit) : 0;
msm_writel_intr_status(val, pctrl, g);
}
static int msm_get_groups_count(struct pinctrl_dev *pctldev)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->ngroups;
}
static const char *msm_get_group_name(struct pinctrl_dev *pctldev,
unsigned group)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->groups[group].name;
}
static int msm_get_group_pins(struct pinctrl_dev *pctldev,
unsigned group,
const unsigned **pins,
unsigned *num_pins)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
*pins = pctrl->soc->groups[group].pins;
*num_pins = pctrl->soc->groups[group].npins;
return 0;
}
static const struct pinctrl_ops msm_pinctrl_ops = {
.get_groups_count = msm_get_groups_count,
.get_group_name = msm_get_group_name,
.get_group_pins = msm_get_group_pins,
.dt_node_to_map = pinconf_generic_dt_node_to_map_group,
.dt_free_map = pinctrl_utils_free_map,
};
static int msm_pinmux_request(struct pinctrl_dev *pctldev, unsigned offset)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct gpio_chip *chip = &pctrl->chip;
return gpiochip_line_is_valid(chip, offset) ? 0 : -EINVAL;
}
static int msm_get_functions_count(struct pinctrl_dev *pctldev)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->nfunctions;
}
static const char *msm_get_function_name(struct pinctrl_dev *pctldev,
unsigned function)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
return pctrl->soc->functions[function].name;
}
static int msm_get_function_groups(struct pinctrl_dev *pctldev,
unsigned function,
const char * const **groups,
unsigned * const num_groups)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
*groups = pctrl->soc->functions[function].groups;
*num_groups = pctrl->soc->functions[function].ngroups;
return 0;
}
static int msm_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned function,
unsigned group)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
struct gpio_chip *gc = &pctrl->chip;
unsigned int irq = irq_find_mapping(gc->irq.domain, group);
struct irq_data *d = irq_get_irq_data(irq);
unsigned int gpio_func = pctrl->soc->gpio_func;
unsigned int egpio_func = pctrl->soc->egpio_func;
const struct msm_pingroup *g;
unsigned long flags;
u32 val, mask;
int i;
g = &pctrl->soc->groups[group];
mask = GENMASK(g->mux_bit + order_base_2(g->nfuncs) - 1, g->mux_bit);
for (i = 0; i < g->nfuncs; i++) {
if (g->funcs[i] == function)
break;
}
if (WARN_ON(i == g->nfuncs))
return -EINVAL;
/*
* If an GPIO interrupt is setup on this pin then we need special
* handling. Specifically interrupt detection logic will still see
* the pin twiddle even when we're muxed away.
*
* When we see a pin with an interrupt setup on it then we'll disable
* (mask) interrupts on it when we mux away until we mux back. Note
* that disable_irq() refcounts and interrupts are disabled as long as
* at least one disable_irq() has been called.
*/
if (d && i != gpio_func &&
!test_and_set_bit(d->hwirq, pctrl->disabled_for_mux))
disable_irq(irq);
raw_spin_lock_irqsave(&pctrl->lock, flags);
val = msm_readl_ctl(pctrl, g);
if (egpio_func && i == egpio_func) {
if (val & BIT(g->egpio_present))
val &= ~BIT(g->egpio_enable);
} else {
val &= ~mask;
val |= i << g->mux_bit;
/* Claim ownership of pin if egpio capable */
if (egpio_func && val & BIT(g->egpio_present))
val |= BIT(g->egpio_enable);
}
msm_writel_ctl(val, pctrl, g);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
if (d && i == gpio_func &&
test_and_clear_bit(d->hwirq, pctrl->disabled_for_mux)) {
/*
* Clear interrupts detected while not GPIO since we only
* masked things.
*/
if (d->parent_data && test_bit(d->hwirq, pctrl->skip_wake_irqs))
irq_chip_set_parent_state(d, IRQCHIP_STATE_PENDING, false);
else
msm_ack_intr_status(pctrl, g);
enable_irq(irq);
}
return 0;
}
static int msm_pinmux_request_gpio(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned offset)
{
struct msm_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
const struct msm_pingroup *g = &pctrl->soc->groups[offset];
/* No funcs? Probably ACPI so can't do anything here */
if (!g->nfuncs)
return 0;
return msm_pinmux_set_mux(pctldev, g->funcs[pctrl->soc->gpio_func], offset);
}
static const struct pinmux_ops msm_pinmux_ops = {
.request = msm_pinmux_request,
.get_functions_count = msm_get_functions_count,
.get_function_name = msm_
|