mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Commit3ef9f710ef
("pinctrl: mediatek: Add EINT support for multiple addresses") introduced an access to the 'soc' field of struct mtk_pinctrl in mtk_eint_do_init() and for that an include of pinctrl-mtk-common-v2.h. However, pinctrl drivers relying on the v1 common driver include pinctrl-mtk-common.h instead, which provides another definition of struct mtk_pinctrl that does not contain an 'soc' field. Since mtk_eint_do_init() can be called both by v1 and v2 drivers, it will now try to dereference an invalid pointer when called on v1 platforms. This has been observed on Genio 350 EVK (MT8365), which crashes very early in boot (the kernel trace can only be seen with earlycon). In order to fix this, since 'struct mtk_pinctrl' was only needed to get a 'struct mtk_eint_pin', make 'struct mtk_eint_pin' a parameter of mtk_eint_do_init() so that callers need to supply it, removing mtk_eint_do_init()'s dependency on any particular 'struct mtk_pinctrl'. Fixes:3ef9f710ef
("pinctrl: mediatek: Add EINT support for multiple addresses") Suggested-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> Signed-off-by: Nícolas F. R. A. Prado <nfraprado@collabora.com> Link: https://lore.kernel.org/20250520-genio-350-eint-null-ptr-deref-fix-v2-1-6a3ca966a7ba@collabora.com Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
126 lines
2.8 KiB
C
126 lines
2.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Copyright (C) 2014-2025 MediaTek Inc.
|
|
*
|
|
* Author: Maoguang Meng <maoguang.meng@mediatek.com>
|
|
* Sean Wang <sean.wang@mediatek.com>
|
|
* Hao Chang <ot_chhao.chang@mediatek.com>
|
|
* Qingliang Li <qingliang.li@mediatek.com>
|
|
*/
|
|
#ifndef __MTK_EINT_H
|
|
#define __MTK_EINT_H
|
|
|
|
#include <linux/irqdomain.h>
|
|
|
|
struct mtk_eint_regs {
|
|
unsigned int stat;
|
|
unsigned int ack;
|
|
unsigned int mask;
|
|
unsigned int mask_set;
|
|
unsigned int mask_clr;
|
|
unsigned int sens;
|
|
unsigned int sens_set;
|
|
unsigned int sens_clr;
|
|
unsigned int soft;
|
|
unsigned int soft_set;
|
|
unsigned int soft_clr;
|
|
unsigned int pol;
|
|
unsigned int pol_set;
|
|
unsigned int pol_clr;
|
|
unsigned int dom_en;
|
|
unsigned int dbnc_ctrl;
|
|
unsigned int dbnc_set;
|
|
unsigned int dbnc_clr;
|
|
};
|
|
|
|
struct mtk_eint_hw {
|
|
u8 port_mask;
|
|
u8 ports;
|
|
unsigned int ap_num;
|
|
unsigned int db_cnt;
|
|
const unsigned int *db_time;
|
|
};
|
|
|
|
struct mtk_eint_pin {
|
|
u16 number;
|
|
u8 instance;
|
|
u8 index;
|
|
bool debounce;
|
|
bool dual_edge;
|
|
};
|
|
|
|
extern const unsigned int debounce_time_mt2701[];
|
|
extern const unsigned int debounce_time_mt6765[];
|
|
extern const unsigned int debounce_time_mt6795[];
|
|
|
|
struct mtk_eint;
|
|
|
|
struct mtk_eint_xt {
|
|
int (*get_gpio_n)(void *data, unsigned long eint_n,
|
|
unsigned int *gpio_n,
|
|
struct gpio_chip **gpio_chip);
|
|
int (*get_gpio_state)(void *data, unsigned long eint_n);
|
|
int (*set_gpio_as_eint)(void *data, unsigned long eint_n);
|
|
};
|
|
|
|
struct mtk_eint {
|
|
struct device *dev;
|
|
void __iomem **base;
|
|
int nbase;
|
|
u16 *base_pin_num;
|
|
struct irq_domain *domain;
|
|
int irq;
|
|
|
|
int *dual_edge;
|
|
u16 **pin_list;
|
|
u32 **wake_mask;
|
|
u32 **cur_mask;
|
|
|
|
/* Used to fit into various EINT device */
|
|
const struct mtk_eint_hw *hw;
|
|
const struct mtk_eint_regs *regs;
|
|
struct mtk_eint_pin *pins;
|
|
u16 num_db_time;
|
|
|
|
/* Used to fit into various pinctrl device */
|
|
void *pctl;
|
|
const struct mtk_eint_xt *gpio_xlate;
|
|
};
|
|
|
|
#if IS_ENABLED(CONFIG_EINT_MTK)
|
|
int mtk_eint_do_init(struct mtk_eint *eint, struct mtk_eint_pin *eint_pin);
|
|
int mtk_eint_do_suspend(struct mtk_eint *eint);
|
|
int mtk_eint_do_resume(struct mtk_eint *eint);
|
|
int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
|
|
unsigned int debounce);
|
|
int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n);
|
|
|
|
#else
|
|
static inline int mtk_eint_do_init(struct mtk_eint *eint,
|
|
struct mtk_eint_pin *eint_pin)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int mtk_eint_do_suspend(struct mtk_eint *eint)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int mtk_eint_do_resume(struct mtk_eint *eint)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_n,
|
|
unsigned int debounce)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
static inline int mtk_eint_find_irq(struct mtk_eint *eint, unsigned long eint_n)
|
|
{
|
|
return -EOPNOTSUPP;
|
|
}
|
|
#endif
|
|
#endif /* __MTK_EINT_H */
|