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

sa1100_h3600.c (4019B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * drivers/pcmcia/sa1100_h3600.c
      4 *
      5 * PCMCIA implementation routines for H3600
      6 *
      7 */
      8#include <linux/module.h>
      9#include <linux/kernel.h>
     10#include <linux/device.h>
     11#include <linux/interrupt.h>
     12#include <linux/init.h>
     13#include <linux/delay.h>
     14#include <linux/gpio.h>
     15
     16#include <mach/hardware.h>
     17#include <asm/irq.h>
     18#include <asm/mach-types.h>
     19#include <mach/h3xxx.h>
     20
     21#include "sa1100_generic.h"
     22
     23static int h3600_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
     24{
     25	int err;
     26
     27	skt->stat[SOC_STAT_CD].name = skt->nr ? "pcmcia1-detect" : "pcmcia0-detect";
     28	skt->stat[SOC_STAT_RDY].name = skt->nr ? "pcmcia1-ready" : "pcmcia0-ready";
     29
     30	err = soc_pcmcia_request_gpiods(skt);
     31	if (err)
     32		return err;
     33
     34	switch (skt->nr) {
     35	case 0:
     36		err = gpio_request(H3XXX_EGPIO_OPT_NVRAM_ON, "OPT NVRAM ON");
     37		if (err)
     38			goto err01;
     39		err = gpio_direction_output(H3XXX_EGPIO_OPT_NVRAM_ON, 0);
     40		if (err)
     41			goto err03;
     42		err = gpio_request(H3XXX_EGPIO_OPT_ON, "OPT ON");
     43		if (err)
     44			goto err03;
     45		err = gpio_direction_output(H3XXX_EGPIO_OPT_ON, 0);
     46		if (err)
     47			goto err04;
     48		err = gpio_request(H3XXX_EGPIO_OPT_RESET, "OPT RESET");
     49		if (err)
     50			goto err04;
     51		err = gpio_direction_output(H3XXX_EGPIO_OPT_RESET, 0);
     52		if (err)
     53			goto err05;
     54		err = gpio_request(H3XXX_EGPIO_CARD_RESET, "PCMCIA CARD RESET");
     55		if (err)
     56			goto err05;
     57		err = gpio_direction_output(H3XXX_EGPIO_CARD_RESET, 0);
     58		if (err)
     59			goto err06;
     60		break;
     61	case 1:
     62		break;
     63	}
     64	return 0;
     65
     66err06:	gpio_free(H3XXX_EGPIO_CARD_RESET);
     67err05:	gpio_free(H3XXX_EGPIO_OPT_RESET);
     68err04:	gpio_free(H3XXX_EGPIO_OPT_ON);
     69err03:	gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON);
     70err01:	gpio_free(H3XXX_GPIO_PCMCIA_IRQ0);
     71	return err;
     72}
     73
     74static void h3600_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
     75{
     76	switch (skt->nr) {
     77	case 0:
     78		/* Disable CF bus: */
     79		gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0);
     80		gpio_set_value(H3XXX_EGPIO_OPT_ON, 0);
     81		gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1);
     82
     83		gpio_free(H3XXX_EGPIO_CARD_RESET);
     84		gpio_free(H3XXX_EGPIO_OPT_RESET);
     85		gpio_free(H3XXX_EGPIO_OPT_ON);
     86		gpio_free(H3XXX_EGPIO_OPT_NVRAM_ON);
     87		break;
     88	case 1:
     89		break;
     90	}
     91}
     92
     93static void
     94h3600_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state)
     95{
     96	state->bvd1 = 0;
     97	state->bvd2 = 0;
     98	state->vs_3v = 0;
     99	state->vs_Xv = 0;
    100}
    101
    102static int
    103h3600_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
    104{
    105	if (state->Vcc != 0 && state->Vcc != 33 && state->Vcc != 50) {
    106		printk(KERN_ERR "h3600_pcmcia: unrecognized Vcc %u.%uV\n",
    107		       state->Vcc / 10, state->Vcc % 10);
    108		return -1;
    109	}
    110
    111	gpio_set_value(H3XXX_EGPIO_CARD_RESET, !!(state->flags & SS_RESET));
    112
    113	/* Silently ignore Vpp, output enable, speaker enable. */
    114
    115	return 0;
    116}
    117
    118static void h3600_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
    119{
    120	/* Enable CF bus: */
    121	gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 1);
    122	gpio_set_value(H3XXX_EGPIO_OPT_ON, 1);
    123	gpio_set_value(H3XXX_EGPIO_OPT_RESET, 0);
    124
    125	msleep(10);
    126}
    127
    128static void h3600_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
    129{
    130	/*
    131	 * FIXME:  This doesn't fit well.  We don't have the mechanism in
    132	 * the generic PCMCIA layer to deal with the idea of two sockets
    133	 * on one bus.  We rely on the cs.c behaviour shutting down
    134	 * socket 0 then socket 1.
    135	 */
    136	if (skt->nr == 1) {
    137		gpio_set_value(H3XXX_EGPIO_OPT_ON, 0);
    138		gpio_set_value(H3XXX_EGPIO_OPT_NVRAM_ON, 0);
    139		/* hmm, does this suck power? */
    140		gpio_set_value(H3XXX_EGPIO_OPT_RESET, 1);
    141	}
    142}
    143
    144struct pcmcia_low_level h3600_pcmcia_ops = { 
    145	.owner			= THIS_MODULE,
    146	.hw_init		= h3600_pcmcia_hw_init,
    147	.hw_shutdown		= h3600_pcmcia_hw_shutdown,
    148	.socket_state		= h3600_pcmcia_socket_state,
    149	.configure_socket	= h3600_pcmcia_configure_socket,
    150
    151	.socket_init		= h3600_pcmcia_socket_init,
    152	.socket_suspend		= h3600_pcmcia_socket_suspend,
    153};
    154
    155int pcmcia_h3600_init(struct device *dev)
    156{
    157	int ret = -ENODEV;
    158
    159	if (machine_is_h3600() || machine_is_h3100())
    160		ret = sa11xx_drv_pcmcia_probe(dev, &h3600_pcmcia_ops, 0, 2);
    161
    162	return ret;
    163}