Pin control fixes for the v5.17 kernel cycle:
- Fix up group name building on the Intel Thunderbay - Fix interrupt problems on the Intel Cherryview - Fix some pin data on the Sunxi H616 - Fix up the CONFIG_PINCTRL_ST Kconfig sort order as noted during the merge window - Fix an unexpected interrupt problem on the Intel Sunrisepoint - Fix a glitch when updating IRQ flags on all Intel pin controllers - Revert a Zynqmp patch to unify the pin naming, let's find some better solution - Fix some error paths in the Broadcom BCM2835 driver - Fix a Kconfig problem pertaining to the BCM63XX drivers - Fix the regmap support in the Microchip SGPIO driver -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEElDRnuGcz/wPCXQWMQRCzN7AZXXMFAmH5x5MACgkQQRCzN7AZ XXPNeQ/9EaMOGK6pE4zok8R0QJ9jChcor07HeOJc0jr/1lKixdpxK/edaugQZRFs CSqdMsHKashPimMn0X//IHhGg3PCC70FFIh0TA1F2dThROqH0JD3j59MUdSkLcCd OMtuIpeRZrhuygJam3MYJETzrI/QeQznUZarri+YJ0ba/Me5XaEY+QWkCB8u7ZLY SsG1p9LRs1PxNvlBMk+QrTg3nMcV3ZhVtEg7soQpNw08oUfiwDvTwkO1pGX/0ntD R0vCvgfaqX1w4v7eiVP4zUj2T7tDxU14WTCDEGbsLr6Z6vzYS7Wzw/tMw7h5iDwX T86CoxD1Yj3RaJplFMFyW9ZN3HHJvISWhujx/EmX871lPwDsHn8zZsS5WSyfiYRb Qddiu3gg4nBBbfeDwP5lcy4ZrHsszAy12Zv3OZTwVkapWxfaKYd2+QTJI+RPrSSS 3F+hAH1cHrOQY0sfGUTI6tmwovccQnNv1qk/IuQwxtDLlWPSyduLH8mmhgLb9wMR AQF6lnlW5M59CDqTN1v/trXC7lJyM4lpSnRxek9rMqQrhy+JWHUCWZ1Je+mk8R0k 03eRmaFHLWhzoQ8ZLToO16He9WI+VFx9KOqoHHUqhBjeBbE69S46PwY3jev3k6YW bViDImOI6DhCeAnu6TH18LOq1UGbPjZ0slmLjWaARPwtC69X3ZE= =3/r6 -----END PGP SIGNATURE----- Merge tag 'pinctrl-v5.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl Pull pin control fixes from Linus Walleij: "Most interesting and urgent is the Intel stuff affecting Chromebooks and laptops. - Fix up group name building on the Intel Thunderbay - Fix interrupt problems on the Intel Cherryview - Fix some pin data on the Sunxi H616 - Fix up the CONFIG_PINCTRL_ST Kconfig sort order as noted during the merge window - Fix an unexpected interrupt problem on the Intel Sunrisepoint - Fix a glitch when updating IRQ flags on all Intel pin controllers - Revert a Zynqmp patch to unify the pin naming, let's find some better solution - Fix some error paths in the Broadcom BCM2835 driver - Fix a Kconfig problem pertaining to the BCM63XX drivers - Fix the regmap support in the Microchip SGPIO driver" * tag 'pinctrl-v5.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-pinctrl: pinctrl: microchip-sgpio: Fix support for regmap pinctrl: bcm63xx: fix unmet dependency on REGMAP for GPIO_REGMAP pinctrl: bcm2835: Fix a few error paths pinctrl: zynqmp: Revert "Unify pin naming" pinctrl: intel: Fix a glitch when updating IRQ flags on a preconfigured line pinctrl: intel: fix unexpected interrupt pinctrl: Place correctly CONFIG_PINCTRL_ST in the Makefile pinctrl: sunxi: Fix H616 I2S3 pin data pinctrl: cherryview: Trigger hwirq0 for interrupt-lines without a mapping pinctrl: thunderbay: rework loops looking for groups names pinctrl: thunderbay: comment process of building functions a bit
This commit is contained in:
Коммит
3e5832e923
|
@ -42,9 +42,9 @@ obj-$(CONFIG_PINCTRL_PISTACHIO) += pinctrl-pistachio.o
|
|||
obj-$(CONFIG_PINCTRL_RK805) += pinctrl-rk805.o
|
||||
obj-$(CONFIG_PINCTRL_ROCKCHIP) += pinctrl-rockchip.o
|
||||
obj-$(CONFIG_PINCTRL_SINGLE) += pinctrl-single.o
|
||||
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
|
||||
obj-$(CONFIG_PINCTRL_STARFIVE) += pinctrl-starfive.o
|
||||
obj-$(CONFIG_PINCTRL_STMFX) += pinctrl-stmfx.o
|
||||
obj-$(CONFIG_PINCTRL_ST) += pinctrl-st.o
|
||||
obj-$(CONFIG_PINCTRL_SX150X) += pinctrl-sx150x.o
|
||||
obj-$(CONFIG_PINCTRL_TB10X) += pinctrl-tb10x.o
|
||||
obj-$(CONFIG_PINCTRL_THUNDERBAY) += pinctrl-thunderbay.o
|
||||
|
|
|
@ -35,6 +35,7 @@ config PINCTRL_BCM63XX
|
|||
select PINCONF
|
||||
select GENERIC_PINCONF
|
||||
select GPIOLIB
|
||||
select REGMAP
|
||||
select GPIO_REGMAP
|
||||
|
||||
config PINCTRL_BCM6318
|
||||
|
|
|
@ -1269,16 +1269,18 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
|
|||
sizeof(*girq->parents),
|
||||
GFP_KERNEL);
|
||||
if (!girq->parents) {
|
||||
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
|
||||
return -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
if (is_7211) {
|
||||
pc->wake_irq = devm_kcalloc(dev, BCM2835_NUM_IRQS,
|
||||
sizeof(*pc->wake_irq),
|
||||
GFP_KERNEL);
|
||||
if (!pc->wake_irq)
|
||||
return -ENOMEM;
|
||||
if (!pc->wake_irq) {
|
||||
err = -ENOMEM;
|
||||
goto out_remove;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1306,8 +1308,10 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
|
|||
|
||||
len = strlen(dev_name(pc->dev)) + 16;
|
||||
name = devm_kzalloc(pc->dev, len, GFP_KERNEL);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
if (!name) {
|
||||
err = -ENOMEM;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
snprintf(name, len, "%s:bank%d", dev_name(pc->dev), i);
|
||||
|
||||
|
@ -1326,11 +1330,14 @@ static int bcm2835_pinctrl_probe(struct platform_device *pdev)
|
|||
err = gpiochip_add_data(&pc->gpio_chip, pc);
|
||||
if (err) {
|
||||
dev_err(dev, "could not add GPIO chip\n");
|
||||
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
|
||||
return err;
|
||||
goto out_remove;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_remove:
|
||||
pinctrl_remove_gpio_range(pc->pctl_dev, &pc->gpio_range);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct platform_driver bcm2835_pinctrl_driver = {
|
||||
|
|
|
@ -1471,8 +1471,9 @@ static void chv_gpio_irq_handler(struct irq_desc *desc)
|
|||
|
||||
offset = cctx->intr_lines[intr_line];
|
||||
if (offset == CHV_INVALID_HWIRQ) {
|
||||
dev_err(dev, "interrupt on unused interrupt line %u\n", intr_line);
|
||||
continue;
|
||||
dev_warn_once(dev, "interrupt on unmapped interrupt line %u\n", intr_line);
|
||||
/* Some boards expect hwirq 0 to trigger in this case */
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
generic_handle_domain_irq(gc->irq.domain, offset);
|
||||
|
|
|
@ -451,8 +451,8 @@ static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
|
|||
value &= ~PADCFG0_PMODE_MASK;
|
||||
value |= PADCFG0_PMODE_GPIO;
|
||||
|
||||
/* Disable input and output buffers */
|
||||
value |= PADCFG0_GPIORXDIS;
|
||||
/* Disable TX buffer and enable RX (this will be input) */
|
||||
value &= ~PADCFG0_GPIORXDIS;
|
||||
value |= PADCFG0_GPIOTXDIS;
|
||||
|
||||
/* Disable SCI/SMI/NMI generation */
|
||||
|
@ -497,9 +497,6 @@ static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
|
|||
|
||||
intel_gpio_set_gpio_mode(padcfg0);
|
||||
|
||||
/* Disable TX buffer and enable RX (this will be input) */
|
||||
__intel_gpio_set_direction(padcfg0, true);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
|
||||
|
||||
return 0;
|
||||
|
@ -1115,9 +1112,6 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned int type)
|
|||
|
||||
intel_gpio_set_gpio_mode(reg);
|
||||
|
||||
/* Disable TX buffer and enable RX (this will be input) */
|
||||
__intel_gpio_set_direction(reg, true);
|
||||
|
||||
value = readl(reg);
|
||||
|
||||
value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
|
||||
|
@ -1216,6 +1210,39 @@ static irqreturn_t intel_gpio_irq(int irq, void *data)
|
|||
return IRQ_RETVAL(ret);
|
||||
}
|
||||
|
||||
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
const struct intel_community *community;
|
||||
void __iomem *base;
|
||||
unsigned int gpp;
|
||||
|
||||
community = &pctrl->communities[i];
|
||||
base = community->regs;
|
||||
|
||||
for (gpp = 0; gpp < community->ngpps; gpp++) {
|
||||
/* Mask and clear all interrupts */
|
||||
writel(0, base + community->ie_offset + gpp * 4);
|
||||
writel(0xffff, base + community->is_offset + gpp * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int intel_gpio_irq_init_hw(struct gpio_chip *gc)
|
||||
{
|
||||
struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
|
||||
|
||||
/*
|
||||
* Make sure the interrupt lines are in a proper state before
|
||||
* further configuration.
|
||||
*/
|
||||
intel_gpio_irq_init(pctrl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int intel_gpio_add_community_ranges(struct intel_pinctrl *pctrl,
|
||||
const struct intel_community *community)
|
||||
{
|
||||
|
@ -1320,6 +1347,7 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
|
|||
girq->num_parents = 0;
|
||||
girq->default_type = IRQ_TYPE_NONE;
|
||||
girq->handler = handle_bad_irq;
|
||||
girq->init_hw = intel_gpio_irq_init_hw;
|
||||
|
||||
ret = devm_gpiochip_add_data(pctrl->dev, &pctrl->chip, pctrl);
|
||||
if (ret) {
|
||||
|
@ -1695,26 +1723,6 @@ int intel_pinctrl_suspend_noirq(struct device *dev)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(intel_pinctrl_suspend_noirq);
|
||||
|
||||
static void intel_gpio_irq_init(struct intel_pinctrl *pctrl)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < pctrl->ncommunities; i++) {
|
||||
const struct intel_community *community;
|
||||
void __iomem *base;
|
||||
unsigned int gpp;
|
||||
|
||||
community = &pctrl->communities[i];
|
||||
base = community->regs;
|
||||
|
||||
for (gpp = 0; gpp < community->ngpps; gpp++) {
|
||||
/* Mask and clear all interrupts */
|
||||
writel(0, base + community->ie_offset + gpp * 4);
|
||||
writel(0xffff, base + community->is_offset + gpp * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool intel_gpio_update_reg(void __iomem *reg, u32 mask, u32 value)
|
||||
{
|
||||
u32 curr, updated;
|
||||
|
|
|
@ -137,7 +137,8 @@ static inline int sgpio_addr_to_pin(struct sgpio_priv *priv, int port, int bit)
|
|||
|
||||
static inline u32 sgpio_get_addr(struct sgpio_priv *priv, u32 rno, u32 off)
|
||||
{
|
||||
return priv->properties->regoff[rno] + off;
|
||||
return (priv->properties->regoff[rno] + off) *
|
||||
regmap_get_reg_stride(priv->regs);
|
||||
}
|
||||
|
||||
static u32 sgpio_readl(struct sgpio_priv *priv, u32 rno, u32 off)
|
||||
|
|
|
@ -773,63 +773,42 @@ static int thunderbay_build_groups(struct thunderbay_pinctrl *tpc)
|
|||
|
||||
static int thunderbay_add_functions(struct thunderbay_pinctrl *tpc, struct function_desc *funcs)
|
||||
{
|
||||
struct function_desc *function = funcs;
|
||||
int i;
|
||||
|
||||
/* Assign the groups for each function */
|
||||
for (i = 0; i < tpc->soc->npins; i++) {
|
||||
const struct pinctrl_pin_desc *pin_info = thunderbay_pins + i;
|
||||
struct thunderbay_mux_desc *pin_mux = pin_info->drv_data;
|
||||
for (i = 0; i < tpc->nfuncs; i++) {
|
||||
struct function_desc *func = &funcs[i];
|
||||
const char **group_names;
|
||||
unsigned int grp_idx = 0;
|
||||
int j;
|
||||
|
||||
while (pin_mux->name) {
|
||||
const char **grp;
|
||||
int j, grp_num, match = 0;
|
||||
size_t grp_size;
|
||||
struct function_desc *func;
|
||||
group_names = devm_kcalloc(tpc->dev, func->num_group_names,
|
||||
sizeof(*group_names), GFP_KERNEL);
|
||||
if (!group_names)
|
||||
return -ENOMEM;
|
||||
|
||||
for (j = 0; j < tpc->nfuncs; j++) {
|
||||
if (!strcmp(pin_mux->name, function[j].name)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
for (j = 0; j < tpc->soc->npins; j++) {
|
||||
const struct pinctrl_pin_desc *pin_info = &thunderbay_pins[j];
|
||||
struct thunderbay_mux_desc *pin_mux;
|
||||
|
||||
for (pin_mux = pin_info->drv_data; pin_mux->name; pin_mux++) {
|
||||
if (!strcmp(pin_mux->name, func->name))
|
||||
group_names[grp_idx++] = pin_info->name;
|
||||
}
|
||||
|
||||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
func = function + j;
|
||||
grp_num = func->num_group_names;
|
||||
grp_size = sizeof(*func->group_names);
|
||||
|
||||
if (!func->group_names) {
|
||||
func->group_names = devm_kcalloc(tpc->dev,
|
||||
grp_num,
|
||||
grp_size,
|
||||
GFP_KERNEL);
|
||||
if (!func->group_names) {
|
||||
kfree(func);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
grp = func->group_names;
|
||||
while (*grp)
|
||||
grp++;
|
||||
|
||||
*grp = pin_info->name;
|
||||
pin_mux++;
|
||||
}
|
||||
|
||||
func->group_names = group_names;
|
||||
}
|
||||
|
||||
/* Add all functions */
|
||||
for (i = 0; i < tpc->nfuncs; i++) {
|
||||
pinmux_generic_add_function(tpc->pctrl,
|
||||
function[i].name,
|
||||
function[i].group_names,
|
||||
function[i].num_group_names,
|
||||
function[i].data);
|
||||
funcs[i].name,
|
||||
funcs[i].group_names,
|
||||
funcs[i].num_group_names,
|
||||
funcs[i].data);
|
||||
}
|
||||
kfree(function);
|
||||
kfree(funcs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -839,27 +818,30 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc)
|
|||
void *ptr;
|
||||
int pin;
|
||||
|
||||
/* Total number of functions is unknown at this point. Allocate first. */
|
||||
/*
|
||||
* Allocate maximum possible number of functions. Assume every pin
|
||||
* being part of 8 (hw maximum) globally unique muxes.
|
||||
*/
|
||||
tpc->nfuncs = 0;
|
||||
thunderbay_funcs = kcalloc(tpc->soc->npins * 8,
|
||||
sizeof(*thunderbay_funcs), GFP_KERNEL);
|
||||
if (!thunderbay_funcs)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Find total number of functions and each's properties */
|
||||
/* Setup 1 function for each unique mux */
|
||||
for (pin = 0; pin < tpc->soc->npins; pin++) {
|
||||
const struct pinctrl_pin_desc *pin_info = thunderbay_pins + pin;
|
||||
struct thunderbay_mux_desc *pin_mux = pin_info->drv_data;
|
||||
struct thunderbay_mux_desc *pin_mux;
|
||||
|
||||
while (pin_mux->name) {
|
||||
struct function_desc *func = thunderbay_funcs;
|
||||
for (pin_mux = pin_info->drv_data; pin_mux->name; pin_mux++) {
|
||||
struct function_desc *func;
|
||||
|
||||
while (func->name) {
|
||||
/* Check if we already have function for this mux */
|
||||
for (func = thunderbay_funcs; func->name; func++) {
|
||||
if (!strcmp(pin_mux->name, func->name)) {
|
||||
func->num_group_names++;
|
||||
break;
|
||||
}
|
||||
func++;
|
||||
}
|
||||
|
||||
if (!func->name) {
|
||||
|
@ -868,8 +850,6 @@ static int thunderbay_build_functions(struct thunderbay_pinctrl *tpc)
|
|||
func->data = (int *)&pin_mux->mode;
|
||||
tpc->nfuncs++;
|
||||
}
|
||||
|
||||
pin_mux++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -809,7 +809,6 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
|
|||
unsigned int *npins)
|
||||
{
|
||||
struct pinctrl_pin_desc *pins, *pin;
|
||||
char **pin_names;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
|
@ -821,14 +820,13 @@ static int zynqmp_pinctrl_prepare_pin_desc(struct device *dev,
|
|||
if (!pins)
|
||||
return -ENOMEM;
|
||||
|
||||
pin_names = devm_kasprintf_strarray(dev, ZYNQMP_PIN_PREFIX, *npins);
|
||||
if (IS_ERR(pin_names))
|
||||
return PTR_ERR(pin_names);
|
||||
|
||||
for (i = 0; i < *npins; i++) {
|
||||
pin = &pins[i];
|
||||
pin->number = i;
|
||||
pin->name = pin_names[i];
|
||||
pin->name = devm_kasprintf(dev, GFP_KERNEL, "%s%d",
|
||||
ZYNQMP_PIN_PREFIX, i);
|
||||
if (!pin->name)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
*zynqmp_pins = pins;
|
||||
|
|
|
@ -363,16 +363,16 @@ static const struct sunxi_desc_pin h616_pins[] = {
|
|||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x2, "uart2"), /* CTS */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* DO0 */
|
||||
SUNXI_FUNCTION(0x3, "i2s3_dout0"), /* DO0 */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* MISO */
|
||||
SUNXI_FUNCTION(0x5, "i2s3"), /* DI1 */
|
||||
SUNXI_FUNCTION(0x5, "i2s3_din1"), /* DI1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 8)), /* PH_EINT8 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 9),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
SUNXI_FUNCTION(0x1, "gpio_out"),
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* DI0 */
|
||||
SUNXI_FUNCTION(0x3, "i2s3_din0"), /* DI0 */
|
||||
SUNXI_FUNCTION(0x4, "spi1"), /* CS1 */
|
||||
SUNXI_FUNCTION(0x3, "i2s3"), /* DO1 */
|
||||
SUNXI_FUNCTION(0x5, "i2s3_dout1"), /* DO1 */
|
||||
SUNXI_FUNCTION_IRQ_BANK(0x6, 6, 9)), /* PH_EINT9 */
|
||||
SUNXI_PIN(SUNXI_PINCTRL_PIN(H, 10),
|
||||
SUNXI_FUNCTION(0x0, "gpio_in"),
|
||||
|
|
Загрузка…
Ссылка в новой задаче