cregit-Linux how code gets into the kernel

Release 4.7 drivers/gpio/gpio-sx150x.c

Directory: drivers/gpio
/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
 *
 * Driver for Semtech SX150X I2C GPIO Expanders
 *
 * Author: Gregory Bean <gbean@codeaurora.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/of_device.h>


#define NO_UPDATE_PENDING	-1

/* The chip models of sx150x */

#define SX150X_123 0

#define SX150X_456 1

#define SX150X_789 2


struct sx150x_123_pri {
	
u8 reg_pld_mode;
	
u8 reg_pld_table0;
	
u8 reg_pld_table1;
	
u8 reg_pld_table2;
	
u8 reg_pld_table3;
	
u8 reg_pld_table4;
	
u8 reg_advance;
};


struct sx150x_456_pri {
	
u8 reg_pld_mode;
	
u8 reg_pld_table0;
	
u8 reg_pld_table1;
	
u8 reg_pld_table2;
	
u8 reg_pld_table3;
	
u8 reg_pld_table4;
	
u8 reg_advance;
};


struct sx150x_789_pri {
	
u8 reg_drain;
	
u8 reg_polarity;
	
u8 reg_clock;
	
u8 reg_misc;
	
u8 reg_reset;
	
u8 ngpios;
};


struct sx150x_device_data {
	
u8 model;
	
u8 reg_pullup;
	
u8 reg_pulldn;
	
u8 reg_dir;
	
u8 reg_data;
	
u8 reg_irq_mask;
	
u8 reg_irq_src;
	
u8 reg_sense;
	
u8 ngpios;
	union {
		
struct sx150x_123_pri x123;
		
struct sx150x_456_pri x456;
		
struct sx150x_789_pri x789;
	} 
pri;
};

/**
 * struct sx150x_platform_data - config data for SX150x driver
 * @gpio_base: The index number of the first GPIO assigned to this
 *             GPIO expander.  The expander will create a block of
 *             consecutively numbered gpios beginning at the given base,
 *             with the size of the block depending on the model of the
 *             expander chip.
 * @oscio_is_gpo: If set to true, the driver will configure OSCIO as a GPO
 *                instead of as an oscillator, increasing the size of the
 *                GP(I)O pool created by this expander by one.  The
 *                output-only GPO pin will be added at the end of the block.
 * @io_pullup_ena: A bit-mask which enables or disables the pull-up resistor
 *                 for each IO line in the expander.  Setting the bit at
 *                 position n will enable the pull-up for the IO at
 *                 the corresponding offset.  For chips with fewer than
 *                 16 IO pins, high-end bits are ignored.
 * @io_pulldn_ena: A bit-mask which enables-or disables the pull-down
 *                 resistor for each IO line in the expander. Setting the
 *                 bit at position n will enable the pull-down for the IO at
 *                 the corresponding offset.  For chips with fewer than
 *                 16 IO pins, high-end bits are ignored.
 * @io_polarity: A bit-mask which enables polarity inversion for each IO line
 *               in the expander.  Setting the bit at position n inverts
 *               the polarity of that IO line, while clearing it results
 *               in normal polarity. For chips with fewer than 16 IO pins,
 *               high-end bits are ignored.
 * @irq_summary: The 'summary IRQ' line to which the GPIO expander's INT line
 *               is connected, via which it reports interrupt events
 *               across all GPIO lines.  This must be a real,
 *               pre-existing IRQ line.
 *               Setting this value < 0 disables the irq_chip functionality
 *               of the driver.
 * @irq_base: The first 'virtual IRQ' line at which our block of GPIO-based
 *            IRQ lines will appear.  Similarly to gpio_base, the expander
 *            will create a block of irqs beginning at this number.
 *            This value is ignored if irq_summary is < 0.
 * @reset_during_probe: If set to true, the driver will trigger a full
 *                      reset of the chip at the beginning of the probe
 *                      in order to place it in a known state.
 */

