drv_spi.c 7.6 KB
Newer Older
B
bigmagic 已提交
1 2 3 4 5 6 7 8 9 10
/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author         Notes
 * 2019-07-29     zdzn           first version
 */
#include "drv_spi.h"
B
bigmagic 已提交
11
#include "raspi.h"
B
bigmagic 已提交
12 13 14

#ifdef RT_USING_SPI

B
bigmagic 已提交
15
#define RPI_CORE_CLK_HZ        250000000
B
bigmagic 已提交
16 17 18
#define BSP_SPI_MAX_HZ (30* 1000 *1000)
#define SPITIMEOUT 0x0FFF

B
bigmagic 已提交
19
void spi_gpio_write(rt_uint8_t pin, rt_uint8_t val)
B
bigmagic 已提交
20
{
B
bigmagic 已提交
21 22 23 24 25
    if (val)
        BCM283X_GPIO_GPSET((pin / 32)) = 1 << (pin % 32);
    else
        BCM283X_GPIO_GPCLR((pin / 32)) = 1 << (pin % 32);
}
B
bigmagic 已提交
26

B
bigmagic 已提交
27
struct raspi_spi_hw_config
B
bigmagic 已提交
28
{
B
bigmagic 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
    rt_uint8_t spi_num;
    raspi_gpio_pin sclk_pin;
    raspi_pin_select sclk_mode;
    raspi_gpio_pin mosi_pin;
    raspi_pin_select mosi_mode;
    raspi_gpio_pin miso_pin;
    raspi_pin_select miso_mode;
#if defined (BSP_USING_SPI0_DEVICE0) || defined (BSP_USING_SPI1_DEVICE0)
    raspi_gpio_pin ce0_pin;
    raspi_pin_select ce0_mode;
#endif

#if defined (BSP_USING_SPI0_DEVICE1) || defined (BSP_USING_SPI1_DEVICE1)
    raspi_gpio_pin ce1_pin;
    raspi_pin_select ce1_mode;
#endif

#if defined (BSP_USING_SPI1_DEVICE2)
    raspi_gpio_pin ce2_pin;
    raspi_pin_select ce2_mode;
#endif
B
bigmagic 已提交
50 51
};

B
bigmagic 已提交
52
struct raspi_spi_device
B
bigmagic 已提交
53 54 55
{
    char *device_name;
    struct rt_spi_bus *spi_bus;
B
bigmagic 已提交
56 57
    struct rt_spi_device *spi_device;
    raspi_gpio_pin cs_pin;
B
bigmagic 已提交
58 59
};

B
bigmagic 已提交
60
static rt_err_t raspi_spi_configure(struct rt_spi_device *device, struct rt_spi_configuration *cfg)
B
bigmagic 已提交
61
{
B
bigmagic 已提交
62 63 64
    RT_ASSERT(cfg != RT_NULL);
    RT_ASSERT(device != RT_NULL);
    rt_uint16_t divider;
B
bigmagic 已提交
65 66

    // spi clear fifo
B
bigmagic 已提交
67
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CLEAR;
B
bigmagic 已提交
68

B
bigmagic 已提交
69 70
    if (cfg->mode & RT_SPI_CPOL)
        BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPOL;
B
bigmagic 已提交
71

B
bigmagic 已提交
72 73
    if (cfg->mode & RT_SPI_CPHA)
        BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CPHA;
B
bigmagic 已提交
74

B
bigmagic 已提交
75 76
    if (cfg->mode & RT_SPI_CS_HIGH)
        BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CSPOL;
B
bigmagic 已提交
77

B
bigmagic 已提交
78 79
    //set clk
    if (cfg->max_hz > BSP_SPI_MAX_HZ)
B
bigmagic 已提交
80 81
        cfg->max_hz = BSP_SPI_MAX_HZ;

B
bigmagic 已提交
82 83
    divider = (rt_uint16_t) ((rt_uint32_t) RPI_CORE_CLK_HZ / cfg->max_hz);
    divider &= 0xFFFE;
B
bigmagic 已提交
84

B
bigmagic 已提交
85
    BCM283X_SPI0_CLK(BCM283X_SPI0_BASE) = divider;
B
bigmagic 已提交
86 87 88 89

    return RT_EOK;
}

B
bigmagic 已提交
90
rt_uint8_t correct_order(rt_uint8_t b, rt_uint8_t flag)
B
bigmagic 已提交
91
{
B
bigmagic 已提交
92 93
    if (flag)
        return raspi_byte_reverse_table[b];
B
bigmagic 已提交
94 95 96 97
    else
        return b;
}

B
bigmagic 已提交
98
static rt_err_t spi_transfernb(rt_uint8_t* tbuf, rt_uint8_t* rbuf, rt_uint32_t len, rt_uint8_t flag)
B
bigmagic 已提交
99 100 101 102 103
{
    rt_uint32_t TXCnt=0;
    rt_uint32_t RXCnt=0;

    /* Clear TX and RX fifos */
B
bigmagic 已提交
104
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_CLEAR & BCM283X_SPI0_CS_CLEAR);
B
bigmagic 已提交
105 106

    /* Set TA = 1 */
