151 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2007-2010 ST-Ericsson4 * Register access functions for the ABX500 Mixed Signal IC family.5 * Author: Mattias Wallin <mattias.wallin@stericsson.com>6 */7 8#include <linux/list.h>9#include <linux/slab.h>10#include <linux/err.h>11#include <linux/init.h>12#include <linux/export.h>13#include <linux/mfd/abx500.h>14 15static LIST_HEAD(abx500_list);16 17struct abx500_device_entry {18 struct list_head list;19 struct abx500_ops ops;20 struct device *dev;21};22 23static void lookup_ops(struct device *dev, struct abx500_ops **ops)24{25 struct abx500_device_entry *dev_entry;26 27 *ops = NULL;28 list_for_each_entry(dev_entry, &abx500_list, list) {29 if (dev_entry->dev == dev) {30 *ops = &dev_entry->ops;31 return;32 }33 }34}35 36int abx500_register_ops(struct device *dev, struct abx500_ops *ops)37{38 struct abx500_device_entry *dev_entry;39 40 dev_entry = devm_kzalloc(dev, sizeof(*dev_entry), GFP_KERNEL);41 if (!dev_entry)42 return -ENOMEM;43 44 dev_entry->dev = dev;45 memcpy(&dev_entry->ops, ops, sizeof(*ops));46 47 list_add_tail(&dev_entry->list, &abx500_list);48 return 0;49}50EXPORT_SYMBOL(abx500_register_ops);51 52void abx500_remove_ops(struct device *dev)53{54 struct abx500_device_entry *dev_entry, *tmp;55 56 list_for_each_entry_safe(dev_entry, tmp, &abx500_list, list)57 if (dev_entry->dev == dev)58 list_del(&dev_entry->list);59}60EXPORT_SYMBOL(abx500_remove_ops);61 62int abx500_set_register_interruptible(struct device *dev, u8 bank, u8 reg,63 u8 value)64{65 struct abx500_ops *ops;66 67 lookup_ops(dev->parent, &ops);68 if (ops && ops->set_register)69 return ops->set_register(dev, bank, reg, value);70 else71 return -ENOTSUPP;72}73EXPORT_SYMBOL(abx500_set_register_interruptible);74 75int abx500_get_register_interruptible(struct device *dev, u8 bank, u8 reg,76 u8 *value)77{78 struct abx500_ops *ops;79 80 lookup_ops(dev->parent, &ops);81 if (ops && ops->get_register)82 return ops->get_register(dev, bank, reg, value);83 else84 return -ENOTSUPP;85}86EXPORT_SYMBOL(abx500_get_register_interruptible);87 88int abx500_get_register_page_interruptible(struct device *dev, u8 bank,89 u8 first_reg, u8 *regvals, u8 numregs)90{91 struct abx500_ops *ops;92 93 lookup_ops(dev->parent, &ops);94 if (ops && ops->get_register_page)95 return ops->get_register_page(dev, bank,96 first_reg, regvals, numregs);97 else98 return -ENOTSUPP;99}100EXPORT_SYMBOL(abx500_get_register_page_interruptible);101 102int abx500_mask_and_set_register_interruptible(struct device *dev, u8 bank,103 u8 reg, u8 bitmask, u8 bitvalues)104{105 struct abx500_ops *ops;106 107 lookup_ops(dev->parent, &ops);108 if (ops && ops->mask_and_set_register)109 return ops->mask_and_set_register(dev, bank,110 reg, bitmask, bitvalues);111 else112 return -ENOTSUPP;113}114EXPORT_SYMBOL(abx500_mask_and_set_register_interruptible);115 116int abx500_get_chip_id(struct device *dev)117{118 struct abx500_ops *ops;119 120 lookup_ops(dev->parent, &ops);121 if (ops && ops->get_chip_id)122 return ops->get_chip_id(dev);123 else124 return -ENOTSUPP;125}126EXPORT_SYMBOL(abx500_get_chip_id);127 128int abx500_event_registers_startup_state_get(struct device *dev, u8 *event)129{130 struct abx500_ops *ops;131 132 lookup_ops(dev->parent, &ops);133 if (ops && ops->event_registers_startup_state_get)134 return ops->event_registers_startup_state_get(dev, event);135 else136 return -ENOTSUPP;137}138EXPORT_SYMBOL(abx500_event_registers_startup_state_get);139 140int abx500_startup_irq_enabled(struct device *dev, unsigned int irq)141{142 struct abx500_ops *ops;143 144 lookup_ops(dev->parent, &ops);145 if (ops && ops->startup_irq_enabled)146 return ops->startup_irq_enabled(dev, irq);147 else148 return -ENOTSUPP;149}150EXPORT_SYMBOL(abx500_startup_irq_enabled);151