cregit-Linux how code gets into the kernel

Release 4.7 drivers/mfd/da903x.c

Directory: drivers/mfd
/*
 * Base driver for Dialog Semiconductor DA9030/DA9034
 *
 * Copyright (C) 2008 Compulab, Ltd.
 *      Mike Rapoport <mike@compulab.co.il>
 *
 * Copyright (C) 2006-2008 Marvell International Ltd.
 *      Eric Miao <eric.miao@marvell.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/i2c.h>
#include <linux/mfd/da903x.h>
#include <linux/slab.h>


#define DA9030_CHIP_ID		0x00

#define DA9030_EVENT_A		0x01

#define DA9030_EVENT_B		0x02

#define DA9030_EVENT_C		0x03

#define DA9030_STATUS		0x04

#define DA9030_IRQ_MASK_A	0x05

#define DA9030_IRQ_MASK_B	0x06

#define DA9030_IRQ_MASK_C	0x07

#define DA9030_SYS_CTRL_A	0x08

#define DA9030_SYS_CTRL_B	0x09

#define DA9030_FAULT_LOG	0x0a


#define DA9034_CHIP_ID		0x00

#define DA9034_EVENT_A		0x01

#define DA9034_EVENT_B		0x02

#define DA9034_EVENT_C		0x03

#define DA9034_EVENT_D		0x04

#define DA9034_STATUS_A		0x05

#define DA9034_STATUS_B		0x06

#define DA9034_IRQ_MASK_A	0x07

#define DA9034_IRQ_MASK_B	0x08

#define DA9034_IRQ_MASK_C	0x09

#define DA9034_IRQ_MASK_D	0x0a

#define DA9034_SYS_CTRL_A	0x0b

#define DA9034_SYS_CTRL_B	0x0c

#define DA9034_FAULT_LOG	0x0d

struct da903x_chip;


struct da903x_chip_ops {
	
int	(*init_chip)(struct da903x_chip *);
	
int	(*unmask_events)(struct da903x_chip *, unsigned int events);
	
int	(*mask_events)(struct da903x_chip *, unsigned int events);
	
int	(*read_events)(struct da903x_chip *, unsigned int *events);
	
int	(*read_status)(struct da903x_chip *, unsigned int *status);
};


struct da903x_chip {
	
struct i2c_client	*client;
	
struct device		*dev;
	
const struct da903x_chip_ops *ops;

	
int			type;
	
uint32_t		events_mask;

	
struct mutex		lock;
	
struct work_struct	irq_work;

	
struct blocking_notifier_head notifier_list;
};


static inline int __da903x_read(struct i2c_client *client, int reg, uint8_t *val) { int ret; ret = i2c_smbus_read_byte_data(client, reg); if (ret < 0) { dev_err(&client->dev, "failed reading at 0x%02x\n", reg); return ret; } *val = (uint8_t)ret; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao65100.00%1100.00%
Total65100.00%1100.00%


static inline int __da903x_reads(struct i2c_client *client, int reg, int len, uint8_t *val) { int ret; ret = i2c_smbus_read_i2c_block_data(client, reg, len, val); if (ret < 0) { dev_err(&client->dev, "failed reading from 0x%02x\n", reg); return ret; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao64100.00%1100.00%
Total64100.00%1100.00%


static inline int __da903x_write(struct i2c_client *client, int reg, uint8_t val) { int ret; ret = i2c_smbus_write_byte_data(client, reg, val); if (ret < 0) { dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n", val, reg); return ret; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao60100.00%1100.00%
Total60100.00%1100.00%


static inline int __da903x_writes(struct i2c_client *client, int reg, int len, uint8_t *val) { int ret; ret = i2c_smbus_write_i2c_block_data(client, reg, len, val); if (ret < 0) { dev_err(&client->dev, "failed writings to 0x%02x\n", reg); return ret; } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao64100.00%1100.00%
Total64100.00%1100.00%


int da903x_register_notifier(struct device *dev, struct notifier_block *nb, unsigned int events) { struct da903x_chip *chip = dev_get_drvdata(dev); chip->ops->unmask_events(chip, events); return blocking_notifier_chain_register(&chip->notifier_list, nb); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao51100.00%1100.00%
Total51100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_register_notifier);
int da903x_unregister_notifier(struct device *dev, struct notifier_block *nb, unsigned int events) { struct da903x_chip *chip = dev_get_drvdata(dev); chip->ops->mask_events(chip, events); return blocking_notifier_chain_unregister(&chip->notifier_list, nb); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao51100.00%1100.00%
Total51100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_unregister_notifier);
int da903x_write(struct device *dev, int reg, uint8_t val) { return __da903x_write(to_i2c_client(dev), reg, val); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao29100.00%1100.00%
Total29100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_write);
int da903x_writes(struct device *dev, int reg, int len, uint8_t *val) { return __da903x_writes(to_i2c_client(dev), reg, len, val); }

Contributors

PersonTokensPropCommitsCommitProp
mike rapoportmike rapoport35100.00%1100.00%
Total35100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_writes);
int da903x_read(struct device *dev, int reg, uint8_t *val) { return __da903x_read(to_i2c_client(dev), reg, val); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao30100.00%1100.00%
Total30100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_read);
int da903x_reads(struct device *dev, int reg, int len, uint8_t *val) { return __da903x_reads(to_i2c_client(dev), reg, len, val); }

Contributors

PersonTokensPropCommitsCommitProp
mike rapoportmike rapoport35100.00%1100.00%
Total35100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_reads);
int da903x_set_bits(struct device *dev, int reg, uint8_t bit_mask) { struct da903x_chip *chip = dev_get_drvdata(dev); uint8_t reg_val; int ret = 0; mutex_lock(&chip->lock); ret = __da903x_read(chip->client, reg, &reg_val); if (ret) goto out; if ((reg_val & bit_mask) != bit_mask) { reg_val |= bit_mask; ret = __da903x_write(chip->client, reg, reg_val); } out: mutex_unlock(&chip->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao10398.10%150.00%
axel linaxel lin21.90%150.00%
Total105100.00%2100.00%

EXPORT_SYMBOL_GPL(da903x_set_bits);
int da903x_clr_bits(struct device *dev, int reg, uint8_t bit_mask) { struct da903x_chip *chip = dev_get_drvdata(dev); uint8_t reg_val; int ret = 0; mutex_lock(&chip->lock); ret = __da903x_read(chip->client, reg, &reg_val); if (ret) goto out; if (reg_val & bit_mask) { reg_val &= ~bit_mask; ret = __da903x_write(chip->client, reg, reg_val); } out: mutex_unlock(&chip->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao102100.00%1100.00%
Total102100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_clr_bits);
int da903x_update(struct device *dev, int reg, uint8_t val, uint8_t mask) { struct da903x_chip *chip = dev_get_drvdata(dev); uint8_t reg_val; int ret = 0; mutex_lock(&chip->lock); ret = __da903x_read(chip->client, reg, &reg_val); if (ret) goto out; if ((reg_val & mask) != val) { reg_val = (reg_val & ~mask) | val; ret = __da903x_write(chip->client, reg, reg_val); } out: mutex_unlock(&chip->lock); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao115100.00%1100.00%
Total115100.00%1100.00%

EXPORT_SYMBOL_GPL(da903x_update);
int da903x_query_status(struct device *dev, unsigned int sbits) { struct da903x_chip *chip = dev_get_drvdata(dev); unsigned int status = 0; chip->ops->read_status(chip, &status); return ((status & sbits) == sbits); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao53100.00%1100.00%
Total53100.00%1100.00%

EXPORT_SYMBOL(da903x_query_status);
static int da9030_init_chip(struct da903x_chip *chip) { uint8_t chip_id; int err; err = __da903x_read(chip->client, DA9030_CHIP_ID, &chip_id); if (err) return err; err = __da903x_write(chip->client, DA9030_SYS_CTRL_A, 0xE8); if (err) return err; dev_info(chip->dev, "DA9030 (CHIP ID: 0x%02x) detected\n", chip_id); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao72100.00%1100.00%
Total72100.00%1100.00%


static int da9030_unmask_events(struct da903x_chip *chip, unsigned int events) { uint8_t v[3]; chip->events_mask &= ~events; v[0] = (chip->events_mask & 0xff); v[1] = (chip->events_mask >> 8) & 0xff; v[2] = (chip->events_mask >> 16) & 0xff; return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao85100.00%1100.00%
Total85100.00%1100.00%


static int da9030_mask_events(struct da903x_chip *chip, unsigned int events) { uint8_t v[3]; chip->events_mask |= events; v[0] = (chip->events_mask & 0xff); v[1] = (chip->events_mask >> 8) & 0xff; v[2] = (chip->events_mask >> 16) & 0xff; return __da903x_writes(chip->client, DA9030_IRQ_MASK_A, 3, v); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao8398.81%150.00%
mike rapoportmike rapoport11.19%150.00%
Total84100.00%2100.00%


static int da9030_read_events(struct da903x_chip *chip, unsigned int *events) { uint8_t v[3] = {0, 0, 0}; int ret; ret = __da903x_reads(chip->client, DA9030_EVENT_A, 3, v); if (ret < 0) return ret; *events = (v[2] << 16) | (v[1] << 8) | v[0]; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao86100.00%1100.00%
Total86100.00%1100.00%


static int da9030_read_status(struct da903x_chip *chip, unsigned int *status) { return __da903x_read(chip->client, DA9030_STATUS, (uint8_t *)status); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao32100.00%1100.00%
Total32100.00%1100.00%


static int da9034_init_chip(struct da903x_chip *chip) { uint8_t chip_id; int err; err = __da903x_read(chip->client, DA9034_CHIP_ID, &chip_id); if (err) return err; err = __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0xE8); if (err) return err; /* avoid SRAM power off during sleep*/ __da903x_write(chip->client, 0x10, 0x07); __da903x_write(chip->client, 0x11, 0xff); __da903x_write(chip->client, 0x12, 0xff); /* Enable the ONKEY power down functionality */ __da903x_write(chip->client, DA9034_SYS_CTRL_B, 0x20); __da903x_write(chip->client, DA9034_SYS_CTRL_A, 0x60); /* workaround to make LEDs work */ __da903x_write(chip->client, 0x90, 0x01); __da903x_write(chip->client, 0xB0, 0x08); /* make ADTV1 and SDTV1 effective */ __da903x_write(chip->client, 0x20, 0x00); dev_info(chip->dev, "DA9034 (CHIP ID: 0x%02x) detected\n", chip_id); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao164100.00%1100.00%
Total164100.00%1100.00%


