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 <platsupport/src.h>
13#include "../../services.h"
14
15/** PWRREG **/
16#define PWRREG_PHY_CONTROL_OFFSET  0x708
17#define PWRREG_PHY_CONTROL_PHY_EN  BIT(0)
18#define PWRREG_SWRST_OFFSET        0x400
19#define PWRREG_SWRST               BIT(0)
20
21/** SYSREG **/
22#define SYSREG_PHY_CONFIG_OFFSET   0x230
23#define SYSREG_PHY_CONFIG_PHY_EN   BIT(0)
24
25struct src_priv {
26    void* sysreg_vaddr[1];
27    void* pwrreg_vaddr[5];
28};
29
30struct src_priv _src_priv;
31
32static inline struct src_priv*
33src_get_priv(src_dev_t* d) {
34    return (struct src_priv*)d->priv;
35}
36
37static inline volatile uint32_t*
38sreg(struct src_priv* src, int offset)
39{
40    void* reg = src->sysreg_vaddr[offset >> 12] + (offset & MASK(12));
41    return (volatile uint32_t*)reg;
42}
43
44static inline volatile uint32_t*
45preg(struct src_priv* src, int offset)
46{
47    void* reg_base;
48    reg_base = src->pwrreg_vaddr[offset >> 12];
49    if (reg_base) {
50        return (volatile uint32_t*)(reg_base + (offset & MASK(12)));
51    } else {
52        return NULL;
53    }
54}
55
56int
57sysreg_usbphy_enable(src_dev_t* dev)
58{
59    volatile uint32_t* a;
60    struct src_priv* priv = src_get_priv(dev);
61    a = sreg(priv, SYSREG_PHY_CONFIG_OFFSET);
62    if (a) {
63        *a |= SYSREG_PHY_CONFIG_PHY_EN;
64    }
65    a = preg(priv, PWRREG_PHY_CONTROL_OFFSET);
66    if (a) {
67        *a |= PWRREG_PHY_CONTROL_PHY_EN;
68    }
69    return 0;
70}
71
72int
73sysreg_swrst_enable(src_dev_t* dev)
74{
75    struct src_priv* priv = src_get_priv(dev);
76    volatile uint32_t* a;
77    a = preg(priv, PWRREG_SWRST_OFFSET);
78    if (a) {
79        LOG_INFO("Software reset triggered");
80        fflush(stdout);
81        *a = PWRREG_SWRST;
82        while (1);
83    }
84    return 0;
85}
86
87void
88reset_controller_assert_reset(src_dev_t* dev, enum src_rst_id id)
89{
90    switch (id) {
91    case SRCRST_SW_RST:
92        sysreg_swrst_enable(dev);
93        break;
94    case SRCRST_USBPHY_EN:
95        sysreg_usbphy_enable(dev);
96        break;
97    default:
98        LOG_ERROR("Invalid option: %d", id);
99    }
100}
101
102int
103reset_controller_init(enum src_id id, ps_io_ops_t* ops, src_dev_t* dev)
104{
105    struct src_priv* src_priv = &_src_priv;
106    int i;
107    /* Sanity check the provided ID */
108    if (id < 0 || id >= NSRC) {
109        return -1;
110    }
111    /* Map sysreg memory */
112    for (i = 0; i < EXYNOS_SYSREG_SIZE >> 12; i++) {
113        if (src_priv->sysreg_vaddr[i] == NULL) {
114            void *vaddr;
115            vaddr = ps_io_map(&ops->io_mapper,
116                              EXYNOS_SYSREG_PADDR + i * BIT(12),
117                              0x1000, 0, PS_MEM_NORMAL);
118            src_priv->sysreg_vaddr[i] = vaddr;
119        }
120    }
121    /* Map pmu memory */
122    for (i = 0; i < EXYNOS_PMU_SIZE >> 12; i++) {
123        if (src_priv->pwrreg_vaddr[i] == NULL) {
124            void *vaddr;
125            vaddr = ps_io_map(&ops->io_mapper,
126                              EXYNOS_PMU_PADDR + i * BIT(12),
127                              0x1000 , 0, PS_MEM_NORMAL);
128
129            src_priv->pwrreg_vaddr[i] = vaddr;
130        }
131    }
132    /* Assign private data */
133    dev->priv = src_priv;
134    return 0;
135}
136