0b53c7b98e93b1f34e6700d9b0bd33866957fdc8
[platform/kernel/u-boot.git] / arch / powerpc / cpu / mpc512x / iopin.c
1 /*
2  * (C) Copyright 2008
3  * Martha J Marx, Silicon Turnkey Express, mmarx@silicontkx.com
4  * mpc512x I/O pin/pad initialization for the ADS5121 board
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9 #include <linux/types.h>
10 #include <asm/io.h>
11
12 void iopin_initialize(iopin_t *ioregs_init, int len)
13 {
14         short i, j, p;
15         u32 *reg;
16         immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
17
18         reg = (u32 *)&(im->io_ctrl);
19
20         if (sizeof(ioregs_init) == 0)
21                 return;
22
23         for (i = 0; i < len; i++) {
24                 for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
25                         p < ioregs_init[i].nr_pins; p++, j++) {
26                         if (ioregs_init[i].bit_or)
27                                 setbits_be32(reg + j, ioregs_init[i].val);
28                         else
29                                 out_be32 (reg + j, ioregs_init[i].val);
30                 }
31         }
32         return;
33 }
34
35 void iopin_initialize_bits(iopin_t *ioregs_init, int len)
36 {
37         short i, j, p;
38         u32 *reg, mask;
39         immap_t *im = (immap_t *)CONFIG_SYS_IMMR;
40
41         reg = (u32 *)&(im->io_ctrl);
42
43         /* iterate over table entries */
44         for (i = 0; i < len; i++) {
45                 /* iterate over pins within a table entry */
46                 for (p = 0, j = ioregs_init[i].p_offset / sizeof(u_long);
47                         p < ioregs_init[i].nr_pins; p++, j++) {
48                         if (ioregs_init[i].bit_or & IO_PIN_OVER_EACH) {
49                                 /* replace all settings at once */
50                                 out_be32(reg + j, ioregs_init[i].val);
51                         } else {
52                                 /*
53                                  * only replace individual parts, but
54                                  * REPLACE them instead of just ORing
55                                  * them in and "inheriting" previously
56                                  * set bits which we don't want
57                                  */
58                                 mask = 0;
59                                 if (ioregs_init[i].bit_or & IO_PIN_OVER_FMUX)
60                                         mask |= IO_PIN_FMUX(3);
61
62                                 if (ioregs_init[i].bit_or & IO_PIN_OVER_HOLD)
63                                         mask |= IO_PIN_HOLD(3);
64
65                                 if (ioregs_init[i].bit_or & IO_PIN_OVER_PULL)
66                                         mask |= IO_PIN_PUD(1) | IO_PIN_PUE(1);
67
68                                 if (ioregs_init[i].bit_or & IO_PIN_OVER_STRIG)
69                                         mask |= IO_PIN_ST(1);
70
71                                 if (ioregs_init[i].bit_or & IO_PIN_OVER_DRVSTR)
72                                         mask |= IO_PIN_DS(3);
73                                 /*
74                                  * DON'T do the "mask, then insert"
75                                  * in place on the register, it may
76                                  * break access to external hardware
77                                  * (like boot ROMs) when configuring
78                                  * LPB related pins, while the code to
79                                  * configure the pin is read from this
80                                  * very address region
81                                  */
82                                 clrsetbits_be32(reg + j, mask,
83                                                 ioregs_init[i].val & mask);
84                         }
85                 }
86         }
87 }