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

parport.h (5819B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2/* parport.h: sparc64 specific parport initialization and dma.
      3 *
      4 * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
      5 */
      6
      7#ifndef _ASM_SPARC64_PARPORT_H
      8#define _ASM_SPARC64_PARPORT_H 1
      9
     10#include <linux/of_device.h>
     11
     12#include <asm/ebus_dma.h>
     13#include <asm/ns87303.h>
     14#include <asm/prom.h>
     15
     16#define PARPORT_PC_MAX_PORTS	PARPORT_MAX
     17
     18/*
     19 * While sparc64 doesn't have an ISA DMA API, we provide something that looks
     20 * close enough to make parport_pc happy
     21 */
     22#define HAS_DMA
     23
     24#ifdef CONFIG_PARPORT_PC_FIFO
     25static DEFINE_SPINLOCK(dma_spin_lock);
     26
     27#define claim_dma_lock() \
     28({	unsigned long flags; \
     29	spin_lock_irqsave(&dma_spin_lock, flags); \
     30	flags; \
     31})
     32
     33#define release_dma_lock(__flags) \
     34	spin_unlock_irqrestore(&dma_spin_lock, __flags);
     35#endif
     36
     37static struct sparc_ebus_info {
     38	struct ebus_dma_info info;
     39	unsigned int addr;
     40	unsigned int count;
     41	int lock;
     42
     43	struct parport *port;
     44} sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
     45
     46static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
     47
     48static inline int request_dma(unsigned int dmanr, const char *device_id)
     49{
     50	if (dmanr >= PARPORT_PC_MAX_PORTS)
     51		return -EINVAL;
     52	if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
     53		return -EBUSY;
     54	return 0;
     55}
     56
     57static inline void free_dma(unsigned int dmanr)
     58{
     59	if (dmanr >= PARPORT_PC_MAX_PORTS) {
     60		printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
     61		return;
     62	}
     63	if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
     64		printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
     65		return;
     66	}
     67}
     68
     69static inline void enable_dma(unsigned int dmanr)
     70{
     71	ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
     72
     73	if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
     74			     sparc_ebus_dmas[dmanr].addr,
     75			     sparc_ebus_dmas[dmanr].count))
     76		BUG();
     77}
     78
     79static inline void disable_dma(unsigned int dmanr)
     80{
     81	ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
     82}
     83
     84static inline void clear_dma_ff(unsigned int dmanr)
     85{
     86	/* nothing */
     87}
     88
     89static inline void set_dma_mode(unsigned int dmanr, char mode)
     90{
     91	ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
     92}
     93
     94static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
     95{
     96	sparc_ebus_dmas[dmanr].addr = addr;
     97}
     98
     99static inline void set_dma_count(unsigned int dmanr, unsigned int count)
    100{
    101	sparc_ebus_dmas[dmanr].count = count;
    102}
    103
    104static inline unsigned int get_dma_residue(unsigned int dmanr)
    105{
    106	return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
    107}
    108
    109static int ecpp_probe(struct platform_device *op)
    110{
    111	unsigned long base = op->resource[0].start;
    112	unsigned long config = op->resource[1].start;
    113	unsigned long d_base = op->resource[2].start;
    114	unsigned long d_len;
    115	struct device_node *parent;
    116	struct parport *p;
    117	int slot, err;
    118
    119	parent = op->dev.of_node->parent;
    120	if (of_node_name_eq(parent, "dma")) {
    121		p = parport_pc_probe_port(base, base + 0x400,
    122					  op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
    123					  op->dev.parent->parent, 0);
    124		if (!p)
    125			return -ENOMEM;
    126		dev_set_drvdata(&op->dev, p);
    127		return 0;
    128	}
    129
    130	for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
    131		if (!test_and_set_bit(slot, dma_slot_map))
    132			break;
    133	}
    134	err = -ENODEV;
    135	if (slot >= PARPORT_PC_MAX_PORTS)
    136		goto out_err;
    137
    138	spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
    139
    140	d_len = (op->resource[2].end - d_base) + 1UL;
    141	sparc_ebus_dmas[slot].info.regs =
    142		of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
    143
    144	if (!sparc_ebus_dmas[slot].info.regs)
    145		goto out_clear_map;
    146
    147	sparc_ebus_dmas[slot].info.flags = 0;
    148	sparc_ebus_dmas[slot].info.callback = NULL;
    149	sparc_ebus_dmas[slot].info.client_cookie = NULL;
    150	sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
    151	strcpy(sparc_ebus_dmas[slot].info.name, "parport");
    152	if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
    153		goto out_unmap_regs;
    154
    155	ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
    156
    157	/* Configure IRQ to Push Pull, Level Low */
    158	/* Enable ECP, set bit 2 of the CTR first */
    159	outb(0x04, base + 0x02);
    160	ns87303_modify(config, PCR,
    161		       PCR_EPP_ENABLE |
    162		       PCR_IRQ_ODRAIN,
    163		       PCR_ECP_ENABLE |
    164		       PCR_ECP_CLK_ENA |
    165		       PCR_IRQ_POLAR);
    166
    167	/* CTR bit 5 controls direction of port */
    168	ns87303_modify(config, PTR,
    169		       0, PTR_LPT_REG_DIR);
    170
    171	p = parport_pc_probe_port(base, base + 0x400,
    172				  op->archdata.irqs[0],
    173				  slot,
    174				  op->dev.parent,
    175				  0);
    176	err = -ENOMEM;
    177	if (!p)
    178		goto out_disable_irq;
    179
    180	dev_set_drvdata(&op->dev, p);
    181
    182	return 0;
    183
    184out_disable_irq:
    185	ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
    186	ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
    187
    188out_unmap_regs:
    189	of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
    190
    191out_clear_map:
    192	clear_bit(slot, dma_slot_map);
    193
    194out_err:
    195	return err;
    196}
    197
    198static int ecpp_remove(struct platform_device *op)
    199{
    200	struct parport *p = dev_get_drvdata(&op->dev);
    201	int slot = p->dma;
    202
    203	parport_pc_unregister_port(p);
    204
    205	if (slot != PARPORT_DMA_NOFIFO) {
    206		unsigned long d_base = op->resource[2].start;
    207		unsigned long d_len;
    208
    209		d_len = (op->resource[2].end - d_base) + 1UL;
    210
    211		ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
    212		ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
    213		of_iounmap(&op->resource[2],
    214			   sparc_ebus_dmas[slot].info.regs,
    215			   d_len);
    216		clear_bit(slot, dma_slot_map);
    217	}
    218
    219	return 0;
    220}
    221
    222static const struct of_device_id ecpp_match[] = {
    223	{
    224		.name = "ecpp",
    225	},
    226	{
    227		.name = "parallel",
    228		.compatible = "ecpp",
    229	},
    230	{
    231		.name = "parallel",
    232		.compatible = "ns87317-ecpp",
    233	},
    234	{
    235		.name = "parallel",
    236		.compatible = "pnpALI,1533,3",
    237	},
    238	{},
    239};
    240
    241static struct platform_driver ecpp_driver = {
    242	.driver = {
    243		.name = "ecpp",
    244		.of_match_table = ecpp_match,
    245	},
    246	.probe			= ecpp_probe,
    247	.remove			= ecpp_remove,
    248};
    249
    250static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
    251{
    252	return platform_driver_register(&ecpp_driver);
    253}
    254
    255#endif /* !(_ASM_SPARC64_PARPORT_H */