]> git.sur5r.net Git - u-boot/blob - board/bf609-ezkit/soft_switch.c
blackfin: bf609: implement soft switch
[u-boot] / board / bf609-ezkit / soft_switch.c
1 /*
2  * U-boot - main board file
3  *
4  * Copyright (c) 2008-2011 Analog Devices Inc.
5  *
6  * Licensed under the GPL-2 or later.
7  */
8
9 #include <common.h>
10 #include <asm/blackfin.h>
11 #include <asm/io.h>
12 #include <i2c.h>
13 #include "soft_switch.h"
14
15 #define SWITCH_ADDR     0x21
16
17 #define NUM_SWITCH      3
18 #define IODIRA          0x0
19 #define IODIRB          0x1
20 #define OLATA           0x14
21 #define OLATB           0x15
22
23 struct switch_config {
24         uchar dir0; /* IODIRA */
25         uchar dir1; /* IODIRB */
26         uchar value0; /* OLATA */
27         uchar value1; /* OLATB */
28 };
29
30 static struct switch_config switch_config_array[NUM_SWITCH] = {
31         {
32 /*
33         U45 Port A                     U45 Port B
34
35         7---------------  RMII_CLK_EN  |  7--------------- ~TEMP_THERM_EN
36         | 6------------- ~CNT0ZM_EN    |  | 6------------- ~TEMP_IRQ_EN
37         | | 5----------- ~CNT0DG_EN    |  | | 5----------- ~UART0CTS_146_EN
38         | | | 4--------- ~CNT0UD_EN    |  | | | 4--------- ~UART0CTS_RST_EN
39         | | | | 3------- ~CAN0RX_EN    |  | | | | 3------- ~UART0CTS_RTS_LPBK
40         | | | | | 2----- ~CAN0_ERR_EN  |  | | | | | 2----- ~UART0CTS_EN
41         | | | | | | 1--- ~CAN_STB      |  | | | | | | 1--- ~UART0RX_EN
42         | | | | | | | 0-  CAN_EN       |  | | | | | | | 0- ~UART0RTS_EN
43         | | | | | | | |                |  | | | | | | | |
44         O O O O O O O O                |  O O O O O O O O   (I/O direction)
45         1 0 0 0 0 0 1 1                |  1 1 1 1 1 0 0 0   (value being set)
46 */
47                 .dir0 = 0x0, /* all output */
48                 .dir1 = 0x0, /* all output */
49                 .value0 = RMII_CLK_EN | CAN_STB | CAN_EN,
50                 .value1 = TEMP_THERM_EN | TEMP_IRQ_EN | UART0CTS_146_EN
51                                 | UART0CTS_RST_EN | UART0CTS_RTS_LPBK,
52         },
53         {
54 /*
55         U46 Port A                       U46 Port B
56
57         7--------------- ~LED4_GPIO_EN   |  7---------------  EMPTY
58         | 6------------- ~LED3_GPIO_EN   |  | 6------------- ~SPI0D3_EN
59         | | 5----------- ~LED2_GPIO_EN   |  | | 5----------- ~SPI0D2_EN
60         | | | 4--------- ~LED1_GPIO_EN   |  | | | 4--------- ~SPIFLASH_CS_EN
61         | | | | 3-------  SMC0_LP0_EN    |  | | | | 3------- ~SD_WP_EN
62         | | | | | 2-----  EMPTY          |  | | | | | 2----- ~SD_CD_EN
63         | | | | | | 1---  SMC0_EPPI2     |  | | | | | | 1--- ~PUSHBUTTON2_EN
64                           _LP1_SWITCH
65         | | | | | | | 0-  OVERRIDE_SMC0  |  | | | | | | | 0- ~PUSHBUTTON1_EN
66                           _LP0_BOOT
67         | | | | | | | |                  |  | | | | | | | |
68         O O O O O O O O                  |  O O O O O O O O   (I/O direction)
69         0 0 0 0 0 X 0 1                  |  X 0 0 0 0 0 0 0   (value being set)
70 */
71                 .dir0 = 0x0, /* all output */
72                 .dir1 = 0x0, /* all output */
73 #ifdef CONFIG_BFIN_LINKPORT
74                 .value0 = OVERRIDE_SMC0_LP0_BOOT,
75 #else
76                 .value0 = SMC0_EPPI2_LP1_SWITCH,
77 #endif
78                 .value1 = 0x0,
79         },
80         {
81 /*
82         U47 Port A                         U47 Port B
83
84         7--------------- ~PD2_SPI0MISO |  7---------------  EMPTY
85                           _EI3_EN
86         | 6------------- ~PD1_SPI0D3   |  | 6-------------  EMPTY
87                           _EPPI1D17
88                           _SPI0SEL2
89                           _EI3_EN
90         | | 5----------- ~PD0_SPI0D2   |  | | 5-----------  EMPTY
91                           _EPPI1D16
92                           _SPI0SEL3
93                           _EI3_EN
94         | | | 4--------- ~WAKE_PUSH    |  | | | 4---------  EMPTY
95                           BUTTON_EN
96         | | | | 3------- ~ETHERNET_EN  |  | | | | 3-------  EMPTY
97         | | | | | 2-----  PHYAD0       |  | | | | | 2-----  EMPTY
98         | | | | | | 1---  PHY_PWR      |  | | | | | | 1--- ~PD4_SPI0CK_EI3_EN
99                           _DWN_INT
100         | | | | | | | 0- ~PHYINT_EN    |  | | | | | | | 0- ~PD3_SPI0MOSI_EI3_EN
101         | | | | | | | |                |  | | | | | | | |
102         O O O O O I I O                |  O O O O O O O O   (I/O direction)
103         1 1 1 0 0 0 0 0                |  X X X X X X 1 1   (value being set)
104 */
105                 .dir0 = 0x6, /* bits 1 and 2 input, all others output */
106                 .dir1 = 0x0, /* all output */
107                 .value0 = PD1_SPI0D3_EN | PD0_SPI0D2_EN,
108                 .value1 = 0,
109         },
110 };
111
112 static int setup_soft_switch(int addr, struct switch_config *config)
113 {
114         int ret = 0;
115
116         ret = i2c_write(addr, OLATA, 1, &config->value0, 1);
117         if (ret)
118                 return ret;
119         ret = i2c_write(addr, OLATB, 1, &config->value1, 1);
120         if (ret)
121                 return ret;
122
123         ret = i2c_write(addr, IODIRA, 1, &config->dir0, 1);
124         if (ret)
125                 return ret;
126         return i2c_write(addr, IODIRB, 1, &config->dir1, 1);
127 }
128
129 int config_switch_bit(int num, int port, int bit, int dir, uchar value)
130 {
131         int addr = SWITCH_ADDR + num;
132         int ret, data_reg, dir_reg;
133         uchar tmp;
134
135         if (port == IO_PORT_A) {
136                 data_reg = OLATA;
137                 dir_reg = IODIRA;
138         } else {
139                 data_reg = OLATB;
140                 dir_reg = IODIRB;
141         }
142
143         if (dir == IO_PORT_INPUT) {
144                 ret = i2c_read(addr, dir_reg, 1, &tmp, 1);
145                 if (ret)
146                         return ret;
147                 tmp |= bit;
148                 return i2c_write(addr, dir_reg, 1, &tmp, 1);
149         } else {
150                 ret = i2c_read(addr, data_reg, 1, &tmp, 1);
151                 if (ret)
152                         return ret;
153                 if (value)
154                         tmp |= bit;
155                 else
156                         tmp &= ~bit;
157                 ret = i2c_write(addr, data_reg, 1, &tmp, 1);
158                 if (ret)
159                         return ret;
160                 ret = i2c_read(addr, dir_reg, 1, &tmp, 1);
161                 if (ret)
162                         return ret;
163                 tmp &= ~bit;
164                 return i2c_write(addr, dir_reg, 1, &tmp, 1);
165         }
166 }
167
168 int setup_board_switches(void)
169 {
170         int ret;
171         int i;
172
173         for (i = 0; i < NUM_SWITCH; i++) {
174                 ret = setup_soft_switch(SWITCH_ADDR + i,
175                                 &switch_config_array[i]);
176                 if (ret)
177                         return ret;
178         }
179         return 0;
180 }