B
bigmagic 已提交
107 108
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (BCM283X_SPI0_CS_TA & BCM283X_SPI0_CS_TA);

B
bigmagic 已提交
109 110 111 112 113

    /* Use the FIFO's to reduce the interbyte times */
    while ((TXCnt < len) || (RXCnt < len))
    {
        /* TX fifo not full, so add some more bytes */
B
bigmagic 已提交
114
        while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_TXD)) && (TXCnt < len))
B
bigmagic 已提交
115
        {
B
bigmagic 已提交
116
            BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE) = correct_order(tbuf[TXCnt],flag);
B
bigmagic 已提交
117 118 119
            TXCnt++;
        }
        /* Rx fifo not empty, so get the next received bytes */
B
bigmagic 已提交
120
        while (((BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_RXD)) && (RXCnt < len))
B
bigmagic 已提交
121
        {
B
bigmagic 已提交
122
            rbuf[RXCnt] = correct_order(BCM283X_SPI0_FIFO(BCM283X_SPI0_BASE),flag);
B
bigmagic 已提交
123 124 125 126
            RXCnt++;
        }
    }
    /* Wait for DONE to be set */
B
bigmagic 已提交
127
    while (!(BCM283X_SPI0_CS(BCM283X_SPI0_BASE) & BCM283X_SPI0_CS_DONE));
B
bigmagic 已提交
128 129

    /* Set TA = 0, and also set the barrier */
B
bigmagic 已提交
130
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= (0 & BCM283X_SPI0_CS_TA);
B
bigmagic 已提交
131 132 133 134 135
    return RT_EOK;
}

static rt_uint32_t raspi_spi_xfer(struct rt_spi_device *device, struct rt_spi_message *message)
{
B
bigmagic 已提交
136

B
bigmagic 已提交
137 138
    RT_ASSERT(device != RT_NULL);
    RT_ASSERT(device->bus != RT_NULL);
B
bigmagic 已提交
139
    RT_ASSERT(device->parent.user_data != RT_NULL);
B
bigmagic 已提交
140 141
    RT_ASSERT(message->send_buf != RT_NULL || message->recv_buf != RT_NULL);

B
bigmagic 已提交
142 143 144 145
    rt_err_t res;
    rt_uint8_t flag;
    struct rt_spi_configuration config = device->config;
    raspi_gpio_pin cs_pin = (raspi_gpio_pin)device->parent.user_data;
B
bigmagic 已提交
146

B
bigmagic 已提交
147 148
    if (config.mode & RT_SPI_MSB)
        flag = 0;
B
bigmagic 已提交
149
    else
B
bigmagic 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
        flag = 1;
    if (message->cs_take);
      //  (config.mode & RT_SPI_CS_HIGH)?
      //          spi_gpio_write(cs_pin, 1):
      //          spi_gpio_write(cs_pin, 0);

    /* deal data */
    res = spi_transfernb((rt_uint8_t *)message->send_buf, (rt_uint8_t *)message->recv_buf,
            (rt_int32_t)message->length, flag);

    if (message->cs_release)
        (config.mode & RT_SPI_CS_HIGH)?
                spi_gpio_write(cs_pin, 0):
                spi_gpio_write(cs_pin, 1);

    if (res != RT_EOK)
           return RT_ERROR;
B
bigmagic 已提交
167 168 169 170

    return message->length;
}

B
bigmagic 已提交
171
rt_err_t raspi_spi_bus_attach_device(const char *bus_name, struct raspi_spi_device *device)
B
bigmagic 已提交
172 173
{
    rt_err_t ret;
B
bigmagic 已提交
174 175
    RT_ASSERT(device != RT_NULL);
    ret = rt_spi_bus_attach_device(device->spi_device, device->device_name, bus_name, (void *)(device->cs_pin));
B
bigmagic 已提交
176 177 178
    return ret;
}

B
bigmagic 已提交
179
rt_err_t raspi_spi_hw_init(struct raspi_spi_hw_config *hwcfg)
B
bigmagic 已提交
180
{
B
bigmagic 已提交
181 182 183
    GPIO_FSEL(hwcfg->sclk_pin, hwcfg->sclk_mode);
    GPIO_FSEL(hwcfg->miso_pin, hwcfg->miso_mode);
    GPIO_FSEL(hwcfg->mosi_pin, hwcfg->mosi_mode);
B
bigmagic 已提交
184

B
bigmagic 已提交
185 186 187
#if defined (BSP_USING_SPI0_DEVICE0)
    GPIO_FSEL(hwcfg->ce0_pin, hwcfg->ce0_mode);
#endif
B
bigmagic 已提交
188

B
bigmagic 已提交
189 190 191
#if defined (BSP_USING_SPI0_DEVICE1)
    GPIO_FSEL(hwcfg->ce1_pin, hwcfg->ce1_mode);
#endif
B
bigmagic 已提交
192

B
bigmagic 已提交
193 194
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = 0;
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) = BCM283X_SPI0_CS_CLEAR;
B
bigmagic 已提交
195

