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

qe_io.c (4805B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * arch/powerpc/sysdev/qe_lib/qe_io.c
      4 *
      5 * QE Parallel I/O ports configuration routines
      6 *
      7 * Copyright 2006 Freescale Semiconductor, Inc. All rights reserved.
      8 *
      9 * Author: Li Yang <LeoLi@freescale.com>
     10 * Based on code from Shlomi Gridish <gridish@freescale.com>
     11 */
     12
     13#include <linux/stddef.h>
     14#include <linux/kernel.h>
     15#include <linux/errno.h>
     16#include <linux/module.h>
     17#include <linux/ioport.h>
     18
     19#include <asm/io.h>
     20#include <soc/fsl/qe/qe.h>
     21
     22#undef DEBUG
     23
     24static struct qe_pio_regs __iomem *par_io;
     25static int num_par_io_ports = 0;
     26
     27int par_io_init(struct device_node *np)
     28{
     29	struct resource res;
     30	int ret;
     31	u32 num_ports;
     32
     33	/* Map Parallel I/O ports registers */
     34	ret = of_address_to_resource(np, 0, &res);
     35	if (ret)
     36		return ret;
     37	par_io = ioremap(res.start, resource_size(&res));
     38	if (!par_io)
     39		return -ENOMEM;
     40
     41	if (!of_property_read_u32(np, "num-ports", &num_ports))
     42		num_par_io_ports = num_ports;
     43
     44	return 0;
     45}
     46
     47void __par_io_config_pin(struct qe_pio_regs __iomem *par_io, u8 pin, int dir,
     48			 int open_drain, int assignment, int has_irq)
     49{
     50	u32 pin_mask1bit;
     51	u32 pin_mask2bits;
     52	u32 new_mask2bits;
     53	u32 tmp_val;
     54
     55	/* calculate pin location for single and 2 bits information */
     56	pin_mask1bit = (u32) (1 << (QE_PIO_PINS - (pin + 1)));
     57
     58	/* Set open drain, if required */
     59	tmp_val = ioread32be(&par_io->cpodr);
     60	if (open_drain)
     61		iowrite32be(pin_mask1bit | tmp_val, &par_io->cpodr);
     62	else
     63		iowrite32be(~pin_mask1bit & tmp_val, &par_io->cpodr);
     64
     65	/* define direction */
     66	tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
     67		ioread32be(&par_io->cpdir2) :
     68		ioread32be(&par_io->cpdir1);
     69
     70	/* get all bits mask for 2 bit per port */
     71	pin_mask2bits = (u32) (0x3 << (QE_PIO_PINS -
     72				(pin % (QE_PIO_PINS / 2) + 1) * 2));
     73
     74	/* Get the final mask we need for the right definition */
     75	new_mask2bits = (u32) (dir << (QE_PIO_PINS -
     76				(pin % (QE_PIO_PINS / 2) + 1) * 2));
     77
     78	/* clear and set 2 bits mask */
     79	if (pin > (QE_PIO_PINS / 2) - 1) {
     80		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cpdir2);
     81		tmp_val &= ~pin_mask2bits;
     82		iowrite32be(new_mask2bits | tmp_val, &par_io->cpdir2);
     83	} else {
     84		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cpdir1);
     85		tmp_val &= ~pin_mask2bits;
     86		iowrite32be(new_mask2bits | tmp_val, &par_io->cpdir1);
     87	}
     88	/* define pin assignment */
     89	tmp_val = (pin > (QE_PIO_PINS / 2) - 1) ?
     90		ioread32be(&par_io->cppar2) :
     91		ioread32be(&par_io->cppar1);
     92
     93	new_mask2bits = (u32) (assignment << (QE_PIO_PINS -
     94			(pin % (QE_PIO_PINS / 2) + 1) * 2));
     95	/* clear and set 2 bits mask */
     96	if (pin > (QE_PIO_PINS / 2) - 1) {
     97		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cppar2);
     98		tmp_val &= ~pin_mask2bits;
     99		iowrite32be(new_mask2bits | tmp_val, &par_io->cppar2);
    100	} else {
    101		iowrite32be(~pin_mask2bits & tmp_val, &par_io->cppar1);
    102		tmp_val &= ~pin_mask2bits;
    103		iowrite32be(new_mask2bits | tmp_val, &par_io->cppar1);
    104	}
    105}
    106EXPORT_SYMBOL(__par_io_config_pin);
    107
    108int par_io_config_pin(u8 port, u8 pin, int dir, int open_drain,
    109		      int assignment, int has_irq)
    110{
    111	if (!par_io || port >= num_par_io_ports)
    112		return -EINVAL;
    113
    114	__par_io_config_pin(&par_io[port], pin, dir, open_drain, assignment,
    115			    has_irq);
    116	return 0;
    117}
    118EXPORT_SYMBOL(par_io_config_pin);
    119
    120int par_io_data_set(u8 port, u8 pin, u8 val)
    121{
    122	u32 pin_mask, tmp_val;
    123
    124	if (port >= num_par_io_ports)
    125		return -EINVAL;
    126	if (pin >= QE_PIO_PINS)
    127		return -EINVAL;
    128	/* calculate pin location */
    129	pin_mask = (u32) (1 << (QE_PIO_PINS - 1 - pin));
    130
    131	tmp_val = ioread32be(&par_io[port].cpdata);
    132
    133	if (val == 0)		/* clear */
    134		iowrite32be(~pin_mask & tmp_val, &par_io[port].cpdata);
    135	else			/* set */
    136		iowrite32be(pin_mask | tmp_val, &par_io[port].cpdata);
    137
    138	return 0;
    139}
    140EXPORT_SYMBOL(par_io_data_set);
    141
    142int par_io_of_config(struct device_node *np)
    143{
    144	struct device_node *pio;
    145	int pio_map_len;
    146	const __be32 *pio_map;
    147
    148	if (par_io == NULL) {
    149		printk(KERN_ERR "par_io not initialized\n");
    150		return -1;
    151	}
    152
    153	pio = of_parse_phandle(np, "pio-handle", 0);
    154	if (pio == NULL) {
    155		printk(KERN_ERR "pio-handle not available\n");
    156		return -1;
    157	}
    158
    159	pio_map = of_get_property(pio, "pio-map", &pio_map_len);
    160	if (pio_map == NULL) {
    161		printk(KERN_ERR "pio-map is not set!\n");
    162		return -1;
    163	}
    164	pio_map_len /= sizeof(unsigned int);
    165	if ((pio_map_len % 6) != 0) {
    166		printk(KERN_ERR "pio-map format wrong!\n");
    167		return -1;
    168	}
    169
    170	while (pio_map_len > 0) {
    171		u8 port        = be32_to_cpu(pio_map[0]);
    172		u8 pin         = be32_to_cpu(pio_map[1]);
    173		int dir        = be32_to_cpu(pio_map[2]);
    174		int open_drain = be32_to_cpu(pio_map[3]);
    175		int assignment = be32_to_cpu(pio_map[4]);
    176		int has_irq    = be32_to_cpu(pio_map[5]);
    177
    178		par_io_config_pin(port, pin, dir, open_drain,
    179				  assignment, has_irq);
    180		pio_map += 6;
    181		pio_map_len -= 6;
    182	}
    183	of_node_put(pio);
    184	return 0;
    185}
    186EXPORT_SYMBOL(par_io_of_config);