1/*
2 * Copyright 2017, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12#include "src.h"
13
14#define SLCR_PADDR                  0xF8000000  /* System Level Control Registers */
15#define SLCR_SIZE                   0x1000
16
17#define SLCR_LOCK_OFFSET            0x000       /* Offset of lock registers */
18#define SLCR_CLK_OFFSET             0x100       /* Offset of clock registers */
19
20#define LOCK_KEY   0x767B
21#define UNLOCK_KEY 0xDF0D
22#define SLCR_LOCKSTA_LOCKED BIT(0)
23
24struct slcr_lock_regs {
25    uint32_t scl;     /* 0x000 32 R/W 00000000h */
26    uint32_t lock;    /* 0x004 32  W  00000000h */
27    uint32_t unlock;  /* 0x008 32  W  00000000h */
28    uint32_t locksta; /* 0x008 32  R  00000001h */
29};
30typedef volatile struct slcr_lock_regs slcr_lock_regs_t;
31
32struct slcr_regs {
33    slcr_lock_regs_t lock;
34};
35typedef volatile struct slcr_regs slcr_regs_t;
36
37slcr_regs_t* slcr_regs;
38
39static inline void
40slcr_set_regs(src_dev_t* d, slcr_regs_t* r)
41{
42    d->priv = (void*)r;
43}
44
45static inline slcr_regs_t*
46slcr_get_regs(src_dev_t* d)
47{
48    return (slcr_regs_t*)d->priv;
49}
50
51static inline int
52reset_controller_unlock(src_dev_t* d)
53{
54    slcr_regs_t* r = slcr_get_regs(d);
55    r->lock.unlock = UNLOCK_KEY;
56    return !(r->lock.locksta & SLCR_LOCKSTA_LOCKED);
57}
58
59static inline int
60reset_controller_lock(src_dev_t* d)
61{
62    slcr_regs_t* r = slcr_get_regs(d);
63    r->lock.lock = LOCK_KEY;
64    return !!(r->lock.locksta & SLCR_LOCKSTA_LOCKED);
65}
66
67void
68reset_controller_assert_reset(src_dev_t* dev, enum src_rst_id id)
69{
70    (void)dev;
71    (void)id;
72}
73
74void*
75reset_controller_get_clock_regs(src_dev_t* dev)
76{
77    void* slcr = (void*)slcr_get_regs(dev);
78    return (slcr + SLCR_CLK_OFFSET);
79}
80
81int
82reset_controller_init(enum src_id id, ps_io_ops_t* ops, src_dev_t* dev)
83{
84    /* Input bounds check */
85    if (id < 0 || id >= NSRC) {
86        return -1;
87    }
88    /* Map in the slcr registers */
89    slcr_regs = ps_io_map(&ops->io_mapper, SLCR_PADDR, SLCR_SIZE, 0, PS_MEM_NORMAL);
90    if (slcr_regs == NULL) {
91        return -1;
92    }
93    slcr_set_regs(dev, slcr_regs);
94    /* Unlock the reset controller registers */
95    reset_controller_unlock(dev);
96    return 0;
97}
98