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

oxygen_io.c (7511B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * C-Media CMI8788 driver - helper functions
      4 *
      5 * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
      6 */
      7
      8#include <linux/delay.h>
      9#include <linux/sched.h>
     10#include <linux/export.h>
     11#include <linux/io.h>
     12#include <sound/core.h>
     13#include <sound/mpu401.h>
     14#include "oxygen.h"
     15
     16u8 oxygen_read8(struct oxygen *chip, unsigned int reg)
     17{
     18	return inb(chip->addr + reg);
     19}
     20EXPORT_SYMBOL(oxygen_read8);
     21
     22u16 oxygen_read16(struct oxygen *chip, unsigned int reg)
     23{
     24	return inw(chip->addr + reg);
     25}
     26EXPORT_SYMBOL(oxygen_read16);
     27
     28u32 oxygen_read32(struct oxygen *chip, unsigned int reg)
     29{
     30	return inl(chip->addr + reg);
     31}
     32EXPORT_SYMBOL(oxygen_read32);
     33
     34void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value)
     35{
     36	outb(value, chip->addr + reg);
     37	chip->saved_registers._8[reg] = value;
     38}
     39EXPORT_SYMBOL(oxygen_write8);
     40
     41void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value)
     42{
     43	outw(value, chip->addr + reg);
     44	chip->saved_registers._16[reg / 2] = cpu_to_le16(value);
     45}
     46EXPORT_SYMBOL(oxygen_write16);
     47
     48void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value)
     49{
     50	outl(value, chip->addr + reg);
     51	chip->saved_registers._32[reg / 4] = cpu_to_le32(value);
     52}
     53EXPORT_SYMBOL(oxygen_write32);
     54
     55void oxygen_write8_masked(struct oxygen *chip, unsigned int reg,
     56			  u8 value, u8 mask)
     57{
     58	u8 tmp = inb(chip->addr + reg);
     59	tmp &= ~mask;
     60	tmp |= value & mask;
     61	outb(tmp, chip->addr + reg);
     62	chip->saved_registers._8[reg] = tmp;
     63}
     64EXPORT_SYMBOL(oxygen_write8_masked);
     65
     66void oxygen_write16_masked(struct oxygen *chip, unsigned int reg,
     67			   u16 value, u16 mask)
     68{
     69	u16 tmp = inw(chip->addr + reg);
     70	tmp &= ~mask;
     71	tmp |= value & mask;
     72	outw(tmp, chip->addr + reg);
     73	chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp);
     74}
     75EXPORT_SYMBOL(oxygen_write16_masked);
     76
     77void oxygen_write32_masked(struct oxygen *chip, unsigned int reg,
     78			   u32 value, u32 mask)
     79{
     80	u32 tmp = inl(chip->addr + reg);
     81	tmp &= ~mask;
     82	tmp |= value & mask;
     83	outl(tmp, chip->addr + reg);
     84	chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp);
     85}
     86EXPORT_SYMBOL(oxygen_write32_masked);
     87
     88static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask)
     89{
     90	u8 status = 0;
     91
     92	/*
     93	 * Reading the status register also clears the bits, so we have to save
     94	 * the read bits in status.
     95	 */
     96	wait_event_timeout(chip->ac97_waitqueue,
     97			   ({ status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS);
     98			      status & mask; }),
     99			   msecs_to_jiffies(1) + 1);
    100	/*
    101	 * Check even after a timeout because this function should not require
    102	 * the AC'97 interrupt to be enabled.
    103	 */
    104	status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS);
    105	return status & mask ? 0 : -EIO;
    106}
    107
    108/*
    109 * About 10% of AC'97 register reads or writes fail to complete, but even those
    110 * where the controller indicates completion aren't guaranteed to have actually
    111 * happened.
    112 *
    113 * It's hard to assign blame to either the controller or the codec because both
    114 * were made by C-Media ...
    115 */
    116
    117void oxygen_write_ac97(struct oxygen *chip, unsigned int codec,
    118		       unsigned int index, u16 data)
    119{
    120	unsigned int count, succeeded;
    121	u32 reg;
    122
    123	reg = data;
    124	reg |= index << OXYGEN_AC97_REG_ADDR_SHIFT;
    125	reg |= OXYGEN_AC97_REG_DIR_WRITE;
    126	reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT;
    127	succeeded = 0;
    128	for (count = 5; count > 0; --count) {
    129		udelay(5);
    130		oxygen_write32(chip, OXYGEN_AC97_REGS, reg);
    131		/* require two "completed" writes, just to be sure */
    132		if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 &&
    133		    ++succeeded >= 2) {
    134			chip->saved_ac97_registers[codec][index / 2] = data;
    135			return;
    136		}
    137	}
    138	dev_err(chip->card->dev, "AC'97 write timeout\n");
    139}
    140EXPORT_SYMBOL(oxygen_write_ac97);
    141
    142u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec,
    143		     unsigned int index)
    144{
    145	unsigned int count;
    146	unsigned int last_read = UINT_MAX;
    147	u32 reg;
    148
    149	reg = index << OXYGEN_AC97_REG_ADDR_SHIFT;
    150	reg |= OXYGEN_AC97_REG_DIR_READ;
    151	reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT;
    152	for (count = 5; count > 0; --count) {
    153		udelay(5);
    154		oxygen_write32(chip, OXYGEN_AC97_REGS, reg);
    155		udelay(10);
    156		if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_READ_DONE) >= 0) {
    157			u16 value = oxygen_read16(chip, OXYGEN_AC97_REGS);
    158			/* we require two consecutive reads of the same value */
    159			if (value == last_read)
    160				return value;
    161			last_read = value;
    162			/*
    163			 * Invert the register value bits to make sure that two
    164			 * consecutive unsuccessful reads do not return the same
    165			 * value.
    166			 */
    167			reg ^= 0xffff;
    168		}
    169	}
    170	dev_err(chip->card->dev, "AC'97 read timeout on codec %u\n", codec);
    171	return 0;
    172}
    173EXPORT_SYMBOL(oxygen_read_ac97);
    174
    175void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec,
    176			      unsigned int index, u16 data, u16 mask)
    177{
    178	u16 value = oxygen_read_ac97(chip, codec, index);
    179	value &= ~mask;
    180	value |= data & mask;
    181	oxygen_write_ac97(chip, codec, index, value);
    182}
    183EXPORT_SYMBOL(oxygen_write_ac97_masked);
    184
    185static int oxygen_wait_spi(struct oxygen *chip)
    186{
    187	unsigned int count;
    188
    189	/*
    190	 * Higher timeout to be sure: 200 us;
    191	 * actual transaction should not need more than 40 us.
    192	 */
    193	for (count = 50; count > 0; count--) {
    194		udelay(4);
    195		if ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) &
    196						OXYGEN_SPI_BUSY) == 0)
    197			return 0;
    198	}
    199	dev_err(chip->card->dev, "oxygen: SPI wait timeout\n");
    200	return -EIO;
    201}
    202
    203int oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data)
    204{
    205	/*
    206	 * We need to wait AFTER initiating the SPI transaction,
    207	 * otherwise read operations will not work.
    208	 */
    209	oxygen_write8(chip, OXYGEN_SPI_DATA1, data);
    210	oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8);
    211	if (control & OXYGEN_SPI_DATA_LENGTH_3)
    212		oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16);
    213	oxygen_write8(chip, OXYGEN_SPI_CONTROL, control);
    214	return oxygen_wait_spi(chip);
    215}
    216EXPORT_SYMBOL(oxygen_write_spi);
    217
    218void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data)
    219{
    220	/* should not need more than about 300 us */
    221	msleep(1);
    222
    223	oxygen_write8(chip, OXYGEN_2WIRE_MAP, map);
    224	oxygen_write8(chip, OXYGEN_2WIRE_DATA, data);
    225	oxygen_write8(chip, OXYGEN_2WIRE_CONTROL,
    226		      device | OXYGEN_2WIRE_DIR_WRITE);
    227}
    228EXPORT_SYMBOL(oxygen_write_i2c);
    229
    230static void _write_uart(struct oxygen *chip, unsigned int port, u8 data)
    231{
    232	if (oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_TX_FULL)
    233		msleep(1);
    234	oxygen_write8(chip, OXYGEN_MPU401 + port, data);
    235}
    236
    237void oxygen_reset_uart(struct oxygen *chip)
    238{
    239	_write_uart(chip, 1, MPU401_RESET);
    240	msleep(1); /* wait for ACK */
    241	_write_uart(chip, 1, MPU401_ENTER_UART);
    242}
    243EXPORT_SYMBOL(oxygen_reset_uart);
    244
    245void oxygen_write_uart(struct oxygen *chip, u8 data)
    246{
    247	_write_uart(chip, 0, data);
    248}
    249EXPORT_SYMBOL(oxygen_write_uart);
    250
    251u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index)
    252{
    253	unsigned int timeout;
    254
    255	oxygen_write8(chip, OXYGEN_EEPROM_CONTROL,
    256		      index | OXYGEN_EEPROM_DIR_READ);
    257	for (timeout = 0; timeout < 100; ++timeout) {
    258		udelay(1);
    259		if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS)
    260		      & OXYGEN_EEPROM_BUSY))
    261			break;
    262	}
    263	return oxygen_read16(chip, OXYGEN_EEPROM_DATA);
    264}
    265
    266void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value)
    267{
    268	unsigned int timeout;
    269
    270	oxygen_write16(chip, OXYGEN_EEPROM_DATA, value);
    271	oxygen_write8(chip, OXYGEN_EEPROM_CONTROL,
    272		      index | OXYGEN_EEPROM_DIR_WRITE);
    273	for (timeout = 0; timeout < 10; ++timeout) {
    274		msleep(1);
    275		if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS)
    276		      & OXYGEN_EEPROM_BUSY))
    277			return;
    278	}
    279	dev_err(chip->card->dev, "EEPROM write timeout\n");
    280}