in tps65010.c [523:656]
static int tps65010_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct tps65010 *tps;
int status;
struct tps65010_board *board = dev_get_platdata(&client->dev);
if (the_tps) {
dev_dbg(&client->dev, "only one tps6501x chip allowed\n");
return -ENODEV;
}
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EINVAL;
tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
if (!tps)
return -ENOMEM;
mutex_init(&tps->lock);
INIT_DELAYED_WORK(&tps->work, tps65010_work);
tps->client = client;
tps->model = id->driver_data;
/* the IRQ is active low, but many gpio lines can't support that
* so this driver uses falling-edge triggers instead.
*/
if (client->irq > 0) {
status = request_irq(client->irq, tps65010_irq,
IRQF_TRIGGER_FALLING, DRIVER_NAME, tps);
if (status < 0) {
dev_dbg(&client->dev, "can't get IRQ %d, err %d\n",
client->irq, status);
return status;
}
/* annoying race here, ideally we'd have an option
* to claim the irq now and enable it later.
* FIXME genirq IRQF_NOAUTOEN now solves that ...
*/
disable_irq(client->irq);
set_bit(FLAG_IRQ_ENABLE, &tps->flags);
} else
dev_warn(&client->dev, "IRQ not configured!\n");
switch (tps->model) {
case TPS65010:
case TPS65012:
tps->por = 1;
break;
/* else CHGCONFIG.POR is replaced by AUA, enabling a WAIT mode */
}
tps->chgconf = i2c_smbus_read_byte_data(client, TPS_CHGCONFIG);
show_chgconfig(tps->por, "conf/init", tps->chgconf);
show_chgstatus("chg/init",
i2c_smbus_read_byte_data(client, TPS_CHGSTATUS));
show_regstatus("reg/init",
i2c_smbus_read_byte_data(client, TPS_REGSTATUS));
pr_debug("%s: vdcdc1 0x%02x, vdcdc2 %02x, vregs1 %02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(client, TPS_VDCDC1),
i2c_smbus_read_byte_data(client, TPS_VDCDC2),
i2c_smbus_read_byte_data(client, TPS_VREGS1));
pr_debug("%s: defgpio 0x%02x, mask3 0x%02x\n", DRIVER_NAME,
i2c_smbus_read_byte_data(client, TPS_DEFGPIO),
i2c_smbus_read_byte_data(client, TPS_MASK3));
i2c_set_clientdata(client, tps);
the_tps = tps;
#if defined(CONFIG_USB_GADGET) && !defined(CONFIG_USB_OTG)
/* USB hosts can't draw VBUS. OTG devices could, later
* when OTG infrastructure enables it. USB peripherals
* could be relying on VBUS while booting, though.
*/
tps->vbus = 100;
#endif
/* unmask the "interesting" irqs, then poll once to
* kickstart monitoring, initialize shadowed status
* registers, and maybe disable VBUS draw.
*/
tps->nmask1 = ~0;
(void) i2c_smbus_write_byte_data(client, TPS_MASK1, ~tps->nmask1);
tps->nmask2 = TPS_REG_ONOFF;
if (tps->model == TPS65013)
tps->nmask2 |= TPS_REG_NO_CHG;
(void) i2c_smbus_write_byte_data(client, TPS_MASK2, ~tps->nmask2);
(void) i2c_smbus_write_byte_data(client, TPS_MASK3, 0x0f
| i2c_smbus_read_byte_data(client, TPS_MASK3));
tps65010_work(&tps->work.work);
tps->file = debugfs_create_file(DRIVER_NAME, S_IRUGO, NULL,
tps, DEBUG_FOPS);
/* optionally register GPIOs */
if (board && board->base != 0) {
tps->outmask = board->outmask;
tps->chip.label = client->name;
tps->chip.parent = &client->dev;
tps->chip.owner = THIS_MODULE;
tps->chip.set = tps65010_gpio_set;
tps->chip.direction_output = tps65010_output;
/* NOTE: only partial support for inputs; nyet IRQs */
tps->chip.get = tps65010_gpio_get;
tps->chip.base = board->base;
tps->chip.ngpio = 7;
tps->chip.can_sleep = 1;
status = gpiochip_add_data(&tps->chip, tps);
if (status < 0)
dev_err(&client->dev, "can't add gpiochip, err %d\n",
status);
else if (board->setup) {
status = board->setup(client, board->context);
if (status < 0) {
dev_dbg(&client->dev,
"board %s %s err %d\n",
"setup", client->name, status);
status = 0;
}
}
}
return 0;
}