B
bigmagic 已提交
196 197 198 199
    //enable chip select
#if defined (BSP_USING_SPI0_DEVICE0)
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0;
#endif
B
bigmagic 已提交
200

B
bigmagic 已提交
201 202 203
#if defined (BSP_USING_SPI0_DEVICE1)
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= 0x2;
#endif
B
bigmagic 已提交
204

B
bigmagic 已提交
205 206 207
#if defined (BSP_USING_SPI0_DEVICE0) && defined (BSP_USING_SPI0_DEVICE1)
    BCM283X_SPI0_CS(BCM283X_SPI0_BASE) |= BCM283X_SPI0_CS_CS;
#endif
B
bigmagic 已提交
208 209 210
    return RT_EOK;
}

B
bigmagic 已提交
211
static struct rt_spi_ops raspi_spi_ops =
B
bigmagic 已提交
212 213 214 215 216
{
    .configure = raspi_spi_configure,
    .xfer = raspi_spi_xfer
};

B
bigmagic 已提交
217 218 219 220
#if defined (BSP_USING_SPI0_BUS)
#define SPI0_BUS_NAME  "spi0"
#define SPI0_DEVICE0_NAME  "spi0.0"
#define SPI0_DEVICE1_NAME  "spi0.1"
B
bigmagic 已提交
221

B
bigmagic 已提交
222
struct rt_spi_bus spi0_bus;
B
bigmagic 已提交
223

B
bigmagic 已提交
224 225
#if defined (BSP_USING_SPI0_DEVICE0)
struct rt_spi_device spi0_device0;
B
bigmagic 已提交
226 227
#endif

B
bigmagic 已提交
228 229 230
#if defined (BSP_USING_SPI0_DEVICE1)
static struct rt_spi_device spi0_device1;
#endif
B
bigmagic 已提交
231

B
bigmagic 已提交
232
struct raspi_spi_hw_config raspi_spi0_hw =
B
bigmagic 已提交
233
{
B
bigmagic 已提交
234 235
    .spi_num = 0,
    .sclk_pin = RPI_GPIO_P1_23,
B
bigmagic 已提交
236
    .sclk_mode = BCM283X_GPIO_FSEL_ALT0,
B
bigmagic 已提交
237
    .mosi_pin = RPI_GPIO_P1_19,
B
bigmagic 已提交
238
    .mosi_mode = BCM283X_GPIO_FSEL_ALT0,
B
bigmagic 已提交
239
    .miso_pin = RPI_GPIO_P1_21,
B
bigmagic 已提交
240 241
    .miso_mode = BCM283X_GPIO_FSEL_ALT0,

B
bigmagic 已提交
242 243 244 245 246 247 248 249 250
#if defined (BSP_USING_SPI0_DEVICE0)
    .ce0_pin = RPI_GPIO_P1_24,
    .ce0_mode = BCM283X_GPIO_FSEL_ALT0,
#endif

#if defined (BSP_USING_SPI0_DEVICE1)
    .ce1_pin = RPI_GPIO_P1_26,
    .ce1_mode = BCM283X_GPIO_FSEL_ALT0,
#endif
B
bigmagic 已提交
251 252 253
};
#endif

B
bigmagic 已提交
254
int rt_hw_spi_init(void)
B
bigmagic 已提交
255 256
{

B
bigmagic 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269
#if defined (BSP_USING_SPI0_BUS)
    raspi_spi_hw_init(&raspi_spi0_hw);
    rt_spi_bus_register(&spi0_bus, SPI0_BUS_NAME, &raspi_spi_ops);

#if defined (BSP_USING_SPI0_DEVICE0)
    struct raspi_spi_device raspi_spi0_device0 =
    {
        .device_name = SPI0_DEVICE0_NAME,
        .spi_bus = &spi0_bus,
        .spi_device = &spi0_device0,
        .cs_pin = raspi_spi0_hw.ce0_pin,
    };
    raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device0);
B
bigmagic 已提交
270 271
#endif

B
bigmagic 已提交
272 273 274 275 276 277 278 279 280 281 282
#if defined (BSP_USING_SPI0_DEVICE1)
    struct raspi_spi_device raspi_spi0_device1 =
    {
        .device_name = SPI0_DEVICE1_NAME,
        .spi_bus = &spi0_bus,
        .spi_device = &spi0_device1,
        .cs_pin = raspi_spi0_hw.ce1_pin,
    };
    raspi_spi_bus_attach_device(SPI0_BUS_NAME, &raspi_spi0_device1);
#endif
#endif
B
bigmagic 已提交
283 284
    return RT_EOK;
}
B
bigmagic 已提交
285
INIT_DEVICE_EXPORT(rt_hw_spi_init);
B
bigmagic 已提交
286 287

#endif