struct sx150x_platform_data {
	
unsigned gpio_base;
	
bool     oscio_is_gpo;
	
u16      io_pullup_ena;
	
u16      io_pulldn_ena;
	
u16      io_polarity;
	
int      irq_summary;
	
unsigned irq_base;
	
bool     reset_during_probe;
};


struct sx150x_chip {
	
struct gpio_chip                 gpio_chip;
	
struct i2c_client               *client;
	
const struct sx150x_device_data *dev_cfg;
	
int                              irq_summary;
	
int                              irq_base;
	
int				 irq_update;
	
u32                              irq_sense;
	
u32				 irq_masked;
	
u32				 dev_sense;
	
u32				 dev_masked;
	
struct irq_chip                  irq_chip;
	
struct mutex                     lock;
};


static const struct sx150x_device_data sx150x_devices[] = {
	[0] = { /* sx1508q */
		.model = SX150X_789,
		.reg_pullup	= 0x03,
		.reg_pulldn	= 0x04,
		.reg_dir	= 0x07,
		.reg_data	= 0x08,
		.reg_irq_mask	= 0x09,
		.reg_irq_src	= 0x0c,
		.reg_sense	= 0x0b,
		.pri.x789 = {
			.reg_drain	= 0x05,
			.reg_polarity	= 0x06,
			.reg_clock	= 0x0f,
			.reg_misc	= 0x10,
			.reg_reset	= 0x7d,
                },
		.ngpios = 8,
        },
	[1] = { /* sx1509q */
		.model = SX150X_789,
		.reg_pullup	= 0x07,
		.reg_pulldn	= 0x09,
		.reg_dir	= 0x0f,
		.reg_data	= 0x11,
		.reg_irq_mask	= 0x13,
		.reg_irq_src	= 0x19,
		.reg_sense	= 0x17,
		.pri.x789 = {
			.reg_drain	= 0x0b,
			.reg_polarity	= 0x0d,
			.reg_clock	= 0x1e,
			.reg_misc	= 0x1f,
			.reg_reset	= 0x7d,
                },
		.ngpios	= 16
	},
	[2] = { /* sx1506q */
		.model = SX150X_456,
		.reg_pullup	= 0x05,
		.reg_pulldn	= 0x07,
		.reg_dir	= 0x03,
		.reg_data	= 0x01,
		.reg_irq_mask	= 0x09,
		.reg_irq_src	= 0x0f,
		.reg_sense	= 0x0d,
		.pri.x456 = {
			.reg_pld_mode	= 0x21,
			.reg_pld_table0	= 0x23,
			.reg_pld_table1	= 0x25,
			.reg_pld_table2	= 0x27,
			.reg_pld_table3	= 0x29,
			.reg_pld_table4	= 0x2b,
			.reg_advance	= 0xad,
                },
		.ngpios	= 16
	},
	[3] = { /* sx1502q */
		.model = SX150X_123,
		.reg_pullup	= 0x02,
		.reg_pulldn	= 0x03,
		.reg_dir	= 0x01,
		.reg_data	= 0x00,
		.reg_irq_mask	= 0x05,
		.reg_irq_src	= 0x08,
		.reg_sense	= 0x07,
		.pri.x123 = {
			.reg_pld_mode	= 0x10,
			.reg_pld_table0	= 0x11,
			.reg_pld_table1	= 0x12,
			.reg_pld_table2	= 0x13,
			.reg_pld_table3	= 0x14,
			.reg_pld_table4	= 0x15,
			.reg_advance	= 0xad,
                },
		.ngpios	= 8,
        },
};


static const struct i2c_device_id sx150x_id[] = {
	{"sx1508q", 0},
	{"sx1509q", 1},
	{"sx1506q", 2},
	{"sx1502q", 3},
	{}
};
MODULE_DEVICE_TABLE(i2c, sx150x_id);


