mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 10:50:53 +07:00
gpio updates for v5.10 - part 1
- automatically drive GPHY leds in gpio-stp-xway - refactor ->{get, set}_multiple() in gpio-aggregator - add support for a new model in rcar-gpio DT bindings - simplify several GPIO drivers with dev_err_probe() - disable Direct KBD interrupts in gpio-tc35894 - use DEFINE_SEQ_ATTRIBUTE() in GPIO chardev to shrink code - switch to using a simpler IDA API in gpiolib - make devprop_gpiochip_set_names() more generic by using device properties instead of using fwnode helpers -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEFp3rbAvDxGAT0sefEacuoBRx13IFAl9jSlsACgkQEacuoBRx 13K6cBAA2Drc9AwFpGzb+yE7bvKmxtbCbD8RZBQNg4Ljy56yQOQhNnQSE91YIeGj MlSNbn89nKGlkUje2qggJn6+ZE1InKI70d67fK4z/MiMDv31YLPN78Qei9kbTXgF dNiV6wnabavAJrpNPtNOU8SLotn9C3zVwTyXOuMqfGL6TqAWf79Xk2QHuV1l/Apz CozfTI/81p1eeuF3yMRz+ubGS/2Zpo862QmgA9CMWb439z7LNbQJ1vjFKMqvkW0P ey9ELjV/y5PFTA9fWYIukOjBqpsWyihdIW2K3R/7yR8OFqREUnvBzJZJLpghCkzO vpivVFlZu7eyMpdUU4ZH7ussFVX+GqYbV8Q42shabClQH7qJAfnO3nhPptWWWd/v CmDOEvsfg2CpXpWJmwxUxoUJEOto2NO3HOBM41XYKQhSs3pw1HheN2wxVOWWOrTa kJfJnyaWYT1qkolRuXMdLkauZHOpmAP3o+o+OtInd+NeM9lyaCjhdtQ11vBDk1Oc 3jLskr29KyTIa9lNPLT+pcQWuF77dhtzTPUIeG1+BzWA/FBpiR2c0M2tmUdRGIKb IEPF0vkihiLy5rz/j1YYgADLDc6uxhEbiP/WKcbKySgc4kCQCHkgFQwa/DyMAROC ye7Yof9m6Yx1KMvioP0QpP/LU9mfooSoa2JU2iHGH8df+VJ1NFQ= =RbA2 -----END PGP SIGNATURE----- Merge tag 'gpio-updates-for-v5.10-part1' of git://git.kernel.org/pub/scm/linux/kernel/git/brgl/linux into devel gpio updates for v5.10 - part 1 - automatically drive GPHY leds in gpio-stp-xway - refactor ->{get, set}_multiple() in gpio-aggregator - add support for a new model in rcar-gpio DT bindings - simplify several GPIO drivers with dev_err_probe() - disable Direct KBD interrupts in gpio-tc35894 - use DEFINE_SEQ_ATTRIBUTE() in GPIO chardev to shrink code - switch to using a simpler IDA API in gpiolib - make devprop_gpiochip_set_names() more generic by using device properties instead of using fwnode helpers
This commit is contained in:
commit
36eccdb58f
@ -37,6 +37,7 @@ properties:
|
||||
- renesas,gpio-r8a774a1 # RZ/G2M
|
||||
- renesas,gpio-r8a774b1 # RZ/G2N
|
||||
- renesas,gpio-r8a774c0 # RZ/G2E
|
||||
- renesas,gpio-r8a774e1 # RZ/G2H
|
||||
- renesas,gpio-r8a7795 # R-Car H3
|
||||
- renesas,gpio-r8a7796 # R-Car M3-W
|
||||
- renesas,gpio-r8a77961 # R-Car M3-W+
|
||||
|
@ -6,7 +6,6 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-devres.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-legacy.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-devprop.o
|
||||
obj-$(CONFIG_GPIOLIB) += gpiolib-cdev.o
|
||||
obj-$(CONFIG_OF_GPIO) += gpiolib-of.o
|
||||
obj-$(CONFIG_GPIO_SYSFS) += gpiolib-sysfs.o
|
||||
|
@ -333,20 +333,14 @@ static int gpio_fwd_get(struct gpio_chip *chip, unsigned int offset)
|
||||
return gpiod_get_value(fwd->descs[offset]);
|
||||
}
|
||||
|
||||
static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask,
|
||||
static int gpio_fwd_get_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
|
||||
unsigned long *bits)
|
||||
{
|
||||
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
|
||||
unsigned long *values, flags = 0;
|
||||
struct gpio_desc **descs;
|
||||
unsigned long *values;
|
||||
unsigned int i, j = 0;
|
||||
int error;
|
||||
|
||||
if (chip->can_sleep)
|
||||
mutex_lock(&fwd->mlock);
|
||||
else
|
||||
spin_lock_irqsave(&fwd->slock, flags);
|
||||
|
||||
/* Both values bitmap and desc pointers are stored in tmp[] */
|
||||
values = &fwd->tmp[0];
|
||||
descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)];
|
||||
@ -356,16 +350,32 @@ static int gpio_fwd_get_multiple(struct gpio_chip *chip, unsigned long *mask,
|
||||
descs[j++] = fwd->descs[i];
|
||||
|
||||
error = gpiod_get_array_value(j, descs, NULL, values);
|
||||
if (!error) {
|
||||
j = 0;
|
||||
for_each_set_bit(i, mask, fwd->chip.ngpio)
|
||||
__assign_bit(i, bits, test_bit(j++, values));
|
||||
}
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (chip->can_sleep)
|
||||
j = 0;
|
||||
for_each_set_bit(i, mask, fwd->chip.ngpio)
|
||||
__assign_bit(i, bits, test_bit(j++, values));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gpio_fwd_get_multiple_locked(struct gpio_chip *chip,
|
||||
unsigned long *mask, unsigned long *bits)
|
||||
{
|
||||
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
int error;
|
||||
|
||||
if (chip->can_sleep) {
|
||||
mutex_lock(&fwd->mlock);
|
||||
error = gpio_fwd_get_multiple(fwd, mask, bits);
|
||||
mutex_unlock(&fwd->mlock);
|
||||
else
|
||||
} else {
|
||||
spin_lock_irqsave(&fwd->slock, flags);
|
||||
error = gpio_fwd_get_multiple(fwd, mask, bits);
|
||||
spin_unlock_irqrestore(&fwd->slock, flags);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
@ -377,19 +387,13 @@ static void gpio_fwd_set(struct gpio_chip *chip, unsigned int offset, int value)
|
||||
gpiod_set_value(fwd->descs[offset], value);
|
||||
}
|
||||
|
||||
static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask,
|
||||
static void gpio_fwd_set_multiple(struct gpiochip_fwd *fwd, unsigned long *mask,
|
||||
unsigned long *bits)
|
||||
{
|
||||
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
|
||||
unsigned long *values, flags = 0;
|
||||
struct gpio_desc **descs;
|
||||
unsigned long *values;
|
||||
unsigned int i, j = 0;
|
||||
|
||||
if (chip->can_sleep)
|
||||
mutex_lock(&fwd->mlock);
|
||||
else
|
||||
spin_lock_irqsave(&fwd->slock, flags);
|
||||
|
||||
/* Both values bitmap and desc pointers are stored in tmp[] */
|
||||
values = &fwd->tmp[0];
|
||||
descs = (void *)&fwd->tmp[BITS_TO_LONGS(fwd->chip.ngpio)];
|
||||
@ -400,11 +404,23 @@ static void gpio_fwd_set_multiple(struct gpio_chip *chip, unsigned long *mask,
|
||||
}
|
||||
|
||||
gpiod_set_array_value(j, descs, NULL, values);
|
||||
}
|
||||
|
||||
if (chip->can_sleep)
|
||||
static void gpio_fwd_set_multiple_locked(struct gpio_chip *chip,
|
||||
unsigned long *mask, unsigned long *bits)
|
||||
{
|
||||
struct gpiochip_fwd *fwd = gpiochip_get_data(chip);
|
||||
unsigned long flags;
|
||||
|
||||
if (chip->can_sleep) {
|
||||
mutex_lock(&fwd->mlock);
|
||||
gpio_fwd_set_multiple(fwd, mask, bits);
|
||||
mutex_unlock(&fwd->mlock);
|
||||
else
|
||||
} else {
|
||||
spin_lock_irqsave(&fwd->slock, flags);
|
||||
gpio_fwd_set_multiple(fwd, mask, bits);
|
||||
spin_unlock_irqrestore(&fwd->slock, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static int gpio_fwd_set_config(struct gpio_chip *chip, unsigned int offset,
|
||||
@ -470,9 +486,9 @@ static struct gpiochip_fwd *gpiochip_fwd_create(struct device *dev,
|
||||
chip->direction_input = gpio_fwd_direction_input;
|
||||
chip->direction_output = gpio_fwd_direction_output;
|
||||
chip->get = gpio_fwd_get;
|
||||
chip->get_multiple = gpio_fwd_get_multiple;
|
||||
chip->get_multiple = gpio_fwd_get_multiple_locked;
|
||||
chip->set = gpio_fwd_set;
|
||||
chip->set_multiple = gpio_fwd_set_multiple;
|
||||
chip->set_multiple = gpio_fwd_set_multiple_locked;
|
||||
chip->base = -1;
|
||||
chip->ngpio = ngpios;
|
||||
fwd->descs = descs;
|
||||
|
@ -590,10 +590,7 @@ static int bcm_kona_gpio_probe(struct platform_device *pdev)
|
||||
dev_err(dev, "Couldn't determine # GPIO banks\n");
|
||||
return -ENOENT;
|
||||
} else if (ret < 0) {
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Couldn't determine GPIO banks: (%pe)\n",
|
||||
ERR_PTR(ret));
|
||||
return ret;
|
||||
return dev_err_probe(dev, ret, "Couldn't determine GPIO banks\n");
|
||||
}
|
||||
kona_gpio->num_bank = ret;
|
||||
|
||||
|
@ -237,12 +237,8 @@ static int davinci_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
for (i = 0; i < nirq; i++) {
|
||||
chips->irqs[i] = platform_get_irq(pdev, i);
|
||||
if (chips->irqs[i] < 0) {
|
||||
if (chips->irqs[i] != -EPROBE_DEFER)
|
||||
dev_info(dev, "IRQ not populated, err = %d\n",
|
||||
chips->irqs[i]);
|
||||
return chips->irqs[i];
|
||||
}
|
||||
if (chips->irqs[i] < 0)
|
||||
return dev_err_probe(dev, chips->irqs[i], "IRQ not populated\n");
|
||||
}
|
||||
|
||||
chips->chip.label = dev_name(dev);
|
||||
|
@ -1394,10 +1394,7 @@ static int omap_gpio_probe(struct platform_device *pdev)
|
||||
if (bank->irq <= 0) {
|
||||
if (!bank->irq)
|
||||
bank->irq = -ENXIO;
|
||||
if (bank->irq != -EPROBE_DEFER)
|
||||
dev_err(dev,
|
||||
"can't get irq resource ret=%d\n", bank->irq);
|
||||
return bank->irq;
|
||||
return dev_err_probe(dev, bank->irq, "can't get irq resource\n");
|
||||
}
|
||||
|
||||
bank->chip.parent = dev;
|
||||
|
@ -1000,12 +1000,9 @@ static int pca953x_probe(struct i2c_client *client,
|
||||
chip->client = client;
|
||||
|
||||
reg = devm_regulator_get(&client->dev, "vcc");
|
||||
if (IS_ERR(reg)) {
|
||||
ret = PTR_ERR(reg);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(&client->dev, "reg get err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(reg))
|
||||
return dev_err_probe(&client->dev, PTR_ERR(reg), "reg get err\n");
|
||||
|
||||
ret = regulator_enable(reg);
|
||||
if (ret) {
|
||||
dev_err(&client->dev, "reg en err: %d\n", ret);
|
||||
|
@ -148,12 +148,9 @@ static int pisosr_gpio_probe(struct spi_device *spi)
|
||||
return -ENOMEM;
|
||||
|
||||
gpio->load_gpio = devm_gpiod_get_optional(dev, "load", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(gpio->load_gpio)) {
|
||||
ret = PTR_ERR(gpio->load_gpio);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(dev, "Unable to allocate load GPIO\n");
|
||||
return ret;
|
||||
}
|
||||
if (IS_ERR(gpio->load_gpio))
|
||||
return dev_err_probe(dev, PTR_ERR(gpio->load_gpio),
|
||||
"Unable to allocate load GPIO\n");
|
||||
|
||||
mutex_init(&gpio->lock);
|
||||
|
||||
|
@ -41,7 +41,10 @@
|
||||
#define XWAY_STP_4HZ BIT(23)
|
||||
#define XWAY_STP_8HZ BIT(24)
|
||||
#define XWAY_STP_10HZ (BIT(24) | BIT(23))
|
||||
#define XWAY_STP_SPEED_MASK (0xf << 23)
|
||||
#define XWAY_STP_SPEED_MASK (BIT(23) | BIT(24) | BIT(25) | BIT(26) | BIT(27))
|
||||
|
||||
#define XWAY_STP_FPIS_VALUE BIT(21)
|
||||
#define XWAY_STP_FPIS_MASK (BIT(20) | BIT(21))
|
||||
|
||||
/* clock source for automatic update */
|
||||
#define XWAY_STP_UPD_FPI BIT(31)
|
||||
@ -54,7 +57,9 @@
|
||||
/* 2 groups of 3 bits can be driven by the phys */
|
||||
#define XWAY_STP_PHY_MASK 0x7
|
||||
#define XWAY_STP_PHY1_SHIFT 27
|
||||
#define XWAY_STP_PHY2_SHIFT 15
|
||||
#define XWAY_STP_PHY2_SHIFT 3
|
||||
#define XWAY_STP_PHY3_SHIFT 6
|
||||
#define XWAY_STP_PHY4_SHIFT 15
|
||||
|
||||
/* STP has 3 groups of 8 bits */
|
||||
#define XWAY_STP_GROUP0 BIT(0)
|
||||
@ -80,6 +85,8 @@ struct xway_stp {
|
||||
u8 dsl; /* the 2 LSBs can be driven by the dsl core */
|
||||
u8 phy1; /* 3 bits can be driven by phy1 */
|
||||
u8 phy2; /* 3 bits can be driven by phy2 */
|
||||
u8 phy3; /* 3 bits can be driven by phy3 */
|
||||
u8 phy4; /* 3 bits can be driven by phy4 */
|
||||
u8 reserved; /* mask out the hw driven bits in gpio_request */
|
||||
};
|
||||
|
||||
@ -114,7 +121,8 @@ static void xway_stp_set(struct gpio_chip *gc, unsigned gpio, int val)
|
||||
else
|
||||
chip->shadow &= ~BIT(gpio);
|
||||
xway_stp_w32(chip->virt, chip->shadow, XWAY_STP_CPU0);
|
||||
xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0);
|
||||
if (!chip->reserved)
|
||||
xway_stp_w32_mask(chip->virt, 0, XWAY_STP_CON_SWU, XWAY_STP_CON0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -188,16 +196,37 @@ static void xway_stp_hw_init(struct xway_stp *chip)
|
||||
chip->phy2 << XWAY_STP_PHY2_SHIFT,
|
||||
XWAY_STP_CON1);
|
||||
|
||||
if (of_machine_is_compatible("lantiq,grx390")
|
||||
|| of_machine_is_compatible("lantiq,ar10")) {
|
||||
xway_stp_w32_mask(chip->virt,
|
||||
XWAY_STP_PHY_MASK << XWAY_STP_PHY3_SHIFT,
|
||||
chip->phy3 << XWAY_STP_PHY3_SHIFT,
|
||||
XWAY_STP_CON1);
|
||||
}
|
||||
|
||||
if (of_machine_is_compatible("lantiq,grx390")) {
|
||||
xway_stp_w32_mask(chip->virt,
|
||||
XWAY_STP_PHY_MASK << XWAY_STP_PHY4_SHIFT,
|
||||
chip->phy4 << XWAY_STP_PHY4_SHIFT,
|
||||
XWAY_STP_CON1);
|
||||
}
|
||||
|
||||
/* mask out the hw driven bits in gpio_request */
|
||||
chip->reserved = (chip->phy2 << 5) | (chip->phy1 << 2) | chip->dsl;
|
||||
chip->reserved = (chip->phy4 << 11) | (chip->phy3 << 8) | (chip->phy2 << 5)
|
||||
| (chip->phy1 << 2) | chip->dsl;
|
||||
|
||||
/*
|
||||
* if we have pins that are driven by hw, we need to tell the stp what
|
||||
* clock to use as a timer.
|
||||
*/
|
||||
if (chip->reserved)
|
||||
if (chip->reserved) {
|
||||
xway_stp_w32_mask(chip->virt, XWAY_STP_UPD_MASK,
|
||||
XWAY_STP_UPD_FPI, XWAY_STP_CON1);
|
||||
xway_stp_w32_mask(chip->virt, XWAY_STP_SPEED_MASK,
|
||||
XWAY_STP_10HZ, XWAY_STP_CON1);
|
||||
xway_stp_w32_mask(chip->virt, XWAY_STP_FPIS_MASK,
|
||||
XWAY_STP_FPIS_VALUE, XWAY_STP_CON1);
|
||||
}
|
||||
}
|
||||
|
||||
static int xway_stp_probe(struct platform_device *pdev)
|
||||
@ -242,13 +271,26 @@ static int xway_stp_probe(struct platform_device *pdev)
|
||||
/* find out which gpios are controlled by the phys */
|
||||
if (of_machine_is_compatible("lantiq,ar9") ||
|
||||
of_machine_is_compatible("lantiq,gr9") ||
|
||||
of_machine_is_compatible("lantiq,vr9")) {
|
||||
of_machine_is_compatible("lantiq,vr9") ||
|
||||
of_machine_is_compatible("lantiq,ar10") ||
|
||||
of_machine_is_compatible("lantiq,grx390")) {
|
||||
if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy1", &phy))
|
||||
chip->phy1 = phy & XWAY_STP_PHY_MASK;
|
||||
if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy2", &phy))
|
||||
chip->phy2 = phy & XWAY_STP_PHY_MASK;
|
||||
}
|
||||
|
||||
if (of_machine_is_compatible("lantiq,ar10") ||
|
||||
of_machine_is_compatible("lantiq,grx390")) {
|
||||
if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy3", &phy))
|
||||
chip->phy3 = phy & XWAY_STP_PHY_MASK;
|
||||
}
|
||||
|
||||
if (of_machine_is_compatible("lantiq,grx390")) {
|
||||
if (!of_property_read_u32(pdev->dev.of_node, "lantiq,phy4", &phy))
|
||||
chip->phy4 = phy & XWAY_STP_PHY_MASK;
|
||||
}
|
||||
|
||||
/* check which edge trigger we should use, default to a falling edge */
|
||||
if (!of_find_property(pdev->dev.of_node, "lantiq,rising", NULL))
|
||||
chip->edge = XWAY_STP_FALLING;
|
||||
|
@ -19,9 +19,9 @@
|
||||
* These registers are modified under the irq bus lock and cached to avoid
|
||||
* unnecessary writes in bus_sync_unlock.
|
||||
*/
|
||||
enum { REG_IBE, REG_IEV, REG_IS, REG_IE };
|
||||
enum { REG_IBE, REG_IEV, REG_IS, REG_IE, REG_DIRECT };
|
||||
|
||||
#define CACHE_NR_REGS 4
|
||||
#define CACHE_NR_REGS 5
|
||||
#define CACHE_NR_BANKS 3
|
||||
|
||||
struct tc3589x_gpio {
|
||||
@ -200,6 +200,7 @@ static void tc3589x_gpio_irq_sync_unlock(struct irq_data *d)
|
||||
[REG_IEV] = TC3589x_GPIOIEV0,
|
||||
[REG_IS] = TC3589x_GPIOIS0,
|
||||
[REG_IE] = TC3589x_GPIOIE0,
|
||||
[REG_DIRECT] = TC3589x_DIRECT0,
|
||||
};
|
||||
int i, j;
|
||||
|
||||
@ -228,6 +229,7 @@ static void tc3589x_gpio_irq_mask(struct irq_data *d)
|
||||
int mask = BIT(offset % 8);
|
||||
|
||||
tc3589x_gpio->regs[REG_IE][regoffset] &= ~mask;
|
||||
tc3589x_gpio->regs[REG_DIRECT][regoffset] |= mask;
|
||||
}
|
||||
|
||||
static void tc3589x_gpio_irq_unmask(struct irq_data *d)
|
||||
@ -239,6 +241,7 @@ static void tc3589x_gpio_irq_unmask(struct irq_data *d)
|
||||
int mask = BIT(offset % 8);
|
||||
|
||||
tc3589x_gpio->regs[REG_IE][regoffset] |= mask;
|
||||
tc3589x_gpio->regs[REG_DIRECT][regoffset] &= ~mask;
|
||||
}
|
||||
|
||||
static struct irq_chip tc3589x_gpio_irq_chip = {
|
||||
@ -334,6 +337,17 @@ static int tc3589x_gpio_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* For tc35894, have to disable Direct KBD interrupts,
|
||||
* else IRQST will always be 0x20, IRQN low level, can't
|
||||
* clear the irq status.
|
||||
* TODO: need more test on other tc3589x chip.
|
||||
*
|
||||
*/
|
||||
ret = tc3589x_reg_write(tc3589x, TC3589x_DKBDMSK,
|
||||
TC3589x_DKBDMSK_ELINT | TC3589x_DKBDMSK_EINT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = devm_request_threaded_irq(&pdev->dev,
|
||||
irq, NULL, tc3589x_gpio_irq,
|
||||
IRQF_ONESHOT, "tc3589x-gpio",
|
||||
|
@ -929,11 +929,9 @@ static int zynq_gpio_probe(struct platform_device *pdev)
|
||||
|
||||
/* Retrieve GPIO clock */
|
||||
gpio->clk = devm_clk_get(&pdev->dev, NULL);
|
||||
if (IS_ERR(gpio->clk)) {
|
||||
if (PTR_ERR(gpio->clk) != -EPROBE_DEFER)
|
||||
dev_err(&pdev->dev, "input clock not found.\n");
|
||||
return PTR_ERR(gpio->clk);
|
||||
}
|
||||
if (IS_ERR(gpio->clk))
|
||||
return dev_err_probe(&pdev->dev, PTR_ERR(gpio->clk), "input clock not found.\n");
|
||||
|
||||
ret = clk_prepare_enable(gpio->clk);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "Unable to enable clock.\n");
|
||||
|
@ -1221,9 +1221,6 @@ void acpi_gpiochip_add(struct gpio_chip *chip)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chip->names)
|
||||
devprop_gpiochip_set_names(chip, dev_fwnode(chip->parent));
|
||||
|
||||
acpi_gpiochip_request_regions(acpi_gpio);
|
||||
acpi_gpiochip_scan_gpios(acpi_gpio);
|
||||
acpi_walk_dep_device_list(handle);
|
||||
|
@ -1,63 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Device property helpers for GPIO chips.
|
||||
*
|
||||
* Copyright (C) 2016, Intel Corporation
|
||||
* Author: Mika Westerberg <mika.westerberg@linux.intel.com>
|
||||
*/
|
||||
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio/consumer.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include "gpiolib.h"
|
||||
|
||||
/**
|
||||
* devprop_gpiochip_set_names - Set GPIO line names using device properties
|
||||
* @chip: GPIO chip whose lines should be named, if possible
|
||||
* @fwnode: Property Node containing the gpio-line-names property
|
||||
*
|
||||
* Looks for device property "gpio-line-names" and if it exists assigns
|
||||
* GPIO line names for the chip. The memory allocated for the assigned
|
||||
* names belong to the underlying firmware node and should not be released
|
||||
* by the caller.
|
||||
*/
|
||||
void devprop_gpiochip_set_names(struct gpio_chip *chip,
|
||||
const struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct gpio_device *gdev = chip->gpiodev;
|
||||
const char **names;
|
||||
int ret, i;
|
||||
int count;
|
||||
|
||||
count = fwnode_property_read_string_array(fwnode, "gpio-line-names",
|
||||
NULL, 0);
|
||||
if (count < 0)
|
||||
return;
|
||||
|
||||
if (count > gdev->ngpio) {
|
||||
dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d",
|
||||
count, gdev->ngpio);
|
||||
count = gdev->ngpio;
|
||||
}
|
||||
|
||||
names = kcalloc(count, sizeof(*names), GFP_KERNEL);
|
||||
if (!names)
|
||||
return;
|
||||
|
||||
ret = fwnode_property_read_string_array(fwnode, "gpio-line-names",
|
||||
names, count);
|
||||
if (ret < 0) {
|
||||
dev_warn(&gdev->dev, "failed to read GPIO line names\n");
|
||||
kfree(names);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
gdev->descs[i].name = names[i];
|
||||
|
||||
kfree(names);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devprop_gpiochip_set_names);
|
@ -1026,11 +1026,6 @@ int of_gpiochip_add(struct gpio_chip *chip)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If the chip defines names itself, these take precedence */
|
||||
if (!chip->names)
|
||||
devprop_gpiochip_set_names(chip,
|
||||
of_fwnode_handle(chip->of_node));
|
||||
|
||||
of_node_get(chip->of_node);
|
||||
|
||||
ret = of_gpiochip_scan_gpios(chip);
|
||||
|
@ -340,9 +340,6 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
|
||||
struct gpio_device *gdev = gc->gpiodev;
|
||||
int i;
|
||||
|
||||
if (!gc->names)
|
||||
return 0;
|
||||
|
||||
/* First check all names if they are unique */
|
||||
for (i = 0; i != gc->ngpio; ++i) {
|
||||
struct gpio_desc *gpio;
|
||||
@ -361,6 +358,57 @@ static int gpiochip_set_desc_names(struct gpio_chip *gc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* devprop_gpiochip_set_names - Set GPIO line names using device properties
|
||||
* @chip: GPIO chip whose lines should be named, if possible
|
||||
*
|
||||
* Looks for device property "gpio-line-names" and if it exists assigns
|
||||
* GPIO line names for the chip. The memory allocated for the assigned
|
||||
* names belong to the underlying software node and should not be released
|
||||
* by the caller.
|
||||
*/
|
||||
static int devprop_gpiochip_set_names(struct gpio_chip *chip)
|
||||
{
|
||||
struct gpio_device *gdev = chip->gpiodev;
|
||||
struct device *dev = chip->parent;
|
||||
const char **names;
|
||||
int ret, i;
|
||||
int count;
|
||||
|
||||
/* GPIO chip may not have a parent device whose properties we inspect. */
|
||||
if (!dev)
|
||||
return 0;
|
||||
|
||||
count = device_property_string_array_count(dev, "gpio-line-names");
|
||||
if (count < 0)
|
||||
return 0;
|
||||
|
||||
if (count > gdev->ngpio) {
|
||||
dev_warn(&gdev->dev, "gpio-line-names is length %d but should be at most length %d",
|
||||
count, gdev->ngpio);
|
||||
count = gdev->ngpio;
|
||||
}
|
||||
|
||||
names = kcalloc(count, sizeof(*names), GFP_KERNEL);
|
||||
if (!names)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = device_property_read_string_array(dev, "gpio-line-names",
|
||||
names, count);
|
||||
if (ret < 0) {
|
||||
dev_warn(&gdev->dev, "failed to read GPIO line names\n");
|
||||
kfree(names);
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
gdev->descs[i].name = names[i];
|
||||
|
||||
kfree(names);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long *gpiochip_allocate_mask(struct gpio_chip *gc)
|
||||
{
|
||||
unsigned long *p;
|
||||
@ -426,7 +474,7 @@ static void gpiodevice_release(struct device *dev)
|
||||
struct gpio_device *gdev = dev_get_drvdata(dev);
|
||||
|
||||
list_del(&gdev->list);
|
||||
ida_simple_remove(&gpio_ida, gdev->id);
|
||||
ida_free(&gpio_ida, gdev->id);
|
||||
kfree_const(gdev->label);
|
||||
kfree(gdev->descs);
|
||||
kfree(gdev);
|
||||
@ -537,7 +585,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
||||
gc->of_node = gdev->dev.of_node;
|
||||
#endif
|
||||
|
||||
gdev->id = ida_simple_get(&gpio_ida, 0, 0, GFP_KERNEL);
|
||||
gdev->id = ida_alloc(&gpio_ida, GFP_KERNEL);
|
||||
if (gdev->id < 0) {
|
||||
ret = gdev->id;
|
||||
goto err_free_gdev;
|
||||
@ -621,7 +669,10 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
||||
INIT_LIST_HEAD(&gdev->pin_ranges);
|
||||
#endif
|
||||
|
||||
ret = gpiochip_set_desc_names(gc);
|
||||
if (gc->names)
|
||||
ret = gpiochip_set_desc_names(gc);
|
||||
else
|
||||
ret = devprop_gpiochip_set_names(gc);
|
||||
if (ret)
|
||||
goto err_remove_from_list;
|
||||
|
||||
@ -705,7 +756,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *gc, void *data,
|
||||
err_free_descs:
|
||||
kfree(gdev->descs);
|
||||
err_free_ida:
|
||||
ida_simple_remove(&gpio_ida, gdev->id);
|
||||
ida_free(&gpio_ida, gdev->id);
|
||||
err_free_gdev:
|
||||
/* failures here can mean systems won't boot... */
|
||||
pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,
|
||||
@ -4402,31 +4453,18 @@ static int gpiolib_seq_show(struct seq_file *s, void *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct seq_operations gpiolib_seq_ops = {
|
||||
static const struct seq_operations gpiolib_sops = {
|
||||
.start = gpiolib_seq_start,
|
||||
.next = gpiolib_seq_next,
|
||||
.stop = gpiolib_seq_stop,
|
||||
.show = gpiolib_seq_show,
|
||||
};
|
||||
|
||||
static int gpiolib_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &gpiolib_seq_ops);
|
||||
}
|
||||
|
||||
static const struct file_operations gpiolib_operations = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = gpiolib_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
};
|
||||
DEFINE_SEQ_ATTRIBUTE(gpiolib);
|
||||
|
||||
static int __init gpiolib_debugfs_init(void)
|
||||
{
|
||||
/* /sys/kernel/debug/gpio */
|
||||
debugfs_create_file("gpio", S_IFREG | S_IRUGO, NULL, NULL,
|
||||
&gpiolib_operations);
|
||||
debugfs_create_file("gpio", 0444, NULL, NULL, &gpiolib_fops);
|
||||
return 0;
|
||||
}
|
||||
subsys_initcall(gpiolib_debugfs_init);
|
||||
|
@ -756,9 +756,6 @@ struct gpio_desc *gpiochip_request_own_desc(struct gpio_chip *gc,
|
||||
enum gpiod_flags dflags);
|
||||
void gpiochip_free_own_desc(struct gpio_desc *desc);
|
||||
|
||||
void devprop_gpiochip_set_names(struct gpio_chip *gc,
|
||||
const struct fwnode_handle *fwnode);
|
||||
|
||||
#ifdef CONFIG_GPIOLIB
|
||||
|
||||
/* lock/unlock as IRQ */
|
||||
|
@ -19,6 +19,9 @@ enum tx3589x_block {
|
||||
#define TC3589x_RSTCTRL_KBDRST (1 << 1)
|
||||
#define TC3589x_RSTCTRL_GPIRST (1 << 0)
|
||||
|
||||
#define TC3589x_DKBDMSK_ELINT (1 << 1)
|
||||
#define TC3589x_DKBDMSK_EINT (1 << 0)
|
||||
|
||||
/* Keyboard Configuration Registers */
|
||||
#define TC3589x_KBDSETTLE_REG 0x01
|
||||
#define TC3589x_KBDBOUNCE 0x02
|
||||
@ -101,6 +104,9 @@ enum tx3589x_block {
|
||||
#define TC3589x_GPIOODM2 0xE4
|
||||
#define TC3589x_GPIOODE2 0xE5
|
||||
|
||||
#define TC3589x_DIRECT0 0xEC
|
||||
#define TC3589x_DKBDMSK 0xF3
|
||||
|
||||
#define TC3589x_INT_GPIIRQ 0
|
||||
#define TC3589x_INT_TI0IRQ 1
|
||||
#define TC3589x_INT_TI1IRQ 2
|
||||
|
@ -170,6 +170,12 @@ static inline int device_property_count_u64(struct device *dev, const char *prop
|
||||
return device_property_read_u64_array(dev, propname, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int device_property_string_array_count(struct device *dev,
|
||||
const char *propname)
|
||||
{
|
||||
return device_property_read_string_array(dev, propname, NULL, 0);
|
||||
}
|
||||
|
||||
static inline bool fwnode_property_read_bool(const struct fwnode_handle *fwnode,
|
||||
const char *propname)
|
||||
{
|
||||
@ -224,6 +230,13 @@ static inline int fwnode_property_count_u64(const struct fwnode_handle *fwnode,
|
||||
return fwnode_property_read_u64_array(fwnode, propname, NULL, 0);
|
||||
}
|
||||
|
||||
static inline int
|
||||
fwnode_property_string_array_count(const struct fwnode_handle *fwnode,
|
||||
const char *propname)
|
||||
{
|
||||
return fwnode_property_read_string_array(fwnode, propname, NULL, 0);
|
||||
}
|
||||
|
||||
struct software_node;
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user