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