static const struct of_device_id sx150x_of_match[] = {
	{ .compatible = "semtech,sx1508q" },
	{ .compatible = "semtech,sx1509q" },
	{ .compatible = "semtech,sx1506q" },
	{ .compatible = "semtech,sx1502q" },
	{},
};
MODULE_DEVICE_TABLE(of, sx150x_of_match);


static s32 sx150x_i2c_write(struct i2c_client *client, u8 reg, u8 val) { s32 err = i2c_smbus_write_byte_data(client, reg, val); if (err < 0) dev_warn(&client->dev, "i2c write fail: can't write %02x to %02x: %d\n", val, reg, err); return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean54100.00%1100.00%
Total54100.00%1100.00%


static s32 sx150x_i2c_read(struct i2c_client *client, u8 reg, u8 *val) { s32 err = i2c_smbus_read_byte_data(client, reg); if (err >= 0) *val = err; else dev_warn(&client->dev, "i2c read fail: can't read from %02x: %d\n", reg, err); return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean57100.00%1100.00%
Total57100.00%1100.00%


static inline bool offset_is_oscio(struct sx150x_chip *chip, unsigned offset) { return (chip->dev_cfg->ngpios == offset); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean26100.00%1100.00%
Total26100.00%1100.00%

/* * These utility functions solve the common problem of locating and setting * configuration bits. Configuration bits are grouped into registers * whose indexes increase downwards. For example, with eight-bit registers, * sixteen gpios would have their config bits grouped in the following order: * REGISTER N-1 [ f e d c b a 9 8 ] * N [ 7 6 5 4 3 2 1 0 ] * * For multi-bit configurations, the pattern gets wider: * REGISTER N-3 [ f f e e d d c c ] * N-2 [ b b a a 9 9 8 8 ] * N-1 [ 7 7 6 6 5 5 4 4 ] * N [ 3 3 2 2 1 1 0 0 ] * * Given the address of the starting register 'N', the index of the gpio * whose configuration we seek to change, and the width in bits of that * configuration, these functions allow us to locate the correct * register and mask the correct bits. */
static inline void sx150x_find_cfg(u8 offset, u8 width, u8 *reg, u8 *mask, u8 *shift) { *reg -= offset * width / 8; *mask = (1 << width) - 1; *shift = (offset * width) % 8; *mask <<= *shift; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean62100.00%1100.00%
Total62100.00%1100.00%


static s32 sx150x_write_cfg(struct sx150x_chip *chip, u8 offset, u8 width, u8 reg, u8 val) { u8 mask; u8 data; u8 shift; s32 err; sx150x_find_cfg(offset, width, &reg, &mask, &shift); err = sx150x_i2c_read(chip->client, reg, &data); if (err < 0) return err; data &= ~mask; data |= (val << shift) & mask; return sx150x_i2c_write(chip->client, reg, data); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean101100.00%1100.00%
Total101100.00%1100.00%


static int sx150x_get_io(struct sx150x_chip *chip, unsigned offset) { u8 reg = chip->dev_cfg->reg_data; u8 mask; u8 data; u8 shift; s32 err; sx150x_find_cfg(offset, 1, &reg, &mask, &shift); err = sx150x_i2c_read(chip->client, reg, &data); if (err >= 0) err = (data & mask) != 0 ? 1 : 0; return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean88100.00%1100.00%
Total88100.00%1100.00%


static void sx150x_set_oscio(struct sx150x_chip *chip, int val) { sx150x_i2c_write(chip->client, chip->dev_cfg->pri.x789.reg_clock, (val ? 0x1f : 0x10)); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean3589.74%150.00%
wei chenwei chen410.26%150.00%
Total39100.00%2100.00%


static void sx150x_set_io(struct sx150x_chip *chip, unsigned offset, int val) { sx150x_write_cfg(chip, offset, 1, chip->dev_cfg->reg_data, (val ? 1 : 0)); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean40100.00%1100.00%
Total40100.00%1100.00%


static int sx150x_io_input(struct sx150x_chip *chip, unsigned offset) { return sx150x_write_cfg(chip, offset, 1, chip->dev_cfg->reg_dir, 1); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean32100.00%1100.00%
Total32100.00%1100.00%


static int sx150x_io_output(struct sx150x_chip *chip, unsigned offset, int val) { int err; err = sx150x_write_cfg(chip, offset, 1, chip->dev_cfg->reg_data, (val ? 1 : 0)); if (err >= 0) err = sx150x_write_cfg(chip, offset, 1, chip->dev_cfg->reg_dir, 0); return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean73100.00%1100.00%
Total73100.00%1100.00%


static int sx150x_gpio_get(struct gpio_chip *gc, unsigned offset) { struct sx150x_chip *chip = gpiochip_get_data(gc); int status = -EINVAL; if (!offset_is_oscio(chip, offset)) { mutex_lock(&chip->lock); status = sx150x_get_io(chip, offset); mutex_unlock(&chip->lock); } return (status < 0) ? status : !!status; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean6581.25%125.00%
linus walleijlinus walleij1518.75%375.00%
Total80100.00%4100.00%


static void sx150x_gpio_set(struct gpio_chip *gc, unsigned offset, int val) { struct sx150x_chip *chip = gpiochip_get_data(gc); mutex_lock(&chip->lock); if (offset_is_oscio(chip, offset)) sx150x_set_oscio(chip, val); else sx150x_set_io(chip, offset, val); mutex_unlock(&chip->lock); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean6695.65%133.33%
linus walleijlinus walleij34.35%266.67%
Total69100.00%3100.00%


static int sx150x_gpio_set_single_ended(struct gpio_chip *gc, unsigned offset, enum single_ended_mode mode) { struct sx150x_chip *chip = gpiochip_get_data(gc); /* On the SX160X 789 we can set open drain */ if (chip->dev_cfg->model != SX150X_789) return -ENOTSUPP; if (mode == LINE_MODE_PUSH_PULL) return sx150x_write_cfg(chip, offset, 1, chip->dev_cfg->pri.x789.reg_drain, 0); if (mode == LINE_MODE_OPEN_DRAIN) return sx150x_write_cfg(chip, offset, 1, chip->dev_cfg->pri.x789.reg_drain, 1); return -ENOTSUPP; }

Contributors

PersonTokensPropCommitsCommitProp
linus walleijlinus walleij103100.00%1100.00%
Total103100.00%1100.00%


static int sx150x_gpio_direction_input(struct gpio_chip *gc, unsigned offset) { struct sx150x_chip *chip = gpiochip_get_data(gc); int status = -EINVAL; if (!offset_is_oscio(chip, offset)) { mutex_lock(&chip->lock); status = sx150x_io_input(chip, offset); mutex_unlock(&chip->lock); } return status; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean6592.86%133.33%
linus walleijlinus walleij57.14%266.67%
Total70100.00%3100.00%


static int sx150x_gpio_direction_output(struct gpio_chip *gc, unsigned offset, int val) { struct sx150x_chip *chip = gpiochip_get_data(gc); int status = 0; if (!offset_is_oscio(chip, offset)) { mutex_lock(&chip->lock); status = sx150x_io_output(chip, offset, val); mutex_unlock(&chip->lock); } return status; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean6993.24%133.33%
linus walleijlinus walleij56.76%266.67%
Total74100.00%3100.00%


static void sx150x_irq_mask(struct irq_data *d) { struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); unsigned n = d->hwirq; chip->irq_masked |= (1 << n); chip->irq_update = n; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean2246.81%114.29%
thomas gleixnerthomas gleixner919.15%114.29%
lennert buytenheklennert buytenhek714.89%114.29%
axel linaxel lin36.38%114.29%
wei chenwei chen36.38%114.29%
linus walleijlinus walleij36.38%228.57%
Total47100.00%7100.00%


static void sx150x_irq_unmask(struct irq_data *d) { struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); unsigned n = d->hwirq; chip->irq_masked &= ~(1 << n); chip->irq_update = n; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean2245.83%114.29%
thomas gleixnerthomas gleixner1020.83%114.29%
lennert buytenheklennert buytenhek714.58%114.29%
wei chenwei chen36.25%114.29%
axel linaxel lin36.25%114.29%
linus walleijlinus walleij36.25%228.57%
Total48100.00%7100.00%


static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type) { struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); unsigned n, val = 0; if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) return -EINVAL; n = d->hwirq; if (flow_type & IRQ_TYPE_EDGE_RISING) val |= 0x1; if (flow_type & IRQ_TYPE_EDGE_FALLING) val |= 0x2; chip->irq_sense &= ~(3UL << (n * 2)); chip->irq_sense |= val << (n * 2); chip->irq_update = n; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean9585.59%114.29%
lennert buytenheklennert buytenhek76.31%114.29%
axel linaxel lin32.70%114.29%
linus walleijlinus walleij32.70%228.57%
thomas gleixnerthomas gleixner21.80%114.29%
wei chenwei chen10.90%114.29%
Total111100.00%7100.00%


static irqreturn_t sx150x_irq_thread_fn(int irq, void *dev_id) { struct sx150x_chip *chip = (struct sx150x_chip *)dev_id; unsigned nhandled = 0; unsigned sub_irq; unsigned n; s32 err; u8 val; int i; for (i = (chip->dev_cfg->ngpios / 8) - 1; i >= 0; --i) { err = sx150x_i2c_read(chip->client, chip->dev_cfg->reg_irq_src - i, &val); if (err < 0) continue; sx150x_i2c_write(chip->client, chip->dev_cfg->reg_irq_src - i, val); for (n = 0; n < 8; ++n) { if (val & (1 << n)) { sub_irq = irq_find_mapping( chip->gpio_chip.irqdomain, (i * 8) + n); handle_nested_irq(sub_irq); ++nhandled; } } } return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean17296.09%150.00%
wei chenwei chen73.91%150.00%
Total179100.00%2100.00%


static void sx150x_irq_bus_lock(struct irq_data *d) { struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); mutex_lock(&chip->lock); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean2165.62%120.00%
lennert buytenheklennert buytenhek515.62%120.00%
axel linaxel lin39.38%120.00%
linus walleijlinus walleij39.38%240.00%
Total32100.00%5100.00%


static void sx150x_irq_bus_sync_unlock(struct irq_data *d) { struct sx150x_chip *chip = gpiochip_get_data(irq_data_get_irq_chip_data(d)); unsigned n; if (chip->irq_update == NO_UPDATE_PENDING) goto out; n = chip->irq_update; chip->irq_update = NO_UPDATE_PENDING; /* Avoid updates if nothing changed */ if (chip->dev_sense == chip->irq_sense && chip->dev_masked == chip->irq_masked) goto out; chip->dev_sense = chip->irq_sense; chip->dev_masked = chip->irq_masked; if (chip->irq_masked & (1 << n)) { sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1); sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0); } else { sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0); sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, chip->irq_sense >> (n * 2)); } out: mutex_unlock(&chip->lock); }

Contributors

PersonTokensPropCommitsCommitProp
thomas gleixnerthomas gleixner10856.54%114.29%
gregory beangregory bean7137.17%114.29%
lennert buytenheklennert buytenhek52.62%114.29%
axel linaxel lin42.09%228.57%
linus walleijlinus walleij31.57%228.57%
Total191100.00%7100.00%


static void sx150x_init_chip(struct sx150x_chip *chip, struct i2c_client *client, kernel_ulong_t driver_data, struct sx150x_platform_data *pdata) { mutex_init(&chip->lock); chip->client = client; chip->dev_cfg = &sx150x_devices[driver_data]; chip->gpio_chip.parent = &client->dev; chip->gpio_chip.label = client->name; chip->gpio_chip.direction_input = sx150x_gpio_direction_input; chip->gpio_chip.direction_output = sx150x_gpio_direction_output; chip->gpio_chip.get = sx150x_gpio_get; chip->gpio_chip.set = sx150x_gpio_set; chip->gpio_chip.set_single_ended = sx150x_gpio_set_single_ended; chip->gpio_chip.base = pdata->gpio_base; chip->gpio_chip.can_sleep = true; chip->gpio_chip.ngpio = chip->dev_cfg->ngpios; #ifdef CONFIG_OF_GPIO chip->gpio_chip.of_node = client->dev.of_node; chip->gpio_chip.of_gpio_n_cells = 2; #endif if (pdata->oscio_is_gpo) ++chip->gpio_chip.ngpio; chip->irq_chip.name = client->name; chip->irq_chip.irq_mask = sx150x_irq_mask; chip->irq_chip.irq_unmask = sx150x_irq_unmask; chip->irq_chip.irq_set_type = sx150x_irq_set_type; chip->irq_chip.irq_bus_lock = sx150x_irq_bus_lock; chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock; chip->irq_summary = -1; chip->irq_base = -1; chip->irq_masked = ~0; chip->irq_sense = 0; chip->dev_masked = ~0; chip->dev_sense = 0; chip->irq_update = NO_UPDATE_PENDING; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean20273.99%111.11%
wei chenwei chen3010.99%222.22%
thomas gleixnerthomas gleixner217.69%111.11%
linus walleijlinus walleij155.49%444.44%
lennert buytenheklennert buytenhek51.83%111.11%
Total273100.00%9100.00%


static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg) { int err = 0; unsigned n; for (n = 0; err >= 0 && n < (chip->dev_cfg->ngpios / 8); ++n) err = sx150x_i2c_write(chip->client, base - n, cfg >> (n * 8)); return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean74100.00%1100.00%
Total74100.00%1100.00%


static int sx150x_reset(struct sx150x_chip *chip) { int err; err = i2c_smbus_write_byte_data(chip->client, chip->dev_cfg->pri.x789.reg_reset, 0x12); if (err < 0) return err; err = i2c_smbus_write_byte_data(chip->client, chip->dev_cfg->pri.x789.reg_reset, 0x34); return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean6088.24%266.67%
wei chenwei chen811.76%133.33%
Total68100.00%3100.00%


static int sx150x_init_hw(struct sx150x_chip *chip, struct sx150x_platform_data *pdata) { int err = 0; if (pdata->reset_during_probe) { err = sx150x_reset(chip); if (err < 0) return err; } if (chip->dev_cfg->model == SX150X_789) err = sx150x_i2c_write(chip->client, chip->dev_cfg->pri.x789.reg_misc, 0x01); else if (chip->dev_cfg->model == SX150X_456) err = sx150x_i2c_write(chip->client, chip->dev_cfg->pri.x456.reg_advance, 0x04); else err = sx150x_i2c_write(chip->client, chip->dev_cfg->pri.x123.reg_advance, 0x00); if (err < 0) return err; err = sx150x_init_io(chip, chip->dev_cfg->reg_pullup, pdata->io_pullup_ena); if (err < 0) return err; err = sx150x_init_io(chip, chip->dev_cfg->reg_pulldn, pdata->io_pulldn_ena); if (err < 0) return err; if (chip->dev_cfg->model == SX150X_789) { err = sx150x_init_io(chip, chip->dev_cfg->pri.x789.reg_polarity, pdata->io_polarity); if (err < 0) return err; } else if (chip->dev_cfg->model == SX150X_456) { /* Set all pins to work in normal mode */ err = sx150x_init_io(chip, chip->dev_cfg->pri.x456.reg_pld_mode, 0); if (err < 0) return err; } else { /* Set all pins to work in normal mode */ err = sx150x_init_io(chip, chip->dev_cfg->pri.x123.reg_pld_mode, 0); if (err < 0) return err; } if (pdata->oscio_is_gpo) sx150x_set_oscio(chip, 0); return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean16551.08%250.00%
wei chenwei chen8225.39%125.00%
peter rosinpeter rosin7623.53%125.00%
Total323100.00%4100.00%


static int sx150x_install_irq_chip(struct sx150x_chip *chip, int irq_summary, int irq_base) { int err; chip->irq_summary = irq_summary; chip->irq_base = irq_base; /* Add gpio chip to irq subsystem */ err = gpiochip_irqchip_add(&chip->gpio_chip, &chip->irq_chip, chip->irq_base, handle_edge_irq, IRQ_TYPE_EDGE_BOTH); if (err) { dev_err(&chip->client->dev, "could not connect irqchip to gpiochip\n"); return err; } err = devm_request_threaded_irq(&chip->client->dev, irq_summary, NULL, sx150x_irq_thread_fn, IRQF_ONESHOT | IRQF_SHARED | IRQF_TRIGGER_FALLING, chip->irq_chip.name, chip); if (err < 0) { chip->irq_summary = -1; chip->irq_base = -1; } return err; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean9570.90%125.00%
wei chenwei chen2921.64%125.00%
nikolay balandinnikolay balandin85.97%125.00%
axel linaxel lin21.49%125.00%
Total134100.00%4100.00%


static int sx150x_probe(struct i2c_client *client, const struct i2c_device_id *id) { static const u32 i2c_funcs = I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WRITE_WORD_DATA; struct sx150x_platform_data *pdata; struct sx150x_chip *chip; int rc; pdata = dev_get_platdata(&client->dev); if (!pdata) return -EINVAL; if (!i2c_check_functionality(client->adapter, i2c_funcs)) return -ENOSYS; chip = devm_kzalloc(&client->dev, sizeof(struct sx150x_chip), GFP_KERNEL); if (!chip) return -ENOMEM; sx150x_init_chip(chip, client, id->driver_data, pdata); rc = sx150x_init_hw(chip, pdata); if (rc < 0) return rc; rc = devm_gpiochip_add_data(&client->dev, &chip->gpio_chip, chip); if (rc) return rc; if (pdata->irq_summary >= 0) { rc = sx150x_install_irq_chip(chip, pdata->irq_summary, pdata->irq_base); if (rc < 0) return rc; } i2c_set_clientdata(client, chip); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean17487.00%120.00%
nikolay balandinnikolay balandin126.00%120.00%
laxman dewanganlaxman dewangan84.00%120.00%
jingoo hanjingoo han42.00%120.00%
linus walleijlinus walleij21.00%120.00%
Total200100.00%5100.00%

static struct i2c_driver sx150x_driver = { .driver = { .name = "sx150x", .of_match_table = of_match_ptr(sx150x_of_match), }, .probe = sx150x_probe, .id_table = sx150x_id, };
static int __init sx150x_init(void) { return i2c_add_driver(&sx150x_driver); }

Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean16100.00%1100.00%
Total16100.00%1100.00%

subsys_initcall(sx150x_init);

Overall Contributors

PersonTokensPropCommitsCommitProp
gregory beangregory bean231167.67%29.09%
wei chenwei chen43112.62%313.64%
peter rosinpeter rosin2196.41%14.55%
linus walleijlinus walleij2025.92%836.36%
thomas gleixnerthomas gleixner1654.83%14.55%
lennert buytenheklennert buytenhek361.05%14.55%
nikolay balandinnikolay balandin200.59%14.55%
axel linaxel lin180.53%29.09%
laxman dewanganlaxman dewangan80.23%14.55%
jingoo hanjingoo han40.12%14.55%
paul gortmakerpaul gortmaker10.03%14.55%
Total3415100.00%22100.00%
Directory: drivers/gpio
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}