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

l3.c (2674B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * L3 code
      4 *
      5 *  Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org>
      6 *
      7 * based on:
      8 *
      9 * L3 bus algorithm module.
     10 *
     11 *  Copyright (C) 2001 Russell King, All Rights Reserved.
     12 */
     13
     14#include <linux/module.h>
     15#include <linux/kernel.h>
     16#include <linux/delay.h>
     17#include <linux/device.h>
     18#include <linux/gpio.h>
     19
     20#include <sound/l3.h>
     21
     22/*
     23 * Send one byte of data to the chip.  Data is latched into the chip on
     24 * the rising edge of the clock.
     25 */
     26static void sendbyte(struct l3_pins *adap, unsigned int byte)
     27{
     28	int i;
     29
     30	for (i = 0; i < 8; i++) {
     31		adap->setclk(adap, 0);
     32		udelay(adap->data_hold);
     33		adap->setdat(adap, byte & 1);
     34		udelay(adap->data_setup);
     35		adap->setclk(adap, 1);
     36		udelay(adap->clock_high);
     37		byte >>= 1;
     38	}
     39}
     40
     41/*
     42 * Send a set of bytes to the chip.  We need to pulse the MODE line
     43 * between each byte, but never at the start nor at the end of the
     44 * transfer.
     45 */
     46static void sendbytes(struct l3_pins *adap, const u8 *buf,
     47		      int len)
     48{
     49	int i;
     50
     51	for (i = 0; i < len; i++) {
     52		if (i) {
     53			udelay(adap->mode_hold);
     54			adap->setmode(adap, 0);
     55			udelay(adap->mode);
     56		}
     57		adap->setmode(adap, 1);
     58		udelay(adap->mode_setup);
     59		sendbyte(adap, buf[i]);
     60	}
     61}
     62
     63int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
     64{
     65	adap->setclk(adap, 1);
     66	adap->setdat(adap, 1);
     67	adap->setmode(adap, 1);
     68	udelay(adap->mode);
     69
     70	adap->setmode(adap, 0);
     71	udelay(adap->mode_setup);
     72	sendbyte(adap, addr);
     73	udelay(adap->mode_hold);
     74
     75	sendbytes(adap, data, len);
     76
     77	adap->setclk(adap, 1);
     78	adap->setdat(adap, 1);
     79	adap->setmode(adap, 0);
     80
     81	return len;
     82}
     83EXPORT_SYMBOL_GPL(l3_write);
     84
     85
     86static void l3_set_clk(struct l3_pins *adap, int val)
     87{
     88	gpio_set_value(adap->gpio_clk, val);
     89}
     90
     91static void l3_set_data(struct l3_pins *adap, int val)
     92{
     93	gpio_set_value(adap->gpio_data, val);
     94}
     95
     96static void l3_set_mode(struct l3_pins *adap, int val)
     97{
     98	gpio_set_value(adap->gpio_mode, val);
     99}
    100
    101int l3_set_gpio_ops(struct device *dev, struct l3_pins *adap)
    102{
    103	int ret;
    104
    105	if (!adap->use_gpios)
    106		return -EINVAL;
    107
    108	ret = devm_gpio_request_one(dev, adap->gpio_data,
    109				GPIOF_OUT_INIT_LOW, "l3_data");
    110	if (ret < 0)
    111		return ret;
    112	adap->setdat = l3_set_data;
    113
    114	ret = devm_gpio_request_one(dev, adap->gpio_clk,
    115				GPIOF_OUT_INIT_LOW, "l3_clk");
    116	if (ret < 0)
    117		return ret;
    118	adap->setclk = l3_set_clk;
    119
    120	ret = devm_gpio_request_one(dev, adap->gpio_mode,
    121				GPIOF_OUT_INIT_LOW, "l3_mode");
    122	if (ret < 0)
    123		return ret;
    124	adap->setmode = l3_set_mode;
    125
    126	return 0;
    127}
    128EXPORT_SYMBOL_GPL(l3_set_gpio_ops);
    129
    130MODULE_DESCRIPTION("L3 bit-banging driver");
    131MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
    132MODULE_LICENSE("GPL");