1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * arch/arm/mach-lpc32xx/common.c |
4 | * |
5 | * Author: Kevin Wells <kevin.wells@nxp.com> |
6 | * |
7 | * Copyright (C) 2010 NXP Semiconductors |
8 | */ |
9 | |
10 | #include <linux/init.h> |
11 | #include <linux/soc/nxp/lpc32xx-misc.h> |
12 | |
13 | #include <asm/mach/map.h> |
14 | #include <asm/system_info.h> |
15 | |
16 | #include "lpc32xx.h" |
17 | #include "common.h" |
18 | |
19 | /* |
20 | * Returns the unique ID for the device |
21 | */ |
22 | void lpc32xx_get_uid(u32 devid[4]) |
23 | { |
24 | int i; |
25 | |
26 | for (i = 0; i < 4; i++) |
27 | devid[i] = __raw_readl(LPC32XX_CLKPWR_DEVID(i << 2)); |
28 | } |
29 | |
30 | /* |
31 | * Detects and returns IRAM size for the device variation |
32 | */ |
33 | #define LPC32XX_IRAM_BANK_SIZE SZ_128K |
34 | static u32 iram_size; |
35 | u32 lpc32xx_return_iram(void __iomem **mapbase, dma_addr_t *dmaaddr) |
36 | { |
37 | if (iram_size == 0) { |
38 | u32 savedval1, savedval2; |
39 | void __iomem *iramptr1, *iramptr2; |
40 | |
41 | iramptr1 = io_p2v(LPC32XX_IRAM_BASE); |
42 | iramptr2 = io_p2v(LPC32XX_IRAM_BASE + LPC32XX_IRAM_BANK_SIZE); |
43 | savedval1 = __raw_readl(addr: iramptr1); |
44 | savedval2 = __raw_readl(addr: iramptr2); |
45 | |
46 | if (savedval1 == savedval2) { |
47 | __raw_writel(val: savedval2 + 1, addr: iramptr2); |
48 | if (__raw_readl(addr: iramptr1) == savedval2 + 1) |
49 | iram_size = LPC32XX_IRAM_BANK_SIZE; |
50 | else |
51 | iram_size = LPC32XX_IRAM_BANK_SIZE * 2; |
52 | __raw_writel(val: savedval2, addr: iramptr2); |
53 | } else |
54 | iram_size = LPC32XX_IRAM_BANK_SIZE * 2; |
55 | } |
56 | if (dmaaddr) |
57 | *dmaaddr = LPC32XX_IRAM_BASE; |
58 | if (mapbase) |
59 | *mapbase = io_p2v(LPC32XX_IRAM_BASE); |
60 | |
61 | return iram_size; |
62 | } |
63 | EXPORT_SYMBOL_GPL(lpc32xx_return_iram); |
64 | |
65 | void lpc32xx_set_phy_interface_mode(phy_interface_t mode) |
66 | { |
67 | u32 tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL); |
68 | tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK; |
69 | if (mode == PHY_INTERFACE_MODE_MII) |
70 | tmp |= LPC32XX_CLKPWR_MACCTRL_USE_MII_PINS; |
71 | else |
72 | tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS; |
73 | __raw_writel(val: tmp, LPC32XX_CLKPWR_MACCLK_CTRL); |
74 | } |
75 | EXPORT_SYMBOL_GPL(lpc32xx_set_phy_interface_mode); |
76 | |
77 | static struct map_desc lpc32xx_io_desc[] __initdata = { |
78 | { |
79 | .virtual = (unsigned long)IO_ADDRESS(LPC32XX_AHB0_START), |
80 | .pfn = __phys_to_pfn(LPC32XX_AHB0_START), |
81 | .length = LPC32XX_AHB0_SIZE, |
82 | .type = MT_DEVICE |
83 | }, |
84 | { |
85 | .virtual = (unsigned long)IO_ADDRESS(LPC32XX_AHB1_START), |
86 | .pfn = __phys_to_pfn(LPC32XX_AHB1_START), |
87 | .length = LPC32XX_AHB1_SIZE, |
88 | .type = MT_DEVICE |
89 | }, |
90 | { |
91 | .virtual = (unsigned long)IO_ADDRESS(LPC32XX_FABAPB_START), |
92 | .pfn = __phys_to_pfn(LPC32XX_FABAPB_START), |
93 | .length = LPC32XX_FABAPB_SIZE, |
94 | .type = MT_DEVICE |
95 | }, |
96 | { |
97 | .virtual = (unsigned long)IO_ADDRESS(LPC32XX_IRAM_BASE), |
98 | .pfn = __phys_to_pfn(LPC32XX_IRAM_BASE), |
99 | .length = (LPC32XX_IRAM_BANK_SIZE * 2), |
100 | .type = MT_DEVICE |
101 | }, |
102 | }; |
103 | |
104 | void __init lpc32xx_map_io(void) |
105 | { |
106 | iotable_init(lpc32xx_io_desc, ARRAY_SIZE(lpc32xx_io_desc)); |
107 | } |
108 | |
109 | static int __init lpc32xx_check_uid(void) |
110 | { |
111 | u32 uid[4]; |
112 | |
113 | lpc32xx_get_uid(devid: uid); |
114 | |
115 | printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n" , |
116 | uid[3], uid[2], uid[1], uid[0]); |
117 | |
118 | if (!system_serial_low && !system_serial_high) { |
119 | system_serial_low = uid[0]; |
120 | system_serial_high = uid[1]; |
121 | } |
122 | |
123 | return 1; |
124 | } |
125 | arch_initcall(lpc32xx_check_uid); |
126 | |