mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-07 21:24:00 +08:00
gpio fixes for v5.11-rc5
- rework the character device code to avoid a frame size warning - fix printk format issues in gpio-tools - warn on redefinition of the to_irq callback in core gpiolib code - fix PWM period calculation in gpio-mvebu - make gpio-sifive Kconfig entry consistent with other drivers - fix a build issue in gpio-tegra -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAmAJSRUACgkQEacuoBRx 13INyQ/8CXh1/nBTx8LkLPNXkmv/RTA0AKjEBuhY/VVYHwhhZ17rTisc3+2LfQ4N dbS1taI5J1GVqk8yrKrcjESZxAuduwokhR5ciRZbHDFMEii6hhH7RuN7Evxd9DCr 1kMhv0X/dRG/C6xAawP6nS8wpf/tOzv71wBpp7MT//ZzZGWx49jMtyEkqijjqH8n lQnoZdBw7vMVvxhXa6WXc3i9N8hAOS3YAFAs9NtDvabGpvIaCSgU43e4we6pYHND 0OHD2+V3FYpRYsenoOmOoRLZheMQ/Z0DjWKkvBQburl1n6ZLaCtdjAi1MoG5FhbN 49VJhyPTOlw1xsmTm/2Fg4WzktDi95gsQzef25bhhTBVoETOen6gBxK2RsdUmpzm zQX1wUrINGfzcfQhStIvjyznHZRabGuxDlFN9UH3mGnDVzWepuqCvY9s2/zmU4eU OtCTWsM9TTmlRiU/bIqC5/aSJyZJ/d1stiacRCsfPJ4Gmb4zsm9y/cILMporiRPJ JEd4T0jUSo94QLcrSSse15TBVVOA9TydFrDgVE3HBAZbqf+eaRG/fYKRABs6cX+H VNhIRi1mjj2rr1UwmCYcEtuT3ODthXS7lTAGmLt7hAzSHCxMsO+pSQ2BPdGanb9O GKWs/owyZm1be4e3yVdQfrQ4/+LimqpyN8uDSU4RbfuNrHiSLxw= =1H0g -----END PGP SIGNATURE----- Merge tag 'gpio-fixes-for-v5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux Pull gpio fixes from Bartosz Golaszewski: - rework the character device code to avoid a frame size warning - fix printk format issues in gpio-tools - warn on redefinition of the to_irq callback in core gpiolib code - fix PWM period calculation in gpio-mvebu - make gpio-sifive Kconfig entry consistent with other drivers - fix a build issue in gpio-tegra * tag 'gpio-fixes-for-v5.11-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux: gpio: tegra: Add missing dependencies gpio: sifive: select IRQ_DOMAIN_HIERARCHY rather than depend on it gpio: mvebu: fix pwm .get_state period calculation gpiolib: add a warning on gpiochip->to_irq defined tools: gpio: fix %llu warning in gpio-watch.c tools: gpio: fix %llu warning in gpio-event-mon.c gpiolib: cdev: fix frame size warning in gpio_ioctl()
This commit is contained in:
commit
d7631e4378
@ -521,7 +521,8 @@ config GPIO_SAMA5D2_PIOBU
|
||||
|
||||
config GPIO_SIFIVE
|
||||
bool "SiFive GPIO support"
|
||||
depends on OF_GPIO && IRQ_DOMAIN_HIERARCHY
|
||||
depends on OF_GPIO
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
select GPIO_GENERIC
|
||||
select GPIOLIB_IRQCHIP
|
||||
select REGMAP_MMIO
|
||||
@ -597,6 +598,8 @@ config GPIO_TEGRA
|
||||
default ARCH_TEGRA
|
||||
depends on ARCH_TEGRA || COMPILE_TEST
|
||||
depends on OF_GPIO
|
||||
select GPIOLIB_IRQCHIP
|
||||
select IRQ_DOMAIN_HIERARCHY
|
||||
help
|
||||
Say yes here to support GPIO pins on NVIDIA Tegra SoCs.
|
||||
|
||||
|
@ -676,20 +676,17 @@ static void mvebu_pwm_get_state(struct pwm_chip *chip,
|
||||
else
|
||||
state->duty_cycle = 1;
|
||||
|
||||
val = (unsigned long long) u; /* on duration */
|
||||
regmap_read(mvpwm->regs, mvebu_pwmreg_blink_off_duration(mvpwm), &u);
|
||||
val = (unsigned long long) u * NSEC_PER_SEC;
|
||||
val += (unsigned long long) u; /* period = on + off duration */
|
||||
val *= NSEC_PER_SEC;
|
||||
do_div(val, mvpwm->clk_rate);
|
||||
if (val < state->duty_cycle) {
|
||||
if (val > UINT_MAX)
|
||||
state->period = UINT_MAX;
|
||||
else if (val)
|
||||
state->period = val;
|
||||
else
|
||||
state->period = 1;
|
||||
} else {
|
||||
val -= state->duty_cycle;
|
||||
if (val > UINT_MAX)
|
||||
state->period = UINT_MAX;
|
||||
else if (val)
|
||||
state->period = val;
|
||||
else
|
||||
state->period = 1;
|
||||
}
|
||||
|
||||
regmap_read(mvchip->regs, GPIO_BLINK_EN_OFF + mvchip->offset, &u);
|
||||
if (u)
|
||||
|
@ -1979,6 +1979,21 @@ struct gpio_chardev_data {
|
||||
#endif
|
||||
};
|
||||
|
||||
static int chipinfo_get(struct gpio_chardev_data *cdev, void __user *ip)
|
||||
{
|
||||
struct gpio_device *gdev = cdev->gdev;
|
||||
struct gpiochip_info chipinfo;
|
||||
|
||||
memset(&chipinfo, 0, sizeof(chipinfo));
|
||||
|
||||
strscpy(chipinfo.name, dev_name(&gdev->dev), sizeof(chipinfo.name));
|
||||
strscpy(chipinfo.label, gdev->label, sizeof(chipinfo.label));
|
||||
chipinfo.lines = gdev->ngpio;
|
||||
if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_GPIO_CDEV_V1
|
||||
/*
|
||||
* returns 0 if the versions match, else the previously selected ABI version
|
||||
@ -1993,6 +2008,41 @@ static int lineinfo_ensure_abi_version(struct gpio_chardev_data *cdata,
|
||||
|
||||
return abiv;
|
||||
}
|
||||
|
||||
static int lineinfo_get_v1(struct gpio_chardev_data *cdev, void __user *ip,
|
||||
bool watch)
|
||||
{
|
||||
struct gpio_desc *desc;
|
||||
struct gpioline_info lineinfo;
|
||||
struct gpio_v2_line_info lineinfo_v2;
|
||||
|
||||
if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
/* this doubles as a range check on line_offset */
|
||||
desc = gpiochip_get_desc(cdev->gdev->chip, lineinfo.line_offset);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
if (watch) {
|
||||
if (lineinfo_ensure_abi_version(cdev, 1))
|
||||
return -EPERM;
|
||||
|
||||
if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
gpio_desc_to_lineinfo(desc, &lineinfo_v2);
|
||||
gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
|
||||
|
||||
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
|
||||
if (watch)
|
||||
clear_bit(lineinfo.line_offset, cdev->watched_lines);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
|
||||
@ -2030,6 +2080,22 @@ static int lineinfo_get(struct gpio_chardev_data *cdev, void __user *ip,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lineinfo_unwatch(struct gpio_chardev_data *cdev, void __user *ip)
|
||||
{
|
||||
__u32 offset;
|
||||
|
||||
if (copy_from_user(&offset, ip, sizeof(offset)))
|
||||
return -EFAULT;
|
||||
|
||||
if (offset >= cdev->gdev->ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
if (!test_and_clear_bit(offset, cdev->watched_lines))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* gpio_ioctl() - ioctl handler for the GPIO chardev
|
||||
*/
|
||||
@ -2037,80 +2103,24 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct gpio_chardev_data *cdev = file->private_data;
|
||||
struct gpio_device *gdev = cdev->gdev;
|
||||
struct gpio_chip *gc = gdev->chip;
|
||||
void __user *ip = (void __user *)arg;
|
||||
__u32 offset;
|
||||
|
||||
/* We fail any subsequent ioctl():s when the chip is gone */
|
||||
if (!gc)
|
||||
if (!gdev->chip)
|
||||
return -ENODEV;
|
||||
|
||||
/* Fill in the struct and pass to userspace */
|
||||
if (cmd == GPIO_GET_CHIPINFO_IOCTL) {
|
||||
struct gpiochip_info chipinfo;
|
||||
|
||||
memset(&chipinfo, 0, sizeof(chipinfo));
|
||||
|
||||
strscpy(chipinfo.name, dev_name(&gdev->dev),
|
||||
sizeof(chipinfo.name));
|
||||
strscpy(chipinfo.label, gdev->label,
|
||||
sizeof(chipinfo.label));
|
||||
chipinfo.lines = gdev->ngpio;
|
||||
if (copy_to_user(ip, &chipinfo, sizeof(chipinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
return chipinfo_get(cdev, ip);
|
||||
#ifdef CONFIG_GPIO_CDEV_V1
|
||||
} else if (cmd == GPIO_GET_LINEINFO_IOCTL) {
|
||||
struct gpio_desc *desc;
|
||||
struct gpioline_info lineinfo;
|
||||
struct gpio_v2_line_info lineinfo_v2;
|
||||
|
||||
if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
/* this doubles as a range check on line_offset */
|
||||
desc = gpiochip_get_desc(gc, lineinfo.line_offset);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
gpio_desc_to_lineinfo(desc, &lineinfo_v2);
|
||||
gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
|
||||
|
||||
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo)))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
} else if (cmd == GPIO_GET_LINEHANDLE_IOCTL) {
|
||||
return linehandle_create(gdev, ip);
|
||||
} else if (cmd == GPIO_GET_LINEEVENT_IOCTL) {
|
||||
return lineevent_create(gdev, ip);
|
||||
} else if (cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
|
||||
struct gpio_desc *desc;
|
||||
struct gpioline_info lineinfo;
|
||||
struct gpio_v2_line_info lineinfo_v2;
|
||||
|
||||
if (copy_from_user(&lineinfo, ip, sizeof(lineinfo)))
|
||||
return -EFAULT;
|
||||
|
||||
/* this doubles as a range check on line_offset */
|
||||
desc = gpiochip_get_desc(gc, lineinfo.line_offset);
|
||||
if (IS_ERR(desc))
|
||||
return PTR_ERR(desc);
|
||||
|
||||
if (lineinfo_ensure_abi_version(cdev, 1))
|
||||
return -EPERM;
|
||||
|
||||
if (test_and_set_bit(lineinfo.line_offset, cdev->watched_lines))
|
||||
return -EBUSY;
|
||||
|
||||
gpio_desc_to_lineinfo(desc, &lineinfo_v2);
|
||||
gpio_v2_line_info_to_v1(&lineinfo_v2, &lineinfo);
|
||||
|
||||
if (copy_to_user(ip, &lineinfo, sizeof(lineinfo))) {
|
||||
clear_bit(lineinfo.line_offset, cdev->watched_lines);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else if (cmd == GPIO_GET_LINEINFO_IOCTL ||
|
||||
cmd == GPIO_GET_LINEINFO_WATCH_IOCTL) {
|
||||
return lineinfo_get_v1(cdev, ip,
|
||||
cmd == GPIO_GET_LINEINFO_WATCH_IOCTL);
|
||||
#endif /* CONFIG_GPIO_CDEV_V1 */
|
||||
} else if (cmd == GPIO_V2_GET_LINEINFO_IOCTL ||
|
||||
cmd == GPIO_V2_GET_LINEINFO_WATCH_IOCTL) {
|
||||
@ -2119,16 +2129,7 @@ static long gpio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||
} else if (cmd == GPIO_V2_GET_LINE_IOCTL) {
|
||||
return linereq_create(gdev, ip);
|
||||
} else if (cmd == GPIO_GET_LINEINFO_UNWATCH_IOCTL) {
|
||||
if (copy_from_user(&offset, ip, sizeof(offset)))
|
||||
return -EFAULT;
|
||||
|
||||
if (offset >= cdev->gdev->ngpio)
|
||||
return -EINVAL;
|
||||
|
||||
if (!test_and_clear_bit(offset, cdev->watched_lines))
|
||||
return -EBUSY;
|
||||
|
||||
return 0;
|
||||
return lineinfo_unwatch(cdev, ip);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -1489,6 +1489,9 @@ static int gpiochip_add_irqchip(struct gpio_chip *gc,
|
||||
type = IRQ_TYPE_NONE;
|
||||
}
|
||||
|
||||
if (gc->to_irq)
|
||||
chip_warn(gc, "to_irq is redefined in %s and you shouldn't rely on it\n", __func__);
|
||||
|
||||
gc->to_irq = gpiochip_to_irq;
|
||||
gc->irq.default_type = type;
|
||||
gc->irq.lock_key = lock_key;
|
||||
|
@ -107,8 +107,8 @@ int monitor_device(const char *device_name,
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
fprintf(stdout, "GPIO EVENT at %llu on line %d (%d|%d) ",
|
||||
event.timestamp_ns, event.offset, event.line_seqno,
|
||||
fprintf(stdout, "GPIO EVENT at %" PRIu64 " on line %d (%d|%d) ",
|
||||
(uint64_t)event.timestamp_ns, event.offset, event.line_seqno,
|
||||
event.seqno);
|
||||
switch (event.id) {
|
||||
case GPIO_V2_LINE_EVENT_RISING_EDGE:
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <poll.h>
|
||||
#include <stdbool.h>
|
||||
@ -86,8 +87,8 @@ int main(int argc, char **argv)
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("line %u: %s at %llu\n",
|
||||
chg.info.offset, event, chg.timestamp_ns);
|
||||
printf("line %u: %s at %" PRIu64 "\n",
|
||||
chg.info.offset, event, (uint64_t)chg.timestamp_ns);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user