summaryrefslogtreecommitdiff
path: root/bsp/loongson/ls2kdev/drivers/drv_pwm.c
blob: 9559a2f46038d53673984c5962b615d589ac758d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Copyright(c) 2020, Du Huanpeng<[email protected]>
 *
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <ls2k1000.h>

#ifdef RT_USING_PWM

#define PWM0_BASE   (0xFFFFFFFFBFe02000)
#define PWM1_BASE   (0xFFFFFFFFBFe02010)
#define PWM2_BASE   (0xFFFFFFFFBFe02020)
#define PWM3_BASE   (0xFFFFFFFFBFe02030)

#define CTRL_EN     (1UL<<0)
#define CTRL_OE     (1UL<<3)
#define CTRL_SINGL  (1UL<<4)
#define CTRL_INTE   (1UL<<5)
#define CTRL_INT    (1UL<<6)
#define CTRL_RST    (1UL<<7)
#define CTRL_CAPTE  (1UL<<8)
#define CTRL_INVERT (1UL<<9)
#define CTRL_DZONE  (1UL<<10)

struct loongson_pwm
{
    rt_uint32_t __PAD0;
    rt_uint32_t low_buffer;
    rt_uint32_t full_buffer;
    rt_uint32_t ctrl;
};

rt_err_t loongson_pwm_enable(struct rt_device_pwm *device, int channel)
{
    int **priv;
    struct loongson_pwm *chip;
    volatile rt_uint64_t *config0;
    rt_uint64_t m;

    channel %= 4;

    config0 = (void *)GEN_CONFIG0_REG;
    m = 1ULL << 12 << channel;
    *config0 |= m;

    priv = device->parent.user_data;
    chip = (void *)priv[channel];
    chip->ctrl = CTRL_EN;

    return RT_EOK;
}

rt_err_t loongson_pwm_disable(struct rt_device_pwm *device, int channel)
{
    struct loongson_pwm **chip;
    rt_uint64_t m;

    chip = device->parent.user_data;
    channel %= 4;
    chip[channel]->ctrl &= ~CTRL_EN;

    return RT_EOK;
}

rt_err_t loongson_pwm_set(struct rt_device_pwm *device, int channel, rt_uint32_t period, rt_uint32_t pulse)
{
    struct loongson_pwm *chip;
    rt_uint32_t **priv;

    priv = device->parent.user_data;
    channel %= 4;
    chip = (void *)priv[channel];

    chip->ctrl       &= ~CTRL_EN;
    chip->full_buffer =  period;
    chip->low_buffer  =  pulse;
    chip->ctrl       |=  CTRL_EN;

    return RT_EOK;
}

static rt_err_t loongson_pwm_ioctl(struct rt_device_pwm *device, int cmd, void *arg)
{
    rt_err_t rc;
    struct rt_pwm_configuration *cfg;

    cfg = (void *)arg;

    switch (cmd)
    {
    case PWM_CMD_ENABLE:
        rc = loongson_pwm_enable(device, cfg->channel);
        break;
    case PWM_CMD_DISABLE:
        rc = loongson_pwm_disable(device, cfg->channel);
        break;
    case PWM_CMD_SET:
        rc = loongson_pwm_set(device, cfg->channel, cfg->period, cfg->pulse);
        break;
    case PWM_CMD_GET:
        rc = -RT_ENOSYS;
        break;
    default:
        rc = -RT_EINVAL;
        break;
    }
    return rc;
}

struct rt_pwm_ops loongson_pwm_ops =
{
    .control = loongson_pwm_ioctl,
};

struct rt_device_pwm loongson_pwm =
{
    .ops = &loongson_pwm_ops,
};

int loongson_pwm_init(void)
{
    int rc = RT_EOK;
    static rt_uint32_t *priv[] =
    {
        (void *)PWM0_BASE,
        (void *)PWM1_BASE,
        (void *)PWM2_BASE,
        (void *)PWM3_BASE
    };
    rc = rt_device_pwm_register(&loongson_pwm, "pwm0", &loongson_pwm_ops, &priv);
    return rc;
}
INIT_DEVICE_EXPORT(loongson_pwm_init);

#endif /*RT_USING_PWM*/