mach-mxs.c (10619B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * Copyright 2012 Freescale Semiconductor, Inc. 4 * Copyright 2012 Linaro Ltd. 5 */ 6 7#include <linux/clk.h> 8#include <linux/clk/mxs.h> 9#include <linux/clkdev.h> 10#include <linux/delay.h> 11#include <linux/err.h> 12#include <linux/gpio.h> 13#include <linux/init.h> 14#include <linux/irqchip/mxs.h> 15#include <linux/reboot.h> 16#include <linux/micrel_phy.h> 17#include <linux/of_address.h> 18#include <linux/of_platform.h> 19#include <linux/phy.h> 20#include <linux/pinctrl/consumer.h> 21#include <linux/sys_soc.h> 22#include <asm/mach/arch.h> 23#include <asm/mach/map.h> 24#include <asm/mach/time.h> 25#include <asm/system_info.h> 26#include <asm/system_misc.h> 27 28#include "pm.h" 29 30/* MXS DIGCTL SAIF CLKMUX */ 31#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT 0x0 32#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT 0x1 33#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 34#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 35 36#define HW_DIGCTL_CHIPID 0x310 37#define HW_DIGCTL_CHIPID_MASK (0xffff << 16) 38#define HW_DIGCTL_REV_MASK 0xff 39#define HW_DIGCTL_CHIPID_MX23 (0x3780 << 16) 40#define HW_DIGCTL_CHIPID_MX28 (0x2800 << 16) 41 42#define MXS_CHIP_REVISION_1_0 0x10 43#define MXS_CHIP_REVISION_1_1 0x11 44#define MXS_CHIP_REVISION_1_2 0x12 45#define MXS_CHIP_REVISION_1_3 0x13 46#define MXS_CHIP_REVISION_1_4 0x14 47#define MXS_CHIP_REV_UNKNOWN 0xff 48 49#define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) 50 51#define MXS_SET_ADDR 0x4 52#define MXS_CLR_ADDR 0x8 53#define MXS_TOG_ADDR 0xc 54 55#define HW_OCOTP_OPS2 19 /* offset 0x150 */ 56#define HW_OCOTP_OPS3 20 /* offset 0x160 */ 57 58static u32 chipid; 59static u32 socid; 60 61static void __iomem *reset_addr; 62 63static inline void __mxs_setl(u32 mask, void __iomem *reg) 64{ 65 __raw_writel(mask, reg + MXS_SET_ADDR); 66} 67 68static inline void __mxs_clrl(u32 mask, void __iomem *reg) 69{ 70 __raw_writel(mask, reg + MXS_CLR_ADDR); 71} 72 73static inline void __mxs_togl(u32 mask, void __iomem *reg) 74{ 75 __raw_writel(mask, reg + MXS_TOG_ADDR); 76} 77 78#define OCOTP_WORD_OFFSET 0x20 79#define OCOTP_WORD_COUNT 0x20 80 81#define BM_OCOTP_CTRL_BUSY (1 << 8) 82#define BM_OCOTP_CTRL_ERROR (1 << 9) 83#define BM_OCOTP_CTRL_RD_BANK_OPEN (1 << 12) 84 85static DEFINE_MUTEX(ocotp_mutex); 86static u32 ocotp_words[OCOTP_WORD_COUNT]; 87 88static const u32 *mxs_get_ocotp(void) 89{ 90 struct device_node *np; 91 void __iomem *ocotp_base; 92 int timeout = 0x400; 93 size_t i; 94 static int once; 95 96 if (once) 97 return ocotp_words; 98 99 np = of_find_compatible_node(NULL, NULL, "fsl,ocotp"); 100 ocotp_base = of_iomap(np, 0); 101 WARN_ON(!ocotp_base); 102 103 mutex_lock(&ocotp_mutex); 104 105 /* 106 * clk_enable(hbus_clk) for ocotp can be skipped 107 * as it must be on when system is running. 108 */ 109 110 /* try to clear ERROR bit */ 111 __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base); 112 113 /* check both BUSY and ERROR cleared */ 114 while ((__raw_readl(ocotp_base) & 115 (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout) 116 cpu_relax(); 117 118 if (unlikely(!timeout)) 119 goto error_unlock; 120 121 /* open OCOTP banks for read */ 122 __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base); 123 124 /* approximately wait 32 hclk cycles */ 125 udelay(1); 126 127 /* poll BUSY bit becoming cleared */ 128 timeout = 0x400; 129 while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout) 130 cpu_relax(); 131 132 if (unlikely(!timeout)) 133 goto error_unlock; 134 135 for (i = 0; i < OCOTP_WORD_COUNT; i++) 136 ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET + 137 i * 0x10); 138 139 /* close banks for power saving */ 140 __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base); 141 142 once = 1; 143 144 mutex_unlock(&ocotp_mutex); 145 146 return ocotp_words; 147 148error_unlock: 149 mutex_unlock(&ocotp_mutex); 150 pr_err("%s: timeout in reading OCOTP\n", __func__); 151 return NULL; 152} 153 154enum mac_oui { 155 OUI_FSL, 156 OUI_DENX, 157 OUI_CRYSTALFONTZ, 158 OUI_I2SE, 159 OUI_ARMADEUS, 160}; 161 162static void __init update_fec_mac_prop(enum mac_oui oui) 163{ 164 struct device_node *np, *from = NULL; 165 struct property *newmac; 166 const u32 *ocotp = mxs_get_ocotp(); 167 u8 *macaddr; 168 u32 val; 169 int i; 170 171 for (i = 0; i < 2; i++) { 172 np = of_find_compatible_node(from, NULL, "fsl,imx28-fec"); 173 if (!np) 174 return; 175 176 from = np; 177 178 if (of_get_property(np, "local-mac-address", NULL)) 179 continue; 180 181 newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); 182 if (!newmac) 183 return; 184 newmac->value = newmac + 1; 185 newmac->length = 6; 186 187 newmac->name = kstrdup("local-mac-address", GFP_KERNEL); 188 if (!newmac->name) { 189 kfree(newmac); 190 return; 191 } 192 193 /* 194 * OCOTP only stores the last 4 octets for each mac address, 195 * so hard-code OUI here. 196 */ 197 macaddr = newmac->value; 198 switch (oui) { 199 case OUI_FSL: 200 macaddr[0] = 0x00; 201 macaddr[1] = 0x04; 202 macaddr[2] = 0x9f; 203 break; 204 case OUI_DENX: 205 macaddr[0] = 0xc0; 206 macaddr[1] = 0xe5; 207 macaddr[2] = 0x4e; 208 break; 209 case OUI_CRYSTALFONTZ: 210 macaddr[0] = 0x58; 211 macaddr[1] = 0xb9; 212 macaddr[2] = 0xe1; 213 break; 214 case OUI_I2SE: 215 macaddr[0] = 0x00; 216 macaddr[1] = 0x01; 217 macaddr[2] = 0x87; 218 break; 219 case OUI_ARMADEUS: 220 macaddr[0] = 0x00; 221 macaddr[1] = 0x1e; 222 macaddr[2] = 0xac; 223 break; 224 } 225 val = ocotp[i]; 226 macaddr[3] = (val >> 16) & 0xff; 227 macaddr[4] = (val >> 8) & 0xff; 228 macaddr[5] = (val >> 0) & 0xff; 229 230 of_update_property(np, newmac); 231 } 232} 233 234static inline void enable_clk_enet_out(void) 235{ 236 struct clk *clk = clk_get_sys("enet_out", NULL); 237 238 if (!IS_ERR(clk)) 239 clk_prepare_enable(clk); 240} 241 242static void __init imx28_evk_init(void) 243{ 244 update_fec_mac_prop(OUI_FSL); 245 246 mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); 247} 248 249static void __init imx28_apf28_init(void) 250{ 251 update_fec_mac_prop(OUI_ARMADEUS); 252} 253 254static int apx4devkit_phy_fixup(struct phy_device *phy) 255{ 256 phy->dev_flags |= MICREL_PHY_50MHZ_CLK; 257 return 0; 258} 259 260static void __init apx4devkit_init(void) 261{ 262 enable_clk_enet_out(); 263 264 if (IS_BUILTIN(CONFIG_PHYLIB)) 265 phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK, 266 apx4devkit_phy_fixup); 267} 268 269static void __init crystalfontz_init(void) 270{ 271 update_fec_mac_prop(OUI_CRYSTALFONTZ); 272} 273 274static void __init duckbill_init(void) 275{ 276 update_fec_mac_prop(OUI_I2SE); 277} 278 279static void __init m28cu3_init(void) 280{ 281 update_fec_mac_prop(OUI_DENX); 282} 283 284static const char __init *mxs_get_soc_id(void) 285{ 286 struct device_node *np; 287 void __iomem *digctl_base; 288 289 np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl"); 290 digctl_base = of_iomap(np, 0); 291 WARN_ON(!digctl_base); 292 293 chipid = readl(digctl_base + HW_DIGCTL_CHIPID); 294 socid = chipid & HW_DIGCTL_CHIPID_MASK; 295 296 iounmap(digctl_base); 297 of_node_put(np); 298 299 switch (socid) { 300 case HW_DIGCTL_CHIPID_MX23: 301 return "i.MX23"; 302 case HW_DIGCTL_CHIPID_MX28: 303 return "i.MX28"; 304 default: 305 return "Unknown"; 306 } 307} 308 309static u32 __init mxs_get_cpu_rev(void) 310{ 311 u32 rev = chipid & HW_DIGCTL_REV_MASK; 312 313 switch (socid) { 314 case HW_DIGCTL_CHIPID_MX23: 315 switch (rev) { 316 case 0x0: 317 return MXS_CHIP_REVISION_1_0; 318 case 0x1: 319 return MXS_CHIP_REVISION_1_1; 320 case 0x2: 321 return MXS_CHIP_REVISION_1_2; 322 case 0x3: 323 return MXS_CHIP_REVISION_1_3; 324 case 0x4: 325 return MXS_CHIP_REVISION_1_4; 326 default: 327 return MXS_CHIP_REV_UNKNOWN; 328 } 329 case HW_DIGCTL_CHIPID_MX28: 330 switch (rev) { 331 case 0x0: 332 return MXS_CHIP_REVISION_1_1; 333 case 0x1: 334 return MXS_CHIP_REVISION_1_2; 335 default: 336 return MXS_CHIP_REV_UNKNOWN; 337 } 338 default: 339 return MXS_CHIP_REV_UNKNOWN; 340 } 341} 342 343static const char __init *mxs_get_revision(void) 344{ 345 u32 rev = mxs_get_cpu_rev(); 346 347 if (rev != MXS_CHIP_REV_UNKNOWN) 348 return kasprintf(GFP_KERNEL, "%d.%d", (rev >> 4) & 0xf, 349 rev & 0xf); 350 else 351 return kasprintf(GFP_KERNEL, "%s", "Unknown"); 352} 353 354#define MX23_CLKCTRL_RESET_OFFSET 0x120 355#define MX28_CLKCTRL_RESET_OFFSET 0x1e0 356 357static int __init mxs_restart_init(void) 358{ 359 struct device_node *np; 360 361 np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl"); 362 reset_addr = of_iomap(np, 0); 363 if (!reset_addr) 364 return -ENODEV; 365 366 if (of_device_is_compatible(np, "fsl,imx23-clkctrl")) 367 reset_addr += MX23_CLKCTRL_RESET_OFFSET; 368 else 369 reset_addr += MX28_CLKCTRL_RESET_OFFSET; 370 of_node_put(np); 371 372 return 0; 373} 374 375static void __init eukrea_mbmx283lc_init(void) 376{ 377 mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); 378} 379 380static void __init mxs_machine_init(void) 381{ 382 struct device_node *root; 383 struct device *parent; 384 struct soc_device *soc_dev; 385 struct soc_device_attribute *soc_dev_attr; 386 u64 soc_uid = 0; 387 const u32 *ocotp = mxs_get_ocotp(); 388 int ret; 389 390 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 391 if (!soc_dev_attr) 392 return; 393 394 root = of_find_node_by_path("/"); 395 ret = of_property_read_string(root, "model", &soc_dev_attr->machine); 396 if (ret) 397 return; 398 399 soc_dev_attr->family = "Freescale MXS Family"; 400 soc_dev_attr->soc_id = mxs_get_soc_id(); 401 soc_dev_attr->revision = mxs_get_revision(); 402 403 if (socid == HW_DIGCTL_CHIPID_MX23) { 404 soc_uid = system_serial_low = ocotp[HW_OCOTP_OPS3]; 405 } else if (socid == HW_DIGCTL_CHIPID_MX28) { 406 soc_uid = system_serial_high = ocotp[HW_OCOTP_OPS2]; 407 soc_uid <<= 32; 408 system_serial_low = ocotp[HW_OCOTP_OPS3]; 409 soc_uid |= system_serial_low; 410 } 411 412 if (soc_uid) 413 soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid); 414 415 soc_dev = soc_device_register(soc_dev_attr); 416 if (IS_ERR(soc_dev)) { 417 kfree(soc_dev_attr->serial_number); 418 kfree(soc_dev_attr->revision); 419 kfree(soc_dev_attr); 420 return; 421 } 422 423 parent = soc_device_to_device(soc_dev); 424 425 if (of_machine_is_compatible("fsl,imx28-evk")) 426 imx28_evk_init(); 427 if (of_machine_is_compatible("armadeus,imx28-apf28")) 428 imx28_apf28_init(); 429 else if (of_machine_is_compatible("bluegiga,apx4devkit")) 430 apx4devkit_init(); 431 else if (of_machine_is_compatible("crystalfontz,cfa10036")) 432 crystalfontz_init(); 433 else if (of_machine_is_compatible("eukrea,mbmx283lc")) 434 eukrea_mbmx283lc_init(); 435 else if (of_machine_is_compatible("i2se,duckbill") || 436 of_machine_is_compatible("i2se,duckbill-2")) 437 duckbill_init(); 438 else if (of_machine_is_compatible("msr,m28cu3")) 439 m28cu3_init(); 440 441 of_platform_default_populate(NULL, NULL, parent); 442 443 mxs_restart_init(); 444} 445 446#define MXS_CLKCTRL_RESET_CHIP (1 << 1) 447 448/* 449 * Reset the system. It is called by machine_restart(). 450 */ 451static void mxs_restart(enum reboot_mode mode, const char *cmd) 452{ 453 if (reset_addr) { 454 /* reset the chip */ 455 __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr); 456 457 pr_err("Failed to assert the chip reset\n"); 458 459 /* Delay to allow the serial port to show the message */ 460 mdelay(50); 461 } 462 463 /* We'll take a jump through zero as a poor second */ 464 soft_restart(0); 465} 466 467static const char *const mxs_dt_compat[] __initconst = { 468 "fsl,imx28", 469 "fsl,imx23", 470 NULL, 471}; 472 473DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") 474 .handle_irq = icoll_handle_irq, 475 .init_machine = mxs_machine_init, 476 .init_late = mxs_pm_init, 477 .dt_compat = mxs_dt_compat, 478 .restart = mxs_restart, 479MACHINE_END