static int da9034_unmask_events(struct da903x_chip *chip, unsigned int events) { uint8_t v[4]; chip->events_mask &= ~events; v[0] = (chip->events_mask & 0xff); v[1] = (chip->events_mask >> 8) & 0xff; v[2] = (chip->events_mask >> 16) & 0xff; v[3] = (chip->events_mask >> 24) & 0xff; return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao100100.00%1100.00%
Total100100.00%1100.00%


static int da9034_mask_events(struct da903x_chip *chip, unsigned int events) { uint8_t v[4]; chip->events_mask |= events; v[0] = (chip->events_mask & 0xff); v[1] = (chip->events_mask >> 8) & 0xff; v[2] = (chip->events_mask >> 16) & 0xff; v[3] = (chip->events_mask >> 24) & 0xff; return __da903x_writes(chip->client, DA9034_IRQ_MASK_A, 4, v); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao99100.00%1100.00%
Total99100.00%1100.00%


static int da9034_read_events(struct da903x_chip *chip, unsigned int *events) { uint8_t v[4] = {0, 0, 0, 0}; int ret; ret = __da903x_reads(chip->client, DA9034_EVENT_A, 4, v); if (ret < 0) return ret; *events = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | v[0]; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao97100.00%1100.00%
Total97100.00%1100.00%


static int da9034_read_status(struct da903x_chip *chip, unsigned int *status) { uint8_t v[2] = {0, 0}; int ret = 0; ret = __da903x_reads(chip->client, DA9034_STATUS_A, 2, v); if (ret) return ret; *status = (v[1] << 8) | v[0]; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao75100.00%1100.00%
Total75100.00%1100.00%


static void da903x_irq_work(struct work_struct *work) { struct da903x_chip *chip = container_of(work, struct da903x_chip, irq_work); unsigned int events = 0; while (1) { if (chip->ops->read_events(chip, &events)) break; events &= ~chip->events_mask; if (events == 0) break; blocking_notifier_call_chain( &chip->notifier_list, events, NULL); } enable_irq(chip->client->irq); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao88100.00%1100.00%
Total88100.00%1100.00%


static irqreturn_t da903x_irq_handler(int irq, void *data) { struct da903x_chip *chip = data; disable_irq_nosync(irq); (void)schedule_work(&chip->irq_work); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao3897.44%150.00%
samuel ortizsamuel ortiz12.56%150.00%
Total39100.00%2100.00%

static const struct da903x_chip_ops da903x_ops[] = { [0] = { .init_chip = da9030_init_chip, .unmask_events = da9030_unmask_events, .mask_events = da9030_mask_events, .read_events = da9030_read_events, .read_status = da9030_read_status, }, [1] = { .init_chip = da9034_init_chip, .unmask_events = da9034_unmask_events, .mask_events = da9034_mask_events, .read_events = da9034_read_events, .read_status = da9034_read_status, } }; static const struct i2c_device_id da903x_id_table[] = { { "da9030", 0 }, { "da9034", 1 }, { }, }; MODULE_DEVICE_TABLE(i2c, da903x_id_table);
static int __remove_subdev(struct device *dev, void *unused) { platform_device_unregister(to_platform_device(dev)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao26100.00%1100.00%
Total26100.00%1100.00%


static int da903x_remove_subdevs(struct da903x_chip *chip) { return device_for_each_child(chip->dev, NULL, __remove_subdev); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao23100.00%1100.00%
Total23100.00%1100.00%


static int da903x_add_subdevs(struct da903x_chip *chip, struct da903x_platform_data *pdata) { struct da903x_subdev_info *subdev; struct platform_device *pdev; int i, ret = 0; for (i = 0; i < pdata->num_subdevs; i++) { subdev = &pdata->subdevs[i]; pdev = platform_device_alloc(subdev->name, subdev->id); if (!pdev) { ret = -ENOMEM; goto failed; } pdev->dev.parent = chip->dev; pdev->dev.platform_data = subdev->platform_data; ret = platform_device_add(pdev); if (ret) { platform_device_put(pdev); goto failed; } } return 0; failed: da903x_remove_subdevs(chip); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao12084.51%150.00%
axel linaxel lin2215.49%150.00%
Total142100.00%2100.00%


static int da903x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct da903x_platform_data *pdata = dev_get_platdata(&client->dev); struct da903x_chip *chip; unsigned int tmp; int ret; chip = devm_kzalloc(&client->dev, sizeof(struct da903x_chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->client = client; chip->dev = &client->dev; chip->ops = &da903x_ops[id->driver_data]; mutex_init(&chip->lock); INIT_WORK(&chip->irq_work, da903x_irq_work); BLOCKING_INIT_NOTIFIER_HEAD(&chip->notifier_list); i2c_set_clientdata(client, chip); ret = chip->ops->init_chip(chip); if (ret) return ret; /* mask and clear all IRQs */ chip->events_mask = 0xffffffff; chip->ops->mask_events(chip, chip->events_mask); chip->ops->read_events(chip, &tmp); ret = devm_request_irq(&client->dev, client->irq, da903x_irq_handler, IRQF_TRIGGER_FALLING, "da903x", chip); if (ret) { dev_err(&client->dev, "failed to request irq %d\n", client->irq); return ret; } return da903x_add_subdevs(chip, pdata); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao21090.13%125.00%
jingoo hanjingoo han229.44%250.00%
javier martinez canillasjavier martinez canillas10.43%125.00%
Total233100.00%4100.00%


static int da903x_remove(struct i2c_client *client) { struct da903x_chip *chip = i2c_get_clientdata(client); da903x_remove_subdevs(chip); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao29100.00%1100.00%
Total29100.00%1100.00%

static struct i2c_driver da903x_driver = { .driver = { .name = "da903x", }, .probe = da903x_probe, .remove = da903x_remove, .id_table = da903x_id_table, };
static int __init da903x_init(void) { return i2c_add_driver(&da903x_driver); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao16100.00%1100.00%
Total16100.00%1100.00%

subsys_initcall(da903x_init);
static void __exit da903x_exit(void) { i2c_del_driver(&da903x_driver); }

Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao15100.00%1100.00%
Total15100.00%1100.00%

module_exit(da903x_exit); MODULE_DESCRIPTION("PMIC Driver for Dialog Semiconductor DA9034"); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>"); MODULE_LICENSE("GPL v2");

Overall Contributors

PersonTokensPropCommitsCommitProp
eric miaoeric miao267895.00%17.69%
mike rapoportmike rapoport812.87%215.38%
axel linaxel lin240.85%215.38%
jingoo hanjingoo han220.78%215.38%
lee joneslee jones60.21%17.69%
tejun heotejun heo30.11%17.69%
julia lawalljulia lawall20.07%17.69%
samuel ortizsamuel ortiz20.07%215.38%
javier martinez canillasjavier martinez canillas10.04%17.69%
Total2819100.00%13100.00%
Directory: drivers/mfd
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}