|
|
|
@ -58,6 +58,7 @@
|
|
|
|
|
#define CHV_PADCTRL1_CFGLOCK BIT(31)
|
|
|
|
|
#define CHV_PADCTRL1_INVRXTX_SHIFT 4
|
|
|
|
|
#define CHV_PADCTRL1_INVRXTX_MASK GENMASK(7, 4)
|
|
|
|
|
#define CHV_PADCTRL1_INVRXTX_TXDATA BIT(7)
|
|
|
|
|
#define CHV_PADCTRL1_INVRXTX_RXDATA BIT(6)
|
|
|
|
|
#define CHV_PADCTRL1_INVRXTX_TXENABLE BIT(5)
|
|
|
|
|
#define CHV_PADCTRL1_ODEN BIT(3)
|
|
|
|
@ -73,35 +74,11 @@ struct intel_pad_context {
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* struct chv_pinctrl - CHV pinctrl private structure
|
|
|
|
|
* @dev: Pointer to the parent device
|
|
|
|
|
* @pctldesc: Pin controller description
|
|
|
|
|
* @pctldev: Pointer to the pin controller device
|
|
|
|
|
* @chip: GPIO chip in this pin controller
|
|
|
|
|
* @irqchip: IRQ chip in this pin controller
|
|
|
|
|
* @soc: Community specific pin configuration data
|
|
|
|
|
* @communities: All communities in this pin controller
|
|
|
|
|
* @ncommunities: Number of communities in this pin controller
|
|
|
|
|
* @context: Configuration saved over system sleep
|
|
|
|
|
* @irq: Our parent irq
|
|
|
|
|
* struct intel_community_context - community context for Cherryview
|
|
|
|
|
* @intr_lines: Mapping between 16 HW interrupt wires and GPIO offset (in GPIO number space)
|
|
|
|
|
* @saved_intmask: Interrupt mask saved for system sleep
|
|
|
|
|
*
|
|
|
|
|
* The first group in @groups is expected to contain all pins that can be
|
|
|
|
|
* used as GPIOs.
|
|
|
|
|
*/
|
|
|
|
|
struct chv_pinctrl {
|
|
|
|
|
struct device *dev;
|
|
|
|
|
struct pinctrl_desc pctldesc;
|
|
|
|
|
struct pinctrl_dev *pctldev;
|
|
|
|
|
struct gpio_chip chip;
|
|
|
|
|
struct irq_chip irqchip;
|
|
|
|
|
const struct intel_pinctrl_soc_data *soc;
|
|
|
|
|
struct intel_community *communities;
|
|
|
|
|
size_t ncommunities;
|
|
|
|
|
struct intel_pinctrl_context context;
|
|
|
|
|
int irq;
|
|
|
|
|
|
|
|
|
|
struct intel_community_context {
|
|
|
|
|
unsigned int intr_lines[16];
|
|
|
|
|
u32 saved_intmask;
|
|
|
|
|
};
|
|
|
|
@ -587,14 +564,14 @@ static const struct intel_pinctrl_soc_data *chv_soc_data[] = {
|
|
|
|
|
*/
|
|
|
|
|
static DEFINE_RAW_SPINLOCK(chv_lock);
|
|
|
|
|
|
|
|
|
|
static u32 chv_pctrl_readl(struct chv_pinctrl *pctrl, unsigned int offset)
|
|
|
|
|
static u32 chv_pctrl_readl(struct intel_pinctrl *pctrl, unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
|
|
|
|
|
return readl(community->regs + offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void chv_pctrl_writel(struct chv_pinctrl *pctrl, unsigned int offset, u32 value)
|
|
|
|
|
static void chv_pctrl_writel(struct intel_pinctrl *pctrl, unsigned int offset, u32 value)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
void __iomem *reg = community->regs + offset;
|
|
|
|
@ -604,7 +581,7 @@ static void chv_pctrl_writel(struct chv_pinctrl *pctrl, unsigned int offset, u32
|
|
|
|
|
readl(reg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned int offset,
|
|
|
|
|
static void __iomem *chv_padreg(struct intel_pinctrl *pctrl, unsigned int offset,
|
|
|
|
|
unsigned int reg)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
@ -616,12 +593,12 @@ static void __iomem *chv_padreg(struct chv_pinctrl *pctrl, unsigned int offset,
|
|
|
|
|
return community->pad_regs + offset + reg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u32 chv_readl(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int offset)
|
|
|
|
|
static u32 chv_readl(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
return readl(chv_padreg(pctrl, pin, offset));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void chv_writel(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int offset, u32 value)
|
|
|
|
|
static void chv_writel(struct intel_pinctrl *pctrl, unsigned int pin, unsigned int offset, u32 value)
|
|
|
|
|
{
|
|
|
|
|
void __iomem *reg = chv_padreg(pctrl, pin, offset);
|
|
|
|
|
|
|
|
|
@ -631,14 +608,14 @@ static void chv_writel(struct chv_pinctrl *pctrl, unsigned int pin, unsigned int
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* When Pad Cfg is locked, driver can only change GPIOTXState or GPIORXState */
|
|
|
|
|
static bool chv_pad_locked(struct chv_pinctrl *pctrl, unsigned int offset)
|
|
|
|
|
static bool chv_pad_locked(struct intel_pinctrl *pctrl, unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
return chv_readl(pctrl, offset, CHV_PADCTRL1) & CHV_PADCTRL1_CFGLOCK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int chv_get_groups_count(struct pinctrl_dev *pctldev)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
|
|
|
|
|
return pctrl->soc->ngroups;
|
|
|
|
|
}
|
|
|
|
@ -646,7 +623,7 @@ static int chv_get_groups_count(struct pinctrl_dev *pctldev)
|
|
|
|
|
static const char *chv_get_group_name(struct pinctrl_dev *pctldev,
|
|
|
|
|
unsigned int group)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
|
|
|
|
|
return pctrl->soc->groups[group].name;
|
|
|
|
|
}
|
|
|
|
@ -654,7 +631,7 @@ static const char *chv_get_group_name(struct pinctrl_dev *pctldev,
|
|
|
|
|
static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
|
|
|
|
|
const unsigned int **pins, unsigned int *npins)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
|
|
|
|
|
*pins = pctrl->soc->groups[group].pins;
|
|
|
|
|
*npins = pctrl->soc->groups[group].npins;
|
|
|
|
@ -664,7 +641,7 @@ static int chv_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
|
|
|
|
|
static void chv_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
|
|
|
|
|
unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 ctrl0, ctrl1;
|
|
|
|
|
bool locked;
|
|
|
|
@ -703,7 +680,7 @@ static const struct pinctrl_ops chv_pinctrl_ops = {
|
|
|
|
|
|
|
|
|
|
static int chv_get_functions_count(struct pinctrl_dev *pctldev)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
|
|
|
|
|
return pctrl->soc->nfunctions;
|
|
|
|
|
}
|
|
|
|
@ -711,7 +688,7 @@ static int chv_get_functions_count(struct pinctrl_dev *pctldev)
|
|
|
|
|
static const char *chv_get_function_name(struct pinctrl_dev *pctldev,
|
|
|
|
|
unsigned int function)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
|
|
|
|
|
return pctrl->soc->functions[function].name;
|
|
|
|
|
}
|
|
|
|
@ -721,7 +698,7 @@ static int chv_get_function_groups(struct pinctrl_dev *pctldev,
|
|
|
|
|
const char * const **groups,
|
|
|
|
|
unsigned int * const ngroups)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
|
|
|
|
|
*groups = pctrl->soc->functions[function].groups;
|
|
|
|
|
*ngroups = pctrl->soc->functions[function].ngroups;
|
|
|
|
@ -731,7 +708,7 @@ static int chv_get_function_groups(struct pinctrl_dev *pctldev,
|
|
|
|
|
static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
|
|
|
|
unsigned int function, unsigned int group)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
const struct intel_pingroup *grp;
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
int i;
|
|
|
|
@ -789,14 +766,25 @@ static int chv_pinmux_set_mux(struct pinctrl_dev *pctldev,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void chv_gpio_clear_triggering(struct chv_pinctrl *pctrl,
|
|
|
|
|
static void chv_gpio_clear_triggering(struct intel_pinctrl *pctrl,
|
|
|
|
|
unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
u32 invrxtx_mask = CHV_PADCTRL1_INVRXTX_MASK;
|
|
|
|
|
u32 value;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* One some devices the GPIO should output the inverted value from what
|
|
|
|
|
* device-drivers / ACPI code expects (inverted external buffer?). The
|
|
|
|
|
* BIOS makes this work by setting the CHV_PADCTRL1_INVRXTX_TXDATA flag,
|
|
|
|
|
* preserve this flag if the pin is already setup as GPIO.
|
|
|
|
|
*/
|
|
|
|
|
value = chv_readl(pctrl, offset, CHV_PADCTRL0);
|
|
|
|
|
if (value & CHV_PADCTRL0_GPIOEN)
|
|
|
|
|
invrxtx_mask &= ~CHV_PADCTRL1_INVRXTX_TXDATA;
|
|
|
|
|
|
|
|
|
|
value = chv_readl(pctrl, offset, CHV_PADCTRL1);
|
|
|
|
|
value &= ~CHV_PADCTRL1_INTWAKECFG_MASK;
|
|
|
|
|
value &= ~CHV_PADCTRL1_INVRXTX_MASK;
|
|
|
|
|
value &= ~invrxtx_mask;
|
|
|
|
|
chv_writel(pctrl, offset, CHV_PADCTRL1, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -804,7 +792,7 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|
|
|
|
struct pinctrl_gpio_range *range,
|
|
|
|
|
unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 value;
|
|
|
|
|
|
|
|
|
@ -818,12 +806,13 @@ static int chv_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|
|
|
|
return -EBUSY;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
struct intel_community_context *cctx = &pctrl->context.communities[0];
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* Reset the interrupt mapping */
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(pctrl->intr_lines); i++) {
|
|
|
|
|
if (pctrl->intr_lines[i] == offset) {
|
|
|
|
|
pctrl->intr_lines[i] = 0;
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(cctx->intr_lines); i++) {
|
|
|
|
|
if (cctx->intr_lines[i] == offset) {
|
|
|
|
|
cctx->intr_lines[i] = 0;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -857,7 +846,7 @@ static void chv_gpio_disable_free(struct pinctrl_dev *pctldev,
|
|
|
|
|
struct pinctrl_gpio_range *range,
|
|
|
|
|
unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
|
|
raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
@ -872,7 +861,7 @@ static int chv_gpio_set_direction(struct pinctrl_dev *pctldev,
|
|
|
|
|
struct pinctrl_gpio_range *range,
|
|
|
|
|
unsigned int offset, bool input)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 ctrl0;
|
|
|
|
|
|
|
|
|
@ -903,7 +892,7 @@ static const struct pinmux_ops chv_pinmux_ops = {
|
|
|
|
|
static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
|
|
|
|
unsigned long *config)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
enum pin_config_param param = pinconf_to_config_param(*config);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 ctrl0, ctrl1;
|
|
|
|
@ -980,7 +969,7 @@ static int chv_config_get(struct pinctrl_dev *pctldev, unsigned int pin,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin,
|
|
|
|
|
static int chv_config_set_pull(struct intel_pinctrl *pctrl, unsigned int pin,
|
|
|
|
|
enum pin_config_param param, u32 arg)
|
|
|
|
|
{
|
|
|
|
|
unsigned long flags;
|
|
|
|
@ -1045,7 +1034,7 @@ static int chv_config_set_pull(struct chv_pinctrl *pctrl, unsigned int pin,
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int chv_config_set_oden(struct chv_pinctrl *pctrl, unsigned int pin,
|
|
|
|
|
static int chv_config_set_oden(struct intel_pinctrl *pctrl, unsigned int pin,
|
|
|
|
|
bool enable)
|
|
|
|
|
{
|
|
|
|
|
unsigned long flags;
|
|
|
|
@ -1068,7 +1057,7 @@ static int chv_config_set_oden(struct chv_pinctrl *pctrl, unsigned int pin,
|
|
|
|
|
static int chv_config_set(struct pinctrl_dev *pctldev, unsigned int pin,
|
|
|
|
|
unsigned long *configs, unsigned int nconfigs)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
|
|
|
|
|
enum pin_config_param param;
|
|
|
|
|
int i, ret;
|
|
|
|
|
u32 arg;
|
|
|
|
@ -1169,7 +1158,7 @@ static struct pinctrl_desc chv_pinctrl_desc = {
|
|
|
|
|
|
|
|
|
|
static int chv_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 ctrl0, cfg;
|
|
|
|
|
|
|
|
|
@ -1187,7 +1176,7 @@ static int chv_gpio_get(struct gpio_chip *chip, unsigned int offset)
|
|
|
|
|
|
|
|
|
|
static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 ctrl0;
|
|
|
|
|
|
|
|
|
@ -1207,7 +1196,7 @@ static void chv_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
|
|
|
|
|
|
|
|
|
|
static int chv_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
u32 ctrl0, direction;
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
|
@ -1250,7 +1239,7 @@ static const struct gpio_chip chv_gpio_chip = {
|
|
|
|
|
static void chv_gpio_irq_ack(struct irq_data *d)
|
|
|
|
|
{
|
|
|
|
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
int pin = irqd_to_hwirq(d);
|
|
|
|
|
u32 intr_line;
|
|
|
|
|
|
|
|
|
@ -1267,7 +1256,7 @@ static void chv_gpio_irq_ack(struct irq_data *d)
|
|
|
|
|
static void chv_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
|
|
|
|
|
{
|
|
|
|
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
int pin = irqd_to_hwirq(d);
|
|
|
|
|
u32 value, intr_line;
|
|
|
|
|
unsigned long flags;
|
|
|
|
@ -1312,7 +1301,8 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|
|
|
|
*/
|
|
|
|
|
if (irqd_get_trigger_type(d) == IRQ_TYPE_NONE) {
|
|
|
|
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_community_context *cctx = &pctrl->context.communities[0];
|
|
|
|
|
unsigned int pin = irqd_to_hwirq(d);
|
|
|
|
|
irq_flow_handler_t handler;
|
|
|
|
|
unsigned long flags;
|
|
|
|
@ -1329,9 +1319,9 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|
|
|
|
else
|
|
|
|
|
handler = handle_edge_irq;
|
|
|
|
|
|
|
|
|
|
if (!pctrl->intr_lines[intsel]) {
|
|
|
|
|
if (!cctx->intr_lines[intsel]) {
|
|
|
|
|
irq_set_handler_locked(d, handler);
|
|
|
|
|
pctrl->intr_lines[intsel] = pin;
|
|
|
|
|
cctx->intr_lines[intsel] = pin;
|
|
|
|
|
}
|
|
|
|
|
raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
|
}
|
|
|
|
@ -1343,7 +1333,8 @@ static unsigned chv_gpio_irq_startup(struct irq_data *d)
|
|
|
|
|
static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
|
|
|
|
|
{
|
|
|
|
|
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_community_context *cctx = &pctrl->context.communities[0];
|
|
|
|
|
unsigned int pin = irqd_to_hwirq(d);
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
u32 value;
|
|
|
|
@ -1388,7 +1379,7 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
|
|
|
|
|
value &= CHV_PADCTRL0_INTSEL_MASK;
|
|
|
|
|
value >>= CHV_PADCTRL0_INTSEL_SHIFT;
|
|
|
|
|
|
|
|
|
|
pctrl->intr_lines[value] = pin;
|
|
|
|
|
cctx->intr_lines[value] = pin;
|
|
|
|
|
|
|
|
|
|
if (type & IRQ_TYPE_EDGE_BOTH)
|
|
|
|
|
irq_set_handler_locked(d, handle_edge_irq);
|
|
|
|
@ -1403,8 +1394,9 @@ static int chv_gpio_irq_type(struct irq_data *d, unsigned int type)
|
|
|
|
|
static void chv_gpio_irq_handler(struct irq_desc *desc)
|
|
|
|
|
{
|
|
|
|
|
struct gpio_chip *gc = irq_desc_get_handler_data(desc);
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
struct intel_community_context *cctx = &pctrl->context.communities[0];
|
|
|
|
|
struct irq_chip *chip = irq_desc_get_chip(desc);
|
|
|
|
|
unsigned long pending;
|
|
|
|
|
unsigned long flags;
|
|
|
|
@ -1419,7 +1411,7 @@ static void chv_gpio_irq_handler(struct irq_desc *desc)
|
|
|
|
|
for_each_set_bit(intr_line, &pending, community->nirqs) {
|
|
|
|
|
unsigned int irq, offset;
|
|
|
|
|
|
|
|
|
|
offset = pctrl->intr_lines[intr_line];
|
|
|
|
|
offset = cctx->intr_lines[intr_line];
|
|
|
|
|
irq = irq_find_mapping(gc->irq.domain, offset);
|
|
|
|
|
generic_handle_irq(irq);
|
|
|
|
|
}
|
|
|
|
@ -1472,7 +1464,7 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip,
|
|
|
|
|
unsigned long *valid_mask,
|
|
|
|
|
unsigned int ngpios)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@ -1494,7 +1486,7 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip,
|
|
|
|
|
|
|
|
|
|
static int chv_gpio_irq_init_hw(struct gpio_chip *chip)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -1520,7 +1512,7 @@ static int chv_gpio_irq_init_hw(struct gpio_chip *chip)
|
|
|
|
|
|
|
|
|
|
static int chv_gpio_add_pin_ranges(struct gpio_chip *chip)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
struct intel_pinctrl *pctrl = gpiochip_get_data(chip);
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
const struct intel_padgroup *gpp;
|
|
|
|
|
int ret, i;
|
|
|
|
@ -1539,7 +1531,7 @@ static int chv_gpio_add_pin_ranges(struct gpio_chip *chip)
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
|
|
|
|
|
static int chv_gpio_probe(struct intel_pinctrl *pctrl, int irq)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
const struct intel_padgroup *gpp;
|
|
|
|
@ -1605,7 +1597,7 @@ static acpi_status chv_pinctrl_mmio_access_handler(u32 function,
|
|
|
|
|
acpi_physical_address address, u32 bits, u64 *value,
|
|
|
|
|
void *handler_context, void *region_context)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = region_context;
|
|
|
|
|
struct intel_pinctrl *pctrl = region_context;
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
acpi_status ret = AE_OK;
|
|
|
|
|
|
|
|
|
@ -1625,34 +1617,23 @@ static acpi_status chv_pinctrl_mmio_access_handler(u32 function,
|
|
|
|
|
|
|
|
|
|
static int chv_pinctrl_probe(struct platform_device *pdev)
|
|
|
|
|
{
|
|
|
|
|
const struct intel_pinctrl_soc_data *soc_data = NULL;
|
|
|
|
|
const struct intel_pinctrl_soc_data **soc_table;
|
|
|
|
|
const struct intel_pinctrl_soc_data *soc_data;
|
|
|
|
|
struct intel_community *community;
|
|
|
|
|
struct device *dev = &pdev->dev;
|
|
|
|
|
struct chv_pinctrl *pctrl;
|
|
|
|
|
struct acpi_device *adev;
|
|
|
|
|
struct acpi_device *adev = ACPI_COMPANION(dev);
|
|
|
|
|
struct intel_pinctrl *pctrl;
|
|
|
|
|
acpi_status status;
|
|
|
|
|
int ret, irq, i;
|
|
|
|
|
int ret, irq;
|
|
|
|
|
|
|
|
|
|
adev = ACPI_COMPANION(&pdev->dev);
|
|
|
|
|
if (!adev)
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
|
|
|
|
|
soc_table = (const struct intel_pinctrl_soc_data **)device_get_match_data(dev);
|
|
|
|
|
for (i = 0; soc_table[i]; i++) {
|
|
|
|
|
if (!strcmp(adev->pnp.unique_id, soc_table[i]->uid)) {
|
|
|
|
|
soc_data = soc_table[i];
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!soc_data)
|
|
|
|
|
return -ENODEV;
|
|
|
|
|
soc_data = intel_pinctrl_get_soc_data(pdev);
|
|
|
|
|
if (IS_ERR(soc_data))
|
|
|
|
|
return PTR_ERR(soc_data);
|
|
|
|
|
|
|
|
|
|
pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL);
|
|
|
|
|
if (!pctrl)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
pctrl->dev = &pdev->dev;
|
|
|
|
|
pctrl->dev = dev;
|
|
|
|
|
pctrl->soc = soc_data;
|
|
|
|
|
|
|
|
|
|
pctrl->ncommunities = pctrl->soc->ncommunities;
|
|
|
|
@ -1677,19 +1658,24 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
pctrl->context.communities = devm_kcalloc(dev, pctrl->soc->ncommunities,
|
|
|
|
|
sizeof(*pctrl->context.communities),
|
|
|
|
|
GFP_KERNEL);
|
|
|
|
|
if (!pctrl->context.communities)
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
irq = platform_get_irq(pdev, 0);
|
|
|
|
|
if (irq < 0)
|
|
|
|
|
return irq;
|
|
|
|
|
|
|
|
|
|
pctrl->pctldesc = chv_pinctrl_desc;
|
|
|
|
|
pctrl->pctldesc.name = dev_name(&pdev->dev);
|
|
|
|
|
pctrl->pctldesc.name = dev_name(dev);
|
|
|
|
|
pctrl->pctldesc.pins = pctrl->soc->pins;
|
|
|
|
|
pctrl->pctldesc.npins = pctrl->soc->npins;
|
|
|
|
|
|
|
|
|
|
pctrl->pctldev = devm_pinctrl_register(&pdev->dev, &pctrl->pctldesc,
|
|
|
|
|
pctrl);
|
|
|
|
|
pctrl->pctldev = devm_pinctrl_register(dev, &pctrl->pctldesc, pctrl);
|
|
|
|
|
if (IS_ERR(pctrl->pctldev)) {
|
|
|
|
|
dev_err(&pdev->dev, "failed to register pinctrl driver\n");
|
|
|
|
|
dev_err(dev, "failed to register pinctrl driver\n");
|
|
|
|
|
return PTR_ERR(pctrl->pctldev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1702,7 +1688,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
|
|
|
|
|
chv_pinctrl_mmio_access_handler,
|
|
|
|
|
NULL, pctrl);
|
|
|
|
|
if (ACPI_FAILURE(status))
|
|
|
|
|
dev_err(&pdev->dev, "failed to install ACPI addr space handler\n");
|
|
|
|
|
dev_err(dev, "failed to install ACPI addr space handler\n");
|
|
|
|
|
|
|
|
|
|
platform_set_drvdata(pdev, pctrl);
|
|
|
|
|
|
|
|
|
@ -1711,7 +1697,7 @@ static int chv_pinctrl_probe(struct platform_device *pdev)
|
|
|
|
|
|
|
|
|
|
static int chv_pinctrl_remove(struct platform_device *pdev)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = platform_get_drvdata(pdev);
|
|
|
|
|
struct intel_pinctrl *pctrl = platform_get_drvdata(pdev);
|
|
|
|
|
const struct intel_community *community = &pctrl->communities[0];
|
|
|
|
|
|
|
|
|
|
acpi_remove_address_space_handler(ACPI_COMPANION(&pdev->dev),
|
|
|
|
@ -1724,13 +1710,14 @@ static int chv_pinctrl_remove(struct platform_device *pdev)
|
|
|
|
|
#ifdef CONFIG_PM_SLEEP
|
|
|
|
|
static int chv_pinctrl_suspend_noirq(struct device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = dev_get_drvdata(dev);
|
|
|
|
|
struct intel_pinctrl *pctrl = dev_get_drvdata(dev);
|
|
|
|
|
struct intel_community_context *cctx = &pctrl->context.communities[0];
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
raw_spin_lock_irqsave(&chv_lock, flags);
|
|
|
|
|
|
|
|
|
|
pctrl->saved_intmask = chv_pctrl_readl(pctrl, CHV_INTMASK);
|
|
|
|
|
cctx->saved_intmask = chv_pctrl_readl(pctrl, CHV_INTMASK);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < pctrl->soc->npins; i++) {
|
|
|
|
|
const struct pinctrl_pin_desc *desc;
|
|
|
|
@ -1753,7 +1740,8 @@ static int chv_pinctrl_suspend_noirq(struct device *dev)
|
|
|
|
|
|
|
|
|
|
static int chv_pinctrl_resume_noirq(struct device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct chv_pinctrl *pctrl = dev_get_drvdata(dev);
|
|
|
|
|
struct intel_pinctrl *pctrl = dev_get_drvdata(dev);
|
|
|
|
|
struct intel_community_context *cctx = &pctrl->context.communities[0];
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
@ -1797,7 +1785,7 @@ static int chv_pinctrl_resume_noirq(struct device *dev)
|
|
|
|
|
* the interrupt mask register as well.
|
|
|
|
|
*/
|
|
|
|
|
chv_pctrl_writel(pctrl, CHV_INTSTAT, 0xffff);
|
|
|
|
|
chv_pctrl_writel(pctrl, CHV_INTMASK, pctrl->saved_intmask);
|
|
|
|
|
chv_pctrl_writel(pctrl, CHV_INTMASK, cctx->saved_intmask);
|
|
|
|
|
|
|
|
|
|
raw_spin_unlock_irqrestore(&chv_lock, flags);
|
|
|
|
|
|
|
|
|
|