spi: zynqmp_gqspi: fix set_speed bug on multiple runs
[platform/kernel/u-boot.git] / board / microchip / mpfs_icicle / mpfs_icicle.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2019 Microchip Technology Inc.
4  * Padmarao Begari <padmarao.begari@microchip.com>
5  */
6
7 #include <common.h>
8 #include <dm.h>
9 #include <env.h>
10 #include <init.h>
11 #include <asm/io.h>
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 #define MPFS_SYSREG_SOFT_RESET          ((unsigned int *)0x20002088)
16 #define MPFS_SYS_SERVICE_CR             ((unsigned int *)0x37020050)
17 #define MPFS_SYS_SERVICE_SR             ((unsigned int *)0x37020054)
18 #define MPFS_SYS_SERVICE_MAILBOX        ((unsigned char *)0x37020800)
19
20 #define PERIPH_RESET_VALUE              0x1e8u
21 #define SERVICE_CR_REQ                  0x1u
22 #define SERVICE_SR_BUSY                 0x2u
23
24 static void read_device_serial_number(u8 *response, u8 response_size)
25 {
26         u8 idx;
27         u8 *response_buf;
28         unsigned int val;
29
30         response_buf = (u8 *)response;
31
32         writel(SERVICE_CR_REQ, MPFS_SYS_SERVICE_CR);
33         /*
34          * REQ bit will remain set till the system controller starts
35          * processing.
36          */
37         do {
38                 val = readl(MPFS_SYS_SERVICE_CR);
39         } while (SERVICE_CR_REQ == (val & SERVICE_CR_REQ));
40
41         /*
42          * Once system controller starts processing the busy bit will
43          * go high and service is completed when busy bit is gone low
44          */
45         do {
46                 val = readl(MPFS_SYS_SERVICE_SR);
47         } while (SERVICE_SR_BUSY == (val & SERVICE_SR_BUSY));
48
49         for (idx = 0; idx < response_size; idx++)
50                 response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + idx);
51 }
52
53 int board_init(void)
54 {
55         /* For now nothing to do here. */
56
57         return 0;
58 }
59
60 int board_early_init_f(void)
61 {
62         unsigned int val;
63
64         /* Reset uart, mmc peripheral */
65         val = readl(MPFS_SYSREG_SOFT_RESET);
66         val = (val & ~(PERIPH_RESET_VALUE));
67         writel(val, MPFS_SYSREG_SOFT_RESET);
68
69         return 0;
70 }
71
72 int board_late_init(void)
73 {
74         u32 ret;
75         u32 node;
76         u8 idx;
77         u8 device_serial_number[16] = { 0 };
78         unsigned char mac_addr[6];
79         char icicle_mac_addr[20];
80         void *blob = (void *)gd->fdt_blob;
81
82         node = fdt_path_offset(blob, "ethernet0");
83         if (node < 0) {
84                 printf("No ethernet0 path offset\n");
85                 return -ENODEV;
86         }
87
88         ret = fdtdec_get_byte_array(blob, node, "local-mac-address", mac_addr, 6);
89         if (ret) {
90                 printf("No local-mac-address property\n");
91                 return -EINVAL;
92         }
93
94         read_device_serial_number(device_serial_number, 16);
95
96         /* Update MAC address with device serial number */
97         mac_addr[0] = 0x00;
98         mac_addr[1] = 0x04;
99         mac_addr[2] = 0xA3;
100         mac_addr[3] = device_serial_number[2];
101         mac_addr[4] = device_serial_number[1];
102         mac_addr[5] = device_serial_number[0];
103
104         ret = fdt_setprop(blob, node, "local-mac-address", mac_addr, 6);
105         if (ret) {
106                 printf("Error setting local-mac-address property\n");
107                 return -ENODEV;
108         }
109
110         icicle_mac_addr[0] = '[';
111
112         sprintf(&icicle_mac_addr[1], "%pM", mac_addr);
113
114         icicle_mac_addr[18] = ']';
115         icicle_mac_addr[19] = '\0';
116
117         for (idx = 0; idx < 20; idx++) {
118                 if (icicle_mac_addr[idx] == ':')
119                         icicle_mac_addr[idx] = ' ';
120         }
121         env_set("icicle_mac_addr", icicle_mac_addr);
122
123         return 0;
124 }