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

jornada720_ssp.c (4389B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/**
      3 *  arch/arm/mac-sa1100/jornada720_ssp.c
      4 *
      5 *  Copyright (C) 2006/2007 Kristoffer Ericson <Kristoffer.Ericson@gmail.com>
      6 *   Copyright (C) 2006 Filip Zyzniewski <filip.zyzniewski@tefnet.pl>
      7 *
      8 *  SSP driver for the HP Jornada 710/720/728
      9 */
     10
     11#include <linux/delay.h>
     12#include <linux/errno.h>
     13#include <linux/init.h>
     14#include <linux/kernel.h>
     15#include <linux/module.h>
     16#include <linux/platform_device.h>
     17#include <linux/sched.h>
     18#include <linux/io.h>
     19
     20#include <mach/hardware.h>
     21#include <mach/jornada720.h>
     22#include <asm/hardware/ssp.h>
     23
     24static DEFINE_SPINLOCK(jornada_ssp_lock);
     25static unsigned long jornada_ssp_flags;
     26
     27/**
     28 * jornada_ssp_reverse - reverses input byte
     29 *
     30 * we need to reverse all data we receive from the mcu due to its physical location
     31 * returns : 01110111 -> 11101110
     32 */
     33inline u8 jornada_ssp_reverse(u8 byte)
     34{
     35	return
     36		((0x80 & byte) >> 7) |
     37		((0x40 & byte) >> 5) |
     38		((0x20 & byte) >> 3) |
     39		((0x10 & byte) >> 1) |
     40		((0x08 & byte) << 1) |
     41		((0x04 & byte) << 3) |
     42		((0x02 & byte) << 5) |
     43		((0x01 & byte) << 7);
     44};
     45EXPORT_SYMBOL(jornada_ssp_reverse);
     46
     47/**
     48 * jornada_ssp_byte - waits for ready ssp bus and sends byte
     49 *
     50 * waits for fifo buffer to clear and then transmits, if it doesn't then we will
     51 * timeout after <timeout> rounds. Needs mcu running before its called.
     52 *
     53 * returns : %mcu output on success
     54 *	   : %-ETIMEDOUT on timeout
     55 */
     56int jornada_ssp_byte(u8 byte)
     57{
     58	int timeout = 400000;
     59	u16 ret;
     60
     61	while ((GPLR & GPIO_GPIO10)) {
     62		if (!--timeout) {
     63			printk(KERN_WARNING "SSP: timeout while waiting for transmit\n");
     64			return -ETIMEDOUT;
     65		}
     66		cpu_relax();
     67	}
     68
     69	ret = jornada_ssp_reverse(byte) << 8;
     70
     71	ssp_write_word(ret);
     72	ssp_read_word(&ret);
     73
     74	return jornada_ssp_reverse(ret);
     75};
     76EXPORT_SYMBOL(jornada_ssp_byte);
     77
     78/**
     79 * jornada_ssp_inout - decide if input is command or trading byte
     80 *
     81 * returns : (jornada_ssp_byte(byte)) on success
     82 *         : %-ETIMEDOUT on timeout failure
     83 */
     84int jornada_ssp_inout(u8 byte)
     85{
     86	int ret, i;
     87
     88	/* true means command byte */
     89	if (byte != TXDUMMY) {
     90		ret = jornada_ssp_byte(byte);
     91		/* Proper return to commands is TxDummy */
     92		if (ret != TXDUMMY) {
     93			for (i = 0; i < 256; i++)/* flushing bus */
     94				if (jornada_ssp_byte(TXDUMMY) == -1)
     95					break;
     96			return -ETIMEDOUT;
     97		}
     98	} else /* Exchange TxDummy for data */
     99		ret = jornada_ssp_byte(TXDUMMY);
    100
    101	return ret;
    102};
    103EXPORT_SYMBOL(jornada_ssp_inout);
    104
    105/**
    106 * jornada_ssp_start - enable mcu
    107 *
    108 */
    109void jornada_ssp_start(void)
    110{
    111	spin_lock_irqsave(&jornada_ssp_lock, jornada_ssp_flags);
    112	GPCR = GPIO_GPIO25;
    113	udelay(50);
    114	return;
    115};
    116EXPORT_SYMBOL(jornada_ssp_start);
    117
    118/**
    119 * jornada_ssp_end - disable mcu and turn off lock
    120 *
    121 */
    122void jornada_ssp_end(void)
    123{
    124	GPSR = GPIO_GPIO25;
    125	spin_unlock_irqrestore(&jornada_ssp_lock, jornada_ssp_flags);
    126	return;
    127};
    128EXPORT_SYMBOL(jornada_ssp_end);
    129
    130static int jornada_ssp_probe(struct platform_device *dev)
    131{
    132	int ret;
    133
    134	GPSR = GPIO_GPIO25;
    135
    136	ret = ssp_init();
    137
    138	/* worked fine, lets not bother with anything else */
    139	if (!ret) {
    140		printk(KERN_INFO "SSP: device initialized with irq\n");
    141		return ret;
    142	}
    143
    144	printk(KERN_WARNING "SSP: initialization failed, trying non-irq solution \n");
    145
    146	/* init of Serial 4 port */
    147	Ser4MCCR0 = 0;
    148	Ser4SSCR0 = 0x0387;
    149	Ser4SSCR1 = 0x18;
    150
    151	/* clear out any left over data */
    152	ssp_flush();
    153
    154	/* enable MCU */
    155	jornada_ssp_start();
    156
    157	/* see if return value makes sense */
    158	ret = jornada_ssp_inout(GETBRIGHTNESS);
    159
    160	/* seems like it worked, just feed it with TxDummy to get rid of data */
    161	if (ret == TXDUMMY)
    162		jornada_ssp_inout(TXDUMMY);
    163
    164	jornada_ssp_end();
    165
    166	/* failed, lets just kill everything */
    167	if (ret == -ETIMEDOUT) {
    168		printk(KERN_WARNING "SSP: attempts failed, bailing\n");
    169		ssp_exit();
    170		return -ENODEV;
    171	}
    172
    173	/* all fine */
    174	printk(KERN_INFO "SSP: device initialized\n");
    175	return 0;
    176};
    177
    178static int jornada_ssp_remove(struct platform_device *dev)
    179{
    180	/* Note that this doesn't actually remove the driver, since theres nothing to remove
    181	 * It just makes sure everything is turned off */
    182	GPSR = GPIO_GPIO25;
    183	ssp_exit();
    184	return 0;
    185};
    186
    187struct platform_driver jornadassp_driver = {
    188	.probe	= jornada_ssp_probe,
    189	.remove	= jornada_ssp_remove,
    190	.driver	= {
    191		.name	= "jornada_ssp",
    192	},
    193};
    194
    195static int __init jornada_ssp_init(void)
    196{
    197	return platform_driver_register(&jornadassp_driver);
    198}
    199
    200module_init(jornada_ssp_init);