^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * htc-i2cpld.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Chip driver for an unknown CPLD chip found on omap850 HTC devices like
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * the HTC Wizard and HTC Herald.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * The cpld is located on the i2c bus and acts as an input/output GPIO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * extender.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Copyright (C) 2009 Cory Maccarrone <darkstar6262@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * Based on work done in the linwizard project
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Copyright (C) 2008-2009 Angelo Arrifano <miknix@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/i2c.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/spinlock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/htcpld.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct htcpld_chip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /* chip info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) u8 reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) u8 addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* Output details */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) u8 cache_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct gpio_chip chip_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /* Input details */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) u8 cache_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) struct gpio_chip chip_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u16 irqs_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) uint irq_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) int nirqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) unsigned int flow_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * Work structure to allow for setting values outside of any
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * possible interrupt context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) struct work_struct set_val_work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) struct htcpld_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* irq info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) u16 irqs_enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) uint irq_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) int nirqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) uint chained_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) unsigned int int_reset_gpio_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) unsigned int int_reset_gpio_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* htcpld info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct htcpld_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) unsigned int nchips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* There does not appear to be a way to proactively mask interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) * on the htcpld chip itself. So, we simply ignore interrupts that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * aren't desired. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void htcpld_mask(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) chip->irqs_enabled &= ~(1 << (data->irq - chip->irq_start));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) pr_debug("HTCPLD mask %d %04x\n", data->irq, chip->irqs_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) static void htcpld_unmask(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) chip->irqs_enabled |= 1 << (data->irq - chip->irq_start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) pr_debug("HTCPLD unmask %d %04x\n", data->irq, chip->irqs_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int htcpld_set_type(struct irq_data *data, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (flags & ~IRQ_TYPE_SENSE_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) /* We only allow edge triggering */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) chip->flow_type = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) static struct irq_chip htcpld_muxed_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) .name = "htcpld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) .irq_mask = htcpld_mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) .irq_unmask = htcpld_unmask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) .irq_set_type = htcpld_set_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* To properly dispatch IRQ events, we need to read from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * chip. This is an I2C action that could possibly sleep
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * (which is bad in interrupt context) -- so we use a threaded
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * interrupt handler to get around that.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) static irqreturn_t htcpld_handler(int irq, void *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) struct htcpld_data *htcpld = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) int irqpin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (!htcpld) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) pr_debug("htcpld is null in ISR\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * For each chip, do a read of the chip and trigger any interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * desired. The interrupts will be triggered from LSB to MSB (i.e.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * bit 0 first, then bit 1, etc.)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) * For chips that have no interrupt range specified, just skip 'em.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) for (i = 0; i < htcpld->nchips; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct htcpld_chip *chip = &htcpld->chip[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) int val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) unsigned long uval, old_val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) if (!chip) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) pr_debug("chip %d is null in ISR\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (chip->nirqs == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) client = chip->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (!client) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) pr_debug("client %d is null in ISR\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* Scan the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) val = i2c_smbus_read_byte_data(client, chip->cache_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (val < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* Throw a warning and skip this chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) dev_warn(chip->dev, "Unable to read from chip: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) uval = (unsigned long)val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) spin_lock_irqsave(&chip->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* Save away the old value so we can compare it */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) old_val = chip->cache_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) /* Write the new value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) chip->cache_in = uval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) spin_unlock_irqrestore(&chip->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * For each bit in the data (starting at bit 0), trigger
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * associated interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) unsigned oldb, newb, type = chip->flow_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) irq = chip->irq_start + irqpin;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) /* Run the IRQ handler, but only if the bit value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) * changed, and the proper flags are set */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) oldb = (old_val >> irqpin) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) newb = (uval >> irqpin) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) if ((!oldb && newb && (type & IRQ_TYPE_EDGE_RISING)) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) (oldb && !newb && (type & IRQ_TYPE_EDGE_FALLING))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) pr_debug("fire IRQ %d\n", irqpin);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) generic_handle_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) * In order to continue receiving interrupts, the int_reset_gpio must
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * be asserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) if (htcpld->int_reset_gpio_hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) gpio_set_value(htcpld->int_reset_gpio_hi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (htcpld->int_reset_gpio_lo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) gpio_set_value(htcpld->int_reset_gpio_lo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) * The GPIO set routines can be called from interrupt context, especially if,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) * for example they're attached to the led-gpio framework and a trigger is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * enabled. As such, we declared work above in the htcpld_chip structure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) * and that work is scheduled in the set routine. The kernel can then run
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * the I2C functions, which will sleep, in process context.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) static void htcpld_chip_set(struct gpio_chip *chip, unsigned offset, int val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct htcpld_chip *chip_data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) client = chip_data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) if (!client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) spin_lock_irqsave(&chip_data->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if (val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) chip_data->cache_out |= (1 << offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) chip_data->cache_out &= ~(1 << offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) spin_unlock_irqrestore(&chip_data->lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) schedule_work(&(chip_data->set_val_work));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) static void htcpld_chip_set_ni(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) struct htcpld_chip *chip_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) chip_data = container_of(work, struct htcpld_chip, set_val_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) client = chip_data->client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) i2c_smbus_read_byte_data(client, chip_data->cache_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static int htcpld_chip_get(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) struct htcpld_chip *chip_data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) u8 cache;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (!strncmp(chip->label, "htcpld-out", 10)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) cache = chip_data->cache_out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) } else if (!strncmp(chip->label, "htcpld-in", 9)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) cache = chip_data->cache_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) return (cache >> offset) & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) static int htcpld_direction_output(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) unsigned offset, int value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) htcpld_chip_set(chip, offset, value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) static int htcpld_direction_input(struct gpio_chip *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) * No-op: this function can only be called on the input chip.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) * We do however make sure the offset is within range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return (offset < chip->ngpio) ? 0 : -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) static int htcpld_chip_to_irq(struct gpio_chip *chip, unsigned offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct htcpld_chip *chip_data = gpiochip_get_data(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (offset < chip_data->nirqs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return chip_data->irq_start + offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) static void htcpld_chip_reset(struct i2c_client *client)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) struct htcpld_chip *chip_data = i2c_get_clientdata(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (!chip_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) i2c_smbus_read_byte_data(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) client, (chip_data->cache_out = chip_data->reset));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static int htcpld_setup_chip_irq(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) int chip_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) struct htcpld_data *htcpld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) struct htcpld_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) unsigned int irq, irq_end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) /* Get the platform and driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) htcpld = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) chip = &htcpld->chip[chip_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) /* Setup irq handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) irq_end = chip->irq_start + chip->nirqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) for (irq = chip->irq_start; irq < irq_end; irq++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) irq_set_chip_and_handler(irq, &htcpld_muxed_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) handle_simple_irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) irq_set_chip_data(irq, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) irq_clear_status_flags(irq, IRQ_NOREQUEST | IRQ_NOPROBE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int htcpld_register_chip_i2c(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) int chip_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct htcpld_data *htcpld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) struct htcpld_core_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct htcpld_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) struct htcpld_chip_platform_data *plat_chip_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) struct i2c_adapter *adapter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) struct i2c_client *client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct i2c_board_info info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Get the platform and driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) htcpld = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) chip = &htcpld->chip[chip_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) plat_chip_data = &pdata->chip[chip_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) adapter = i2c_get_adapter(pdata->i2c_adapter_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (!adapter) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /* Eek, no such I2C adapter! Bail out. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) dev_warn(dev, "Chip at i2c address 0x%x: Invalid i2c adapter %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) plat_chip_data->addr, pdata->i2c_adapter_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dev_warn(dev, "i2c adapter %d non-functional\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) pdata->i2c_adapter_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) i2c_put_adapter(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) memset(&info, 0, sizeof(struct i2c_board_info));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) info.addr = plat_chip_data->addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) strlcpy(info.type, "htcpld-chip", I2C_NAME_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) info.platform_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Add the I2C device. This calls the probe() function. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) client = i2c_new_client_device(adapter, &info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (IS_ERR(client)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /* I2C device registration failed, contineu with the next */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) dev_warn(dev, "Unable to add I2C device for 0x%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) plat_chip_data->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) i2c_put_adapter(adapter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) return PTR_ERR(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) i2c_set_clientdata(client, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) snprintf(client->name, I2C_NAME_SIZE, "Chip_0x%x", client->addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) chip->client = client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) /* Reset the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) htcpld_chip_reset(client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) chip->cache_in = i2c_smbus_read_byte_data(client, chip->cache_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) static void htcpld_unregister_chip_i2c(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int chip_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct htcpld_data *htcpld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct htcpld_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) /* Get the platform and driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) htcpld = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) chip = &htcpld->chip[chip_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) i2c_unregister_device(chip->client);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) static int htcpld_register_chip_gpio(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) struct platform_device *pdev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) int chip_index)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) struct htcpld_data *htcpld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct htcpld_core_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) struct htcpld_chip *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct htcpld_chip_platform_data *plat_chip_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct gpio_chip *gpio_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) /* Get the platform and driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) htcpld = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) chip = &htcpld->chip[chip_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) plat_chip_data = &pdata->chip[chip_index];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /* Setup the GPIO chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) gpio_chip = &(chip->chip_out);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) gpio_chip->label = "htcpld-out";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) gpio_chip->parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) gpio_chip->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) gpio_chip->get = htcpld_chip_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) gpio_chip->set = htcpld_chip_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) gpio_chip->direction_input = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) gpio_chip->direction_output = htcpld_direction_output;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) gpio_chip->base = plat_chip_data->gpio_out_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) gpio_chip->ngpio = plat_chip_data->num_gpios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) gpio_chip = &(chip->chip_in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) gpio_chip->label = "htcpld-in";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) gpio_chip->parent = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) gpio_chip->owner = THIS_MODULE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) gpio_chip->get = htcpld_chip_get;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) gpio_chip->set = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) gpio_chip->direction_input = htcpld_direction_input;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) gpio_chip->direction_output = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) gpio_chip->to_irq = htcpld_chip_to_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) gpio_chip->base = plat_chip_data->gpio_in_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) gpio_chip->ngpio = plat_chip_data->num_gpios;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* Add the GPIO chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) ret = gpiochip_add_data(&(chip->chip_out), chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) dev_warn(dev, "Unable to register output GPIOs for 0x%x: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) plat_chip_data->addr, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) ret = gpiochip_add_data(&(chip->chip_in), chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) dev_warn(dev, "Unable to register input GPIOs for 0x%x: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) plat_chip_data->addr, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) gpiochip_remove(&(chip->chip_out));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static int htcpld_setup_chips(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct htcpld_data *htcpld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct htcpld_core_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) /* Get the platform and driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) htcpld = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) /* Setup each chip's output GPIOs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) htcpld->nchips = pdata->num_chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) htcpld->chip = devm_kcalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) htcpld->nchips,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) sizeof(struct htcpld_chip),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) if (!htcpld->chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Add the chips as best we can */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) for (i = 0; i < htcpld->nchips; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) /* Setup the HTCPLD chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) htcpld->chip[i].reset = pdata->chip[i].reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) htcpld->chip[i].cache_out = pdata->chip[i].reset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) htcpld->chip[i].cache_in = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) htcpld->chip[i].dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) htcpld->chip[i].irq_start = pdata->chip[i].irq_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) htcpld->chip[i].nirqs = pdata->chip[i].num_irqs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) INIT_WORK(&(htcpld->chip[i].set_val_work), &htcpld_chip_set_ni);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) spin_lock_init(&(htcpld->chip[i].lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* Setup the interrupts for the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (htcpld->chained_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) ret = htcpld_setup_chip_irq(pdev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) /* Register the chip with I2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) ret = htcpld_register_chip_i2c(pdev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) /* Register the chips with the GPIO subsystem */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) ret = htcpld_register_chip_gpio(pdev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) /* Unregister the chip from i2c and continue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) htcpld_unregister_chip_i2c(pdev, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dev_info(dev, "Registered chip at 0x%x\n", pdata->chip[i].addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) static int htcpld_core_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) struct htcpld_data *htcpld;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) struct htcpld_core_platform_data *pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) if (!dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) pdata = dev_get_platdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) if (!pdata) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) dev_warn(dev, "Platform data not found for htcpld core!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) htcpld = devm_kzalloc(dev, sizeof(struct htcpld_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (!htcpld)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /* Find chained irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) if (res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) int flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) htcpld->chained_irq = res->start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) /* Setup the chained interrupt handler */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) IRQF_ONESHOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) ret = request_threaded_irq(htcpld->chained_irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) NULL, htcpld_handler,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) flags, pdev->name, htcpld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) dev_warn(dev, "Unable to setup chained irq handler: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) device_init_wakeup(dev, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) /* Set the driver data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) platform_set_drvdata(pdev, htcpld);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) /* Setup the htcpld chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) ret = htcpld_setup_chips(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* Request the GPIO(s) for the int reset and set them up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) if (pdata->int_reset_gpio_hi) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) ret = gpio_request(pdata->int_reset_gpio_hi, "htcpld-core");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) * If it failed, that sucks, but we can probably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) * continue on without it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) dev_warn(dev, "Unable to request int_reset_gpio_hi -- interrupts may not work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) htcpld->int_reset_gpio_hi = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) htcpld->int_reset_gpio_hi = pdata->int_reset_gpio_hi;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) gpio_set_value(htcpld->int_reset_gpio_hi, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (pdata->int_reset_gpio_lo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) ret = gpio_request(pdata->int_reset_gpio_lo, "htcpld-core");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * If it failed, that sucks, but we can probably
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * continue on without it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) dev_warn(dev, "Unable to request int_reset_gpio_lo -- interrupts may not work\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) htcpld->int_reset_gpio_lo = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) htcpld->int_reset_gpio_lo = pdata->int_reset_gpio_lo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) gpio_set_value(htcpld->int_reset_gpio_lo, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) dev_info(dev, "Initialized successfully\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) /* The I2C Driver -- used internally */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) static const struct i2c_device_id htcpld_chip_id[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) { "htcpld-chip", 0 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) { }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) static struct i2c_driver htcpld_chip_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) .name = "htcpld-chip",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) .id_table = htcpld_chip_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) /* The Core Driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) static struct platform_driver htcpld_core_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) .name = "i2c-htcpld",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static int __init htcpld_core_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) /* Register the I2C Chip driver */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) ret = i2c_add_driver(&htcpld_chip_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) /* Probe for our chips */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) return platform_driver_probe(&htcpld_core_driver, htcpld_core_probe);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) device_initcall(htcpld_core_init);