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 | |
24 | static struct qe_pio_regs __iomem *par_io; |
25 | static int num_par_io_ports = 0; |
26 | |
27 | int 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(dev: np, index: 0, r: &res); |
35 | if (ret) |
36 | return ret; |
37 | par_io = ioremap(offset: res.start, size: resource_size(res: &res)); |
38 | if (!par_io) |
39 | return -ENOMEM; |
40 | |
41 | if (!of_property_read_u32(np, propname: "num-ports" , out_value: &num_ports)) |
42 | num_par_io_ports = num_ports; |
43 | |
44 | return 0; |
45 | } |
46 | |
47 | void __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 | } |
106 | EXPORT_SYMBOL(__par_io_config_pin); |
107 | |
108 | int 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 | } |
118 | EXPORT_SYMBOL(par_io_config_pin); |
119 | |
120 | int 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 | } |
140 | EXPORT_SYMBOL(par_io_data_set); |
141 | |
142 | int 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, phandle_name: "pio-handle" , index: 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(node: pio, name: "pio-map" , lenp: &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(node: pio); |
184 | return 0; |
185 | } |
186 | EXPORT_SYMBOL(par_io_of_config); |
187 | |