Commit 3dda927f authored by Linus Walleij's avatar Linus Walleij

Merge branch 'ib-qcom-ssbi' into devel

parents 9aac1e33 79890c2e
......@@ -93,9 +93,8 @@ cm3605 {
vdd-supply = <&pm8058_l14>; // 2.85V
aset-gpios = <&pm8058_gpio 35 GPIO_ACTIVE_LOW>;
capella,aset-resistance-ohms = <100000>;
/* GPIO34 has interrupt 225 on the PM8058 */
/* Trig on both edges - getting close or far away */
interrupts-extended = <&pm8058 225 IRQ_TYPE_EDGE_BOTH>;
interrupts-extended = <&pm8058_gpio 34 IRQ_TYPE_EDGE_BOTH>;
/* MPP05 analog input to the XOADC */
io-channels = <&xoadc 0x00 0x05>;
io-channel-names = "aout";
......@@ -515,9 +514,8 @@ i2c@19c80000 {
ak8975@c {
compatible = "asahi-kasei,ak8975";
reg = <0x0c>;
/* FIXME: GPIO33 has interrupt 224 on the PM8058 */
interrupt-parent = <&pm8058>;
interrupts = <224 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&pm8058_gpio>;
interrupts = <33 IRQ_TYPE_EDGE_RISING>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_ak8975_gpios>;
vid-supply = <&pm8058_lvs0>; // 1.8V
......@@ -526,9 +524,8 @@ ak8975@c {
bmp085@77 {
compatible = "bosch,bmp085";
reg = <0x77>;
/* FIXME: GPIO16 has interrupt 207 on the PM8058 */
interrupt-parent = <&pm8058>;
interrupts = <207 IRQ_TYPE_EDGE_RISING>;
interrupt-parent = <&pm8058_gpio>;
interrupts = <16 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&tlmm 86 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_bmp085_gpios>;
......@@ -539,12 +536,11 @@ mpu3050@68 {
compatible = "invensense,mpu3050";
reg = <0x68>;
/*
* GPIO17 has interrupt 208 on the
* PM8058, it is pulled high by a 10k
* GPIO17 is pulled high by a 10k
* resistor to VLOGIC so needs to be
* active low/falling edge.
*/
interrupts-extended = <&pm8058 208 IRQ_TYPE_EDGE_FALLING>;
interrupts-extended = <&pm8058_gpio 17 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
pinctrl-0 = <&dragon_mpu3050_gpios>;
vlogic-supply = <&pm8058_lvs0>; // 1.8V
......@@ -589,11 +585,10 @@ ethernet-ebi2@2,0 {
compatible = "smsc,lan9221", "smsc,lan9115";
reg = <2 0x0 0x100>;
/*
* GPIO7 has interrupt 198 on the PM8058
* The second interrupt is the PME interrupt
* for network wakeup, connected to the TLMM.
*/
interrupts-extended = <&pm8058 198 IRQ_TYPE_EDGE_FALLING>,
interrupts-extended = <&pm8058_gpio 7 IRQ_TYPE_EDGE_FALLING>,
<&tlmm 29 IRQ_TYPE_EDGE_RISING>;
reset-gpios = <&tlmm 30 GPIO_ACTIVE_LOW>;
vdd33a-supply = <&dragon_veth>;
......
......@@ -705,50 +705,8 @@ pm8921_gpio: gpio@150 {
compatible = "qcom,pm8921-gpio",
"qcom,ssbi-gpio";
reg = <0x150>;
interrupts = <192 IRQ_TYPE_NONE>,
<193 IRQ_TYPE_NONE>,
<194 IRQ_TYPE_NONE>,
<195 IRQ_TYPE_NONE>,
<196 IRQ_TYPE_NONE>,
<197 IRQ_TYPE_NONE>,
<198 IRQ_TYPE_NONE>,
<199 IRQ_TYPE_NONE>,
<200 IRQ_TYPE_NONE>,
<201 IRQ_TYPE_NONE>,
<202 IRQ_TYPE_NONE>,
<203 IRQ_TYPE_NONE>,
<204 IRQ_TYPE_NONE>,
<205 IRQ_TYPE_NONE>,
<206 IRQ_TYPE_NONE>,
<207 IRQ_TYPE_NONE>,
<208 IRQ_TYPE_NONE>,
<209 IRQ_TYPE_NONE>,
<210 IRQ_TYPE_NONE>,
<211 IRQ_TYPE_NONE>,
<212 IRQ_TYPE_NONE>,
<213 IRQ_TYPE_NONE>,
<214 IRQ_TYPE_NONE>,
<215 IRQ_TYPE_NONE>,
<216 IRQ_TYPE_NONE>,
<217 IRQ_TYPE_NONE>,
<218 IRQ_TYPE_NONE>,
<219 IRQ_TYPE_NONE>,
<220 IRQ_TYPE_NONE>,
<221 IRQ_TYPE_NONE>,
<222 IRQ_TYPE_NONE>,
<223 IRQ_TYPE_NONE>,
<224 IRQ_TYPE_NONE>,
<225 IRQ_TYPE_NONE>,
<226 IRQ_TYPE_NONE>,
<227 IRQ_TYPE_NONE>,
<228 IRQ_TYPE_NONE>,
<229 IRQ_TYPE_NONE>,
<230 IRQ_TYPE_NONE>,
<231 IRQ_TYPE_NONE>,
<232 IRQ_TYPE_NONE>,
<233 IRQ_TYPE_NONE>,
<234 IRQ_TYPE_NONE>,
<235 IRQ_TYPE_NONE>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
......
......@@ -323,13 +323,8 @@ rtc@11d {
pmicgpio: gpio@150 {
compatible = "qcom,pm8018-gpio", "qcom,ssbi-gpio";
interrupt-parent = <&pmicintc>;
interrupts = <24 IRQ_TYPE_NONE>,
<25 IRQ_TYPE_NONE>,
<26 IRQ_TYPE_NONE>,
<27 IRQ_TYPE_NONE>,
<28 IRQ_TYPE_NONE>,
<29 IRQ_TYPE_NONE>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
};
......
......@@ -285,51 +285,8 @@ pm8058_gpio: gpio@150 {
compatible = "qcom,pm8058-gpio",
"qcom,ssbi-gpio";
reg = <0x150>;
interrupt-parent = <&pm8058>;
interrupts = <192 IRQ_TYPE_NONE>,
<193 IRQ_TYPE_NONE>,
<194 IRQ_TYPE_NONE>,
<195 IRQ_TYPE_NONE>,
<196 IRQ_TYPE_NONE>,
<197 IRQ_TYPE_NONE>,
<198 IRQ_TYPE_NONE>,
<199 IRQ_TYPE_NONE>,
<200 IRQ_TYPE_NONE>,
<201 IRQ_TYPE_NONE>,
<202 IRQ_TYPE_NONE>,
<203 IRQ_TYPE_NONE>,
<204 IRQ_TYPE_NONE>,
<205 IRQ_TYPE_NONE>,
<206 IRQ_TYPE_NONE>,
<207 IRQ_TYPE_NONE>,
<208 IRQ_TYPE_NONE>,
<209 IRQ_TYPE_NONE>,
<210 IRQ_TYPE_NONE>,
<211 IRQ_TYPE_NONE>,
<212 IRQ_TYPE_NONE>,
<213 IRQ_TYPE_NONE>,
<214 IRQ_TYPE_NONE>,
<215 IRQ_TYPE_NONE>,
<216 IRQ_TYPE_NONE>,
<217 IRQ_TYPE_NONE>,
<218 IRQ_TYPE_NONE>,
<219 IRQ_TYPE_NONE>,
<220 IRQ_TYPE_NONE>,
<221 IRQ_TYPE_NONE>,
<222 IRQ_TYPE_NONE>,
<223 IRQ_TYPE_NONE>,
<224 IRQ_TYPE_NONE>,
<225 IRQ_TYPE_NONE>,
<226 IRQ_TYPE_NONE>,
<227 IRQ_TYPE_NONE>,
<228 IRQ_TYPE_NONE>,
<229 IRQ_TYPE_NONE>,
<230 IRQ_TYPE_NONE>,
<231 IRQ_TYPE_NONE>,
<232 IRQ_TYPE_NONE>,
<233 IRQ_TYPE_NONE>,
<234 IRQ_TYPE_NONE>,
<235 IRQ_TYPE_NONE>;
interrupt-controller;
#interrupt-cells = <2>;
gpio-controller;
#gpio-cells = <2>;
......
......@@ -928,7 +928,7 @@ config UCB1400_CORE
config MFD_PM8XXX
tristate "Qualcomm PM8xxx PMIC chips driver"
depends on (ARM || HEXAGON || COMPILE_TEST)
select IRQ_DOMAIN
select IRQ_DOMAIN_HIERARCHY
select MFD_CORE
select REGMAP
help
......
......@@ -70,22 +70,23 @@
#define PM8XXX_NR_IRQS 256
#define PM8821_NR_IRQS 112
struct pm_irq_data {
int num_irqs;
struct irq_chip *irq_chip;
void (*irq_handler)(struct irq_desc *desc);
};
struct pm_irq_chip {
struct regmap *regmap;
spinlock_t pm_irq_lock;
struct irq_domain *irqdomain;
unsigned int num_irqs;
unsigned int num_blocks;
unsigned int num_masters;
const struct pm_irq_data *pm_irq_data;
/* MUST BE AT THE END OF THIS STRUCT */
u8 config[0];
};
struct pm_irq_data {
int num_irqs;
const struct irq_domain_ops *irq_domain_ops;
void (*irq_handler)(struct irq_desc *desc);
};
static int pm8xxx_read_block_irq(struct pm_irq_chip *chip, unsigned int bp,
unsigned int *ip)
{
......@@ -375,21 +376,38 @@ static struct irq_chip pm8xxx_irq_chip = {
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static int pm8xxx_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
static void pm8xxx_irq_domain_map(struct pm_irq_chip *chip,
struct irq_domain *domain, unsigned int irq,
irq_hw_number_t hwirq, unsigned int type)
{
struct pm_irq_chip *chip = d->host_data;
irq_set_chip_and_handler(irq, &pm8xxx_irq_chip, handle_level_irq);
irq_set_chip_data(irq, chip);
irq_domain_set_info(domain, irq, hwirq, chip->pm_irq_data->irq_chip,
chip, handle_level_irq, NULL, NULL);
irq_set_noprobe(irq);
}
static int pm8xxx_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct pm_irq_chip *chip = domain->host_data;
struct irq_fwspec *fwspec = data;
irq_hw_number_t hwirq;
unsigned int type;
int ret, i;
ret = irq_domain_translate_twocell(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
for (i = 0; i < nr_irqs; i++)
pm8xxx_irq_domain_map(chip, domain, virq + i, hwirq + i, type);
return 0;
}
static const struct irq_domain_ops pm8xxx_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
.map = pm8xxx_irq_domain_map,
.alloc = pm8xxx_irq_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = irq_domain_translate_twocell,
};
static void pm8821_irq_mask_ack(struct irq_data *d)
......@@ -473,23 +491,6 @@ static struct irq_chip pm8821_irq_chip = {
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static int pm8821_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hwirq)
{
struct pm_irq_chip *chip = d->host_data;
irq_set_chip_and_handler(irq, &pm8821_irq_chip, handle_level_irq);
irq_set_chip_data(irq, chip);
irq_set_noprobe(irq);
return 0;
}
static const struct irq_domain_ops pm8821_irq_domain_ops = {
.xlate = irq_domain_xlate_twocell,
.map = pm8821_irq_domain_map,
};
static const struct regmap_config ssbi_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
......@@ -501,13 +502,13 @@ static const struct regmap_config ssbi_regmap_config = {
static const struct pm_irq_data pm8xxx_data = {
.num_irqs = PM8XXX_NR_IRQS,
.irq_domain_ops = &pm8xxx_irq_domain_ops,
.irq_chip = &pm8xxx_irq_chip,
.irq_handler = pm8xxx_irq_handler,
};
static const struct pm_irq_data pm8821_data = {
.num_irqs = PM8821_NR_IRQS,
.irq_domain_ops = &pm8821_irq_domain_ops,
.irq_chip = &pm8821_irq_chip,
.irq_handler = pm8821_irq_handler,
};
......@@ -571,14 +572,14 @@ static int pm8xxx_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, chip);
chip->regmap = regmap;
chip->num_irqs = data->num_irqs;
chip->num_blocks = DIV_ROUND_UP(chip->num_irqs, 8);
chip->num_blocks = DIV_ROUND_UP(data->num_irqs, 8);
chip->num_masters = DIV_ROUND_UP(chip->num_blocks, 8);
chip->pm_irq_data = data;
spin_lock_init(&chip->pm_irq_lock);
chip->irqdomain = irq_domain_add_linear(pdev->dev.of_node,
data->num_irqs,
data->irq_domain_ops,
&pm8xxx_irq_domain_ops,
chip);
if (!chip->irqdomain)
return -ENODEV;
......
......@@ -150,6 +150,7 @@ config PINCTRL_QCOM_SSBI_PMIC
select PINMUX
select PINCONF
select GENERIC_PINCONF
select IRQ_DOMAIN_HIERARCHY
help
This is the pinctrl, pinmux, pinconf and gpiolib driver for the
Qualcomm GPIO and MPP blocks found in the Qualcomm PMIC's chips,
......
......@@ -55,6 +55,8 @@
#define PM8XXX_MAX_GPIOS 44
#define PM8XXX_GPIO_PHYSICAL_OFFSET 1
/* custom pinconf parameters */
#define PM8XXX_QCOM_DRIVE_STRENGH (PIN_CONFIG_END + 1)
#define PM8XXX_QCOM_PULL_UP_STRENGTH (PIN_CONFIG_END + 2)
......@@ -99,6 +101,9 @@ struct pm8xxx_gpio {
struct pinctrl_desc desc;
unsigned npins;
struct fwnode_handle *fwnode;
struct irq_domain *domain;
};
static const struct pinconf_generic_params pm8xxx_gpio_bindings[] = {
......@@ -499,11 +504,12 @@ static int pm8xxx_gpio_get(struct gpio_chip *chip, unsigned offset)
if (pin->mode == PM8XXX_GPIO_MODE_OUTPUT) {
ret = pin->output_value;
} else {
} else if (pin->irq >= 0) {
ret = irq_get_irqchip_state(pin->irq, IRQCHIP_STATE_LINE_LEVEL, &state);
if (!ret)
ret = !!state;
}
} else
ret = -EINVAL;
return ret;
}
......@@ -533,16 +539,39 @@ static int pm8xxx_gpio_of_xlate(struct gpio_chip *chip,
if (flags)
*flags = gpio_desc->args[1];
return gpio_desc->args[0] - 1;
return gpio_desc->args[0] - PM8XXX_GPIO_PHYSICAL_OFFSET;
}
static int pm8xxx_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
{
struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
struct irq_fwspec fwspec;
int ret;
fwspec.fwnode = pctrl->fwnode;
fwspec.param_count = 2;
fwspec.param[0] = offset + PM8XXX_GPIO_PHYSICAL_OFFSET;
fwspec.param[1] = IRQ_TYPE_EDGE_RISING;
ret = irq_create_fwspec_mapping(&fwspec);
/*
* Cache the IRQ since pm8xxx_gpio_get() needs this to get determine the
* line level.
*/
pin->irq = ret;
return ret;
}
static void pm8xxx_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
struct pm8xxx_gpio *pctrl = gpiochip_get_data(chip);
struct pm8xxx_pin_data *pin = pctrl->desc.pins[offset].drv_data;
return pin->irq;
pin->irq = -1;
}
#ifdef CONFIG_DEBUG_FS
......@@ -571,7 +600,7 @@ static void pm8xxx_gpio_dbg_show_one(struct seq_file *s,
"no", "high", "medium", "low"
};
seq_printf(s, " gpio%-2d:", offset + 1);
seq_printf(s, " gpio%-2d:", offset + PM8XXX_GPIO_PHYSICAL_OFFSET);
if (pin->disable) {
seq_puts(s, " ---");
} else {
......@@ -603,6 +632,7 @@ static void pm8xxx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
#endif
static const struct gpio_chip pm8xxx_gpio_template = {
.free = pm8xxx_gpio_free,
.direction_input = pm8xxx_gpio_direction_input,
.direction_output = pm8xxx_gpio_direction_output,
.get = pm8xxx_gpio_get,
......@@ -664,13 +694,75 @@ static int pm8xxx_pin_populate(struct pm8xxx_gpio *pctrl,
return 0;
}
static struct irq_chip pm8xxx_irq_chip = {
.name = "ssbi-gpio",
.irq_mask_ack = irq_chip_mask_ack_parent,
.irq_unmask = irq_chip_unmask_parent,
.irq_set_type = irq_chip_set_type_parent,
.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static int pm8xxx_domain_translate(struct irq_domain *domain,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
struct pm8xxx_gpio *pctrl = container_of(domain->host_data,
struct pm8xxx_gpio, chip);
if (fwspec->param_count != 2 || fwspec->param[0] < 1 ||
fwspec->param[0] > pctrl->chip.ngpio)
return -EINVAL;
*hwirq = fwspec->param[0] - PM8XXX_GPIO_PHYSICAL_OFFSET;
*type = fwspec->param[1];
return 0;
}
static int pm8xxx_domain_alloc(struct irq_domain *domain, unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct pm8xxx_gpio *pctrl = container_of(domain->host_data,
struct pm8xxx_gpio, chip);
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
unsigned int type;
int ret, i;
ret = pm8xxx_domain_translate(domain, fwspec, &hwirq, &type);
if (ret)
return ret;
for (i = 0; i < nr_irqs; i++)
irq_domain_set_info(domain, virq + i, hwirq + i,
&pm8xxx_irq_chip, pctrl, handle_level_irq,
NULL, NULL);
parent_fwspec.fwnode = domain->parent->fwnode;
parent_fwspec.param_count = 2;
parent_fwspec.param[0] = hwirq + 0xc0;
parent_fwspec.param[1] = fwspec->param[1];
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
&parent_fwspec);
}
static const struct irq_domain_ops pm8xxx_domain_ops = {
.activate = gpiochip_irq_domain_activate,
.alloc = pm8xxx_domain_alloc,
.deactivate = gpiochip_irq_domain_deactivate,
.free = irq_domain_free_irqs_common,
.translate = pm8xxx_domain_translate,
};
static const struct of_device_id pm8xxx_gpio_of_match[] = {
{ .compatible = "qcom,pm8018-gpio" },
{ .compatible = "qcom,pm8038-gpio" },
{ .compatible = "qcom,pm8058-gpio" },
{ .compatible = "qcom,pm8917-gpio" },
{ .compatible = "qcom,pm8921-gpio" },
{ .compatible = "qcom,ssbi-gpio" },
{ .compatible = "qcom,pm8018-gpio", .data = (void *) 6 },
{ .compatible = "qcom,pm8038-gpio", .data = (void *) 12 },
{ .compatible = "qcom,pm8058-gpio", .data = (void *) 44 },
{ .compatible = "qcom,pm8917-gpio", .data = (void *) 38 },
{ .compatible = "qcom,pm8921-gpio", .data = (void *) 44 },
{ },
};
MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match);
......@@ -678,22 +770,18 @@ MODULE_DEVICE_TABLE(of, pm8xxx_gpio_of_match);
static int pm8xxx_gpio_probe(struct platform_device *pdev)
{
struct pm8xxx_pin_data *pin_data;
struct irq_domain *parent_domain;
struct device_node *parent_node;
struct pinctrl_pin_desc *pins;
struct pm8xxx_gpio *pctrl;
int ret;
int i, npins;
int ret, i;
pctrl = devm_kzalloc(&pdev->dev, sizeof(*pctrl), GFP_KERNEL);
if (!pctrl)
return -ENOMEM;
pctrl->dev = &pdev->dev;
npins = platform_irq_count(pdev);
if (!npins)
return -EINVAL;
if (npins < 0)
return npins;
pctrl->npins = npins;
pctrl->npins = (uintptr_t) device_get_match_data(&pdev->dev);
pctrl->regmap = dev_get_regmap(pdev->dev.parent, NULL);
if (!pctrl->regmap) {
......@@ -720,12 +808,7 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
for (i = 0; i < pctrl->desc.npins; i++) {
pin_data[i].reg = SSBI_REG_ADDR_GPIO(i);
pin_data[i].irq = platform_get_irq(pdev, i);
if (pin_data[i].irq < 0) {
dev_err(&pdev->dev,
"missing interrupts for pin %d\n", i);
return pin_data[i].irq;
}
pin_data[i].irq = -1;
ret = pm8xxx_pin_populate(pctrl, &pin_data[i]);
if (ret)
......@@ -756,10 +839,29 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
pctrl->chip.of_gpio_n_cells = 2;
pctrl->chip.label = dev_name(pctrl->dev);
pctrl->chip.ngpio = pctrl->npins;
parent_node = of_irq_find_parent(pctrl->dev->of_node);
if (!parent_node)
return -ENXIO;
parent_domain = irq_find_host(parent_node);
of_node_put(parent_node);
if (!parent_domain)
return -ENXIO;
pctrl->fwnode = of_node_to_fwnode(pctrl->dev->of_node);
pctrl->domain = irq_domain_create_hierarchy(parent_domain, 0,
pctrl->chip.ngpio,
pctrl->fwnode,
&pm8xxx_domain_ops,
&pctrl->chip);
if (!pctrl->domain)
return -ENODEV;
ret = gpiochip_add_data(&pctrl->chip, pctrl);
if (ret) {
dev_err(&pdev->dev, "failed register gpiochip\n");
return ret;
goto err_chip_add_data;
}
/*
......@@ -789,6 +891,8 @@ static int pm8xxx_gpio_probe(struct platform_device *pdev)
unregister_gpiochip:
gpiochip_remove(&pctrl->chip);
err_chip_add_data:
irq_domain_remove(pctrl->domain);
return ret;
}
......@@ -798,6 +902,7 @@ static int pm8xxx_gpio_remove(struct platform_device *pdev)
struct pm8xxx_gpio *pctrl = platform_get_drvdata(pdev);
gpiochip_remove(&pctrl->chip);
irq_domain_remove(pctrl->domain);
return 0;
}
......
......@@ -605,6 +605,7 @@ extern void irq_chip_disable_parent(struct irq_data *data);
extern void irq_chip_ack_parent(struct irq_data *data);
extern int irq_chip_retrigger_hierarchy(struct irq_data *data);
extern void irq_chip_mask_parent(struct irq_data *data);
extern void irq_chip_mask_ack_parent(struct irq_data *data);
extern void irq_chip_unmask_parent(struct irq_data *data);
extern void irq_chip_eoi_parent(struct irq_data *data);
extern int irq_chip_set_affinity_parent(struct irq_data *data,
......
......@@ -419,6 +419,11 @@ int irq_domain_xlate_onetwocell(struct irq_domain *d, struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type);
int irq_domain_translate_twocell(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *out_hwirq,
unsigned int *out_type);
/* IPI functions */
int irq_reserve_ipi(struct irq_domain *domain, const struct cpumask *dest);
int irq_destroy_ipi(unsigned int irq, const struct cpumask *dest);
......
......@@ -1277,6 +1277,17 @@ void irq_chip_mask_parent(struct irq_data *data)
}
EXPORT_SYMBOL_GPL(irq_chip_mask_parent);
/**
* irq_chip_mask_ack_parent - Mask and acknowledge the parent interrupt
* @data: Pointer to interrupt specific data
*/
void irq_chip_mask_ack_parent(struct irq_data *data)
{
data = data->parent_data;
data->chip->irq_mask_ack(data);
}
EXPORT_SYMBOL_GPL(irq_chip_mask_ack_parent);
/**
* irq_chip_unmask_parent - Unmask the parent interrupt
* @data: Pointer to interrupt specific data
......
......@@ -729,16 +729,17 @@ static int irq_domain_translate(struct irq_domain *d,
return 0;
}
static void of_phandle_args_to_fwspec(struct of_phandle_args *irq_data,
static void of_phandle_args_to_fwspec(struct device_node *np, const u32 *args,
unsigned int count,
struct irq_fwspec *fwspec)
{
int i;
fwspec->fwnode = irq_data->np ? &irq_data->np->fwnode : NULL;
fwspec->param_count = irq_data->args_count;
fwspec->fwnode = np ? &np->fwnode : NULL;
fwspec->param_count = count;
for (i = 0; i < irq_data->args_count; i++)
fwspec->param[i] = irq_data->args[i];
for (i = 0; i < count; i++)
fwspec->param[i] = args[i];
}
unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
......@@ -836,7 +837,9 @@ unsigned int irq_create_of_mapping(struct of_phandle_args *irq_data)
{
struct irq_fwspec fwspec;
of_phandle_args_to_fwspec(irq_data, &fwspec);
of_phandle_args_to_fwspec(irq_data->np, irq_data->args,
irq_data->args_count, &fwspec);
return irq_create_fwspec_mapping(&fwspec);
}
EXPORT_SYMBOL_GPL(irq_create_of_mapping);
......@@ -928,11 +931,10 @@ int irq_domain_xlate_twocell(struct irq_domain *d, struct device_node *ctrlr,
const u32 *intspec, unsigned int intsize,
irq_hw_number_t *out_hwirq, unsigned int *out_type)
{
if (WARN_ON(intsize < 2))
return -EINVAL;
*out_hwirq = intspec[0];
*out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
return 0;
struct irq_fwspec fwspec;
of_phandle_args_to_fwspec(ctrlr, intspec, intsize, &fwspec);
return irq_domain_translate_twocell(d, &fwspec, out_hwirq, out_type);
}
EXPORT_SYMBOL_GPL(irq_domain_xlate_twocell);
......@@ -968,6 +970,27 @@ const struct irq_domain_ops irq_domain_simple_ops = {
};
EXPORT_SYMBOL_GPL(irq_domain_simple_ops);
/**
* irq_domain_translate_twocell() - Generic translate for direct two cell
* bindings
*
* Device Tree IRQ specifier translation function which works with two cell
* bindings where the cell values map directly to the hwirq number
* and linux irq flags.
*/
int irq_domain_translate_twocell(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *out_hwirq,
unsigned int *out_type)
{
if (WARN_ON(fwspec->param_count < 2))
return -EINVAL;
*out_hwirq = fwspec->param[0];
*out_type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
return 0;
}
EXPORT_SYMBOL_GPL(irq_domain_translate_twocell);
int irq_domain_alloc_descs(int virq, unsigned int cnt, irq_hw_number_t hwirq,
int node, const struct irq_affinity_desc *affinity)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment