cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

i2c.c (7679B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *   Generic i2c interface for ALSA
      4 *
      5 *   (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
      6 *   Modified for the ALSA driver by Jaroslav Kysela <perex@perex.cz>
      7 */
      8
      9#include <linux/init.h>
     10#include <linux/slab.h>
     11#include <linux/module.h>
     12#include <linux/string.h>
     13#include <linux/errno.h>
     14#include <sound/core.h>
     15#include <sound/i2c.h>
     16
     17MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
     18MODULE_DESCRIPTION("Generic i2c interface for ALSA");
     19MODULE_LICENSE("GPL");
     20
     21static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
     22				 unsigned char *bytes, int count);
     23static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
     24				 unsigned char *bytes, int count);
     25static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus,
     26				 unsigned short addr);
     27
     28static const struct snd_i2c_ops snd_i2c_bit_ops = {
     29	.sendbytes = snd_i2c_bit_sendbytes,
     30	.readbytes = snd_i2c_bit_readbytes,
     31	.probeaddr = snd_i2c_bit_probeaddr,
     32};
     33
     34static int snd_i2c_bus_free(struct snd_i2c_bus *bus)
     35{
     36	struct snd_i2c_bus *slave;
     37	struct snd_i2c_device *device;
     38
     39	if (snd_BUG_ON(!bus))
     40		return -EINVAL;
     41	while (!list_empty(&bus->devices)) {
     42		device = snd_i2c_device(bus->devices.next);
     43		snd_i2c_device_free(device);
     44	}
     45	if (bus->master)
     46		list_del(&bus->buses);
     47	else {
     48		while (!list_empty(&bus->buses)) {
     49			slave = snd_i2c_slave_bus(bus->buses.next);
     50			snd_device_free(bus->card, slave);
     51		}
     52	}
     53	if (bus->private_free)
     54		bus->private_free(bus);
     55	kfree(bus);
     56	return 0;
     57}
     58
     59static int snd_i2c_bus_dev_free(struct snd_device *device)
     60{
     61	struct snd_i2c_bus *bus = device->device_data;
     62	return snd_i2c_bus_free(bus);
     63}
     64
     65int snd_i2c_bus_create(struct snd_card *card, const char *name,
     66		       struct snd_i2c_bus *master, struct snd_i2c_bus **ri2c)
     67{
     68	struct snd_i2c_bus *bus;
     69	int err;
     70	static const struct snd_device_ops ops = {
     71		.dev_free =	snd_i2c_bus_dev_free,
     72	};
     73
     74	*ri2c = NULL;
     75	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
     76	if (bus == NULL)
     77		return -ENOMEM;
     78	mutex_init(&bus->lock_mutex);
     79	INIT_LIST_HEAD(&bus->devices);
     80	INIT_LIST_HEAD(&bus->buses);
     81	bus->card = card;
     82	bus->ops = &snd_i2c_bit_ops;
     83	if (master) {
     84		list_add_tail(&bus->buses, &master->buses);
     85		bus->master = master;
     86	}
     87	strscpy(bus->name, name, sizeof(bus->name));
     88	err = snd_device_new(card, SNDRV_DEV_BUS, bus, &ops);
     89	if (err < 0) {
     90		snd_i2c_bus_free(bus);
     91		return err;
     92	}
     93	*ri2c = bus;
     94	return 0;
     95}
     96
     97EXPORT_SYMBOL(snd_i2c_bus_create);
     98
     99int snd_i2c_device_create(struct snd_i2c_bus *bus, const char *name,
    100			  unsigned char addr, struct snd_i2c_device **rdevice)
    101{
    102	struct snd_i2c_device *device;
    103
    104	*rdevice = NULL;
    105	if (snd_BUG_ON(!bus))
    106		return -EINVAL;
    107	device = kzalloc(sizeof(*device), GFP_KERNEL);
    108	if (device == NULL)
    109		return -ENOMEM;
    110	device->addr = addr;
    111	strscpy(device->name, name, sizeof(device->name));
    112	list_add_tail(&device->list, &bus->devices);
    113	device->bus = bus;
    114	*rdevice = device;
    115	return 0;
    116}
    117
    118EXPORT_SYMBOL(snd_i2c_device_create);
    119
    120int snd_i2c_device_free(struct snd_i2c_device *device)
    121{
    122	if (device->bus)
    123		list_del(&device->list);
    124	if (device->private_free)
    125		device->private_free(device);
    126	kfree(device);
    127	return 0;
    128}
    129
    130EXPORT_SYMBOL(snd_i2c_device_free);
    131
    132int snd_i2c_sendbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
    133{
    134	return device->bus->ops->sendbytes(device, bytes, count);
    135}
    136
    137EXPORT_SYMBOL(snd_i2c_sendbytes);
    138
    139int snd_i2c_readbytes(struct snd_i2c_device *device, unsigned char *bytes, int count)
    140{
    141	return device->bus->ops->readbytes(device, bytes, count);
    142}
    143
    144EXPORT_SYMBOL(snd_i2c_readbytes);
    145
    146int snd_i2c_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
    147{
    148	return bus->ops->probeaddr(bus, addr);
    149}
    150
    151EXPORT_SYMBOL(snd_i2c_probeaddr);
    152
    153/*
    154 *  bit-operations
    155 */
    156
    157static inline void snd_i2c_bit_hw_start(struct snd_i2c_bus *bus)
    158{
    159	if (bus->hw_ops.bit->start)
    160		bus->hw_ops.bit->start(bus);
    161}
    162
    163static inline void snd_i2c_bit_hw_stop(struct snd_i2c_bus *bus)
    164{
    165	if (bus->hw_ops.bit->stop)
    166		bus->hw_ops.bit->stop(bus);
    167}
    168
    169static void snd_i2c_bit_direction(struct snd_i2c_bus *bus, int clock, int data)
    170{
    171	if (bus->hw_ops.bit->direction)
    172		bus->hw_ops.bit->direction(bus, clock, data);
    173}
    174
    175static void snd_i2c_bit_set(struct snd_i2c_bus *bus, int clock, int data)
    176{
    177	bus->hw_ops.bit->setlines(bus, clock, data);
    178}
    179
    180#if 0
    181static int snd_i2c_bit_clock(struct snd_i2c_bus *bus)
    182{
    183	if (bus->hw_ops.bit->getclock)
    184		return bus->hw_ops.bit->getclock(bus);
    185	return -ENXIO;
    186}
    187#endif
    188
    189static int snd_i2c_bit_data(struct snd_i2c_bus *bus, int ack)
    190{
    191	return bus->hw_ops.bit->getdata(bus, ack);
    192}
    193
    194static void snd_i2c_bit_start(struct snd_i2c_bus *bus)
    195{
    196	snd_i2c_bit_hw_start(bus);
    197	snd_i2c_bit_direction(bus, 1, 1);	/* SCL - wr, SDA - wr */
    198	snd_i2c_bit_set(bus, 1, 1);
    199	snd_i2c_bit_set(bus, 1, 0);
    200	snd_i2c_bit_set(bus, 0, 0);
    201}
    202
    203static void snd_i2c_bit_stop(struct snd_i2c_bus *bus)
    204{
    205	snd_i2c_bit_set(bus, 0, 0);
    206	snd_i2c_bit_set(bus, 1, 0);
    207	snd_i2c_bit_set(bus, 1, 1);
    208	snd_i2c_bit_hw_stop(bus);
    209}
    210
    211static void snd_i2c_bit_send(struct snd_i2c_bus *bus, int data)
    212{
    213	snd_i2c_bit_set(bus, 0, data);
    214	snd_i2c_bit_set(bus, 1, data);
    215	snd_i2c_bit_set(bus, 0, data);
    216}
    217
    218static int snd_i2c_bit_ack(struct snd_i2c_bus *bus)
    219{
    220	int ack;
    221
    222	snd_i2c_bit_set(bus, 0, 1);
    223	snd_i2c_bit_set(bus, 1, 1);
    224	snd_i2c_bit_direction(bus, 1, 0);	/* SCL - wr, SDA - rd */
    225	ack = snd_i2c_bit_data(bus, 1);
    226	snd_i2c_bit_direction(bus, 1, 1);	/* SCL - wr, SDA - wr */
    227	snd_i2c_bit_set(bus, 0, 1);
    228	return ack ? -EIO : 0;
    229}
    230
    231static int snd_i2c_bit_sendbyte(struct snd_i2c_bus *bus, unsigned char data)
    232{
    233	int i, err;
    234
    235	for (i = 7; i >= 0; i--)
    236		snd_i2c_bit_send(bus, !!(data & (1 << i)));
    237	err = snd_i2c_bit_ack(bus);
    238	if (err < 0)
    239		return err;
    240	return 0;
    241}
    242
    243static int snd_i2c_bit_readbyte(struct snd_i2c_bus *bus, int last)
    244{
    245	int i;
    246	unsigned char data = 0;
    247
    248	snd_i2c_bit_set(bus, 0, 1);
    249	snd_i2c_bit_direction(bus, 1, 0);	/* SCL - wr, SDA - rd */
    250	for (i = 7; i >= 0; i--) {
    251		snd_i2c_bit_set(bus, 1, 1);
    252		if (snd_i2c_bit_data(bus, 0))
    253			data |= (1 << i);
    254		snd_i2c_bit_set(bus, 0, 1);
    255	}
    256	snd_i2c_bit_direction(bus, 1, 1);	/* SCL - wr, SDA - wr */
    257	snd_i2c_bit_send(bus, !!last);
    258	return data;
    259}
    260
    261static int snd_i2c_bit_sendbytes(struct snd_i2c_device *device,
    262				 unsigned char *bytes, int count)
    263{
    264	struct snd_i2c_bus *bus = device->bus;
    265	int err, res = 0;
    266
    267	if (device->flags & SND_I2C_DEVICE_ADDRTEN)
    268		return -EIO;		/* not yet implemented */
    269	snd_i2c_bit_start(bus);
    270	err = snd_i2c_bit_sendbyte(bus, device->addr << 1);
    271	if (err < 0) {
    272		snd_i2c_bit_hw_stop(bus);
    273		return err;
    274	}
    275	while (count-- > 0) {
    276		err = snd_i2c_bit_sendbyte(bus, *bytes++);
    277		if (err < 0) {
    278			snd_i2c_bit_hw_stop(bus);
    279			return err;
    280		}
    281		res++;
    282	}
    283	snd_i2c_bit_stop(bus);
    284	return res;
    285}
    286
    287static int snd_i2c_bit_readbytes(struct snd_i2c_device *device,
    288				 unsigned char *bytes, int count)
    289{
    290	struct snd_i2c_bus *bus = device->bus;
    291	int err, res = 0;
    292
    293	if (device->flags & SND_I2C_DEVICE_ADDRTEN)
    294		return -EIO;		/* not yet implemented */
    295	snd_i2c_bit_start(bus);
    296	err = snd_i2c_bit_sendbyte(bus, (device->addr << 1) | 1);
    297	if (err < 0) {
    298		snd_i2c_bit_hw_stop(bus);
    299		return err;
    300	}
    301	while (count-- > 0) {
    302		err = snd_i2c_bit_readbyte(bus, count == 0);
    303		if (err < 0) {
    304			snd_i2c_bit_hw_stop(bus);
    305			return err;
    306		}
    307		*bytes++ = (unsigned char)err;
    308		res++;
    309	}
    310	snd_i2c_bit_stop(bus);
    311	return res;
    312}
    313
    314static int snd_i2c_bit_probeaddr(struct snd_i2c_bus *bus, unsigned short addr)
    315{
    316	int err;
    317
    318	if (addr & 0x8000)	/* 10-bit address */
    319		return -EIO;	/* not yet implemented */
    320	if (addr & 0x7f80)	/* invalid address */
    321		return -EINVAL;
    322	snd_i2c_bit_start(bus);
    323	err = snd_i2c_bit_sendbyte(bus, addr << 1);
    324	snd_i2c_bit_stop(bus);
    325	return err;
    326}