1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Device State Control Registers driver
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2011 Texas Instruments Incorporated
6*4882a593Smuzhiyun * Author: Mark Salter <msalter@redhat.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun * The Device State Control Registers (DSCR) provide SoC level control over
11*4882a593Smuzhiyun * a number of peripherals. Details vary considerably among the various SoC
12*4882a593Smuzhiyun * parts. In general, the DSCR block will provide one or more configuration
13*4882a593Smuzhiyun * registers often protected by a lock register. One or more key values must
14*4882a593Smuzhiyun * be written to a lock register in order to unlock the configuration register.
15*4882a593Smuzhiyun * The configuration register may be used to enable (and disable in some
16*4882a593Smuzhiyun * cases) SoC pin drivers, peripheral clock sources (internal or pin), etc.
17*4882a593Smuzhiyun * In some cases, a configuration register is write once or the individual
18*4882a593Smuzhiyun * bits are write once. That is, you may be able to enable a device, but
19*4882a593Smuzhiyun * will not be able to disable it.
20*4882a593Smuzhiyun *
21*4882a593Smuzhiyun * In addition to device configuration, the DSCR block may provide registers
22*4882a593Smuzhiyun * which are used to reset SoC peripherals, provide device ID information,
23*4882a593Smuzhiyun * provide MAC addresses, and other miscellaneous functions.
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #include <linux/of.h>
27*4882a593Smuzhiyun #include <linux/of_address.h>
28*4882a593Smuzhiyun #include <linux/of_platform.h>
29*4882a593Smuzhiyun #include <linux/module.h>
30*4882a593Smuzhiyun #include <linux/io.h>
31*4882a593Smuzhiyun #include <linux/delay.h>
32*4882a593Smuzhiyun #include <asm/soc.h>
33*4882a593Smuzhiyun #include <asm/dscr.h>
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #define MAX_DEVSTATE_IDS 32
36*4882a593Smuzhiyun #define MAX_DEVCTL_REGS 8
37*4882a593Smuzhiyun #define MAX_DEVSTAT_REGS 8
38*4882a593Smuzhiyun #define MAX_LOCKED_REGS 4
39*4882a593Smuzhiyun #define MAX_SOC_EMACS 2
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun struct rmii_reset_reg {
42*4882a593Smuzhiyun u32 reg;
43*4882a593Smuzhiyun u32 mask;
44*4882a593Smuzhiyun };
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * Some registerd may be locked. In order to write to these
48*4882a593Smuzhiyun * registers, the key value must first be written to the lockreg.
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun struct locked_reg {
51*4882a593Smuzhiyun u32 reg; /* offset from base */
52*4882a593Smuzhiyun u32 lockreg; /* offset from base */
53*4882a593Smuzhiyun u32 key; /* unlock key */
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /*
57*4882a593Smuzhiyun * This describes a contiguous area of like control bits used to enable/disable
58*4882a593Smuzhiyun * SoC devices. Each controllable device is given an ID which is used by the
59*4882a593Smuzhiyun * individual device drivers to control the device state. These IDs start at
60*4882a593Smuzhiyun * zero and are assigned sequentially to the control bitfield ranges described
61*4882a593Smuzhiyun * by this structure.
62*4882a593Smuzhiyun */
63*4882a593Smuzhiyun struct devstate_ctl_reg {
64*4882a593Smuzhiyun u32 reg; /* register holding the control bits */
65*4882a593Smuzhiyun u8 start_id; /* start id of this range */
66*4882a593Smuzhiyun u8 num_ids; /* number of devices in this range */
67*4882a593Smuzhiyun u8 enable_only; /* bits are write-once to enable only */
68*4882a593Smuzhiyun u8 enable; /* value used to enable device */
69*4882a593Smuzhiyun u8 disable; /* value used to disable device */
70*4882a593Smuzhiyun u8 shift; /* starting (rightmost) bit in range */
71*4882a593Smuzhiyun u8 nbits; /* number of bits per device */
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun /*
76*4882a593Smuzhiyun * This describes a region of status bits indicating the state of
77*4882a593Smuzhiyun * various devices. This is used internally to wait for status
78*4882a593Smuzhiyun * change completion when enabling/disabling a device. Status is
79*4882a593Smuzhiyun * optional and not all device controls will have a corresponding
80*4882a593Smuzhiyun * status.
81*4882a593Smuzhiyun */
82*4882a593Smuzhiyun struct devstate_stat_reg {
83*4882a593Smuzhiyun u32 reg; /* register holding the status bits */
84*4882a593Smuzhiyun u8 start_id; /* start id of this range */
85*4882a593Smuzhiyun u8 num_ids; /* number of devices in this range */
86*4882a593Smuzhiyun u8 enable; /* value indicating enabled state */
87*4882a593Smuzhiyun u8 disable; /* value indicating disabled state */
88*4882a593Smuzhiyun u8 shift; /* starting (rightmost) bit in range */
89*4882a593Smuzhiyun u8 nbits; /* number of bits per device */
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun struct devstate_info {
93*4882a593Smuzhiyun struct devstate_ctl_reg *ctl;
94*4882a593Smuzhiyun struct devstate_stat_reg *stat;
95*4882a593Smuzhiyun };
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun /* These are callbacks to SOC-specific code. */
98*4882a593Smuzhiyun struct dscr_ops {
99*4882a593Smuzhiyun void (*init)(struct device_node *node);
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun struct dscr_regs {
103*4882a593Smuzhiyun spinlock_t lock;
104*4882a593Smuzhiyun void __iomem *base;
105*4882a593Smuzhiyun u32 kick_reg[2];
106*4882a593Smuzhiyun u32 kick_key[2];
107*4882a593Smuzhiyun struct locked_reg locked[MAX_LOCKED_REGS];
108*4882a593Smuzhiyun struct devstate_info devstate_info[MAX_DEVSTATE_IDS];
109*4882a593Smuzhiyun struct rmii_reset_reg rmii_resets[MAX_SOC_EMACS];
110*4882a593Smuzhiyun struct devstate_ctl_reg devctl[MAX_DEVCTL_REGS];
111*4882a593Smuzhiyun struct devstate_stat_reg devstat[MAX_DEVSTAT_REGS];
112*4882a593Smuzhiyun };
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun static struct dscr_regs dscr;
115*4882a593Smuzhiyun
find_locked_reg(u32 reg)116*4882a593Smuzhiyun static struct locked_reg *find_locked_reg(u32 reg)
117*4882a593Smuzhiyun {
118*4882a593Smuzhiyun int i;
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun for (i = 0; i < MAX_LOCKED_REGS; i++)
121*4882a593Smuzhiyun if (dscr.locked[i].key && reg == dscr.locked[i].reg)
122*4882a593Smuzhiyun return &dscr.locked[i];
123*4882a593Smuzhiyun return NULL;
124*4882a593Smuzhiyun }
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun /*
127*4882a593Smuzhiyun * Write to a register with one lock
128*4882a593Smuzhiyun */
dscr_write_locked1(u32 reg,u32 val,u32 lock,u32 key)129*4882a593Smuzhiyun static void dscr_write_locked1(u32 reg, u32 val,
130*4882a593Smuzhiyun u32 lock, u32 key)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun void __iomem *reg_addr = dscr.base + reg;
133*4882a593Smuzhiyun void __iomem *lock_addr = dscr.base + lock;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun /*
136*4882a593Smuzhiyun * For some registers, the lock is relocked after a short number
137*4882a593Smuzhiyun * of cycles. We have to put the lock write and register write in
138*4882a593Smuzhiyun * the same fetch packet to meet this timing. The .align ensures
139*4882a593Smuzhiyun * the two stw instructions are in the same fetch packet.
140*4882a593Smuzhiyun */
141*4882a593Smuzhiyun asm volatile ("b .s2 0f\n"
142*4882a593Smuzhiyun "nop 5\n"
143*4882a593Smuzhiyun " .align 5\n"
144*4882a593Smuzhiyun "0:\n"
145*4882a593Smuzhiyun "stw .D1T2 %3,*%2\n"
146*4882a593Smuzhiyun "stw .D1T2 %1,*%0\n"
147*4882a593Smuzhiyun :
148*4882a593Smuzhiyun : "a"(reg_addr), "b"(val), "a"(lock_addr), "b"(key)
149*4882a593Smuzhiyun );
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* in case the hw doesn't reset the lock */
152*4882a593Smuzhiyun soc_writel(0, lock_addr);
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun * Write to a register protected by two lock registers
157*4882a593Smuzhiyun */
dscr_write_locked2(u32 reg,u32 val,u32 lock0,u32 key0,u32 lock1,u32 key1)158*4882a593Smuzhiyun static void dscr_write_locked2(u32 reg, u32 val,
159*4882a593Smuzhiyun u32 lock0, u32 key0,
160*4882a593Smuzhiyun u32 lock1, u32 key1)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun soc_writel(key0, dscr.base + lock0);
163*4882a593Smuzhiyun soc_writel(key1, dscr.base + lock1);
164*4882a593Smuzhiyun soc_writel(val, dscr.base + reg);
165*4882a593Smuzhiyun soc_writel(0, dscr.base + lock0);
166*4882a593Smuzhiyun soc_writel(0, dscr.base + lock1);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun
dscr_write(u32 reg,u32 val)169*4882a593Smuzhiyun static void dscr_write(u32 reg, u32 val)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun struct locked_reg *lock;
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun lock = find_locked_reg(reg);
174*4882a593Smuzhiyun if (lock)
175*4882a593Smuzhiyun dscr_write_locked1(reg, val, lock->lockreg, lock->key);
176*4882a593Smuzhiyun else if (dscr.kick_key[0])
177*4882a593Smuzhiyun dscr_write_locked2(reg, val, dscr.kick_reg[0], dscr.kick_key[0],
178*4882a593Smuzhiyun dscr.kick_reg[1], dscr.kick_key[1]);
179*4882a593Smuzhiyun else
180*4882a593Smuzhiyun soc_writel(val, dscr.base + reg);
181*4882a593Smuzhiyun }
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun /*
185*4882a593Smuzhiyun * Drivers can use this interface to enable/disable SoC IP blocks.
186*4882a593Smuzhiyun */
dscr_set_devstate(int id,enum dscr_devstate_t state)187*4882a593Smuzhiyun void dscr_set_devstate(int id, enum dscr_devstate_t state)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct devstate_ctl_reg *ctl;
190*4882a593Smuzhiyun struct devstate_stat_reg *stat;
191*4882a593Smuzhiyun struct devstate_info *info;
192*4882a593Smuzhiyun u32 ctl_val, val;
193*4882a593Smuzhiyun int ctl_shift, ctl_mask;
194*4882a593Smuzhiyun unsigned long flags;
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun if (!dscr.base)
197*4882a593Smuzhiyun return;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (id < 0 || id >= MAX_DEVSTATE_IDS)
200*4882a593Smuzhiyun return;
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun info = &dscr.devstate_info[id];
203*4882a593Smuzhiyun ctl = info->ctl;
204*4882a593Smuzhiyun stat = info->stat;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun if (ctl == NULL)
207*4882a593Smuzhiyun return;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun ctl_shift = ctl->shift + ctl->nbits * (id - ctl->start_id);
210*4882a593Smuzhiyun ctl_mask = ((1 << ctl->nbits) - 1) << ctl_shift;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun switch (state) {
213*4882a593Smuzhiyun case DSCR_DEVSTATE_ENABLED:
214*4882a593Smuzhiyun ctl_val = ctl->enable << ctl_shift;
215*4882a593Smuzhiyun break;
216*4882a593Smuzhiyun case DSCR_DEVSTATE_DISABLED:
217*4882a593Smuzhiyun if (ctl->enable_only)
218*4882a593Smuzhiyun return;
219*4882a593Smuzhiyun ctl_val = ctl->disable << ctl_shift;
220*4882a593Smuzhiyun break;
221*4882a593Smuzhiyun default:
222*4882a593Smuzhiyun return;
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun spin_lock_irqsave(&dscr.lock, flags);
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun val = soc_readl(dscr.base + ctl->reg);
228*4882a593Smuzhiyun val &= ~ctl_mask;
229*4882a593Smuzhiyun val |= ctl_val;
230*4882a593Smuzhiyun
231*4882a593Smuzhiyun dscr_write(ctl->reg, val);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun spin_unlock_irqrestore(&dscr.lock, flags);
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun if (!stat)
236*4882a593Smuzhiyun return;
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun ctl_shift = stat->shift + stat->nbits * (id - stat->start_id);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun if (state == DSCR_DEVSTATE_ENABLED)
241*4882a593Smuzhiyun ctl_val = stat->enable;
242*4882a593Smuzhiyun else
243*4882a593Smuzhiyun ctl_val = stat->disable;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun do {
246*4882a593Smuzhiyun val = soc_readl(dscr.base + stat->reg);
247*4882a593Smuzhiyun val >>= ctl_shift;
248*4882a593Smuzhiyun val &= ((1 << stat->nbits) - 1);
249*4882a593Smuzhiyun } while (val != ctl_val);
250*4882a593Smuzhiyun }
251*4882a593Smuzhiyun EXPORT_SYMBOL(dscr_set_devstate);
252*4882a593Smuzhiyun
253*4882a593Smuzhiyun /*
254*4882a593Smuzhiyun * Drivers can use this to reset RMII module.
255*4882a593Smuzhiyun */
dscr_rmii_reset(int id,int assert)256*4882a593Smuzhiyun void dscr_rmii_reset(int id, int assert)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun struct rmii_reset_reg *r;
259*4882a593Smuzhiyun unsigned long flags;
260*4882a593Smuzhiyun u32 val;
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun if (id < 0 || id >= MAX_SOC_EMACS)
263*4882a593Smuzhiyun return;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun r = &dscr.rmii_resets[id];
266*4882a593Smuzhiyun if (r->mask == 0)
267*4882a593Smuzhiyun return;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun spin_lock_irqsave(&dscr.lock, flags);
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun val = soc_readl(dscr.base + r->reg);
272*4882a593Smuzhiyun if (assert)
273*4882a593Smuzhiyun dscr_write(r->reg, val | r->mask);
274*4882a593Smuzhiyun else
275*4882a593Smuzhiyun dscr_write(r->reg, val & ~(r->mask));
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun spin_unlock_irqrestore(&dscr.lock, flags);
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun EXPORT_SYMBOL(dscr_rmii_reset);
280*4882a593Smuzhiyun
dscr_parse_devstat(struct device_node * node,void __iomem * base)281*4882a593Smuzhiyun static void __init dscr_parse_devstat(struct device_node *node,
282*4882a593Smuzhiyun void __iomem *base)
283*4882a593Smuzhiyun {
284*4882a593Smuzhiyun u32 val;
285*4882a593Smuzhiyun int err;
286*4882a593Smuzhiyun
287*4882a593Smuzhiyun err = of_property_read_u32_array(node, "ti,dscr-devstat", &val, 1);
288*4882a593Smuzhiyun if (!err)
289*4882a593Smuzhiyun c6x_devstat = soc_readl(base + val);
290*4882a593Smuzhiyun printk(KERN_INFO "DEVSTAT: %08x\n", c6x_devstat);
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
dscr_parse_silicon_rev(struct device_node * node,void __iomem * base)293*4882a593Smuzhiyun static void __init dscr_parse_silicon_rev(struct device_node *node,
294*4882a593Smuzhiyun void __iomem *base)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun u32 vals[3];
297*4882a593Smuzhiyun int err;
298*4882a593Smuzhiyun
299*4882a593Smuzhiyun err = of_property_read_u32_array(node, "ti,dscr-silicon-rev", vals, 3);
300*4882a593Smuzhiyun if (!err) {
301*4882a593Smuzhiyun c6x_silicon_rev = soc_readl(base + vals[0]);
302*4882a593Smuzhiyun c6x_silicon_rev >>= vals[1];
303*4882a593Smuzhiyun c6x_silicon_rev &= vals[2];
304*4882a593Smuzhiyun }
305*4882a593Smuzhiyun }
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun /*
308*4882a593Smuzhiyun * Some SoCs will have a pair of fuse registers which hold
309*4882a593Smuzhiyun * an ethernet MAC address. The "ti,dscr-mac-fuse-regs"
310*4882a593Smuzhiyun * property is a mapping from fuse register bytes to MAC
311*4882a593Smuzhiyun * address bytes. The expected format is:
312*4882a593Smuzhiyun *
313*4882a593Smuzhiyun * ti,dscr-mac-fuse-regs = <reg0 b3 b2 b1 b0
314*4882a593Smuzhiyun * reg1 b3 b2 b1 b0>
315*4882a593Smuzhiyun *
316*4882a593Smuzhiyun * reg0 and reg1 are the offsets of the two fuse registers.
317*4882a593Smuzhiyun * b3-b0 positionally represent bytes within the fuse register.
318*4882a593Smuzhiyun * b3 is the most significant byte and b0 is the least.
319*4882a593Smuzhiyun * Allowable values for b3-b0 are:
320*4882a593Smuzhiyun *
321*4882a593Smuzhiyun * 0 = fuse register byte not used in MAC address
322*4882a593Smuzhiyun * 1-6 = index+1 into c6x_fuse_mac[]
323*4882a593Smuzhiyun */
dscr_parse_mac_fuse(struct device_node * node,void __iomem * base)324*4882a593Smuzhiyun static void __init dscr_parse_mac_fuse(struct device_node *node,
325*4882a593Smuzhiyun void __iomem *base)
326*4882a593Smuzhiyun {
327*4882a593Smuzhiyun u32 vals[10], fuse;
328*4882a593Smuzhiyun int f, i, j, err;
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun err = of_property_read_u32_array(node, "ti,dscr-mac-fuse-regs",
331*4882a593Smuzhiyun vals, 10);
332*4882a593Smuzhiyun if (err)
333*4882a593Smuzhiyun return;
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun for (f = 0; f < 2; f++) {
336*4882a593Smuzhiyun fuse = soc_readl(base + vals[f * 5]);
337*4882a593Smuzhiyun for (j = (f * 5) + 1, i = 24; i >= 0; i -= 8, j++)
338*4882a593Smuzhiyun if (vals[j] && vals[j] <= 6)
339*4882a593Smuzhiyun c6x_fuse_mac[vals[j] - 1] = fuse >> i;
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
dscr_parse_rmii_resets(struct device_node * node,void __iomem * base)343*4882a593Smuzhiyun static void __init dscr_parse_rmii_resets(struct device_node *node,
344*4882a593Smuzhiyun void __iomem *base)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun const __be32 *p;
347*4882a593Smuzhiyun int i, size;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun /* look for RMII reset registers */
350*4882a593Smuzhiyun p = of_get_property(node, "ti,dscr-rmii-resets", &size);
351*4882a593Smuzhiyun if (p) {
352*4882a593Smuzhiyun /* parse all the reg/mask pairs we can handle */
353*4882a593Smuzhiyun size /= (sizeof(*p) * 2);
354*4882a593Smuzhiyun if (size > MAX_SOC_EMACS)
355*4882a593Smuzhiyun size = MAX_SOC_EMACS;
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun for (i = 0; i < size; i++) {
358*4882a593Smuzhiyun dscr.rmii_resets[i].reg = be32_to_cpup(p++);
359*4882a593Smuzhiyun dscr.rmii_resets[i].mask = be32_to_cpup(p++);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun }
362*4882a593Smuzhiyun }
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun
dscr_parse_privperm(struct device_node * node,void __iomem * base)365*4882a593Smuzhiyun static void __init dscr_parse_privperm(struct device_node *node,
366*4882a593Smuzhiyun void __iomem *base)
367*4882a593Smuzhiyun {
368*4882a593Smuzhiyun u32 vals[2];
369*4882a593Smuzhiyun int err;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun err = of_property_read_u32_array(node, "ti,dscr-privperm", vals, 2);
372*4882a593Smuzhiyun if (err)
373*4882a593Smuzhiyun return;
374*4882a593Smuzhiyun dscr_write(vals[0], vals[1]);
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
377*4882a593Smuzhiyun /*
378*4882a593Smuzhiyun * SoCs may have "locked" DSCR registers which can only be written
379*4882a593Smuzhiyun * to only after writing a key value to a lock registers. These
380*4882a593Smuzhiyun * regisers can be described with the "ti,dscr-locked-regs" property.
381*4882a593Smuzhiyun * This property provides a list of register descriptions with each
382*4882a593Smuzhiyun * description consisting of three values.
383*4882a593Smuzhiyun *
384*4882a593Smuzhiyun * ti,dscr-locked-regs = <reg0 lockreg0 key0
385*4882a593Smuzhiyun * ...
386*4882a593Smuzhiyun * regN lockregN keyN>;
387*4882a593Smuzhiyun *
388*4882a593Smuzhiyun * reg is the offset of the locked register
389*4882a593Smuzhiyun * lockreg is the offset of the lock register
390*4882a593Smuzhiyun * key is the unlock key written to lockreg
391*4882a593Smuzhiyun *
392*4882a593Smuzhiyun */
dscr_parse_locked_regs(struct device_node * node,void __iomem * base)393*4882a593Smuzhiyun static void __init dscr_parse_locked_regs(struct device_node *node,
394*4882a593Smuzhiyun void __iomem *base)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun struct locked_reg *r;
397*4882a593Smuzhiyun const __be32 *p;
398*4882a593Smuzhiyun int i, size;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun p = of_get_property(node, "ti,dscr-locked-regs", &size);
401*4882a593Smuzhiyun if (p) {
402*4882a593Smuzhiyun /* parse all the register descriptions we can handle */
403*4882a593Smuzhiyun size /= (sizeof(*p) * 3);
404*4882a593Smuzhiyun if (size > MAX_LOCKED_REGS)
405*4882a593Smuzhiyun size = MAX_LOCKED_REGS;
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun for (i = 0; i < size; i++) {
408*4882a593Smuzhiyun r = &dscr.locked[i];
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun r->reg = be32_to_cpup(p++);
411*4882a593Smuzhiyun r->lockreg = be32_to_cpup(p++);
412*4882a593Smuzhiyun r->key = be32_to_cpup(p++);
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun /*
418*4882a593Smuzhiyun * SoCs may have DSCR registers which are only write enabled after
419*4882a593Smuzhiyun * writing specific key values to two registers. The two key registers
420*4882a593Smuzhiyun * and the key values can be parsed from a "ti,dscr-kick-regs"
421*4882a593Smuzhiyun * propety with the following layout:
422*4882a593Smuzhiyun *
423*4882a593Smuzhiyun * ti,dscr-kick-regs = <kickreg0 key0 kickreg1 key1>
424*4882a593Smuzhiyun *
425*4882a593Smuzhiyun * kickreg is the offset of the "kick" register
426*4882a593Smuzhiyun * key is the value which unlocks writing for protected regs
427*4882a593Smuzhiyun */
dscr_parse_kick_regs(struct device_node * node,void __iomem * base)428*4882a593Smuzhiyun static void __init dscr_parse_kick_regs(struct device_node *node,
429*4882a593Smuzhiyun void __iomem *base)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun u32 vals[4];
432*4882a593Smuzhiyun int err;
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun err = of_property_read_u32_array(node, "ti,dscr-kick-regs", vals, 4);
435*4882a593Smuzhiyun if (!err) {
436*4882a593Smuzhiyun dscr.kick_reg[0] = vals[0];
437*4882a593Smuzhiyun dscr.kick_key[0] = vals[1];
438*4882a593Smuzhiyun dscr.kick_reg[1] = vals[2];
439*4882a593Smuzhiyun dscr.kick_key[1] = vals[3];
440*4882a593Smuzhiyun }
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun /*
445*4882a593Smuzhiyun * SoCs may provide controls to enable/disable individual IP blocks. These
446*4882a593Smuzhiyun * controls in the DSCR usually control pin drivers but also may control
447*4882a593Smuzhiyun * clocking and or resets. The device tree is used to describe the bitfields
448*4882a593Smuzhiyun * in registers used to control device state. The number of bits and their
449*4882a593Smuzhiyun * values may vary even within the same register.
450*4882a593Smuzhiyun *
451*4882a593Smuzhiyun * The layout of these bitfields is described by the ti,dscr-devstate-ctl-regs
452*4882a593Smuzhiyun * property. This property is a list where each element describes a contiguous
453*4882a593Smuzhiyun * range of control fields with like properties. Each element of the list
454*4882a593Smuzhiyun * consists of 7 cells with the following values:
455*4882a593Smuzhiyun *
456*4882a593Smuzhiyun * start_id num_ids reg enable disable start_bit nbits
457*4882a593Smuzhiyun *
458*4882a593Smuzhiyun * start_id is device id for the first device control in the range
459*4882a593Smuzhiyun * num_ids is the number of device controls in the range
460*4882a593Smuzhiyun * reg is the offset of the register holding the control bits
461*4882a593Smuzhiyun * enable is the value to enable a device
462*4882a593Smuzhiyun * disable is the value to disable a device (0xffffffff if cannot disable)
463*4882a593Smuzhiyun * start_bit is the bit number of the first bit in the range
464*4882a593Smuzhiyun * nbits is the number of bits per device control
465*4882a593Smuzhiyun */
dscr_parse_devstate_ctl_regs(struct device_node * node,void __iomem * base)466*4882a593Smuzhiyun static void __init dscr_parse_devstate_ctl_regs(struct device_node *node,
467*4882a593Smuzhiyun void __iomem *base)
468*4882a593Smuzhiyun {
469*4882a593Smuzhiyun struct devstate_ctl_reg *r;
470*4882a593Smuzhiyun const __be32 *p;
471*4882a593Smuzhiyun int i, j, size;
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun p = of_get_property(node, "ti,dscr-devstate-ctl-regs", &size);
474*4882a593Smuzhiyun if (p) {
475*4882a593Smuzhiyun /* parse all the ranges we can handle */
476*4882a593Smuzhiyun size /= (sizeof(*p) * 7);
477*4882a593Smuzhiyun if (size > MAX_DEVCTL_REGS)
478*4882a593Smuzhiyun size = MAX_DEVCTL_REGS;
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun for (i = 0; i < size; i++) {
481*4882a593Smuzhiyun r = &dscr.devctl[i];
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun r->start_id = be32_to_cpup(p++);
484*4882a593Smuzhiyun r->num_ids = be32_to_cpup(p++);
485*4882a593Smuzhiyun r->reg = be32_to_cpup(p++);
486*4882a593Smuzhiyun r->enable = be32_to_cpup(p++);
487*4882a593Smuzhiyun r->disable = be32_to_cpup(p++);
488*4882a593Smuzhiyun if (r->disable == 0xffffffff)
489*4882a593Smuzhiyun r->enable_only = 1;
490*4882a593Smuzhiyun r->shift = be32_to_cpup(p++);
491*4882a593Smuzhiyun r->nbits = be32_to_cpup(p++);
492*4882a593Smuzhiyun
493*4882a593Smuzhiyun for (j = r->start_id;
494*4882a593Smuzhiyun j < (r->start_id + r->num_ids);
495*4882a593Smuzhiyun j++)
496*4882a593Smuzhiyun dscr.devstate_info[j].ctl = r;
497*4882a593Smuzhiyun }
498*4882a593Smuzhiyun }
499*4882a593Smuzhiyun }
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun /*
502*4882a593Smuzhiyun * SoCs may provide status registers indicating the state (enabled/disabled) of
503*4882a593Smuzhiyun * devices on the SoC. The device tree is used to describe the bitfields in
504*4882a593Smuzhiyun * registers used to provide device status. The number of bits and their
505*4882a593Smuzhiyun * values used to provide status may vary even within the same register.
506*4882a593Smuzhiyun *
507*4882a593Smuzhiyun * The layout of these bitfields is described by the ti,dscr-devstate-stat-regs
508*4882a593Smuzhiyun * property. This property is a list where each element describes a contiguous
509*4882a593Smuzhiyun * range of status fields with like properties. Each element of the list
510*4882a593Smuzhiyun * consists of 7 cells with the following values:
511*4882a593Smuzhiyun *
512*4882a593Smuzhiyun * start_id num_ids reg enable disable start_bit nbits
513*4882a593Smuzhiyun *
514*4882a593Smuzhiyun * start_id is device id for the first device status in the range
515*4882a593Smuzhiyun * num_ids is the number of devices covered by the range
516*4882a593Smuzhiyun * reg is the offset of the register holding the status bits
517*4882a593Smuzhiyun * enable is the value indicating device is enabled
518*4882a593Smuzhiyun * disable is the value indicating device is disabled
519*4882a593Smuzhiyun * start_bit is the bit number of the first bit in the range
520*4882a593Smuzhiyun * nbits is the number of bits per device status
521*4882a593Smuzhiyun */
dscr_parse_devstate_stat_regs(struct device_node * node,void __iomem * base)522*4882a593Smuzhiyun static void __init dscr_parse_devstate_stat_regs(struct device_node *node,
523*4882a593Smuzhiyun void __iomem *base)
524*4882a593Smuzhiyun {
525*4882a593Smuzhiyun struct devstate_stat_reg *r;
526*4882a593Smuzhiyun const __be32 *p;
527*4882a593Smuzhiyun int i, j, size;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun p = of_get_property(node, "ti,dscr-devstate-stat-regs", &size);
530*4882a593Smuzhiyun if (p) {
531*4882a593Smuzhiyun /* parse all the ranges we can handle */
532*4882a593Smuzhiyun size /= (sizeof(*p) * 7);
533*4882a593Smuzhiyun if (size > MAX_DEVSTAT_REGS)
534*4882a593Smuzhiyun size = MAX_DEVSTAT_REGS;
535*4882a593Smuzhiyun
536*4882a593Smuzhiyun for (i = 0; i < size; i++) {
537*4882a593Smuzhiyun r = &dscr.devstat[i];
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun r->start_id = be32_to_cpup(p++);
540*4882a593Smuzhiyun r->num_ids = be32_to_cpup(p++);
541*4882a593Smuzhiyun r->reg = be32_to_cpup(p++);
542*4882a593Smuzhiyun r->enable = be32_to_cpup(p++);
543*4882a593Smuzhiyun r->disable = be32_to_cpup(p++);
544*4882a593Smuzhiyun r->shift = be32_to_cpup(p++);
545*4882a593Smuzhiyun r->nbits = be32_to_cpup(p++);
546*4882a593Smuzhiyun
547*4882a593Smuzhiyun for (j = r->start_id;
548*4882a593Smuzhiyun j < (r->start_id + r->num_ids);
549*4882a593Smuzhiyun j++)
550*4882a593Smuzhiyun dscr.devstate_info[j].stat = r;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun
555*4882a593Smuzhiyun static struct of_device_id dscr_ids[] __initdata = {
556*4882a593Smuzhiyun { .compatible = "ti,c64x+dscr" },
557*4882a593Smuzhiyun {}
558*4882a593Smuzhiyun };
559*4882a593Smuzhiyun
560*4882a593Smuzhiyun /*
561*4882a593Smuzhiyun * Probe for DSCR area.
562*4882a593Smuzhiyun *
563*4882a593Smuzhiyun * This has to be done early on in case timer or interrupt controller
564*4882a593Smuzhiyun * needs something. e.g. On C6455 SoC, timer must be enabled through
565*4882a593Smuzhiyun * DSCR before it is functional.
566*4882a593Smuzhiyun */
dscr_probe(void)567*4882a593Smuzhiyun void __init dscr_probe(void)
568*4882a593Smuzhiyun {
569*4882a593Smuzhiyun struct device_node *node;
570*4882a593Smuzhiyun void __iomem *base;
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun spin_lock_init(&dscr.lock);
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun node = of_find_matching_node(NULL, dscr_ids);
575*4882a593Smuzhiyun if (!node)
576*4882a593Smuzhiyun return;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun base = of_iomap(node, 0);
579*4882a593Smuzhiyun if (!base) {
580*4882a593Smuzhiyun of_node_put(node);
581*4882a593Smuzhiyun return;
582*4882a593Smuzhiyun }
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun dscr.base = base;
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun dscr_parse_devstat(node, base);
587*4882a593Smuzhiyun dscr_parse_silicon_rev(node, base);
588*4882a593Smuzhiyun dscr_parse_mac_fuse(node, base);
589*4882a593Smuzhiyun dscr_parse_rmii_resets(node, base);
590*4882a593Smuzhiyun dscr_parse_locked_regs(node, base);
591*4882a593Smuzhiyun dscr_parse_kick_regs(node, base);
592*4882a593Smuzhiyun dscr_parse_devstate_ctl_regs(node, base);
593*4882a593Smuzhiyun dscr_parse_devstate_stat_regs(node, base);
594*4882a593Smuzhiyun dscr_parse_privperm(node, base);
595*4882a593Smuzhiyun }
596