19de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 29de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Device State Control Registers driver 39de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 49de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Copyright (C) 2011 Texas Instruments Incorporated 59de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Author: Mark Salter <msalter@redhat.com> 69de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 79de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * This program is free software; you can redistribute it and/or modify 89de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * it under the terms of the GNU General Public License version 2 as 99de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * published by the Free Software Foundation. 109de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 119de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 129de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 139de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * The Device State Control Registers (DSCR) provide SoC level control over 149de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * a number of peripherals. Details vary considerably among the various SoC 159de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * parts. In general, the DSCR block will provide one or more configuration 169de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * registers often protected by a lock register. One or more key values must 179de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * be written to a lock register in order to unlock the configuration register. 189de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * The configuration register may be used to enable (and disable in some 199de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * cases) SoC pin drivers, peripheral clock sources (internal or pin), etc. 209de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * In some cases, a configuration register is write once or the individual 219de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * bits are write once. That is, you may be able to enable a device, but 229de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * will not be able to disable it. 239de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 249de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * In addition to device configuration, the DSCR block may provide registers 259de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * which are used to reset SoC peripherals, provide device ID information, 269de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * provide MAC addresses, and other miscellaneous functions. 279de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 289de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 299de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <linux/of.h> 309de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <linux/of_address.h> 319de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <linux/of_platform.h> 329de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <linux/module.h> 339de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <linux/io.h> 349de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <linux/delay.h> 359de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <asm/soc.h> 369de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#include <asm/dscr.h> 379de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 389de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#define MAX_DEVSTATE_IDS 32 399de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#define MAX_DEVCTL_REGS 8 409de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#define MAX_DEVSTAT_REGS 8 419de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#define MAX_LOCKED_REGS 4 429de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter#define MAX_SOC_EMACS 2 439de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 449de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct rmii_reset_reg { 459de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 reg; 469de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 mask; 479de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 489de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 499de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 509de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Some registerd may be locked. In order to write to these 519de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * registers, the key value must first be written to the lockreg. 529de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 539de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct locked_reg { 549de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 reg; /* offset from base */ 559de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 lockreg; /* offset from base */ 569de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 key; /* unlock key */ 579de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 589de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 599de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 609de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * This describes a contiguous area of like control bits used to enable/disable 619de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * SoC devices. Each controllable device is given an ID which is used by the 629de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * individual device drivers to control the device state. These IDs start at 639de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * zero and are assigned sequentially to the control bitfield ranges described 649de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * by this structure. 659de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 669de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct devstate_ctl_reg { 679de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 reg; /* register holding the control bits */ 689de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 start_id; /* start id of this range */ 699de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 num_ids; /* number of devices in this range */ 709de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 enable_only; /* bits are write-once to enable only */ 719de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 enable; /* value used to enable device */ 729de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 disable; /* value used to disable device */ 739de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 shift; /* starting (rightmost) bit in range */ 749de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 nbits; /* number of bits per device */ 759de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 769de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 779de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 789de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 799de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * This describes a region of status bits indicating the state of 809de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * various devices. This is used internally to wait for status 819de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * change completion when enabling/disabling a device. Status is 829de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * optional and not all device controls will have a corresponding 839de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * status. 849de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 859de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct devstate_stat_reg { 869de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 reg; /* register holding the status bits */ 879de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 start_id; /* start id of this range */ 889de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 num_ids; /* number of devices in this range */ 899de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 enable; /* value indicating enabled state */ 909de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 disable; /* value indicating disabled state */ 919de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 shift; /* starting (rightmost) bit in range */ 929de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u8 nbits; /* number of bits per device */ 939de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 949de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 959de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct devstate_info { 969de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_ctl_reg *ctl; 979de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_stat_reg *stat; 989de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 999de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1009de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* These are callbacks to SOC-specific code. */ 1019de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct dscr_ops { 1029de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void (*init)(struct device_node *node); 1039de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 1049de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1059de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstruct dscr_regs { 1069de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter spinlock_t lock; 1079de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base; 1089de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 kick_reg[2]; 1099de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 kick_key[2]; 1109de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct locked_reg locked[MAX_LOCKED_REGS]; 1119de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_info devstate_info[MAX_DEVSTATE_IDS]; 1129de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct rmii_reset_reg rmii_resets[MAX_SOC_EMACS]; 1139de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_ctl_reg devctl[MAX_DEVCTL_REGS]; 1149de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_stat_reg devstat[MAX_DEVSTAT_REGS]; 1159de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 1169de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1179de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic struct dscr_regs dscr; 1189de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1199de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic struct locked_reg *find_locked_reg(u32 reg) 1209de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 1219de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int i; 1229de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1239de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (i = 0; i < MAX_LOCKED_REGS; i++) 1249de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (dscr.locked[i].key && reg == dscr.locked[i].reg) 1259de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return &dscr.locked[i]; 1269de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return NULL; 1279de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 1289de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1299de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 1309de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Write to a register with one lock 1319de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 1329de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void dscr_write_locked1(u32 reg, u32 val, 1339de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 lock, u32 key) 1349de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 1359de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *reg_addr = dscr.base + reg; 1369de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *lock_addr = dscr.base + lock; 1379de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1389de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* 1399de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * For some registers, the lock is relocked after a short number 1409de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * of cycles. We have to put the lock write and register write in 1419de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * the same fetch packet to meet this timing. The .align ensures 1429de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * the two stw instructions are in the same fetch packet. 1439de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 1449de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter asm volatile ("b .s2 0f\n" 1459de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter "nop 5\n" 1469de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter " .align 5\n" 1479de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter "0:\n" 1489de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter "stw .D1T2 %3,*%2\n" 1499de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter "stw .D1T2 %1,*%0\n" 1509de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter : 1519de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter : "a"(reg_addr), "b"(val), "a"(lock_addr), "b"(key) 1529de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ); 1539de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1549de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* in case the hw doesn't reset the lock */ 1559de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(0, lock_addr); 1569de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 1579de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1589de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 1599de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Write to a register protected by two lock registers 1609de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 1619de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void dscr_write_locked2(u32 reg, u32 val, 1629de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 lock0, u32 key0, 1639de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 lock1, u32 key1) 1649de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 1659de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(key0, dscr.base + lock0); 1669de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(key1, dscr.base + lock1); 1679de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(val, dscr.base + reg); 1689de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(0, dscr.base + lock0); 1699de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(0, dscr.base + lock1); 1709de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 1719de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1729de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void dscr_write(u32 reg, u32 val) 1739de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 1749de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct locked_reg *lock; 1759de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1769de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter lock = find_locked_reg(reg); 1779de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (lock) 1789de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_write_locked1(reg, val, lock->lockreg, lock->key); 1799de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter else if (dscr.kick_key[0]) 1809de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_write_locked2(reg, val, dscr.kick_reg[0], dscr.kick_key[0], 1819de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.kick_reg[1], dscr.kick_key[1]); 1829de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter else 1839de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter soc_writel(val, dscr.base + reg); 1849de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 1859de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1869de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1879de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 1889de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Drivers can use this interface to enable/disable SoC IP blocks. 1899de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 1909de98fb4ec4c91597feedc521120c16fca54a5b6Mark Saltervoid dscr_set_devstate(int id, enum dscr_devstate_t state) 1919de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 1929de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_ctl_reg *ctl; 1939de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_stat_reg *stat; 1949de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_info *info; 1959de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 ctl_val, val; 1969de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int ctl_shift, ctl_mask; 1979de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter unsigned long flags; 1989de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 1999de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!dscr.base) 2009de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2019de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2029de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (id < 0 || id >= MAX_DEVSTATE_IDS) 2039de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2049de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2059de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter info = &dscr.devstate_info[id]; 2069de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl = info->ctl; 2079de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter stat = info->stat; 2089de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2099de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (ctl == NULL) 2109de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2119de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2129de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_shift = ctl->shift + ctl->nbits * (id - ctl->start_id); 2139de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_mask = ((1 << ctl->nbits) - 1) << ctl_shift; 2149de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2159de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter switch (state) { 2169de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter case DSCR_DEVSTATE_ENABLED: 2179de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_val = ctl->enable << ctl_shift; 2189de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter break; 2199de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter case DSCR_DEVSTATE_DISABLED: 2209de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (ctl->enable_only) 2219de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2229de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_val = ctl->disable << ctl_shift; 2239de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter break; 2249de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter default: 2259de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2269de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 2279de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2289de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter spin_lock_irqsave(&dscr.lock, flags); 2299de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2309de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val = soc_readl(dscr.base + ctl->reg); 2319de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val &= ~ctl_mask; 2329de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val |= ctl_val; 2339de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2349de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_write(ctl->reg, val); 2359de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2369de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter spin_unlock_irqrestore(&dscr.lock, flags); 2379de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2389de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!stat) 2399de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2409de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2419de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_shift = stat->shift + stat->nbits * (id - stat->start_id); 2429de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2439de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (state == DSCR_DEVSTATE_ENABLED) 2449de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_val = stat->enable; 2459de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter else 2469de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter ctl_val = stat->disable; 2479de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2489de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter do { 2499de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val = soc_readl(dscr.base + stat->reg); 2509de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val >>= ctl_shift; 2519de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val &= ((1 << stat->nbits) - 1); 2529de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } while (val != ctl_val); 2539de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 2549de98fb4ec4c91597feedc521120c16fca54a5b6Mark SalterEXPORT_SYMBOL(dscr_set_devstate); 2559de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2569de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 2579de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Drivers can use this to reset RMII module. 2589de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 2599de98fb4ec4c91597feedc521120c16fca54a5b6Mark Saltervoid dscr_rmii_reset(int id, int assert) 2609de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 2619de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct rmii_reset_reg *r; 2629de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter unsigned long flags; 2639de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 val; 2649de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2659de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (id < 0 || id >= MAX_SOC_EMACS) 2669de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2679de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2689de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r = &dscr.rmii_resets[id]; 2699de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (r->mask == 0) 2709de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 2719de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2729de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter spin_lock_irqsave(&dscr.lock, flags); 2739de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2749de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter val = soc_readl(dscr.base + r->reg); 2759de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (assert) 2769de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_write(r->reg, val | r->mask); 2779de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter else 2789de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_write(r->reg, val & ~(r->mask)); 2799de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2809de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter spin_unlock_irqrestore(&dscr.lock, flags); 2819de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 2829de98fb4ec4c91597feedc521120c16fca54a5b6Mark SalterEXPORT_SYMBOL(dscr_rmii_reset); 2839de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2849de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_devstat(struct device_node *node, 2859de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 2869de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 2879de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 val; 2889de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int err; 2899de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2909de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter err = of_property_read_u32_array(node, "ti,dscr-devstat", &val, 1); 2919de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!err) 2929de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter c6x_devstat = soc_readl(base + val); 2939de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter printk(KERN_INFO "DEVSTAT: %08x\n", c6x_devstat); 2949de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 2959de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 2969de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_silicon_rev(struct device_node *node, 2979de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 2989de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 2999de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 vals[3]; 3009de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int err; 3019de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3029de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter err = of_property_read_u32_array(node, "ti,dscr-silicon-rev", vals, 3); 3039de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!err) { 3049de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter c6x_silicon_rev = soc_readl(base + vals[0]); 3059de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter c6x_silicon_rev >>= vals[1]; 3069de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter c6x_silicon_rev &= vals[2]; 3079de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 3089de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 3099de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3109de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 3119de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Some SoCs will have a pair of fuse registers which hold 3129de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * an ethernet MAC address. The "ti,dscr-mac-fuse-regs" 3139de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * property is a mapping from fuse register bytes to MAC 3149de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * address bytes. The expected format is: 3159de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 3169de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * ti,dscr-mac-fuse-regs = <reg0 b3 b2 b1 b0 3179de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * reg1 b3 b2 b1 b0> 3189de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 3199de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * reg0 and reg1 are the offsets of the two fuse registers. 3209de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * b3-b0 positionally represent bytes within the fuse register. 3219de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * b3 is the most significant byte and b0 is the least. 3229de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Allowable values for b3-b0 are: 3239de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 3249de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 0 = fuse register byte not used in MAC address 3259de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 1-6 = index+1 into c6x_fuse_mac[] 3269de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 3279de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_mac_fuse(struct device_node *node, 3289de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 3299de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 3309de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 vals[10], fuse; 3319de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int f, i, j, err; 3329de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3339de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter err = of_property_read_u32_array(node, "ti,dscr-mac-fuse-regs", 3349de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter vals, 10); 3359de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (err) 3369de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 3379de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3389de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (f = 0; f < 2; f++) { 3399de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter fuse = soc_readl(base + vals[f * 5]); 3409de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (j = (f * 5) + 1, i = 24; i >= 0; i -= 8, j++) 3419de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (vals[j] && vals[j] <= 6) 3429de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter c6x_fuse_mac[vals[j] - 1] = fuse >> i; 3439de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 3449de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 3459de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3469de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_rmii_resets(struct device_node *node, 3479de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 3489de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 3499de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter const __be32 *p; 3509de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int i, size; 3519de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3529de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* look for RMII reset registers */ 3539de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter p = of_get_property(node, "ti,dscr-rmii-resets", &size); 3549de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (p) { 3559de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* parse all the reg/mask pairs we can handle */ 3569de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size /= (sizeof(*p) * 2); 3579de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (size > MAX_SOC_EMACS) 3589de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size = MAX_SOC_EMACS; 3599de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3609de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (i = 0; i < size; i++) { 3619de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.rmii_resets[i].reg = be32_to_cpup(p++); 3629de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.rmii_resets[i].mask = be32_to_cpup(p++); 3639de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 3649de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 3659de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 3669de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3679de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3689de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_privperm(struct device_node *node, 3699de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 3709de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 3719de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 vals[2]; 3729de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int err; 3739de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3749de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter err = of_property_read_u32_array(node, "ti,dscr-privperm", vals, 2); 3759de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (err) 3769de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 3779de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_write(vals[0], vals[1]); 3789de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 3799de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 3809de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 3819de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * SoCs may have "locked" DSCR registers which can only be written 3829de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * to only after writing a key value to a lock registers. These 3839de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * regisers can be described with the "ti,dscr-locked-regs" property. 3849de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * This property provides a list of register descriptions with each 3859de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * description consisting of three values. 3869de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 3879de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * ti,dscr-locked-regs = <reg0 lockreg0 key0 3889de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * ... 3899de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * regN lockregN keyN>; 3909de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 3919de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * reg is the offset of the locked register 3929de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * lockreg is the offset of the lock register 3939de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * key is the unlock key written to lockreg 3949de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 3959de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 3969de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_locked_regs(struct device_node *node, 3979de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 3989de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 3999de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct locked_reg *r; 4009de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter const __be32 *p; 4019de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int i, size; 4029de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4039de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter p = of_get_property(node, "ti,dscr-locked-regs", &size); 4049de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (p) { 4059de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* parse all the register descriptions we can handle */ 4069de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size /= (sizeof(*p) * 3); 4079de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (size > MAX_LOCKED_REGS) 4089de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size = MAX_LOCKED_REGS; 4099de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4109de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (i = 0; i < size; i++) { 4119de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r = &dscr.locked[i]; 4129de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4139de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->reg = be32_to_cpup(p++); 4149de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->lockreg = be32_to_cpup(p++); 4159de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->key = be32_to_cpup(p++); 4169de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 4179de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 4189de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 4199de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4209de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 4219de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * SoCs may have DSCR registers which are only write enabled after 4229de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * writing specific key values to two registers. The two key registers 4239de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * and the key values can be parsed from a "ti,dscr-kick-regs" 4249de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * propety with the following layout: 4259de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 4269de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * ti,dscr-kick-regs = <kickreg0 key0 kickreg1 key1> 4279de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 4289de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * kickreg is the offset of the "kick" register 4299de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * key is the value which unlocks writing for protected regs 4309de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 4319de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_kick_regs(struct device_node *node, 4329de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 4339de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 4349de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter u32 vals[4]; 4359de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int err; 4369de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4379de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter err = of_property_read_u32_array(node, "ti,dscr-kick-regs", vals, 4); 4389de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!err) { 4399de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.kick_reg[0] = vals[0]; 4409de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.kick_key[0] = vals[1]; 4419de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.kick_reg[1] = vals[2]; 4429de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.kick_key[1] = vals[3]; 4439de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 4449de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 4459de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4469de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4479de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 4489de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * SoCs may provide controls to enable/disable individual IP blocks. These 4499de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * controls in the DSCR usually control pin drivers but also may control 4509de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * clocking and or resets. The device tree is used to describe the bitfields 4519de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * in registers used to control device state. The number of bits and their 4529de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * values may vary even within the same register. 4539de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 4549de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * The layout of these bitfields is described by the ti,dscr-devstate-ctl-regs 4559de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * property. This property is a list where each element describes a contiguous 4569de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * range of control fields with like properties. Each element of the list 4579de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * consists of 7 cells with the following values: 4589de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 4599de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * start_id num_ids reg enable disable start_bit nbits 4609de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 4619de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * start_id is device id for the first device control in the range 4629de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * num_ids is the number of device controls in the range 4639de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * reg is the offset of the register holding the control bits 4649de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * enable is the value to enable a device 4659de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * disable is the value to disable a device (0xffffffff if cannot disable) 4669de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * start_bit is the bit number of the first bit in the range 4679de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * nbits is the number of bits per device control 4689de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 4699de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_devstate_ctl_regs(struct device_node *node, 4709de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 4719de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 4729de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_ctl_reg *r; 4739de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter const __be32 *p; 4749de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int i, j, size; 4759de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4769de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter p = of_get_property(node, "ti,dscr-devstate-ctl-regs", &size); 4779de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (p) { 4789de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* parse all the ranges we can handle */ 4799de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size /= (sizeof(*p) * 7); 4809de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (size > MAX_DEVCTL_REGS) 4819de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size = MAX_DEVCTL_REGS; 4829de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4839de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (i = 0; i < size; i++) { 4849de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r = &dscr.devctl[i]; 4859de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4869de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->start_id = be32_to_cpup(p++); 4879de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->num_ids = be32_to_cpup(p++); 4889de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->reg = be32_to_cpup(p++); 4899de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->enable = be32_to_cpup(p++); 4909de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->disable = be32_to_cpup(p++); 4919de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (r->disable == 0xffffffff) 4929de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->enable_only = 1; 4939de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->shift = be32_to_cpup(p++); 4949de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->nbits = be32_to_cpup(p++); 4959de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 4969de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (j = r->start_id; 4979de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter j < (r->start_id + r->num_ids); 4989de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter j++) 4999de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.devstate_info[j].ctl = r; 5009de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 5019de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 5029de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 5039de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5049de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 5059de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * SoCs may provide status registers indicating the state (enabled/disabled) of 5069de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * devices on the SoC. The device tree is used to describe the bitfields in 5079de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * registers used to provide device status. The number of bits and their 5089de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * values used to provide status may vary even within the same register. 5099de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 5109de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * The layout of these bitfields is described by the ti,dscr-devstate-stat-regs 5119de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * property. This property is a list where each element describes a contiguous 5129de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * range of status fields with like properties. Each element of the list 5139de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * consists of 7 cells with the following values: 5149de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 5159de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * start_id num_ids reg enable disable start_bit nbits 5169de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 5179de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * start_id is device id for the first device status in the range 5189de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * num_ids is the number of devices covered by the range 5199de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * reg is the offset of the register holding the status bits 5209de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * enable is the value indicating device is enabled 5219de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * disable is the value indicating device is disabled 5229de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * start_bit is the bit number of the first bit in the range 5239de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * nbits is the number of bits per device status 5249de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 5259de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic void __init dscr_parse_devstate_stat_regs(struct device_node *node, 5269de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base) 5279de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 5289de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct devstate_stat_reg *r; 5299de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter const __be32 *p; 5309de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter int i, j, size; 5319de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5329de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter p = of_get_property(node, "ti,dscr-devstate-stat-regs", &size); 5339de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (p) { 5349de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter /* parse all the ranges we can handle */ 5359de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size /= (sizeof(*p) * 7); 5369de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (size > MAX_DEVSTAT_REGS) 5379de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter size = MAX_DEVSTAT_REGS; 5389de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5399de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (i = 0; i < size; i++) { 5409de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r = &dscr.devstat[i]; 5419de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5429de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->start_id = be32_to_cpup(p++); 5439de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->num_ids = be32_to_cpup(p++); 5449de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->reg = be32_to_cpup(p++); 5459de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->enable = be32_to_cpup(p++); 5469de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->disable = be32_to_cpup(p++); 5479de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->shift = be32_to_cpup(p++); 5489de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter r->nbits = be32_to_cpup(p++); 5499de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5509de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter for (j = r->start_id; 5519de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter j < (r->start_id + r->num_ids); 5529de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter j++) 5539de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.devstate_info[j].stat = r; 5549de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 5559de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 5569de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 5579de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5589de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salterstatic struct of_device_id dscr_ids[] __initdata = { 5599de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter { .compatible = "ti,c64x+dscr" }, 5609de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter {} 5619de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter}; 5629de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5639de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter/* 5649de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * Probe for DSCR area. 5659de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * 5669de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * This has to be done early on in case timer or interrupt controller 5679de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * needs something. e.g. On C6455 SoC, timer must be enabled through 5689de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter * DSCR before it is functional. 5699de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter */ 5709de98fb4ec4c91597feedc521120c16fca54a5b6Mark Saltervoid __init dscr_probe(void) 5719de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter{ 5729de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter struct device_node *node; 5739de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter void __iomem *base; 5749de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5759de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter spin_lock_init(&dscr.lock); 5769de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5779de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter node = of_find_matching_node(NULL, dscr_ids); 5789de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!node) 5799de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 5809de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5819de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter base = of_iomap(node, 0); 5829de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter if (!base) { 5839de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter of_node_put(node); 5849de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter return; 5859de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter } 5869de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5879de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr.base = base; 5889de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter 5899de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_devstat(node, base); 5909de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_silicon_rev(node, base); 5919de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_mac_fuse(node, base); 5929de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_rmii_resets(node, base); 5939de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_locked_regs(node, base); 5949de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_kick_regs(node, base); 5959de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_devstate_ctl_regs(node, base); 5969de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_devstate_stat_regs(node, base); 5979de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter dscr_parse_privperm(node, base); 5989de98fb4ec4c91597feedc521120c16fca54a5b6Mark Salter} 599