1
2
3
4
5
6
7
8#include <dm.h>
9#include <fdt_support.h>
10#include <linux/ctype.h>
11#include <linux/delay.h>
12#include <linux/io.h>
13#include <asm/global_data.h>
14
15#include "micro-support-card.h"
16
17#define SMC911X_OFFSET 0x00000
18#define LED_OFFSET 0x90000
19#define NS16550A_OFFSET 0xb0000
20#define MICRO_SUPPORT_CARD_RESET 0xd0034
21#define MICRO_SUPPORT_CARD_REVISION 0xd00e0
22
23static bool support_card_found;
24static void __iomem *support_card_base;
25
26static void support_card_detect(void)
27{
28 DECLARE_GLOBAL_DATA_PTR;
29 const void *fdt = gd->fdt_blob;
30 int offset;
31 u64 addr, addr2;
32
33 offset = fdt_node_offset_by_compatible(fdt, 0, "smsc,lan9118");
34 if (offset < 0)
35 return;
36
37 addr = fdt_get_base_address(fdt, offset);
38 if (addr == OF_BAD_ADDR)
39 return;
40 addr -= SMC911X_OFFSET;
41
42 offset = fdt_node_offset_by_compatible(fdt, 0, "ns16550a");
43 if (offset < 0)
44 return;
45
46 addr2 = fdt_get_base_address(fdt, offset);
47 if (addr2 == OF_BAD_ADDR)
48 return;
49 addr2 -= NS16550A_OFFSET;
50
51
52 if (addr != addr2)
53 return;
54
55 support_card_base = ioremap(addr, 0x100000);
56
57 support_card_found = true;
58}
59
60
61
62
63
64
65
66static void support_card_reset_deassert(void)
67{
68 writel(0x00010000, support_card_base + MICRO_SUPPORT_CARD_RESET);
69}
70
71static void support_card_reset(void)
72{
73 writel(0x00020003, support_card_base + MICRO_SUPPORT_CARD_RESET);
74}
75
76static int support_card_show_revision(void)
77{
78 u32 revision;
79
80 revision = readl(support_card_base + MICRO_SUPPORT_CARD_REVISION);
81 revision &= 0xff;
82
83
84 printf("SC: Micro Support Card (CPLD version %s%d.%d)\n",
85 revision >> 4 == 6 ? "3." : "",
86 revision >> 4, revision & 0xf);
87
88 return 0;
89}
90
91void support_card_init(void)
92{
93 struct udevice *dev;
94 int ret;
95
96
97 ret = uclass_get_device_by_driver(UCLASS_SIMPLE_BUS,
98 DM_DRIVER_GET(uniphier_system_bus_driver),
99 &dev);
100 if (ret)
101 return;
102
103
104 support_card_detect();
105
106 if (!support_card_found)
107 return;
108
109 support_card_reset();
110
111
112
113
114 udelay(200);
115 support_card_reset_deassert();
116
117 support_card_show_revision();
118}
119
120static const u8 ledval_num[] = {
121 0x7e,
122 0x0c,
123 0xb6,
124 0x9e,
125 0xcc,
126 0xda,
127 0xfa,
128 0x4e,
129 0xfe,
130 0xde,
131};
132
133static const u8 ledval_alpha[] = {
134 0xee,
135 0xf8,
136 0x72,
137 0xbc,
138 0xf2,
139 0xe2,
140 0x7a,
141 0xe8,
142 0x08,
143 0x3c,
144 0xea,
145 0x70,
146 0x6e,
147 0xa8,
148 0xb8,
149 0xe6,
150 0xce,
151 0xa0,
152 0xc8,
153 0x8c,
154 0x7c,
155 0x54,
156 0xfc,
157 0xec,
158 0xdc,
159 0xa4,
160};
161
162static u8 char2ledval(char c)
163{
164 if (isdigit(c))
165 return ledval_num[c - '0'];
166 else if (isalpha(c))
167 return ledval_alpha[toupper(c) - 'A'];
168
169 return 0;
170}
171
172void led_puts(const char *s)
173{
174 int i;
175 u32 val = 0;
176
177 if (!support_card_found)
178 return;
179
180 if (!s)
181 return;
182
183 for (i = 0; i < 4; i++) {
184 val <<= 8;
185 val |= char2ledval(*s);
186 if (*s != '\0')
187 s++;
188 }
189
190 writel(~val, support_card_base + LED_OFFSET);
191}
192