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

solo6x10-eeprom.c (3476B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2010-2013 Bluecherry, LLC <https://www.bluecherrydvr.com>
      4 *
      5 * Original author:
      6 * Ben Collins <bcollins@ubuntu.com>
      7 *
      8 * Additional work by:
      9 * John Brooks <john.brooks@bluecherry.net>
     10 */
     11
     12#include <linux/kernel.h>
     13#include <linux/delay.h>
     14
     15#include "solo6x10.h"
     16
     17/* Control */
     18#define EE_SHIFT_CLK	0x04
     19#define EE_CS		0x08
     20#define EE_DATA_WRITE	0x02
     21#define EE_DATA_READ	0x01
     22#define EE_ENB		(0x80 | EE_CS)
     23
     24#define eeprom_delay()	udelay(100)
     25#if 0
     26#define eeprom_delay()	solo_reg_read(solo_dev, SOLO_EEPROM_CTRL)
     27#define eeprom_delay()	({				\
     28	int i, ret;					\
     29	udelay(100);					\
     30	for (i = ret = 0; i < 1000 && !ret; i++)	\
     31		ret = solo_eeprom_reg_read(solo_dev);	\
     32})
     33#endif
     34#define ADDR_LEN	6
     35
     36/* Commands */
     37#define EE_EWEN_CMD	4
     38#define EE_EWDS_CMD	4
     39#define EE_WRITE_CMD	5
     40#define EE_READ_CMD	6
     41#define EE_ERASE_CMD	7
     42
     43static unsigned int solo_eeprom_reg_read(struct solo_dev *solo_dev)
     44{
     45	return solo_reg_read(solo_dev, SOLO_EEPROM_CTRL) & EE_DATA_READ;
     46}
     47
     48static void solo_eeprom_reg_write(struct solo_dev *solo_dev, u32 data)
     49{
     50	solo_reg_write(solo_dev, SOLO_EEPROM_CTRL, data);
     51	eeprom_delay();
     52}
     53
     54static void solo_eeprom_cmd(struct solo_dev *solo_dev, int cmd)
     55{
     56	int i;
     57
     58	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ACCESS_EN);
     59	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
     60
     61	for (i = 4 + ADDR_LEN; i >= 0; i--) {
     62		int dataval = (cmd & (1 << i)) ? EE_DATA_WRITE : 0;
     63
     64		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE | dataval);
     65		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
     66				      EE_SHIFT_CLK | dataval);
     67	}
     68
     69	solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
     70}
     71
     72unsigned int solo_eeprom_ewen(struct solo_dev *solo_dev, int w_en)
     73{
     74	int ewen_cmd = (w_en ? 0x3f : 0) | (EE_EWEN_CMD << ADDR_LEN);
     75	unsigned int retval = 0;
     76	int i;
     77
     78	solo_eeprom_cmd(solo_dev, ewen_cmd);
     79
     80	for (i = 0; i < 16; i++) {
     81		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
     82				      EE_SHIFT_CLK);
     83		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
     84		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
     85		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
     86	}
     87
     88	solo_eeprom_reg_write(solo_dev, ~EE_CS);
     89	retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
     90
     91	return retval;
     92}
     93
     94__be16 solo_eeprom_read(struct solo_dev *solo_dev, int loc)
     95{
     96	int read_cmd = loc | (EE_READ_CMD << ADDR_LEN);
     97	u16 retval = 0;
     98	int i;
     99
    100	solo_eeprom_cmd(solo_dev, read_cmd);
    101
    102	for (i = 0; i < 16; i++) {
    103		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE |
    104				      EE_SHIFT_CLK);
    105		retval = (retval << 1) | solo_eeprom_reg_read(solo_dev);
    106		solo_eeprom_reg_write(solo_dev, SOLO_EEPROM_ENABLE);
    107	}
    108
    109	solo_eeprom_reg_write(solo_dev, ~EE_CS);
    110
    111	return (__force __be16)retval;
    112}
    113
    114int solo_eeprom_write(struct solo_dev *solo_dev, int loc,
    115		      __be16 data)
    116{
    117	int write_cmd = loc | (EE_WRITE_CMD << ADDR_LEN);
    118	unsigned int retval;
    119	int i;
    120
    121	solo_eeprom_cmd(solo_dev, write_cmd);
    122
    123	for (i = 15; i >= 0; i--) {
    124		unsigned int dataval = ((__force unsigned)data >> i) & 1;
    125
    126		solo_eeprom_reg_write(solo_dev, EE_ENB);
    127		solo_eeprom_reg_write(solo_dev,
    128				      EE_ENB | (dataval << 1) | EE_SHIFT_CLK);
    129	}
    130
    131	solo_eeprom_reg_write(solo_dev, EE_ENB);
    132	solo_eeprom_reg_write(solo_dev, ~EE_CS);
    133	solo_eeprom_reg_write(solo_dev, EE_ENB);
    134
    135	for (i = retval = 0; i < 10000 && !retval; i++)
    136		retval = solo_eeprom_reg_read(solo_dev);
    137
    138	solo_eeprom_reg_write(solo_dev, ~EE_CS);
    139
    140	return !retval;
    141}