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